diff --git a/Changelog b/Changelog
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,9 @@
+Changed in version 0.7.3.0:
+   * Require ghc version of at least 7.4.1, and clean up obsolete code
+   * Add thread-safe (in terminal-style interaction) external print function
+   * Add a MonadFix instance for InputT
+   * Bump upper bounds on `base` and `directory` to support ghc-8.0.2
+
 Changed in version 0.7.2.3:
    * Fix hsc2hs-related warning on ghc-8
    * Fix the behavior of ctrl-W in the emacs bindings
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,20 +1,8 @@
-{-# LANGUAGE CPP #-}
 import Distribution.System
-import Distribution.Verbosity
 import Distribution.PackageDescription
 import Distribution.Simple
-import Distribution.Simple.Program
 import Distribution.Simple.Setup
-import Distribution.Simple.LocalBuildInfo
-import Distribution.Simple.Utils
 
-import Distribution.Simple.PackageIndex
-import qualified Distribution.InstalledPackageInfo as Installed
-
-import System.IO
-import System.Exit
-import System.Directory
-import Control.Exception
 import Control.Monad(when)
 
 main :: IO ()
@@ -26,14 +14,7 @@
     | otherwise = simpleUserHooks {
             confHook = \genericDescript flags -> do
                         warnIfNotTerminfo flags
-                        lbi <- confHook simpleUserHooks genericDescript flags
-                        let pkgDescr = localPkgDescr lbi
-                        let Just lib = library pkgDescr
-                        let bi = libBuildInfo lib
-                        bi' <- maybeSetLibiconv flags bi lbi
-                        return lbi {localPkgDescr = pkgDescr {
-                                                library = Just lib {
-                                                    libBuildInfo = bi'}}}
+                        confHook simpleUserHooks genericDescript flags
             }
 
 warnIfNotTerminfo flags = when (not (hasFlagSet flags (FlagName "terminfo")))
@@ -47,80 +28,3 @@
 
 hasFlagSet :: ConfigFlags -> FlagName -> Bool
 hasFlagSet cflags flag = Just True == lookup flag (configConfigurationsFlags cflags)
-
-
--- Test whether compiling a c program that links against libiconv needs -liconv.
--- (Not needed for ghc>=7.4.1, even for the legacy POSIX backend, since
--- the base library always links against iconv .)
-maybeSetLibiconv :: ConfigFlags -> BuildInfo -> LocalBuildInfo -> IO BuildInfo
-
-#if __GLASGOW_HASKELL__ >= 704
-maybeSetLibiconv _ bi _ = return bi
-#else
-maybeSetLibiconv flags bi lbi = do
-    let biWithIconv = addIconv bi
-    let verb = fromFlag (configVerbosity flags)
-    if hasFlagSet flags (FlagName "libiconv")
-        then do
-            putStrLn "Using -liconv."
-            return biWithIconv
-        else do
-    putStr "checking whether to use -liconv... "
-    hFlush stdout
-    worksWithout <- tryCompile iconv_prog bi lbi verb
-    if worksWithout
-        then do
-            putStrLn "not needed."
-            return bi
-        else do
-    worksWith <- tryCompile iconv_prog biWithIconv lbi verb
-    if worksWith
-        then do
-            putStrLn "using -liconv."
-            return biWithIconv
-        else error "Unable to link against the iconv library."
-
-tryCompile :: String -> BuildInfo -> LocalBuildInfo -> Verbosity -> IO Bool
-tryCompile program bi lbi verb = handle processExit $ handle processException $ do
-    tempDir <- getTemporaryDirectory
-    withTempFile tempDir ".c" $ \fname cH ->
-      withTempFile tempDir "" $ \execName oH -> do
-        hPutStr cH program
-        hClose cH
-        hClose oH
-        -- TODO take verbosity from the args.
-        rawSystemProgramStdoutConf verb gccProgram (withPrograms lbi)
-                        (fname : "-o" : execName : args)
-        return True
-  where
-    processException :: IOException -> IO Bool
-    processException e = return False
-    processExit = return . (==ExitSuccess)
-    -- Mimicing Distribution.Simple.Configure
-    deps = topologicalOrder (installedPkgs lbi)
-    args = concat
-                  [ ccOptions bi
-                  , cppOptions bi
-                  , ldOptions bi
-                  -- --extra-include-dirs and --extra-lib-dirs are included
-                  -- in the below fields.
-                  -- Also sometimes a dependency like rts points to a nonstandard
-                  -- include/lib directory where iconv can be found. 
-                  , map ("-I" ++) (includeDirs bi ++ concatMap Installed.includeDirs deps)
-                  , map ("-L" ++) (extraLibDirs bi ++ concatMap Installed.libraryDirs deps)
-                  , map ("-l" ++) (extraLibs bi)
-                  ]
-
-addIconv :: BuildInfo -> BuildInfo
-addIconv bi = bi {extraLibs = "iconv" : extraLibs bi}
-
-iconv_prog :: String
-iconv_prog = unlines $
-    [ "#include <iconv.h>"
-    , "int main(void) {"
-    , "    iconv_t t = iconv_open(\"UTF-8\", \"UTF-8\");"
-    , "    return 0;"
-    , "}"
-    ]
-#endif
-
diff --git a/System/Console/Haskeline.hs b/System/Console/Haskeline.hs
--- a/System/Console/Haskeline.hs
+++ b/System/Console/Haskeline.hs
@@ -1,7 +1,7 @@
-{- | 
+{- |
 
 A rich user interface for line input in command-line programs.  Haskeline is
-Unicode-aware and runs both on POSIX-compatible systems and on Windows.  
+Unicode-aware and runs both on POSIX-compatible systems and on Windows.
 
 Users may customize the interface with a @~/.haskeline@ file; see
 <http://trac.haskell.org/haskeline/wiki/UserPrefs> for more information.
@@ -10,10 +10,10 @@
 following:
 
 > import System.Console.Haskeline
-> 
+>
 > main :: IO ()
 > main = runInputT defaultSettings loop
->    where 
+>    where
 >        loop :: InputT IO ()
 >        loop = do
 >            minput <- getInputLine "% "
@@ -51,6 +51,7 @@
                     -- $outputfncs
                     outputStr,
                     outputStrLn,
+                    getExternalPrint,
                     -- * Customization
                     -- ** Settings
                     Settings(..),
@@ -183,7 +184,7 @@
     settings :: Settings m <- InputT ask
     histDupes <- InputT $ asks historyDuplicates
     case result of
-        Just line | autoAddHistory settings && not (all isSpace line) 
+        Just line | autoAddHistory settings && not (all isSpace line)
             -> let adder = case histDupes of
                         AlwaysAdd -> addHistory
                         IgnoreConsecutive -> addHistoryUnlessConsecutiveDupe
@@ -214,9 +215,9 @@
     case fmap isPrint c of
         Just False -> getPrintableChar fops
         _ -> return c
-        
+
 getInputCmdChar :: MonadException m => TermOps -> String -> InputT m (Maybe Char)
-getInputCmdChar tops prefix = runInputCmdT tops 
+getInputCmdChar tops prefix = runInputCmdT tops
         $ runCommandLoop tops prefix acceptOneChar emptyIM
 
 acceptOneChar :: Monad m => KeyCommand m InsertMode (Maybe Char)
@@ -235,7 +236,7 @@
 When using file-style interaction, this function turns off echoing while reading
 the line of input.
 -}
- 
+
 getPassword :: MonadException m => Maybe Char -- ^ A masking character; e.g., @Just \'*\'@
                             -> String -> InputT m (Maybe String)
 getPassword x = promptedInput
@@ -256,7 +257,7 @@
                      , ctrlChar 'l' +> clearScreenCmd >|> loop'
                      ]
     loop' = keyCommand loop
-                        
+
 {- $history
 The 'InputT' monad transformer provides direct, low-level access to the user's line history state.
 
@@ -293,16 +294,16 @@
 
 > tryAction :: InputT IO ()
 > tryAction = handle (\Interrupt -> outputStrLn "Cancelled.")
->                $ wrapInterrupt $ someLongAction
+>                $ withInterrupt $ someLongAction
 
 The action can handle the interrupt itself; a new 'Interrupt' exception will be thrown
 every time Ctrl-C is pressed.
 
 > tryAction :: InputT IO ()
-> tryAction = wrapInterrupt loop
+> tryAction = withInterrupt loop
 >     where loop = handle (\Interrupt -> outputStrLn "Cancelled; try again." >> loop)
 >                    someLongAction
- 
+
 This behavior differs from GHC's built-in Ctrl-C handling, which
 may immediately terminate the program after the second time that the user presses
 Ctrl-C.
@@ -313,8 +314,18 @@
     rterm <- InputT ask
     liftIOOp_ (wrapInterrupt rterm) act
 
--- | Catch and handle an exception of type 'Interrupt'.  
+-- | Catch and handle an exception of type 'Interrupt'.
 --
 -- > handleInterrupt f = handle $ \Interrupt -> f
 handleInterrupt :: MonadException m => m a -> m a -> m a
 handleInterrupt f = handle $ \Interrupt -> f
+
+{- | Return a printing function, which in terminal-style interactions is
+thread-safe and may be run concurrently with user input without affecting the
+prompt. -}
+getExternalPrint :: MonadException m => InputT m (String -> IO ())
+getExternalPrint = do
+    rterm <- InputT ask
+    return $ case termOps rterm of
+        Right _ -> putStrOut rterm
+        Left tops -> externalPrint tops
diff --git a/System/Console/Haskeline/Backend/DumbTerm.hs b/System/Console/Haskeline/Backend/DumbTerm.hs
--- a/System/Console/Haskeline/Backend/DumbTerm.hs
+++ b/System/Console/Haskeline/Backend/DumbTerm.hs
@@ -1,7 +1,6 @@
 module System.Console.Haskeline.Backend.DumbTerm where
 
 import System.Console.Haskeline.Backend.Posix
-import System.Console.Haskeline.Backend.Posix.Encoder (putEncodedStr)
 import System.Console.Haskeline.Backend.WCWidth
 import System.Console.Haskeline.Term
 import System.Console.Haskeline.LineState
@@ -23,13 +22,12 @@
 
 newtype DumbTerm m a = DumbTerm {unDumbTerm :: StateT Window (PosixT m) a}
                 deriving (Functor, Applicative, Monad, MonadIO, MonadException,
-                          MonadState Window,
-                          MonadReader Handles, MonadReader Encoder)
+                          MonadState Window, MonadReader Handles)
 
 type DumbTermM a = forall m . (MonadIO m, MonadReader Layout m) => DumbTerm m a
 
 instance MonadTrans DumbTerm where
-    lift = DumbTerm . lift . lift . lift
+    lift = DumbTerm . lift . lift
 
 evalDumb :: (MonadReader Layout m, CommandMonad m) => EvalTerm (PosixT m)
 evalDumb = EvalTerm (evalStateT' initWindow . unDumbTerm) (DumbTerm . lift)
@@ -50,8 +48,7 @@
 printText :: MonadIO m => String -> DumbTerm m ()
 printText str = do
     h <- liftM ehOut ask
-    encode <- ask
-    liftIO $ putEncodedStr encode h str
+    liftIO $ hPutStr h str
     liftIO $ hFlush h
 
 -- Things we can assume a dumb terminal knows how to do
diff --git a/System/Console/Haskeline/Backend/Posix.hsc b/System/Console/Haskeline/Backend/Posix.hsc
--- a/System/Console/Haskeline/Backend/Posix.hsc
+++ b/System/Console/Haskeline/Backend/Posix.hsc
@@ -6,8 +6,6 @@
                         Handles(),
                         ehIn,
                         ehOut,
-                        Encoder,
-                        Decoder,
                         mapLines,
                         stdinTTYHandles,
                         ttyHandles,
@@ -35,7 +33,6 @@
 
 import System.Console.Haskeline.Backend.Posix.Encoder
 
-#if __GLASGOW_HASKELL__ >= 611
 import GHC.IO.FD (fdFD)
 import Data.Dynamic (cast)
 import System.IO.Error
@@ -43,10 +40,6 @@
 import GHC.IO.Handle.Types hiding (getState)
 import GHC.IO.Handle.Internals
 import System.Posix.Internals (FD)
-#else
-import GHC.IOBase(haFD,FD)
-import GHC.Handle (withHandle_)
-#endif
 
 #if defined(USE_TERMIOS_H) || defined(__ANDROID__)
 #include <termios.h>
@@ -81,7 +74,6 @@
                     else return Nothing
 
 unsafeHandleToFD :: Handle -> IO FD
-#if __GLASGOW_HASKELL__ >= 611
 unsafeHandleToFD h =
   withHandle_ "unsafeHandleToFd" h $ \Handle__{haDevice=dev} -> do
   case cast dev of
@@ -89,9 +81,6 @@
                                            "unsafeHandleToFd" (Just h) Nothing)
                         "handle is not a file descriptor")
     Just fd -> return (fdFD fd)
-#else
-unsafeHandleToFD h = withHandle_ "unsafeHandleToFd" h (return . haFD)
-#endif
 
 envLayout :: IO (Maybe Layout)
 envLayout = handle (\(_::IOException) -> return Nothing) $ do
@@ -160,7 +149,7 @@
     attrs <- getTerminalAttributes (Fd fd)
     let getStty (k,c) = do {str <- controlChar attrs k; return ([str],c)}
     return $ catMaybes $ map getStty [(Erase,simpleKey Backspace),(Kill,simpleKey KillLine)]
-                        
+
 newtype TreeMap a b = TreeMap (Map.Map a (Maybe b, TreeMap a b))
                         deriving Show
 
@@ -211,22 +200,22 @@
 
 -----------------------------
 
-withPosixGetEvent :: (MonadException m, MonadReader Prefs m) 
-        => Chan Event -> Handles -> Decoder -> [(String,Key)]
+withPosixGetEvent :: (MonadException m, MonadReader Prefs m)
+        => Chan Event -> Handles -> [(String,Key)]
                 -> (m Event -> m a) -> m a
-withPosixGetEvent eventChan h enc termKeys f = wrapTerminalOps h $ do
+withPosixGetEvent eventChan h termKeys f = wrapTerminalOps h $ do
     baseMap <- getKeySequences (ehIn h) termKeys
     withWindowHandler eventChan
-        $ f $ liftIO $ getEvent (ehIn h) enc baseMap eventChan
+        $ f $ liftIO $ getEvent (ehIn h) baseMap eventChan
 
 withWindowHandler :: MonadException m => Chan Event -> m a -> m a
-withWindowHandler eventChan = withHandler windowChange $ 
+withWindowHandler eventChan = withHandler windowChange $
     Catch $ writeChan eventChan WindowResize
 
 withSigIntHandler :: MonadException m => m a -> m a
 withSigIntHandler f = do
-    tid <- liftIO myThreadId 
-    withHandler keyboardSignal 
+    tid <- liftIO myThreadId
+    withHandler keyboardSignal
             (Catch (throwTo tid Interrupt))
             f
 
@@ -235,11 +224,27 @@
     old_handler <- liftIO $ installHandler signal handler Nothing
     f `finally` liftIO (installHandler signal old_handler Nothing)
 
-getEvent :: Handle -> Decoder -> TreeMap Char Key -> Chan Event -> IO Event
-getEvent h dec baseMap = keyEventLoop $ do
-        cs <- getBlockOfChars h dec
+getEvent :: Handle -> TreeMap Char Key -> Chan Event -> IO Event
+getEvent h baseMap = keyEventLoop $ do
+        cs <- getBlockOfChars h
         return [KeyInput $ lexKeys baseMap cs]
 
+-- Read at least one character of input, and more if immediately
+-- available.  In particular the characters making up a control sequence
+-- will all be available at once, so they can be processed together
+-- (with Posix.lexKeys).
+getBlockOfChars :: Handle -> IO String
+getBlockOfChars h = do
+    c <- hGetChar h
+    loop [c]
+  where
+    loop cs = do
+        isReady <- hReady h
+        if not isReady
+            then return $ reverse cs
+            else do
+                    c <- hGetChar h
+                    loop (c:cs)
 
 stdinTTYHandles, ttyHandles :: MaybeT IO Handles
 stdinTTYHandles = do
@@ -269,7 +274,7 @@
             $ liftIO $ openInCodingMode "/dev/tty" mode
 
 
-posixRunTerm :: 
+posixRunTerm ::
     Handles
     -> [IO (Maybe Layout)]
     -> [(String,Key)]
@@ -279,26 +284,26 @@
 posixRunTerm hs layoutGetters keys wrapGetEvent evalBackend = do
     ch <- newChan
     fileRT <- posixFileRunTerm hs
-    (enc,dec) <- newEncoders
     return fileRT
-                { closeTerm = closeTerm fileRT
-                , termOps = Left TermOps
+                { termOps = Left TermOps
                             { getLayout = tryGetLayouts layoutGetters
-                            , withGetEvent = wrapGetEvent 
-                                            . withPosixGetEvent ch hs dec
+                            , withGetEvent = wrapGetEvent
+                                            . withPosixGetEvent ch hs
                                                 keys
                             , saveUnusedKeys = saveKeys ch
                             , evalTerm = mapEvalTerm
-                                            (runPosixT enc hs)
-                                                (lift . lift)
-                                            evalBackend
+                                            (runPosixT hs) lift evalBackend
+                            , externalPrint = writeChan ch . ExternalPrint
                             }
+                , closeTerm = do
+                    flushEventQueue (putStrOut fileRT) ch
+                    closeTerm fileRT
                 }
 
-type PosixT m = ReaderT Encoder (ReaderT Handles m)
+type PosixT m = ReaderT Handles m
 
-runPosixT :: Monad m => Encoder -> Handles -> PosixT m a -> m a
-runPosixT enc h = runReaderT' h . runReaderT' enc
+runPosixT :: Monad m => Handles -> PosixT m a -> m a
+runPosixT h = runReaderT' h
 
 fileRunTerm :: Handle -> IO RunTerm
 fileRunTerm h_in = posixFileRunTerm Handles
@@ -309,19 +314,18 @@
 
 posixFileRunTerm :: Handles -> IO RunTerm
 posixFileRunTerm hs = do
-    (enc,dec) <- newEncoders
     return RunTerm
                 { putStrOut = \str -> withCodingMode (hOut hs) $ do
-                                        putEncodedStr enc (ehOut hs) str
+                                        hPutStr (ehOut hs) str
                                         hFlush (ehOut hs)
                 , closeTerm = closeHandles hs
                 , wrapInterrupt = withSigIntHandler
                 , termOps = Right FileOps
                           { inputHandle = ehIn hs
                           , wrapFileInput = withCodingMode (hIn hs)
-                          , getLocaleChar = getDecodedChar (ehIn hs) dec
+                          , getLocaleChar = guardedEOF hGetChar (ehIn hs)
                           , maybeReadNewline = hMaybeReadNewline (ehIn hs)
-                          , getLocaleLine = getDecodedLine (ehIn hs) dec
+                          , getLocaleLine = guardedEOF hGetLine (ehIn hs)
                           }
                 }
 
diff --git a/System/Console/Haskeline/Backend/Posix/Encoder.hs b/System/Console/Haskeline/Backend/Posix/Encoder.hs
--- a/System/Console/Haskeline/Backend/Posix/Encoder.hs
+++ b/System/Console/Haskeline/Backend/Posix/Encoder.hs
@@ -7,63 +7,19 @@
 functions that wrap the old/new ways.
 -}
 module System.Console.Haskeline.Backend.Posix.Encoder (
-        Encoder,
-        Decoder,
-        newEncoders,
         ExternalHandle(eH),
         externalHandle,
         withCodingMode,
         openInCodingMode,
-        putEncodedStr,
-#ifdef TERMINFO
-        getTermText,
-#endif
-        getBlockOfChars,
-        getDecodedChar,
-        getDecodedLine,
-                ) where
+        ) where
 
 import System.IO
 import System.Console.Haskeline.Monads
-import System.Console.Haskeline.Term
-#ifdef TERMINFO
-import qualified System.Console.Terminfo.Base as Terminfo
-#endif
 
--- Way-dependent imports
-#ifdef USE_GHC_ENCODINGS
 import GHC.IO.Encoding (initLocaleEncoding)
 import System.Console.Haskeline.Recover
-#else
-import System.Console.Haskeline.Backend.Posix.IConv
-import Data.ByteString (ByteString)
-import qualified Data.ByteString as B
-#ifdef TERMINFO
-import qualified Data.ByteString.Char8 as BC
-#endif
-import Control.Monad (liftM2)
-#endif
 
 
-
-#ifdef USE_GHC_ENCODINGS
-data Encoder = Encoder
-data Decoder = Decoder
-#else
-type Decoder = PartialDecoder
-type Encoder = String -> IO ByteString
-#endif
-
-newEncoders :: IO (Encoder,Decoder)
-#ifdef USE_GHC_ENCODINGS
-newEncoders = return (Encoder,Decoder)
-#else
-newEncoders = do
-    codeset <- bracket (setLocale (Just "")) setLocale $ const $ getCodeset
-    liftM2 (,) (openEncoder codeset)
-                (openPartialDecoder codeset)
-#endif
-
 -- | An 'ExternalHandle' is a handle which may or may not be in the correct
 -- mode for Unicode input/output.  When the POSIX backend opens a file
 -- (or /dev/tty) it sets it permanently to the correct mode.
@@ -71,10 +27,8 @@
 -- sets it to the correct mode (e.g., for the duration of getInputLine);
 -- otherwise, we might interfere with the rest of the Haskell program.
 --
--- For the legacy backend, the correct mode is BinaryMode.
--- For the new backend, the correct mode is the locale encoding, set to
--- transliterate errors (rather than crashing, as is the base library's
--- default.)  (See Posix/Recover.hs)
+-- The correct mode is the locale encoding, set to transliterate errors (rather
+-- than crashing, as is the base library's default).  See Recover.hs.
 data ExternalHandle = ExternalHandle
                         { externalMode :: ExternalMode
                         , eH :: Handle
@@ -89,7 +43,6 @@
 -- for the duration of the given action.
 withCodingMode :: ExternalHandle -> IO a -> IO a
 withCodingMode ExternalHandle {externalMode=CodingMode} act = act
-#ifdef USE_GHC_ENCODINGS
 withCodingMode (ExternalHandle OtherMode h) act = do
     bracket (liftIO $ hGetEncoding h)
             (liftIO . hSetBinOrEncoding h)
@@ -100,112 +53,16 @@
 hSetBinOrEncoding :: Handle -> Maybe TextEncoding -> IO ()
 hSetBinOrEncoding h Nothing = hSetBinaryMode h True
 hSetBinOrEncoding h (Just enc) = hSetEncoding h enc
-#else
-withCodingMode (ExternalHandle OtherMode h) act = hWithBinaryMode h act
-#endif
 
-#ifdef USE_GHC_ENCODINGS
 haskelineEncoding :: TextEncoding
 haskelineEncoding = transliterateFailure initLocaleEncoding
-#endif
 
 -- Open a file and permanently set it to the correct mode.
 openInCodingMode :: FilePath -> IOMode -> IO ExternalHandle
-#ifdef USE_GHC_ENCODINGS
 openInCodingMode path iomode = do
     h <- openFile path iomode
     hSetEncoding h haskelineEncoding
     return $ ExternalHandle CodingMode h
-#else
-openInCodingMode path iomode
-    = fmap (ExternalHandle CodingMode) $ openBinaryFile path iomode
-#endif
 
-
-
------------------------
--- Output
-putEncodedStr :: Encoder -> Handle -> String -> IO ()
-#ifdef USE_GHC_ENCODINGS
-putEncodedStr _ h = hPutStr h
-#else
-putEncodedStr enc h s = enc s >>= B.hPutStr h
-#endif
-
-#ifdef TERMINFO
-getTermText :: Encoder -> String -> IO Terminfo.TermOutput
-#ifdef USE_GHC_ENCODINGS
-getTermText _ = return . Terminfo.termText
-#else
-getTermText enc s = enc s >>= return . Terminfo.termText . BC.unpack
-#endif
-#endif
-
-
-
--- Read at least one character of input, and more if immediately
--- available.  In particular the characters making up a control sequence
--- will all be available at once, so they can be processed together
--- (with Posix.lexKeys).
-getBlockOfChars :: Handle -> Decoder -> IO String
-#ifdef USE_GHC_ENCODINGS
-getBlockOfChars h _ = do
-    c <- hGetChar h
-    loop [c]
-  where
-    loop cs = do
-        isReady <- hReady h
-        if not isReady
-            then return $ reverse cs
-            else do
-                    c <- hGetChar h
-                    loop (c:cs)
-#else
-getBlockOfChars h decode = do
-    let bufferSize = 32
-    blockUntilInput h
-    bs <- B.hGetNonBlocking h bufferSize
-    decodeAndMore decode h bs
-
-#endif
-
--- Read in a single character, or Nothing if eof.
--- Assumes the handle is "prepared".
-getDecodedChar :: Handle -> Decoder -> MaybeT IO Char
-#ifdef USE_GHC_ENCODINGS
-getDecodedChar h _ = guardedEOF hGetChar h
-#else
-getDecodedChar h decode = do
-    b <- hGetByte h
-    cs <- liftIO $ decodeAndMore decode h (B.pack [b])
-    case cs of
-        [] -> return '?' -- shouldn't happen, but doesn't hurt to be careful.
-        (c:_) -> return c
-#endif
-
--- Read in a single line, or Nothing if eof.
-getDecodedLine :: Handle -> Decoder -> MaybeT IO String
-#ifdef USE_GHC_ENCODINGS
-getDecodedLine h _ = guardedEOF hGetLine h
-#else
-getDecodedLine h decode
-    = hGetLocaleLine h >>= liftIO . decodeAndMore decode h
-
-#endif
-
--- Helper functions for iconv encoding
-#ifndef USE_GHC_ENCODINGS
-blockUntilInput :: Handle -> IO ()
-#if __GLASGOW_HASKELL__ >= 611
--- threadWaitRead doesn't work with the new (ghc-6.12) IO library,
--- because it keeps a buffer even when NoBuffering is set.
-blockUntilInput h = hWaitForInput h (-1) >> return ()
-#else
--- hWaitForInput doesn't work with -threaded on ghc < 6.10
--- (#2363 in ghc's trac)
-blockUntilInput h = unsafeHandleToFD h >>= threadWaitRead . Fd
-#endif
-
-#endif
 
 
diff --git a/System/Console/Haskeline/Backend/Posix/IConv.hsc b/System/Console/Haskeline/Backend/Posix/IConv.hsc
deleted file mode 100644
--- a/System/Console/Haskeline/Backend/Posix/IConv.hsc
+++ /dev/null
@@ -1,177 +0,0 @@
-{- | This module exports iconv-based encoding/decoding, for use on
-older versions of GHC.  
--}
-module System.Console.Haskeline.Backend.Posix.IConv(
-        setLocale,
-        getCodeset,
-        openEncoder,
-        openDecoder,
-        openPartialDecoder,
-        PartialDecoder,
-        decodeAndMore,
-        ) where
-
-import Foreign.C
-import Foreign
-import Data.ByteString (ByteString, useAsCStringLen, append )
--- TODO: Base or Internal, depending on whether base>=3.
-import Data.ByteString.Internal (createAndTrim')
-import qualified Data.ByteString as B
-import qualified Data.ByteString.UTF8 as UTF8
-import Data.Maybe (fromMaybe)
-import System.IO (Handle)
-
-#include <locale.h>
-#include <langinfo.h>
-#include "h_iconv.h"
-
-openEncoder :: String -> IO (String -> IO ByteString)
-openEncoder codeset = do
-    encodeT <- iconvOpen codeset "UTF-8"
-    return $ simpleIConv dropUTF8Char encodeT . UTF8.fromString
-
-openDecoder :: String -> IO (ByteString -> IO String)
-openDecoder codeset = do
-    decodeT <- iconvOpen "UTF-8" codeset
-    return $ fmap UTF8.toString . simpleIConv (B.drop 1) decodeT
-
-dropUTF8Char :: ByteString -> ByteString
-dropUTF8Char = fromMaybe B.empty . fmap snd . UTF8.uncons
-
-replacement :: Word8
-replacement = toEnum (fromEnum '?')
-
--- handle errors by dropping unuseable chars.
-simpleIConv :: (ByteString -> ByteString) -> IConvT -> ByteString -> IO ByteString
-simpleIConv dropper t bs = do
-    (cs,result) <- iconv t bs
-    case result of
-        Invalid rest    -> continueOnError cs rest
-        Incomplete rest -> continueOnError cs rest
-        _               -> return cs
-  where
-    continueOnError cs rest = fmap ((cs `append`) . (replacement `B.cons`))
-                                $ simpleIConv dropper t (dropper rest)
-
-type PartialDecoder = ByteString -> IO (String,Result)
-
-openPartialDecoder :: String -> IO PartialDecoder
-openPartialDecoder codeset = do
-    decodeT <- iconvOpen "UTF-8" codeset
-    return $ \bs -> do
-        (s,result) <- iconv decodeT bs
-        return (UTF8.toString s,result)
-
----------------------
--- Setting the locale
-
-foreign import ccall "setlocale" c_setlocale :: CInt -> CString -> IO CString
-
-setLocale :: Maybe String -> IO (Maybe String)
-setLocale oldLocale = (maybeWith withCAString) oldLocale $ \loc_p -> do
-    c_setlocale (#const LC_CTYPE) loc_p >>= maybePeek peekCAString
-
------------------
--- Getting the encoding
-
-type NLItem = #type nl_item
-
-foreign import ccall nl_langinfo :: NLItem -> IO CString
-
-getCodeset :: IO String
-getCodeset = do
-    str <- nl_langinfo (#const CODESET) >>= peekCAString
-    -- check for codesets which may be returned by Solaris, but not understood
-    -- by GNU iconv.
-    if str `elem` ["","646"]
-        then return "ISO-8859-1"
-        else return str
-
-----------------
--- Iconv
-
--- TODO: This may not work on platforms where iconv_t is not a pointer.
-type IConvT = ForeignPtr ()
-type IConvTPtr = Ptr ()
-
-foreign import ccall "haskeline_iconv_open" iconv_open
-    :: CString -> CString -> IO IConvTPtr
-
-iconvOpen :: String -> String -> IO IConvT
-iconvOpen destName srcName = withCAString destName $ \dest ->
-                            withCAString srcName $ \src -> do
-                                res <- iconv_open dest src
-                                if res == nullPtr `plusPtr` (-1)
-                                    then throwErrno $ "iconvOpen "
-                                            ++ show (srcName,destName)
-                                    -- list the two it couldn't convert between?
-                                    else newForeignPtr iconv_close res
-
--- really this returns a CInt, but it's easiest to just ignore that, I think.
-foreign import ccall "& haskeline_iconv_close" iconv_close :: FunPtr (IConvTPtr -> IO ())
-
-foreign import ccall "haskeline_iconv" c_iconv :: IConvTPtr -> Ptr CString -> Ptr CSize
-                            -> Ptr CString -> Ptr CSize -> IO CSize
-
-data Result = Successful
-            | Invalid ByteString
-            | Incomplete ByteString
-    deriving Show
-
-iconv :: IConvT -> ByteString -> IO (ByteString,Result)
-iconv cd inStr = useAsCStringLen inStr $ \(inPtr, inBuffLen) ->
-        with inPtr $ \inBuff ->
-        with (toEnum inBuffLen) $ \inBytesLeft -> do
-                out <- loop inBuffLen (castPtr inBuff) inBytesLeft
-                return out
-    where
-        -- TODO: maybe a better algorithm for increasing the buffer size?
-        -- and also maybe a different starting buffer size?
-        biggerBuffer = (+1)
-        loop outSize inBuff inBytesLeft = do
-            (bs, errno) <- partialIconv cd outSize inBuff inBytesLeft
-            inLeft <- fmap fromEnum $ peek inBytesLeft
-            let rest = B.drop (B.length inStr - inLeft) inStr
-            case errno of
-                Nothing -> return (bs,Successful)
-                Just err 
-                    | err == e2BIG  -> do -- output buffer too small
-                            (bs',result) <- loop (biggerBuffer outSize) inBuff inBytesLeft
-                            -- TODO: is this efficient enough?
-                            return (bs `append` bs', result)
-                    | err == eINVAL -> return (bs,Incomplete rest)
-                    | otherwise     -> return (bs, Invalid rest)
-
-partialIconv :: IConvT -> Int -> Ptr CString -> Ptr CSize -> IO (ByteString, Maybe Errno)
-partialIconv cd outSize inBuff inBytesLeft =
-    withForeignPtr cd $ \cd_p ->
-    createAndTrim' outSize $ \outPtr ->
-    with outPtr $ \outBuff ->
-    with (toEnum outSize) $ \outBytesLeft -> do
-        -- ignore the return value; checking the errno is more reliable.
-        _ <- c_iconv cd_p inBuff inBytesLeft (castPtr outBuff) outBytesLeft
-        outLeft <- fmap fromEnum $ peek outBytesLeft
-        inLeft <- peek inBytesLeft
-        errno <- if inLeft > 0
-                    then fmap Just getErrno
-                    else return Nothing
-        return (0,outSize - outLeft,errno)
-
--------------
--- Decode the given ByteString.  If necessary, finish decoding it
--- by reading more bytes one at a time from the given handle.
--- (This assumes that the handle is in BinaryMode.)
-decodeAndMore:: PartialDecoder
-        -> Handle -> B.ByteString -> IO String
-decodeAndMore decoder h bs = do
-    (cs,result) <- decoder bs
-    case result of
-        Incomplete rest -> do
-            extra <- B.hGetNonBlocking h 1
-            if B.null extra
-                then return (cs ++ "?")
-                else fmap (cs++)
-                        $ decodeAndMore decoder h (rest `B.append` extra)
-        Invalid rest -> fmap ((cs ++) . ('?':))
-                            $ decodeAndMore decoder h (B.drop 1 rest)
-        Successful -> return cs
diff --git a/System/Console/Haskeline/Backend/Terminfo.hs b/System/Console/Haskeline/Backend/Terminfo.hs
--- a/System/Console/Haskeline/Backend/Terminfo.hs
+++ b/System/Console/Haskeline/Backend/Terminfo.hs
@@ -17,7 +17,6 @@
 import System.Console.Haskeline.LineState
 import System.Console.Haskeline.Term
 import System.Console.Haskeline.Backend.Posix
-import System.Console.Haskeline.Backend.Posix.Encoder (getTermText)
 import System.Console.Haskeline.Backend.WCWidth
 import System.Console.Haskeline.Key
 
@@ -106,11 +105,10 @@
                                     (PosixT m))))) a}
     deriving (Functor, Applicative, Monad, MonadIO, MonadException,
               MonadReader Actions, MonadReader Terminal, MonadState TermPos,
-              MonadState TermRows,
-              MonadReader Handles, MonadReader Encoder)
+              MonadState TermRows, MonadReader Handles)
 
 instance MonadTrans Draw where
-    lift = Draw . lift . lift . lift . lift . lift . lift
+    lift = Draw . lift . lift . lift . lift . lift
 
 evalDraw :: forall m . (MonadReader Layout m, CommandMonad m) => Terminal -> Actions -> EvalTerm (PosixT m)
 evalDraw term actions = EvalTerm eval liftE
@@ -200,10 +198,7 @@
                           -- see GHC ticket #1749).
 
 outputText :: String -> ActionM ()
-outputText str = do
-    encode <- lift ask
-    liftIO (getTermText encode str)
-        >>= output . const
+outputText = output . const . termText
 
 left,right,up :: Int -> TermAction
 left = flip leftA
diff --git a/System/Console/Haskeline/Backend/Win32.hsc b/System/Console/Haskeline/Backend/Win32.hsc
--- a/System/Console/Haskeline/Backend/Win32.hsc
+++ b/System/Console/Haskeline/Backend/Win32.hsc
@@ -380,17 +380,20 @@
     hs <- consoleHandles
     ch <- liftIO newChan
     fileRT <- liftIO $ fileRunTerm stdin
-    return fileRT {
-                            termOps = Left TermOps {
-                                getLayout = getBufferSize (hOut hs)
-                                , withGetEvent = withWindowMode hs
-                                                    . win32WithEvent hs ch
-                                , saveUnusedKeys = saveKeys ch
-                                , evalTerm = EvalTerm (runReaderT' hs . runDraw)
-                                                    (Draw . lift)
-                                },
-                            closeTerm = closeHandles hs
-                        }
+    return fileRT
+      { termOps = Left TermOps {
+          getLayout = getBufferSize (hOut hs)
+          , withGetEvent = withWindowMode hs
+                              . win32WithEvent hs ch
+          , saveUnusedKeys = saveKeys ch
+          , evalTerm = EvalTerm (runReaderT' hs . runDraw)
+                              (Draw . lift)
+          , externalPrint = writeChan ch . ExternalPrint
+          }
+      , closeTerm = do
+          flushEventQueue (putStrOut fileRT) ch
+          closeHandles hs
+      }
 
 win32WithEvent :: MonadException m => Handles -> Chan Event
                                         -> (m Event -> m a) -> m a
@@ -545,4 +548,3 @@
     liftIO $ fillConsoleChar h ' ' windowSize origin
     liftIO $ fillConsoleAttribute h attr windowSize origin
     setPos origin
-
diff --git a/System/Console/Haskeline/Directory.hsc b/System/Console/Haskeline/Directory.hsc
--- a/System/Console/Haskeline/Directory.hsc
+++ b/System/Console/Haskeline/Directory.hsc
@@ -14,9 +14,7 @@
 import Foreign
 import Foreign.C
 import System.Win32.Types
-#if __GLASGOW_HASKELL__ >= 611
 import qualified System.Directory
-#endif
 
 #include <windows.h>
 #include <shlobj.h>
@@ -62,59 +60,11 @@
     return $ attrs /= (#const INVALID_FILE_ATTRIBUTES)
             && (attrs .&. (#const FILE_ATTRIBUTE_DIRECTORY)) /= 0
 
-#if __GLASGOW_HASKELL__ >= 611
 getHomeDirectory :: IO FilePath
 getHomeDirectory = System.Directory.getHomeDirectory
-#else
-type HRESULT = #type HRESULT
 
-foreign import WINDOWS_CCONV "SHGetFolderPathW" c_SHGetFolderPath
-    :: Ptr () -> CInt -> HANDLE -> DWORD -> LPTSTR -> IO HRESULT
-
-getHomeDirectory :: IO FilePath
-getHomeDirectory = allocaBytes ((#const MAX_PATH) * (#size TCHAR)) $ \pathPtr -> do
-    result <- c_SHGetFolderPath nullPtr (#const CSIDL_PROFILE) nullPtr 0 pathPtr
-
-    if result /= (#const S_OK)
-        then return ""
-        else peekCWString pathPtr
-#endif
-
 #else 
--- POSIX
--- On 7.2.1 and later, getDirectoryContents uses the locale encoding
--- But previous version don't, so we need to decode manually.
 
-#if __GLASGOW_HASKELL__ >= 701
 import System.Directory
-#else
 
-import Data.ByteString.Char8 (pack, unpack)
-import qualified System.Directory as D
-import Control.Exception
-import System.Console.Haskeline.Backend.Posix.IConv
-
-getDirectoryContents :: FilePath -> IO [FilePath]
-getDirectoryContents path = do
-    codeset <- getCodeset
-    encoder <- openEncoder codeset
-    decoder <- openDecoder codeset
-    dirEnc <- fmap unpack (encoder path)
-    filesEnc <- handle (\(_::IOException) -> return [])
-                    $ D.getDirectoryContents dirEnc
-    mapM (decoder . pack) filesEnc
-
-doesDirectoryExist :: FilePath -> IO Bool
-doesDirectoryExist file = do
-    codeset <- getCodeset
-    encoder <- openEncoder codeset
-    encoder file >>= D.doesDirectoryExist . unpack
-
-getHomeDirectory :: IO FilePath
-getHomeDirectory = do
-    codeset <- getCodeset
-    decoder <- openDecoder codeset
-    handle (\(_::IOException) -> return "")
-        $ D.getHomeDirectory >>= decoder . pack
-#endif
 #endif
diff --git a/System/Console/Haskeline/History.hs b/System/Console/Haskeline/History.hs
--- a/System/Console/Haskeline/History.hs
+++ b/System/Console/Haskeline/History.hs
@@ -32,13 +32,8 @@
 
 import System.Directory(doesFileExist)
 
-#ifdef USE_GHC_ENCODINGS
 import qualified System.IO as IO
 import System.Console.Haskeline.Recover
-#else
-import qualified Data.ByteString as B
-import qualified Data.ByteString.UTF8 as UTF8
-#endif
 
 data History = History {histLines :: Seq String,
                         stifleAmt :: Maybe Int}
@@ -117,7 +112,6 @@
 -- UTF-8 file I/O, for old versions of GHC
 
 readUTF8File :: FilePath -> IO String
-#ifdef USE_GHC_ENCODINGS
 readUTF8File file = do
     h <- IO.openFile file IO.ReadMode
     IO.hSetEncoding h $ transliterateFailure IO.utf8
@@ -126,15 +120,8 @@
     _ <- evaluate (length contents)
     IO.hClose h
     return contents
-#else
-readUTF8File file = do
-    contents <- fmap UTF8.toString $ B.readFile file
-    _ <- evaluate (length contents)
-    return contents
-#endif
 
 writeUTF8File :: FilePath -> String -> IO ()
-#ifdef USE_GHC_ENCODINGS
 writeUTF8File file contents = do
     h <- IO.openFile file IO.WriteMode
     IO.hSetEncoding h IO.utf8
@@ -142,8 +129,3 @@
     IO.hSetNewlineMode h IO.noNewlineTranslation
     IO.hPutStr h contents
     IO.hClose h
-#else
--- use binary file I/O to avoid Windows CRLF line endings
--- which cause confusion when switching between systems.
-writeUTF8File file = B.writeFile file . UTF8.fromString
-#endif
diff --git a/System/Console/Haskeline/InputT.hs b/System/Console/Haskeline/InputT.hs
--- a/System/Console/Haskeline/InputT.hs
+++ b/System/Console/Haskeline/InputT.hs
@@ -15,6 +15,7 @@
 import System.FilePath
 import Control.Applicative
 import Control.Monad (liftM, ap)
+import Control.Monad.Fix
 import System.IO
 import Data.IORef
 
@@ -55,6 +56,9 @@
 
 instance MonadTrans InputT where
     lift = InputT . lift . lift . lift . lift . lift
+
+instance ( MonadFix m ) => MonadFix (InputT m) where
+    mfix f = InputT (mfix (unInputT . f))
 
 -- | Get the current line input history.
 getHistory :: MonadIO m => InputT m History
diff --git a/System/Console/Haskeline/RunCommand.hs b/System/Console/Haskeline/RunCommand.hs
--- a/System/Console/Haskeline/RunCommand.hs
+++ b/System/Console/Haskeline/RunCommand.hs
@@ -40,6 +40,9 @@
                     KeyInput ks -> do
                         bound_ks <- mapM (asks . lookupKeyBinding) ks
                         loopCmd s $ applyKeysToMap (concat bound_ks) next
+                    ExternalPrint str -> do
+                        printPreservingLineChars s str
+                        readMoreKeys s next
 
     loopCmd :: LineChars -> CmdM m (a,[Key]) -> n a
     loopCmd s (GetKey next) = readMoreKeys s next
@@ -57,6 +60,11 @@
                                     moveToNextLine s
                                     return x
 
+printPreservingLineChars :: Term m => LineChars -> String -> m ()
+printPreservingLineChars s str =  do
+    clearLine s
+    printLines . lines $ str
+    drawLine s
 
 drawReposition :: (Term n, MonadState Layout m)
     => (forall a . m a -> n a) -> TermOps -> LineChars -> n ()
diff --git a/System/Console/Haskeline/Term.hs b/System/Console/Haskeline/Term.hs
--- a/System/Console/Haskeline/Term.hs
+++ b/System/Console/Haskeline/Term.hs
@@ -28,25 +28,42 @@
 drawLine = drawLineDiff ([],[])
 
 clearLine = flip drawLineDiff ([],[])
-    
+
 data RunTerm = RunTerm {
             -- | Write unicode characters to stdout.
             putStrOut :: String -> IO (),
             termOps :: Either TermOps FileOps,
-            wrapInterrupt :: forall a . IO a -> IO a,            
+            wrapInterrupt :: forall a . IO a -> IO a,
             closeTerm :: IO ()
     }
 
 -- | Operations needed for terminal-style interaction.
-data TermOps = TermOps {
-            getLayout :: IO Layout
-            , withGetEvent :: forall m a . CommandMonad m => (m Event -> m a) -> m a
-            , evalTerm :: forall m . CommandMonad m => EvalTerm m
-            , saveUnusedKeys :: [Key] -> IO ()
-        }
+data TermOps = TermOps
+    { getLayout :: IO Layout
+    , withGetEvent :: forall m a . CommandMonad m => (m Event -> m a) -> m a
+    , evalTerm :: forall m . CommandMonad m => EvalTerm m
+    , saveUnusedKeys :: [Key] -> IO ()
+    , externalPrint :: String -> IO ()
+    }
 
+-- This hack is needed to grab latest writes from some other thread.
+-- Without it, if you are using another thread to process the logging
+-- and write on screen via exposed externalPrint, latest writes from
+-- this thread are not able to cross the thread boundary in time.
+flushEventQueue :: (String -> IO ()) -> Chan Event -> IO ()
+flushEventQueue print' eventChan = yield >> loopUntilFlushed
+    where loopUntilFlushed = do
+              flushed <- isEmptyChan eventChan
+              if flushed then return () else do
+                  event <- readChan eventChan
+                  case event of
+                      ExternalPrint str -> do
+                          print' (str ++ "\n") >> loopUntilFlushed
+                      -- We don't want to raise exceptions when doing cleanup.
+                      _ -> loopUntilFlushed
+
 -- | Operations needed for file-style interaction.
--- 
+--
 -- Backends can assume that getLocaleLine, getLocaleChar and maybeReadNewline
 -- are "wrapped" by wrapFileInput.
 data FileOps = FileOps {
@@ -96,8 +113,12 @@
 matchInit (x:xs) (y:ys)  | x == y = matchInit xs ys
 matchInit xs ys = (xs,ys)
 
-data Event = WindowResize | KeyInput [Key] | ErrorEvent SomeException
-                deriving Show
+data Event
+  = WindowResize
+  | KeyInput [Key]
+  | ErrorEvent SomeException
+  | ExternalPrint String
+  deriving Show
 
 keyEventLoop :: IO [Event] -> Chan Event -> IO Event
 keyEventLoop readEvents eventChan = do
@@ -121,7 +142,7 @@
             else -- Use the lock to work around the fact that writeList2Chan
                  -- isn't atomic.  Otherwise, some events could be ignored if
                  -- the subthread is killed before it saves them in the chan.
-                 bracket_ (putMVar lock ()) (takeMVar lock) $ 
+                 bracket_ (putMVar lock ()) (takeMVar lock) $
                     writeList2Chan eventChan es
     handleErrorEvent = handle $ \e -> case fromException e of
                                 Just ThreadKilled -> return ()
@@ -138,13 +159,9 @@
 
 -- | Utility function since we're not using the new IO library yet.
 hWithBinaryMode :: MonadException m => Handle -> m a -> m a
-#if __GLASGOW_HASKELL__ >= 611
 hWithBinaryMode h = bracket (liftIO $ hGetEncoding h)
                         (maybe (return ()) (liftIO . hSetEncoding h))
                         . const . (liftIO (hSetBinaryMode h True) >>)
-#else
-hWithBinaryMode _ = id
-#endif
 
 -- | Utility function for changing a property of a terminal for the duration of
 -- a computation.
@@ -170,7 +187,7 @@
 -- 1) By itself, this (by using hReady) might crash on invalid characters.
 -- The handle should be set to binary mode or a TextEncoder that
 -- transliterates or ignores invalid input.
--- 
+--
 -- 1) Note that in ghc-6.8.3 and earlier, hReady returns False at an EOF,
 -- whereas in ghc-6.10.1 and later it throws an exception.  (GHC trac #1063).
 -- This code handles both of those cases.
@@ -195,4 +212,3 @@
     liftIO $ if buff == NoBuffering
         then fmap BC.pack $ System.IO.hGetLine h
         else BC.hGetLine h
-
diff --git a/cbits/h_iconv.c b/cbits/h_iconv.c
deleted file mode 100644
--- a/cbits/h_iconv.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include "h_iconv.h"
-
-// Wrapper functions, since iconv_open et al are macros in libiconv.
-iconv_t haskeline_iconv_open(const char *tocode, const char *fromcode) {
-    return iconv_open(tocode, fromcode);
-}
-
-void haskeline_iconv_close(iconv_t cd) {
-    iconv_close(cd);
-}
-
-size_t haskeline_iconv(iconv_t cd, char **inbuf, size_t *inbytesleft,
-                char **outbuf, size_t *outbytesleft) {
-    // Cast inbuf to (void*) so that it works both on Solaris, which expects
-    // a (const char**), and on other platforms (e.g. Linux), which expect
-    // a (char **).
-    return iconv(cd, (void*)inbuf, inbytesleft, outbuf, outbytesleft);
-}
diff --git a/haskeline.cabal b/haskeline.cabal
--- a/haskeline.cabal
+++ b/haskeline.cabal
@@ -1,6 +1,6 @@
 Name:           haskeline
 Cabal-Version:  >=1.10
-Version:        0.7.2.3
+Version:        0.7.3.0
 Category:       User Interfaces
 License:        BSD3
 License-File:   LICENSE
@@ -9,16 +9,16 @@
 Maintainer:     Judah Jacobson <judah.jacobson@gmail.com>
 Category:       User Interfaces
 Synopsis:       A command-line interface for user input, written in Haskell.
-Description:    
+Description:
                 Haskeline provides a user interface for line input in command-line
                 programs.  This library is similar in purpose to readline, but since
                 it is written in Haskell it is (hopefully) more easily used in other
                 Haskell programs.
                 .
                 Haskeline runs both on POSIX-compatible systems and on Windows.
-Homepage:       https://github.com/judah/haskeline
+Homepage:       http://trac.haskell.org/haskeline
 Bug-Reports:    https://github.com/judah/haskeline/issues
-Stability:      Experimental
+Stability:      Stable
 Build-Type:     Custom
 extra-source-files: examples/Test.hs Changelog
 
@@ -38,24 +38,15 @@
     Description: Use the terminfo package for POSIX consoles.
     Default: True
 
--- Note that the Setup script checks whether -liconv is necessary.  This flag
--- lets us override that decision.  When it is True, we use -liconv.  When it
--- is False, we run tests to decide.
-flag libiconv
-    Description: Explicitly link against the libiconv library.
-    Default: False
-
-flag legacy-encoding
-    Description: Use the legacy iconv encoding for POSIX, even on ghc>=7.4.1.
-                 (Intended for testing only.)
-    Default: False
-
 Library
-    Build-depends: base >=4.3 && < 4.10, containers>=0.4 && < 0.6,
-                   directory>=1.1 && < 1.3, bytestring>=0.9 && < 0.11,
+    -- We require ghc>=7.4.1 (base>=4.5) to use the base library encodings, even
+    -- though it was implemented in earlier releases, due to GHC bug #5436 which
+    -- wasn't fixed until 7.4.1
+    Build-depends: base >=4.5 && < 4.11, containers>=0.4 && < 0.6,
+                   directory>=1.1 && < 1.4, bytestring>=0.9 && < 0.11,
                    filepath >= 1.2 && < 1.5, transformers >= 0.2 && < 0.6
     Default-Language: Haskell98
-    Default-Extensions: 
+    Default-Extensions:
                 ForeignFunctionInterface, Rank2Types, FlexibleInstances,
                 TypeSynonymInstances
                 FlexibleContexts, ExistentialQuantification
@@ -84,6 +75,7 @@
                 System.Console.Haskeline.LineState
                 System.Console.Haskeline.Monads
                 System.Console.Haskeline.Prefs
+                System.Console.Haskeline.Recover
                 System.Console.Haskeline.RunCommand
                 System.Console.Haskeline.Term
                 System.Console.Haskeline.Command.Undo
@@ -91,15 +83,6 @@
     include-dirs: includes
     c-sources: cbits/h_wcwidth.c
 
-    -- We require ghc>=7.4.1 to use the base library encodings,
-    -- even though it was implemented in earlier releases,
-    -- due to GHC bug #5436 which wasn't fixed until 7.4.1
-    if !flag(legacy-encoding) && impl(ghc>=7.4) {
-        cpp-options: -DUSE_GHC_ENCODINGS
-        Other-modules: System.Console.Haskeline.Recover
-    } else {
-        Build-depends: utf8-string==0.3.* && >=0.3.6
-    }
     if os(windows) {
         Build-depends: Win32>=2.0
         Other-modules: System.Console.Haskeline.Backend.Win32
@@ -109,14 +92,6 @@
         cpp-options: -DMINGW
     } else {
         Build-depends: unix>=2.0 && < 2.8
-                        -- unix-2.3 doesn't build on ghc-6.8.1 or earlier
-        -- Use manual encoding/decoding on ghc<7.4
-        if flag (legacy-encoding) || impl(ghc<7.4) {
-            c-sources: cbits/h_iconv.c
-            includes: h_iconv.h
-            install-includes: h_iconv.h
-            Other-modules: System.Console.Haskeline.Backend.Posix.IConv
-        }
         Other-modules: 
                 System.Console.Haskeline.Backend.Posix
                 System.Console.Haskeline.Backend.Posix.Encoder
diff --git a/includes/h_iconv.h b/includes/h_iconv.h
deleted file mode 100644
--- a/includes/h_iconv.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <iconv.h>
-
-iconv_t haskeline_iconv_open(const char *tocode, const char *fromcode);
-
-void haskeline_iconv_close(iconv_t cd);
-
-size_t haskeline_iconv(iconv_t cd, char **inbuf, size_t *inbytesleft,
-                char **outbuf, size_t *outbytesleft);
-
