diff --git a/Changelog b/Changelog
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,12 @@
+Changed in version 0.8.1.0:
+   * Use grapheme's width to align a list of completions (#143)
+   * Add withRunInBase to help decompose InputT (#131)
+   * Add support for WINIO to haskeline. (#140)
+   * Allow base-4.15
+   * Eta expand as required by simplified subsumption rules in newer GHC
+   * Remove unused iconv cbits (#135)
+   * Support non-BMP characters (or, surrogate pairs) on Windows (#125)
+
 Changed in version 0.8.0.1:
    * Add a Cabal flag to disable the example executable as well as
      the test that uses it.
diff --git a/System/Console/Haskeline.hs b/System/Console/Haskeline.hs
--- a/System/Console/Haskeline.hs
+++ b/System/Console/Haskeline.hs
@@ -64,6 +64,7 @@
                     defaultPrefs,
                     runInputTWithPrefs,
                     runInputTBehaviorWithPrefs,
+                    withRunInBase,
                     -- ** History
                     -- $history
                     getHistory,
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
@@ -39,7 +39,7 @@
                                 
 instance (MonadIO m, MonadMask m, MonadReader Layout m) => Term (DumbTerm m) where
     reposition _ s = refitLine s
-    drawLineDiff = drawLineDiff'
+    drawLineDiff x y = drawLineDiff' x y
     
     printLines = mapM_ (printText . (++ crlf))
     moveToNextLine _ = printText crlf
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
@@ -202,7 +202,7 @@
                           -- see GHC ticket #1749).
 
 outputText :: String -> ActionM ()
-outputText = output . const . termText
+outputText s = output (const (termText s))
 
 left,right,up :: Int -> TermAction
 left = flip leftA
@@ -238,7 +238,7 @@
 
 moveRelative :: Int -> ActionM ()
 moveRelative n = liftM3 (advancePos n) ask get get
-                    >>= moveToPos
+                    >>= \p -> moveToPos p
 
 -- Note that these move by a certain number of cells, not graphemes.
 changeRight, changeLeft :: Int -> ActionM ()
diff --git a/System/Console/Haskeline/Backend/WCWidth.hs b/System/Console/Haskeline/Backend/WCWidth.hs
--- a/System/Console/Haskeline/Backend/WCWidth.hs
+++ b/System/Console/Haskeline/Backend/WCWidth.hs
@@ -13,7 +13,7 @@
 import Data.List
 import Foreign.C.Types
 
-foreign import ccall unsafe haskeline_mk_wcwidth :: CWchar -> CInt
+foreign import ccall unsafe haskeline_mk_wcwidth :: CInt -> CInt
 
 wcwidth :: Char -> Int
 wcwidth c = case haskeline_mk_wcwidth $ toEnum $ fromEnum c of
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
@@ -13,7 +13,7 @@
 import Data.List(intercalate)
 import Control.Concurrent.STM
 import Control.Concurrent hiding (throwTo)
-import Data.Char(isPrint)
+import Data.Char(isPrint, chr, ord)
 import Data.Maybe(mapMaybe)
 import Control.Exception (IOException, throwTo)
 import Control.Monad
@@ -66,8 +66,16 @@
         then eventReader h
         else do
             es <- readEvents h
-            return $ mapMaybe processEvent es
+            return $ combineSurrogatePairs $ mapMaybe processEvent es
 
+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
+combineSurrogatePairs (e:es) = e : combineSurrogatePairs es
+combineSurrogatePairs [] = []
+
 consoleHandles :: MaybeT IO Handles
 consoleHandles = do
     h_in <- open "CONIN$"
@@ -226,10 +234,10 @@
     -- To be safe, we pick a round number we know to be less than the limit.
     limit = 20000 -- known to be less than WriteConsoleW's buffer limit
     writeConsole'
-        = withArray (map (toEnum . fromEnum) xs)
-            $ \t_arr -> alloca $ \numWritten -> do
+        = withCWStringLen xs
+            $ \(t_arr, len) -> alloca $ \numWritten -> do
                     failIfFalse_ "WriteConsoleW"
-                        $ c_WriteConsoleW h t_arr (toEnum $ length xs)
+                        $ c_WriteConsoleW h t_arr (toEnum len)
                                 numWritten nullPtr
 
 foreign import WINDOWS_CCONV "windows.h MessageBeep" c_messageBeep :: UINT -> IO Bool
diff --git a/System/Console/Haskeline/Backend/Win32/Echo.hs b/System/Console/Haskeline/Backend/Win32/Echo.hs
--- a/System/Console/Haskeline/Backend/Win32/Echo.hs
+++ b/System/Console/Haskeline/Backend/Win32/Echo.hs
@@ -21,6 +21,10 @@
 import Foreign.StablePtr (StablePtr, freeStablePtr, newStablePtr)
 
 import GHC.IO.FD (FD(..))
+#if defined(__IO_MANAGER_WINIO__)
+import GHC.IO.Handle.Windows (handleToHANDLE)
+import GHC.IO.SubSystem ((<!>))
+#endif
 import GHC.IO.Handle.Types (Handle(..), Handle__(..))
 
 import System.Win32.Types (HANDLE)
@@ -145,11 +149,30 @@
 
 -- Originally authored by Max Bolingbroke in the ansi-terminal library
 withHandleToHANDLE :: Handle -> (HANDLE -> IO a) -> IO a
-withHandleToHANDLE haskell_handle action =
+#if defined(__IO_MANAGER_WINIO__)
+withHandleToHANDLE = withHandleToHANDLEPosix <!> withHandleToHANDLENative
+#else
+withHandleToHANDLE = withHandleToHANDLEPosix
+#endif
+
+#if defined(__IO_MANAGER_WINIO__)
+withHandleToHANDLENative :: Handle -> (HANDLE -> IO a) -> IO a
+withHandleToHANDLENative haskell_handle action =
     -- Create a stable pointer to the Handle. This prevents the garbage collector
     -- getting to it while we are doing horrible manipulations with it, and hence
     -- stops it being finalized (and closed).
     withStablePtr haskell_handle $ const $ do
+        windows_handle <- handleToHANDLE haskell_handle
+        -- Do what the user originally wanted
+        action windows_handle
+#endif
+
+withHandleToHANDLEPosix :: Handle -> (HANDLE -> IO a) -> IO a
+withHandleToHANDLEPosix haskell_handle action =
+    -- Create a stable pointer to the Handle. This prevents the garbage collector
+    -- getting to it while we are doing horrible manipulations with it, and hence
+    -- stops it being finalized (and closed).
+    withStablePtr haskell_handle $ const $ do
         -- Grab the write handle variable from the Handle
         let write_handle_mvar = case haskell_handle of
                 FileHandle _ handle_mvar     -> handle_mvar
@@ -162,7 +185,6 @@
 
         -- Finally, turn that (C-land) FD into a HANDLE using msvcrt
         windows_handle <- c_get_osfhandle fd
-
         -- Do what the user originally wanted
         action windows_handle
 
diff --git a/System/Console/Haskeline/Command/Completion.hs b/System/Console/Haskeline/Command/Completion.hs
--- a/System/Console/Haskeline/Command/Completion.hs
+++ b/System/Console/Haskeline/Command/Completion.hs
@@ -5,6 +5,7 @@
                             completionCmd
                             ) where
 
+import System.Console.Haskeline.Backend.WCWidth (gsWidth)
 import System.Console.Haskeline.Command
 import System.Console.Haskeline.Command.Undo
 import System.Console.Haskeline.Key
@@ -120,27 +121,26 @@
 makeLines ws layout = let
     minColPad = 2
     printWidth = width layout
-    maxLength = min printWidth (maximum (map length ws) + minColPad)
-    numCols = printWidth `div` maxLength
-    ls = if maxLength >= printWidth
+    maxWidth = min printWidth (maximum (map (gsWidth . stringToGraphemes) ws) + minColPad)
+    numCols = printWidth `div` maxWidth
+    ls = if maxWidth >= printWidth
                     then map (: []) ws
                     else splitIntoGroups numCols ws
-    in map (padWords maxLength) ls
+    in map (padWords maxWidth) ls
 
--- Add spaces to the end of each word so that it takes up the given length.
--- Don't padd the word in the last column, since printing a space in the last column
+-- Add spaces to the end of each word so that it takes up the given visual width.
+-- Don't pad the word in the last column, since printing a space in the last column
 -- causes a line wrap on some terminals.
 padWords :: Int -> [String] -> String
 padWords _ [x] = x
 padWords _ [] = ""
-padWords len (x:xs) = x ++ replicate (len - glength x) ' '
-                        ++ padWords len xs
+padWords wid (x:xs) = x ++ replicate (wid - widthOf x) ' '
+                        ++ padWords wid xs
     where
-        -- kludge: compute the length in graphemes, not chars.
-        -- but don't use graphemes for the max length, since I'm not convinced
-        -- that would work correctly. (This way, the worst that can happen is
-        -- that columns are longer than necessary.)
-        glength = length . stringToGraphemes
+        -- kludge: compute the width in graphemes, not chars.
+        -- also use graphemes for the max width so that multi-width characters
+        -- such as CJK letters are aligned correctly.
+        widthOf = gsWidth . stringToGraphemes
 
 -- Split xs into rows of length n,
 -- such that the list increases incrementally along the columns.
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
@@ -65,6 +65,27 @@
 instance ( MonadFix m ) => MonadFix (InputT m) where
     mfix f = InputT (mfix (unInputT . f))
 
+-- | Run an action in the underlying monad, as per 'lift', passing it a runner
+-- function which restores the current 'InputT' context. This can be used in
+-- the event that we have some function that takes an action in the underlying
+-- monad as an argument (such as 'lift', 'hoist', 'forkIO', etc) and we want
+-- to compose it with actions in 'InputT'.
+withRunInBase :: Monad m =>
+    ((forall a . InputT m a -> m a) -> m b) -> InputT m b
+withRunInBase inner = InputT $ do
+    runTerm <- ask
+    history <- ask
+    killRing <- ask
+    prefs <- ask
+    settings <- ask
+    lift $ lift $ lift $ lift $ lift $ inner $
+        flip runReaderT settings .
+        flip runReaderT prefs .
+        flip runReaderT killRing .
+        flip runReaderT history .
+        flip runReaderT runTerm .
+        unInputT
+
 -- | Get the current line input history.
 getHistory :: MonadIO m => InputT m History
 getHistory = InputT get
diff --git a/cbits/h_wcwidth.c b/cbits/h_wcwidth.c
--- a/cbits/h_wcwidth.c
+++ b/cbits/h_wcwidth.c
@@ -67,7 +67,7 @@
 };
 
 /* auxiliary function for binary search in interval table */
-static int haskeline_bisearch(wchar_t ucs, const struct interval *table, int max) {
+static int haskeline_bisearch(int ucs, const struct interval *table, int max) {
   int min = 0;
   int mid;
 
@@ -119,7 +119,7 @@
  * in ISO 10646.
  */
 
-int haskeline_mk_wcwidth(wchar_t ucs)
+int haskeline_mk_wcwidth(int ucs)
 {
   /* sorted list of non-overlapping intervals of non-spacing characters */
   /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
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.8.0.1
+Version:        0.8.1.0
 Category:       User Interfaces
 License:        BSD3
 License-File:   LICENSE
@@ -49,7 +49,7 @@
     -- 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.9 && < 4.15, containers>=0.4 && < 0.7,
+    Build-depends: base >=4.9 && < 4.16, containers>=0.4 && < 0.7,
                    directory>=1.1 && < 1.4, bytestring>=0.9 && < 0.11,
                    filepath >= 1.2 && < 1.5, transformers >= 0.2 && < 0.6,
                    process >= 1.0 && < 1.7, stm >= 2.4 && < 2.6,
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);
-
