diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,70 +1,78 @@
-Changes
-=======
-
-Version 0.8
------------
-
-* Make the fields of `SGR` strict
-* Make compatible with GHC 8.2.2
-* Improve the error message on Windows when not ANSI-capable or ConHost
-* Recognise Appveyor build environment as ANSI-enabled
-
-Version 0.7.1.1
----------------
-
-`getReportedCursorPosition`: don't let the cursor reporting code be echo'd
-
-Version 0.7.1
--------------
-
-* Allow saving, restoring, and querying the current cursor position
-* Fix a couple of issues with the Reset emulation on Windows
-
-Version 0.7
------------
-
-Add 24-bit RGB color support
-
-Version 0.6.3.1
----------------
-
-Fix Windows + ghc 7.8 compatibility
-
-Version 0.6.3
--------------
-
-* Add ANSI support for Windows
-* Add compatibility with Win32-2.5.0.0 and above
-
-Version 0.6.2.3
----------------
-
-Add an example to the haddocks
-
-Version 0.6.2.2
----------------
-
-Fix a GHC 7.10 warning
-
-Version 0.6.2.1
----------------
-
-Restore compatibility with GHC 7.4 and older
-
-Version 0.6.2
--------------
-
-* Add `hSupportsANSI`
-* Drop support for `base < 4`
-
-Version 0.6.1.1
----------------
-
-Fix to build with GHC 7.8 on Windows
-
-Version 0.6.1
--------------
-
-* `BoldIntensity` no longer changes background color on Windows
-* `setSGR []` was not equivalent to `setSGR [Reset]` on Windows, even though it
-  should be according to the documentation. This is now fixed.
+Changes
+=======
+
+Version 0.8.0.1
+---------------
+
+* On Windows, if the standard output channel is valid but not a ConHost
+  terminal, assume it is ANSI-enabled rather than failing
+* On Windows, output the improved error message to the standard error channel
+  rather than the standard output channel
+
+Version 0.8
+-----------
+
+* Make the fields of `SGR` strict
+* Make compatible with GHC 8.2.2
+* Improve the error message on Windows when not ANSI-capable or ConHost
+* Recognise Appveyor build environment as ANSI-enabled
+
+Version 0.7.1.1
+---------------
+
+`getReportedCursorPosition`: don't let the cursor reporting code be echo'd
+
+Version 0.7.1
+-------------
+
+* Allow saving, restoring, and querying the current cursor position
+* Fix a couple of issues with the Reset emulation on Windows
+
+Version 0.7
+-----------
+
+Add 24-bit RGB color support
+
+Version 0.6.3.1
+---------------
+
+Fix Windows + ghc 7.8 compatibility
+
+Version 0.6.3
+-------------
+
+* Add ANSI support for Windows
+* Add compatibility with Win32-2.5.0.0 and above
+
+Version 0.6.2.3
+---------------
+
+Add an example to the haddocks
+
+Version 0.6.2.2
+---------------
+
+Fix a GHC 7.10 warning
+
+Version 0.6.2.1
+---------------
+
+Restore compatibility with GHC 7.4 and older
+
+Version 0.6.2
+-------------
+
+* Add `hSupportsANSI`
+* Drop support for `base < 4`
+
+Version 0.6.1.1
+---------------
+
+Fix to build with GHC 7.8 on Windows
+
+Version 0.6.1
+-------------
+
+* `BoldIntensity` no longer changes background color on Windows
+* `setSGR []` was not equivalent to `setSGR [Reset]` on Windows, even though it
+  should be according to the documentation. This is now fixed.
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,22 +1,22 @@
-Copyright (c) 2008, Maximilian Bolingbroke
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, are permitted
-provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright notice, this list of
-      conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright notice, this list of
-      conditions and the following disclaimer in the documentation and/or other materials
-      provided with the distribution.
-    * Neither the name of Maximilian Bolingbroke nor the names of other contributors may be used to
-      endorse or promote products derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
-IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+Copyright (c) 2008, Maximilian Bolingbroke
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted
+provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, this list of
+      conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice, this list of
+      conditions and the following disclaimer in the documentation and/or other materials
+      provided with the distribution.
+    * Neither the name of Maximilian Bolingbroke nor the names of other contributors may be used to
+      endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,88 +1,88 @@
-ansi-terminal
-=============
-
-Haskell ANSI Terminal Package For Windows, OS X and Linux
-
-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
--   Changing the console title (though this is not strictly part of
-    ANSI, it is widely supported in Unix)
-
-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.
-
-Not all of the ANSI escape codes are provided by this module, but most
-(if not all) of the popular and well supported ones are. For a full
-list, have a look at the [current version of the
-API](http://github.com/feuerbach/ansi-terminal/tree/master/includes/Common-Include.hs).
-Each supported escape code or family of codes has a corresponding
-function that comes in three variants:
-
--   A straight `IO` variant that doesn't take a `Handle` and just
-    applies the ANSI escape code to the terminal attached to stdout
--   An `IO` variant similar to above, but which takes a `Handle` to
-    which the ANSI escape should be applied
--   A `String` variant that returns a literal string that should be
-    included to get the effect of the code. This is the only one of the
-    three API variants that only works on Unix-like operating systems:
-    on Windows these strings will always be blank!
-
-Example
--------
-
-A full example is
-[available](http://github.com/feuerbach/ansi-terminal/tree/master/System/Console/ANSI/Example.hs),
-but for a taste of how the library works try the following code:
-
-``` haskell
-import System.Console.ANSI
-
-main = do
-    setCursorPosition 5 0
-    setTitle "ANSI Terminal Short Example"
-
-    setSGR [ SetConsoleIntensity BoldIntensity
-           , SetColor Foreground Vivid Red
-           ]
-    putStr "Hello"
-
-    setSGR [ SetConsoleIntensity NormalIntensity
-           , SetColor Foreground Vivid White
-           , SetColor Background Dull Blue
-           ]
-    putStrLn "World!"
-```
-
-![](https://raw.githubusercontent.com/feuerbach/ansi-terminal/master/example.png)
-
-Documentation
--------------
-
-Haddock documentation is [available at
-Hackage](http://hackage.haskell.org/packages/archive/ansi-terminal/latest/doc/html/System-Console-ANSI.html).
-
-Credits
--------
-
-The library is originally written by [Max Bolingbroke](https://github.com/batterseapower)
-
-Maintainers
------------
-
-[Roman Cheplyaka](https://github.com/feuerbach) is the primary maintainer.
-
-[Oliver Charles](https://github.com/ocharles) is the backup maintainer. Please
-get in touch with him if the primary maintainer cannot be reached.
+ansi-terminal
+=============
+
+Haskell ANSI Terminal Package For Windows, OS X and Linux
+
+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
+-   Changing the console title (though this is not strictly part of
+    ANSI, it is widely supported in Unix)
+
+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.
+
+Not all of the ANSI escape codes are provided by this module, but most
+(if not all) of the popular and well supported ones are. For a full
+list, have a look at the [current version of the
+API](http://github.com/feuerbach/ansi-terminal/tree/master/includes/Common-Include.hs).
+Each supported escape code or family of codes has a corresponding
+function that comes in three variants:
+
+-   A straight `IO` variant that doesn't take a `Handle` and just
+    applies the ANSI escape code to the terminal attached to stdout
+-   An `IO` variant similar to above, but which takes a `Handle` to
+    which the ANSI escape should be applied
+-   A `String` variant that returns a literal string that should be
+    included to get the effect of the code. This is the only one of the
+    three API variants that only works on Unix-like operating systems:
+    on Windows these strings will always be blank!
+
+Example
+-------
+
+A full example is
+[available](http://github.com/feuerbach/ansi-terminal/tree/master/System/Console/ANSI/Example.hs),
+but for a taste of how the library works try the following code:
+
+``` haskell
+import System.Console.ANSI
+
+main = do
+    setCursorPosition 5 0
+    setTitle "ANSI Terminal Short Example"
+
+    setSGR [ SetConsoleIntensity BoldIntensity
+           , SetColor Foreground Vivid Red
+           ]
+    putStr "Hello"
+
+    setSGR [ SetConsoleIntensity NormalIntensity
+           , SetColor Foreground Vivid White
+           , SetColor Background Dull Blue
+           ]
+    putStrLn "World!"
+```
+
+![](https://raw.githubusercontent.com/feuerbach/ansi-terminal/master/example.png)
+
+Documentation
+-------------
+
+Haddock documentation is [available at
+Hackage](http://hackage.haskell.org/packages/archive/ansi-terminal/latest/doc/html/System-Console-ANSI.html).
+
+Credits
+-------
+
+The library is originally written by [Max Bolingbroke](https://github.com/batterseapower)
+
+Maintainers
+-----------
+
+[Mike Pilgrem](https://github.com/mpilgrem) and [Roman Cheplyaka](https://github.com/feuerbach) are the primary maintainers.
+
+[Oliver Charles](https://github.com/ocharles) is the backup maintainer. Please
+get in touch with him if the primary maintainers cannot be reached.
diff --git a/Setup.lhs b/Setup.lhs
--- a/Setup.lhs
+++ b/Setup.lhs
@@ -1,4 +1,4 @@
-#! /usr/bin/env runhaskell
-
-> import Distribution.Simple
+#! /usr/bin/env runhaskell
+
+> import Distribution.Simple
 > main = defaultMain
diff --git a/System/Console/ANSI.hs b/System/Console/ANSI.hs
--- a/System/Console/ANSI.hs
+++ b/System/Console/ANSI.hs
@@ -1,78 +1,78 @@
--- | Provides ANSI terminal support for ANSI terminal software running on a
--- Unix-like operating system or on a Windows operating system (where supported)
--- or on other Windows operating systems where the terminal in use is not
--- ANSI-enabled.
---
--- 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 you 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. The use of
---    these codes is generally discouraged because they will not work on Windows
---    operating systems where the terminal in use is not ANSI-enabled (such as
---    those before Windows 10 Threshold 2). On versions of Windows where the
---    terminal in use is not ANSI-enabled, 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 an operating system that is Unix-like or is a version of
---    Windows where the terminal in use is ANSI-enabled.
---
--- Example:
---
--- > -- Set colors and write some text in those colors.
--- > sgrExample :: IO ()
--- > sgrExample = do
--- >     setSGR [SetColor Foreground Vivid Red]
--- >     setSGR [SetColor Background Vivid Blue]
--- >     putStr "Red-On-Blue"
--- >     setSGR [Reset]
--- >     putStr "White-On-Black"
---
--- For many more examples, see the project's extensive
--- <https://raw.githubusercontent.com/feuerbach/ansi-terminal/master/System/Console/ANSI/Example.hs Example.hs> file.
-#if defined(WINDOWS)
-module System.Console.ANSI
-  (
-    module System.Console.ANSI.Windows
-  ) where
-
-import System.Console.ANSI.Windows
-
-#elif defined(UNIX)
-
-module System.Console.ANSI
-  (
-    module System.Console.ANSI.Unix
-  ) where
-
-import System.Console.ANSI.Unix
-
-#else
-
-#error Unsupported platform for the ansi-terminal package
-
-#endif
+-- | Provides ANSI terminal support for ANSI terminal software running on a
+-- Unix-like operating system or on a Windows operating system (where supported)
+-- or on other Windows operating systems where the terminal in use is not
+-- ANSI-enabled.
+--
+-- 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 you 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. The use of
+--    these codes is generally discouraged because they will not work on Windows
+--    operating systems where the terminal in use is not ANSI-enabled (such as
+--    those before Windows 10 Threshold 2). On versions of Windows where the
+--    terminal in use is not ANSI-enabled, 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 an operating system that is Unix-like or is a version of
+--    Windows where the terminal in use is ANSI-enabled.
+--
+-- Example:
+--
+-- > -- Set colors and write some text in those colors.
+-- > sgrExample :: IO ()
+-- > sgrExample = do
+-- >     setSGR [SetColor Foreground Vivid Red]
+-- >     setSGR [SetColor Background Vivid Blue]
+-- >     putStr "Red-On-Blue"
+-- >     setSGR [Reset]
+-- >     putStr "White-On-Black"
+--
+-- For many more examples, see the project's extensive
+-- <https://raw.githubusercontent.com/feuerbach/ansi-terminal/master/System/Console/ANSI/Example.hs Example.hs> file.
+#if defined(WINDOWS)
+module System.Console.ANSI
+  (
+    module System.Console.ANSI.Windows
+  ) where
+
+import System.Console.ANSI.Windows
+
+#elif defined(UNIX)
+
+module System.Console.ANSI
+  (
+    module System.Console.ANSI.Unix
+  ) where
+
+import System.Console.ANSI.Unix
+
+#else
+
+#error Unsupported platform for the ansi-terminal package
+
+#endif
diff --git a/System/Console/ANSI/Codes.hs b/System/Console/ANSI/Codes.hs
--- a/System/Console/ANSI/Codes.hs
+++ b/System/Console/ANSI/Codes.hs
@@ -1,188 +1,188 @@
--- | This module exports functions that return 'String' values containing codes
--- in accordance with: (1) standard ECMA-48 Control Functions for Coded
--- Character Sets (5th edition, 1991); or (2) in the case of 'saveCursorCode',
--- 'restoreCursorCode', 'reportCursorPositionCode' and 'setTitleCode', the XTerm
--- control sequence.
---
--- The reference used for the codes in this module was
--- <http://en.wikipedia.org/wiki/ANSI_escape_sequences>.
---
--- The module "System.Console.ANSI" exports functions with the same names as
--- those in this module. On some versions of Windows, the terminal in use may
--- not be ANSI-capable. When that is the case, the same-named functions exported
--- by module "System.Console.ANSI" return \"\", for the reasons set out in the
--- documentation of that module.
---
--- Consequently, if module "System.Console.ANSI" is also imported, this module
--- is intended to be imported qualified, to avoid name clashes with those
--- functions. For example:
---
--- > import qualified System.Console.ANSI.Codes as ANSI
---
-module System.Console.ANSI.Codes
-  (
-    -- * Basic data types
-    module System.Console.ANSI.Types
-
-    -- * Cursor movement by character
-  , cursorUpCode, cursorDownCode, cursorForwardCode, cursorBackwardCode
-
-    -- * Cursor movement by line
-  , cursorUpLineCode, cursorDownLineCode
-
-    -- * Directly changing cursor position
-  , setCursorColumnCode, setCursorPositionCode
-
-    -- * Saving, restoring and reporting cursor position
-  , saveCursorCode, restoreCursorCode, reportCursorPositionCode
-
-    -- * Clearing parts of the screen
-  , clearFromCursorToScreenEndCode, clearFromCursorToScreenBeginningCode
-  , clearScreenCode, clearFromCursorToLineEndCode
-  , clearFromCursorToLineBeginningCode, clearLineCode
-
-    -- * Scrolling the screen
-  , scrollPageUpCode, scrollPageDownCode
-
-    -- * Select Graphic Rendition mode: colors and other whizzy stuff
-  , setSGRCode
-
-    -- * Cursor visibilty changes
-  , hideCursorCode, showCursorCode
-
-    -- * Changing the title
-    -- | Thanks to Brandon S. Allbery and Curt Sampson for pointing me in the
-    -- right direction on xterm title setting on haskell-cafe. The "0"
-    -- signifies that both the title and "icon" text should be set: i.e. the
-    -- text for the window in the Start bar (or similar) as well as that in
-    -- the actual window title. This is chosen for consistent behaviour
-    -- between Unixes and Windows.
-  , setTitleCode
-
-    -- * Utilities
-  , colorToCode, csi, sgrToCode
-  ) where
-
-import Data.List (intersperse)
-
-import Data.Colour.SRGB (toSRGB24, RGB (..))
-
-import System.Console.ANSI.Types
-
--- | 'csi' @parameters controlFunction@, where @parameters@ is a list of 'Int',
--- returns the control sequence comprising the control function CONTROL
--- SEQUENCE INTRODUCER (CSI) followed by the parameter(s) (separated by \';\')
--- and ending with the @controlFunction@ character(s) that identifies the
--- control function.
-csi :: [Int]  -- ^ List of parameters for the control sequence
-    -> String -- ^ Character(s) that identify the control function
-    -> String
-csi args code = "\ESC[" ++ concat (intersperse ";" (map show args)) ++ code
-
--- | 'colorToCode' @color@ returns the 0-based index of the color (one of the
--- eight colors in the standard).
-colorToCode :: Color -> Int
-colorToCode color = case color of
-  Black   -> 0
-  Red     -> 1
-  Green   -> 2
-  Yellow  -> 3
-  Blue    -> 4
-  Magenta -> 5
-  Cyan    -> 6
-  White   -> 7
-
--- | 'sgrToCode' @sgr@ returns the parameter of the SELECT GRAPHIC RENDITION
--- (SGR) aspect identified by @sgr@.
-sgrToCode :: SGR -- ^ The SGR aspect
-          -> [Int]
-sgrToCode sgr = case sgr of
-  Reset -> [0]
-  SetConsoleIntensity intensity -> case intensity of
-    BoldIntensity   -> [1]
-    FaintIntensity  -> [2]
-    NormalIntensity -> [22]
-  SetItalicized True  -> [3]
-  SetItalicized False -> [23]
-  SetUnderlining underlining -> case underlining of
-    SingleUnderline -> [4]
-    DoubleUnderline -> [21]
-    NoUnderline     -> [24]
-  SetBlinkSpeed blink_speed -> case blink_speed of
-    SlowBlink   -> [5]
-    RapidBlink  -> [6]
-    NoBlink     -> [25]
-  SetVisible False -> [8]
-  SetVisible True  -> [28]
-  SetSwapForegroundBackground True  -> [7]
-  SetSwapForegroundBackground False -> [27]
-  SetColor Foreground Dull color  -> [30 + colorToCode color]
-  SetColor Foreground Vivid color -> [90 + colorToCode color]
-  SetColor Background Dull color  -> [40 + colorToCode color]
-  SetColor Background Vivid color -> [100 + colorToCode color]
-  SetRGBColor Foreground color -> [38, 2] ++ toRGB color
-  SetRGBColor Background color -> [48, 2] ++ toRGB color
- where
-  toRGB color = let RGB r g b = toSRGB24 color
-                in  map fromIntegral [r, g, b]
-
-cursorUpCode, cursorDownCode, cursorForwardCode, cursorBackwardCode
-  :: Int -- ^ Number of lines or characters to move
-  -> String
-cursorUpCode n = csi [n] "A"
-cursorDownCode n = csi [n] "B"
-cursorForwardCode n = csi [n] "C"
-cursorBackwardCode n = csi [n] "D"
-
-cursorDownLineCode, cursorUpLineCode :: Int -- ^ Number of lines to move
-                                     -> String
-cursorDownLineCode n = csi [n] "E"
-cursorUpLineCode n = csi [n] "F"
-
-setCursorColumnCode :: Int -- ^ 0-based column to move to
-                    -> String
-setCursorColumnCode n = csi [n + 1] "G"
-
-setCursorPositionCode :: Int -- ^ 0-based row to move to
-                      -> Int -- ^ 0-based column to move to
-                      -> String
-setCursorPositionCode n m = csi [n + 1, m + 1] "H"
-
-saveCursorCode, restoreCursorCode, reportCursorPositionCode :: String
-saveCursorCode = "\ESC7"
-restoreCursorCode = "\ESC8"
-reportCursorPositionCode = csi [] "6n"
-
-clearFromCursorToScreenEndCode, clearFromCursorToScreenBeginningCode,
-  clearScreenCode :: String
-clearFromCursorToLineEndCode, clearFromCursorToLineBeginningCode,
-  clearLineCode :: String
-
-clearFromCursorToScreenEndCode = csi [0] "J"
-clearFromCursorToScreenBeginningCode = csi [1] "J"
-clearScreenCode = csi [2] "J"
-clearFromCursorToLineEndCode = csi [0] "K"
-clearFromCursorToLineBeginningCode = csi [1] "K"
-clearLineCode = csi [2] "K"
-
-scrollPageUpCode, scrollPageDownCode :: Int -- ^ Number of lines to scroll by
-                                     -> String
-scrollPageUpCode n = csi [n] "S"
-scrollPageDownCode n = csi [n] "T"
-
-setSGRCode :: [SGR] -- ^ Commands: these will typically be applied on top of the
-                    -- current console SGR mode. An empty list of commands is
-                    -- equivalent to the list @[Reset]@. Commands are applied
-                    -- left to right.
-           -> String
-setSGRCode sgrs = csi (concatMap sgrToCode sgrs) "m"
-
-hideCursorCode, showCursorCode :: String
-hideCursorCode = csi [] "?25l"
-showCursorCode = csi [] "?25h"
-
-
--- | XTerm control sequence to set the Icon Name and Window Title.
-setTitleCode :: String -- ^ New Icon Name and Window Title
-             -> String
-setTitleCode title = "\ESC]0;" ++ filter (/= '\007') title ++ "\007"
+-- | This module exports functions that return 'String' values containing codes
+-- in accordance with: (1) standard ECMA-48 Control Functions for Coded
+-- Character Sets (5th edition, 1991); or (2) in the case of 'saveCursorCode',
+-- 'restoreCursorCode', 'reportCursorPositionCode' and 'setTitleCode', the XTerm
+-- control sequence.
+--
+-- The reference used for the codes in this module was
+-- <http://en.wikipedia.org/wiki/ANSI_escape_sequences>.
+--
+-- The module "System.Console.ANSI" exports functions with the same names as
+-- those in this module. On some versions of Windows, the terminal in use may
+-- not be ANSI-capable. When that is the case, the same-named functions exported
+-- by module "System.Console.ANSI" return \"\", for the reasons set out in the
+-- documentation of that module.
+--
+-- Consequently, if module "System.Console.ANSI" is also imported, this module
+-- is intended to be imported qualified, to avoid name clashes with those
+-- functions. For example:
+--
+-- > import qualified System.Console.ANSI.Codes as ANSI
+--
+module System.Console.ANSI.Codes
+  (
+    -- * Basic data types
+    module System.Console.ANSI.Types
+
+    -- * Cursor movement by character
+  , cursorUpCode, cursorDownCode, cursorForwardCode, cursorBackwardCode
+
+    -- * Cursor movement by line
+  , cursorUpLineCode, cursorDownLineCode
+
+    -- * Directly changing cursor position
+  , setCursorColumnCode, setCursorPositionCode
+
+    -- * Saving, restoring and reporting cursor position
+  , saveCursorCode, restoreCursorCode, reportCursorPositionCode
+
+    -- * Clearing parts of the screen
+  , clearFromCursorToScreenEndCode, clearFromCursorToScreenBeginningCode
+  , clearScreenCode, clearFromCursorToLineEndCode
+  , clearFromCursorToLineBeginningCode, clearLineCode
+
+    -- * Scrolling the screen
+  , scrollPageUpCode, scrollPageDownCode
+
+    -- * Select Graphic Rendition mode: colors and other whizzy stuff
+  , setSGRCode
+
+    -- * Cursor visibilty changes
+  , hideCursorCode, showCursorCode
+
+    -- * Changing the title
+    -- | Thanks to Brandon S. Allbery and Curt Sampson for pointing me in the
+    -- right direction on xterm title setting on haskell-cafe. The "0"
+    -- signifies that both the title and "icon" text should be set: i.e. the
+    -- text for the window in the Start bar (or similar) as well as that in
+    -- the actual window title. This is chosen for consistent behaviour
+    -- between Unixes and Windows.
+  , setTitleCode
+
+    -- * Utilities
+  , colorToCode, csi, sgrToCode
+  ) where
+
+import Data.List (intersperse)
+
+import Data.Colour.SRGB (toSRGB24, RGB (..))
+
+import System.Console.ANSI.Types
+
+-- | 'csi' @parameters controlFunction@, where @parameters@ is a list of 'Int',
+-- returns the control sequence comprising the control function CONTROL
+-- SEQUENCE INTRODUCER (CSI) followed by the parameter(s) (separated by \';\')
+-- and ending with the @controlFunction@ character(s) that identifies the
+-- control function.
+csi :: [Int]  -- ^ List of parameters for the control sequence
+    -> String -- ^ Character(s) that identify the control function
+    -> String
+csi args code = "\ESC[" ++ concat (intersperse ";" (map show args)) ++ code
+
+-- | 'colorToCode' @color@ returns the 0-based index of the color (one of the
+-- eight colors in the standard).
+colorToCode :: Color -> Int
+colorToCode color = case color of
+  Black   -> 0
+  Red     -> 1
+  Green   -> 2
+  Yellow  -> 3
+  Blue    -> 4
+  Magenta -> 5
+  Cyan    -> 6
+  White   -> 7
+
+-- | 'sgrToCode' @sgr@ returns the parameter of the SELECT GRAPHIC RENDITION
+-- (SGR) aspect identified by @sgr@.
+sgrToCode :: SGR -- ^ The SGR aspect
+          -> [Int]
+sgrToCode sgr = case sgr of
+  Reset -> [0]
+  SetConsoleIntensity intensity -> case intensity of
+    BoldIntensity   -> [1]
+    FaintIntensity  -> [2]
+    NormalIntensity -> [22]
+  SetItalicized True  -> [3]
+  SetItalicized False -> [23]
+  SetUnderlining underlining -> case underlining of
+    SingleUnderline -> [4]
+    DoubleUnderline -> [21]
+    NoUnderline     -> [24]
+  SetBlinkSpeed blink_speed -> case blink_speed of
+    SlowBlink   -> [5]
+    RapidBlink  -> [6]
+    NoBlink     -> [25]
+  SetVisible False -> [8]
+  SetVisible True  -> [28]
+  SetSwapForegroundBackground True  -> [7]
+  SetSwapForegroundBackground False -> [27]
+  SetColor Foreground Dull color  -> [30 + colorToCode color]
+  SetColor Foreground Vivid color -> [90 + colorToCode color]
+  SetColor Background Dull color  -> [40 + colorToCode color]
+  SetColor Background Vivid color -> [100 + colorToCode color]
+  SetRGBColor Foreground color -> [38, 2] ++ toRGB color
+  SetRGBColor Background color -> [48, 2] ++ toRGB color
+ where
+  toRGB color = let RGB r g b = toSRGB24 color
+                in  map fromIntegral [r, g, b]
+
+cursorUpCode, cursorDownCode, cursorForwardCode, cursorBackwardCode
+  :: Int -- ^ Number of lines or characters to move
+  -> String
+cursorUpCode n = csi [n] "A"
+cursorDownCode n = csi [n] "B"
+cursorForwardCode n = csi [n] "C"
+cursorBackwardCode n = csi [n] "D"
+
+cursorDownLineCode, cursorUpLineCode :: Int -- ^ Number of lines to move
+                                     -> String
+cursorDownLineCode n = csi [n] "E"
+cursorUpLineCode n = csi [n] "F"
+
+setCursorColumnCode :: Int -- ^ 0-based column to move to
+                    -> String
+setCursorColumnCode n = csi [n + 1] "G"
+
+setCursorPositionCode :: Int -- ^ 0-based row to move to
+                      -> Int -- ^ 0-based column to move to
+                      -> String
+setCursorPositionCode n m = csi [n + 1, m + 1] "H"
+
+saveCursorCode, restoreCursorCode, reportCursorPositionCode :: String
+saveCursorCode = "\ESC7"
+restoreCursorCode = "\ESC8"
+reportCursorPositionCode = csi [] "6n"
+
+clearFromCursorToScreenEndCode, clearFromCursorToScreenBeginningCode,
+  clearScreenCode :: String
+clearFromCursorToLineEndCode, clearFromCursorToLineBeginningCode,
+  clearLineCode :: String
+
+clearFromCursorToScreenEndCode = csi [0] "J"
+clearFromCursorToScreenBeginningCode = csi [1] "J"
+clearScreenCode = csi [2] "J"
+clearFromCursorToLineEndCode = csi [0] "K"
+clearFromCursorToLineBeginningCode = csi [1] "K"
+clearLineCode = csi [2] "K"
+
+scrollPageUpCode, scrollPageDownCode :: Int -- ^ Number of lines to scroll by
+                                     -> String
+scrollPageUpCode n = csi [n] "S"
+scrollPageDownCode n = csi [n] "T"
+
+setSGRCode :: [SGR] -- ^ Commands: these will typically be applied on top of the
+                    -- current console SGR mode. An empty list of commands is
+                    -- equivalent to the list @[Reset]@. Commands are applied
+                    -- left to right.
+           -> String
+setSGRCode sgrs = csi (concatMap sgrToCode sgrs) "m"
+
+hideCursorCode, showCursorCode :: String
+hideCursorCode = csi [] "?25l"
+showCursorCode = csi [] "?25h"
+
+
+-- | XTerm control sequence to set the Icon Name and Window Title.
+setTitleCode :: String -- ^ New Icon Name and Window Title
+             -> String
+setTitleCode title = "\ESC]0;" ++ filter (/= '\007') title ++ "\007"
diff --git a/System/Console/ANSI/Example.hs b/System/Console/ANSI/Example.hs
--- a/System/Console/ANSI/Example.hs
+++ b/System/Console/ANSI/Example.hs
@@ -1,315 +1,315 @@
-module Main
-  (
-    main
-  ) where
-
-import Control.Concurrent (threadDelay)
-import Control.Monad (forM_)
-import System.IO (hFlush, stdout)
-
-import System.Console.ANSI
-
-examples :: [IO ()]
-examples = [ cursorMovementExample
-           , lineChangeExample
-           , setCursorPositionExample
-           , saveRestoreCursorExample
-           , clearExample
-           , scrollExample
-           , sgrExample
-           , cursorVisibilityExample
-           , titleExample
-           , getCursorPositionExample
-           ]
-
-main :: IO ()
-main = mapM_ (\example -> resetScreen >> example) examples
-
--- Annex D to Standard ECMA-48 (5th Ed, 1991) identifies that the representation
--- of an erased state is implementation-dependent. There may or may not be a
--- distinction between a character position in the erased state and one imaging
--- SPACE. Consequently, to reset the screen, the default graphic rendition must
--- be selected (setSGR [Reset]) before all character positions are put into the
--- erased state (clearScreen).
-resetScreen :: IO ()
-resetScreen = setSGR [Reset] >> clearScreen >> setCursorPosition 0 0
-
-pause :: IO ()
-pause = do
-  hFlush stdout
-  -- 1 second pause
-  threadDelay 1000000
-
-cursorMovementExample :: IO ()
-cursorMovementExample = do
-  putStrLn "Line One"
-  putStr "Line Two"
-  pause
-  -- Line One
-  -- Line Two
-
-  cursorUp 1
-  putStr " - Extras"
-  pause
-  -- Line One - Extras
-  -- Line Two
-
-  cursorBackward 2
-  putStr "zz"
-  pause
-  -- Line One - Extrzz
-  -- Line Two
-
-  cursorForward 2
-  putStr "- And More"
-  pause
-  -- Line One - Extrzz  - And More
-  -- Line Two
-
-  cursorDown 1
-  putStr "Disconnected"
-  pause
-  -- Line One - Extrzz  - And More
-  -- Line Two                     Disconnected
-
-lineChangeExample :: IO ()
-lineChangeExample = do
-  putStrLn "Line One"
-  putStr "Line Two"
-  pause
-  -- Line One
-  -- Line Two
-
-  cursorUpLine 1
-  putStr "New Line One"
-  pause
-  -- New Line One
-  -- Line Two
-
-  cursorDownLine 1
-  putStr "New Line Two"
-  pause
-  -- New Line One
-  -- New Line Two
-
-setCursorPositionExample :: IO ()
-setCursorPositionExample = do
-  putStrLn "Line One"
-  putStrLn "Line Two"
-  pause
-  -- Line One
-  -- Line Two
-
-  setCursorPosition 0 5
-  putStr "Foo"
-  pause
-  -- Line Foo
-  -- Line Two
-
-  setCursorPosition 1 5
-  putStr "Bar"
-  pause
-  -- Line Foo
-  -- Line Bar
-
-  setCursorColumn 1
-  putStr "oaf"
-  pause
-  -- Line Foo
-  -- Loaf Bar
-
-saveRestoreCursorExample :: IO ()
-saveRestoreCursorExample = do
-  putStr "Start sentence ..."
-  pause
-  -- Start sentence ...
-
-  saveCursor
-  setCursorPosition 2 3
-  putStr "SPLASH!"
-  pause
-  -- Start sentence ...
-  --
-  --    SPLASH!
-
-  restoreCursor
-  putStr " end sentence, uninterrupted."
-  pause
-  -- Start sentence ... end sentence, uninterrupted
-  --
-  --    SPLASH!
-
-clearExample :: IO ()
-clearExample = do
-  putStrLn "Line One"
-  putStrLn "Line Two"
-  pause
-  -- Line One
-  -- Line Two
-
-  setCursorPosition 0 4
-  clearFromCursorToScreenEnd
-  pause
-  -- Line
-
-  resetScreen
-  putStrLn "Line One"
-  putStrLn "Line Two"
-  pause
-  -- Line One
-  -- Line Two
-
-  setCursorPosition 1 4
-  clearFromCursorToScreenBeginning
-  pause
-  --
-  --     Two
-
-  resetScreen
-  putStrLn "Line One"
-  putStrLn "Line Two"
-  pause
-  -- Line One
-  -- Line Two
-
-  setCursorPosition 0 4
-  clearFromCursorToLineEnd
-  pause
-  -- Line
-  -- Line Two
-
-  setCursorPosition 1 4
-  clearFromCursorToLineBeginning
-  pause
-  -- Line
-  --      Two
-
-  clearLine
-  pause
-  -- Line
-
-  clearScreen
-  pause
-  --
-
-scrollExample :: IO ()
-scrollExample = do
-  putStrLn "Line One"
-  putStrLn "Line Two"
-  putStrLn "Line Three"
-  pause
-  -- Line One
-  -- Line Two
-  -- Line Three
-
-  scrollPageDown 2
-  pause
-  --
-  --
-  -- Line One
-  -- Line Two
-  -- Line Three
-
-  scrollPageUp 3
-  pause
-  -- Line Two
-  -- Line Three
-
-sgrExample :: IO ()
-sgrExample = do
-  let colors = enumFromTo minBound maxBound :: [Color]
-  forM_ [Foreground, Background] $ \layer ->  do
-    forM_ [Dull, Vivid] $ \intensity -> do
-      resetScreen
-      forM_ colors $ \color -> do
-        setSGR [Reset]
-        setSGR [SetColor layer intensity color]
-        putStrLn (show color)
-      pause
-  -- All the colors, 4 times in sequence
-
-  let named_styles = [ (SetConsoleIntensity BoldIntensity, "Bold")
-                     , (SetConsoleIntensity FaintIntensity, "Faint")
-                     , (SetConsoleIntensity NormalIntensity, "Normal")
-                     , (SetItalicized True, "Italic")
-                     , (SetItalicized False, "No Italics")
-                     , (SetUnderlining SingleUnderline, "Single Underline")
-                     , (SetUnderlining DoubleUnderline, "Double Underline")
-                     , (SetUnderlining NoUnderline, "No Underline")
-                     , (SetBlinkSpeed SlowBlink, "Slow Blink")
-                     , (SetBlinkSpeed RapidBlink, "Rapid Blink")
-                     , (SetBlinkSpeed NoBlink, "No Blink")
-                     , (SetVisible False, "Conceal")
-                     , (SetVisible True, "Reveal")
-                     ]
-  forM_ named_styles $ \(style, name) -> do
-    resetScreen
-    setSGR [style]
-    putStrLn name
-    pause
-  -- Text describing a style displayed in that style in sequence
-
-  setSGR [SetColor Foreground Vivid Red]
-  setSGR [SetColor Background Vivid Blue]
-
-  clearScreen >> setCursorPosition 0 0
-  setSGR [SetSwapForegroundBackground False]
-  putStr "Red-On-Blue"
-  pause
-  -- Red-On-Blue
-
-  clearScreen >> setCursorPosition 0 0
-  setSGR [SetSwapForegroundBackground True]
-  putStr "Blue-On-Red"
-  pause
-  -- Blue-On-Red
-
-cursorVisibilityExample :: IO ()
-cursorVisibilityExample = do
-  putStr "Cursor Demo"
-  pause
-  -- Cursor Demo|
-
-  hideCursor
-  pause
-  -- Cursor Demo
-
-  showCursor
-  pause
-  -- Cursor Demo|
-
-titleExample :: IO ()
-titleExample = do
-  putStr "Title Demo"
-  pause
-  -- ~/foo/ - ansi-terminal-ex - 83x70
-  ------------------------------------
-  -- Title Demo
-
-  setTitle "Yup, I'm a new title!"
-  pause
-  -- Yup, I'm a new title! - ansi-terminal-ex - 83x70
-  ---------------------------------------------------
-  -- Title Demo
-
-getCursorPositionExample :: IO ()
-getCursorPositionExample = do
-  putStrLn "         11111111112222222222"
-  putStrLn "12345678901234567890123456789"
-  putStr   "Report cursor position here:"
-  pause
-  --          11111111112222222222
-  -- 12345678901234567890123456789
-  -- Report cursor position here:|
-  result <- getCursorPosition
-  putStrLn " (3rd row, 29th column) to stdin, as CSI 3 ; 29 R.\n"
-  case result of
-    Just (row, col) -> putStrLn $ "The cursor was at row number " ++
-      show row ++ " and column number " ++ show col ++ ".\n"
-    Nothing -> putStrLn "Error: unable to get the cursor position\n"
-  pause
-  --          11111111112222222222
-  -- 12345678901234567890123456789
-  -- Report cursor position here: (3rd row, 29th column) to stdin, as CSI 3 ; 29 R.
-  --
-  -- The cursor was at row number 3 and column number 29.
+module Main
+  (
+    main
+  ) where
+
+import Control.Concurrent (threadDelay)
+import Control.Monad (forM_)
+import System.IO (hFlush, stdout)
+
+import System.Console.ANSI
+
+examples :: [IO ()]
+examples = [ cursorMovementExample
+           , lineChangeExample
+           , setCursorPositionExample
+           , saveRestoreCursorExample
+           , clearExample
+           , scrollExample
+           , sgrExample
+           , cursorVisibilityExample
+           , titleExample
+           , getCursorPositionExample
+           ]
+
+main :: IO ()
+main = mapM_ (\example -> resetScreen >> example) examples
+
+-- Annex D to Standard ECMA-48 (5th Ed, 1991) identifies that the representation
+-- of an erased state is implementation-dependent. There may or may not be a
+-- distinction between a character position in the erased state and one imaging
+-- SPACE. Consequently, to reset the screen, the default graphic rendition must
+-- be selected (setSGR [Reset]) before all character positions are put into the
+-- erased state (clearScreen).
+resetScreen :: IO ()
+resetScreen = setSGR [Reset] >> clearScreen >> setCursorPosition 0 0
+
+pause :: IO ()
+pause = do
+  hFlush stdout
+  -- 1 second pause
+  threadDelay 1000000
+
+cursorMovementExample :: IO ()
+cursorMovementExample = do
+  putStrLn "Line One"
+  putStr "Line Two"
+  pause
+  -- Line One
+  -- Line Two
+
+  cursorUp 1
+  putStr " - Extras"
+  pause
+  -- Line One - Extras
+  -- Line Two
+
+  cursorBackward 2
+  putStr "zz"
+  pause
+  -- Line One - Extrzz
+  -- Line Two
+
+  cursorForward 2
+  putStr "- And More"
+  pause
+  -- Line One - Extrzz  - And More
+  -- Line Two
+
+  cursorDown 1
+  putStr "Disconnected"
+  pause
+  -- Line One - Extrzz  - And More
+  -- Line Two                     Disconnected
+
+lineChangeExample :: IO ()
+lineChangeExample = do
+  putStrLn "Line One"
+  putStr "Line Two"
+  pause
+  -- Line One
+  -- Line Two
+
+  cursorUpLine 1
+  putStr "New Line One"
+  pause
+  -- New Line One
+  -- Line Two
+
+  cursorDownLine 1
+  putStr "New Line Two"
+  pause
+  -- New Line One
+  -- New Line Two
+
+setCursorPositionExample :: IO ()
+setCursorPositionExample = do
+  putStrLn "Line One"
+  putStrLn "Line Two"
+  pause
+  -- Line One
+  -- Line Two
+
+  setCursorPosition 0 5
+  putStr "Foo"
+  pause
+  -- Line Foo
+  -- Line Two
+
+  setCursorPosition 1 5
+  putStr "Bar"
+  pause
+  -- Line Foo
+  -- Line Bar
+
+  setCursorColumn 1
+  putStr "oaf"
+  pause
+  -- Line Foo
+  -- Loaf Bar
+
+saveRestoreCursorExample :: IO ()
+saveRestoreCursorExample = do
+  putStr "Start sentence ..."
+  pause
+  -- Start sentence ...
+
+  saveCursor
+  setCursorPosition 2 3
+  putStr "SPLASH!"
+  pause
+  -- Start sentence ...
+  --
+  --    SPLASH!
+
+  restoreCursor
+  putStr " end sentence, uninterrupted."
+  pause
+  -- Start sentence ... end sentence, uninterrupted
+  --
+  --    SPLASH!
+
+clearExample :: IO ()
+clearExample = do
+  putStrLn "Line One"
+  putStrLn "Line Two"
+  pause
+  -- Line One
+  -- Line Two
+
+  setCursorPosition 0 4
+  clearFromCursorToScreenEnd
+  pause
+  -- Line
+
+  resetScreen
+  putStrLn "Line One"
+  putStrLn "Line Two"
+  pause
+  -- Line One
+  -- Line Two
+
+  setCursorPosition 1 4
+  clearFromCursorToScreenBeginning
+  pause
+  --
+  --     Two
+
+  resetScreen
+  putStrLn "Line One"
+  putStrLn "Line Two"
+  pause
+  -- Line One
+  -- Line Two
+
+  setCursorPosition 0 4
+  clearFromCursorToLineEnd
+  pause
+  -- Line
+  -- Line Two
+
+  setCursorPosition 1 4
+  clearFromCursorToLineBeginning
+  pause
+  -- Line
+  --      Two
+
+  clearLine
+  pause
+  -- Line
+
+  clearScreen
+  pause
+  --
+
+scrollExample :: IO ()
+scrollExample = do
+  putStrLn "Line One"
+  putStrLn "Line Two"
+  putStrLn "Line Three"
+  pause
+  -- Line One
+  -- Line Two
+  -- Line Three
+
+  scrollPageDown 2
+  pause
+  --
+  --
+  -- Line One
+  -- Line Two
+  -- Line Three
+
+  scrollPageUp 3
+  pause
+  -- Line Two
+  -- Line Three
+
+sgrExample :: IO ()
+sgrExample = do
+  let colors = enumFromTo minBound maxBound :: [Color]
+  forM_ [Foreground, Background] $ \layer ->  do
+    forM_ [Dull, Vivid] $ \intensity -> do
+      resetScreen
+      forM_ colors $ \color -> do
+        setSGR [Reset]
+        setSGR [SetColor layer intensity color]
+        putStrLn (show color)
+      pause
+  -- All the colors, 4 times in sequence
+
+  let named_styles = [ (SetConsoleIntensity BoldIntensity, "Bold")
+                     , (SetConsoleIntensity FaintIntensity, "Faint")
+                     , (SetConsoleIntensity NormalIntensity, "Normal")
+                     , (SetItalicized True, "Italic")
+                     , (SetItalicized False, "No Italics")
+                     , (SetUnderlining SingleUnderline, "Single Underline")
+                     , (SetUnderlining DoubleUnderline, "Double Underline")
+                     , (SetUnderlining NoUnderline, "No Underline")
+                     , (SetBlinkSpeed SlowBlink, "Slow Blink")
+                     , (SetBlinkSpeed RapidBlink, "Rapid Blink")
+                     , (SetBlinkSpeed NoBlink, "No Blink")
+                     , (SetVisible False, "Conceal")
+                     , (SetVisible True, "Reveal")
+                     ]
+  forM_ named_styles $ \(style, name) -> do
+    resetScreen
+    setSGR [style]
+    putStrLn name
+    pause
+  -- Text describing a style displayed in that style in sequence
+
+  setSGR [SetColor Foreground Vivid Red]
+  setSGR [SetColor Background Vivid Blue]
+
+  clearScreen >> setCursorPosition 0 0
+  setSGR [SetSwapForegroundBackground False]
+  putStr "Red-On-Blue"
+  pause
+  -- Red-On-Blue
+
+  clearScreen >> setCursorPosition 0 0
+  setSGR [SetSwapForegroundBackground True]
+  putStr "Blue-On-Red"
+  pause
+  -- Blue-On-Red
+
+cursorVisibilityExample :: IO ()
+cursorVisibilityExample = do
+  putStr "Cursor Demo"
+  pause
+  -- Cursor Demo|
+
+  hideCursor
+  pause
+  -- Cursor Demo
+
+  showCursor
+  pause
+  -- Cursor Demo|
+
+titleExample :: IO ()
+titleExample = do
+  putStr "Title Demo"
+  pause
+  -- ~/foo/ - ansi-terminal-ex - 83x70
+  ------------------------------------
+  -- Title Demo
+
+  setTitle "Yup, I'm a new title!"
+  pause
+  -- Yup, I'm a new title! - ansi-terminal-ex - 83x70
+  ---------------------------------------------------
+  -- Title Demo
+
+getCursorPositionExample :: IO ()
+getCursorPositionExample = do
+  putStrLn "         11111111112222222222"
+  putStrLn "12345678901234567890123456789"
+  putStr   "Report cursor position here:"
+  pause
+  --          11111111112222222222
+  -- 12345678901234567890123456789
+  -- Report cursor position here:|
+  result <- getCursorPosition
+  putStrLn " (3rd row, 29th column) to stdin, as CSI 3 ; 29 R.\n"
+  case result of
+    Just (row, col) -> putStrLn $ "The cursor was at row number " ++
+      show row ++ " and column number " ++ show col ++ ".\n"
+    Nothing -> putStrLn "Error: unable to get the cursor position\n"
+  pause
+  --          11111111112222222222
+  -- 12345678901234567890123456789
+  -- Report cursor position here: (3rd row, 29th column) to stdin, as CSI 3 ; 29 R.
+  --
+  -- The cursor was at row number 3 and column number 29.
diff --git a/System/Console/ANSI/Types.hs b/System/Console/ANSI/Types.hs
--- a/System/Console/ANSI/Types.hs
+++ b/System/Console/ANSI/Types.hs
@@ -1,71 +1,71 @@
--- | Types used to represent SELECT GRAPHIC RENDITION (SGR) aspects.
-module System.Console.ANSI.Types
-  (
-    SGR (..)
-  , ConsoleLayer (..)
-  , Color (..)
-  , ColorIntensity (..)
-  , ConsoleIntensity (..)
-  , Underlining (..)
-  , BlinkSpeed (..)
-  ) where
-
-import Data.Ix (Ix)
-
-import Data.Colour (Colour)
-
--- | ANSI colors: come in various intensities, which are controlled by
--- 'ColorIntensity'
-data Color = Black
-           | Red
-           | Green
-           | Yellow
-           | Blue
-           | Magenta
-           | Cyan
-           | White
-           deriving (Eq, Ord, Bounded, Enum, Show, Read, Ix)
-
--- | ANSI colors come in two intensities
-data ColorIntensity = Dull
-                    | Vivid
-                    deriving (Eq, Ord, Bounded, Enum, Show, Read, Ix)
-
--- | ANSI colors can be set on two different layers
-data ConsoleLayer = Foreground
-                  | Background
-                  deriving (Eq, Ord, Bounded, Enum, Show, Read, Ix)
-
--- | ANSI blink speeds: values other than 'NoBlink' are not widely supported
-data BlinkSpeed = SlowBlink -- ^ Less than 150 blinks per minute
-                | RapidBlink -- ^ More than 150 blinks per minute
-                | NoBlink
-                deriving (Eq, Ord, Bounded, Enum, Show, Read, Ix)
-
--- | ANSI text underlining
-data Underlining = SingleUnderline
-                 | DoubleUnderline -- ^ Not widely supported
-                 | NoUnderline
-                 deriving (Eq, Ord, Bounded ,Enum, Show, Read, Ix)
-
--- | ANSI general console intensity: usually treated as setting the font style
--- (e.g. 'BoldIntensity' causes text to be bold)
-data ConsoleIntensity = BoldIntensity
-                      | FaintIntensity -- ^ Not widely supported: sometimes
-                                       -- treated as concealing text
-                      | NormalIntensity
-                      deriving (Eq, Ord, Bounded, Enum, Show, Read, Ix)
-
--- | ANSI Select Graphic Rendition command
-data SGR = Reset
-         | SetConsoleIntensity !ConsoleIntensity
-         | SetItalicized !Bool -- ^ Not widely supported: sometimes treated as
-                               -- swapping foreground and background
-         | SetUnderlining !Underlining
-         | SetBlinkSpeed !BlinkSpeed
-         | SetVisible !Bool -- ^ Not widely supported
-         | SetSwapForegroundBackground !Bool
-         | SetColor !ConsoleLayer !ColorIntensity !Color
-         | SetRGBColor !ConsoleLayer !(Colour Float) -- ^ Supported from Windows 10
-                                                     -- Creators Update
-         deriving (Eq, Show, Read)
+-- | Types used to represent SELECT GRAPHIC RENDITION (SGR) aspects.
+module System.Console.ANSI.Types
+  (
+    SGR (..)
+  , ConsoleLayer (..)
+  , Color (..)
+  , ColorIntensity (..)
+  , ConsoleIntensity (..)
+  , Underlining (..)
+  , BlinkSpeed (..)
+  ) where
+
+import Data.Ix (Ix)
+
+import Data.Colour (Colour)
+
+-- | ANSI colors: come in various intensities, which are controlled by
+-- 'ColorIntensity'
+data Color = Black
+           | Red
+           | Green
+           | Yellow
+           | Blue
+           | Magenta
+           | Cyan
+           | White
+           deriving (Eq, Ord, Bounded, Enum, Show, Read, Ix)
+
+-- | ANSI colors come in two intensities
+data ColorIntensity = Dull
+                    | Vivid
+                    deriving (Eq, Ord, Bounded, Enum, Show, Read, Ix)
+
+-- | ANSI colors can be set on two different layers
+data ConsoleLayer = Foreground
+                  | Background
+                  deriving (Eq, Ord, Bounded, Enum, Show, Read, Ix)
+
+-- | ANSI blink speeds: values other than 'NoBlink' are not widely supported
+data BlinkSpeed = SlowBlink -- ^ Less than 150 blinks per minute
+                | RapidBlink -- ^ More than 150 blinks per minute
+                | NoBlink
+                deriving (Eq, Ord, Bounded, Enum, Show, Read, Ix)
+
+-- | ANSI text underlining
+data Underlining = SingleUnderline
+                 | DoubleUnderline -- ^ Not widely supported
+                 | NoUnderline
+                 deriving (Eq, Ord, Bounded ,Enum, Show, Read, Ix)
+
+-- | ANSI general console intensity: usually treated as setting the font style
+-- (e.g. 'BoldIntensity' causes text to be bold)
+data ConsoleIntensity = BoldIntensity
+                      | FaintIntensity -- ^ Not widely supported: sometimes
+                                       -- treated as concealing text
+                      | NormalIntensity
+                      deriving (Eq, Ord, Bounded, Enum, Show, Read, Ix)
+
+-- | ANSI Select Graphic Rendition command
+data SGR = Reset
+         | SetConsoleIntensity !ConsoleIntensity
+         | SetItalicized !Bool -- ^ Not widely supported: sometimes treated as
+                               -- swapping foreground and background
+         | SetUnderlining !Underlining
+         | SetBlinkSpeed !BlinkSpeed
+         | SetVisible !Bool -- ^ Not widely supported
+         | SetSwapForegroundBackground !Bool
+         | SetColor !ConsoleLayer !ColorIntensity !Color
+         | SetRGBColor !ConsoleLayer !(Colour Float) -- ^ Supported from Windows 10
+                                                     -- Creators Update
+         deriving (Eq, Show, Read)
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,100 +1,100 @@
-{-# OPTIONS_HADDOCK hide #-}
-
-module System.Console.ANSI.Unix
-  (
--- This file contains code that is common to modules
--- System.Console.ANSI.Unix and System.Console.ANSI.Windows, namely the module
--- exports and the associated Haddock documentation.
-#include "Exports-Include.hs"
-  ) where
-
-import Control.Exception.Base (bracket)
-import System.IO (BufferMode (..), Handle, hFlush, hGetBuffering, hGetEcho,
-  hIsTerminalDevice, hPutStr, hSetBuffering, hSetEcho, stdin, stdout)
-import Text.ParserCombinators.ReadP (readP_to_S)
-
-import System.Console.ANSI.Codes
-import System.Console.ANSI.Types
-
--- This file contains code that is common to modules System.Console.ANSI.Unix,
--- System.Console.ANSI.Windows and System.Console.ANSI.Windows.Emulator, such as
--- type signatures and the definition of functions specific to stdout in terms
--- of the corresponding more general functions, inclduding the related Haddock
--- documentation.
-#include "Common-Include.hs"
--- This file contains code that is common save that different code is required
--- in the case of the module System.Console.ANSI.Windows.Emulator (see the file
--- Common-Include-Emulator.hs in respect of the latter).
-#include "Common-Include-Enabled.hs"
-
-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
-
-hCursorDownLine h n = hPutStr h $ cursorDownLineCode n
-hCursorUpLine h n = hPutStr h $ cursorUpLineCode n
-
-hSetCursorColumn h n = hPutStr h $ setCursorColumnCode n
-hSetCursorPosition h n m = hPutStr h $ setCursorPositionCode n m
-
-hSaveCursor h = hPutStr h saveCursorCode
-hRestoreCursor h = hPutStr h restoreCursorCode
-hReportCursorPosition h = hPutStr h reportCursorPositionCode
-
-hClearFromCursorToScreenEnd h = hPutStr h clearFromCursorToScreenEndCode
-hClearFromCursorToScreenBeginning h
-    = hPutStr h clearFromCursorToScreenBeginningCode
-hClearScreen h = hPutStr h clearScreenCode
-
-hClearFromCursorToLineEnd h = hPutStr h clearFromCursorToLineEndCode
-hClearFromCursorToLineBeginning h = hPutStr h clearFromCursorToLineBeginningCode
-hClearLine h = hPutStr h clearLineCode
-
-hScrollPageUp h n = hPutStr h $ scrollPageUpCode n
-hScrollPageDown h n = hPutStr h $ scrollPageDownCode n
-
-hSetSGR h sgrs = hPutStr h $ setSGRCode sgrs
-
-hHideCursor h = hPutStr h hideCursorCode
-hShowCursor h = hPutStr h showCursorCode
-
-hSetTitle h title = hPutStr h $ setTitleCode title
-
--- getReportedCursorPosition :: IO String
--- (See Common-Include.hs for Haddock documentation)
-getReportedCursorPosition = bracket (hGetEcho stdin) (hSetEcho stdin) $ \_ -> do
-  hSetEcho stdin False   -- Turn echo off
-  get
- where
-  get = do
-    c <- getChar
-    if c == '\ESC'
-      then get' [c]
-      else return [c] -- If the first character is not the expected \ESC then
-                      -- give up. This provides a modicom of protection against
-                      -- unexpected data in the input stream.
-  get' s = do
-    c <- getChar
-    if c /= 'R'
-      then get' (c:s) -- Continue building the list, until the expected 'R'
-                      -- character is obtained. Build the list in reverse order,
-                      -- in order to avoid O(n^2) complexity.
-      else return $ reverse (c:s) -- Reverse the order of the built list.
-
--- getCursorPosition :: IO (Maybe (Int, Int))
--- (See Common-Include.hs for Haddock documentation)
-getCursorPosition = do
-  input <- bracket (hGetBuffering stdin) (hSetBuffering stdin) $ \_ -> do
-    hSetBuffering stdin NoBuffering -- set no buffering (the contents of the
-                                    -- buffer will be discarded, so this needs
-                                    -- to be done before the cursor positon is
-                                    -- emitted)
-    reportCursorPosition
-    hFlush stdout -- ensure the report cursor position code is sent to the
-                  -- operating system
-    getReportedCursorPosition
-  case readP_to_S cursorPosition input of
-    [] -> return Nothing
-    [((row, col),_)] -> return $ Just (row, col)
-    (_:_) -> return Nothing
+{-# OPTIONS_HADDOCK hide #-}
+
+module System.Console.ANSI.Unix
+  (
+-- This file contains code that is common to modules
+-- System.Console.ANSI.Unix and System.Console.ANSI.Windows, namely the module
+-- exports and the associated Haddock documentation.
+#include "Exports-Include.hs"
+  ) where
+
+import Control.Exception.Base (bracket)
+import System.IO (BufferMode (..), Handle, hFlush, hGetBuffering, hGetEcho,
+  hIsTerminalDevice, hPutStr, hSetBuffering, hSetEcho, stdin, stdout)
+import Text.ParserCombinators.ReadP (readP_to_S)
+
+import System.Console.ANSI.Codes
+import System.Console.ANSI.Types
+
+-- This file contains code that is common to modules System.Console.ANSI.Unix,
+-- System.Console.ANSI.Windows and System.Console.ANSI.Windows.Emulator, such as
+-- type signatures and the definition of functions specific to stdout in terms
+-- of the corresponding more general functions, inclduding the related Haddock
+-- documentation.
+#include "Common-Include.hs"
+-- This file contains code that is common save that different code is required
+-- in the case of the module System.Console.ANSI.Windows.Emulator (see the file
+-- Common-Include-Emulator.hs in respect of the latter).
+#include "Common-Include-Enabled.hs"
+
+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
+
+hCursorDownLine h n = hPutStr h $ cursorDownLineCode n
+hCursorUpLine h n = hPutStr h $ cursorUpLineCode n
+
+hSetCursorColumn h n = hPutStr h $ setCursorColumnCode n
+hSetCursorPosition h n m = hPutStr h $ setCursorPositionCode n m
+
+hSaveCursor h = hPutStr h saveCursorCode
+hRestoreCursor h = hPutStr h restoreCursorCode
+hReportCursorPosition h = hPutStr h reportCursorPositionCode
+
+hClearFromCursorToScreenEnd h = hPutStr h clearFromCursorToScreenEndCode
+hClearFromCursorToScreenBeginning h
+    = hPutStr h clearFromCursorToScreenBeginningCode
+hClearScreen h = hPutStr h clearScreenCode
+
+hClearFromCursorToLineEnd h = hPutStr h clearFromCursorToLineEndCode
+hClearFromCursorToLineBeginning h = hPutStr h clearFromCursorToLineBeginningCode
+hClearLine h = hPutStr h clearLineCode
+
+hScrollPageUp h n = hPutStr h $ scrollPageUpCode n
+hScrollPageDown h n = hPutStr h $ scrollPageDownCode n
+
+hSetSGR h sgrs = hPutStr h $ setSGRCode sgrs
+
+hHideCursor h = hPutStr h hideCursorCode
+hShowCursor h = hPutStr h showCursorCode
+
+hSetTitle h title = hPutStr h $ setTitleCode title
+
+-- getReportedCursorPosition :: IO String
+-- (See Common-Include.hs for Haddock documentation)
+getReportedCursorPosition = bracket (hGetEcho stdin) (hSetEcho stdin) $ \_ -> do
+  hSetEcho stdin False   -- Turn echo off
+  get
+ where
+  get = do
+    c <- getChar
+    if c == '\ESC'
+      then get' [c]
+      else return [c] -- If the first character is not the expected \ESC then
+                      -- give up. This provides a modicom of protection against
+                      -- unexpected data in the input stream.
+  get' s = do
+    c <- getChar
+    if c /= 'R'
+      then get' (c:s) -- Continue building the list, until the expected 'R'
+                      -- character is obtained. Build the list in reverse order,
+                      -- in order to avoid O(n^2) complexity.
+      else return $ reverse (c:s) -- Reverse the order of the built list.
+
+-- getCursorPosition :: IO (Maybe (Int, Int))
+-- (See Common-Include.hs for Haddock documentation)
+getCursorPosition = do
+  input <- bracket (hGetBuffering stdin) (hSetBuffering stdin) $ \_ -> do
+    hSetBuffering stdin NoBuffering -- set no buffering (the contents of the
+                                    -- buffer will be discarded, so this needs
+                                    -- to be done before the cursor positon is
+                                    -- emitted)
+    reportCursorPosition
+    hFlush stdout -- ensure the report cursor position code is sent to the
+                  -- operating system
+    getReportedCursorPosition
+  case readP_to_S cursorPosition input of
+    [] -> return Nothing
+    [((row, col),_)] -> return $ Just (row, col)
+    (_:_) -> return Nothing
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,187 +1,187 @@
-{-# OPTIONS_HADDOCK hide #-}
-
-module System.Console.ANSI.Windows
-  (
--- This file contains code that is common to modules
--- System.Console.ANSI.Unix and System.Console.ANSI.Windows, namely the module
--- exports and the associated Haddock documentation.
-#include "Exports-Include.hs"
-  ) where
-
-import System.IO (Handle, hIsTerminalDevice, stdout)
-
-import System.Console.ANSI.Types
-import qualified System.Console.ANSI.Unix as U
-import System.Console.ANSI.Windows.Detect (ANSIEnabledStatus (..),
-  ConsoleDefaultState (..), isANSIEnabled)
-import qualified System.Console.ANSI.Windows.Emulator as E
-
--- This file contains code that is common to modules System.Console.ANSI.Unix,
--- System.Console.ANSI.Windows and System.Console.ANSI.Windows.Emulator, such as
--- type signatures and the definition of functions specific to stdout in terms
--- of the corresponding more general functions, inclduding the related Haddock
--- documentation.
-#include "Common-Include.hs"
--- This file contains code that is common save that different code is required
--- in the case of the module System.Console.ANSI.Windows.Emulator (see the file
--- Common-Include-Emulator.hs in respect of the latter).
-#include "Common-Include-Enabled.hs"
-
--- | A helper function which returns the native or emulated version, depending
--- on `isANSIEnabled`.
-nativeOrEmulated :: a -> a -> a
-nativeOrEmulated native emulated = case isANSIEnabled of
-  ANSIEnabled      -> native
-  NotANSIEnabled _ -> emulated
-
--- | A helper function which returns the native or emulated version, depending
--- on `isANSIEnabled`, where the emulator uses the default console state.
-nativeOrEmulatedWithDefault :: a -> (ConsoleDefaultState -> a) -> a
-nativeOrEmulatedWithDefault native emulated = case isANSIEnabled of
-  ANSIEnabled        -> native
-  NotANSIEnabled def -> emulated def
-
-
--- * Cursor movement by character
-hCursorUp       = nativeOrEmulated U.hCursorUp       E.hCursorUp
-hCursorDown     = nativeOrEmulated U.hCursorDown     E.hCursorDown
-hCursorForward  = nativeOrEmulated U.hCursorForward  E.hCursorForward
-hCursorBackward = nativeOrEmulated U.hCursorBackward E.hCursorBackward
-
-cursorUpCode :: Int -> String
-cursorUpCode = nativeOrEmulated U.cursorUpCode E.cursorUpCode
-
-cursorDownCode :: Int -> String
-cursorDownCode = nativeOrEmulated U.cursorDownCode E.cursorDownCode
-
-cursorForwardCode :: Int -> String
-cursorForwardCode = nativeOrEmulated U.cursorForwardCode E.cursorForwardCode
-
-cursorBackwardCode :: Int -> String
-cursorBackwardCode = nativeOrEmulated U.cursorBackwardCode E.cursorBackwardCode
-
--- * Cursor movement by line
-hCursorUpLine   = nativeOrEmulated U.hCursorUpLine   E.hCursorUpLine
-hCursorDownLine = nativeOrEmulated U.hCursorDownLine E.hCursorDownLine
-
-cursorUpLineCode :: Int -> String
-cursorUpLineCode = nativeOrEmulated U.cursorUpLineCode E.cursorUpLineCode
-
-cursorDownLineCode :: Int -> String
-cursorDownLineCode = nativeOrEmulated U.cursorDownLineCode E.cursorDownLineCode
-
--- * Directly changing cursor position
-hSetCursorColumn = nativeOrEmulated U.hSetCursorColumn E.hSetCursorColumn
-
-setCursorColumnCode :: Int -> String
-setCursorColumnCode = nativeOrEmulated
-  U.setCursorColumnCode E.setCursorColumnCode
-
-hSetCursorPosition = nativeOrEmulated U.hSetCursorPosition E.hSetCursorPosition
-
-setCursorPositionCode :: Int -> Int -> String
-setCursorPositionCode = nativeOrEmulated
-  U.setCursorPositionCode E.setCursorPositionCode
-
--- * Saving, restoring and reporting cursor position
-hSaveCursor = nativeOrEmulated U.hSaveCursor E.hSaveCursor
-hRestoreCursor = nativeOrEmulated U.hRestoreCursor E.hRestoreCursor
-hReportCursorPosition = nativeOrEmulated
-  U.hReportCursorPosition E.hReportCursorPosition
-
-saveCursorCode :: String
-saveCursorCode = nativeOrEmulated U.saveCursorCode E.saveCursorCode
-
-restoreCursorCode :: String
-restoreCursorCode = nativeOrEmulated U.restoreCursorCode E.restoreCursorCode
-
-reportCursorPositionCode :: String
-reportCursorPositionCode = nativeOrEmulated
-    U.reportCursorPositionCode E.reportCursorPositionCode
-
--- * Clearing parts of the screen
-hClearFromCursorToScreenEnd = nativeOrEmulatedWithDefault
-  U.hClearFromCursorToScreenEnd E.hClearFromCursorToScreenEnd
-hClearFromCursorToScreenBeginning = nativeOrEmulatedWithDefault
-  U.hClearFromCursorToScreenBeginning E.hClearFromCursorToScreenBeginning
-hClearScreen = nativeOrEmulatedWithDefault U.hClearScreen E.hClearScreen
-
-clearFromCursorToScreenEndCode :: String
-clearFromCursorToScreenEndCode = nativeOrEmulated
-  U.clearFromCursorToScreenEndCode E.clearFromCursorToScreenEndCode
-
-clearFromCursorToScreenBeginningCode :: String
-clearFromCursorToScreenBeginningCode = nativeOrEmulated
-    U.clearFromCursorToScreenBeginningCode E.clearFromCursorToScreenBeginningCode
-
-clearScreenCode :: String
-clearScreenCode = nativeOrEmulated U.clearScreenCode E.clearScreenCode
-
-hClearFromCursorToLineEnd = nativeOrEmulatedWithDefault
-  U.hClearFromCursorToLineEnd E.hClearFromCursorToLineEnd
-hClearFromCursorToLineBeginning = nativeOrEmulatedWithDefault
-  U.hClearFromCursorToLineBeginning E.hClearFromCursorToLineBeginning
-hClearLine = nativeOrEmulatedWithDefault U.hClearLine E.hClearLine
-
-clearFromCursorToLineEndCode :: String
-clearFromCursorToLineEndCode = nativeOrEmulated
-  U.clearFromCursorToLineEndCode E.clearFromCursorToLineEndCode
-
-clearFromCursorToLineBeginningCode :: String
-clearFromCursorToLineBeginningCode = nativeOrEmulated
-  U.clearFromCursorToLineBeginningCode E.clearFromCursorToLineBeginningCode
-
-clearLineCode :: String
-clearLineCode = nativeOrEmulated U.clearLineCode E.clearLineCode
-
--- * Scrolling the screen
-hScrollPageUp   = nativeOrEmulatedWithDefault U.hScrollPageUp   E.hScrollPageUp
-hScrollPageDown = nativeOrEmulatedWithDefault U.hScrollPageDown E.hScrollPageDown
-
-scrollPageUpCode :: Int -> String
-scrollPageUpCode = nativeOrEmulated U.scrollPageUpCode E.scrollPageUpCode
-
-scrollPageDownCode :: Int -> String
-scrollPageDownCode = nativeOrEmulated U.scrollPageDownCode E.scrollPageDownCode
-
--- * Select Graphic Rendition mode: colors and other whizzy stuff
---
--- The following SGR codes are NOT implemented by Windows 10 Threshold 2:
--- 2   SetConsoleIntensity FaintIntensity
--- 3   SetItalicized True
--- 5   SetBlinkSpeed SlowBlink
--- 6   SetBlinkSpeed RapidBlink
--- 8   SetVisible False
--- 21  SetUnderlining DoubleUnderline
--- 23  SetItalicized False
--- 25  SetBlinkSpeed NoBlink
--- 28  SetVisible True
-
-hSetSGR = nativeOrEmulatedWithDefault U.hSetSGR E.hSetSGR
-
-setSGRCode :: [SGR] -> String
-setSGRCode = nativeOrEmulated U.setSGRCode E.setSGRCode
-
--- * Cursor visibilty changes
-hHideCursor = nativeOrEmulated U.hHideCursor E.hHideCursor
-hShowCursor = nativeOrEmulated U.hShowCursor E.hShowCursor
-
-hideCursorCode :: String
-hideCursorCode = nativeOrEmulated U.hideCursorCode E.hideCursorCode
-
-showCursorCode :: String
-showCursorCode = nativeOrEmulated U.showCursorCode E.showCursorCode
-
--- * Changing the title
-hSetTitle = nativeOrEmulated U.hSetTitle E.hSetTitle
-
-setTitleCode :: String -> String
-setTitleCode = nativeOrEmulated U.setTitleCode E.setTitleCode
-
--- getReportedCursorPosition :: IO String
--- (See Common-Include.hs for Haddock documentation)
-getReportedCursorPosition = E.getReportedCursorPosition
-
--- getCursorPosition :: IO (Maybe (Int, Int))
--- (See Common-Include.hs for Haddock documentation)
-getCursorPosition = E.getCursorPosition
+{-# OPTIONS_HADDOCK hide #-}
+
+module System.Console.ANSI.Windows
+  (
+-- This file contains code that is common to modules
+-- System.Console.ANSI.Unix and System.Console.ANSI.Windows, namely the module
+-- exports and the associated Haddock documentation.
+#include "Exports-Include.hs"
+  ) where
+
+import System.IO (Handle, hIsTerminalDevice, stdout)
+
+import System.Console.ANSI.Types
+import qualified System.Console.ANSI.Unix as U
+import System.Console.ANSI.Windows.Detect (ANSIEnabledStatus (..),
+  ConsoleDefaultState (..), isANSIEnabled)
+import qualified System.Console.ANSI.Windows.Emulator as E
+
+-- This file contains code that is common to modules System.Console.ANSI.Unix,
+-- System.Console.ANSI.Windows and System.Console.ANSI.Windows.Emulator, such as
+-- type signatures and the definition of functions specific to stdout in terms
+-- of the corresponding more general functions, inclduding the related Haddock
+-- documentation.
+#include "Common-Include.hs"
+-- This file contains code that is common save that different code is required
+-- in the case of the module System.Console.ANSI.Windows.Emulator (see the file
+-- Common-Include-Emulator.hs in respect of the latter).
+#include "Common-Include-Enabled.hs"
+
+-- | A helper function which returns the native or emulated version, depending
+-- on `isANSIEnabled`.
+nativeOrEmulated :: a -> a -> a
+nativeOrEmulated native emulated = case isANSIEnabled of
+  ANSIEnabled      -> native
+  NotANSIEnabled _ -> emulated
+
+-- | A helper function which returns the native or emulated version, depending
+-- on `isANSIEnabled`, where the emulator uses the default console state.
+nativeOrEmulatedWithDefault :: a -> (ConsoleDefaultState -> a) -> a
+nativeOrEmulatedWithDefault native emulated = case isANSIEnabled of
+  ANSIEnabled        -> native
+  NotANSIEnabled def -> emulated def
+
+
+-- * Cursor movement by character
+hCursorUp       = nativeOrEmulated U.hCursorUp       E.hCursorUp
+hCursorDown     = nativeOrEmulated U.hCursorDown     E.hCursorDown
+hCursorForward  = nativeOrEmulated U.hCursorForward  E.hCursorForward
+hCursorBackward = nativeOrEmulated U.hCursorBackward E.hCursorBackward
+
+cursorUpCode :: Int -> String
+cursorUpCode = nativeOrEmulated U.cursorUpCode E.cursorUpCode
+
+cursorDownCode :: Int -> String
+cursorDownCode = nativeOrEmulated U.cursorDownCode E.cursorDownCode
+
+cursorForwardCode :: Int -> String
+cursorForwardCode = nativeOrEmulated U.cursorForwardCode E.cursorForwardCode
+
+cursorBackwardCode :: Int -> String
+cursorBackwardCode = nativeOrEmulated U.cursorBackwardCode E.cursorBackwardCode
+
+-- * Cursor movement by line
+hCursorUpLine   = nativeOrEmulated U.hCursorUpLine   E.hCursorUpLine
+hCursorDownLine = nativeOrEmulated U.hCursorDownLine E.hCursorDownLine
+
+cursorUpLineCode :: Int -> String
+cursorUpLineCode = nativeOrEmulated U.cursorUpLineCode E.cursorUpLineCode
+
+cursorDownLineCode :: Int -> String
+cursorDownLineCode = nativeOrEmulated U.cursorDownLineCode E.cursorDownLineCode
+
+-- * Directly changing cursor position
+hSetCursorColumn = nativeOrEmulated U.hSetCursorColumn E.hSetCursorColumn
+
+setCursorColumnCode :: Int -> String
+setCursorColumnCode = nativeOrEmulated
+  U.setCursorColumnCode E.setCursorColumnCode
+
+hSetCursorPosition = nativeOrEmulated U.hSetCursorPosition E.hSetCursorPosition
+
+setCursorPositionCode :: Int -> Int -> String
+setCursorPositionCode = nativeOrEmulated
+  U.setCursorPositionCode E.setCursorPositionCode
+
+-- * Saving, restoring and reporting cursor position
+hSaveCursor = nativeOrEmulated U.hSaveCursor E.hSaveCursor
+hRestoreCursor = nativeOrEmulated U.hRestoreCursor E.hRestoreCursor
+hReportCursorPosition = nativeOrEmulated
+  U.hReportCursorPosition E.hReportCursorPosition
+
+saveCursorCode :: String
+saveCursorCode = nativeOrEmulated U.saveCursorCode E.saveCursorCode
+
+restoreCursorCode :: String
+restoreCursorCode = nativeOrEmulated U.restoreCursorCode E.restoreCursorCode
+
+reportCursorPositionCode :: String
+reportCursorPositionCode = nativeOrEmulated
+    U.reportCursorPositionCode E.reportCursorPositionCode
+
+-- * Clearing parts of the screen
+hClearFromCursorToScreenEnd = nativeOrEmulatedWithDefault
+  U.hClearFromCursorToScreenEnd E.hClearFromCursorToScreenEnd
+hClearFromCursorToScreenBeginning = nativeOrEmulatedWithDefault
+  U.hClearFromCursorToScreenBeginning E.hClearFromCursorToScreenBeginning
+hClearScreen = nativeOrEmulatedWithDefault U.hClearScreen E.hClearScreen
+
+clearFromCursorToScreenEndCode :: String
+clearFromCursorToScreenEndCode = nativeOrEmulated
+  U.clearFromCursorToScreenEndCode E.clearFromCursorToScreenEndCode
+
+clearFromCursorToScreenBeginningCode :: String
+clearFromCursorToScreenBeginningCode = nativeOrEmulated
+    U.clearFromCursorToScreenBeginningCode E.clearFromCursorToScreenBeginningCode
+
+clearScreenCode :: String
+clearScreenCode = nativeOrEmulated U.clearScreenCode E.clearScreenCode
+
+hClearFromCursorToLineEnd = nativeOrEmulatedWithDefault
+  U.hClearFromCursorToLineEnd E.hClearFromCursorToLineEnd
+hClearFromCursorToLineBeginning = nativeOrEmulatedWithDefault
+  U.hClearFromCursorToLineBeginning E.hClearFromCursorToLineBeginning
+hClearLine = nativeOrEmulatedWithDefault U.hClearLine E.hClearLine
+
+clearFromCursorToLineEndCode :: String
+clearFromCursorToLineEndCode = nativeOrEmulated
+  U.clearFromCursorToLineEndCode E.clearFromCursorToLineEndCode
+
+clearFromCursorToLineBeginningCode :: String
+clearFromCursorToLineBeginningCode = nativeOrEmulated
+  U.clearFromCursorToLineBeginningCode E.clearFromCursorToLineBeginningCode
+
+clearLineCode :: String
+clearLineCode = nativeOrEmulated U.clearLineCode E.clearLineCode
+
+-- * Scrolling the screen
+hScrollPageUp   = nativeOrEmulatedWithDefault U.hScrollPageUp   E.hScrollPageUp
+hScrollPageDown = nativeOrEmulatedWithDefault U.hScrollPageDown E.hScrollPageDown
+
+scrollPageUpCode :: Int -> String
+scrollPageUpCode = nativeOrEmulated U.scrollPageUpCode E.scrollPageUpCode
+
+scrollPageDownCode :: Int -> String
+scrollPageDownCode = nativeOrEmulated U.scrollPageDownCode E.scrollPageDownCode
+
+-- * Select Graphic Rendition mode: colors and other whizzy stuff
+--
+-- The following SGR codes are NOT implemented by Windows 10 Threshold 2:
+-- 2   SetConsoleIntensity FaintIntensity
+-- 3   SetItalicized True
+-- 5   SetBlinkSpeed SlowBlink
+-- 6   SetBlinkSpeed RapidBlink
+-- 8   SetVisible False
+-- 21  SetUnderlining DoubleUnderline
+-- 23  SetItalicized False
+-- 25  SetBlinkSpeed NoBlink
+-- 28  SetVisible True
+
+hSetSGR = nativeOrEmulatedWithDefault U.hSetSGR E.hSetSGR
+
+setSGRCode :: [SGR] -> String
+setSGRCode = nativeOrEmulated U.setSGRCode E.setSGRCode
+
+-- * Cursor visibilty changes
+hHideCursor = nativeOrEmulated U.hHideCursor E.hHideCursor
+hShowCursor = nativeOrEmulated U.hShowCursor E.hShowCursor
+
+hideCursorCode :: String
+hideCursorCode = nativeOrEmulated U.hideCursorCode E.hideCursorCode
+
+showCursorCode :: String
+showCursorCode = nativeOrEmulated U.showCursorCode E.showCursorCode
+
+-- * Changing the title
+hSetTitle = nativeOrEmulated U.hSetTitle E.hSetTitle
+
+setTitleCode :: String -> String
+setTitleCode = nativeOrEmulated U.setTitleCode E.setTitleCode
+
+-- getReportedCursorPosition :: IO String
+-- (See Common-Include.hs for Haddock documentation)
+getReportedCursorPosition = E.getReportedCursorPosition
+
+-- getCursorPosition :: IO (Maybe (Int, Int))
+-- (See Common-Include.hs for Haddock documentation)
+getCursorPosition = E.getCursorPosition
diff --git a/System/Console/ANSI/Windows/Detect.hs b/System/Console/ANSI/Windows/Detect.hs
--- a/System/Console/ANSI/Windows/Detect.hs
+++ b/System/Console/ANSI/Windows/Detect.hs
@@ -1,115 +1,123 @@
-{-# OPTIONS_HADDOCK hide #-}
-
-module System.Console.ANSI.Windows.Detect
-  (
-    ANSIEnabledStatus (..)
-  , ConsoleDefaultState (..)
-  , isANSIEnabled
-  ) where
-
-import Control.Exception (SomeException(..), onException, throwIO, try)
-import Data.Bits ((.&.), (.|.))
--- 'lookupEnv' is not available until base-4.6.0.0 (GHC 7.6.1)
-import System.Environment.Compat (lookupEnv)
-import System.IO.Unsafe (unsafePerformIO)
-
-import System.Console.ANSI.Windows.Foreign (bACKGROUND_INTENSE_WHITE,
-  ConsoleException(..), CONSOLE_SCREEN_BUFFER_INFO (..), DWORD,
-  eNABLE_VIRTUAL_TERMINAL_PROCESSING, fOREGROUND_INTENSE_WHITE,
-  getConsoleMode, getConsoleScreenBufferInfo, getStdHandle, HANDLE,
-  iNVALID_HANDLE_VALUE, nullHANDLE, setConsoleMode, sTD_OUTPUT_HANDLE, WORD)
-
--- | The default state of the console
-data ConsoleDefaultState = ConsoleDefaultState
-  { defaultForegroundAttributes :: WORD -- ^ Foreground attributes
-  , defaultBackgroundAttributes :: WORD -- ^ Background attributes
-  } deriving (Eq, Show)
-
--- | The status of the console as regards it being ANSI-enabled or not
--- ANSI-enabled.
-data ANSIEnabledStatus
-  = ANSIEnabled -- ^ ANSI-enabled
-  | NotANSIEnabled ConsoleDefaultState -- ^ Not ANSI-enabled (including the
-                                       -- state of the console when that status
-                                       -- was determined)
-  deriving (Eq, Show)
-
--- | This function assumes that once it is first established whether or not the
--- Windows console is ANSI-enabled, that will not change. If the console is not
--- ANSI-enabled, the state of the console is considered to be its default state.
-{-# NOINLINE isANSIEnabled #-}
-isANSIEnabled :: ANSIEnabledStatus
-isANSIEnabled = unsafePerformIO $ do
-  e <- safeIsANSIEnabled
-  if e
-    then return ANSIEnabled
-    else onException (do
-      hOut <- getValidStdHandle sTD_OUTPUT_HANDLE
-      info <- getConsoleScreenBufferInfo hOut
-      let attributes = csbi_attributes info
-          fgAttributes = attributes .&. fOREGROUND_INTENSE_WHITE
-          bgAttributes = attributes .&. bACKGROUND_INTENSE_WHITE
-          consoleDefaultState = ConsoleDefaultState
-            { defaultForegroundAttributes = fgAttributes
-            , defaultBackgroundAttributes = bgAttributes }
-      return $ NotANSIEnabled consoleDefaultState)
-      (putStrLn $ "A fatal error has occurred. An attempt has been made to " ++
-        "send console virtual terminal sequences (ANSI codes) to an output " ++
-        "that has not been recognised as an ANSI-capable terminal and also " ++
-        "cannot be emulated as an ANSI-enabled terminal (emulation needs a " ++
-        "ConHost-based terminal, such as Command Prompt or PowerShell).\n\n" ++
-        "If that is unexpected, please post an issue at the home page of " ++
-        "the ansi-terminal package. See " ++
-        "https://hackage.haskell.org/package/ansi-terminal for the home " ++
-        "page location.\n")
-
--- This function takes the following approach. If the environment variable
--- APPVEYOR exists and is set to 'True', it assumes the code is running in the
--- Appveyor build environment and that the build console is ANSI-enabled.
--- Otherwise, if the environment variable TERM exists and is not set to 'dumb'
--- or 'msys' (see below), it assumes the console is ANSI-enabled. Otherwise, it
--- tries to enable virtual terminal processing. If that fails, it assumes the
--- console is not ANSI-enabled.
---
--- In Git Shell, if Command Prompt or PowerShell are used, the environment
--- variable TERM is set to 'msys'. If 'Git Bash' (mintty) is used, TERM is set
--- to 'xterm' (by default).
-safeIsANSIEnabled :: IO Bool
-safeIsANSIEnabled = do
-  appveyor <- lookupEnv "APPVEYOR"
-  case appveyor of
-    Just "True" -> return True
-    _           -> do
-      term <- lookupEnv "TERM"
-      case term of
-        Just "dumb" -> return False
-        Just "msys" -> doesEnableANSIOutSucceed
-        Just _      -> return True
-        Nothing     -> doesEnableANSIOutSucceed
-
--- This function returns whether or not an attempt to enable virtual terminal
--- processing succeeded, in the IO monad.
-doesEnableANSIOutSucceed :: IO Bool
-doesEnableANSIOutSucceed = do
-  result <- try enableANSIOut :: IO (Either SomeException ())
-  case result of
-    Left _ -> return False
-    Right () -> return True
-
--- This function tries to enable virtual terminal processing on the standard
--- output and throws an exception if it cannot.
-enableANSIOut :: IO ()
-enableANSIOut = do
-  hOut <- getValidStdHandle sTD_OUTPUT_HANDLE
-  mOut <- getConsoleMode hOut
-  let mOut' = mOut .|. eNABLE_VIRTUAL_TERMINAL_PROCESSING
-  setConsoleMode hOut mOut'
-
--- This function tries to get a valid standard handle and throws an exception if
--- it cannot.
-getValidStdHandle :: DWORD -> IO HANDLE
-getValidStdHandle nStdHandle = do
-  h <- getStdHandle nStdHandle
-  if h == iNVALID_HANDLE_VALUE || h == nullHANDLE
-    then throwIO $ ConsoleException 6 -- Invalid Handle
-    else return h
+{-# OPTIONS_HADDOCK hide #-}
+
+module System.Console.ANSI.Windows.Detect
+  (
+    ANSIEnabledStatus (..)
+  , ConsoleDefaultState (..)
+  , isANSIEnabled
+  ) where
+
+import Control.Exception (SomeException(..), onException, throwIO, try)
+import Data.Bits ((.&.), (.|.))
+-- 'lookupEnv' is not available until base-4.6.0.0 (GHC 7.6.1)
+import System.Environment.Compat (lookupEnv)
+import System.IO.Unsafe (unsafePerformIO)
+
+import System.Console.ANSI.Windows.Foreign (bACKGROUND_INTENSE_WHITE,
+  ConsoleException(..), CONSOLE_SCREEN_BUFFER_INFO (..), DWORD,
+  eNABLE_VIRTUAL_TERMINAL_PROCESSING, fOREGROUND_INTENSE_WHITE,
+  getConsoleMode, getConsoleScreenBufferInfo, getStdHandle, HANDLE,
+  iNVALID_HANDLE_VALUE, nullHANDLE, setConsoleMode, sTD_OUTPUT_HANDLE, WORD)
+
+-- | The default state of the console
+data ConsoleDefaultState = ConsoleDefaultState
+  { defaultForegroundAttributes :: WORD -- ^ Foreground attributes
+  , defaultBackgroundAttributes :: WORD -- ^ Background attributes
+  } deriving (Eq, Show)
+
+-- | The status of the console as regards it being ANSI-enabled or not
+-- ANSI-enabled.
+data ANSIEnabledStatus
+  = ANSIEnabled -- ^ ANSI-enabled
+  | NotANSIEnabled ConsoleDefaultState -- ^ Not ANSI-enabled (including the
+                                       -- state of the console when that status
+                                       -- was determined)
+  deriving (Eq, Show)
+
+-- | This function assumes that once it is first established whether or not the
+-- Windows console is ANSI-enabled, that will not change. If the console is not
+-- ANSI-enabled, the state of the console is considered to be its default state.
+{-# NOINLINE isANSIEnabled #-}
+isANSIEnabled :: ANSIEnabledStatus
+isANSIEnabled = unsafePerformIO $ do
+  e <- safeIsANSIEnabled
+  if e
+    then return ANSIEnabled
+    else do
+      hOut <- getValidStdHandle sTD_OUTPUT_HANDLE
+      info <- getConsoleScreenBufferInfo hOut
+      let attributes = csbi_attributes info
+          fgAttributes = attributes .&. fOREGROUND_INTENSE_WHITE
+          bgAttributes = attributes .&. bACKGROUND_INTENSE_WHITE
+          consoleDefaultState = ConsoleDefaultState
+            { defaultForegroundAttributes = fgAttributes
+            , defaultBackgroundAttributes = bgAttributes }
+      return $ NotANSIEnabled consoleDefaultState
+
+-- This function takes the following approach. If the environment variable
+-- APPVEYOR exists and is set to 'True', it assumes the code is running in the
+-- Appveyor build environment and that the build console is ANSI-enabled.
+-- Otherwise, if the environment variable TERM exists and is not set to 'dumb'
+-- or 'msys' (see below), it assumes the console is ANSI-enabled. Otherwise, it
+-- tries to get a valid standard output handle. If that does not fail, it
+-- tried to get a ConHost console mode. If that fails, it assumes that the
+-- handle is ANSI-enabled. Otherwise, it tries to enable virtual terminal
+-- processing. If that fails, it assumes the console is not ANSI-enabled.
+--
+-- In Git Shell, if Command Prompt or PowerShell are used, the environment
+-- variable TERM is set to 'msys'. If 'Git Bash' (mintty) is used, TERM is set
+-- to 'xterm' (by default).
+safeIsANSIEnabled :: IO Bool
+safeIsANSIEnabled = do
+  appveyor <- lookupEnv "APPVEYOR"
+  case appveyor of
+    Just "True" -> return True
+    _           -> do
+      term <- lookupEnv "TERM"
+      case term of
+        Just "dumb" -> return False
+        Just "msys" -> doesEnableANSIOutSucceed
+        Just _      -> return True
+        Nothing     -> doesEnableANSIOutSucceed
+
+-- This function returns whether or not an attempt to enable virtual terminal
+-- processing succeeded, or was deemed to succeed, in the IO monad.
+doesEnableANSIOutSucceed :: IO Bool
+doesEnableANSIOutSucceed = do
+  result <- try enableANSIOut :: IO (Either SomeException ())
+  case result of
+    Left _ -> return False
+    Right () -> return True
+
+-- This function tries to get a valid handle on the standard output and throws
+-- an exception if it cannot. It then tries to get a ConHost console mode for
+-- that handle. If it can not, it assumes that the standard output handle is
+-- ANSI-enabled. If it can, it tries to enable virtual terminal processing and
+-- throws an exception if it can not.
+enableANSIOut :: IO ()
+enableANSIOut = do
+  hOut <- getValidStdHandle sTD_OUTPUT_HANDLE
+  result <- conHostConsoleMode hOut
+  case result of
+    Nothing -> return ()  -- assume hOut is ANSI-enabled
+    Just mOut -> do
+      let mOut' = mOut .|. eNABLE_VIRTUAL_TERMINAL_PROCESSING
+      setConsoleMode hOut mOut'
+
+-- This function tries to get a valid standard handle and throws an exception if
+-- it cannot.
+getValidStdHandle :: DWORD -> IO HANDLE
+getValidStdHandle nStdHandle = do
+  h <- getStdHandle nStdHandle
+  if h == iNVALID_HANDLE_VALUE || h == nullHANDLE
+    then throwIO $ ConsoleException 6 -- Invalid handle or no handle
+    else return h
+
+-- The function tries to get a ConHost console mode from a handle that is
+-- assumed to be a valid standard handle (see getValidStdHandle)
+conHostConsoleMode :: HANDLE -> IO (Maybe DWORD)
+conHostConsoleMode h = do
+  result <- try (getConsoleMode h) :: IO (Either SomeException DWORD)
+  case result of
+    Left _ -> return Nothing
+    Right mode -> return (Just mode)
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,464 +1,464 @@
-{-# OPTIONS_HADDOCK hide #-}
-
-module System.Console.ANSI.Windows.Emulator
-  (
-#include "Exports-Include.hs"
-  ) where
-
-import Control.Exception (catch, catchJust, IOException)
-import Control.Monad (forM_, unless)
-import Data.Bits ((.&.), (.|.), complement, shiftL, shiftR)
-import Data.IORef (IORef, newIORef, readIORef, writeIORef)
-import Data.List (foldl', minimumBy)
-import Data.Maybe (mapMaybe)
-import qualified Data.Map.Strict as Map (Map, empty, insert, lookup)
-import System.IO (Handle, hFlush, hIsTerminalDevice, stdin, stdout)
-import System.IO.Unsafe (unsafePerformIO)
-import Text.ParserCombinators.ReadP (readP_to_S)
-
-import Data.Colour (Colour)
-import Data.Colour.Names (black, blue, cyan, green, grey, lime, magenta, maroon,
-  navy, olive, purple, red, silver, teal, white, yellow)
-import Data.Colour.SRGB (RGB (..), toSRGB)
-
-import System.Console.ANSI.Types
-import qualified System.Console.ANSI.Unix as Unix
-import System.Console.ANSI.Windows.Detect
-import System.Console.ANSI.Windows.Emulator.Codes
-import System.Console.ANSI.Windows.Foreign
-
--- This file contains code that is common to modules System.Console.ANSI.Unix,
--- System.Console.ANSI.Windows and System.Console.ANSI.Windows.Emulator, such as
--- type signatures and the definition of functions specific to stdout in terms
--- of the corresponding more general functions, inclduding the related Haddock
--- documentation.
-#include "Common-Include.hs"
--- This file contains code that is required in the case of the module
--- System.Console.ANSI.Windows.Emulator and differs from the common code in
--- file Common-Include-Enabled.hs.
-#include "Common-Include-Emulator.hs"
-
-withHandle :: Handle -> (HANDLE -> IO a) -> IO a
-withHandle handle action = do
-  -- It's VERY IMPORTANT that we flush before issuing any sort of Windows API
-  -- call to change the console because on Windows the arrival of
-  -- API-initiated state changes is not necessarily synchronised with that of
-  -- the text they are attempting to modify.
-  hFlush handle
-  withHandleToHANDLE handle action
-
--- Unfortunately, the emulator is not perfect. In particular, it has a tendency
--- to die with exceptions about invalid handles when it is used with certain
--- Windows consoles (e.g. mintty, terminator, or cygwin sshd).
---
--- This happens because in those environments the stdout family of handles are
--- not actually associated with a real console.
---
--- My observation is that every time I've seen this in practice, the handle we
--- have instead of the actual console handle is there so that the terminal
--- supports ANSI escape codes. So 99% of the time, the correct thing to do is
--- just to fall back on the Unix module to output the ANSI codes and hope for
--- the best.
-emulatorFallback :: IO a -> IO a -> IO a
-emulatorFallback fallback first_try
-  = catchJust invalidHandle first_try (const fallback)
- where
-  invalidHandle (ConsoleException 6) = Just ()  -- 6 is the Windows error code
-                                                -- for invalid handles
-  invalidHandle (_)                  = Nothing
-
-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'
-
-hCursorUp h n
-  = emulatorFallback (Unix.hCursorUp h n) $ withHandle h $
-      \handle -> adjustCursorPosition handle (\_ x -> x)
-                   (\_ y -> y - fromIntegral n)
-hCursorDown h n
-  = emulatorFallback (Unix.hCursorDown h n) $ withHandle h $
-      \handle -> adjustCursorPosition handle (\_ x -> x)
-                   (\_ y -> y + fromIntegral n)
-hCursorForward h n
-  = emulatorFallback (Unix.hCursorForward h n) $ withHandle h $
-      \handle -> adjustCursorPosition handle (\_ x -> x + fromIntegral n)
-                   (\_ y -> y)
-hCursorBackward h n
-  = emulatorFallback (Unix.hCursorBackward h n) $ withHandle h $
-      \handle -> adjustCursorPosition handle (\_ x -> x - fromIntegral n)
-                   (\_ y -> y)
-
-adjustLine :: HANDLE -> (SHORT -> SHORT -> SHORT) -> IO ()
-adjustLine handle change_y
-  = adjustCursorPosition handle (\window_left _ -> window_left) change_y
-
-hCursorDownLine h n
-  = emulatorFallback (Unix.hCursorDownLine h n) $ withHandle h $
-      \handle -> adjustLine handle (\_ y -> y + fromIntegral n)
-
-hCursorUpLine h n
-  = emulatorFallback (Unix.hCursorUpLine h n) $ withHandle h $
-      \handle -> adjustLine handle (\_ y -> y - fromIntegral n)
-
-hSetCursorColumn h x
-  = emulatorFallback (Unix.hSetCursorColumn h x) $ withHandle h $
-      \handle -> adjustCursorPosition handle
-                   (\window_left _ -> window_left + fromIntegral x) (\_ y -> y)
-
-hSetCursorPosition h y x
-  = emulatorFallback (Unix.hSetCursorPosition h y x) $ withHandle h $
-      \handle -> adjustCursorPosition handle
-                   (\window_left _ -> window_left + fromIntegral x)
-                   (\window_top _ -> window_top + fromIntegral y)
-
-clearChar :: WCHAR
-clearChar = charToWCHAR ' '
-
--- | The 'clear' attribute is equated with the default background attributes.
-clearAttribute :: ConsoleDefaultState -> WORD
-clearAttribute = defaultBackgroundAttributes
-
-hClearScreenFraction
-  :: ConsoleDefaultState
-  -> HANDLE
-  -> (SMALL_RECT -> COORD -> (SHORT, SHORT, SHORT, SHORT, SHORT, SHORT))
-  -> IO ()
-hClearScreenFraction cds handle fraction_finder = do
-  screen_buffer_info <- getConsoleScreenBufferInfo handle
-  let window = csbi_window screen_buffer_info
-      cursor_pos = csbi_cursor_position screen_buffer_info
-      (left, top, right, bottom, start_x, end_x)
-          = fraction_finder window cursor_pos
-  mapM_ (fill_line left top right bottom start_x end_x) [top .. bottom]
- where
-  fill_line left top right bottom start_x end_x y = do
-    let left'  = if y == top    then start_x else left
-        right' = if y == bottom then end_x   else right
-        fill_cursor_pos = COORD left' y
-        fill_length = fromIntegral $ right' - left' + 1
-    _ <- fillConsoleOutputCharacter handle clearChar fill_length fill_cursor_pos
-    fillConsoleOutputAttribute handle (clearAttribute cds) fill_length
-      fill_cursor_pos
-
-hClearFromCursorToScreenEnd cds h
-  = emulatorFallback (Unix.hClearFromCursorToScreenEnd h) $ withHandle h $
-      \handle -> hClearScreenFraction cds handle go
- where
-  go window cursor_pos = (left, top, right, bottom, start_x, right)
-   where
-    SMALL_RECT (COORD left _) (COORD right bottom) = window
-    COORD start_x top = cursor_pos
-
-hClearFromCursorToScreenBeginning cds h
-  = emulatorFallback (Unix.hClearFromCursorToScreenBeginning h) $ withHandle h $
-      \handle -> hClearScreenFraction cds handle go
- where
-  go window cursor_pos = (left, top, right, bottom, left, end_x)
-   where
-    SMALL_RECT (COORD left top) (COORD right _) = window
-    COORD end_x bottom = cursor_pos
-
-hClearScreen cds h
-  = emulatorFallback (Unix.hClearScreen h) $ withHandle h $
-      \handle -> hClearScreenFraction cds handle go
- where
-  go window _ = (left, top, right, bottom, left, right)
-   where
-    SMALL_RECT (COORD left top) (COORD right bottom) = window
-
-hClearFromCursorToLineEnd cds h
-  = emulatorFallback (Unix.hClearFromCursorToLineEnd h) $ withHandle h $
-      \handle -> hClearScreenFraction cds handle go
- where
-  go window cursor_pos = (left, y, right, y, start_x, right)
-   where
-    SMALL_RECT (COORD left _) (COORD right _) = window
-    COORD start_x y = cursor_pos
-
-hClearFromCursorToLineBeginning cds h
-  = emulatorFallback (Unix.hClearFromCursorToLineBeginning h) $ withHandle h $
-        \handle -> hClearScreenFraction cds handle go
- where
-  go window cursor_pos = (left, y, right, y, left, end_x)
-   where
-    SMALL_RECT (COORD left _) (COORD right _) = window
-    COORD end_x y = cursor_pos
-
-hClearLine cds h
-  = emulatorFallback (Unix.hClearLine h) $ withHandle h $
-      \handle -> hClearScreenFraction cds handle go
- where
-  go window cursor_pos = (left, y, right, y, left, right)
-   where
-    SMALL_RECT (COORD left _) (COORD right _) = window
-    COORD _ y = cursor_pos
-
-hScrollPage
-  :: ConsoleDefaultState -- ^ The default console state
-  -> HANDLE
-  -> Int
-  -> IO ()
-hScrollPage cds handle new_origin_y = do
-  screen_buffer_info <- getConsoleScreenBufferInfo handle
-  let fill = CHAR_INFO clearChar (clearAttribute cds)
-      window = csbi_window screen_buffer_info
-      origin = COORD (rect_left window)
-                     (rect_top window + fromIntegral new_origin_y)
-  scrollConsoleScreenBuffer handle window Nothing origin fill
-
-hScrollPageUp cds h n
-  = emulatorFallback (Unix.hScrollPageUp h n) $ withHandle h $
-      \handle -> hScrollPage cds handle (negate n)
-
-hScrollPageDown cds h n
-  = emulatorFallback (Unix.hScrollPageDown h n) $ withHandle h $
-      \handle -> hScrollPage cds handle n
-
-{-# INLINE applyANSIColorToAttribute #-}
-applyANSIColorToAttribute :: WORD -> WORD -> WORD -> Color -> WORD -> WORD
-applyANSIColorToAttribute rED gREEN bLUE color attribute = case color of
-  Black   -> attribute'
-  Red     -> attribute' .|. rED
-  Green   -> attribute' .|. gREEN
-  Yellow  -> attribute' .|. rED .|. gREEN
-  Blue    -> attribute' .|. bLUE
-  Magenta -> attribute' .|. rED .|. bLUE
-  Cyan    -> attribute' .|. gREEN .|. bLUE
-  White   -> attribute' .|. wHITE
- where
-  wHITE = rED .|. gREEN .|. bLUE
-  attribute' = attribute .&. (complement wHITE)
-
-applyForegroundANSIColorToAttribute, applyBackgroundANSIColorToAttribute
-  :: Color
-  -> WORD
-  -> WORD
-applyForegroundANSIColorToAttribute
-  = applyANSIColorToAttribute fOREGROUND_RED fOREGROUND_GREEN fOREGROUND_BLUE
-applyBackgroundANSIColorToAttribute
-  = applyANSIColorToAttribute bACKGROUND_RED bACKGROUND_GREEN bACKGROUND_BLUE
-
-swapForegroundBackgroundColors :: WORD -> WORD
-swapForegroundBackgroundColors attribute
-  = clean_attribute .|. foreground_attribute' .|. background_attribute'
- where
-  foreground_attribute = attribute .&. fOREGROUND_INTENSE_WHITE
-  background_attribute = attribute .&. bACKGROUND_INTENSE_WHITE
-  clean_attribute = attribute .&. complement
-    (fOREGROUND_INTENSE_WHITE .|. bACKGROUND_INTENSE_WHITE)
-  foreground_attribute' = background_attribute `shiftR` 4
-  background_attribute' = foreground_attribute `shiftL` 4
-
-applyANSISGRToAttribute :: WORD -> SGR -> WORD -> WORD
-applyANSISGRToAttribute def sgr attribute = case sgr of
-  Reset -> def
-  SetConsoleIntensity intensity -> case intensity of
-    BoldIntensity   -> attribute .|. iNTENSITY
-    FaintIntensity  -> attribute .&. (complement iNTENSITY) -- Not supported
-    NormalIntensity -> attribute .&. (complement iNTENSITY)
-  SetItalicized _ -> attribute -- Not supported
-  SetUnderlining underlining -> case underlining of
-    NoUnderline -> attribute .&. (complement cOMMON_LVB_UNDERSCORE)
-    _           -> attribute .|. cOMMON_LVB_UNDERSCORE -- Not supported, since
-    -- cOMMON_LVB_UNDERSCORE seems to have no effect
-  SetBlinkSpeed _ -> attribute -- Not supported
-  SetVisible _    -> attribute -- Not supported
-  -- The cOMMON_LVB_REVERSE_VIDEO doesn't actually appear to have any affect
-  -- on the colors being displayed, so the emulator just uses it to carry
-  -- information and implements the color-swapping behaviour itself. Bit of a
-  -- hack, I guess :-)
-  SetSwapForegroundBackground True ->
-    -- Check if the color-swapping flag is already set
-    if attribute .&. cOMMON_LVB_REVERSE_VIDEO /= 0
-      then attribute
-      else swapForegroundBackgroundColors attribute .|. cOMMON_LVB_REVERSE_VIDEO
-  SetSwapForegroundBackground False ->
-    -- Check if the color-swapping flag is already not set
-    if attribute .&. cOMMON_LVB_REVERSE_VIDEO == 0
-      then attribute
-      else swapForegroundBackgroundColors attribute .&.
-          (complement cOMMON_LVB_REVERSE_VIDEO)
-  SetColor Foreground Dull color  -> applyForegroundANSIColorToAttribute color
-    (attribute .&. (complement fOREGROUND_INTENSITY))
-  SetColor Foreground Vivid color -> applyForegroundANSIColorToAttribute color
-    (attribute .|. fOREGROUND_INTENSITY)
-  SetColor Background Dull color  -> applyBackgroundANSIColorToAttribute color
-    (attribute .&. (complement bACKGROUND_INTENSITY))
-  SetColor Background Vivid color -> applyBackgroundANSIColorToAttribute color
-    (attribute .|. bACKGROUND_INTENSITY)
-  SetRGBColor Foreground color ->
-    let (colorIntensity, aNSIColor) = toANSIColor color
-        attribute' = case colorIntensity of
-          Dull  -> attribute .&. complement fOREGROUND_INTENSITY
-          Vivid -> attribute .|. fOREGROUND_INTENSITY
-    in applyForegroundANSIColorToAttribute aNSIColor attribute'
-  SetRGBColor Background color ->
-    let (colorIntensity, aNSIColor) = toANSIColor color
-        attribute' = case colorIntensity of
-          Dull  -> attribute .&. complement bACKGROUND_INTENSITY
-          Vivid -> attribute .|. bACKGROUND_INTENSITY
-    in applyBackgroundANSIColorToAttribute aNSIColor attribute'
- where
-  iNTENSITY = fOREGROUND_INTENSITY
-
-hSetSGR cds h sgr
-  = emulatorFallback (Unix.hSetSGR h sgr) $ withHandle h $ \handle -> do
-      screen_buffer_info <- getConsoleScreenBufferInfo handle
-      let attribute  = csbi_attributes screen_buffer_info
-          def        =     defaultForegroundAttributes cds
-                       .|. defaultBackgroundAttributes cds
-          attribute' = foldl' (flip $ applyANSISGRToAttribute def) attribute
-            -- make [] equivalent to [Reset], as documented
-            (if null sgr then [Reset] else sgr)
-      setConsoleTextAttribute handle attribute'
-
-hChangeCursorVisibility :: HANDLE -> Bool -> IO ()
-hChangeCursorVisibility handle cursor_visible = do
-  cursor_info <- getConsoleCursorInfo handle
-  setConsoleCursorInfo handle
-    (cursor_info { cci_cursor_visible = cursor_visible })
-
-hHideCursor h
-  = emulatorFallback (Unix.hHideCursor h) $ withHandle h $
-      \handle -> hChangeCursorVisibility handle False
-hShowCursor h
-  = emulatorFallback (Unix.hShowCursor h) $ withHandle h $
-      \handle -> hChangeCursorVisibility handle True
-
--- Windows only supports setting the terminal title on a process-wide basis, so
--- for now we will assume that that is what the user intended. This will fail if
--- they are sending the command over e.g. a network link... but that's not
--- really what I'm designing for.
-hSetTitle h title
-  = emulatorFallback (Unix.hSetTitle h title) $
-      withTString title $ setConsoleTitle
-
-cursorPositionRef :: IORef (Map.Map HANDLE COORD)
-{-# NOINLINE cursorPositionRef #-}
-cursorPositionRef = unsafePerformIO $ newIORef Map.empty
-
-hSaveCursor h
-  = emulatorFallback (Unix.hSaveCursor h) $ withHandle h $ \handle -> do
-      screen_buffer_info <- getConsoleScreenBufferInfo handle
-      m <- readIORef cursorPositionRef
-      writeIORef cursorPositionRef
-        (Map.insert handle (csbi_cursor_position screen_buffer_info) m)
-
-hRestoreCursor h
-  = emulatorFallback (Unix.hRestoreCursor h) $ withHandle h $ \handle -> do
-      m <- readIORef cursorPositionRef
-      let result = Map.lookup handle m
-      forM_ result (setConsoleCursorPosition handle)
-
-hReportCursorPosition h
-  = emulatorFallback (Unix.hReportCursorPosition h) $ withHandle h $
-      \handle -> do
-        result <- getConsoleScreenBufferInfo handle
-        let (COORD cx cy) = csbi_cursor_position result
-            window = csbi_window result
-            x = cx - rect_left window + 1
-            y = cy - rect_top window + 1
-        hIn <- getStdHandle sTD_INPUT_HANDLE
-        _ <- writeConsoleInput hIn $ keyPresses $
-            "\ESC[" ++ show y ++ ";" ++ show x ++ "R"
-        return ()
-
-keyPress :: Char -> [INPUT_RECORD]
-keyPress c = [keyDown, keyUp]
- where
-  keyDown = key True
-  keyUp   = key False
-  c' = UnicodeAsciiChar $ charToWCHAR c
-  key isDown = INPUT_RECORD kEY_EVENT $
-    InputKeyEvent (KEY_EVENT_RECORD isDown 1 0 0 c' 0)
-
-keyPresses :: String -> [INPUT_RECORD]
-keyPresses = concatMap keyPress
-
-aNSIColors :: [((ColorIntensity, Color), Colour Float)]
-aNSIColors = [ ((Dull,  Black),   black)
-             , ((Dull,  Blue),    navy)
-             , ((Dull,  Green),   green)
-             , ((Dull,  Cyan),    teal)
-             , ((Dull,  Red),     maroon)
-             , ((Dull,  Magenta), purple)
-             , ((Dull,  Yellow),  olive)
-             , ((Dull,  White),   silver)
-             , ((Vivid, Black),   grey)
-             , ((Vivid, Blue),    blue)
-             , ((Vivid, Green),   lime)
-             , ((Vivid, Cyan),    cyan)
-             , ((Vivid, Red),     red)
-             , ((Vivid, Magenta), magenta)
-             , ((Vivid, Yellow),  yellow)
-             , ((Vivid, White),   white) ]
-
-toANSIColor :: Colour Float -> (ColorIntensity, Color)
-toANSIColor color = fst $ minimumBy order aNSIColors
- where
-  RGB r g b = toSRGB color
-  order (_, c1) (_, c2) = compare (dist c1) (dist c2)
-  dist c = let RGB r' g' b' = toSRGB c
-               dr = r' - r
-               dg = g' - g
-               db = b' - b
-           in  dr * dr + dg * dg + db * db
-
--- getReportedCursorPosition :: IO String
--- (See Common-Include.hs for Haddock documentation)
-getReportedCursorPosition
-  = catch getReportedCursorPosition' getCPExceptionHandler
- where
-  getReportedCursorPosition' = withHandleToHANDLE stdin action
-   where
-    action hdl = do
-      n <- getNumberOfConsoleInputEvents hdl
-      if n == 0
-        then return ""
-        else do
-          es <- readConsoleInput hdl n
-          return $ stringFromInputEvents es
-    stringFromInputEvents = cWcharsToChars . wCharsFromInputEvents
-    wCharsFromInputEvents = mapMaybe wCharFromInputEvent
-    wCharFromInputEvent e = if isKeyDownEvent
-      then Just (unicodeAsciiChar $ keyEventChar keyEventRecord)
-      else Nothing
-     where
-      eventType = inputEventType e
-      InputKeyEvent keyEventRecord = inputEvent e
-      isKeyDown = keyEventKeyDown keyEventRecord
-      isKeyDownEvent = eventType == 1 && isKeyDown
-
--- getCursorPosition :: IO (Maybe (Int, Int))
--- (See Common-Include.hs for Haddock documentation)
-getCursorPosition = catch getCursorPosition' getCPExceptionHandler
- where
-  getCursorPosition' = do
-    withHandleToHANDLE stdin flush -- Flush the console input buffer
-    reportCursorPosition
-    hFlush stdout -- ensure the report cursor position code is sent to the
-                  -- operating system
-    input <- getReportedCursorPosition
-    case readP_to_S cursorPosition input of
-      [] -> return Nothing
-      [((row, col),_)] -> return $ Just (row, col)
-      (_:_) -> return Nothing
-   where
-    flush hdl = do
-      n <- getNumberOfConsoleInputEvents hdl
-      unless (n == 0) (void $ readConsoleInput hdl n)
-
-getCPExceptionHandler :: IOException -> IO a
-getCPExceptionHandler e = error msg
- where
-  msg = "Error: " ++ show e ++ "\nThis error may be avoided by using a " ++
-        "console based on the Win32 console of the Windows API, such as " ++
-        "Command Prompt or PowerShell."
+{-# OPTIONS_HADDOCK hide #-}
+
+module System.Console.ANSI.Windows.Emulator
+  (
+#include "Exports-Include.hs"
+  ) where
+
+import Control.Exception (catch, catchJust, IOException)
+import Control.Monad (forM_, unless)
+import Data.Bits ((.&.), (.|.), complement, shiftL, shiftR)
+import Data.IORef (IORef, newIORef, readIORef, writeIORef)
+import Data.List (foldl', minimumBy)
+import Data.Maybe (mapMaybe)
+import qualified Data.Map.Strict as Map (Map, empty, insert, lookup)
+import System.IO (Handle, hFlush, hIsTerminalDevice, stdin, stdout)
+import System.IO.Unsafe (unsafePerformIO)
+import Text.ParserCombinators.ReadP (readP_to_S)
+
+import Data.Colour (Colour)
+import Data.Colour.Names (black, blue, cyan, green, grey, lime, magenta, maroon,
+  navy, olive, purple, red, silver, teal, white, yellow)
+import Data.Colour.SRGB (RGB (..), toSRGB)
+
+import System.Console.ANSI.Types
+import qualified System.Console.ANSI.Unix as Unix
+import System.Console.ANSI.Windows.Detect
+import System.Console.ANSI.Windows.Emulator.Codes
+import System.Console.ANSI.Windows.Foreign
+
+-- This file contains code that is common to modules System.Console.ANSI.Unix,
+-- System.Console.ANSI.Windows and System.Console.ANSI.Windows.Emulator, such as
+-- type signatures and the definition of functions specific to stdout in terms
+-- of the corresponding more general functions, inclduding the related Haddock
+-- documentation.
+#include "Common-Include.hs"
+-- This file contains code that is required in the case of the module
+-- System.Console.ANSI.Windows.Emulator and differs from the common code in
+-- file Common-Include-Enabled.hs.
+#include "Common-Include-Emulator.hs"
+
+withHandle :: Handle -> (HANDLE -> IO a) -> IO a
+withHandle handle action = do
+  -- It's VERY IMPORTANT that we flush before issuing any sort of Windows API
+  -- call to change the console because on Windows the arrival of
+  -- API-initiated state changes is not necessarily synchronised with that of
+  -- the text they are attempting to modify.
+  hFlush handle
+  withHandleToHANDLE handle action
+
+-- Unfortunately, the emulator is not perfect. In particular, it has a tendency
+-- to die with exceptions about invalid handles when it is used with certain
+-- Windows consoles (e.g. mintty, terminator, or cygwin sshd).
+--
+-- This happens because in those environments the stdout family of handles are
+-- not actually associated with a real console.
+--
+-- My observation is that every time I've seen this in practice, the handle we
+-- have instead of the actual console handle is there so that the terminal
+-- supports ANSI escape codes. So 99% of the time, the correct thing to do is
+-- just to fall back on the Unix module to output the ANSI codes and hope for
+-- the best.
+emulatorFallback :: IO a -> IO a -> IO a
+emulatorFallback fallback first_try
+  = catchJust invalidHandle first_try (const fallback)
+ where
+  invalidHandle (ConsoleException 6) = Just ()  -- 6 is the Windows error code
+                                                -- for invalid handles
+  invalidHandle (_)                  = Nothing
+
+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'
+
+hCursorUp h n
+  = emulatorFallback (Unix.hCursorUp h n) $ withHandle h $
+      \handle -> adjustCursorPosition handle (\_ x -> x)
+                   (\_ y -> y - fromIntegral n)
+hCursorDown h n
+  = emulatorFallback (Unix.hCursorDown h n) $ withHandle h $
+      \handle -> adjustCursorPosition handle (\_ x -> x)
+                   (\_ y -> y + fromIntegral n)
+hCursorForward h n
+  = emulatorFallback (Unix.hCursorForward h n) $ withHandle h $
+      \handle -> adjustCursorPosition handle (\_ x -> x + fromIntegral n)
+                   (\_ y -> y)
+hCursorBackward h n
+  = emulatorFallback (Unix.hCursorBackward h n) $ withHandle h $
+      \handle -> adjustCursorPosition handle (\_ x -> x - fromIntegral n)
+                   (\_ y -> y)
+
+adjustLine :: HANDLE -> (SHORT -> SHORT -> SHORT) -> IO ()
+adjustLine handle change_y
+  = adjustCursorPosition handle (\window_left _ -> window_left) change_y
+
+hCursorDownLine h n
+  = emulatorFallback (Unix.hCursorDownLine h n) $ withHandle h $
+      \handle -> adjustLine handle (\_ y -> y + fromIntegral n)
+
+hCursorUpLine h n
+  = emulatorFallback (Unix.hCursorUpLine h n) $ withHandle h $
+      \handle -> adjustLine handle (\_ y -> y - fromIntegral n)
+
+hSetCursorColumn h x
+  = emulatorFallback (Unix.hSetCursorColumn h x) $ withHandle h $
+      \handle -> adjustCursorPosition handle
+                   (\window_left _ -> window_left + fromIntegral x) (\_ y -> y)
+
+hSetCursorPosition h y x
+  = emulatorFallback (Unix.hSetCursorPosition h y x) $ withHandle h $
+      \handle -> adjustCursorPosition handle
+                   (\window_left _ -> window_left + fromIntegral x)
+                   (\window_top _ -> window_top + fromIntegral y)
+
+clearChar :: WCHAR
+clearChar = charToWCHAR ' '
+
+-- | The 'clear' attribute is equated with the default background attributes.
+clearAttribute :: ConsoleDefaultState -> WORD
+clearAttribute = defaultBackgroundAttributes
+
+hClearScreenFraction
+  :: ConsoleDefaultState
+  -> HANDLE
+  -> (SMALL_RECT -> COORD -> (SHORT, SHORT, SHORT, SHORT, SHORT, SHORT))
+  -> IO ()
+hClearScreenFraction cds handle fraction_finder = do
+  screen_buffer_info <- getConsoleScreenBufferInfo handle
+  let window = csbi_window screen_buffer_info
+      cursor_pos = csbi_cursor_position screen_buffer_info
+      (left, top, right, bottom, start_x, end_x)
+          = fraction_finder window cursor_pos
+  mapM_ (fill_line left top right bottom start_x end_x) [top .. bottom]
+ where
+  fill_line left top right bottom start_x end_x y = do
+    let left'  = if y == top    then start_x else left
+        right' = if y == bottom then end_x   else right
+        fill_cursor_pos = COORD left' y
+        fill_length = fromIntegral $ right' - left' + 1
+    _ <- fillConsoleOutputCharacter handle clearChar fill_length fill_cursor_pos
+    fillConsoleOutputAttribute handle (clearAttribute cds) fill_length
+      fill_cursor_pos
+
+hClearFromCursorToScreenEnd cds h
+  = emulatorFallback (Unix.hClearFromCursorToScreenEnd h) $ withHandle h $
+      \handle -> hClearScreenFraction cds handle go
+ where
+  go window cursor_pos = (left, top, right, bottom, start_x, right)
+   where
+    SMALL_RECT (COORD left _) (COORD right bottom) = window
+    COORD start_x top = cursor_pos
+
+hClearFromCursorToScreenBeginning cds h
+  = emulatorFallback (Unix.hClearFromCursorToScreenBeginning h) $ withHandle h $
+      \handle -> hClearScreenFraction cds handle go
+ where
+  go window cursor_pos = (left, top, right, bottom, left, end_x)
+   where
+    SMALL_RECT (COORD left top) (COORD right _) = window
+    COORD end_x bottom = cursor_pos
+
+hClearScreen cds h
+  = emulatorFallback (Unix.hClearScreen h) $ withHandle h $
+      \handle -> hClearScreenFraction cds handle go
+ where
+  go window _ = (left, top, right, bottom, left, right)
+   where
+    SMALL_RECT (COORD left top) (COORD right bottom) = window
+
+hClearFromCursorToLineEnd cds h
+  = emulatorFallback (Unix.hClearFromCursorToLineEnd h) $ withHandle h $
+      \handle -> hClearScreenFraction cds handle go
+ where
+  go window cursor_pos = (left, y, right, y, start_x, right)
+   where
+    SMALL_RECT (COORD left _) (COORD right _) = window
+    COORD start_x y = cursor_pos
+
+hClearFromCursorToLineBeginning cds h
+  = emulatorFallback (Unix.hClearFromCursorToLineBeginning h) $ withHandle h $
+        \handle -> hClearScreenFraction cds handle go
+ where
+  go window cursor_pos = (left, y, right, y, left, end_x)
+   where
+    SMALL_RECT (COORD left _) (COORD right _) = window
+    COORD end_x y = cursor_pos
+
+hClearLine cds h
+  = emulatorFallback (Unix.hClearLine h) $ withHandle h $
+      \handle -> hClearScreenFraction cds handle go
+ where
+  go window cursor_pos = (left, y, right, y, left, right)
+   where
+    SMALL_RECT (COORD left _) (COORD right _) = window
+    COORD _ y = cursor_pos
+
+hScrollPage
+  :: ConsoleDefaultState -- ^ The default console state
+  -> HANDLE
+  -> Int
+  -> IO ()
+hScrollPage cds handle new_origin_y = do
+  screen_buffer_info <- getConsoleScreenBufferInfo handle
+  let fill = CHAR_INFO clearChar (clearAttribute cds)
+      window = csbi_window screen_buffer_info
+      origin = COORD (rect_left window)
+                     (rect_top window + fromIntegral new_origin_y)
+  scrollConsoleScreenBuffer handle window Nothing origin fill
+
+hScrollPageUp cds h n
+  = emulatorFallback (Unix.hScrollPageUp h n) $ withHandle h $
+      \handle -> hScrollPage cds handle (negate n)
+
+hScrollPageDown cds h n
+  = emulatorFallback (Unix.hScrollPageDown h n) $ withHandle h $
+      \handle -> hScrollPage cds handle n
+
+{-# INLINE applyANSIColorToAttribute #-}
+applyANSIColorToAttribute :: WORD -> WORD -> WORD -> Color -> WORD -> WORD
+applyANSIColorToAttribute rED gREEN bLUE color attribute = case color of
+  Black   -> attribute'
+  Red     -> attribute' .|. rED
+  Green   -> attribute' .|. gREEN
+  Yellow  -> attribute' .|. rED .|. gREEN
+  Blue    -> attribute' .|. bLUE
+  Magenta -> attribute' .|. rED .|. bLUE
+  Cyan    -> attribute' .|. gREEN .|. bLUE
+  White   -> attribute' .|. wHITE
+ where
+  wHITE = rED .|. gREEN .|. bLUE
+  attribute' = attribute .&. (complement wHITE)
+
+applyForegroundANSIColorToAttribute, applyBackgroundANSIColorToAttribute
+  :: Color
+  -> WORD
+  -> WORD
+applyForegroundANSIColorToAttribute
+  = applyANSIColorToAttribute fOREGROUND_RED fOREGROUND_GREEN fOREGROUND_BLUE
+applyBackgroundANSIColorToAttribute
+  = applyANSIColorToAttribute bACKGROUND_RED bACKGROUND_GREEN bACKGROUND_BLUE
+
+swapForegroundBackgroundColors :: WORD -> WORD
+swapForegroundBackgroundColors attribute
+  = clean_attribute .|. foreground_attribute' .|. background_attribute'
+ where
+  foreground_attribute = attribute .&. fOREGROUND_INTENSE_WHITE
+  background_attribute = attribute .&. bACKGROUND_INTENSE_WHITE
+  clean_attribute = attribute .&. complement
+    (fOREGROUND_INTENSE_WHITE .|. bACKGROUND_INTENSE_WHITE)
+  foreground_attribute' = background_attribute `shiftR` 4
+  background_attribute' = foreground_attribute `shiftL` 4
+
+applyANSISGRToAttribute :: WORD -> SGR -> WORD -> WORD
+applyANSISGRToAttribute def sgr attribute = case sgr of
+  Reset -> def
+  SetConsoleIntensity intensity -> case intensity of
+    BoldIntensity   -> attribute .|. iNTENSITY
+    FaintIntensity  -> attribute .&. (complement iNTENSITY) -- Not supported
+    NormalIntensity -> attribute .&. (complement iNTENSITY)
+  SetItalicized _ -> attribute -- Not supported
+  SetUnderlining underlining -> case underlining of
+    NoUnderline -> attribute .&. (complement cOMMON_LVB_UNDERSCORE)
+    _           -> attribute .|. cOMMON_LVB_UNDERSCORE -- Not supported, since
+    -- cOMMON_LVB_UNDERSCORE seems to have no effect
+  SetBlinkSpeed _ -> attribute -- Not supported
+  SetVisible _    -> attribute -- Not supported
+  -- The cOMMON_LVB_REVERSE_VIDEO doesn't actually appear to have any affect
+  -- on the colors being displayed, so the emulator just uses it to carry
+  -- information and implements the color-swapping behaviour itself. Bit of a
+  -- hack, I guess :-)
+  SetSwapForegroundBackground True ->
+    -- Check if the color-swapping flag is already set
+    if attribute .&. cOMMON_LVB_REVERSE_VIDEO /= 0
+      then attribute
+      else swapForegroundBackgroundColors attribute .|. cOMMON_LVB_REVERSE_VIDEO
+  SetSwapForegroundBackground False ->
+    -- Check if the color-swapping flag is already not set
+    if attribute .&. cOMMON_LVB_REVERSE_VIDEO == 0
+      then attribute
+      else swapForegroundBackgroundColors attribute .&.
+          (complement cOMMON_LVB_REVERSE_VIDEO)
+  SetColor Foreground Dull color  -> applyForegroundANSIColorToAttribute color
+    (attribute .&. (complement fOREGROUND_INTENSITY))
+  SetColor Foreground Vivid color -> applyForegroundANSIColorToAttribute color
+    (attribute .|. fOREGROUND_INTENSITY)
+  SetColor Background Dull color  -> applyBackgroundANSIColorToAttribute color
+    (attribute .&. (complement bACKGROUND_INTENSITY))
+  SetColor Background Vivid color -> applyBackgroundANSIColorToAttribute color
+    (attribute .|. bACKGROUND_INTENSITY)
+  SetRGBColor Foreground color ->
+    let (colorIntensity, aNSIColor) = toANSIColor color
+        attribute' = case colorIntensity of
+          Dull  -> attribute .&. complement fOREGROUND_INTENSITY
+          Vivid -> attribute .|. fOREGROUND_INTENSITY
+    in applyForegroundANSIColorToAttribute aNSIColor attribute'
+  SetRGBColor Background color ->
+    let (colorIntensity, aNSIColor) = toANSIColor color
+        attribute' = case colorIntensity of
+          Dull  -> attribute .&. complement bACKGROUND_INTENSITY
+          Vivid -> attribute .|. bACKGROUND_INTENSITY
+    in applyBackgroundANSIColorToAttribute aNSIColor attribute'
+ where
+  iNTENSITY = fOREGROUND_INTENSITY
+
+hSetSGR cds h sgr
+  = emulatorFallback (Unix.hSetSGR h sgr) $ withHandle h $ \handle -> do
+      screen_buffer_info <- getConsoleScreenBufferInfo handle
+      let attribute  = csbi_attributes screen_buffer_info
+          def        =     defaultForegroundAttributes cds
+                       .|. defaultBackgroundAttributes cds
+          attribute' = foldl' (flip $ applyANSISGRToAttribute def) attribute
+            -- make [] equivalent to [Reset], as documented
+            (if null sgr then [Reset] else sgr)
+      setConsoleTextAttribute handle attribute'
+
+hChangeCursorVisibility :: HANDLE -> Bool -> IO ()
+hChangeCursorVisibility handle cursor_visible = do
+  cursor_info <- getConsoleCursorInfo handle
+  setConsoleCursorInfo handle
+    (cursor_info { cci_cursor_visible = cursor_visible })
+
+hHideCursor h
+  = emulatorFallback (Unix.hHideCursor h) $ withHandle h $
+      \handle -> hChangeCursorVisibility handle False
+hShowCursor h
+  = emulatorFallback (Unix.hShowCursor h) $ withHandle h $
+      \handle -> hChangeCursorVisibility handle True
+
+-- Windows only supports setting the terminal title on a process-wide basis, so
+-- for now we will assume that that is what the user intended. This will fail if
+-- they are sending the command over e.g. a network link... but that's not
+-- really what I'm designing for.
+hSetTitle h title
+  = emulatorFallback (Unix.hSetTitle h title) $
+      withTString title $ setConsoleTitle
+
+cursorPositionRef :: IORef (Map.Map HANDLE COORD)
+{-# NOINLINE cursorPositionRef #-}
+cursorPositionRef = unsafePerformIO $ newIORef Map.empty
+
+hSaveCursor h
+  = emulatorFallback (Unix.hSaveCursor h) $ withHandle h $ \handle -> do
+      screen_buffer_info <- getConsoleScreenBufferInfo handle
+      m <- readIORef cursorPositionRef
+      writeIORef cursorPositionRef
+        (Map.insert handle (csbi_cursor_position screen_buffer_info) m)
+
+hRestoreCursor h
+  = emulatorFallback (Unix.hRestoreCursor h) $ withHandle h $ \handle -> do
+      m <- readIORef cursorPositionRef
+      let result = Map.lookup handle m
+      forM_ result (setConsoleCursorPosition handle)
+
+hReportCursorPosition h
+  = emulatorFallback (Unix.hReportCursorPosition h) $ withHandle h $
+      \handle -> do
+        result <- getConsoleScreenBufferInfo handle
+        let (COORD cx cy) = csbi_cursor_position result
+            window = csbi_window result
+            x = cx - rect_left window + 1
+            y = cy - rect_top window + 1
+        hIn <- getStdHandle sTD_INPUT_HANDLE
+        _ <- writeConsoleInput hIn $ keyPresses $
+            "\ESC[" ++ show y ++ ";" ++ show x ++ "R"
+        return ()
+
+keyPress :: Char -> [INPUT_RECORD]
+keyPress c = [keyDown, keyUp]
+ where
+  keyDown = key True
+  keyUp   = key False
+  c' = UnicodeAsciiChar $ charToWCHAR c
+  key isDown = INPUT_RECORD kEY_EVENT $
+    InputKeyEvent (KEY_EVENT_RECORD isDown 1 0 0 c' 0)
+
+keyPresses :: String -> [INPUT_RECORD]
+keyPresses = concatMap keyPress
+
+aNSIColors :: [((ColorIntensity, Color), Colour Float)]
+aNSIColors = [ ((Dull,  Black),   black)
+             , ((Dull,  Blue),    navy)
+             , ((Dull,  Green),   green)
+             , ((Dull,  Cyan),    teal)
+             , ((Dull,  Red),     maroon)
+             , ((Dull,  Magenta), purple)
+             , ((Dull,  Yellow),  olive)
+             , ((Dull,  White),   silver)
+             , ((Vivid, Black),   grey)
+             , ((Vivid, Blue),    blue)
+             , ((Vivid, Green),   lime)
+             , ((Vivid, Cyan),    cyan)
+             , ((Vivid, Red),     red)
+             , ((Vivid, Magenta), magenta)
+             , ((Vivid, Yellow),  yellow)
+             , ((Vivid, White),   white) ]
+
+toANSIColor :: Colour Float -> (ColorIntensity, Color)
+toANSIColor color = fst $ minimumBy order aNSIColors
+ where
+  RGB r g b = toSRGB color
+  order (_, c1) (_, c2) = compare (dist c1) (dist c2)
+  dist c = let RGB r' g' b' = toSRGB c
+               dr = r' - r
+               dg = g' - g
+               db = b' - b
+           in  dr * dr + dg * dg + db * db
+
+-- getReportedCursorPosition :: IO String
+-- (See Common-Include.hs for Haddock documentation)
+getReportedCursorPosition
+  = catch getReportedCursorPosition' getCPExceptionHandler
+ where
+  getReportedCursorPosition' = withHandleToHANDLE stdin action
+   where
+    action hdl = do
+      n <- getNumberOfConsoleInputEvents hdl
+      if n == 0
+        then return ""
+        else do
+          es <- readConsoleInput hdl n
+          return $ stringFromInputEvents es
+    stringFromInputEvents = cWcharsToChars . wCharsFromInputEvents
+    wCharsFromInputEvents = mapMaybe wCharFromInputEvent
+    wCharFromInputEvent e = if isKeyDownEvent
+      then Just (unicodeAsciiChar $ keyEventChar keyEventRecord)
+      else Nothing
+     where
+      eventType = inputEventType e
+      InputKeyEvent keyEventRecord = inputEvent e
+      isKeyDown = keyEventKeyDown keyEventRecord
+      isKeyDownEvent = eventType == 1 && isKeyDown
+
+-- getCursorPosition :: IO (Maybe (Int, Int))
+-- (See Common-Include.hs for Haddock documentation)
+getCursorPosition = catch getCursorPosition' getCPExceptionHandler
+ where
+  getCursorPosition' = do
+    withHandleToHANDLE stdin flush -- Flush the console input buffer
+    reportCursorPosition
+    hFlush stdout -- ensure the report cursor position code is sent to the
+                  -- operating system
+    input <- getReportedCursorPosition
+    case readP_to_S cursorPosition input of
+      [] -> return Nothing
+      [((row, col),_)] -> return $ Just (row, col)
+      (_:_) -> return Nothing
+   where
+    flush hdl = do
+      n <- getNumberOfConsoleInputEvents hdl
+      unless (n == 0) (void $ readConsoleInput hdl n)
+
+getCPExceptionHandler :: IOException -> IO a
+getCPExceptionHandler e = error msg
+ where
+  msg = "Error: " ++ show e ++ "\nThis error may be avoided by using a " ++
+        "console based on the Win32 console of the Windows API, such as " ++
+        "Command Prompt or PowerShell."
diff --git a/System/Console/ANSI/Windows/Emulator/Codes.hs b/System/Console/ANSI/Windows/Emulator/Codes.hs
--- a/System/Console/ANSI/Windows/Emulator/Codes.hs
+++ b/System/Console/ANSI/Windows/Emulator/Codes.hs
@@ -1,94 +1,94 @@
-{-# OPTIONS_HADDOCK hide #-}
-
-module System.Console.ANSI.Windows.Emulator.Codes
-  (
-    -- * Cursor movement by character
-    cursorUpCode, cursorDownCode, cursorForwardCode, cursorBackwardCode
-
-    -- * Cursor movement by line
-  , cursorUpLineCode, cursorDownLineCode
-
-    -- * Directly changing cursor position
-  , setCursorColumnCode, setCursorPositionCode
-
-    -- * Saving, restoring and reporting cursor position
-  , saveCursorCode, restoreCursorCode, reportCursorPositionCode
-
-    -- * Clearing parts of the screen
-  , clearFromCursorToScreenEndCode, clearFromCursorToScreenBeginningCode
-  , clearScreenCode, clearFromCursorToLineEndCode
-  , clearFromCursorToLineBeginningCode, clearLineCode
-
-    -- * Scrolling the screen
-  , scrollPageUpCode, scrollPageDownCode
-
-    -- * Select Graphic Rendition mode: colors and other whizzy stuff
-  , setSGRCode
-
-    -- * Cursor visibilty changes
-  , hideCursorCode, showCursorCode
-
-    -- * Changing the title
-  , setTitleCode
-  ) where
-
-import System.Console.ANSI.Types
-
-cursorUpCode, cursorDownCode, cursorForwardCode, cursorBackwardCode
-  :: Int -- ^ Number of lines or characters to move
-  -> String
-cursorUpCode _       = ""
-cursorDownCode _     = ""
-cursorForwardCode _  = ""
-cursorBackwardCode _ = ""
-
-cursorDownLineCode, cursorUpLineCode :: Int -- ^ Number of lines to move
-                                     -> String
-cursorDownLineCode _ = ""
-cursorUpLineCode _   = ""
-
-setCursorColumnCode :: Int -- ^ 0-based column to move to
-                    -> String
-setCursorColumnCode _ = ""
-
-setCursorPositionCode :: Int -- ^ 0-based row to move to
-                      -> Int -- ^ 0-based column to move to
-                      -> String
-setCursorPositionCode _ _ = ""
-
-saveCursorCode, restoreCursorCode, reportCursorPositionCode :: String
-saveCursorCode = ""
-restoreCursorCode = ""
-reportCursorPositionCode = ""
-
-clearFromCursorToScreenEndCode, clearFromCursorToScreenBeginningCode,
-  clearScreenCode :: String
-clearFromCursorToLineEndCode, clearFromCursorToLineBeginningCode,
-  clearLineCode :: String
-
-clearFromCursorToScreenEndCode       = ""
-clearFromCursorToScreenBeginningCode = ""
-clearScreenCode                      = ""
-clearFromCursorToLineEndCode         = ""
-clearFromCursorToLineBeginningCode   = ""
-clearLineCode                        = ""
-
-scrollPageUpCode, scrollPageDownCode :: Int -- ^ Number of lines to scroll by
-                                     -> String
-scrollPageUpCode _   = ""
-scrollPageDownCode _ = ""
-
-setSGRCode :: [SGR] -- ^ Commands: these will typically be applied on top of the
-                    -- current console SGR mode. An empty list of commands is
-                    -- equivalent to the list @[Reset]@. Commands are applied
-                    -- left to right.
-           -> String
-setSGRCode _ = ""
-
-hideCursorCode, showCursorCode :: String
-hideCursorCode = ""
-showCursorCode = ""
-
-setTitleCode :: String -- ^ New title
-             -> String
-setTitleCode _ = ""
+{-# OPTIONS_HADDOCK hide #-}
+
+module System.Console.ANSI.Windows.Emulator.Codes
+  (
+    -- * Cursor movement by character
+    cursorUpCode, cursorDownCode, cursorForwardCode, cursorBackwardCode
+
+    -- * Cursor movement by line
+  , cursorUpLineCode, cursorDownLineCode
+
+    -- * Directly changing cursor position
+  , setCursorColumnCode, setCursorPositionCode
+
+    -- * Saving, restoring and reporting cursor position
+  , saveCursorCode, restoreCursorCode, reportCursorPositionCode
+
+    -- * Clearing parts of the screen
+  , clearFromCursorToScreenEndCode, clearFromCursorToScreenBeginningCode
+  , clearScreenCode, clearFromCursorToLineEndCode
+  , clearFromCursorToLineBeginningCode, clearLineCode
+
+    -- * Scrolling the screen
+  , scrollPageUpCode, scrollPageDownCode
+
+    -- * Select Graphic Rendition mode: colors and other whizzy stuff
+  , setSGRCode
+
+    -- * Cursor visibilty changes
+  , hideCursorCode, showCursorCode
+
+    -- * Changing the title
+  , setTitleCode
+  ) where
+
+import System.Console.ANSI.Types
+
+cursorUpCode, cursorDownCode, cursorForwardCode, cursorBackwardCode
+  :: Int -- ^ Number of lines or characters to move
+  -> String
+cursorUpCode _       = ""
+cursorDownCode _     = ""
+cursorForwardCode _  = ""
+cursorBackwardCode _ = ""
+
+cursorDownLineCode, cursorUpLineCode :: Int -- ^ Number of lines to move
+                                     -> String
+cursorDownLineCode _ = ""
+cursorUpLineCode _   = ""
+
+setCursorColumnCode :: Int -- ^ 0-based column to move to
+                    -> String
+setCursorColumnCode _ = ""
+
+setCursorPositionCode :: Int -- ^ 0-based row to move to
+                      -> Int -- ^ 0-based column to move to
+                      -> String
+setCursorPositionCode _ _ = ""
+
+saveCursorCode, restoreCursorCode, reportCursorPositionCode :: String
+saveCursorCode = ""
+restoreCursorCode = ""
+reportCursorPositionCode = ""
+
+clearFromCursorToScreenEndCode, clearFromCursorToScreenBeginningCode,
+  clearScreenCode :: String
+clearFromCursorToLineEndCode, clearFromCursorToLineBeginningCode,
+  clearLineCode :: String
+
+clearFromCursorToScreenEndCode       = ""
+clearFromCursorToScreenBeginningCode = ""
+clearScreenCode                      = ""
+clearFromCursorToLineEndCode         = ""
+clearFromCursorToLineBeginningCode   = ""
+clearLineCode                        = ""
+
+scrollPageUpCode, scrollPageDownCode :: Int -- ^ Number of lines to scroll by
+                                     -> String
+scrollPageUpCode _   = ""
+scrollPageDownCode _ = ""
+
+setSGRCode :: [SGR] -- ^ Commands: these will typically be applied on top of the
+                    -- current console SGR mode. An empty list of commands is
+                    -- equivalent to the list @[Reset]@. Commands are applied
+                    -- left to right.
+           -> String
+setSGRCode _ = ""
+
+hideCursorCode, showCursorCode :: String
+hideCursorCode = ""
+showCursorCode = ""
+
+setTitleCode :: String -- ^ New title
+             -> String
+setTitleCode _ = ""
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
@@ -1,718 +1,731 @@
-{-# OPTIONS_HADDOCK hide #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-
--- | "System.Win32.Console" is really very impoverished, so I have had to do all
--- the FFI myself.
-module System.Console.ANSI.Windows.Foreign
-  (
-    -- Re-exports from Win32.Types
-    BOOL, WORD, DWORD, WCHAR, HANDLE, iNVALID_HANDLE_VALUE, nullHANDLE, SHORT,
-
-    -- 'Re-exports from System.Win32.Console.Extra'
-    INPUT_RECORD (..), INPUT_RECORD_EVENT (..), kEY_EVENT,
-    KEY_EVENT_RECORD (..), UNICODE_ASCII_CHAR (..), writeConsoleInput,
-    getNumberOfConsoleInputEvents, readConsoleInput,
-
-    charToWCHAR, cWcharsToChars,
-
-    COORD(..), SMALL_RECT(..), rect_top, rect_bottom, rect_left, rect_right,
-    rect_width, rect_height, CONSOLE_CURSOR_INFO(..),
-    CONSOLE_SCREEN_BUFFER_INFO(..), CHAR_INFO(..),
-
-    sTD_INPUT_HANDLE, sTD_OUTPUT_HANDLE, sTD_ERROR_HANDLE,
-
-    eNABLE_VIRTUAL_TERMINAL_INPUT, eNABLE_VIRTUAL_TERMINAL_PROCESSING,
-
-    fOREGROUND_BLUE, fOREGROUND_GREEN, fOREGROUND_RED, fOREGROUND_INTENSITY,
-    fOREGROUND_WHITE, fOREGROUND_INTENSE_WHITE,
-    bACKGROUND_BLUE, bACKGROUND_GREEN, bACKGROUND_RED, bACKGROUND_INTENSITY,
-    bACKGROUND_WHITE, bACKGROUND_INTENSE_WHITE,
-    cOMMON_LVB_REVERSE_VIDEO, cOMMON_LVB_UNDERSCORE,
-
-    getStdHandle,
-    getConsoleScreenBufferInfo,
-    getConsoleCursorInfo,
-    getConsoleMode,
-
-    setConsoleTextAttribute,
-    setConsoleCursorPosition,
-    setConsoleCursorInfo,
-    setConsoleTitle,
-    setConsoleMode,
-
-    fillConsoleOutputAttribute,
-    fillConsoleOutputCharacter,
-    scrollConsoleScreenBuffer,
-
-    withTString, withHandleToHANDLE,
-
-    ConsoleException (..)
-  ) where
-
-import Control.Exception (Exception, throw)
-import Data.Bits ((.|.), shiftL)
-import Data.Char (chr, ord)
-import Data.Typeable (Typeable)
-import Foreign.C.Types (CInt (..), CWchar (..))
--- Some Windows types missing from System.Win32 prior to version 2.5.0.0
-#if !MIN_VERSION_Win32(2,5,0)
-import Foreign.C.Types (CShort (..))
-#endif
-import Foreign.Marshal (alloca, allocaArray, maybeWith, peekArray, with,
-  withArrayLen)
-import Foreign.Ptr (Ptr, castPtr, plusPtr)
-import Foreign.Storable (Storable (..))
-
-#if !MIN_VERSION_Win32(2,5,1)
-import Control.Concurrent.MVar (readMVar)
-import Control.Exception (bracket)
-import Foreign.StablePtr (StablePtr, freeStablePtr, newStablePtr)
-#if __GLASGOW_HASKELL__ >= 612
-import Data.Typeable (cast)
-import GHC.IO.FD (FD(..)) -- A wrapper around an Int32
-import GHC.IO.Handle.Types (Handle (..), Handle__ (..))
-#else
-import GHC.IOBase (Handle (..), Handle__ (..))
-import qualified GHC.IOBase as IOBase (FD)  -- Just an Int32
-#endif
-#endif
-
-import System.Win32.Types (BOOL, DWORD, ErrCode, HANDLE, LPCTSTR, LPDWORD,
-  TCHAR, UINT, WORD, failIfFalse_, getLastError, iNVALID_HANDLE_VALUE,
-  nullHANDLE, withTString)
--- Missing from System.Win32.Types prior to version 2.5.0.0
-#if MIN_VERSION_Win32(2,5,0)
-import System.Win32.Types (SHORT)
-#endif
--- withHandleToHANDLE added to System.Win32.Types from version 2.5.1.0
-#if MIN_VERSION_Win32(2,5,1)
-import System.Win32.Types (withHandleToHANDLE)
-#endif
-
-#if defined(i386_HOST_ARCH)
-#define WINDOWS_CCONV stdcall
-#elif defined(x86_64_HOST_ARCH)
-#define WINDOWS_CCONV ccall
-#else
-#error Unknown mingw32 arch
-#endif
-
--- Missing from System.Win32.Types prior to version 2.5.0.0
-#if !MIN_VERSION_Win32(2,5,0)
-type SHORT = CShort
-#endif
-type WCHAR = CWchar
-
-charToWCHAR :: Char -> WCHAR
-charToWCHAR char = fromIntegral (ord char)
-
--- This is a FFI hack. Some of the API calls take a Coord, but that isn't a
--- built-in FFI type so I can't use it directly. Instead, I use UNPACKED_COORD
--- and marshal COORDs into this manually. Note that we CAN'T just use two SHORTs
--- directly because they get expanded to 4 bytes each instead of just boing 2
--- lots of 2 bytes by the stdcall convention, so linking fails.
-type UNPACKED_COORD = CInt
-
--- Field packing order determined experimentally: I couldn't immediately find a
--- specification for Windows struct layout anywhere.
-unpackCOORD :: COORD -> UNPACKED_COORD
-unpackCOORD (COORD x y)
-  = (fromIntegral y) `shiftL` (sizeOf x * 8) .|. (fromIntegral x)
-
-
-peekAndOffset :: Storable a => Ptr a -> IO (a, Ptr b)
-peekAndOffset ptr = do
-  item <- peek ptr
-  return (item, ptr `plusPtr` sizeOf item)
-
-pokeAndOffset :: Storable a => Ptr a -> a -> IO (Ptr b)
-pokeAndOffset ptr item = do
-  poke ptr item
-  return (ptr `plusPtr` sizeOf item)
-
-data COORD = COORD
-  { coord_x :: SHORT
-  , coord_y :: SHORT
-  } deriving (Read, Eq)
-
-instance Show COORD where
-  show (COORD x y) = "(" ++ show x ++ ", " ++ show y ++ ")"
-
-instance Storable COORD where
-  sizeOf ~(COORD x y) = sizeOf x + sizeOf y
-  alignment ~(COORD x _) = alignment x
-  peek ptr = do
-    let ptr' = castPtr ptr :: Ptr SHORT
-    x <- peekElemOff ptr' 0
-    y <- peekElemOff ptr' 1
-    return (COORD x y)
-  poke ptr (COORD x y) = do
-    let ptr' = castPtr ptr :: Ptr SHORT
-    pokeElemOff ptr' 0 x
-    pokeElemOff ptr' 1 y
-
-data SMALL_RECT = SMALL_RECT
-  { rect_top_left     :: COORD
-  , rect_bottom_right :: COORD
-  }
-
-rect_top, rect_left, rect_bottom, rect_right :: SMALL_RECT -> SHORT
-rect_top = coord_y . rect_top_left
-rect_left = coord_x . rect_top_left
-rect_bottom = coord_y . rect_bottom_right
-rect_right = coord_x . rect_bottom_right
-
-rect_width, rect_height :: SMALL_RECT -> SHORT
-rect_width rect = rect_right rect - rect_left rect + 1
-rect_height rect = rect_bottom rect - rect_top rect + 1
-
-instance Show SMALL_RECT where
-  show (SMALL_RECT tl br) = show tl ++ "-" ++ show br
-
-instance Storable SMALL_RECT where
-  sizeOf ~(SMALL_RECT tl br) = sizeOf tl + sizeOf br
-  alignment ~(SMALL_RECT tl _) = alignment tl
-  peek ptr = do
-    let ptr' = castPtr ptr :: Ptr COORD
-    tl <- peekElemOff ptr' 0
-    br <- peekElemOff ptr' 1
-    return (SMALL_RECT tl br)
-  poke ptr (SMALL_RECT tl br) = do
-    let ptr' = castPtr ptr :: Ptr COORD
-    pokeElemOff ptr' 0 tl
-    pokeElemOff ptr' 1 br
-
-data CONSOLE_CURSOR_INFO = CONSOLE_CURSOR_INFO
-  { cci_cursor_size    :: DWORD
-  , cci_cursor_visible :: BOOL
-  } deriving (Show)
-
-instance Storable CONSOLE_CURSOR_INFO where
-  sizeOf ~(CONSOLE_CURSOR_INFO size visible) = sizeOf size + sizeOf visible
-  alignment ~(CONSOLE_CURSOR_INFO size _) = alignment size
-  peek ptr = do
-    (size, ptr') <- peekAndOffset (castPtr ptr)
-    visible <- peek ptr'
-    return (CONSOLE_CURSOR_INFO size visible)
-  poke ptr (CONSOLE_CURSOR_INFO size visible) = do
-    ptr' <- pokeAndOffset (castPtr ptr) size
-    poke ptr' visible
-
-data CONSOLE_SCREEN_BUFFER_INFO = CONSOLE_SCREEN_BUFFER_INFO
-  { csbi_size                :: COORD
-  , csbi_cursor_position     :: COORD
-  , csbi_attributes          :: WORD
-  , csbi_window              :: SMALL_RECT
-  , csbi_maximum_window_size :: COORD
-  } deriving (Show)
-
-instance Storable CONSOLE_SCREEN_BUFFER_INFO where
-  sizeOf ~(CONSOLE_SCREEN_BUFFER_INFO
-    size cursor_position attributes window maximum_window_size)
-    = sizeOf size + sizeOf cursor_position + sizeOf attributes + sizeOf window
-        + sizeOf maximum_window_size
-  alignment ~(CONSOLE_SCREEN_BUFFER_INFO size _ _ _ _) = alignment size
-  peek ptr = do
-    (size, ptr1) <- peekAndOffset (castPtr ptr)
-    (cursor_position, ptr2) <- peekAndOffset ptr1
-    (attributes, ptr3) <- peekAndOffset ptr2
-    (window, ptr4) <- peekAndOffset ptr3
-    maximum_window_size <- peek ptr4
-    return (CONSOLE_SCREEN_BUFFER_INFO
-      size cursor_position attributes window maximum_window_size)
-  poke ptr (CONSOLE_SCREEN_BUFFER_INFO
-    size cursor_position attributes window maximum_window_size)
-    = do
-      ptr1 <- pokeAndOffset (castPtr ptr) size
-      ptr2 <- pokeAndOffset ptr1 cursor_position
-      ptr3 <- pokeAndOffset ptr2 attributes
-      ptr4 <- pokeAndOffset ptr3 window
-      poke ptr4 maximum_window_size
-
-data CHAR_INFO = CHAR_INFO
-  { ci_char       :: WCHAR
-  , ci_attributes :: WORD
-  } deriving (Show)
-
-instance Storable CHAR_INFO where
-  sizeOf ~(CHAR_INFO char attributes) = sizeOf char + sizeOf attributes
-  alignment ~(CHAR_INFO char _) = alignment char
-  peek ptr = do
-    (char, ptr') <- peekAndOffset (castPtr ptr)
-    attributes <- peek ptr'
-    return (CHAR_INFO char attributes)
-  poke ptr (CHAR_INFO char attributes) = do
-    ptr' <- pokeAndOffset (castPtr ptr) char
-    poke ptr' attributes
-
-eNABLE_VIRTUAL_TERMINAL_INPUT, eNABLE_VIRTUAL_TERMINAL_PROCESSING :: DWORD
-sTD_INPUT_HANDLE, sTD_OUTPUT_HANDLE, sTD_ERROR_HANDLE :: DWORD
-eNABLE_VIRTUAL_TERMINAL_INPUT      = 512
-eNABLE_VIRTUAL_TERMINAL_PROCESSING =   4
-sTD_INPUT_HANDLE  = 0xFFFFFFF6 -- minus 10
-sTD_OUTPUT_HANDLE = 0xFFFFFFF5 -- minus 11
-sTD_ERROR_HANDLE  = 0xFFFFFFF4 -- minus 12
-
-fOREGROUND_BLUE, fOREGROUND_GREEN, fOREGROUND_RED, fOREGROUND_INTENSITY,
-  bACKGROUND_BLUE, bACKGROUND_GREEN, bACKGROUND_RED, bACKGROUND_INTENSITY,
-  cOMMON_LVB_REVERSE_VIDEO, cOMMON_LVB_UNDERSCORE :: WORD
-fOREGROUND_BLUE          =    0x1
-fOREGROUND_GREEN         =    0x2
-fOREGROUND_RED           =    0x4
-fOREGROUND_INTENSITY     =    0x8
-bACKGROUND_BLUE          =   0x10
-bACKGROUND_GREEN         =   0x20
-bACKGROUND_RED           =   0x40
-bACKGROUND_INTENSITY     =   0x80
-cOMMON_LVB_REVERSE_VIDEO = 0x4000
-cOMMON_LVB_UNDERSCORE    = 0x8000
-
-fOREGROUND_WHITE, bACKGROUND_WHITE, fOREGROUND_INTENSE_WHITE,
-  bACKGROUND_INTENSE_WHITE :: WORD
-fOREGROUND_WHITE = fOREGROUND_RED .|. fOREGROUND_GREEN .|. fOREGROUND_BLUE
-bACKGROUND_WHITE = bACKGROUND_RED .|. bACKGROUND_GREEN .|. bACKGROUND_BLUE
-fOREGROUND_INTENSE_WHITE = fOREGROUND_WHITE .|. fOREGROUND_INTENSITY
-bACKGROUND_INTENSE_WHITE = bACKGROUND_WHITE .|. bACKGROUND_INTENSITY
-
-kEY_EVENT, mOUSE_EVENT, wINDOW_BUFFER_SIZE_EVENT, mENU_EVENT,
-  fOCUS_EVENT :: WORD
-kEY_EVENT                =  1
-mOUSE_EVENT              =  2
-wINDOW_BUFFER_SIZE_EVENT =  4
-mENU_EVENT               =  8
-fOCUS_EVENT              = 16
-
-foreign import WINDOWS_CCONV unsafe "windows.h GetStdHandle"
-  getStdHandle :: DWORD -> IO HANDLE
-foreign import WINDOWS_CCONV unsafe "windows.h GetConsoleScreenBufferInfo"
-  cGetConsoleScreenBufferInfo :: HANDLE
-                              -> Ptr CONSOLE_SCREEN_BUFFER_INFO
-                              -> IO BOOL
-foreign import WINDOWS_CCONV unsafe "windows.h GetConsoleCursorInfo"
-  cGetConsoleCursorInfo :: HANDLE -> Ptr CONSOLE_CURSOR_INFO -> IO BOOL
-foreign import WINDOWS_CCONV unsafe "windows.h GetConsoleMode"
-  cGetConsoleMode :: HANDLE -> Ptr DWORD -> IO BOOL
-foreign import WINDOWS_CCONV unsafe "windows.h SetConsoleTextAttribute"
-  cSetConsoleTextAttribute :: HANDLE -> WORD -> IO BOOL
-foreign import WINDOWS_CCONV unsafe "windows.h SetConsoleCursorPosition"
-  cSetConsoleCursorPosition :: HANDLE -> UNPACKED_COORD -> IO BOOL
-foreign import WINDOWS_CCONV unsafe "windows.h SetConsoleCursorInfo"
-  cSetConsoleCursorInfo :: HANDLE -> Ptr CONSOLE_CURSOR_INFO -> IO BOOL
-foreign import WINDOWS_CCONV unsafe "windows.h SetConsoleTitleW"
-  cSetConsoleTitle :: LPCTSTR -> IO BOOL
-foreign import WINDOWS_CCONV unsafe "windows.h SetConsoleMode"
-  cSetConsoleMode :: HANDLE -> DWORD -> IO BOOL
-foreign import WINDOWS_CCONV unsafe "windows.h FillConsoleOutputAttribute"
-  cFillConsoleOutputAttribute :: HANDLE
-                              -> WORD
-                              -> DWORD
-                              -> UNPACKED_COORD
-                              -> Ptr DWORD
-                              -> IO BOOL
-foreign import WINDOWS_CCONV unsafe "windows.h FillConsoleOutputCharacterW"
-  cFillConsoleOutputCharacter :: HANDLE
-                              -> TCHAR
-                              -> DWORD
-                              -> UNPACKED_COORD
-                              -> Ptr DWORD
-                              -> IO BOOL
-foreign import WINDOWS_CCONV unsafe "windows.h ScrollConsoleScreenBufferW"
-  cScrollConsoleScreenBuffer :: HANDLE
-                             -> Ptr SMALL_RECT
-                             -> Ptr SMALL_RECT
-                             -> UNPACKED_COORD
-                             -> Ptr CHAR_INFO
-                             -> IO BOOL
-foreign import WINDOWS_CCONV unsafe "windows.h WriteConsoleInputW"
-  cWriteConsoleInput :: HANDLE
-                     -> Ptr INPUT_RECORD
-                     -> DWORD
-                     -> LPDWORD
-                     -> IO BOOL
-foreign import WINDOWS_CCONV unsafe "windows.h GetNumberOfConsoleInputEvents"
-  cGetNumberOfConsoleInputEvents :: HANDLE -> Ptr DWORD -> IO BOOL
-foreign import WINDOWS_CCONV unsafe "windows.h ReadConsoleInputW"
-  cReadConsoleInput :: HANDLE
-                    -> Ptr INPUT_RECORD
-                    -> DWORD
-                    -> LPDWORD
-                    -> IO BOOL
-
-data ConsoleException = ConsoleException !ErrCode deriving (Show, Eq, Typeable)
-
-instance Exception ConsoleException
-
-throwIfFalse :: IO Bool -> IO ()
-throwIfFalse action = do
-  succeeded <- action
-  if not succeeded
-    then getLastError >>= throw . ConsoleException -- TODO: Check if last error
-    -- is zero for some instructable reason (?)
-    else return ()
-
-getConsoleScreenBufferInfo :: HANDLE -> IO CONSOLE_SCREEN_BUFFER_INFO
-getConsoleScreenBufferInfo handle
-  = alloca $ \ptr_console_screen_buffer_info -> do
-      throwIfFalse $
-        cGetConsoleScreenBufferInfo handle ptr_console_screen_buffer_info
-      peek ptr_console_screen_buffer_info
-
-getConsoleCursorInfo :: HANDLE -> IO CONSOLE_CURSOR_INFO
-getConsoleCursorInfo handle = alloca $ \ptr_console_cursor_info -> do
-  throwIfFalse $ cGetConsoleCursorInfo handle ptr_console_cursor_info
-  peek ptr_console_cursor_info
-
-getConsoleMode :: HANDLE -> IO DWORD
-getConsoleMode handle = alloca $ \ptr_mode -> do
-  throwIfFalse $ cGetConsoleMode handle ptr_mode
-  peek ptr_mode
-
-setConsoleTextAttribute :: HANDLE -> WORD -> IO ()
-setConsoleTextAttribute handle attributes
-  = throwIfFalse $ cSetConsoleTextAttribute handle attributes
-
-setConsoleCursorPosition :: HANDLE -> COORD -> IO ()
-setConsoleCursorPosition handle cursor_position
-  = throwIfFalse $ cSetConsoleCursorPosition handle
-      (unpackCOORD cursor_position)
-
-setConsoleCursorInfo :: HANDLE -> CONSOLE_CURSOR_INFO -> IO ()
-setConsoleCursorInfo handle console_cursor_info
-  = with console_cursor_info $ \ptr_console_cursor_info -> do
-      throwIfFalse $ cSetConsoleCursorInfo handle ptr_console_cursor_info
-
-setConsoleTitle :: LPCTSTR -> IO ()
-setConsoleTitle title = throwIfFalse $ cSetConsoleTitle title
-
-setConsoleMode :: HANDLE -> DWORD -> IO ()
-setConsoleMode handle attributes
-  = throwIfFalse $ cSetConsoleMode handle attributes
-
-fillConsoleOutputAttribute :: HANDLE -> WORD -> DWORD -> COORD -> IO DWORD
-fillConsoleOutputAttribute handle attribute fill_length write_origin
-  = alloca $ \ptr_chars_written -> do
-      throwIfFalse $ cFillConsoleOutputAttribute handle attribute
-        fill_length (unpackCOORD write_origin) ptr_chars_written
-      peek ptr_chars_written
-
-fillConsoleOutputCharacter :: HANDLE -> TCHAR -> DWORD -> COORD -> IO DWORD
-fillConsoleOutputCharacter handle char fill_length write_origin
-  = alloca $ \ptr_chars_written -> do
-      throwIfFalse $ cFillConsoleOutputCharacter handle char fill_length
-        (unpackCOORD write_origin) ptr_chars_written
-      peek ptr_chars_written
-
-scrollConsoleScreenBuffer :: HANDLE
-                          -> SMALL_RECT
-                          -> Maybe SMALL_RECT
-                          -> COORD
-                          -> CHAR_INFO
-                          -> IO ()
-scrollConsoleScreenBuffer
-  handle scroll_rectangle mb_clip_rectangle destination_origin fill
-  = with scroll_rectangle $ \ptr_scroll_rectangle ->
-    maybeWith with mb_clip_rectangle $ \ptr_clip_rectangle ->
-    with fill $ \ptr_fill ->
-    throwIfFalse $ cScrollConsoleScreenBuffer handle ptr_scroll_rectangle
-      ptr_clip_rectangle (unpackCOORD destination_origin) ptr_fill
-
--- withHandleToHANDLE added to System.Win32.Types from version 2.5.1.0
-#if !MIN_VERSION_Win32(2,5,1)
--- | 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 was added in Win32-2.5.1.0
-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
-#if __GLASGOW_HASKELL__ < 612
-    fd <- fmap haFD $ readMVar write_handle_mvar
-#else
-    -- readMVar write_handle_mvar >>= \(Handle__ { haDevice = dev }) ->
-    -- print (typeOf dev)
-    Just fd <- fmap (\(Handle__ { haDevice = dev }) ->
-      fmap fdFD (cast dev)) $ readMVar write_handle_mvar
-#endif
-
-    -- 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
-
--- This essential function comes from the C runtime system. It is certainly
--- provided by msvcrt, and also seems to be provided by the mingw C library -
--- hurrah!
-#if __GLASGOW_HASKELL__ >= 612
-foreign import WINDOWS_CCONV unsafe "_get_osfhandle"
-  cget_osfhandle :: CInt -> IO HANDLE
-#else
-foreign import WINDOWS_CCONV unsafe "_get_osfhandle"
-  cget_osfhandle :: IOBase.FD -> IO HANDLE
-#endif
-
--- withStablePtr was added in Win32-2.5.1.0
-withStablePtr :: a -> (StablePtr a -> IO b) -> IO b
-withStablePtr value = bracket (newStablePtr value) freeStablePtr
-#endif
-
--- The following is based on module System.Win32.Console.Extra from package
--- Win32-console, cut down for the WCHAR version of writeConsoleInput.
-
-writeConsoleInput :: HANDLE -> [INPUT_RECORD] -> IO DWORD
-writeConsoleInput hdl evs
-  = writeConsoleInputWith hdl $ \act ->
-    withArrayLen evs $ \len ptr ->
-    act (ptr, toEnum len)
-
-writeConsoleInputWith :: HANDLE
-                      -> InputHandler (Ptr INPUT_RECORD, DWORD)
-                      -> IO DWORD
-writeConsoleInputWith hdl withBuffer
-  = returnWith_ $ \ptrN ->
-    withBuffer $ \(ptrBuf, len) ->
-    failIfFalse_ "WriteConsoleInputW" $ cWriteConsoleInput hdl ptrBuf len ptrN
-
-returnWith_ :: Storable a => (Ptr a -> IO b) -> IO a
-returnWith_ act = alloca $ \ptr -> act ptr >> peek ptr
-
-type InputHandler i = forall a. (i -> IO a) -> IO a
-
-{-
-typedef union _UNICODE_ASCII_CHAR {
-    WCHAR UnicodeChar;
-    CHAR  AsciiChar;
-} UNICODE_ASCII_CHAR;
--}
-newtype UNICODE_ASCII_CHAR = UnicodeAsciiChar
-  { unicodeAsciiChar :: WCHAR
-  } deriving (Show, Read, Eq)
-
-instance Storable UNICODE_ASCII_CHAR where
-  sizeOf _    = 2
-  alignment _ = 2
-  peek ptr = UnicodeAsciiChar <$> (`peekByteOff` 0) ptr
-  poke ptr val = case val of
-    UnicodeAsciiChar c -> (`pokeByteOff` 0) ptr c
-
-{-
-typedef struct _KEY_EVENT_RECORD {
-	BOOL bKeyDown;
-	WORD wRepeatCount;
-	WORD wVirtualKeyCode;
-	WORD wVirtualScanCode;
-	union {
-		WCHAR UnicodeChar;
-		CHAR AsciiChar;
-	} uChar;
-	DWORD dwControlKeyState;
-}
-#ifdef __GNUC__
-/* gcc's alignment is not what win32 expects */
- PACKED
-#endif
-KEY_EVENT_RECORD;
--}
-data KEY_EVENT_RECORD = KEY_EVENT_RECORD
-  { keyEventKeyDown         :: BOOL
-  , keyEventRepeatCount     :: WORD
-  , keyEventVirtualKeyCode  :: WORD
-  , keyEventVirtualScanCode :: WORD
-  , keyEventChar            :: UNICODE_ASCII_CHAR
-  , keyEventControlKeystate :: DWORD
-  } deriving (Show, Read, Eq)
-
-instance Storable KEY_EVENT_RECORD where
-  sizeOf _    = 16
-  alignment _ =  4
-  peek ptr = KEY_EVENT_RECORD <$> (`peekByteOff`  0) ptr
-                              <*> (`peekByteOff`  4) ptr
-                              <*> (`peekByteOff`  6) ptr
-                              <*> (`peekByteOff`  8) ptr
-                              <*> (`peekByteOff` 10) ptr
-                              <*> (`peekByteOff` 12) ptr
-  poke ptr val = do
-    (`pokeByteOff`  0) ptr $ keyEventKeyDown val
-    (`pokeByteOff`  4) ptr $ keyEventRepeatCount val
-    (`pokeByteOff`  6) ptr $ keyEventVirtualKeyCode val
-    (`pokeByteOff`  8) ptr $ keyEventVirtualScanCode val
-    (`pokeByteOff` 10) ptr $ keyEventChar val
-    (`pokeByteOff` 12) ptr $ keyEventControlKeystate val
-
-{-
-typedef struct _MOUSE_EVENT_RECORD {
-	COORD dwMousePosition;
-	DWORD dwButtonState;
-	DWORD dwControlKeyState;
-	DWORD dwEventFlags;
-} MOUSE_EVENT_RECORD;
--}
-data MOUSE_EVENT_RECORD = MOUSE_EVENT_RECORD
-  { mousePosition        :: COORD
-  , mouseButtonState     :: DWORD
-  , mouseControlKeyState :: DWORD
-  , mouseEventFlags      :: DWORD
-  } deriving (Show, Read, Eq)
-
-instance Storable MOUSE_EVENT_RECORD where
-  sizeOf _    = 16
-  alignment _ =  4
-  peek ptr = MOUSE_EVENT_RECORD <$> (`peekByteOff`  0) ptr
-                                <*> (`peekByteOff`  4) ptr
-                                <*> (`peekByteOff`  8) ptr
-                                <*> (`peekByteOff` 12) ptr
-  poke ptr val = do
-    (`pokeByteOff`  0) ptr $ mousePosition val
-    (`pokeByteOff`  4) ptr $ mouseButtonState val
-    (`pokeByteOff`  8) ptr $ mouseControlKeyState val
-    (`pokeByteOff` 12) ptr $ mouseEventFlags val
-
-{-
-typedef struct _WINDOW_BUFFER_SIZE_RECORD {
-    COORD dwSize;
-} WINDOW_BUFFER_SIZE_RECORD;
--}
-data WINDOW_BUFFER_SIZE_RECORD = WINDOW_BUFFER_SIZE_RECORD
-  { bufSizeNew :: COORD
-  } deriving (Show, Read, Eq)
-
-instance Storable WINDOW_BUFFER_SIZE_RECORD where
-  sizeOf _    = 4
-  alignment _ = 4
-  peek ptr = WINDOW_BUFFER_SIZE_RECORD <$> (`peekByteOff` 0) ptr
-  poke ptr val = (`pokeByteOff` 0) ptr $ bufSizeNew val
-
-{-
-typedef struct _MENU_EVENT_RECORD {
-    UINT dwCommandId;
-} MENU_EVENT_RECORD,*PMENU_EVENT_RECORD;
--}
-data MENU_EVENT_RECORD = MENU_EVENT_RECORD
-  { menuCommandId :: UINT
-  } deriving (Show, Read, Eq)
-
-instance Storable MENU_EVENT_RECORD where
-  sizeOf _    = 4
-  alignment _ = 4
-  peek ptr = MENU_EVENT_RECORD <$> (`peekByteOff` 0) ptr
-  poke ptr val = (`pokeByteOff` 0) ptr $ menuCommandId val
-
-{-
-typedef struct _FOCUS_EVENT_RECORD { BOOL bSetFocus; } FOCUS_EVENT_RECORD;
--}
-data FOCUS_EVENT_RECORD = FOCUS_EVENT_RECORD
-  { focusSetFocus :: BOOL
-  } deriving (Show, Read, Eq)
-
-instance Storable FOCUS_EVENT_RECORD where
-  sizeOf _    = 4
-  alignment _ = 4
-  peek ptr = FOCUS_EVENT_RECORD <$> (`peekByteOff` 0) ptr
-  poke ptr val = (`pokeByteOff` 0) ptr $ focusSetFocus val
-
-data INPUT_RECORD_EVENT
-  = InputKeyEvent KEY_EVENT_RECORD
-  | InputMouseEvent MOUSE_EVENT_RECORD
-  | InputWindowBufferSizeEvent WINDOW_BUFFER_SIZE_RECORD
-  | InputMenuEvent MENU_EVENT_RECORD
-  | InputFocusEvent FOCUS_EVENT_RECORD
-  deriving (Show, Read, Eq)
-
-{-
-typedef struct _INPUT_RECORD {
-	WORD EventType;
-	union {
-		KEY_EVENT_RECORD KeyEvent;
-		MOUSE_EVENT_RECORD MouseEvent;
-		WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
-		MENU_EVENT_RECORD MenuEvent;
-		FOCUS_EVENT_RECORD FocusEvent;
-	} Event;
-} INPUT_RECORD,*PINPUT_RECORD;
--}
-data INPUT_RECORD = INPUT_RECORD
-  { inputEventType :: WORD
-  , inputEvent     :: INPUT_RECORD_EVENT
-  } deriving (Show, Read, Eq)
-
-instance Storable INPUT_RECORD where
-  sizeOf _    = 20
-  alignment _ =  4
-  peek ptr = do
-    evType <- (`peekByteOff` 0) ptr
-    event <- case evType of
-      _ | evType == kEY_EVENT
-          -> InputKeyEvent              <$> (`peekByteOff` 4) ptr
-      _ | evType == mOUSE_EVENT
-          -> InputMouseEvent            <$> (`peekByteOff` 4) ptr
-      _ | evType == wINDOW_BUFFER_SIZE_EVENT
-          -> InputWindowBufferSizeEvent <$> (`peekByteOff` 4) ptr
-      _ | evType == mENU_EVENT
-          -> InputMenuEvent             <$> (`peekByteOff` 4) ptr
-      _ | evType == fOCUS_EVENT
-          -> InputFocusEvent            <$> (`peekByteOff` 4) ptr
-      _ -> error $ "peek (INPUT_RECORD): Unknown event type " ++
-             show evType
-    return $ INPUT_RECORD evType event
-  poke ptr val = do
-    (`pokeByteOff` 0) ptr $ inputEventType val
-    case inputEvent val of
-      InputKeyEvent              ev -> (`pokeByteOff` 4) ptr ev
-      InputMouseEvent            ev -> (`pokeByteOff` 4) ptr ev
-      InputWindowBufferSizeEvent ev -> (`pokeByteOff` 4) ptr ev
-      InputMenuEvent             ev -> (`pokeByteOff` 4) ptr ev
-      InputFocusEvent            ev -> (`pokeByteOff` 4) ptr ev
-
--- The following is based on module System.Win32.Console.Extra from package
--- Win32-console.
-
-getNumberOfConsoleInputEvents :: HANDLE -> IO DWORD
-getNumberOfConsoleInputEvents hdl =
-  returnWith_ $ \ptrN ->
-    failIfFalse_ "GetNumberOfConsoleInputEvents" $
-      cGetNumberOfConsoleInputEvents hdl ptrN
-
--- The following is based on module System.Win32.Console.Extra from package
--- Win32-console, cut down for the WCHAR version of readConsoleInput.
-
-readConsoleInput :: HANDLE -> DWORD -> IO [INPUT_RECORD]
-readConsoleInput hdl len
-  = readConsoleInputWith hdl len $ \(ptr, n) -> peekArray (fromEnum n) ptr
-
-readConsoleInputWith :: HANDLE
-                     -> DWORD
-                     -> OutputHandler (Ptr INPUT_RECORD, DWORD)
-readConsoleInputWith hdl len handler =
-  allocaArray (fromEnum len) $ \ptrBuf ->
-    alloca $ \ptrN -> do
-      failIfFalse_ "ReadConsoleInputW" $
-        cReadConsoleInput hdl ptrBuf len ptrN
-      n <- peek ptrN
-      handler (ptrBuf, n)
-
-type OutputHandler o = forall a. (o -> IO a) -> IO a
-
--- Replicated from module Foreign.C.String in package base because that module
--- does not export the function.
-cWcharsToChars :: [CWchar] -> [Char]
-cWcharsToChars = map chr . fromUTF16 . map fromIntegral
- where
-  fromUTF16 (c1:c2:wcs)
-    | 0xd800 <= c1 && c1 <= 0xdbff && 0xdc00 <= c2 && c2 <= 0xdfff =
-      ((c1 - 0xd800)*0x400 + (c2 - 0xdc00) + 0x10000) : fromUTF16 wcs
-  fromUTF16 (c:wcs) = c : fromUTF16 wcs
-  fromUTF16 [] = []
+{-# OPTIONS_HADDOCK hide #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+
+-- | "System.Win32.Console" is really very impoverished, so I have had to do all
+-- the FFI myself.
+module System.Console.ANSI.Windows.Foreign
+  (
+    -- Re-exports from Win32.Types
+    BOOL, WORD, DWORD, WCHAR, HANDLE, iNVALID_HANDLE_VALUE, nullHANDLE, SHORT,
+
+    -- 'Re-exports from System.Win32.Console.Extra'
+    INPUT_RECORD (..), INPUT_RECORD_EVENT (..), kEY_EVENT,
+    KEY_EVENT_RECORD (..), UNICODE_ASCII_CHAR (..), writeConsoleInput,
+    getNumberOfConsoleInputEvents, readConsoleInput,
+
+    charToWCHAR, cWcharsToChars,
+
+    COORD(..), SMALL_RECT(..), rect_top, rect_bottom, rect_left, rect_right,
+    rect_width, rect_height, CONSOLE_CURSOR_INFO(..),
+    CONSOLE_SCREEN_BUFFER_INFO(..), CHAR_INFO(..),
+
+    sTD_INPUT_HANDLE, sTD_OUTPUT_HANDLE, sTD_ERROR_HANDLE,
+
+    eNABLE_VIRTUAL_TERMINAL_INPUT, eNABLE_VIRTUAL_TERMINAL_PROCESSING,
+
+    fOREGROUND_BLUE, fOREGROUND_GREEN, fOREGROUND_RED, fOREGROUND_INTENSITY,
+    fOREGROUND_WHITE, fOREGROUND_INTENSE_WHITE,
+    bACKGROUND_BLUE, bACKGROUND_GREEN, bACKGROUND_RED, bACKGROUND_INTENSITY,
+    bACKGROUND_WHITE, bACKGROUND_INTENSE_WHITE,
+    cOMMON_LVB_REVERSE_VIDEO, cOMMON_LVB_UNDERSCORE,
+
+    getStdHandle,
+    getConsoleScreenBufferInfo,
+    getConsoleCursorInfo,
+    getConsoleMode,
+
+    setConsoleTextAttribute,
+    setConsoleCursorPosition,
+    setConsoleCursorInfo,
+    setConsoleTitle,
+    setConsoleMode,
+
+    fillConsoleOutputAttribute,
+    fillConsoleOutputCharacter,
+    scrollConsoleScreenBuffer,
+
+    withTString, withHandleToHANDLE,
+
+    ConsoleException (..)
+  ) where
+
+import Control.Exception (Exception, throw)
+import Data.Bits ((.|.), shiftL)
+import Data.Char (chr, ord)
+import Data.Typeable (Typeable)
+import Foreign.C.Types (CInt (..), CWchar (..))
+-- Some Windows types missing from System.Win32 prior to version 2.5.0.0
+#if !MIN_VERSION_Win32(2,5,0)
+import Foreign.C.Types (CShort (..))
+#endif
+import Foreign.Marshal (alloca, allocaArray, maybeWith, peekArray, with,
+  withArrayLen)
+import Foreign.Ptr (Ptr, castPtr, plusPtr)
+import Foreign.Storable (Storable (..))
+
+#if !MIN_VERSION_Win32(2,5,1)
+import Control.Concurrent.MVar (readMVar)
+import Control.Exception (bracket)
+import Foreign.StablePtr (StablePtr, freeStablePtr, newStablePtr)
+#if __GLASGOW_HASKELL__ >= 612
+import Data.Typeable (cast)
+import GHC.IO.FD (FD(..)) -- A wrapper around an Int32
+import GHC.IO.Handle.Types (Handle (..), Handle__ (..))
+#else
+import GHC.IOBase (Handle (..), Handle__ (..))
+import qualified GHC.IOBase as IOBase (FD)  -- Just an Int32
+#endif
+#endif
+
+import System.Win32.Types (BOOL, DWORD, ErrCode, HANDLE, LPCTSTR, LPDWORD,
+  TCHAR, UINT, WORD, failIfFalse_, getLastError, iNVALID_HANDLE_VALUE,
+  nullHANDLE, withTString)
+-- Missing from System.Win32.Types prior to version 2.5.0.0
+#if MIN_VERSION_Win32(2,5,0)
+import System.Win32.Types (SHORT)
+#endif
+-- withHandleToHANDLE added to System.Win32.Types from version 2.5.1.0
+#if MIN_VERSION_Win32(2,5,1)
+import System.Win32.Types (withHandleToHANDLE)
+#endif
+
+#if defined(i386_HOST_ARCH)
+#define WINDOWS_CCONV stdcall
+#elif defined(x86_64_HOST_ARCH)
+#define WINDOWS_CCONV ccall
+#else
+#error Unknown mingw32 arch
+#endif
+
+-- Missing from System.Win32.Types prior to version 2.5.0.0
+#if !MIN_VERSION_Win32(2,5,0)
+type SHORT = CShort
+#endif
+type WCHAR = CWchar
+
+charToWCHAR :: Char -> WCHAR
+charToWCHAR char = fromIntegral (ord char)
+
+-- This is a FFI hack. Some of the API calls take a Coord, but that isn't a
+-- built-in FFI type so I can't use it directly. Instead, I use UNPACKED_COORD
+-- and marshal COORDs into this manually. Note that we CAN'T just use two SHORTs
+-- directly because they get expanded to 4 bytes each instead of just boing 2
+-- lots of 2 bytes by the stdcall convention, so linking fails.
+type UNPACKED_COORD = CInt
+
+-- Field packing order determined experimentally: I couldn't immediately find a
+-- specification for Windows struct layout anywhere.
+unpackCOORD :: COORD -> UNPACKED_COORD
+unpackCOORD (COORD x y)
+  = (fromIntegral y) `shiftL` (sizeOf x * 8) .|. (fromIntegral x)
+
+
+peekAndOffset :: Storable a => Ptr a -> IO (a, Ptr b)
+peekAndOffset ptr = do
+  item <- peek ptr
+  return (item, ptr `plusPtr` sizeOf item)
+
+pokeAndOffset :: Storable a => Ptr a -> a -> IO (Ptr b)
+pokeAndOffset ptr item = do
+  poke ptr item
+  return (ptr `plusPtr` sizeOf item)
+
+data COORD = COORD
+  { coord_x :: SHORT
+  , coord_y :: SHORT
+  } deriving (Read, Eq)
+
+instance Show COORD where
+  show (COORD x y) = "(" ++ show x ++ ", " ++ show y ++ ")"
+
+instance Storable COORD where
+  sizeOf ~(COORD x y) = sizeOf x + sizeOf y
+  alignment ~(COORD x _) = alignment x
+  peek ptr = do
+    let ptr' = castPtr ptr :: Ptr SHORT
+    x <- peekElemOff ptr' 0
+    y <- peekElemOff ptr' 1
+    return (COORD x y)
+  poke ptr (COORD x y) = do
+    let ptr' = castPtr ptr :: Ptr SHORT
+    pokeElemOff ptr' 0 x
+    pokeElemOff ptr' 1 y
+
+data SMALL_RECT = SMALL_RECT
+  { rect_top_left     :: COORD
+  , rect_bottom_right :: COORD
+  }
+
+rect_top, rect_left, rect_bottom, rect_right :: SMALL_RECT -> SHORT
+rect_top = coord_y . rect_top_left
+rect_left = coord_x . rect_top_left
+rect_bottom = coord_y . rect_bottom_right
+rect_right = coord_x . rect_bottom_right
+
+rect_width, rect_height :: SMALL_RECT -> SHORT
+rect_width rect = rect_right rect - rect_left rect + 1
+rect_height rect = rect_bottom rect - rect_top rect + 1
+
+instance Show SMALL_RECT where
+  show (SMALL_RECT tl br) = show tl ++ "-" ++ show br
+
+instance Storable SMALL_RECT where
+  sizeOf ~(SMALL_RECT tl br) = sizeOf tl + sizeOf br
+  alignment ~(SMALL_RECT tl _) = alignment tl
+  peek ptr = do
+    let ptr' = castPtr ptr :: Ptr COORD
+    tl <- peekElemOff ptr' 0
+    br <- peekElemOff ptr' 1
+    return (SMALL_RECT tl br)
+  poke ptr (SMALL_RECT tl br) = do
+    let ptr' = castPtr ptr :: Ptr COORD
+    pokeElemOff ptr' 0 tl
+    pokeElemOff ptr' 1 br
+
+data CONSOLE_CURSOR_INFO = CONSOLE_CURSOR_INFO
+  { cci_cursor_size    :: DWORD
+  , cci_cursor_visible :: BOOL
+  } deriving (Show)
+
+instance Storable CONSOLE_CURSOR_INFO where
+  sizeOf ~(CONSOLE_CURSOR_INFO size visible) = sizeOf size + sizeOf visible
+  alignment ~(CONSOLE_CURSOR_INFO size _) = alignment size
+  peek ptr = do
+    (size, ptr') <- peekAndOffset (castPtr ptr)
+    visible <- peek ptr'
+    return (CONSOLE_CURSOR_INFO size visible)
+  poke ptr (CONSOLE_CURSOR_INFO size visible) = do
+    ptr' <- pokeAndOffset (castPtr ptr) size
+    poke ptr' visible
+
+data CONSOLE_SCREEN_BUFFER_INFO = CONSOLE_SCREEN_BUFFER_INFO
+  { csbi_size                :: COORD
+  , csbi_cursor_position     :: COORD
+  , csbi_attributes          :: WORD
+  , csbi_window              :: SMALL_RECT
+  , csbi_maximum_window_size :: COORD
+  } deriving (Show)
+
+instance Storable CONSOLE_SCREEN_BUFFER_INFO where
+  sizeOf ~(CONSOLE_SCREEN_BUFFER_INFO
+    size cursor_position attributes window maximum_window_size)
+    = sizeOf size + sizeOf cursor_position + sizeOf attributes + sizeOf window
+        + sizeOf maximum_window_size
+  alignment ~(CONSOLE_SCREEN_BUFFER_INFO size _ _ _ _) = alignment size
+  peek ptr = do
+    (size, ptr1) <- peekAndOffset (castPtr ptr)
+    (cursor_position, ptr2) <- peekAndOffset ptr1
+    (attributes, ptr3) <- peekAndOffset ptr2
+    (window, ptr4) <- peekAndOffset ptr3
+    maximum_window_size <- peek ptr4
+    return (CONSOLE_SCREEN_BUFFER_INFO
+      size cursor_position attributes window maximum_window_size)
+  poke ptr (CONSOLE_SCREEN_BUFFER_INFO
+    size cursor_position attributes window maximum_window_size)
+    = do
+      ptr1 <- pokeAndOffset (castPtr ptr) size
+      ptr2 <- pokeAndOffset ptr1 cursor_position
+      ptr3 <- pokeAndOffset ptr2 attributes
+      ptr4 <- pokeAndOffset ptr3 window
+      poke ptr4 maximum_window_size
+
+data CHAR_INFO = CHAR_INFO
+  { ci_char       :: WCHAR
+  , ci_attributes :: WORD
+  } deriving (Show)
+
+instance Storable CHAR_INFO where
+  sizeOf ~(CHAR_INFO char attributes) = sizeOf char + sizeOf attributes
+  alignment ~(CHAR_INFO char _) = alignment char
+  peek ptr = do
+    (char, ptr') <- peekAndOffset (castPtr ptr)
+    attributes <- peek ptr'
+    return (CHAR_INFO char attributes)
+  poke ptr (CHAR_INFO char attributes) = do
+    ptr' <- pokeAndOffset (castPtr ptr) char
+    poke ptr' attributes
+
+eNABLE_VIRTUAL_TERMINAL_INPUT, eNABLE_VIRTUAL_TERMINAL_PROCESSING :: DWORD
+sTD_INPUT_HANDLE, sTD_OUTPUT_HANDLE, sTD_ERROR_HANDLE :: DWORD
+eNABLE_VIRTUAL_TERMINAL_INPUT      = 512
+eNABLE_VIRTUAL_TERMINAL_PROCESSING =   4
+sTD_INPUT_HANDLE  = 0xFFFFFFF6 -- minus 10
+sTD_OUTPUT_HANDLE = 0xFFFFFFF5 -- minus 11
+sTD_ERROR_HANDLE  = 0xFFFFFFF4 -- minus 12
+
+fOREGROUND_BLUE, fOREGROUND_GREEN, fOREGROUND_RED, fOREGROUND_INTENSITY,
+  bACKGROUND_BLUE, bACKGROUND_GREEN, bACKGROUND_RED, bACKGROUND_INTENSITY,
+  cOMMON_LVB_REVERSE_VIDEO, cOMMON_LVB_UNDERSCORE :: WORD
+fOREGROUND_BLUE          =    0x1
+fOREGROUND_GREEN         =    0x2
+fOREGROUND_RED           =    0x4
+fOREGROUND_INTENSITY     =    0x8
+bACKGROUND_BLUE          =   0x10
+bACKGROUND_GREEN         =   0x20
+bACKGROUND_RED           =   0x40
+bACKGROUND_INTENSITY     =   0x80
+cOMMON_LVB_REVERSE_VIDEO = 0x4000
+cOMMON_LVB_UNDERSCORE    = 0x8000
+
+fOREGROUND_WHITE, bACKGROUND_WHITE, fOREGROUND_INTENSE_WHITE,
+  bACKGROUND_INTENSE_WHITE :: WORD
+fOREGROUND_WHITE = fOREGROUND_RED .|. fOREGROUND_GREEN .|. fOREGROUND_BLUE
+bACKGROUND_WHITE = bACKGROUND_RED .|. bACKGROUND_GREEN .|. bACKGROUND_BLUE
+fOREGROUND_INTENSE_WHITE = fOREGROUND_WHITE .|. fOREGROUND_INTENSITY
+bACKGROUND_INTENSE_WHITE = bACKGROUND_WHITE .|. bACKGROUND_INTENSITY
+
+kEY_EVENT, mOUSE_EVENT, wINDOW_BUFFER_SIZE_EVENT, mENU_EVENT,
+  fOCUS_EVENT :: WORD
+kEY_EVENT                =  1
+mOUSE_EVENT              =  2
+wINDOW_BUFFER_SIZE_EVENT =  4
+mENU_EVENT               =  8
+fOCUS_EVENT              = 16
+
+foreign import WINDOWS_CCONV unsafe "windows.h GetStdHandle"
+  getStdHandle :: DWORD -> IO HANDLE
+foreign import WINDOWS_CCONV unsafe "windows.h GetConsoleScreenBufferInfo"
+  cGetConsoleScreenBufferInfo :: HANDLE
+                              -> Ptr CONSOLE_SCREEN_BUFFER_INFO
+                              -> IO BOOL
+foreign import WINDOWS_CCONV unsafe "windows.h GetConsoleCursorInfo"
+  cGetConsoleCursorInfo :: HANDLE -> Ptr CONSOLE_CURSOR_INFO -> IO BOOL
+foreign import WINDOWS_CCONV unsafe "windows.h GetConsoleMode"
+  cGetConsoleMode :: HANDLE -> Ptr DWORD -> IO BOOL
+foreign import WINDOWS_CCONV unsafe "windows.h SetConsoleTextAttribute"
+  cSetConsoleTextAttribute :: HANDLE -> WORD -> IO BOOL
+foreign import WINDOWS_CCONV unsafe "windows.h SetConsoleCursorPosition"
+  cSetConsoleCursorPosition :: HANDLE -> UNPACKED_COORD -> IO BOOL
+foreign import WINDOWS_CCONV unsafe "windows.h SetConsoleCursorInfo"
+  cSetConsoleCursorInfo :: HANDLE -> Ptr CONSOLE_CURSOR_INFO -> IO BOOL
+foreign import WINDOWS_CCONV unsafe "windows.h SetConsoleTitleW"
+  cSetConsoleTitle :: LPCTSTR -> IO BOOL
+foreign import WINDOWS_CCONV unsafe "windows.h SetConsoleMode"
+  cSetConsoleMode :: HANDLE -> DWORD -> IO BOOL
+foreign import WINDOWS_CCONV unsafe "windows.h FillConsoleOutputAttribute"
+  cFillConsoleOutputAttribute :: HANDLE
+                              -> WORD
+                              -> DWORD
+                              -> UNPACKED_COORD
+                              -> Ptr DWORD
+                              -> IO BOOL
+foreign import WINDOWS_CCONV unsafe "windows.h FillConsoleOutputCharacterW"
+  cFillConsoleOutputCharacter :: HANDLE
+                              -> TCHAR
+                              -> DWORD
+                              -> UNPACKED_COORD
+                              -> Ptr DWORD
+                              -> IO BOOL
+foreign import WINDOWS_CCONV unsafe "windows.h ScrollConsoleScreenBufferW"
+  cScrollConsoleScreenBuffer :: HANDLE
+                             -> Ptr SMALL_RECT
+                             -> Ptr SMALL_RECT
+                             -> UNPACKED_COORD
+                             -> Ptr CHAR_INFO
+                             -> IO BOOL
+foreign import WINDOWS_CCONV unsafe "windows.h WriteConsoleInputW"
+  cWriteConsoleInput :: HANDLE
+                     -> Ptr INPUT_RECORD
+                     -> DWORD
+                     -> LPDWORD
+                     -> IO BOOL
+foreign import WINDOWS_CCONV unsafe "windows.h GetNumberOfConsoleInputEvents"
+  cGetNumberOfConsoleInputEvents :: HANDLE -> Ptr DWORD -> IO BOOL
+foreign import WINDOWS_CCONV unsafe "windows.h ReadConsoleInputW"
+  cReadConsoleInput :: HANDLE
+                    -> Ptr INPUT_RECORD
+                    -> DWORD
+                    -> LPDWORD
+                    -> IO BOOL
+
+data ConsoleException = ConsoleException !ErrCode deriving (Eq, Typeable)
+
+instance Show ConsoleException where
+  show (ConsoleException 6) =
+    "A fatal error has occurred.\n\n" ++
+    "An attempt has been made to send console virtual terminal sequences\n" ++
+    "(ANSI codes) to an output that has not been recognised as an\n" ++
+    "ANSI-capable terminal and also cannot be emulated as an ANSI-enabled\n" ++
+    "terminal (emulation needs a ConHost-based terminal, such as Command\n" ++
+    "Prompt or PowerShell). That may occur, for example, if output has\n" ++
+    "been redirected to a file.\n\n" ++
+    "If that is unexpected, please post an issue at:\n" ++
+    "https://github.com/feuerbach/ansi-terminal/issues\n"
+  show (ConsoleException errCode) = "ConsoleException " ++ show errCode
+
+instance Exception ConsoleException
+
+throwIfFalse :: IO Bool -> IO ()
+throwIfFalse action = do
+  succeeded <- action
+  if not succeeded
+    then getLastError >>= throw . ConsoleException -- TODO: Check if last error
+    -- is zero for some instructable reason (?)
+    else return ()
+
+getConsoleScreenBufferInfo :: HANDLE -> IO CONSOLE_SCREEN_BUFFER_INFO
+getConsoleScreenBufferInfo handle
+  = alloca $ \ptr_console_screen_buffer_info -> do
+      throwIfFalse $
+        cGetConsoleScreenBufferInfo handle ptr_console_screen_buffer_info
+      peek ptr_console_screen_buffer_info
+
+getConsoleCursorInfo :: HANDLE -> IO CONSOLE_CURSOR_INFO
+getConsoleCursorInfo handle = alloca $ \ptr_console_cursor_info -> do
+  throwIfFalse $ cGetConsoleCursorInfo handle ptr_console_cursor_info
+  peek ptr_console_cursor_info
+
+getConsoleMode :: HANDLE -> IO DWORD
+getConsoleMode handle = alloca $ \ptr_mode -> do
+  throwIfFalse $ cGetConsoleMode handle ptr_mode
+  peek ptr_mode
+
+setConsoleTextAttribute :: HANDLE -> WORD -> IO ()
+setConsoleTextAttribute handle attributes
+  = throwIfFalse $ cSetConsoleTextAttribute handle attributes
+
+setConsoleCursorPosition :: HANDLE -> COORD -> IO ()
+setConsoleCursorPosition handle cursor_position
+  = throwIfFalse $ cSetConsoleCursorPosition handle
+      (unpackCOORD cursor_position)
+
+setConsoleCursorInfo :: HANDLE -> CONSOLE_CURSOR_INFO -> IO ()
+setConsoleCursorInfo handle console_cursor_info
+  = with console_cursor_info $ \ptr_console_cursor_info -> do
+      throwIfFalse $ cSetConsoleCursorInfo handle ptr_console_cursor_info
+
+setConsoleTitle :: LPCTSTR -> IO ()
+setConsoleTitle title = throwIfFalse $ cSetConsoleTitle title
+
+setConsoleMode :: HANDLE -> DWORD -> IO ()
+setConsoleMode handle attributes
+  = throwIfFalse $ cSetConsoleMode handle attributes
+
+fillConsoleOutputAttribute :: HANDLE -> WORD -> DWORD -> COORD -> IO DWORD
+fillConsoleOutputAttribute handle attribute fill_length write_origin
+  = alloca $ \ptr_chars_written -> do
+      throwIfFalse $ cFillConsoleOutputAttribute handle attribute
+        fill_length (unpackCOORD write_origin) ptr_chars_written
+      peek ptr_chars_written
+
+fillConsoleOutputCharacter :: HANDLE -> TCHAR -> DWORD -> COORD -> IO DWORD
+fillConsoleOutputCharacter handle char fill_length write_origin
+  = alloca $ \ptr_chars_written -> do
+      throwIfFalse $ cFillConsoleOutputCharacter handle char fill_length
+        (unpackCOORD write_origin) ptr_chars_written
+      peek ptr_chars_written
+
+scrollConsoleScreenBuffer :: HANDLE
+                          -> SMALL_RECT
+                          -> Maybe SMALL_RECT
+                          -> COORD
+                          -> CHAR_INFO
+                          -> IO ()
+scrollConsoleScreenBuffer
+  handle scroll_rectangle mb_clip_rectangle destination_origin fill
+  = with scroll_rectangle $ \ptr_scroll_rectangle ->
+    maybeWith with mb_clip_rectangle $ \ptr_clip_rectangle ->
+    with fill $ \ptr_fill ->
+    throwIfFalse $ cScrollConsoleScreenBuffer handle ptr_scroll_rectangle
+      ptr_clip_rectangle (unpackCOORD destination_origin) ptr_fill
+
+-- withHandleToHANDLE added to System.Win32.Types from version 2.5.1.0
+#if !MIN_VERSION_Win32(2,5,1)
+-- | 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 was added in Win32-2.5.1.0
+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
+#if __GLASGOW_HASKELL__ < 612
+    fd <- fmap haFD $ readMVar write_handle_mvar
+#else
+    -- readMVar write_handle_mvar >>= \(Handle__ { haDevice = dev }) ->
+    -- print (typeOf dev)
+    Just fd <- fmap (\(Handle__ { haDevice = dev }) ->
+      fmap fdFD (cast dev)) $ readMVar write_handle_mvar
+#endif
+
+    -- 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
+
+-- This essential function comes from the C runtime system. It is certainly
+-- provided by msvcrt, and also seems to be provided by the mingw C library -
+-- hurrah!
+#if __GLASGOW_HASKELL__ >= 612
+foreign import WINDOWS_CCONV unsafe "_get_osfhandle"
+  cget_osfhandle :: CInt -> IO HANDLE
+#else
+foreign import WINDOWS_CCONV unsafe "_get_osfhandle"
+  cget_osfhandle :: IOBase.FD -> IO HANDLE
+#endif
+
+-- withStablePtr was added in Win32-2.5.1.0
+withStablePtr :: a -> (StablePtr a -> IO b) -> IO b
+withStablePtr value = bracket (newStablePtr value) freeStablePtr
+#endif
+
+-- The following is based on module System.Win32.Console.Extra from package
+-- Win32-console, cut down for the WCHAR version of writeConsoleInput.
+
+writeConsoleInput :: HANDLE -> [INPUT_RECORD] -> IO DWORD
+writeConsoleInput hdl evs
+  = writeConsoleInputWith hdl $ \act ->
+    withArrayLen evs $ \len ptr ->
+    act (ptr, toEnum len)
+
+writeConsoleInputWith :: HANDLE
+                      -> InputHandler (Ptr INPUT_RECORD, DWORD)
+                      -> IO DWORD
+writeConsoleInputWith hdl withBuffer
+  = returnWith_ $ \ptrN ->
+    withBuffer $ \(ptrBuf, len) ->
+    failIfFalse_ "WriteConsoleInputW" $ cWriteConsoleInput hdl ptrBuf len ptrN
+
+returnWith_ :: Storable a => (Ptr a -> IO b) -> IO a
+returnWith_ act = alloca $ \ptr -> act ptr >> peek ptr
+
+type InputHandler i = forall a. (i -> IO a) -> IO a
+
+{-
+typedef union _UNICODE_ASCII_CHAR {
+    WCHAR UnicodeChar;
+    CHAR  AsciiChar;
+} UNICODE_ASCII_CHAR;
+-}
+newtype UNICODE_ASCII_CHAR = UnicodeAsciiChar
+  { unicodeAsciiChar :: WCHAR
+  } deriving (Show, Read, Eq)
+
+instance Storable UNICODE_ASCII_CHAR where
+  sizeOf _    = 2
+  alignment _ = 2
+  peek ptr = UnicodeAsciiChar <$> (`peekByteOff` 0) ptr
+  poke ptr val = case val of
+    UnicodeAsciiChar c -> (`pokeByteOff` 0) ptr c
+
+{-
+typedef struct _KEY_EVENT_RECORD {
+	BOOL bKeyDown;
+	WORD wRepeatCount;
+	WORD wVirtualKeyCode;
+	WORD wVirtualScanCode;
+	union {
+		WCHAR UnicodeChar;
+		CHAR AsciiChar;
+	} uChar;
+	DWORD dwControlKeyState;
+}
+#ifdef __GNUC__
+/* gcc's alignment is not what win32 expects */
+ PACKED
+#endif
+KEY_EVENT_RECORD;
+-}
+data KEY_EVENT_RECORD = KEY_EVENT_RECORD
+  { keyEventKeyDown         :: BOOL
+  , keyEventRepeatCount     :: WORD
+  , keyEventVirtualKeyCode  :: WORD
+  , keyEventVirtualScanCode :: WORD
+  , keyEventChar            :: UNICODE_ASCII_CHAR
+  , keyEventControlKeystate :: DWORD
+  } deriving (Show, Read, Eq)
+
+instance Storable KEY_EVENT_RECORD where
+  sizeOf _    = 16
+  alignment _ =  4
+  peek ptr = KEY_EVENT_RECORD <$> (`peekByteOff`  0) ptr
+                              <*> (`peekByteOff`  4) ptr
+                              <*> (`peekByteOff`  6) ptr
+                              <*> (`peekByteOff`  8) ptr
+                              <*> (`peekByteOff` 10) ptr
+                              <*> (`peekByteOff` 12) ptr
+  poke ptr val = do
+    (`pokeByteOff`  0) ptr $ keyEventKeyDown val
+    (`pokeByteOff`  4) ptr $ keyEventRepeatCount val
+    (`pokeByteOff`  6) ptr $ keyEventVirtualKeyCode val
+    (`pokeByteOff`  8) ptr $ keyEventVirtualScanCode val
+    (`pokeByteOff` 10) ptr $ keyEventChar val
+    (`pokeByteOff` 12) ptr $ keyEventControlKeystate val
+
+{-
+typedef struct _MOUSE_EVENT_RECORD {
+	COORD dwMousePosition;
+	DWORD dwButtonState;
+	DWORD dwControlKeyState;
+	DWORD dwEventFlags;
+} MOUSE_EVENT_RECORD;
+-}
+data MOUSE_EVENT_RECORD = MOUSE_EVENT_RECORD
+  { mousePosition        :: COORD
+  , mouseButtonState     :: DWORD
+  , mouseControlKeyState :: DWORD
+  , mouseEventFlags      :: DWORD
+  } deriving (Show, Read, Eq)
+
+instance Storable MOUSE_EVENT_RECORD where
+  sizeOf _    = 16
+  alignment _ =  4
+  peek ptr = MOUSE_EVENT_RECORD <$> (`peekByteOff`  0) ptr
+                                <*> (`peekByteOff`  4) ptr
+                                <*> (`peekByteOff`  8) ptr
+                                <*> (`peekByteOff` 12) ptr
+  poke ptr val = do
+    (`pokeByteOff`  0) ptr $ mousePosition val
+    (`pokeByteOff`  4) ptr $ mouseButtonState val
+    (`pokeByteOff`  8) ptr $ mouseControlKeyState val
+    (`pokeByteOff` 12) ptr $ mouseEventFlags val
+
+{-
+typedef struct _WINDOW_BUFFER_SIZE_RECORD {
+    COORD dwSize;
+} WINDOW_BUFFER_SIZE_RECORD;
+-}
+data WINDOW_BUFFER_SIZE_RECORD = WINDOW_BUFFER_SIZE_RECORD
+  { bufSizeNew :: COORD
+  } deriving (Show, Read, Eq)
+
+instance Storable WINDOW_BUFFER_SIZE_RECORD where
+  sizeOf _    = 4
+  alignment _ = 4
+  peek ptr = WINDOW_BUFFER_SIZE_RECORD <$> (`peekByteOff` 0) ptr
+  poke ptr val = (`pokeByteOff` 0) ptr $ bufSizeNew val
+
+{-
+typedef struct _MENU_EVENT_RECORD {
+    UINT dwCommandId;
+} MENU_EVENT_RECORD,*PMENU_EVENT_RECORD;
+-}
+data MENU_EVENT_RECORD = MENU_EVENT_RECORD
+  { menuCommandId :: UINT
+  } deriving (Show, Read, Eq)
+
+instance Storable MENU_EVENT_RECORD where
+  sizeOf _    = 4
+  alignment _ = 4
+  peek ptr = MENU_EVENT_RECORD <$> (`peekByteOff` 0) ptr
+  poke ptr val = (`pokeByteOff` 0) ptr $ menuCommandId val
+
+{-
+typedef struct _FOCUS_EVENT_RECORD { BOOL bSetFocus; } FOCUS_EVENT_RECORD;
+-}
+data FOCUS_EVENT_RECORD = FOCUS_EVENT_RECORD
+  { focusSetFocus :: BOOL
+  } deriving (Show, Read, Eq)
+
+instance Storable FOCUS_EVENT_RECORD where
+  sizeOf _    = 4
+  alignment _ = 4
+  peek ptr = FOCUS_EVENT_RECORD <$> (`peekByteOff` 0) ptr
+  poke ptr val = (`pokeByteOff` 0) ptr $ focusSetFocus val
+
+data INPUT_RECORD_EVENT
+  = InputKeyEvent KEY_EVENT_RECORD
+  | InputMouseEvent MOUSE_EVENT_RECORD
+  | InputWindowBufferSizeEvent WINDOW_BUFFER_SIZE_RECORD
+  | InputMenuEvent MENU_EVENT_RECORD
+  | InputFocusEvent FOCUS_EVENT_RECORD
+  deriving (Show, Read, Eq)
+
+{-
+typedef struct _INPUT_RECORD {
+	WORD EventType;
+	union {
+		KEY_EVENT_RECORD KeyEvent;
+		MOUSE_EVENT_RECORD MouseEvent;
+		WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
+		MENU_EVENT_RECORD MenuEvent;
+		FOCUS_EVENT_RECORD FocusEvent;
+	} Event;
+} INPUT_RECORD,*PINPUT_RECORD;
+-}
+data INPUT_RECORD = INPUT_RECORD
+  { inputEventType :: WORD
+  , inputEvent     :: INPUT_RECORD_EVENT
+  } deriving (Show, Read, Eq)
+
+instance Storable INPUT_RECORD where
+  sizeOf _    = 20
+  alignment _ =  4
+  peek ptr = do
+    evType <- (`peekByteOff` 0) ptr
+    event <- case evType of
+      _ | evType == kEY_EVENT
+          -> InputKeyEvent              <$> (`peekByteOff` 4) ptr
+      _ | evType == mOUSE_EVENT
+          -> InputMouseEvent            <$> (`peekByteOff` 4) ptr
+      _ | evType == wINDOW_BUFFER_SIZE_EVENT
+          -> InputWindowBufferSizeEvent <$> (`peekByteOff` 4) ptr
+      _ | evType == mENU_EVENT
+          -> InputMenuEvent             <$> (`peekByteOff` 4) ptr
+      _ | evType == fOCUS_EVENT
+          -> InputFocusEvent            <$> (`peekByteOff` 4) ptr
+      _ -> error $ "peek (INPUT_RECORD): Unknown event type " ++
+             show evType
+    return $ INPUT_RECORD evType event
+  poke ptr val = do
+    (`pokeByteOff` 0) ptr $ inputEventType val
+    case inputEvent val of
+      InputKeyEvent              ev -> (`pokeByteOff` 4) ptr ev
+      InputMouseEvent            ev -> (`pokeByteOff` 4) ptr ev
+      InputWindowBufferSizeEvent ev -> (`pokeByteOff` 4) ptr ev
+      InputMenuEvent             ev -> (`pokeByteOff` 4) ptr ev
+      InputFocusEvent            ev -> (`pokeByteOff` 4) ptr ev
+
+-- The following is based on module System.Win32.Console.Extra from package
+-- Win32-console.
+
+getNumberOfConsoleInputEvents :: HANDLE -> IO DWORD
+getNumberOfConsoleInputEvents hdl =
+  returnWith_ $ \ptrN ->
+    failIfFalse_ "GetNumberOfConsoleInputEvents" $
+      cGetNumberOfConsoleInputEvents hdl ptrN
+
+-- The following is based on module System.Win32.Console.Extra from package
+-- Win32-console, cut down for the WCHAR version of readConsoleInput.
+
+readConsoleInput :: HANDLE -> DWORD -> IO [INPUT_RECORD]
+readConsoleInput hdl len
+  = readConsoleInputWith hdl len $ \(ptr, n) -> peekArray (fromEnum n) ptr
+
+readConsoleInputWith :: HANDLE
+                     -> DWORD
+                     -> OutputHandler (Ptr INPUT_RECORD, DWORD)
+readConsoleInputWith hdl len handler =
+  allocaArray (fromEnum len) $ \ptrBuf ->
+    alloca $ \ptrN -> do
+      failIfFalse_ "ReadConsoleInputW" $
+        cReadConsoleInput hdl ptrBuf len ptrN
+      n <- peek ptrN
+      handler (ptrBuf, n)
+
+type OutputHandler o = forall a. (o -> IO a) -> IO a
+
+-- Replicated from module Foreign.C.String in package base because that module
+-- does not export the function.
+cWcharsToChars :: [CWchar] -> [Char]
+cWcharsToChars = map chr . fromUTF16 . map fromIntegral
+ where
+  fromUTF16 (c1:c2:wcs)
+    | 0xd800 <= c1 && c1 <= 0xdbff && 0xdc00 <= c2 && c2 <= 0xdfff =
+      ((c1 - 0xd800)*0x400 + (c2 - 0xdc00) + 0x10000) : fromUTF16 wcs
+  fromUTF16 (c:wcs) = c : fromUTF16 wcs
+  fromUTF16 [] = []
diff --git a/ansi-terminal.cabal b/ansi-terminal.cabal
--- a/ansi-terminal.cabal
+++ b/ansi-terminal.cabal
@@ -1,94 +1,94 @@
-Name:                ansi-terminal
-Version:             0.8
-Cabal-Version:       >= 1.6
-Category:            User Interfaces
-Synopsis:            Simple ANSI terminal support, with Windows compatibility
-Description:         ANSI terminal support for Haskell: allows cursor movement,
-                     screen clearing, color output, showing or hiding the
-                     cursor, and changing the title. Works on UNIX and Windows.
-License:             BSD3
-License-File:        LICENSE
-Author:              Max Bolingbroke
-Maintainer:          Roman Cheplyaka <roma@ro-che.info>
-Homepage:            https://github.com/feuerbach/ansi-terminal
-Build-Type:          Simple
-
-Extra-Source-Files:     includes/Common-Include.hs
-                        includes/Common-Include-Emulator.hs
-                        includes/Common-Include-Enabled.hs
-                        includes/Exports-Include.hs
-                        CHANGELOG.md
-                        README.md
-
-Source-repository head
-  type:     git
-  location: git://github.com/feuerbach/ansi-terminal.git
-
-Flag Example
-        Description:    Build the example application
-        Default:        False
-
-Library
-        Exposed-Modules:        System.Console.ANSI
-                                System.Console.ANSI.Types
-                                System.Console.ANSI.Codes
-
-        Include-Dirs:           includes
-
-        Build-Depends:          base >= 4 && < 5
-                              , colour
-        if os(windows)
-                Build-Depends:          base-compat >= 0.9.1
-                                      , containers
-                                      , Win32 >= 2.0
-                                      , process
-                Cpp-Options:            -DWINDOWS
-                Other-Modules:          System.Console.ANSI.Windows
-                                        System.Console.ANSI.Windows.Detect
-                                        System.Console.ANSI.Windows.Emulator
-                                        System.Console.ANSI.Windows.Emulator.Codes
-                                        System.Console.ANSI.Windows.Foreign
-                                        -- NB: used for fallback by the emulator
-                                        System.Console.ANSI.Unix
-        else
-                -- We assume any non-Windows platform is Unix
-                Cpp-Options:            -DUNIX
-                Other-Modules:          System.Console.ANSI.Unix
-
-        Extensions:             CPP
-                                ForeignFunctionInterface
-
-        Ghc-Options:                    -Wall
-
-Executable ansi-terminal-example
-        Main-Is:                System/Console/ANSI/Example.hs
-
-        Include-Dirs:           includes
-
-        Other-Modules:          System.Console.ANSI
-                                System.Console.ANSI.Codes
-                                System.Console.ANSI.Types
-                                System.Console.ANSI.Unix
-
-        if os(windows)
-                Build-Depends:          base-compat >= 0.9.1
-                                      , containers
-                                      , Win32 >= 2.0
-                Cpp-Options:            -DWINDOWS
-                Other-Modules:          System.Console.ANSI.Windows
-                                        System.Console.ANSI.Windows.Detect
-                                        System.Console.ANSI.Windows.Emulator
-                                        System.Console.ANSI.Windows.Emulator.Codes
-                                        System.Console.ANSI.Windows.Foreign
-        else
-                -- We assume any non-Windows platform is Unix
-                Cpp-Options:            -DUNIX
-
-        Build-Depends:          base >= 4 && < 5
-        Extensions:             CPP
-                                ForeignFunctionInterface
-
-        Ghc-Options:            -Wall
-
-        if !flag(example)
-                Buildable:              False
+Name:                ansi-terminal
+Version:             0.8.0.1
+Cabal-Version:       >= 1.6
+Category:            User Interfaces
+Synopsis:            Simple ANSI terminal support, with Windows compatibility
+Description:         ANSI terminal support for Haskell: allows cursor movement,
+                     screen clearing, color output, showing or hiding the
+                     cursor, and changing the title. Works on UNIX and Windows.
+License:             BSD3
+License-File:        LICENSE
+Author:              Max Bolingbroke
+Maintainer:          Mike Pilgrem <public@pilgrem.com>, Roman Cheplyaka <roma@ro-che.info>
+Homepage:            https://github.com/feuerbach/ansi-terminal
+Build-Type:          Simple
+
+Extra-Source-Files:     includes/Common-Include.hs
+                        includes/Common-Include-Emulator.hs
+                        includes/Common-Include-Enabled.hs
+                        includes/Exports-Include.hs
+                        CHANGELOG.md
+                        README.md
+
+Source-repository head
+  type:     git
+  location: git://github.com/feuerbach/ansi-terminal.git
+
+Flag Example
+        Description:    Build the example application
+        Default:        False
+
+Library
+        Exposed-Modules:        System.Console.ANSI
+                                System.Console.ANSI.Types
+                                System.Console.ANSI.Codes
+
+        Include-Dirs:           includes
+
+        Build-Depends:          base >= 4 && < 5
+                              , colour
+        if os(windows)
+                Build-Depends:          base-compat >= 0.9.1
+                                      , containers
+                                      , Win32 >= 2.0
+                                      , process
+                Cpp-Options:            -DWINDOWS
+                Other-Modules:          System.Console.ANSI.Windows
+                                        System.Console.ANSI.Windows.Detect
+                                        System.Console.ANSI.Windows.Emulator
+                                        System.Console.ANSI.Windows.Emulator.Codes
+                                        System.Console.ANSI.Windows.Foreign
+                                        -- NB: used for fallback by the emulator
+                                        System.Console.ANSI.Unix
+        else
+                -- We assume any non-Windows platform is Unix
+                Cpp-Options:            -DUNIX
+                Other-Modules:          System.Console.ANSI.Unix
+
+        Extensions:             CPP
+                                ForeignFunctionInterface
+
+        Ghc-Options:                    -Wall
+
+Executable ansi-terminal-example
+        Main-Is:                System/Console/ANSI/Example.hs
+
+        Include-Dirs:           includes
+
+        Other-Modules:          System.Console.ANSI
+                                System.Console.ANSI.Codes
+                                System.Console.ANSI.Types
+                                System.Console.ANSI.Unix
+
+        if os(windows)
+                Build-Depends:          base-compat >= 0.9.1
+                                      , containers
+                                      , Win32 >= 2.0
+                Cpp-Options:            -DWINDOWS
+                Other-Modules:          System.Console.ANSI.Windows
+                                        System.Console.ANSI.Windows.Detect
+                                        System.Console.ANSI.Windows.Emulator
+                                        System.Console.ANSI.Windows.Emulator.Codes
+                                        System.Console.ANSI.Windows.Foreign
+        else
+                -- We assume any non-Windows platform is Unix
+                Cpp-Options:            -DUNIX
+
+        Build-Depends:          base >= 4 && < 5
+        Extensions:             CPP
+                                ForeignFunctionInterface
+
+        Ghc-Options:            -Wall
+
+        if !flag(example)
+                Buildable:              False
diff --git a/includes/Common-Include-Emulator.hs b/includes/Common-Include-Emulator.hs
--- a/includes/Common-Include-Emulator.hs
+++ b/includes/Common-Include-Emulator.hs
@@ -1,65 +1,65 @@
--- This file contains code that is required in the case of the module
--- System.Console.ANSI.Windows.Emulator and differs from the common code in
--- file Common-Include-Enabled.hs.
-
--- | Set the Select Graphic Rendition mode
-hSetSGR
-  :: ConsoleDefaultState -- ^ The default console state
-  -> Handle
-  -> [SGR] -- ^ Commands: these will typically be applied on top of the
-           -- current console SGR mode. An empty list of commands is
-           -- equivalent to the list @[Reset]@. Commands are applied left to
-           -- right.
-  -> IO ()
-
--- | Set the Select Graphic Rendition mode
-setSGR
-  :: ConsoleDefaultState -- ^ The default console state
-  -> [SGR] -- ^ Commands: these will typically be applied on top of the
-           -- current console SGR mode. An empty list of commands is
-           -- equivalent to the list @[Reset]@. Commands are applied left to
-           -- right.
-  -> IO ()
-setSGR def = hSetSGR def stdout
-
-hClearFromCursorToScreenEnd, hClearFromCursorToScreenBeginning, hClearScreen
-  :: ConsoleDefaultState -- ^ The default console state
-  -> Handle
-  -> IO ()
-
-clearFromCursorToScreenEnd, clearFromCursorToScreenBeginning, clearScreen
-  :: ConsoleDefaultState -- ^ The default console state
-  -> IO ()
-clearFromCursorToScreenEnd def = hClearFromCursorToScreenEnd def stdout
-clearFromCursorToScreenBeginning def
-  = hClearFromCursorToScreenBeginning def stdout
-clearScreen def = hClearScreen def stdout
-
-hClearFromCursorToLineEnd, hClearFromCursorToLineBeginning, hClearLine
-  :: ConsoleDefaultState -- ^ The default console state
-  -> Handle
-  -> IO ()
-
-clearFromCursorToLineEnd, clearFromCursorToLineBeginning, clearLine
-  :: ConsoleDefaultState -- ^ The default console state
-  -> IO ()
-clearFromCursorToLineEnd def = hClearFromCursorToLineEnd def stdout
-clearFromCursorToLineBeginning def = hClearFromCursorToLineBeginning def stdout
-clearLine def = hClearLine def stdout
-
--- | Scroll the displayed information up or down the terminal: not widely
--- supported
-hScrollPageUp, hScrollPageDown
-  :: ConsoleDefaultState -- ^ The default console state
-  -> Handle
-  -> Int -- ^ Number of lines to scroll by
-  -> IO ()
-
--- | Scroll the displayed information up or down the terminal: not widely
--- supported
-scrollPageUp, scrollPageDown
-  :: ConsoleDefaultState -- ^ The default console state
-  -> Int -- ^ Number of lines to scroll by
-  -> IO ()
-scrollPageUp def = hScrollPageUp def stdout
-scrollPageDown def = hScrollPageDown def stdout
+-- This file contains code that is required in the case of the module
+-- System.Console.ANSI.Windows.Emulator and differs from the common code in
+-- file Common-Include-Enabled.hs.
+
+-- | Set the Select Graphic Rendition mode
+hSetSGR
+  :: ConsoleDefaultState -- ^ The default console state
+  -> Handle
+  -> [SGR] -- ^ Commands: these will typically be applied on top of the
+           -- current console SGR mode. An empty list of commands is
+           -- equivalent to the list @[Reset]@. Commands are applied left to
+           -- right.
+  -> IO ()
+
+-- | Set the Select Graphic Rendition mode
+setSGR
+  :: ConsoleDefaultState -- ^ The default console state
+  -> [SGR] -- ^ Commands: these will typically be applied on top of the
+           -- current console SGR mode. An empty list of commands is
+           -- equivalent to the list @[Reset]@. Commands are applied left to
+           -- right.
+  -> IO ()
+setSGR def = hSetSGR def stdout
+
+hClearFromCursorToScreenEnd, hClearFromCursorToScreenBeginning, hClearScreen
+  :: ConsoleDefaultState -- ^ The default console state
+  -> Handle
+  -> IO ()
+
+clearFromCursorToScreenEnd, clearFromCursorToScreenBeginning, clearScreen
+  :: ConsoleDefaultState -- ^ The default console state
+  -> IO ()
+clearFromCursorToScreenEnd def = hClearFromCursorToScreenEnd def stdout
+clearFromCursorToScreenBeginning def
+  = hClearFromCursorToScreenBeginning def stdout
+clearScreen def = hClearScreen def stdout
+
+hClearFromCursorToLineEnd, hClearFromCursorToLineBeginning, hClearLine
+  :: ConsoleDefaultState -- ^ The default console state
+  -> Handle
+  -> IO ()
+
+clearFromCursorToLineEnd, clearFromCursorToLineBeginning, clearLine
+  :: ConsoleDefaultState -- ^ The default console state
+  -> IO ()
+clearFromCursorToLineEnd def = hClearFromCursorToLineEnd def stdout
+clearFromCursorToLineBeginning def = hClearFromCursorToLineBeginning def stdout
+clearLine def = hClearLine def stdout
+
+-- | Scroll the displayed information up or down the terminal: not widely
+-- supported
+hScrollPageUp, hScrollPageDown
+  :: ConsoleDefaultState -- ^ The default console state
+  -> Handle
+  -> Int -- ^ Number of lines to scroll by
+  -> IO ()
+
+-- | Scroll the displayed information up or down the terminal: not widely
+-- supported
+scrollPageUp, scrollPageDown
+  :: ConsoleDefaultState -- ^ The default console state
+  -> Int -- ^ Number of lines to scroll by
+  -> IO ()
+scrollPageUp def = hScrollPageUp def stdout
+scrollPageDown def = hScrollPageDown def stdout
diff --git a/includes/Common-Include-Enabled.hs b/includes/Common-Include-Enabled.hs
--- a/includes/Common-Include-Enabled.hs
+++ b/includes/Common-Include-Enabled.hs
@@ -1,56 +1,56 @@
--- This file contains code that is common save that different code is required
--- in the case of the module System.Console.ANSI.Windows.Emulator (see the file
--- Common-Include-Emulator.hs in respect of the latter).
-
--- | Set the Select Graphic Rendition mode
-hSetSGR
-  :: Handle
-  -> [SGR] -- ^ Commands: these will typically be applied on top of the
-           -- current console SGR mode. An empty list of commands is
-           -- equivalent to the list @[Reset]@. Commands are applied left to
-           -- right.
-  -> IO ()
-
--- | Set the Select Graphic Rendition mode
-setSGR
-  :: [SGR] -- ^ Commands: these will typically be applied on top of the
-           -- current console SGR mode. An empty list of commands is
-           -- equivalent to the list @[Reset]@. Commands are applied left to
-           -- right.
-  -> IO ()
-setSGR = hSetSGR stdout
-
-hClearFromCursorToScreenEnd, hClearFromCursorToScreenBeginning, hClearScreen
-  :: Handle
-  -> IO ()
-
-clearFromCursorToScreenEnd, clearFromCursorToScreenBeginning, clearScreen
-  :: IO ()
-clearFromCursorToScreenEnd = hClearFromCursorToScreenEnd stdout
-clearFromCursorToScreenBeginning = hClearFromCursorToScreenBeginning stdout
-clearScreen = hClearScreen stdout
-
-hClearFromCursorToLineEnd, hClearFromCursorToLineBeginning, hClearLine
-  :: Handle
-  -> IO ()
-
-clearFromCursorToLineEnd, clearFromCursorToLineBeginning, clearLine
-  :: IO ()
-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 ()
-scrollPageUp = hScrollPageUp stdout
-scrollPageDown = hScrollPageDown stdout
+-- This file contains code that is common save that different code is required
+-- in the case of the module System.Console.ANSI.Windows.Emulator (see the file
+-- Common-Include-Emulator.hs in respect of the latter).
+
+-- | Set the Select Graphic Rendition mode
+hSetSGR
+  :: Handle
+  -> [SGR] -- ^ Commands: these will typically be applied on top of the
+           -- current console SGR mode. An empty list of commands is
+           -- equivalent to the list @[Reset]@. Commands are applied left to
+           -- right.
+  -> IO ()
+
+-- | Set the Select Graphic Rendition mode
+setSGR
+  :: [SGR] -- ^ Commands: these will typically be applied on top of the
+           -- current console SGR mode. An empty list of commands is
+           -- equivalent to the list @[Reset]@. Commands are applied left to
+           -- right.
+  -> IO ()
+setSGR = hSetSGR stdout
+
+hClearFromCursorToScreenEnd, hClearFromCursorToScreenBeginning, hClearScreen
+  :: Handle
+  -> IO ()
+
+clearFromCursorToScreenEnd, clearFromCursorToScreenBeginning, clearScreen
+  :: IO ()
+clearFromCursorToScreenEnd = hClearFromCursorToScreenEnd stdout
+clearFromCursorToScreenBeginning = hClearFromCursorToScreenBeginning stdout
+clearScreen = hClearScreen stdout
+
+hClearFromCursorToLineEnd, hClearFromCursorToLineBeginning, hClearLine
+  :: Handle
+  -> IO ()
+
+clearFromCursorToLineEnd, clearFromCursorToLineBeginning, clearLine
+  :: IO ()
+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 ()
+scrollPageUp = hScrollPageUp stdout
+scrollPageDown = hScrollPageDown stdout
diff --git a/includes/Common-Include.hs b/includes/Common-Include.hs
--- a/includes/Common-Include.hs
+++ b/includes/Common-Include.hs
@@ -1,164 +1,164 @@
--- This file contains code that is common to modules System.Console.ANSI.Unix,
--- System.Console.ANSI.Windows and System.Console.ANSI.Windows.Emulator, such as
--- type signatures and the definition of functions specific to stdout in terms
--- of the corresponding more general functions, inclduding the related Haddock
--- documentation.
-
-import System.Environment
-#if !MIN_VERSION_base(4,8,0)
-import Control.Applicative
-#endif
-
-import Control.Monad (void)
-import Data.Char (isDigit)
-import Text.ParserCombinators.ReadP (char, many1, ReadP, satisfy)
-
-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 ()
-cursorUp = hCursorUp stdout
-cursorDown = hCursorDown stdout
-cursorForward = hCursorForward stdout
-cursorBackward = hCursorBackward stdout
-
-hCursorDownLine, hCursorUpLine :: Handle
-                               -> Int -- ^ Number of lines to move
-                               -> IO ()
-cursorDownLine, cursorUpLine :: Int -- ^ Number of lines to move
-                             -> IO ()
-cursorDownLine = hCursorDownLine stdout
-cursorUpLine = hCursorUpLine stdout
-
-hSetCursorColumn :: Handle
-                 -> Int -- ^ 0-based column to move to
-                 -> IO ()
-setCursorColumn :: Int -- ^ 0-based column to move to
-                -> IO ()
-setCursorColumn = hSetCursorColumn stdout
-
-hSetCursorPosition :: Handle
-                   -> Int -- ^ 0-based row to move to
-                   -> Int -- ^ 0-based column to move to
-                   -> IO ()
-setCursorPosition :: Int -- ^ 0-based row to move to
-                  -> Int -- ^ 0-based column to move to
-                  -> IO ()
-setCursorPosition = hSetCursorPosition stdout
-
-hSaveCursor, hRestoreCursor, hReportCursorPosition :: Handle -> IO ()
-
--- | Save the cursor position in memory. The only way to access the saved value
--- is with the 'restoreCursor' command.
-saveCursor :: IO ()
--- | Restore the cursor position from memory. There will be no value saved in
--- memory until the first use of the 'saveCursor' command.
-restoreCursor :: IO ()
--- | Looking for a way to get the cursors position? See
--- 'getCursorPosition'.
---
--- Emit the cursor position into the console input stream, immediately after
--- being recognised on the output stream, as:
--- @ESC [ \<cursor row> ; \<cursor column> R@
---
--- In isolation of 'getReportedCursorPosition' or 'getCursorPosition', this
--- function may be of limited use on Windows operating systems because of
--- difficulties in obtaining the data emitted into the console input stream.
--- The function 'hGetBufNonBlocking' in module "System.IO" does not work on
--- Windows. This has been attributed to the lack of non-blocking primatives in
--- the operating system (see the GHC bug report #806 at
--- <https://ghc.haskell.org/trac/ghc/ticket/806>).
-reportCursorPosition :: IO ()
-
-saveCursor = hSaveCursor stdout
-restoreCursor = hRestoreCursor stdout
-reportCursorPosition = hReportCursorPosition stdout
-
-hHideCursor, hShowCursor :: Handle
-                         -> IO ()
-hideCursor, showCursor :: IO ()
-hideCursor = hHideCursor stdout
-showCursor = hShowCursor stdout
-
--- | Set the terminal window title
-hSetTitle :: Handle
-          -> String -- ^ New title
-          -> IO ()
--- | Set the terminal window title
-setTitle :: String -- ^ New title
-         -> IO ()
-setTitle = hSetTitle stdout
-
--- | Use heuristics to determine whether the functions defined in this
--- package will work with a given handle.
---
--- The current implementation checks that the handle is a terminal, and
--- that the @TERM@ environment variable doesn't say @dumb@ (which is what
--- Emacs sets for its own terminal).
-hSupportsANSI :: Handle -> IO Bool
--- Borrowed from an HSpec patch by Simon Hengel
--- (https://github.com/hspec/hspec/commit/d932f03317e0e2bd08c85b23903fb8616ae642bd)
-hSupportsANSI h = (&&) <$> hIsTerminalDevice h <*> (not <$> isDumb)
- where
-  -- cannot use lookupEnv since it only appeared in GHC 7.6
-  isDumb = maybe False (== "dumb") . lookup "TERM" <$> getEnvironment
-
--- | Parses the characters emitted by 'reportCursorPosition' into the console
--- input stream. Returns the cursor row and column as a tuple.
---
--- For example, if the characters emitted by 'reportCursorPosition' are in
--- 'String' @input@ then the parser could be applied like this:
---
--- > let result = readP_to_S cursorPosition input
--- > case result of
--- >     [] -> putStrLn $ "Error: could not parse " ++ show input
--- >     [((row, column), _)] -> putStrLn $ "The cursor was at row " ++ show row
--- >         ++ " and column" ++ show column ++ "."
--- >     (_:_) -> putStrLn $ "Error: parse not unique"
---
-cursorPosition :: ReadP (Int, Int)
-cursorPosition = do
-  void $ char '\ESC'
-  void $ char '['
-  row <- decimal -- A non-negative whole decimal number
-  void $ char ';'
-  col <- decimal -- A non-negative whole decimal number
-  void $ char 'R'
-  return (read row, read col)
- where
-  digit = satisfy isDigit
-  decimal = many1 digit
-
--- | Attempts to get the reported cursor position data from the console input
--- stream. The function is intended to be called immediately after
--- 'reportCursorPosition' (or related functions) have caused characters to be
--- emitted into the stream.
---
--- For example, on a Unix-like operating system:
---
--- > hSetBuffering stdin NoBuffering -- set no buffering (the contents of the
--- >                                 -- buffer will be discarded, so this needs
--- >                                 -- to be done before the cursor positon is
--- >                                 -- emitted)
--- > reportCursorPosition
--- > hFlush stdout -- ensure the report cursor position code is sent to the
--- >               -- operating system
--- > input <- getReportedCursorPosition
---
--- On Windows operating systems, the function is not supported on consoles, such
--- as mintty, that are not based on the Win32 console of the Windows API.
--- (Command Prompt and PowerShell are based on the Win32 console.)
-getReportedCursorPosition :: IO String
-
--- | Attempts to get the reported cursor position, combining the functions
--- 'reportCursorPosition', 'getReportedCursorPosition' and 'cursorPosition'.
--- Returns 'Nothing' if any data emitted by 'reportCursorPosition', obtained by
--- 'getReportedCursorPosition', cannot be parsed by 'cursorPosition'.
---
--- On Windows operating systems, the function is not supported on consoles, such
--- as mintty, that are not based on the Win32 console of the Windows API.
--- (Command Prompt and PowerShell are based on the Win32 console.)
-getCursorPosition :: IO (Maybe (Int, Int))
+-- This file contains code that is common to modules System.Console.ANSI.Unix,
+-- System.Console.ANSI.Windows and System.Console.ANSI.Windows.Emulator, such as
+-- type signatures and the definition of functions specific to stdout in terms
+-- of the corresponding more general functions, inclduding the related Haddock
+-- documentation.
+
+import System.Environment
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative
+#endif
+
+import Control.Monad (void)
+import Data.Char (isDigit)
+import Text.ParserCombinators.ReadP (char, many1, ReadP, satisfy)
+
+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 ()
+cursorUp = hCursorUp stdout
+cursorDown = hCursorDown stdout
+cursorForward = hCursorForward stdout
+cursorBackward = hCursorBackward stdout
+
+hCursorDownLine, hCursorUpLine :: Handle
+                               -> Int -- ^ Number of lines to move
+                               -> IO ()
+cursorDownLine, cursorUpLine :: Int -- ^ Number of lines to move
+                             -> IO ()
+cursorDownLine = hCursorDownLine stdout
+cursorUpLine = hCursorUpLine stdout
+
+hSetCursorColumn :: Handle
+                 -> Int -- ^ 0-based column to move to
+                 -> IO ()
+setCursorColumn :: Int -- ^ 0-based column to move to
+                -> IO ()
+setCursorColumn = hSetCursorColumn stdout
+
+hSetCursorPosition :: Handle
+                   -> Int -- ^ 0-based row to move to
+                   -> Int -- ^ 0-based column to move to
+                   -> IO ()
+setCursorPosition :: Int -- ^ 0-based row to move to
+                  -> Int -- ^ 0-based column to move to
+                  -> IO ()
+setCursorPosition = hSetCursorPosition stdout
+
+hSaveCursor, hRestoreCursor, hReportCursorPosition :: Handle -> IO ()
+
+-- | Save the cursor position in memory. The only way to access the saved value
+-- is with the 'restoreCursor' command.
+saveCursor :: IO ()
+-- | Restore the cursor position from memory. There will be no value saved in
+-- memory until the first use of the 'saveCursor' command.
+restoreCursor :: IO ()
+-- | Looking for a way to get the cursors position? See
+-- 'getCursorPosition'.
+--
+-- Emit the cursor position into the console input stream, immediately after
+-- being recognised on the output stream, as:
+-- @ESC [ \<cursor row> ; \<cursor column> R@
+--
+-- In isolation of 'getReportedCursorPosition' or 'getCursorPosition', this
+-- function may be of limited use on Windows operating systems because of
+-- difficulties in obtaining the data emitted into the console input stream.
+-- The function 'hGetBufNonBlocking' in module "System.IO" does not work on
+-- Windows. This has been attributed to the lack of non-blocking primatives in
+-- the operating system (see the GHC bug report #806 at
+-- <https://ghc.haskell.org/trac/ghc/ticket/806>).
+reportCursorPosition :: IO ()
+
+saveCursor = hSaveCursor stdout
+restoreCursor = hRestoreCursor stdout
+reportCursorPosition = hReportCursorPosition stdout
+
+hHideCursor, hShowCursor :: Handle
+                         -> IO ()
+hideCursor, showCursor :: IO ()
+hideCursor = hHideCursor stdout
+showCursor = hShowCursor stdout
+
+-- | Set the terminal window title
+hSetTitle :: Handle
+          -> String -- ^ New title
+          -> IO ()
+-- | Set the terminal window title
+setTitle :: String -- ^ New title
+         -> IO ()
+setTitle = hSetTitle stdout
+
+-- | Use heuristics to determine whether the functions defined in this
+-- package will work with a given handle.
+--
+-- The current implementation checks that the handle is a terminal, and
+-- that the @TERM@ environment variable doesn't say @dumb@ (which is what
+-- Emacs sets for its own terminal).
+hSupportsANSI :: Handle -> IO Bool
+-- Borrowed from an HSpec patch by Simon Hengel
+-- (https://github.com/hspec/hspec/commit/d932f03317e0e2bd08c85b23903fb8616ae642bd)
+hSupportsANSI h = (&&) <$> hIsTerminalDevice h <*> (not <$> isDumb)
+ where
+  -- cannot use lookupEnv since it only appeared in GHC 7.6
+  isDumb = maybe False (== "dumb") . lookup "TERM" <$> getEnvironment
+
+-- | Parses the characters emitted by 'reportCursorPosition' into the console
+-- input stream. Returns the cursor row and column as a tuple.
+--
+-- For example, if the characters emitted by 'reportCursorPosition' are in
+-- 'String' @input@ then the parser could be applied like this:
+--
+-- > let result = readP_to_S cursorPosition input
+-- > case result of
+-- >     [] -> putStrLn $ "Error: could not parse " ++ show input
+-- >     [((row, column), _)] -> putStrLn $ "The cursor was at row " ++ show row
+-- >         ++ " and column" ++ show column ++ "."
+-- >     (_:_) -> putStrLn $ "Error: parse not unique"
+--
+cursorPosition :: ReadP (Int, Int)
+cursorPosition = do
+  void $ char '\ESC'
+  void $ char '['
+  row <- decimal -- A non-negative whole decimal number
+  void $ char ';'
+  col <- decimal -- A non-negative whole decimal number
+  void $ char 'R'
+  return (read row, read col)
+ where
+  digit = satisfy isDigit
+  decimal = many1 digit
+
+-- | Attempts to get the reported cursor position data from the console input
+-- stream. The function is intended to be called immediately after
+-- 'reportCursorPosition' (or related functions) have caused characters to be
+-- emitted into the stream.
+--
+-- For example, on a Unix-like operating system:
+--
+-- > hSetBuffering stdin NoBuffering -- set no buffering (the contents of the
+-- >                                 -- buffer will be discarded, so this needs
+-- >                                 -- to be done before the cursor positon is
+-- >                                 -- emitted)
+-- > reportCursorPosition
+-- > hFlush stdout -- ensure the report cursor position code is sent to the
+-- >               -- operating system
+-- > input <- getReportedCursorPosition
+--
+-- On Windows operating systems, the function is not supported on consoles, such
+-- as mintty, that are not based on the Win32 console of the Windows API.
+-- (Command Prompt and PowerShell are based on the Win32 console.)
+getReportedCursorPosition :: IO String
+
+-- | Attempts to get the reported cursor position, combining the functions
+-- 'reportCursorPosition', 'getReportedCursorPosition' and 'cursorPosition'.
+-- Returns 'Nothing' if any data emitted by 'reportCursorPosition', obtained by
+-- 'getReportedCursorPosition', cannot be parsed by 'cursorPosition'.
+--
+-- On Windows operating systems, the function is not supported on consoles, such
+-- as mintty, that are not based on the Win32 console of the Windows API.
+-- (Command Prompt and PowerShell are based on the Win32 console.)
+getCursorPosition :: IO (Maybe (Int, Int))
diff --git a/includes/Exports-Include.hs b/includes/Exports-Include.hs
--- a/includes/Exports-Include.hs
+++ b/includes/Exports-Include.hs
@@ -1,114 +1,114 @@
--- This file contains code that is common to modules
--- System.Console.ANSI.Unix and System.Console.ANSI.Windows, namely the module
--- exports and the associated Haddock documentation.
-
-    -- * Basic data types
-    module System.Console.ANSI.Types
-
-    -- * Cursor movement by character
-  , cursorUp
-  , cursorDown
-  , cursorForward
-  , cursorBackward
-  , hCursorUp
-  , hCursorDown
-  , hCursorForward
-  , hCursorBackward
-  , cursorUpCode
-  , cursorDownCode
-  , cursorForwardCode
-  , cursorBackwardCode
-
-    -- * Cursor movement by line
-    -- | The difference between movements \"by character\" and \"by line\" is
-    -- that @*Line@ functions additionally move the cursor to the start of the
-    -- line, while functions like @cursorUp@ and @cursorDown@ keep the column
-    -- the same.
-    --
-    -- Also keep in mind that @*Line@ functions are not as portable. See
-    -- <https://github.com/feuerbach/ansi-terminal/issues/10> for the details.
-  , cursorUpLine
-  , cursorDownLine
-  , hCursorUpLine
-  , hCursorDownLine
-  , cursorUpLineCode
-  , cursorDownLineCode
-
-    -- * Directly changing cursor position
-  , setCursorColumn
-  , hSetCursorColumn
-  , setCursorColumnCode
-
-  , setCursorPosition
-  , hSetCursorPosition
-  , setCursorPositionCode
-
-    -- * Saving, restoring and reporting cursor position
-  , saveCursor
-  , hSaveCursor
-  , saveCursorCode
-
-  , restoreCursor
-  , hRestoreCursor
-  , restoreCursorCode
-
-  , reportCursorPosition
-  , hReportCursorPosition
-  , reportCursorPositionCode
-
-    -- * Clearing parts of the screen
-    -- | Note that these functions only clear parts of the screen. They do not move the
-    -- cursor.
-  , 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
-
-    -- * Cursor visibilty changes
-  , hideCursor
-  , showCursor
-  , hHideCursor
-  , hShowCursor
-  , hideCursorCode
-  , showCursorCode
-
-    -- * Changing the title
-  , setTitle
-  , hSetTitle
-  , setTitleCode
-
-    -- * Checking if handle supports ANSI
-  , hSupportsANSI
-
-    -- * Getting the cursor position
-  , getCursorPosition
-  , getReportedCursorPosition
-  , cursorPosition
+-- This file contains code that is common to modules
+-- System.Console.ANSI.Unix and System.Console.ANSI.Windows, namely the module
+-- exports and the associated Haddock documentation.
+
+    -- * Basic data types
+    module System.Console.ANSI.Types
+
+    -- * Cursor movement by character
+  , cursorUp
+  , cursorDown
+  , cursorForward
+  , cursorBackward
+  , hCursorUp
+  , hCursorDown
+  , hCursorForward
+  , hCursorBackward
+  , cursorUpCode
+  , cursorDownCode
+  , cursorForwardCode
+  , cursorBackwardCode
+
+    -- * Cursor movement by line
+    -- | The difference between movements \"by character\" and \"by line\" is
+    -- that @*Line@ functions additionally move the cursor to the start of the
+    -- line, while functions like @cursorUp@ and @cursorDown@ keep the column
+    -- the same.
+    --
+    -- Also keep in mind that @*Line@ functions are not as portable. See
+    -- <https://github.com/feuerbach/ansi-terminal/issues/10> for the details.
+  , cursorUpLine
+  , cursorDownLine
+  , hCursorUpLine
+  , hCursorDownLine
+  , cursorUpLineCode
+  , cursorDownLineCode
+
+    -- * Directly changing cursor position
+  , setCursorColumn
+  , hSetCursorColumn
+  , setCursorColumnCode
+
+  , setCursorPosition
+  , hSetCursorPosition
+  , setCursorPositionCode
+
+    -- * Saving, restoring and reporting cursor position
+  , saveCursor
+  , hSaveCursor
+  , saveCursorCode
+
+  , restoreCursor
+  , hRestoreCursor
+  , restoreCursorCode
+
+  , reportCursorPosition
+  , hReportCursorPosition
+  , reportCursorPositionCode
+
+    -- * Clearing parts of the screen
+    -- | Note that these functions only clear parts of the screen. They do not move the
+    -- cursor.
+  , 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
+
+    -- * Cursor visibilty changes
+  , hideCursor
+  , showCursor
+  , hHideCursor
+  , hShowCursor
+  , hideCursorCode
+  , showCursorCode
+
+    -- * Changing the title
+  , setTitle
+  , hSetTitle
+  , setTitleCode
+
+    -- * Checking if handle supports ANSI
+  , hSupportsANSI
+
+    -- * Getting the cursor position
+  , getCursorPosition
+  , getReportedCursorPosition
+  , cursorPosition
