diff --git a/README.textile b/README.textile
new file mode 100644
--- /dev/null
+++ b/README.textile
@@ -0,0 +1,52 @@
+h1. ANSI Terminal
+
+You can help improve this README with extra snippets and advice by using the "GitHub wiki":http://github.com/batterseapower/ansi-terminal/wikis/readme.
+
+
+h2. Installing
+
+To just install the library:
+
+<pre>
+<code>runghc Setup.lhs configure
+runghc Setup.lhs build
+sudo runghc Setup.lhs install
+</pre>
+</code>
+
+If you want to build the example, to check it's all working:
+
+<pre>
+<code>runghc Setup.lhs configure -fexample
+runghc Setup.lhs build
+dist/build/ansi-terminal-example/ansi-terminal-example
+</pre>
+</code>
+
+
+h2. Description
+
+"ANSI":http://en.wikipedia.org/wiki/ANSI_escape_sequences terminal support for Haskell, which allows:
+
+* Cursor movement
+* Screen and line clearing
+* Color output
+* Showing or hiding the cursor
+
+It is compatible with Windows (via an emulation layer) and those Unixes with ANSI terminals
+
+If you like this, you may be interested in "ansi-wl-pprint":http://github.com/batterseapower/ansi-wl-pprint, which provides a pretty-printer that can construct strings containing ANSI colorisation.
+
+
+h2. Example
+
+A full example is provided with the package, and can be compiled by suppling Cabal with the @-fexample@ flag. It is also available online at "GitHub":http://github.com/batterseapower/ansi-terminal/tree/master/System/Console/ANSI/Example.hs.
+
+The API is very simple, and should be available to look at "here":http://github.com/batterseapower/ansi-terminal/tree/master/includes/Common-Include.hs. It basically consists of @IO@ actions for the various operations. Note that a Unix-only library for ANSI output would permit a pure API that outputs strings, but unfortunately it's not possible to provide ANSI operations with strings in Windows, so I must provide a stateful @IO@-based interface.
+
+
+h2. Linkage
+
+* "Hackage":http://hackage.haskell.org/cgi-bin/hackage-scripts/package/ansi-terminal
+* "Bug Tracker":http://bsp.lighthouseapp.com/projects/16235-hs-ansi-terminal
+* "GitHub":http://github.com/batterseapower/ansi-terminal/
diff --git a/System/Console/ANSI.hs b/System/Console/ANSI.hs
--- a/System/Console/ANSI.hs
+++ b/System/Console/ANSI.hs
@@ -1,3 +1,31 @@
+-- | Provides ANSI terminal support for Windows and ANSI terminal software running on a Unix-like operating system.
+--
+-- The ANSI escape codes are described at <http://en.wikipedia.org/wiki/ANSI_escape_code> and provide a rich range of
+-- functionality for terminal control, which includes:
+--
+--  * Colored text output, with control over both foreground and background colors
+--
+--  * Hiding or showing the cursor
+--
+--  * Moving the cursor around
+--
+--  * Clearing parts of the screen
+--
+-- The most frequently used parts of this ANSI command set are exposed with a platform independent interface by
+-- this module.  Every function exported comes in three flavours:
+--
+--  * Vanilla: has an @IO ()@ type and doesn't take a @Handle@.  This just outputs the ANSI command directly on
+--    to the terminal corresponding to stdout.  Commands issued like this should work as you expect on both Windows
+--    and Unix.
+--
+--  * Chocolate: has an @IO ()@ type but takes a @Handle@.  This outputs the ANSI command on the terminal corresponding
+--    to the supplied handle.  Commands issued like this should also work as your expect on both Windows and Unix.
+--
+--  * Strawberry: has a @String@ type and just consists of an escape code which can be added to any other bit of text
+--    before being output.  This version of the API is often convenient to use, but due to fundamental limitations in
+--    Windows ANSI terminal support will only work on Unix.  On Windows these codes will always be the empty string,
+--    so it is possible to use them portably for e.g. coloring console output on the understanding that you will only
+--    see colors if you are running on a Unix-like operating system.
 #if defined(WINDOWS)
 module System.Console.ANSI (
         module System.Console.ANSI.Windows
diff --git a/System/Console/ANSI/Common.hs b/System/Console/ANSI/Common.hs
--- a/System/Console/ANSI/Common.hs
+++ b/System/Console/ANSI/Common.hs
@@ -1,5 +1,6 @@
 module System.Console.ANSI.Common where
 
+-- | ANSI colors: come in various intensities, which are controlled by 'ANSISGR'
 data ANSIColor = Black
                | Red
                | Green
@@ -10,6 +11,7 @@
                | White
                deriving (Bounded, Enum, Show)
 
+-- | ANSI Select Graphic Rendition command
 data ANSISGR = Reset
              | BoldIntensity
              | FaintIntensity -- ^ Not widely supported: sometimes treated as conceal
diff --git a/System/Console/ANSI/Unix.hs b/System/Console/ANSI/Unix.hs
--- a/System/Console/ANSI/Unix.hs
+++ b/System/Console/ANSI/Unix.hs
@@ -1,9 +1,12 @@
+{-# OPTIONS_HADDOCK hide #-}
 module System.Console.ANSI.Unix (
 #include "Exports-Include.hs"
     ) where
 
 import System.Console.ANSI.Common
 
+import System.IO
+
 import Data.List
 
 
@@ -11,38 +14,8 @@
 
 
 -- | The reference I used for the escape characters in this module was http://en.wikipedia.org/wiki/ANSI_escape_sequences
-csi :: [Int] -> String -> IO ()
-csi args code = putStr $ "\ESC[" ++ concat (intersperse ";" (map show args)) ++ code
-
-
-cursorUp n = csi [n] "A"
-cursorDown n = csi [n] "B"
-cursorForward n = csi [n] "C"
-cursorBackward n = csi [n] "D"
-
-nextLine n = csi [n] "E"
-previousLine n = csi [n] "F"
-
-setColumn n = csi [n + 1] "G"
-
-setPosition n m = csi [n + 1, m + 1] "H"
-
-clearFromCursorToScreenEnd = csi [0] "J"
-clearFromCursorToScreenBeginning = csi [1] "J"
-clearScreen = csi [2] "J"
-
-clearFromCursorToLineEnd = csi [0] "K"
-clearFromCursorToLineBeginning = csi [1] "K"
-clearLine = csi [2] "K"
-
-scrollPageUp n = csi [n] "S"
-scrollPageDown n = csi [n] "T"
-
-setSGR sgr = csi [ansiSGRToCode sgr] "m"
-
-hideCursor = csi [] "?25l"
-showCursor = csi [] "?25h"
-
+csi :: [Int] -> String -> String
+csi args code = "\ESC[" ++ concat (intersperse ";" (map show args)) ++ code
 
 ansiColorToCode :: ANSIColor -> Int
 ansiColorToCode color = case color of
@@ -76,3 +49,65 @@
     ForegroundHighIntensity color   -> 90 + ansiColorToCode color
     BackgroundNormalIntensity color -> 40 + ansiColorToCode color
     BackgroundHighIntensity color   -> 100 + ansiColorToCode color
+
+
+cursorUpCode n = csi [n] "A"
+cursorDownCode n = csi [n] "B"
+cursorForwardCode n = csi [n] "C"
+cursorBackwardCode n = csi [n] "D"
+
+hCursorUp h n = hPutStr h $ cursorUpCode n
+hCursorDown h n = hPutStr h $ cursorDownCode n
+hCursorForward h n = hPutStr h $ cursorForwardCode n
+hCursorBackward h n = hPutStr h $ cursorBackwardCode n
+
+
+nextLineCode n = csi [n] "E"
+previousLineCode n = csi [n] "F"
+
+hNextLine h n = hPutStr h $ nextLineCode n
+hPreviousLine h n = hPutStr h $ previousLineCode n
+
+
+setColumnCode n = csi [n + 1] "G"
+setPositionCode n m = csi [n + 1, m + 1] "H"
+
+hSetColumn h n = hPutStr h $ setColumnCode n
+hSetPosition h n m = hPutStr h $ setPositionCode n m
+
+
+clearFromCursorToScreenEndCode = csi [0] "J"
+clearFromCursorToScreenBeginningCode = csi [1] "J"
+clearScreenCode = csi [2] "J"
+
+hClearFromCursorToScreenEnd h = hPutStr h clearFromCursorToScreenEndCode
+hClearFromCursorToScreenBeginning h = hPutStr h clearFromCursorToScreenBeginningCode
+hClearScreen h = hPutStr h clearScreenCode
+
+
+clearFromCursorToLineEndCode = csi [0] "K"
+clearFromCursorToLineBeginningCode = csi [1] "K"
+clearLineCode = csi [2] "K"
+
+hClearFromCursorToLineEnd h = hPutStr h clearFromCursorToLineEndCode
+hClearFromCursorToLineBeginning h = hPutStr h clearFromCursorToLineBeginningCode
+hClearLine h = hPutStr h clearLineCode
+
+
+scrollPageUpCode n = csi [n] "S"
+scrollPageDownCode n = csi [n] "T"
+
+hScrollPageUp h n = hPutStr h $ scrollPageUpCode n
+hScrollPageDown h n = hPutStr h $ scrollPageDownCode n
+
+
+setSGRCode sgr = csi [ansiSGRToCode sgr] "m"
+
+hSetSGR h sgr = hPutStr h $ setSGRCode sgr
+
+
+hideCursorCode = csi [] "?25l"
+showCursorCode = csi [] "?25h"
+
+hHideCursor h = hPutStr h hideCursorCode
+hShowCursor h = hPutStr h showCursorCode
diff --git a/System/Console/ANSI/Windows.hs b/System/Console/ANSI/Windows.hs
--- a/System/Console/ANSI/Windows.hs
+++ b/System/Console/ANSI/Windows.hs
@@ -1,3 +1,4 @@
+{-# OPTIONS_HADDOCK hide #-}
 module System.Console.ANSI.Windows (
 #include "Exports-Include.hs"
     ) where
diff --git a/System/Console/ANSI/Windows/Emulator.hs b/System/Console/ANSI/Windows/Emulator.hs
--- a/System/Console/ANSI/Windows/Emulator.hs
+++ b/System/Console/ANSI/Windows/Emulator.hs
@@ -1,57 +1,65 @@
-module System.Console.ANSI.Windows.Emulator where
+module System.Console.ANSI.Windows.Emulator (
+#include "Exports-Include.hs"
+    ) where
 
 import System.Console.ANSI.Common
 import System.Console.ANSI.Windows.Foreign
 
+import System.IO
+
 import Data.Bits
 
 
 #include "Common-Include.hs"
 
 
-screenRectangle :: IO SMALL_RECT
-screenRectangle = do
-    handle <- getStdHandle sTD_OUTPUT_HANDLE
-    fmap csbi_window $ getConsoleScreenBufferInfo handle
-
-
-adjustCursorPosition :: (SHORT -> SHORT -> SHORT) -> (SHORT -> SHORT -> SHORT) -> IO ()
-adjustCursorPosition change_x change_y = do
-    handle <- getStdHandle sTD_OUTPUT_HANDLE
+adjustCursorPosition :: HANDLE -> (SHORT -> SHORT -> SHORT) -> (SHORT -> SHORT -> SHORT) -> IO ()
+adjustCursorPosition handle change_x change_y = do
     screen_buffer_info <- getConsoleScreenBufferInfo handle
     let window = csbi_window screen_buffer_info
         (COORD x y) = csbi_cursor_position screen_buffer_info
         cursor_pos' = COORD (change_x (rect_left window) x) (change_y (rect_top window) y)
     setConsoleCursorPosition handle cursor_pos'
 
-cursorUp n       = adjustCursorPosition (\_ x -> x) (\_ y -> y - fromIntegral n)
-cursorDown n     = adjustCursorPosition (\_ x -> x) (\_ y -> y + fromIntegral n)
-cursorForward n  = adjustCursorPosition (\_ x -> x + fromIntegral n) (\_ y -> y)
-cursorBackward n = adjustCursorPosition (\_ x -> x - fromIntegral n) (\_ y -> y)
+hCursorUp h n       = withHandleToHANDLE h $ \handle -> adjustCursorPosition handle (\_ x -> x) (\_ y -> y - fromIntegral n)
+hCursorDown h n     = withHandleToHANDLE h $ \handle -> adjustCursorPosition handle (\_ x -> x) (\_ y -> y + fromIntegral n)
+hCursorForward h n  = withHandleToHANDLE h $ \handle -> adjustCursorPosition handle (\_ x -> x + fromIntegral n) (\_ y -> y)
+hCursorBackward h n = withHandleToHANDLE h $ \handle -> adjustCursorPosition handle (\_ x -> x - fromIntegral n) (\_ y -> y)
 
+cursorUpCode _       = ""
+cursorDownCode _     = ""
+cursorForwardCode _  = ""
+cursorBackwardCode _ = ""
 
-adjustLine :: (SHORT -> SHORT -> SHORT) -> IO ()
-adjustLine change_y = do
-    adjustCursorPosition (\window_left _ -> window_left) change_y
 
-nextLine n     = adjustLine (\_ y -> y + fromIntegral n)
-previousLine n = adjustLine (\_ y -> y - fromIntegral n)
+adjustLine :: HANDLE -> (SHORT -> SHORT -> SHORT) -> IO ()
+adjustLine handle change_y = adjustCursorPosition handle (\window_left _ -> window_left) change_y
 
+hNextLine h n     = withHandleToHANDLE h $ \handle -> adjustLine handle (\_ y -> y + fromIntegral n)
+hPreviousLine h n = withHandleToHANDLE h $ \handle -> adjustLine handle (\_ y -> y - fromIntegral n)
 
-setColumn x = adjustCursorPosition (\window_left _ -> window_left + fromIntegral x) (\_ y -> y)
+nextLineCode _     = ""
+previousLineCode _ = ""
 
-setPosition y x = adjustCursorPosition (\window_left _ -> window_left + fromIntegral x) (\window_top _ -> window_top + fromIntegral y)
 
+hSetColumn h x = withHandleToHANDLE h $ \handle -> adjustCursorPosition handle (\window_left _ -> window_left + fromIntegral x) (\_ y -> y)
 
+setColumnCode _ = ""
+
+
+hSetPosition h y x = withHandleToHANDLE h $ \handle -> adjustCursorPosition handle (\window_left _ -> window_left + fromIntegral x) (\window_top _ -> window_top + fromIntegral y)
+
+setPositionCode _ _ = ""
+
+
 clearChar :: WCHAR
 clearChar = charToWCHAR ' '
 
 clearAttribute :: WORD
 clearAttribute = 0
 
-clearScreenFraction :: (SMALL_RECT -> COORD -> (DWORD, COORD)) -> IO ()
-clearScreenFraction fraction_finder = do
-    handle <- getStdHandle sTD_OUTPUT_HANDLE
+hClearScreenFraction :: HANDLE -> (SMALL_RECT -> COORD -> (DWORD, COORD)) -> IO ()
+hClearScreenFraction handle fraction_finder = do
     screen_buffer_info <- getConsoleScreenBufferInfo handle
     
     let window = csbi_window screen_buffer_info
@@ -62,7 +70,7 @@
     fillConsoleOutputAttribute handle clearAttribute fill_length fill_cursor_pos
     return ()
 
-clearFromCursorToScreenEnd = clearScreenFraction go
+hClearFromCursorToScreenEnd h = withHandleToHANDLE h $ \handle -> hClearScreenFraction handle go
   where
     go window cursor_pos = (fromIntegral fill_length, cursor_pos)
       where
@@ -71,7 +79,7 @@
         line_remainder = size_x - coord_x cursor_pos
         fill_length = size_x * size_y + line_remainder
 
-clearFromCursorToScreenBeginning = clearScreenFraction go
+hClearFromCursorToScreenBeginning h = withHandleToHANDLE h $ \handle -> hClearScreenFraction handle go
   where
     go window cursor_pos = (fromIntegral fill_length, rect_top_left window)
       where
@@ -80,7 +88,7 @@
         line_remainder = coord_x cursor_pos
         fill_length = size_x * size_y + line_remainder
 
-clearScreen = clearScreenFraction go
+hClearScreen h = withHandleToHANDLE h $ \handle -> hClearScreenFraction handle go
   where
     go window _ = (fromIntegral fill_length, rect_top_left window)
       where
@@ -88,32 +96,41 @@
         size_y = rect_height window
         fill_length = size_x * size_y
 
-clearFromCursorToLineEnd = clearScreenFraction go
+hClearFromCursorToLineEnd h = withHandleToHANDLE h $ \handle -> hClearScreenFraction handle go
   where
     go window cursor_pos = (fromIntegral (rect_right window - coord_x cursor_pos), cursor_pos)
 
-clearFromCursorToLineBeginning = clearScreenFraction go
+hClearFromCursorToLineBeginning h = withHandleToHANDLE h $ \handle -> hClearScreenFraction handle go
   where
     go window cursor_pos = (fromIntegral (coord_x cursor_pos), cursor_pos { coord_x = rect_left window })
 
-clearLine = clearScreenFraction go
+hClearLine h = withHandleToHANDLE h $ \handle -> hClearScreenFraction handle go
   where
     go window cursor_pos = (fromIntegral (rect_width window), cursor_pos { coord_x = rect_left window })
 
+clearFromCursorToScreenEndCode       = ""
+clearFromCursorToScreenBeginningCode = ""
+clearScreenCode                      = ""
+clearFromCursorToLineEndCode         = ""
+clearFromCursorToLineBeginningCode   = ""
+clearLineCode                        = ""
 
-scrollPage :: Int -> IO ()
-scrollPage new_origin_y = do
-    handle <- getStdHandle sTD_OUTPUT_HANDLE
+
+hScrollPage :: HANDLE -> Int -> IO ()
+hScrollPage handle new_origin_y = do
     screen_buffer_info <- getConsoleScreenBufferInfo handle
     let fill = CHAR_INFO clearChar clearAttribute
         window = csbi_window screen_buffer_info
         origin = COORD (rect_left window) (rect_top window + fromIntegral new_origin_y)
     scrollConsoleScreenBuffer handle window Nothing origin fill
 
-scrollPageUp n = scrollPage (negate n)
-scrollPageDown n = scrollPage n
+hScrollPageUp h n = withHandleToHANDLE h $ \handle -> hScrollPage handle (negate n)
+hScrollPageDown h n = withHandleToHANDLE h $ \handle -> hScrollPage handle n
 
+scrollPageUpCode _   = ""
+scrollPageDownCode _ = ""
 
+
 {-# INLINE applyANSIColorToAttribute #-}
 applyANSIColorToAttribute :: WORD -> WORD -> WORD -> ANSIColor -> WORD -> WORD
 applyANSIColorToAttribute rED gREEN bLUE color attribute = case color of
@@ -176,20 +193,22 @@
   where
     iNTENSITY = fOREGROUND_INTENSITY .|. bACKGROUND_INTENSITY
 
-setSGR sgr = do
-    handle <- getStdHandle sTD_OUTPUT_HANDLE
+hSetSGR h sgr = withHandleToHANDLE h $ \handle -> do
     screen_buffer_info <- getConsoleScreenBufferInfo handle
     let attribute = csbi_attributes screen_buffer_info
         attribute' = applyANSISGRToAttribute sgr attribute
     setConsoleTextAttribute handle attribute'
 
+setSGRCode _ = ""
 
-changeCursorVisibility :: Bool -> IO ()
-changeCursorVisibility cursor_visible = do
-    handle <- getStdHandle sTD_OUTPUT_HANDLE
+
+hChangeCursorVisibility :: HANDLE -> Bool -> IO ()
+hChangeCursorVisibility handle cursor_visible = do
     cursor_info <- getConsoleCursorInfo handle
     setConsoleCursorInfo handle (cursor_info { cci_cursor_visible = cursor_visible })
 
-hideCursor = changeCursorVisibility False
-showCursor = changeCursorVisibility True
-    
+hHideCursor h = withHandleToHANDLE h $ \handle -> hChangeCursorVisibility handle False
+hShowCursor h = withHandleToHANDLE h $ \handle -> hChangeCursorVisibility handle True
+
+hideCursorCode = ""
+showCursorCode = ""
diff --git a/System/Console/ANSI/Windows/Foreign.hs b/System/Console/ANSI/Windows/Foreign.hs
--- a/System/Console/ANSI/Windows/Foreign.hs
+++ b/System/Console/ANSI/Windows/Foreign.hs
@@ -24,7 +24,9 @@
         
         fillConsoleOutputAttribute,
         fillConsoleOutputCharacter,
-        scrollConsoleScreenBuffer
+        scrollConsoleScreenBuffer,
+        
+        withHandleToHANDLE
     ) where
 
 import Foreign.C.Types
@@ -37,7 +39,14 @@
 
 import System.Win32.Types
 
+import Control.Concurrent.MVar
+import Control.Exception (bracket)
 
+import Foreign.StablePtr
+
+import GHC.IOBase (Handle(..), Handle__(..), FD)
+
+
 -- Some Windows types missing from System.Win32
 type SHORT = CShort
 type WCHAR = CWchar
@@ -264,3 +273,35 @@
     maybeWith with mb_clip_rectangle $ \ptr_clip_rectangle ->
     with fill $ \ptr_fill ->
     failIfFalse_ "scrollConsoleScreenBuffer" $ cScrollConsoleScreenBuffer handle ptr_scroll_rectangle ptr_clip_rectangle (unpackCOORD destination_origin) ptr_fill
+
+
+-- This essential function comes from msvcrt.  It's OK to depend on msvcrt since GHC's base package does.
+foreign import ccall unsafe "_get_osfhandle" cget_osfhandle :: FD -> IO HANDLE
+
+-- | This bit is all highly dubious.  The problem is that we want to output ANSI to arbitrary Handles rather than forcing
+-- people to use stdout.  However, the Windows ANSI emulator needs a Windows HANDLE to work it's magic, so we need to be able
+-- to extract one of those from the Haskell Handle.
+--
+-- This code accomplishes this, albeit at the cost of only being compatible with GHC.
+withHandleToHANDLE :: Handle -> (HANDLE -> IO a) -> IO a
+withHandleToHANDLE 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
+                DuplexHandle _ _ handle_mvar -> handle_mvar -- This is "write" MVar, we could also take the "read" one
+        
+        -- Get the FD from the algebraic data type
+        fd <- fmap haFD $ readMVar write_handle_mvar
+        
+        -- Finally, turn that (C-land) FD into a HANDLE using msvcrt
+        windows_handle <- cget_osfhandle fd
+        
+        -- Do what the user originally wanted
+        action windows_handle
+
+withStablePtr :: a -> (StablePtr a -> IO b) -> IO b
+withStablePtr value = bracket (newStablePtr value) freeStablePtr
diff --git a/ansi-terminal.cabal b/ansi-terminal.cabal
--- a/ansi-terminal.cabal
+++ b/ansi-terminal.cabal
@@ -1,15 +1,17 @@
-Name:           ansi-terminal
-Version:        0.2.1
-Cabal-Version:  >= 1.2
-Category:       User Interfaces
-Synopsis:       Simple ANSI terminal support, with Windows compatibility
-Description:    ANSI terminal support for Haskell: allows cursor movement, screen clearing, color output and showing or hiding the cursor. Compatible with Windows and those Unixes with ANSI terminals.
-License:        BSD3
-License-File:   LICENSE
-Author:         Max Bolingbroke
-Maintainer:     batterseapower@hotmail.com
-Homepage:       http://bsp.lighthouseapp.com/projects/16235-hs-ansi-terminal/overview
-Build-Type:     Simple
+Name:                ansi-terminal
+Version:             0.3.0
+Cabal-Version:       >= 1.2
+Category:            User Interfaces
+Synopsis:            Simple ANSI terminal support, with Windows compatibility
+Description:         ANSI terminal support for Haskell: allows cursor movement, screen clearing, color output and showing or hiding the cursor.
+                     Compatible with Windows and those Unixes with ANSI terminals, but only GHC is supported as a compiler.
+License:             BSD3
+License-File:        LICENSE
+Extra-Source-Files:  README.textile
+Author:              Max Bolingbroke
+Maintainer:          batterseapower@hotmail.com
+Homepage:            http://github.com/batterseapower/ansi-terminal
+Build-Type:          Simple
 
 Extra-Source-Files:     includes/Common-Include.hs
                         includes/Exports-Include.hs
@@ -32,7 +34,7 @@
         if os(windows)
                 Build-Depends:          Win32 >= 2.0
                 Cpp-Options:            -DWINDOWS
-                Extra-Libraries:        "kernel32"
+                Extra-Libraries:        "kernel32", "msvcrt"
                 Other-Modules:          System.Console.ANSI.Windows
                                         System.Console.ANSI.Windows.Foreign
                                         System.Console.ANSI.Windows.Emulator
@@ -60,7 +62,7 @@
         if os(windows)
                 Build-Depends:          Win32 >= 2.0
                 Cpp-Options:            -DWINDOWS
-                Extra-Libraries:        "kernel32"
+                Extra-Libraries:        "kernel32", "msvcrt"
                 Other-Modules:          System.Console.ANSI.Windows
                                         System.Console.ANSI.Windows.Foreign
                                         System.Console.ANSI.Windows.Emulator
diff --git a/includes/Common-Include.hs b/includes/Common-Include.hs
--- a/includes/Common-Include.hs
+++ b/includes/Common-Include.hs
@@ -1,24 +1,107 @@
+hCursorUp, hCursorDown, hCursorForward, hCursorBackward :: Handle
+                                                        -> Int -- ^ Number of lines or characters to move
+                                                        -> IO ()
 cursorUp, cursorDown, cursorForward, cursorBackward :: Int -- ^ Number of lines or characters to move
                                                     -> IO ()
+cursorUpCode, cursorDownCode, cursorForwardCode, cursorBackwardCode :: Int -- ^ Number of lines or characters to move
+                                                                    -> String
 
+cursorUp = hCursorUp stdout
+cursorDown = hCursorDown stdout
+cursorForward = hCursorForward stdout
+cursorBackward = hCursorBackward stdout
+
+
+hNextLine, hPreviousLine :: Handle
+                         -> Int -- ^ Number of lines to move
+                         -> IO ()
 nextLine, previousLine :: Int -- ^ Number of lines to move
                        -> IO ()
+nextLineCode, previousLineCode :: Int -- ^ Number of lines to move
+                               -> String
 
+nextLine = hNextLine stdout
+previousLine = hPreviousLine stdout
+
+
+hSetColumn :: Handle
+           -> Int -- ^ 0-based column to move to
+           -> IO ()
 setColumn :: Int -- ^ 0-based column to move to
           -> IO ()
+setColumnCode :: Int -- ^ 0-based column to move to
+              -> String
 
+setColumn = hSetColumn stdout
+
+
+hSetPosition :: Handle
+             -> Int -- ^ 0-based row to move to
+             -> Int -- ^ 0-based column to move to
+             -> IO ()
 setPosition :: Int -- ^ 0-based row to move to
             -> Int -- ^ 0-based column to move to
             -> IO ()
+setPositionCode :: Int -- ^ 0-based row to move to
+                -> Int -- ^ 0-based column to move to
+                -> String
 
+setPosition = hSetPosition stdout
+
+
+hClearFromCursorToScreenEnd, hClearFromCursorToScreenBeginning, hClearScreen :: Handle
+                                                                             -> IO ()
 clearFromCursorToScreenEnd, clearFromCursorToScreenBeginning, clearScreen :: IO ()
+clearFromCursorToScreenEndCode, clearFromCursorToScreenBeginningCode, clearScreenCode :: String
 
+clearFromCursorToScreenEnd = hClearFromCursorToScreenEnd stdout
+clearFromCursorToScreenBeginning = hClearFromCursorToScreenBeginning stdout
+clearScreen = hClearScreen stdout
+
+
+hClearFromCursorToLineEnd, hClearFromCursorToLineBeginning, hClearLine :: Handle
+                                                                       -> IO ()
 clearFromCursorToLineEnd, clearFromCursorToLineBeginning, clearLine :: IO ()
+clearFromCursorToLineEndCode, clearFromCursorToLineBeginningCode, clearLineCode :: String
 
+clearFromCursorToLineEnd = hClearFromCursorToLineEnd stdout
+clearFromCursorToLineBeginning = hClearFromCursorToLineBeginning stdout
+clearLine = hClearLine stdout
+
+
 -- | Scroll the displayed information up or down the terminal: not widely supported
+hScrollPageUp, hScrollPageDown :: Handle
+                               -> Int -- ^ Number of lines to scroll by
+                               -> IO ()
+-- | Scroll the displayed information up or down the terminal: not widely supported
 scrollPageUp, scrollPageDown :: Int -- ^ Number of lines to scroll by
                              -> IO ()
+-- | Scroll the displayed information up or down the terminal: not widely supported
+scrollPageUpCode, scrollPageDownCode :: Int -- ^ Number of lines to scroll by
+                                     -> String
 
-setSGR :: ANSISGR -> IO ()
+scrollPageUp = hScrollPageUp stdout
+scrollPageDown = hScrollPageDown stdout
 
+
+-- | Set the Select Graphic Rendition mode
+hSetSGR :: Handle
+        -> ANSISGR -- ^ Mode: this is applied to the current console SGR mode
+        -> IO ()
+-- | Set the Select Graphic Rendition mode
+setSGR :: ANSISGR -- ^ Mode: this is applied to the current console SGR mode
+       -> IO ()
+-- | Set the Select Graphic Rendition mode
+setSGRCode :: ANSISGR -- ^ Mode: this is applied to the current console SGR mode
+           -> String
+
+setSGR = hSetSGR stdout
+
+
+hHideCursor, hShowCursor :: Handle
+                         -> IO ()
 hideCursor, showCursor :: IO ()
+hideCursorCode, showCursorCode :: String
+
+hideCursor = hHideCursor stdout
+showCursor = hShowCursor stdout
diff --git a/includes/Exports-Include.hs b/includes/Exports-Include.hs
--- a/includes/Exports-Include.hs
+++ b/includes/Exports-Include.hs
@@ -1,19 +1,45 @@
+-- * Basic data types
 module System.Console.ANSI.Common,
 
+-- * Cursor movement by character
 cursorUp, cursorDown, cursorForward, cursorBackward,
+hCursorUp, hCursorDown, hCursorForward, hCursorBackward,
+cursorUpCode, cursorDownCode, cursorForwardCode, cursorBackwardCode,
 
+-- * Cursor movement by line
 nextLine, previousLine,
+hNextLine, hPreviousLine,
+nextLineCode, previousLineCode,
 
+-- * Directly changing cursor position
 setColumn,
+hSetColumn,
+setColumnCode,
 
 setPosition,
+hSetPosition,
+setPositionCode,
 
+-- * Clearing parts of the screen
 clearFromCursorToScreenEnd, clearFromCursorToScreenBeginning, clearScreen,
+hClearFromCursorToScreenEnd, hClearFromCursorToScreenBeginning, hClearScreen,
+clearFromCursorToScreenEndCode, clearFromCursorToScreenBeginningCode, clearScreenCode,
 
 clearFromCursorToLineEnd, clearFromCursorToLineBeginning, clearLine,
+hClearFromCursorToLineEnd, hClearFromCursorToLineBeginning, hClearLine,
+clearFromCursorToLineEndCode, clearFromCursorToLineBeginningCode, clearLineCode,
 
+-- * Scrolling the screen
 scrollPageUp, scrollPageDown,
+hScrollPageUp, hScrollPageDown,
+scrollPageUpCode, scrollPageDownCode,
 
+-- * Select Graphic Rendition mode: colors and other whizzy stuff
 setSGR,
+hSetSGR,
+setSGRCode,
 
-hideCursor, showCursor
+-- * Cursor visibilty changes
+hideCursor, showCursor,
+hHideCursor, hShowCursor,
+hideCursorCode, showCursorCode
