diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,23 @@
 
+5.26
+ - Resolved various import warnings (thanks @glguy)
+ - Removed the MonadIO constraint from the Output type's fields and
+   removed MonadFail uses (PR #177, thanks @glguy)
+ - Clarified documentation for ANSI colors (thanks Colby Jenn)
+ - Graphics.Vty.Attributes no longer re-exports
+   Graphics.Vty.Attributes.Color
+ - The Graphics.Vty.Attributes.Color module is now exposed (thanks Colby
+   Jenn)
+ - Raised upper bound for microlens to 0.4.12 (thanks Artyom Kazak)
+ - Changed from using System.Posix.Env.getEnv to
+   System.Environment.lookupEnv (thanks Jonathan Osser)
+ - Added Graphics.Vty.Image functions for dealing with character width
+   computations on Text values instead of Strings:
+   - safeWctwidth
+   - safeWctlwidth
+   - wctwidth
+   - wctlwidth
+
 5.25.1
  - Avoided a conflict with a Microlens 0.4.10 operator and added an
    upper bound on Microlens of 0.4.11.
diff --git a/src/Graphics/Text/Width.hs b/src/Graphics/Text/Width.hs
--- a/src/Graphics/Text/Width.hs
+++ b/src/Graphics/Text/Width.hs
@@ -4,16 +4,36 @@
 module Graphics.Text.Width
   ( wcwidth
   , wcswidth
+  , wctwidth
+  , wctlwidth
   , safeWcwidth
   , safeWcswidth
+  , safeWctwidth
+  , safeWctlwidth
   )
 where
 
+import Data.List (foldl')
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+
 foreign import ccall unsafe "vty_mk_wcwidth" wcwidth :: Char -> Int
 
 wcswidth :: String -> Int
-wcswidth = sum . map wcwidth
+wcswidth = foldl' (\l c -> wcwidth c + l) 0
+{-# INLINE [1] wcswidth #-}
 
+wctwidth :: T.Text -> Int
+wctwidth = T.foldl' (\l c -> wcwidth c + l) 0
+
+wctlwidth :: TL.Text -> Int
+wctlwidth = TL.foldl' (\l c -> wcwidth c + l) 0
+
+{-# RULES
+"wcswidth/unpack" forall x. wcswidth (T.unpack x) = wctwidth x
+"wcswidth/lazy-unpack" forall x. wcswidth (TL.unpack x) = wctlwidth x
+  #-}
+
 -- XXX: Characters with unknown widths occupy 1 column?
 --
 -- Not sure if this is actually correct. I presume there is a
@@ -30,4 +50,14 @@
 -- | Returns the display width of a string. Assumes all characters with
 -- unknown widths are 0 width.
 safeWcswidth :: String -> Int
-safeWcswidth = sum . map safeWcwidth
+safeWcswidth = foldl' (\l c -> safeWcwidth c + l) 0
+
+-- | Returns the display width of a text. Assumes all characters with
+-- unknown widths are 0 width.
+safeWctwidth :: T.Text -> Int
+safeWctwidth = T.foldl' (\l c -> safeWcwidth c + l) 0
+
+-- | Returns the display width of a lazy text. Assumes all characters
+-- with unknown widths are 0 width.
+safeWctlwidth :: TL.Text -> Int
+safeWctlwidth = TL.foldl' (\l c -> safeWcwidth c + l) 0
diff --git a/src/Graphics/Vty/Attributes.hs b/src/Graphics/Vty/Attributes.hs
--- a/src/Graphics/Vty/Attributes.hs
+++ b/src/Graphics/Vty/Attributes.hs
@@ -30,7 +30,9 @@
 -- The value 'currentAttr' will keep the attributes of whatever was
 -- output previously.
 module Graphics.Vty.Attributes
-  ( Attr(..)
+  ( module Graphics.Vty.Attributes.Color
+
+  , Attr(..)
   , FixedAttr(..)
   , MaybeDefault(..)
   , defAttr
@@ -56,10 +58,6 @@
 
   -- * Setting hyperlinks
   , withURL
-
-  -- * Colors
-  , module Graphics.Vty.Attributes.Color
-  , module Graphics.Vty.Attributes.Color240
   )
 where
 
@@ -73,7 +71,6 @@
 import GHC.Generics
 
 import Graphics.Vty.Attributes.Color
-import Graphics.Vty.Attributes.Color240
 
 -- | A display attribute defines the Color and Style of all the
 -- characters rendered after the attribute is applied.
diff --git a/src/Graphics/Vty/Attributes/Color.hs b/src/Graphics/Vty/Attributes/Color.hs
--- a/src/Graphics/Vty/Attributes/Color.hs
+++ b/src/Graphics/Vty/Attributes/Color.hs
@@ -1,7 +1,18 @@
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE DeriveAnyClass #-}
+
 module Graphics.Vty.Attributes.Color
   ( Color(..)
+
+  -- ** Fixed Colors
+  -- | Standard 8-color ANSI terminal color codes.
+  --
+  -- Note that these map to colors in the terminal's custom palette. For
+  -- instance, `white` maps to whatever the terminal color theme uses for
+  -- white.
+  --
+  -- Use these functions if you want to make apps that fit the terminal theme.
+  -- If you want access to more/stronger colors use `rgbColor`
   , black
   , red
   , green
@@ -10,6 +21,8 @@
   , magenta
   , cyan
   , white
+
+  -- | Bright/Vivid variants of the standard 8-color ANSI
   , brightBlack
   , brightRed
   , brightGreen
@@ -18,6 +31,9 @@
   , brightMagenta
   , brightCyan
   , brightWhite
+  -- ** Creating Colors From RGB
+  , rgbColor
+  , module Graphics.Vty.Attributes.Color240
   )
 where
 
@@ -25,6 +41,8 @@
 import GHC.Generics
 import Control.DeepSeq
 
+import Graphics.Vty.Attributes.Color240
+
 -- | Abstract data type representing a color.
 --
 -- Currently the foreground and background color are specified as points
@@ -80,7 +98,6 @@
 data Color = ISOColor !Word8 | Color240 !Word8
     deriving ( Eq, Show, Read, Generic, NFData )
 
--- | Standard 8-color ANSI terminal color codes.
 black, red, green, yellow, blue, magenta, cyan, white :: Color
 black  = ISOColor 0
 red    = ISOColor 1
@@ -91,7 +108,6 @@
 cyan   = ISOColor 6
 white  = ISOColor 7
 
--- | Bright/Vivid variants of the standard 8-color ANSI
 brightBlack, brightRed, brightGreen, brightYellow :: Color
 brightBlue, brightMagenta, brightCyan, brightWhite :: Color
 brightBlack  = ISOColor 8
@@ -102,3 +118,10 @@
 brightMagenta= ISOColor 13
 brightCyan   = ISOColor 14
 brightWhite  = ISOColor 15
+
+
+-- | Create a Vty 'Color' (in the 240 color set) from an RGB triple.
+-- This function is lossy in the sense that we only internally support 240 colors but the
+-- #RRGGBB format supports 16^3 colors.
+rgbColor :: Integral i => i -> i -> i -> Color
+rgbColor r g b = Color240 (rgbColorToColor240 r g b)
diff --git a/src/Graphics/Vty/Attributes/Color240.hs b/src/Graphics/Vty/Attributes/Color240.hs
--- a/src/Graphics/Vty/Attributes/Color240.hs
+++ b/src/Graphics/Vty/Attributes/Color240.hs
@@ -1,264 +1,260 @@
 -- This header file was generated by ./256colres.pl
 module Graphics.Vty.Attributes.Color240
-  ( rgbColor
+  ( rgbColorToColor240
   , color240CodeToRGB
   )
 where
 
-import Graphics.Vty.Attributes.Color
-
 import Data.Word (Word8)
 import Text.Printf
 
 -- Note: rgbColor's mapping from RGB to 240 colors was generated from
 -- 256colres.pl which is forked from xterm 256colres.pl.
 
--- | Create a Vty 'Color' (in the 240 color set) from an RGB triple.
--- This function is lossy in the sense that we only internally support 240 colors but the
--- #RRGGBB format supports 16^3 colors.
-rgbColor :: Integral i => i -> i -> i -> Color
-rgbColor r g b
+-- | Create a value in the Color240 set from an RGB triple
+rgbColorToColor240 :: Integral i => i -> i -> i -> Word8
+rgbColorToColor240 r g b
     | r < 0 && g < 0 && b < 0 = error "rgbColor with negative color component intensity"
-    | r == 8 && g == 8 && b == 8 = Color240 216
-    | r == 18 && g == 18 && b == 18 = Color240 217
-    | r == 28 && g == 28 && b == 28 = Color240 218
-    | r == 38 && g == 38 && b == 38 = Color240 219
-    | r == 48 && g == 48 && b == 48 = Color240 220
-    | r == 58 && g == 58 && b == 58 = Color240 221
-    | r == 68 && g == 68 && b == 68 = Color240 222
-    | r == 78 && g == 78 && b == 78 = Color240 223
-    | r == 88 && g == 88 && b == 88 = Color240 224
-    | r == 98 && g == 98 && b == 98 = Color240 225
-    | r == 108 && g == 108 && b == 108 = Color240 226
-    | r == 118 && g == 118 && b == 118 = Color240 227
-    | r == 128 && g == 128 && b == 128 = Color240 228
-    | r == 138 && g == 138 && b == 138 = Color240 229
-    | r == 148 && g == 148 && b == 148 = Color240 230
-    | r == 158 && g == 158 && b == 158 = Color240 231
-    | r == 168 && g == 168 && b == 168 = Color240 232
-    | r == 178 && g == 178 && b == 178 = Color240 233
-    | r == 188 && g == 188 && b == 188 = Color240 234
-    | r == 198 && g == 198 && b == 198 = Color240 235
-    | r == 208 && g == 208 && b == 208 = Color240 236
-    | r == 218 && g == 218 && b == 218 = Color240 237
-    | r == 228 && g == 228 && b == 228 = Color240 238
-    | r == 238 && g == 238 && b == 238 = Color240 239
-    | r <= 0 && g <= 0 && b <= 0 = Color240 0
-    | r <= 0 && g <= 0 && b <= 95 = Color240 1
-    | r <= 0 && g <= 0 && b <= 135 = Color240 2
-    | r <= 0 && g <= 0 && b <= 175 = Color240 3
-    | r <= 0 && g <= 0 && b <= 215 = Color240 4
-    | r <= 0 && g <= 0 && b <= 255 = Color240 5
-    | r <= 0 && g <= 95 && b <= 0 = Color240 6
-    | r <= 0 && g <= 95 && b <= 95 = Color240 7
-    | r <= 0 && g <= 95 && b <= 135 = Color240 8
-    | r <= 0 && g <= 95 && b <= 175 = Color240 9
-    | r <= 0 && g <= 95 && b <= 215 = Color240 10
-    | r <= 0 && g <= 95 && b <= 255 = Color240 11
-    | r <= 0 && g <= 135 && b <= 0 = Color240 12
-    | r <= 0 && g <= 135 && b <= 95 = Color240 13
-    | r <= 0 && g <= 135 && b <= 135 = Color240 14
-    | r <= 0 && g <= 135 && b <= 175 = Color240 15
-    | r <= 0 && g <= 135 && b <= 215 = Color240 16
-    | r <= 0 && g <= 135 && b <= 255 = Color240 17
-    | r <= 0 && g <= 175 && b <= 0 = Color240 18
-    | r <= 0 && g <= 175 && b <= 95 = Color240 19
-    | r <= 0 && g <= 175 && b <= 135 = Color240 20
-    | r <= 0 && g <= 175 && b <= 175 = Color240 21
-    | r <= 0 && g <= 175 && b <= 215 = Color240 22
-    | r <= 0 && g <= 175 && b <= 255 = Color240 23
-    | r <= 0 && g <= 215 && b <= 0 = Color240 24
-    | r <= 0 && g <= 215 && b <= 95 = Color240 25
-    | r <= 0 && g <= 215 && b <= 135 = Color240 26
-    | r <= 0 && g <= 215 && b <= 175 = Color240 27
-    | r <= 0 && g <= 215 && b <= 215 = Color240 28
-    | r <= 0 && g <= 215 && b <= 255 = Color240 29
-    | r <= 0 && g <= 255 && b <= 0 = Color240 30
-    | r <= 0 && g <= 255 && b <= 95 = Color240 31
-    | r <= 0 && g <= 255 && b <= 135 = Color240 32
-    | r <= 0 && g <= 255 && b <= 175 = Color240 33
-    | r <= 0 && g <= 255 && b <= 215 = Color240 34
-    | r <= 0 && g <= 255 && b <= 255 = Color240 35
-    | r <= 95 && g <= 0 && b <= 0 = Color240 36
-    | r <= 95 && g <= 0 && b <= 95 = Color240 37
-    | r <= 95 && g <= 0 && b <= 135 = Color240 38
-    | r <= 95 && g <= 0 && b <= 175 = Color240 39
-    | r <= 95 && g <= 0 && b <= 215 = Color240 40
-    | r <= 95 && g <= 0 && b <= 255 = Color240 41
-    | r <= 95 && g <= 95 && b <= 0 = Color240 42
-    | r <= 95 && g <= 95 && b <= 95 = Color240 43
-    | r <= 95 && g <= 95 && b <= 135 = Color240 44
-    | r <= 95 && g <= 95 && b <= 175 = Color240 45
-    | r <= 95 && g <= 95 && b <= 215 = Color240 46
-    | r <= 95 && g <= 95 && b <= 255 = Color240 47
-    | r <= 95 && g <= 135 && b <= 0 = Color240 48
-    | r <= 95 && g <= 135 && b <= 95 = Color240 49
-    | r <= 95 && g <= 135 && b <= 135 = Color240 50
-    | r <= 95 && g <= 135 && b <= 175 = Color240 51
-    | r <= 95 && g <= 135 && b <= 215 = Color240 52
-    | r <= 95 && g <= 135 && b <= 255 = Color240 53
-    | r <= 95 && g <= 175 && b <= 0 = Color240 54
-    | r <= 95 && g <= 175 && b <= 95 = Color240 55
-    | r <= 95 && g <= 175 && b <= 135 = Color240 56
-    | r <= 95 && g <= 175 && b <= 175 = Color240 57
-    | r <= 95 && g <= 175 && b <= 215 = Color240 58
-    | r <= 95 && g <= 175 && b <= 255 = Color240 59
-    | r <= 95 && g <= 215 && b <= 0 = Color240 60
-    | r <= 95 && g <= 215 && b <= 95 = Color240 61
-    | r <= 95 && g <= 215 && b <= 135 = Color240 62
-    | r <= 95 && g <= 215 && b <= 175 = Color240 63
-    | r <= 95 && g <= 215 && b <= 215 = Color240 64
-    | r <= 95 && g <= 215 && b <= 255 = Color240 65
-    | r <= 95 && g <= 255 && b <= 0 = Color240 66
-    | r <= 95 && g <= 255 && b <= 95 = Color240 67
-    | r <= 95 && g <= 255 && b <= 135 = Color240 68
-    | r <= 95 && g <= 255 && b <= 175 = Color240 69
-    | r <= 95 && g <= 255 && b <= 215 = Color240 70
-    | r <= 95 && g <= 255 && b <= 255 = Color240 71
-    | r <= 135 && g <= 0 && b <= 0 = Color240 72
-    | r <= 135 && g <= 0 && b <= 95 = Color240 73
-    | r <= 135 && g <= 0 && b <= 135 = Color240 74
-    | r <= 135 && g <= 0 && b <= 175 = Color240 75
-    | r <= 135 && g <= 0 && b <= 215 = Color240 76
-    | r <= 135 && g <= 0 && b <= 255 = Color240 77
-    | r <= 135 && g <= 95 && b <= 0 = Color240 78
-    | r <= 135 && g <= 95 && b <= 95 = Color240 79
-    | r <= 135 && g <= 95 && b <= 135 = Color240 80
-    | r <= 135 && g <= 95 && b <= 175 = Color240 81
-    | r <= 135 && g <= 95 && b <= 215 = Color240 82
-    | r <= 135 && g <= 95 && b <= 255 = Color240 83
-    | r <= 135 && g <= 135 && b <= 0 = Color240 84
-    | r <= 135 && g <= 135 && b <= 95 = Color240 85
-    | r <= 135 && g <= 135 && b <= 135 = Color240 86
-    | r <= 135 && g <= 135 && b <= 175 = Color240 87
-    | r <= 135 && g <= 135 && b <= 215 = Color240 88
-    | r <= 135 && g <= 135 && b <= 255 = Color240 89
-    | r <= 135 && g <= 175 && b <= 0 = Color240 90
-    | r <= 135 && g <= 175 && b <= 95 = Color240 91
-    | r <= 135 && g <= 175 && b <= 135 = Color240 92
-    | r <= 135 && g <= 175 && b <= 175 = Color240 93
-    | r <= 135 && g <= 175 && b <= 215 = Color240 94
-    | r <= 135 && g <= 175 && b <= 255 = Color240 95
-    | r <= 135 && g <= 215 && b <= 0 = Color240 96
-    | r <= 135 && g <= 215 && b <= 95 = Color240 97
-    | r <= 135 && g <= 215 && b <= 135 = Color240 98
-    | r <= 135 && g <= 215 && b <= 175 = Color240 99
-    | r <= 135 && g <= 215 && b <= 215 = Color240 100
-    | r <= 135 && g <= 215 && b <= 255 = Color240 101
-    | r <= 135 && g <= 255 && b <= 0 = Color240 102
-    | r <= 135 && g <= 255 && b <= 95 = Color240 103
-    | r <= 135 && g <= 255 && b <= 135 = Color240 104
-    | r <= 135 && g <= 255 && b <= 175 = Color240 105
-    | r <= 135 && g <= 255 && b <= 215 = Color240 106
-    | r <= 135 && g <= 255 && b <= 255 = Color240 107
-    | r <= 175 && g <= 0 && b <= 0 = Color240 108
-    | r <= 175 && g <= 0 && b <= 95 = Color240 109
-    | r <= 175 && g <= 0 && b <= 135 = Color240 110
-    | r <= 175 && g <= 0 && b <= 175 = Color240 111
-    | r <= 175 && g <= 0 && b <= 215 = Color240 112
-    | r <= 175 && g <= 0 && b <= 255 = Color240 113
-    | r <= 175 && g <= 95 && b <= 0 = Color240 114
-    | r <= 175 && g <= 95 && b <= 95 = Color240 115
-    | r <= 175 && g <= 95 && b <= 135 = Color240 116
-    | r <= 175 && g <= 95 && b <= 175 = Color240 117
-    | r <= 175 && g <= 95 && b <= 215 = Color240 118
-    | r <= 175 && g <= 95 && b <= 255 = Color240 119
-    | r <= 175 && g <= 135 && b <= 0 = Color240 120
-    | r <= 175 && g <= 135 && b <= 95 = Color240 121
-    | r <= 175 && g <= 135 && b <= 135 = Color240 122
-    | r <= 175 && g <= 135 && b <= 175 = Color240 123
-    | r <= 175 && g <= 135 && b <= 215 = Color240 124
-    | r <= 175 && g <= 135 && b <= 255 = Color240 125
-    | r <= 175 && g <= 175 && b <= 0 = Color240 126
-    | r <= 175 && g <= 175 && b <= 95 = Color240 127
-    | r <= 175 && g <= 175 && b <= 135 = Color240 128
-    | r <= 175 && g <= 175 && b <= 175 = Color240 129
-    | r <= 175 && g <= 175 && b <= 215 = Color240 130
-    | r <= 175 && g <= 175 && b <= 255 = Color240 131
-    | r <= 175 && g <= 215 && b <= 0 = Color240 132
-    | r <= 175 && g <= 215 && b <= 95 = Color240 133
-    | r <= 175 && g <= 215 && b <= 135 = Color240 134
-    | r <= 175 && g <= 215 && b <= 175 = Color240 135
-    | r <= 175 && g <= 215 && b <= 215 = Color240 136
-    | r <= 175 && g <= 215 && b <= 255 = Color240 137
-    | r <= 175 && g <= 255 && b <= 0 = Color240 138
-    | r <= 175 && g <= 255 && b <= 95 = Color240 139
-    | r <= 175 && g <= 255 && b <= 135 = Color240 140
-    | r <= 175 && g <= 255 && b <= 175 = Color240 141
-    | r <= 175 && g <= 255 && b <= 215 = Color240 142
-    | r <= 175 && g <= 255 && b <= 255 = Color240 143
-    | r <= 215 && g <= 0 && b <= 0 = Color240 144
-    | r <= 215 && g <= 0 && b <= 95 = Color240 145
-    | r <= 215 && g <= 0 && b <= 135 = Color240 146
-    | r <= 215 && g <= 0 && b <= 175 = Color240 147
-    | r <= 215 && g <= 0 && b <= 215 = Color240 148
-    | r <= 215 && g <= 0 && b <= 255 = Color240 149
-    | r <= 215 && g <= 95 && b <= 0 = Color240 150
-    | r <= 215 && g <= 95 && b <= 95 = Color240 151
-    | r <= 215 && g <= 95 && b <= 135 = Color240 152
-    | r <= 215 && g <= 95 && b <= 175 = Color240 153
-    | r <= 215 && g <= 95 && b <= 215 = Color240 154
-    | r <= 215 && g <= 95 && b <= 255 = Color240 155
-    | r <= 215 && g <= 135 && b <= 0 = Color240 156
-    | r <= 215 && g <= 135 && b <= 95 = Color240 157
-    | r <= 215 && g <= 135 && b <= 135 = Color240 158
-    | r <= 215 && g <= 135 && b <= 175 = Color240 159
-    | r <= 215 && g <= 135 && b <= 215 = Color240 160
-    | r <= 215 && g <= 135 && b <= 255 = Color240 161
-    | r <= 215 && g <= 175 && b <= 0 = Color240 162
-    | r <= 215 && g <= 175 && b <= 95 = Color240 163
-    | r <= 215 && g <= 175 && b <= 135 = Color240 164
-    | r <= 215 && g <= 175 && b <= 175 = Color240 165
-    | r <= 215 && g <= 175 && b <= 215 = Color240 166
-    | r <= 215 && g <= 175 && b <= 255 = Color240 167
-    | r <= 215 && g <= 215 && b <= 0 = Color240 168
-    | r <= 215 && g <= 215 && b <= 95 = Color240 169
-    | r <= 215 && g <= 215 && b <= 135 = Color240 170
-    | r <= 215 && g <= 215 && b <= 175 = Color240 171
-    | r <= 215 && g <= 215 && b <= 215 = Color240 172
-    | r <= 215 && g <= 215 && b <= 255 = Color240 173
-    | r <= 215 && g <= 255 && b <= 0 = Color240 174
-    | r <= 215 && g <= 255 && b <= 95 = Color240 175
-    | r <= 215 && g <= 255 && b <= 135 = Color240 176
-    | r <= 215 && g <= 255 && b <= 175 = Color240 177
-    | r <= 215 && g <= 255 && b <= 215 = Color240 178
-    | r <= 215 && g <= 255 && b <= 255 = Color240 179
-    | r <= 255 && g <= 0 && b <= 0 = Color240 180
-    | r <= 255 && g <= 0 && b <= 95 = Color240 181
-    | r <= 255 && g <= 0 && b <= 135 = Color240 182
-    | r <= 255 && g <= 0 && b <= 175 = Color240 183
-    | r <= 255 && g <= 0 && b <= 215 = Color240 184
-    | r <= 255 && g <= 0 && b <= 255 = Color240 185
-    | r <= 255 && g <= 95 && b <= 0 = Color240 186
-    | r <= 255 && g <= 95 && b <= 95 = Color240 187
-    | r <= 255 && g <= 95 && b <= 135 = Color240 188
-    | r <= 255 && g <= 95 && b <= 175 = Color240 189
-    | r <= 255 && g <= 95 && b <= 215 = Color240 190
-    | r <= 255 && g <= 95 && b <= 255 = Color240 191
-    | r <= 255 && g <= 135 && b <= 0 = Color240 192
-    | r <= 255 && g <= 135 && b <= 95 = Color240 193
-    | r <= 255 && g <= 135 && b <= 135 = Color240 194
-    | r <= 255 && g <= 135 && b <= 175 = Color240 195
-    | r <= 255 && g <= 135 && b <= 215 = Color240 196
-    | r <= 255 && g <= 135 && b <= 255 = Color240 197
-    | r <= 255 && g <= 175 && b <= 0 = Color240 198
-    | r <= 255 && g <= 175 && b <= 95 = Color240 199
-    | r <= 255 && g <= 175 && b <= 135 = Color240 200
-    | r <= 255 && g <= 175 && b <= 175 = Color240 201
-    | r <= 255 && g <= 175 && b <= 215 = Color240 202
-    | r <= 255 && g <= 175 && b <= 255 = Color240 203
-    | r <= 255 && g <= 215 && b <= 0 = Color240 204
-    | r <= 255 && g <= 215 && b <= 95 = Color240 205
-    | r <= 255 && g <= 215 && b <= 135 = Color240 206
-    | r <= 255 && g <= 215 && b <= 175 = Color240 207
-    | r <= 255 && g <= 215 && b <= 215 = Color240 208
-    | r <= 255 && g <= 215 && b <= 255 = Color240 209
-    | r <= 255 && g <= 255 && b <= 0 = Color240 210
-    | r <= 255 && g <= 255 && b <= 95 = Color240 211
-    | r <= 255 && g <= 255 && b <= 135 = Color240 212
-    | r <= 255 && g <= 255 && b <= 175 = Color240 213
-    | r <= 255 && g <= 255 && b <= 215 = Color240 214
-    | r <= 255 && g <= 255 && b <= 255 = Color240 215
+    | r == 8 && g == 8 && b == 8 = 216
+    | r == 18 && g == 18 && b == 18 = 217
+    | r == 28 && g == 28 && b == 28 = 218
+    | r == 38 && g == 38 && b == 38 = 219
+    | r == 48 && g == 48 && b == 48 = 220
+    | r == 58 && g == 58 && b == 58 = 221
+    | r == 68 && g == 68 && b == 68 = 222
+    | r == 78 && g == 78 && b == 78 = 223
+    | r == 88 && g == 88 && b == 88 = 224
+    | r == 98 && g == 98 && b == 98 = 225
+    | r == 108 && g == 108 && b == 108 = 226
+    | r == 118 && g == 118 && b == 118 = 227
+    | r == 128 && g == 128 && b == 128 = 228
+    | r == 138 && g == 138 && b == 138 = 229
+    | r == 148 && g == 148 && b == 148 = 230
+    | r == 158 && g == 158 && b == 158 = 231
+    | r == 168 && g == 168 && b == 168 = 232
+    | r == 178 && g == 178 && b == 178 = 233
+    | r == 188 && g == 188 && b == 188 = 234
+    | r == 198 && g == 198 && b == 198 = 235
+    | r == 208 && g == 208 && b == 208 = 236
+    | r == 218 && g == 218 && b == 218 = 237
+    | r == 228 && g == 228 && b == 228 = 238
+    | r == 238 && g == 238 && b == 238 = 239
+    | r <= 0 && g <= 0 && b <= 0 = 0
+    | r <= 0 && g <= 0 && b <= 95 = 1
+    | r <= 0 && g <= 0 && b <= 135 = 2
+    | r <= 0 && g <= 0 && b <= 175 = 3
+    | r <= 0 && g <= 0 && b <= 215 = 4
+    | r <= 0 && g <= 0 && b <= 255 = 5
+    | r <= 0 && g <= 95 && b <= 0 = 6
+    | r <= 0 && g <= 95 && b <= 95 = 7
+    | r <= 0 && g <= 95 && b <= 135 = 8
+    | r <= 0 && g <= 95 && b <= 175 = 9
+    | r <= 0 && g <= 95 && b <= 215 = 10
+    | r <= 0 && g <= 95 && b <= 255 = 11
+    | r <= 0 && g <= 135 && b <= 0 = 12
+    | r <= 0 && g <= 135 && b <= 95 = 13
+    | r <= 0 && g <= 135 && b <= 135 = 14
+    | r <= 0 && g <= 135 && b <= 175 = 15
+    | r <= 0 && g <= 135 && b <= 215 = 16
+    | r <= 0 && g <= 135 && b <= 255 = 17
+    | r <= 0 && g <= 175 && b <= 0 = 18
+    | r <= 0 && g <= 175 && b <= 95 = 19
+    | r <= 0 && g <= 175 && b <= 135 = 20
+    | r <= 0 && g <= 175 && b <= 175 = 21
+    | r <= 0 && g <= 175 && b <= 215 = 22
+    | r <= 0 && g <= 175 && b <= 255 = 23
+    | r <= 0 && g <= 215 && b <= 0 = 24
+    | r <= 0 && g <= 215 && b <= 95 = 25
+    | r <= 0 && g <= 215 && b <= 135 = 26
+    | r <= 0 && g <= 215 && b <= 175 = 27
+    | r <= 0 && g <= 215 && b <= 215 = 28
+    | r <= 0 && g <= 215 && b <= 255 = 29
+    | r <= 0 && g <= 255 && b <= 0 = 30
+    | r <= 0 && g <= 255 && b <= 95 = 31
+    | r <= 0 && g <= 255 && b <= 135 = 32
+    | r <= 0 && g <= 255 && b <= 175 = 33
+    | r <= 0 && g <= 255 && b <= 215 = 34
+    | r <= 0 && g <= 255 && b <= 255 = 35
+    | r <= 95 && g <= 0 && b <= 0 = 36
+    | r <= 95 && g <= 0 && b <= 95 = 37
+    | r <= 95 && g <= 0 && b <= 135 = 38
+    | r <= 95 && g <= 0 && b <= 175 = 39
+    | r <= 95 && g <= 0 && b <= 215 = 40
+    | r <= 95 && g <= 0 && b <= 255 = 41
+    | r <= 95 && g <= 95 && b <= 0 = 42
+    | r <= 95 && g <= 95 && b <= 95 = 43
+    | r <= 95 && g <= 95 && b <= 135 = 44
+    | r <= 95 && g <= 95 && b <= 175 = 45
+    | r <= 95 && g <= 95 && b <= 215 = 46
+    | r <= 95 && g <= 95 && b <= 255 = 47
+    | r <= 95 && g <= 135 && b <= 0 = 48
+    | r <= 95 && g <= 135 && b <= 95 = 49
+    | r <= 95 && g <= 135 && b <= 135 = 50
+    | r <= 95 && g <= 135 && b <= 175 = 51
+    | r <= 95 && g <= 135 && b <= 215 = 52
+    | r <= 95 && g <= 135 && b <= 255 = 53
+    | r <= 95 && g <= 175 && b <= 0 = 54
+    | r <= 95 && g <= 175 && b <= 95 = 55
+    | r <= 95 && g <= 175 && b <= 135 = 56
+    | r <= 95 && g <= 175 && b <= 175 = 57
+    | r <= 95 && g <= 175 && b <= 215 = 58
+    | r <= 95 && g <= 175 && b <= 255 = 59
+    | r <= 95 && g <= 215 && b <= 0 = 60
+    | r <= 95 && g <= 215 && b <= 95 = 61
+    | r <= 95 && g <= 215 && b <= 135 = 62
+    | r <= 95 && g <= 215 && b <= 175 = 63
+    | r <= 95 && g <= 215 && b <= 215 = 64
+    | r <= 95 && g <= 215 && b <= 255 = 65
+    | r <= 95 && g <= 255 && b <= 0 = 66
+    | r <= 95 && g <= 255 && b <= 95 = 67
+    | r <= 95 && g <= 255 && b <= 135 = 68
+    | r <= 95 && g <= 255 && b <= 175 = 69
+    | r <= 95 && g <= 255 && b <= 215 = 70
+    | r <= 95 && g <= 255 && b <= 255 = 71
+    | r <= 135 && g <= 0 && b <= 0 = 72
+    | r <= 135 && g <= 0 && b <= 95 = 73
+    | r <= 135 && g <= 0 && b <= 135 = 74
+    | r <= 135 && g <= 0 && b <= 175 = 75
+    | r <= 135 && g <= 0 && b <= 215 = 76
+    | r <= 135 && g <= 0 && b <= 255 = 77
+    | r <= 135 && g <= 95 && b <= 0 = 78
+    | r <= 135 && g <= 95 && b <= 95 = 79
+    | r <= 135 && g <= 95 && b <= 135 = 80
+    | r <= 135 && g <= 95 && b <= 175 = 81
+    | r <= 135 && g <= 95 && b <= 215 = 82
+    | r <= 135 && g <= 95 && b <= 255 = 83
+    | r <= 135 && g <= 135 && b <= 0 = 84
+    | r <= 135 && g <= 135 && b <= 95 = 85
+    | r <= 135 && g <= 135 && b <= 135 = 86
+    | r <= 135 && g <= 135 && b <= 175 = 87
+    | r <= 135 && g <= 135 && b <= 215 = 88
+    | r <= 135 && g <= 135 && b <= 255 = 89
+    | r <= 135 && g <= 175 && b <= 0 = 90
+    | r <= 135 && g <= 175 && b <= 95 = 91
+    | r <= 135 && g <= 175 && b <= 135 = 92
+    | r <= 135 && g <= 175 && b <= 175 = 93
+    | r <= 135 && g <= 175 && b <= 215 = 94
+    | r <= 135 && g <= 175 && b <= 255 = 95
+    | r <= 135 && g <= 215 && b <= 0 = 96
+    | r <= 135 && g <= 215 && b <= 95 = 97
+    | r <= 135 && g <= 215 && b <= 135 = 98
+    | r <= 135 && g <= 215 && b <= 175 = 99
+    | r <= 135 && g <= 215 && b <= 215 = 100
+    | r <= 135 && g <= 215 && b <= 255 = 101
+    | r <= 135 && g <= 255 && b <= 0 = 102
+    | r <= 135 && g <= 255 && b <= 95 = 103
+    | r <= 135 && g <= 255 && b <= 135 = 104
+    | r <= 135 && g <= 255 && b <= 175 = 105
+    | r <= 135 && g <= 255 && b <= 215 = 106
+    | r <= 135 && g <= 255 && b <= 255 = 107
+    | r <= 175 && g <= 0 && b <= 0 = 108
+    | r <= 175 && g <= 0 && b <= 95 = 109
+    | r <= 175 && g <= 0 && b <= 135 = 110
+    | r <= 175 && g <= 0 && b <= 175 = 111
+    | r <= 175 && g <= 0 && b <= 215 = 112
+    | r <= 175 && g <= 0 && b <= 255 = 113
+    | r <= 175 && g <= 95 && b <= 0 = 114
+    | r <= 175 && g <= 95 && b <= 95 = 115
+    | r <= 175 && g <= 95 && b <= 135 = 116
+    | r <= 175 && g <= 95 && b <= 175 = 117
+    | r <= 175 && g <= 95 && b <= 215 = 118
+    | r <= 175 && g <= 95 && b <= 255 = 119
+    | r <= 175 && g <= 135 && b <= 0 = 120
+    | r <= 175 && g <= 135 && b <= 95 = 121
+    | r <= 175 && g <= 135 && b <= 135 = 122
+    | r <= 175 && g <= 135 && b <= 175 = 123
+    | r <= 175 && g <= 135 && b <= 215 = 124
+    | r <= 175 && g <= 135 && b <= 255 = 125
+    | r <= 175 && g <= 175 && b <= 0 = 126
+    | r <= 175 && g <= 175 && b <= 95 = 127
+    | r <= 175 && g <= 175 && b <= 135 = 128
+    | r <= 175 && g <= 175 && b <= 175 = 129
+    | r <= 175 && g <= 175 && b <= 215 = 130
+    | r <= 175 && g <= 175 && b <= 255 = 131
+    | r <= 175 && g <= 215 && b <= 0 = 132
+    | r <= 175 && g <= 215 && b <= 95 = 133
+    | r <= 175 && g <= 215 && b <= 135 = 134
+    | r <= 175 && g <= 215 && b <= 175 = 135
+    | r <= 175 && g <= 215 && b <= 215 = 136
+    | r <= 175 && g <= 215 && b <= 255 = 137
+    | r <= 175 && g <= 255 && b <= 0 = 138
+    | r <= 175 && g <= 255 && b <= 95 = 139
+    | r <= 175 && g <= 255 && b <= 135 = 140
+    | r <= 175 && g <= 255 && b <= 175 = 141
+    | r <= 175 && g <= 255 && b <= 215 = 142
+    | r <= 175 && g <= 255 && b <= 255 = 143
+    | r <= 215 && g <= 0 && b <= 0 = 144
+    | r <= 215 && g <= 0 && b <= 95 = 145
+    | r <= 215 && g <= 0 && b <= 135 = 146
+    | r <= 215 && g <= 0 && b <= 175 = 147
+    | r <= 215 && g <= 0 && b <= 215 = 148
+    | r <= 215 && g <= 0 && b <= 255 = 149
+    | r <= 215 && g <= 95 && b <= 0 = 150
+    | r <= 215 && g <= 95 && b <= 95 = 151
+    | r <= 215 && g <= 95 && b <= 135 = 152
+    | r <= 215 && g <= 95 && b <= 175 = 153
+    | r <= 215 && g <= 95 && b <= 215 = 154
+    | r <= 215 && g <= 95 && b <= 255 = 155
+    | r <= 215 && g <= 135 && b <= 0 = 156
+    | r <= 215 && g <= 135 && b <= 95 = 157
+    | r <= 215 && g <= 135 && b <= 135 = 158
+    | r <= 215 && g <= 135 && b <= 175 = 159
+    | r <= 215 && g <= 135 && b <= 215 = 160
+    | r <= 215 && g <= 135 && b <= 255 = 161
+    | r <= 215 && g <= 175 && b <= 0 = 162
+    | r <= 215 && g <= 175 && b <= 95 = 163
+    | r <= 215 && g <= 175 && b <= 135 = 164
+    | r <= 215 && g <= 175 && b <= 175 = 165
+    | r <= 215 && g <= 175 && b <= 215 = 166
+    | r <= 215 && g <= 175 && b <= 255 = 167
+    | r <= 215 && g <= 215 && b <= 0 = 168
+    | r <= 215 && g <= 215 && b <= 95 = 169
+    | r <= 215 && g <= 215 && b <= 135 = 170
+    | r <= 215 && g <= 215 && b <= 175 = 171
+    | r <= 215 && g <= 215 && b <= 215 = 172
+    | r <= 215 && g <= 215 && b <= 255 = 173
+    | r <= 215 && g <= 255 && b <= 0 = 174
+    | r <= 215 && g <= 255 && b <= 95 = 175
+    | r <= 215 && g <= 255 && b <= 135 = 176
+    | r <= 215 && g <= 255 && b <= 175 = 177
+    | r <= 215 && g <= 255 && b <= 215 = 178
+    | r <= 215 && g <= 255 && b <= 255 = 179
+    | r <= 255 && g <= 0 && b <= 0 = 180
+    | r <= 255 && g <= 0 && b <= 95 = 181
+    | r <= 255 && g <= 0 && b <= 135 = 182
+    | r <= 255 && g <= 0 && b <= 175 = 183
+    | r <= 255 && g <= 0 && b <= 215 = 184
+    | r <= 255 && g <= 0 && b <= 255 = 185
+    | r <= 255 && g <= 95 && b <= 0 = 186
+    | r <= 255 && g <= 95 && b <= 95 = 187
+    | r <= 255 && g <= 95 && b <= 135 = 188
+    | r <= 255 && g <= 95 && b <= 175 = 189
+    | r <= 255 && g <= 95 && b <= 215 = 190
+    | r <= 255 && g <= 95 && b <= 255 = 191
+    | r <= 255 && g <= 135 && b <= 0 = 192
+    | r <= 255 && g <= 135 && b <= 95 = 193
+    | r <= 255 && g <= 135 && b <= 135 = 194
+    | r <= 255 && g <= 135 && b <= 175 = 195
+    | r <= 255 && g <= 135 && b <= 215 = 196
+    | r <= 255 && g <= 135 && b <= 255 = 197
+    | r <= 255 && g <= 175 && b <= 0 = 198
+    | r <= 255 && g <= 175 && b <= 95 = 199
+    | r <= 255 && g <= 175 && b <= 135 = 200
+    | r <= 255 && g <= 175 && b <= 175 = 201
+    | r <= 255 && g <= 175 && b <= 215 = 202
+    | r <= 255 && g <= 175 && b <= 255 = 203
+    | r <= 255 && g <= 215 && b <= 0 = 204
+    | r <= 255 && g <= 215 && b <= 95 = 205
+    | r <= 255 && g <= 215 && b <= 135 = 206
+    | r <= 255 && g <= 215 && b <= 175 = 207
+    | r <= 255 && g <= 215 && b <= 215 = 208
+    | r <= 255 && g <= 215 && b <= 255 = 209
+    | r <= 255 && g <= 255 && b <= 0 = 210
+    | r <= 255 && g <= 255 && b <= 95 = 211
+    | r <= 255 && g <= 255 && b <= 135 = 212
+    | r <= 255 && g <= 255 && b <= 175 = 213
+    | r <= 255 && g <= 255 && b <= 215 = 214
+    | r <= 255 && g <= 255 && b <= 255 = 215
     | otherwise = error (printf "RGB color %d %d %d does not map to 240 palette."
                                 (fromIntegral r :: Int)
                                 (fromIntegral g :: Int)
diff --git a/src/Graphics/Vty/Config.hs b/src/Graphics/Vty/Config.hs
--- a/src/Graphics/Vty/Config.hs
+++ b/src/Graphics/Vty/Config.hs
@@ -76,7 +76,9 @@
 import Control.Monad (liftM, guard, void)
 
 import qualified Data.ByteString as BS
+#if !(MIN_VERSION_base(4,8,0))
 import Data.Monoid (Monoid(..))
+#endif
 #if !(MIN_VERSION_base(4,11,0))
 import Data.Semigroup (Semigroup(..))
 #endif
@@ -87,7 +89,7 @@
 import GHC.Generics
 
 import System.Directory (getAppUserDataDirectory)
-import System.Posix.Env (getEnv)
+import System.Environment (lookupEnv)
 import System.Posix.IO (stdInput, stdOutput)
 import System.Posix.Types (Fd(..))
 
@@ -176,20 +178,20 @@
 userConfig :: IO Config
 userConfig = do
     configFile <- (mappend <$> getAppUserDataDirectory "vty" <*> pure "/config") >>= parseConfigFile
-    overrideConfig <- maybe (return defaultConfig) parseConfigFile =<< getEnv "VTY_CONFIG_FILE"
+    overrideConfig <- maybe (return defaultConfig) parseConfigFile =<< lookupEnv "VTY_CONFIG_FILE"
     let base = configFile <> overrideConfig
     mappend base <$> overrideEnvConfig
 
 overrideEnvConfig :: IO Config
 overrideEnvConfig = do
-    d <- getEnv "VTY_DEBUG_LOG"
+    d <- lookupEnv "VTY_DEBUG_LOG"
     return $ defaultConfig { debugLog = d }
 
 -- | Configures VTY using defaults suitable for terminals. This function
 -- can raise 'VtyConfigurationError'.
 standardIOConfig :: IO Config
 standardIOConfig = do
-    mb <- getEnv "TERM"
+    mb <- lookupEnv "TERM"
     case mb of
       Nothing -> throwIO VtyMissingTermEnvVar
       Just t ->
diff --git a/src/Graphics/Vty/Debug.hs b/src/Graphics/Vty/Debug.hs
--- a/src/Graphics/Vty/Debug.hs
+++ b/src/Graphics/Vty/Debug.hs
@@ -12,16 +12,16 @@
 
 import qualified Data.Vector as Vector
 
-rowOpsEffectedColumns :: DisplayOps -> [Int]
-rowOpsEffectedColumns ops
-    = Vector.toList $ Vector.map spanOpsEffectedColumns ops
+rowOpsAffectedColumns :: DisplayOps -> [Int]
+rowOpsAffectedColumns ops
+    = Vector.toList $ Vector.map spanOpsAffectedColumns ops
 
 allSpansHaveWidth :: DisplayOps -> Int -> Bool
 allSpansHaveWidth ops expected
-    = all (== expected) $ Vector.toList $ Vector.map spanOpsEffectedColumns ops
+    = all (== expected) $ Vector.toList $ Vector.map spanOpsAffectedColumns ops
 
-spanOpsEffectedRows :: DisplayOps -> Int
-spanOpsEffectedRows ops
+spanOpsAffectedRows :: DisplayOps -> Int
+spanOpsAffectedRows ops
     = toEnum $ length (filter (not . null . Vector.toList) (Vector.toList ops))
 
 type SpanConstructLog = [SpanConstructEvent]
diff --git a/src/Graphics/Vty/Image.hs b/src/Graphics/Vty/Image.hs
--- a/src/Graphics/Vty/Image.hs
+++ b/src/Graphics/Vty/Image.hs
@@ -46,8 +46,12 @@
   -- * Character width functions
   , safeWcwidth
   , safeWcswidth
+  , safeWctwidth
+  , safeWctlwidth
   , wcwidth
   , wcswidth
+  , wctwidth
+  , wctlwidth
   -- * Display Regions
   , DisplayText
   , DisplayRegion
@@ -116,13 +120,13 @@
 -- | Make an 'Image' from a lazy text value. This function should not be
 -- given a text value containing escapes.
 text :: Attr -> TL.Text -> Image
-text a txt = let displayWidth = safeWcswidth (TL.unpack txt)
+text a txt = let displayWidth = safeWctlwidth txt
              in HorizText a txt displayWidth (fromIntegral $! TL.length txt)
 
 -- | Make an 'Image' from a text value. This function should not be
 -- given a text value containing escapes.
 text' :: Attr -> T.Text -> Image
-text' a txt = let displayWidth = safeWcswidth (T.unpack txt)
+text' a txt = let displayWidth = safeWctwidth txt
               in HorizText a (TL.fromStrict txt) displayWidth (T.length txt)
 
 -- | Make an image from a single character. This is a standard Haskell
@@ -170,7 +174,7 @@
 utf8Bytestring :: Attr -> BL.ByteString -> Image
 utf8Bytestring a bs = text a (TL.decodeUtf8 bs)
 
--- | Make an 'Image' from a UTF-8 encoded lazy bytestring.
+-- | Make an 'Image' from a UTF-8 encoded strict bytestring.
 utf8Bytestring' :: Attr -> B.ByteString -> Image
 utf8Bytestring' a bs = text' a (T.decodeUtf8 bs)
 
diff --git a/src/Graphics/Vty/Input.hs b/src/Graphics/Vty/Input.hs
--- a/src/Graphics/Vty/Input.hs
+++ b/src/Graphics/Vty/Input.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE RecordWildCards, CPP #-}
 
 -- | This module provides the input layer for Vty, including methods
 -- for initializing an 'Input' structure and reading 'Event's from the
@@ -132,7 +132,9 @@
 import qualified System.Console.Terminfo as Terminfo
 import System.Posix.Signals.Exts
 
+#if !MIN_VERSION_base(4,11,0)
 import Data.Monoid ((<>))
+#endif
 
 -- | Set up the terminal with file descriptor `inputFd` for input.
 -- Returns an 'Input'.
diff --git a/src/Graphics/Vty/Output.hs b/src/Graphics/Vty/Output.hs
--- a/src/Graphics/Vty/Output.hs
+++ b/src/Graphics/Vty/Output.hs
@@ -1,5 +1,4 @@
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE RecordWildCards, NamedFieldPuns, CPP #-}
 -- | This module provides functions for accessing the current terminal
 -- or a specific terminal device.
 --
@@ -38,10 +37,11 @@
 
 import Blaze.ByteString.Builder (writeToByteString)
 
-import Control.Monad.Trans
-
 import Data.List (isPrefixOf)
+
+#if !MIN_VERSION_base(4,11,0)
 import Data.Monoid ((<>))
+#endif
 
 -- | Returns an `Output` for the terminal specified in `Config`.
 --
@@ -84,23 +84,23 @@
 -- Currently, the only way to set the cursor position to a given
 -- character coordinate is to specify the coordinate in the Picture
 -- instance provided to 'outputPicture' or 'refresh'.
-setCursorPos :: MonadIO m => Output -> Int -> Int -> m ()
+setCursorPos :: Output -> Int -> Int -> IO ()
 setCursorPos t x y = do
     bounds <- displayBounds t
     when (x >= 0 && x < regionWidth bounds && y >= 0 && y < regionHeight bounds) $ do
         dc <- displayContext t bounds
-        liftIO $ outputByteBuffer t $ writeToByteString $ writeMoveCursor dc x y
+        outputByteBuffer t $ writeToByteString $ writeMoveCursor dc x y
 
 -- | Hides the cursor.
-hideCursor :: MonadIO m => Output -> m ()
+hideCursor :: Output -> IO ()
 hideCursor t = do
     bounds <- displayBounds t
     dc <- displayContext t bounds
-    liftIO $ outputByteBuffer t $ writeToByteString $ writeHideCursor dc
+    outputByteBuffer t $ writeToByteString $ writeHideCursor dc
 
 -- | Shows the cursor.
-showCursor :: MonadIO m => Output -> m ()
+showCursor :: Output -> IO ()
 showCursor t = do
     bounds <- displayBounds t
     dc <- displayContext t bounds
-    liftIO $ outputByteBuffer t $ writeToByteString $ writeShowCursor dc
+    outputByteBuffer t $ writeToByteString $ writeShowCursor dc
diff --git a/src/Graphics/Vty/Output/Interface.hs b/src/Graphics/Vty/Output/Interface.hs
--- a/src/Graphics/Vty/Output/Interface.hs
+++ b/src/Graphics/Vty/Output/Interface.hs
@@ -29,8 +29,6 @@
 import Blaze.ByteString.Builder (Write, writeToByteString)
 import Blaze.ByteString.Builder.ByteString (writeByteString)
 
-import Control.Monad.Trans
-
 import qualified Data.ByteString as BS
 import Data.IORef
 import qualified Data.Text.Encoding as T
@@ -61,7 +59,7 @@
       terminalID :: String
       -- | Release the terminal just prior to application exit and reset
       -- it to its state prior to application startup.
-    , releaseTerminal :: forall m. MonadIO m => m ()
+    , releaseTerminal :: IO ()
       -- | Clear the display and initialize the terminal to some initial
       -- display state.
       --
@@ -71,12 +69,12 @@
       --  - cursor at top left
       --  - UTF-8 character encoding
       --  - drawing characteristics are the default
-    , reserveDisplay :: forall m. MonadIO m => m ()
+    , reserveDisplay :: IO ()
       -- | Return the display to the state before `reserveDisplay` If no
       -- previous state then set the display state to the initial state.
-    , releaseDisplay :: forall m. MonadIO m => m ()
+    , releaseDisplay :: IO ()
       -- | Returns the current display bounds.
-    , displayBounds :: forall m. MonadIO m => m DisplayRegion
+    , displayBounds :: IO DisplayRegion
       -- | Output the bytestring to the terminal device.
     , outputByteBuffer :: BS.ByteString -> IO ()
       -- | Specifies the maximum number of colors supported by the
@@ -88,23 +86,23 @@
     , supportsMode :: Mode -> Bool
       -- | Enables or disables a mode (does nothing if the mode is
       -- unsupported).
-    , setMode :: forall m. MonadIO m => Mode -> Bool -> m ()
+    , setMode :: Mode -> Bool -> IO ()
       -- | Returns whether a mode is enabled.
-    , getModeStatus :: forall m. MonadIO m => Mode -> m Bool
+    , getModeStatus :: Mode -> IO Bool
     , assumedStateRef :: IORef AssumedState
       -- | Acquire display access to the given region of the display.
       -- Currently all regions have the upper left corner of (0,0) and
       -- the lower right corner at (max displayWidth providedWidth, max
       -- displayHeight providedHeight)
-    , mkDisplayContext :: forall m. MonadIO m => Output -> DisplayRegion -> m DisplayContext
+    , mkDisplayContext :: Output -> DisplayRegion -> IO DisplayContext
       -- | Ring the terminal bell if supported.
-    , ringTerminalBell :: forall m. MonadIO m => m ()
+    , ringTerminalBell :: IO ()
       -- | Returns whether the terminal has an audio bell feature.
-    , supportsBell :: forall m. MonadIO m => m Bool
+    , supportsBell :: IO Bool
     }
 
-displayContext :: MonadIO m => Output -> DisplayRegion -> m DisplayContext
-displayContext t = liftIO . mkDisplayContext t t
+displayContext :: Output -> DisplayRegion -> IO DisplayContext
+displayContext t = mkDisplayContext t t
 
 data AssumedState = AssumedState
     { prevFattr :: Maybe FixedAttr
@@ -163,8 +161,8 @@
 --      4. Serialized to the display.
 --
 --      5. The cursor is then shown and positioned or kept hidden.
-outputPicture :: MonadIO m => DisplayContext -> Picture -> m ()
-outputPicture dc pic = liftIO $ do
+outputPicture :: DisplayContext -> Picture -> IO ()
+outputPicture dc pic = do
     urlsEnabled <- getModeStatus (contextDevice dc) Hyperlink
     as <- readIORef (assumedStateRef $ contextDevice dc)
     let manipCursor = supportsCursorVisibility (contextDevice dc)
diff --git a/src/Graphics/Vty/Output/TerminfoBased.hs b/src/Graphics/Vty/Output/TerminfoBased.hs
--- a/src/Graphics/Vty/Output/TerminfoBased.hs
+++ b/src/Graphics/Vty/Output/TerminfoBased.hs
@@ -1,6 +1,7 @@
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE CPP #-}
 {-# OPTIONS_GHC -D_XOPEN_SOURCE=500 -fno-warn-warnings-deprecations #-}
 {-# CFILES gwinsz.c #-}
 
@@ -25,14 +26,15 @@
 
 import Blaze.ByteString.Builder (Write, writeToByteString, writeStorable)
 
-import Control.Monad.Trans
-
 import Data.Bits ((.&.))
-import Data.Foldable (foldMap)
 import Data.IORef
 import Data.Maybe (isJust, isNothing, fromJust)
 import Data.Word
 
+#if !MIN_VERSION_base(4,8,0)
+import Data.Foldable (foldMap)
+#endif
+
 import Foreign.C.Types ( CInt(..), CLong(..) )
 import Foreign.ForeignPtr (withForeignPtr)
 import Foreign.Ptr (Ptr, plusPtr)
@@ -100,8 +102,8 @@
 --
 --  * Providing independent string capabilities for all display
 --    attributes.
-reserveTerminal :: ( Applicative m, MonadIO m ) => String -> Fd -> m Output
-reserveTerminal termName outFd = liftIO $ do
+reserveTerminal :: String -> Fd -> IO Output
+reserveTerminal termName outFd = do
     ti <- Terminfo.setupTerm termName
     -- assumes set foreground always implies set background exists.
     -- if set foreground is not set then all color changing style
@@ -130,13 +132,13 @@
           curStatus <- terminfoModeStatus m
           when (newStatus /= curStatus) $
               case m of
-                  Hyperlink -> liftIO $ do
+                  Hyperlink -> do
                       writeIORef hyperlinkModeStatus newStatus
                       writeIORef newAssumedStateRef initialAssumedState
                   _ -> return ()
         terminfoModeStatus m =
             case m of
-                Hyperlink -> liftIO $ readIORef hyperlinkModeStatus
+                Hyperlink -> readIORef hyperlinkModeStatus
                 _ -> return False
         terminfoModeSupported Hyperlink = True
         terminfoModeSupported _ = False
@@ -158,22 +160,22 @@
         <*> probeCap ti "bel"
     let t = Output
             { terminalID = termName
-            , releaseTerminal = liftIO $ do
+            , releaseTerminal = do
                 sendCap setDefaultAttr []
                 maybeSendCap cnorm []
             , supportsBell = return $ isJust $ ringBellAudio terminfoCaps
-            , ringTerminalBell = liftIO $ maybeSendCap ringBellAudio []
-            , reserveDisplay = liftIO $ do
+            , ringTerminalBell = maybeSendCap ringBellAudio []
+            , reserveDisplay = do
                 -- If there is no support for smcup: Clear the screen
                 -- and then move the mouse to the home position to
                 -- approximate the behavior.
                 maybeSendCap smcup []
                 sendCap clearScreen []
-            , releaseDisplay = liftIO $ do
+            , releaseDisplay = do
                 maybeSendCap rmcup []
                 maybeSendCap cnorm []
             , displayBounds = do
-                rawSize <- liftIO $ getWindowSize outFd
+                rawSize <- getWindowSize outFd
                 case rawSize of
                     (w, h)  | w < 0 || h < 0 -> fail $ "getwinsize returned < 0 : " ++ show rawSize
                             | otherwise      -> return (w,h)
@@ -197,33 +199,31 @@
             , assumedStateRef = newAssumedStateRef
             -- I think fix would help assure tActual is the only
             -- reference. I was having issues tho.
-            , mkDisplayContext = \tActual -> liftIO . terminfoDisplayContext tActual terminfoCaps
+            , mkDisplayContext = \tActual -> terminfoDisplayContext tActual terminfoCaps
             }
         sendCap s = sendCapToTerminal t (s terminfoCaps)
         maybeSendCap s = when (isJust $ s terminfoCaps) . sendCap (fromJust . s)
     return t
 
-requireCap :: (Applicative m, MonadIO m) => Terminfo.Terminal -> String -> m CapExpression
+requireCap :: Terminfo.Terminal -> String -> IO CapExpression
 requireCap ti capName
     = case Terminfo.getCapability ti (Terminfo.tiGetStr capName) of
         Nothing     -> fail $ "Terminal does not define required capability \"" ++ capName ++ "\""
         Just capStr -> parseCap capStr
 
-probeCap :: (Applicative m, MonadIO m) => Terminfo.Terminal -> String -> m (Maybe CapExpression)
+probeCap :: Terminfo.Terminal -> String -> IO (Maybe CapExpression)
 probeCap ti capName
     = case Terminfo.getCapability ti (Terminfo.tiGetStr capName) of
         Nothing     -> return Nothing
         Just capStr -> Just <$> parseCap capStr
 
-parseCap :: (Applicative m, MonadIO m) => String -> m CapExpression
+parseCap :: String -> IO CapExpression
 parseCap capStr = do
     case parseCapExpression capStr of
         Left e -> fail $ show e
         Right cap -> return cap
 
-currentDisplayAttrCaps :: ( Applicative m, MonadIO m )
-                       => Terminfo.Terminal
-                       -> m DisplayAttrCaps
+currentDisplayAttrCaps :: Terminfo.Terminal -> IO DisplayAttrCaps
 currentDisplayAttrCaps ti
     =   pure DisplayAttrCaps
     <*> probeCap ti "sgr"
diff --git a/src/Graphics/Vty/Output/XTermColor.hs b/src/Graphics/Vty/Output/XTermColor.hs
--- a/src/Graphics/Vty/Output/XTermColor.hs
+++ b/src/Graphics/Vty/Output/XTermColor.hs
@@ -1,3 +1,4 @@
+{-# Language CPP #-}
 -- Copyright 2009-2010 Corey O'Connor
 -- | Xterm output driver. This uses the Terminfo driver with some
 -- extensions for Xterm.
@@ -24,7 +25,10 @@
 
 import Data.List (isInfixOf)
 import Data.Maybe (catMaybes)
+
+#if !MIN_VERSION_base(4,11,0)
 import Data.Monoid ((<>))
+#endif
 
 -- | Construct an Xterm output driver. Initialize the display to UTF-8.
 reserveTerminal :: ( Applicative m, MonadIO m ) => String -> Fd -> m Output
diff --git a/src/Graphics/Vty/PictureToSpans.hs b/src/Graphics/Vty/PictureToSpans.hs
--- a/src/Graphics/Vty/PictureToSpans.hs
+++ b/src/Graphics/Vty/PictureToSpans.hs
@@ -323,14 +323,14 @@
     let op = TextSpan a usedDisplayColumns
                       (fromIntegral $ TL.length txt)
                       txt
-        usedDisplayColumns = wcswidth $ TL.unpack txt
+        usedDisplayColumns = wctlwidth txt
     use rowOffset >>= snocOp op
 
 addRowCompletion :: DisplayRegion -> Int -> BlitM s ()
 addRowCompletion displayRegion row = do
     allRowOps <- view mrowOps
     rowOps <- lift $ lift $ MVector.read allRowOps row
-    let endX = spanOpsEffectedColumns rowOps
+    let endX = spanOpsAffectedColumns rowOps
     when (endX < regionWidth displayRegion) $ do
         let ow = regionWidth displayRegion - endX
         snocOp (Skip ow) row
@@ -343,6 +343,6 @@
     lift $ lift $ do
         ops <- MVector.read theMrowOps row
         let ops' = Vector.snoc ops op
-        when (spanOpsEffectedColumns ops' > regionWidth theRegion)
+        when (spanOpsAffectedColumns ops' > regionWidth theRegion)
              $ fail $ "row " ++ show row ++ " now exceeds region width"
         MVector.write theMrowOps row ops'
diff --git a/src/Graphics/Vty/Span.hs b/src/Graphics/Vty/Span.hs
--- a/src/Graphics/Vty/Span.hs
+++ b/src/Graphics/Vty/Span.hs
@@ -109,12 +109,12 @@
 affectedRegion ops = (displayOpsColumns ops, displayOpsRows ops)
 
 -- | The number of columns a SpanOps affects.
-spanOpsEffectedColumns :: SpanOps -> Int
-spanOpsEffectedColumns inOps = Vector.foldl' spanOpsEffectedColumns' 0 inOps
+spanOpsAffectedColumns :: SpanOps -> Int
+spanOpsAffectedColumns inOps = Vector.foldl' spanOpsAffectedColumns' 0 inOps
     where
-        spanOpsEffectedColumns' t (TextSpan _ w _ _ ) = t + w
-        spanOpsEffectedColumns' t (Skip w) = t + w
-        spanOpsEffectedColumns' t (RowEnd w) = t + w
+        spanOpsAffectedColumns' t (TextSpan _ w _ _ ) = t + w
+        spanOpsAffectedColumns' t (Skip w) = t + w
+        spanOpsAffectedColumns' t (RowEnd w) = t + w
 
 -- | The width of a single SpanOp in columns.
 spanOpHasWidth :: SpanOp -> Maybe (Int, Int)
@@ -126,7 +126,6 @@
 -- span op.
 columnsToCharOffset :: Int -> SpanOp -> Int
 columnsToCharOffset cx (TextSpan _ _ _ utf8Str) =
-    let str = TL.unpack utf8Str
-    in wcswidth (take cx str)
+    wctlwidth (TL.take (fromIntegral cx) utf8Str)
 columnsToCharOffset cx (Skip _) = cx
 columnsToCharOffset cx (RowEnd _) = cx
diff --git a/test/Verify/Graphics/Vty/Span.hs b/test/Verify/Graphics/Vty/Span.hs
--- a/test/Verify/Graphics/Vty/Span.hs
+++ b/test/Verify/Graphics/Vty/Span.hs
@@ -20,7 +20,7 @@
 isAttrSpanOp _           = False
 
 verifyAllSpansHaveWidth i spans w
-    = let v = map (\s -> (spanOpsEffectedColumns s /= w, s)) (Vector.toList spans)
+    = let v = map (\s -> (spanOpsAffectedColumns s /= w, s)) (Vector.toList spans)
       in case any ((== True) . fst) v of
         False -> succeeded
         True -> failed { reason = "Not all spans contained operations defining exactly "
diff --git a/test/VerifyOutput.hs b/test/VerifyOutput.hs
--- a/test/VerifyOutput.hs
+++ b/test/VerifyOutput.hs
@@ -13,7 +13,6 @@
 import Control.Monad
 
 import qualified System.Console.Terminfo as Terminfo
-import System.Posix.Env
 import System.Posix.IO
 
 tests :: IO [Test]
diff --git a/test/VerifySimpleSpanGeneration.hs b/test/VerifySimpleSpanGeneration.hs
--- a/test/VerifySimpleSpanGeneration.hs
+++ b/test/VerifySimpleSpanGeneration.hs
@@ -25,7 +25,7 @@
 unitImageAndZeroWindow1 (UnitImage _ i) (EmptyWindow w) =
     let p = picForImage i
         ops = displayOpsForPic p (regionForWindow w)
-    in ( spanOpsEffectedRows ops == 0 ) && ( allSpansHaveWidth ops 0 )
+    in ( spanOpsAffectedRows ops == 0 ) && ( allSpansHaveWidth ops 0 )
 
 horizSpanImageAndZeroWindow0 :: SingleRowSingleAttrImage -> EmptyWindow -> Bool
 horizSpanImageAndZeroWindow0 (SingleRowSingleAttrImage { rowImage = i }) (EmptyWindow w) =
@@ -37,7 +37,7 @@
 horizSpanImageAndZeroWindow1 (SingleRowSingleAttrImage { rowImage = i }) (EmptyWindow w) =
     let p = picForImage i
         ops = displayOpsForPic p (regionForWindow w)
-    in ( spanOpsEffectedRows ops == 0 ) && ( allSpansHaveWidth ops 0 )
+    in ( spanOpsAffectedRows ops == 0 ) && ( allSpansHaveWidth ops 0 )
 
 horizSpanImageAndEqualWindow0 :: SingleRowSingleAttrImage -> Result
 horizSpanImageAndEqualWindow0 (SingleRowSingleAttrImage { rowImage = i, expectedColumns = c }) =
@@ -51,7 +51,7 @@
     let p = picForImage i
         w = MockWindow c 1
         ops = displayOpsForPic p (regionForWindow w)
-    in spanOpsEffectedRows ops == 1
+    in spanOpsAffectedRows ops == 1
 
 horizSpanImageAndLesserWindow0 :: SingleRowSingleAttrImage -> Result
 horizSpanImageAndLesserWindow0 (SingleRowSingleAttrImage { rowImage = i, expectedColumns = c }) =
@@ -74,7 +74,7 @@
         expectedRowCount = stackHeight stack `div` 2
         w = MockWindow (stackWidth stack) expectedRowCount
         ops = displayOpsForPic p (regionForWindow w)
-        actualRowCount = spanOpsEffectedRows ops
+        actualRowCount = spanOpsAffectedRows ops
     in expectedRowCount == actualRowCount
 
 singleAttrSingleSpanStackCropped2 :: SingleAttrSingleSpanStack -> SingleAttrSingleSpanStack -> Result
@@ -90,7 +90,7 @@
         w = MockWindow (imageWidth (picImage p))  expectedRowCount
         ops = displayOpsForPic p (regionForWindow w)
         expectedRowCount = imageHeight (picImage p) `div` 2
-        actualRowCount = spanOpsEffectedRows ops
+        actualRowCount = spanOpsAffectedRows ops
     in expectedRowCount == actualRowCount
 
 singleAttrSingleSpanStackCropped4 :: SingleAttrSingleSpanStack -> SingleAttrSingleSpanStack -> Result
@@ -107,7 +107,7 @@
         w = MockWindow (imageWidth (picImage p)) (stackHeight stack0)
         ops = displayOpsForPic p (regionForWindow w)
         expectedRowCount = stackHeight stack0
-        actualRowCount = spanOpsEffectedRows ops
+        actualRowCount = spanOpsAffectedRows ops
     in expectedRowCount == actualRowCount
 
 horizSpanImageAndGreaterWindow0 :: SingleRowSingleAttrImage -> Result
@@ -123,13 +123,13 @@
 arbImageIsCropped (DefaultImage image) win@(MockWindow w h) =
     let pic = picForImage image
         ops = displayOpsForPic pic (regionForWindow win)
-    in ( spanOpsEffectedRows ops == h ) && ( allSpansHaveWidth ops w )
+    in ( spanOpsAffectedRows ops == h ) && ( allSpansHaveWidth ops w )
 
 spanOpsActuallyFillRows :: DefaultPic -> Bool
 spanOpsActuallyFillRows (DefaultPic pic win) =
     let ops = displayOpsForPic pic (regionForWindow win)
         expectedRowCount = regionHeight (regionForWindow win)
-        actualRowCount = spanOpsEffectedRows ops
+        actualRowCount = spanOpsAffectedRows ops
     in expectedRowCount == actualRowCount
 
 spanOpsActuallyFillColumns :: DefaultPic -> Bool
diff --git a/vty.cabal b/vty.cabal
--- a/vty.cabal
+++ b/vty.cabal
@@ -1,5 +1,5 @@
 name:                vty
-version:             5.25.1
+version:             5.26
 license:             BSD3
 license-file:        LICENSE
 author:              AUTHORS
@@ -30,7 +30,7 @@
                      AUTHORS,
                      CHANGELOG.md,
                      LICENSE
-tested-with:         GHC==7.10.3, GHC==8.0.2, GHC==8.2.2, GHC==8.4.3
+tested-with:         GHC==7.10.3, GHC==8.0.2, GHC==8.2.2, GHC==8.4.3, GHC==8.6.5
 
 source-repository head
   type: git
@@ -45,7 +45,7 @@
                        deepseq >= 1.1 && < 1.5,
                        directory,
                        filepath >= 1.0 && < 2.0,
-                       microlens < 0.4.11,
+                       microlens < 0.4.12,
                        microlens-mtl,
                        microlens-th,
                        -- required for nice installation with yi
@@ -62,10 +62,12 @@
                        vector >= 0.7
 
   if !impl(ghc >= 8.0)
-    build-depends:     semigroups >= 0.16
+    build-depends:     semigroups >= 0.16,
+                       fail
 
   exposed-modules:     Graphics.Vty
                        Graphics.Vty.Attributes
+                       Graphics.Vty.Attributes.Color 
                        Graphics.Vty.Config
                        Graphics.Vty.Error
                        Graphics.Vty.Image
@@ -98,8 +100,7 @@
                        Graphics.Vty.Output.XTermColor
                        Graphics.Vty.Output.TerminfoBased
 
-  other-modules:       Graphics.Vty.Attributes.Color
-                       Graphics.Vty.Attributes.Color240
+  other-modules:       Graphics.Vty.Attributes.Color240
                        Graphics.Vty.Debug.Image
                        Graphics.Vty.Input.Terminfo.ANSIVT
 
