diff --git a/README b/README
--- a/README
+++ b/README
@@ -1,15 +1,13 @@
-vty is a very simple terminal interface library.
+vty is a terminal interface library.
 
 Vty currently provides:
 
-* Automatic handling of suspend/resume (SIGTSTP+SIGCONT).
-
 * Automatic handling of window resizes.
 
 * Supports Unicode characters on output, automatically setting and
-  resetting UTF-8 mode (beware double width and combining characters!)
+  resetting UTF-8 mode for xterm. Other terminals are assumed to support 
 
-* Automatic computation of minimal differences.
+* Efficient output. 
 
 * Minimizes repaint area, thus virtually eliminating the flicker
   problem that plagues ncurses programs.
@@ -27,17 +25,13 @@
 * Interface is designed for relatively easy compatible extension.
 
 * Supports all ANSI SGR-modes (defined in console_codes(4)) with
-  a simple type-safe interface.
+  a type-safe interface. 
 
-* Properly handles cleanup, leaving the cursor at the bottom of
-  the screen and erasing the last line.
+* Properly handles cleanup.
 
 Current disadvantages:
 
-* No current support for non-ANSI terminals.
-
-* UTF-8 support only works properly on the linux console/xterm,
-  and even then only if it is not the system default.
+* The character encoding of the output terminal is assumed to be UTF-8.
 
 * Minimal support for special keys on terminals other than the
   linux-console.  (F1-5 and arrow keys should work, but anything
@@ -46,9 +40,9 @@
 * Uses the TIOCGWINSZ ioctl to find the current window size, which
   appears to be limited to Linux and *BSD.
 
-darcs get --tag=rel-3.0.0 http://code.haskell.org/vty/
+darcs get --tag=vty-4.0.0.1 http://code.haskell.org/vty/
 
-To compile the demonstration program: ghc --make Test.hs gwinsz.c
+To compile the demonstration program: ghc --make test/Test.hs gwinsz.c
 
-The main documentation consists of the haddock-comments and the
-demonstration program
+The main documentation consists of the haddock-comments and the demonstration
+program
diff --git a/TODO b/TODO
--- a/TODO
+++ b/TODO
@@ -1,6 +1,4 @@
-Minor:
-- input parser uses similar interface to DisplayHandle. Derive instance from terminfo
-- Improve input handling performance.
+- Improve input handling
   - base off of haskeline input system. The haskeline input system appears to be excellent and
     satisfy all of Vty's input requirements. The current haskeline distribution does not appear to
     export the required modules. Either:
@@ -10,13 +8,8 @@
         1. Partition the backend of haskeline into a separate package usable by both vty and
         haskeline.
 - use compact-string for character encoding handling
-- xterm cursor foreground handling.
+- Custom cursor appearance handling?
     - specific color?
     - reverse video?
     - auto?
-- resolve gnome-terminal performance.
-    - too much output per update? Diff the previous versus the requested to reduce?
-
-Major:
-- Remove size fields in resize constr
 
diff --git a/src/Codec/Binary/UTF8/Debug.hs b/src/Codec/Binary/UTF8/Debug.hs
--- a/src/Codec/Binary/UTF8/Debug.hs
+++ b/src/Codec/Binary/UTF8/Debug.hs
@@ -8,7 +8,7 @@
 
 import Numeric
 
--- Converts an array of ISO-10464 characters (Char type) to an array of Word8 bytes that is the
+-- Converts an array of ISO-10646 characters (Char type) to an array of Word8 bytes that is the
 -- corresponding UTF8 byte sequence
 utf8_from_iso :: Integral i => [i] -> [Word8]
 utf8_from_iso = encode . map toEnum
diff --git a/src/Data/Marshalling.hs b/src/Data/Marshalling.hs
--- a/src/Data/Marshalling.hs
+++ b/src/Data/Marshalling.hs
@@ -9,7 +9,6 @@
                         )
     where
 
-import Control.Monad ( foldM )
 import Control.Monad.Trans
 
 import Data.Word
@@ -17,6 +16,7 @@
 import Foreign.Ptr
 import Foreign.ForeignPtr
 import Foreign.Marshal
+import Foreign.Marshal.Array
 import Foreign.Storable
 
 type OutputBuffer = Ptr Word8
@@ -25,9 +25,7 @@
 string_to_bytes str = map (toEnum . fromEnum) str
 
 serialize_bytes :: MonadIO m => [Word8] -> OutputBuffer -> m OutputBuffer
-serialize_bytes bytes !out_ptr = foldM ( \ptr b -> liftIO (poke ptr b) 
-                                                   >> ( return $! ( ptr `plusPtr` 1 ) ) 
-                                       ) 
-                                       out_ptr 
-                                       bytes
+serialize_bytes bytes !out_ptr = do
+    liftIO $! pokeArray out_ptr bytes
+    return $! out_ptr `plusPtr` ( length bytes )
 
diff --git a/src/Data/Terminfo/Eval.hs b/src/Data/Terminfo/Eval.hs
--- a/src/Data/Terminfo/Eval.hs
+++ b/src/Data/Terminfo/Eval.hs
@@ -19,8 +19,10 @@
 import Data.Marshalling
 import Data.Terminfo.Parse
 
+import Control.Monad.Identity
 import Control.Monad.Reader
 import Control.Monad.State.Strict
+import Control.Monad.Trans
 
 import Data.Array.Unboxed
 import Data.Bits ( (.|.), (.&.), xor )
@@ -29,8 +31,8 @@
 import GHC.Prim
 import GHC.Word
 
-type Eval a = ReaderT (CapExpression,[CapParam]) (State [CapParam]) a
-type EvalIO a = ReaderT (CapExpression,[CapParam]) (StateT [CapParam] IO) a
+type EvalT m a = ReaderT (CapExpression,[CapParam]) (StateT [CapParam] m) a
+type Eval a = EvalT Identity a
 
 pop :: MonadState [CapParam] m => m CapParam
 pop = do
@@ -67,7 +69,7 @@
 cap_expression_required_bytes :: CapExpression -> [CapParam] -> Word
 cap_expression_required_bytes cap params = 
     let params' = apply_param_ops cap params
-    in fst $! runState (runReaderT (cap_ops_required_bytes $ cap_ops cap) (cap, params')) []
+    in fst $! runIdentity $ runStateT (runReaderT (cap_ops_required_bytes $ cap_ops cap) (cap, params')) []
 
 cap_ops_required_bytes :: CapOps -> Eval Word
 cap_ops_required_bytes ops = do
@@ -148,16 +150,16 @@
     push $ if v_0 > v_1 then 1 else 0
     return 0
 
-serialize_cap_expression :: CapExpression -> [CapParam] -> OutputBuffer -> IO OutputBuffer
+serialize_cap_expression :: MonadIO m => CapExpression -> [CapParam] -> OutputBuffer -> m OutputBuffer
 serialize_cap_expression cap params out_ptr = do
     let params' = apply_param_ops cap params
     (!out_ptr', _) <- runStateT (runReaderT (serialize_cap_ops out_ptr (cap_ops cap)) (cap, params')) []
     return out_ptr'
 
-serialize_cap_ops :: OutputBuffer -> CapOps -> EvalIO OutputBuffer
+serialize_cap_ops :: MonadIO m => OutputBuffer -> CapOps -> EvalT m OutputBuffer
 serialize_cap_ops out_ptr ops = foldM serialize_cap_op out_ptr ops
 
-serialize_cap_op :: OutputBuffer -> CapOp -> EvalIO OutputBuffer
+serialize_cap_op :: MonadIO m => OutputBuffer -> CapOp -> EvalT m OutputBuffer
 serialize_cap_op out_ptr (Bytes offset c) = do
     (cap, _) <- ask
     let out_bytes = bytes_for_range cap offset c
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
@@ -36,7 +36,7 @@
     where
 
 import Data.Bits
-
+import Data.Monoid
 import Data.Word
 
 -- | A display attribute defines the Color and Style of all the characters rendered after the
@@ -46,11 +46,18 @@
 --  foreground. The 240 colors and 16 colors are points in different palettes. See Color for more
 --  information.
 data Attr = Attr 
-    { style :: !(MaybeDefault Style)
-    , fore_color :: !(MaybeDefault Color)
-    , back_color :: !(MaybeDefault Color)
+    { attr_style :: !(MaybeDefault Style)
+    , attr_fore_color :: !(MaybeDefault Color)
+    , attr_back_color :: !(MaybeDefault Color)
     } deriving ( Eq, Show )
 
+instance Monoid Attr where
+    mempty = Attr mempty mempty mempty
+    mappend attr_0 attr_1 = 
+        Attr ( attr_style attr_0 `mappend` attr_style attr_1 )
+             ( attr_fore_color attr_0 `mappend` attr_fore_color attr_1 )
+             ( attr_back_color attr_0 `mappend` attr_back_color attr_1 )
+
 -- | Specifies the display attributes such that the final style and color values do not depend on
 -- the previously applied display attribute. The display attributes can still depend on the
 -- terminal's default colors (unfortunately).
@@ -65,6 +72,18 @@
 data Eq v => MaybeDefault v = Default | KeepCurrent | SetTo !v
     deriving ( Eq, Show )
 
+instance Eq v => Monoid ( MaybeDefault v ) where
+    mempty = KeepCurrent
+    mappend Default Default = Default
+    mappend Default KeepCurrent = Default
+    mappend Default ( SetTo v ) = SetTo v
+    mappend KeepCurrent Default = Default
+    mappend KeepCurrent KeepCurrent = KeepCurrent
+    mappend KeepCurrent ( SetTo v ) = SetTo v
+    mappend ( SetTo _v ) Default = Default
+    mappend ( SetTo v ) KeepCurrent = SetTo v
+    mappend ( SetTo _ ) ( SetTo v ) = SetTo v
+
 -- | Abstract data type representing a color.
 --  
 -- Currently the foreground and background color are specified as points in either a:
@@ -168,7 +187,7 @@
 
 style_mask :: Attr -> Word8
 style_mask attr 
-    = case style attr of
+    = case attr_style attr of
         Default  -> 0
         KeepCurrent -> 0
         SetTo v  -> v
@@ -179,15 +198,15 @@
 
 -- | Set the foreground color of an `Attr'.
 with_fore_color :: Attr -> Color -> Attr
-with_fore_color attr c = attr { fore_color = SetTo c }
+with_fore_color attr c = attr { attr_fore_color = SetTo c }
 
 -- | Set the background color of an `Attr'.
 with_back_color :: Attr -> Color -> Attr
-with_back_color attr c = attr { back_color = SetTo c }
+with_back_color attr c = attr { attr_back_color = SetTo c }
 
 -- | Add the given style attribute
 with_style :: Attr -> Style -> Attr
-with_style attr style_flag = attr { style = SetTo $ style_mask attr .|. style_flag }
+with_style attr style_flag = attr { attr_style = SetTo $ style_mask attr .|. style_flag }
 
 -- | Sets the style, background color and foreground color to the default values for the terminal.
 -- There is no easy way to determine what the default background and foreground colors are.
diff --git a/src/Graphics/Vty/DisplayAttributes.hs b/src/Graphics/Vty/DisplayAttributes.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Vty/DisplayAttributes.hs
@@ -0,0 +1,106 @@
+{-# LANGUAGE BangPatterns #-}
+module Graphics.Vty.DisplayAttributes
+    where
+
+import Graphics.Vty.Attributes
+
+import Data.Bits ( (.&.) )
+import Data.Monoid ( Monoid(..), mconcat )
+
+-- | Given the previously applied display attributes as a FixedAttr and the current display
+-- attributes as an Attr produces a FixedAttr that represents the current display attributes. This
+-- is done by using the previously applied display attributes to remove the "KeepCurrent"
+-- abstraction.
+fix_display_attr :: FixedAttr -> Attr -> FixedAttr
+fix_display_attr fattr attr 
+    = FixedAttr ( fix_style (fixed_style fattr) (attr_style attr) )
+                ( fix_color (fixed_fore_color fattr) (attr_fore_color attr) )
+                ( fix_color (fixed_back_color fattr) (attr_back_color attr) )
+    where
+        fix_style _s Default = default_style_mask
+        fix_style s KeepCurrent = s
+        fix_style _s (SetTo new_style) = new_style
+        fix_color _c Default = Nothing
+        fix_color c KeepCurrent = c
+        fix_color _c (SetTo c) = Just c
+
+data DisplayAttrDiff = DisplayAttrDiff
+    { style_diffs :: [ StyleStateChange ]
+    , fore_color_diff :: DisplayColorDiff
+    , back_color_diff :: DisplayColorDiff
+    }
+    deriving ( Show )
+
+instance Monoid DisplayAttrDiff where
+    mempty = DisplayAttrDiff [] NoColorChange NoColorChange
+    mappend d_0 d_1 = 
+        let ds = simplify_style_diffs ( style_diffs d_0 ) ( style_diffs d_1 )
+            fcd = simplify_color_diffs ( fore_color_diff d_0 ) ( fore_color_diff d_1 )
+            bcd = simplify_color_diffs ( back_color_diff d_0 ) ( back_color_diff d_1 )
+        in DisplayAttrDiff ds fcd bcd
+
+simplify_style_diffs :: [ StyleStateChange ] -> [ StyleStateChange ] -> [ StyleStateChange ]
+simplify_style_diffs cs_0 cs_1 = cs_0 `mappend` cs_1
+
+simplify_color_diffs _cd             ColorToDefault  = ColorToDefault
+simplify_color_diffs cd              NoColorChange   = cd
+simplify_color_diffs _cd             ( SetColor !c ) = SetColor c
+
+data DisplayColorDiff 
+    = ColorToDefault
+    | NoColorChange
+    | SetColor !Color
+    deriving ( Show, Eq )
+
+data StyleStateChange 
+    = ApplyStandout
+    | RemoveStandout
+    | ApplyUnderline
+    | RemoveUnderline
+    | ApplyReverseVideo
+    | RemoveReverseVideo
+    | ApplyBlink
+    | RemoveBlink
+    | ApplyDim
+    | RemoveDim
+    | ApplyBold
+    | RemoveBold
+    deriving ( Show, Eq )
+
+display_attr_diffs :: FixedAttr -> FixedAttr -> DisplayAttrDiff
+display_attr_diffs attr attr' = DisplayAttrDiff
+    { style_diffs = diff_styles ( fixed_style attr ) ( fixed_style attr' )
+    , fore_color_diff = diff_color ( fixed_fore_color attr ) ( fixed_fore_color attr' )
+    , back_color_diff = diff_color ( fixed_back_color attr ) ( fixed_back_color attr' )
+    }
+
+diff_color :: Maybe Color -> Maybe Color -> DisplayColorDiff
+diff_color Nothing  (Just c') = SetColor c'
+diff_color (Just c) (Just c') 
+    | c == c'   = NoColorChange
+    | otherwise = SetColor c'
+diff_color Nothing  Nothing = NoColorChange
+diff_color (Just _) Nothing = ColorToDefault
+
+diff_styles :: Style -> Style -> [StyleStateChange]
+diff_styles prev cur 
+    = mconcat 
+    [ style_diff standout ApplyStandout RemoveStandout
+    , style_diff underline ApplyUnderline RemoveUnderline
+    , style_diff reverse_video ApplyReverseVideo RemoveReverseVideo
+    , style_diff blink ApplyBlink RemoveBlink
+    , style_diff dim ApplyDim RemoveDim
+    , style_diff bold ApplyBold RemoveBold
+    ]
+    where 
+        style_diff s sm rm 
+            = case ( 0 == prev .&. s, 0 == cur .&. s ) of
+                -- not set in either
+                ( True, True ) -> []
+                -- set in both
+                ( False, False ) -> []
+                -- now set
+                ( True, False) -> [ sm ]
+                -- now unset
+                ( False, True) -> [ rm ]
+
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
@@ -13,10 +13,12 @@
                           , background_fill
                           , char
                           , string
-                          , iso_10464_string
+                          , iso_10646_string
                           , utf8_string
                           , utf8_bytestring
                           , char_fill
+                          , empty_image
+                          , translate
                           -- | The possible display attributes used in constructing an `Image`.
                           , module Graphics.Vty.Attributes
                           )
@@ -28,7 +30,9 @@
 
 import Codec.Binary.UTF8.String ( decode )
 
+import Data.AffineSpace
 import qualified Data.ByteString as BS
+import Data.Monoid
 import qualified Data.Sequence as Seq
 import qualified Data.String.UTF8 as UTF8
 import Data.Word
@@ -89,8 +93,13 @@
       { output_width :: !Word -- >= 1
       , output_height :: !Word -- >= 1
       }
-    -- Any image of zero size equals the id image
-    | IdImage
+    -- The combining operators identity constant. 
+    -- EmptyImage <|> a = a
+    -- EmptyImage <-> a = a
+    -- 
+    -- Any image of zero size equals the empty image.
+    | EmptyImage
+    | Translation (Int, Int) Image
     deriving Eq
 
 instance Show Image where
@@ -102,20 +111,26 @@
         = "HorizJoin " ++ show c ++ " ( " ++ show l ++ " <|> " ++ show r ++ " )"
     show ( VertJoin { part_top = t, part_bottom = b, output_width = c, output_height = r } ) 
         = "VertJoin (" ++ show c ++ ", " ++ show r ++ ") ( " ++ show t ++ " ) <-> ( " ++ show b ++ " )"
-    show ( IdImage ) = "IdImage"
+    show ( EmptyImage ) = "EmptyImage"
 
--- A horizontal text image of 0 characters in width simplifies to the IdImage
+-- | Currently append in the Monoid instance is equivalent to <->. Future versions will just stack
+-- the images.
+instance Monoid Image where
+    mempty = empty_image
+    mappend = (<->)
+    
+-- A horizontal text image of 0 characters in width simplifies to the EmptyImage
 horiz_text :: Attr -> StringSeq -> Word -> Image
 horiz_text a txt ow
-    | ow == 0    = IdImage
+    | ow == 0    = EmptyImage
     | otherwise = HorizText a txt ow (toEnum $ Seq.length txt)
 
 horiz_join :: Image -> Image -> Word -> Word -> Image
 horiz_join i_0 i_1 w h
-    -- A horiz join of two 0 width images simplifies to the IdImage
-    | w == 0 = IdImage
+    -- A horiz join of two 0 width images simplifies to the EmptyImage
+    | w == 0 = EmptyImage
     -- A horizontal join where either part is 0 columns in width simplifies to the other part.
-    -- This covers the case where one part is the IdImage.
+    -- This covers the case where one part is the EmptyImage.
     | image_width i_0 == 0 = i_1
     | image_width i_1 == 0 = i_0
     -- If the images are of the same height then no BG padding is required
@@ -143,10 +158,10 @@
 
 vert_join :: Image -> Image -> Word -> Word -> Image
 vert_join i_0 i_1 w h
-    -- A vertical join of two 0 height images simplifies to the IdImage
-    | h == 0                = IdImage
+    -- A vertical join of two 0 height images simplifies to the EmptyImage
+    | h == 0                = EmptyImage
     -- A vertical join where either part is 0 rows in height simplifies to the other part.
-    -- This covers the case where one part is the IdImage
+    -- This covers the case where one part is the EmptyImage
     | image_height i_0 == 0 = i_1
     | image_height i_1 == 0 = i_0
     -- If the images are of the same height then no background padding is required
@@ -175,8 +190,8 @@
 -- | An area of the picture's bacground (See Background) of w columns and h rows.
 background_fill :: Word -> Word -> Image
 background_fill w h 
-    | w == 0    = IdImage
-    | h == 0    = IdImage
+    | w == 0    = EmptyImage
+    | h == 0    = EmptyImage
     | otherwise = BGFill w h
 
 -- | The width of an Image. This is the number display columns the image will occupy.
@@ -185,7 +200,8 @@
 image_width HorizJoin { output_width = w } = w
 image_width VertJoin { output_width = w } = w
 image_width BGFill { output_width = w } = w
-image_width IdImage = 0
+image_width EmptyImage = 0
+image_width ( Translation _v i ) = image_width i
 
 -- | The height of an Image. This is the number of display rows the image will occupy.
 image_height :: Image -> Word
@@ -193,7 +209,8 @@
 image_height HorizJoin { output_height = r } = r
 image_height VertJoin { output_height = r } = r
 image_height BGFill { output_height = r } = r
-image_height IdImage = 0
+image_height EmptyImage = 0
+image_height ( Translation _v i ) = image_width i
 
 -- | Combines two images side by side.
 --
@@ -243,28 +260,28 @@
 
 -- | Compose any number of images horizontally.
 horiz_cat :: [Image] -> Image
-horiz_cat = foldr (<|>) IdImage
+horiz_cat = foldr (<|>) EmptyImage
 
 -- | Compose any number of images vertically.
 vert_cat :: [Image] -> Image
-vert_cat = foldr (<->) IdImage
+vert_cat = foldr (<->) EmptyImage
 
 -- | an image of a single character. This is a standard Haskell 31-bit character assumed to be in
--- the ISO-10464 encoding.
+-- the ISO-10646 encoding.
 char :: Attr -> Char -> Image
 char !a !c = HorizText a (Seq.singleton c) (safe_wcwidth c) 1
 
 -- | A string of characters layed out on a single row with the same display attribute. The string is
--- assumed to be a sequence of ISO-10464 characters. 
+-- assumed to be a sequence of ISO-10646 characters. 
 --
 -- Note: depending on how the Haskell compiler represents string literals a string literal in a
--- UTF-8 encoded source file, for example, may be represented as a ISO-10464 string. 
+-- UTF-8 encoded source file, for example, may be represented as a ISO-10646 string. 
 -- That is, I think, the case with GHC 6.10. This means, for the most part, you don't need to worry
 -- about the encoding format when outputting string literals. Just provide the string literal
--- directly to iso_10464_string or string.
+-- directly to iso_10646_string or string.
 -- 
-iso_10464_string :: Attr -> String -> Image
-iso_10464_string !a !str = horiz_text a (Seq.fromList str) (safe_wcswidth str)
+iso_10646_string :: Attr -> String -> Image
+iso_10646_string !a !str = horiz_text a (Seq.fromList str) (safe_wcswidth str)
 
 -- | Alias for iso_10646_string. Since the usual case is that a literal string like "foo" is
 -- represented internally as a list of ISO 10646 31 bit characters.  
@@ -273,7 +290,7 @@
 -- UTF-8 encoded in the source, will be transcoded to a ISO 10646 31 bit characters runtime
 -- representation.
 string :: Attr -> String -> Image
-string = iso_10464_string
+string = iso_10646_string
 
 -- | A string of characters layed out on a single row. The string is assumed to be a sequence of
 -- UTF-8 characters.
@@ -301,4 +318,12 @@
 char_fill :: Enum d => Attr -> Char -> d -> d -> Image
 char_fill !a !c w h = 
     vert_cat $ replicate (fromEnum h) $ horiz_cat $ replicate (fromEnum w) $ char a c
+
+-- | The empty image. Useful for fold combinators. These occupy no space nor define any display
+-- attributes.
+empty_image :: Image 
+empty_image = EmptyImage
+
+translate :: (Int, Int) -> Image -> Image
+translate v i = Translation v i
 
diff --git a/src/Graphics/Vty/Inline.hs b/src/Graphics/Vty/Inline.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Vty/Inline.hs
@@ -0,0 +1,58 @@
+{-# LANGUAGE BangPatterns #-}
+module Graphics.Vty.Inline ( module Graphics.Vty.Inline
+                           )
+    where
+
+import Graphics.Vty.Attributes
+import Graphics.Vty.DisplayAttributes
+import Graphics.Vty.Terminal.Generic
+
+import Control.Applicative
+import Control.Monad.State.Strict
+import Control.Monad.Trans
+
+import Data.Bits ( (.&.), complement )
+import Data.IORef
+import Data.Monoid ( mappend )
+
+type InlineM v = State Attr v
+
+back_color :: Color -> InlineM ()
+back_color c = modify $ flip mappend ( current_attr `with_back_color` c )
+
+fore_color :: Color -> InlineM ()
+fore_color c = modify $ flip mappend ( current_attr `with_fore_color` c )
+
+apply_style :: Style -> InlineM ()
+apply_style s = modify $ flip mappend ( current_attr `with_style` s )
+
+remove_style :: Style -> InlineM ()
+remove_style s_mask = modify $ \attr -> 
+    let style' = case attr_style attr of
+                    Default -> error $ "Graphics.Vty.Inline: Cannot remove_style if apply_style never used."
+                    KeepCurrent -> error $ "Graphics.Vty.Inline: Cannot remove_style if apply_style never used."
+                    SetTo s -> s .&. complement s_mask
+    in attr { attr_style = SetTo style' } 
+
+default_all :: InlineM ()
+default_all = put def_attr
+
+put_attr_change :: ( Applicative m, MonadIO m ) => TerminalHandle -> InlineM () -> m ()
+put_attr_change t c = do
+    bounds <- display_bounds t
+    d <- display_context t bounds
+    mfattr <- liftIO $ known_fattr <$> readIORef ( state_ref t )
+    fattr <- case mfattr of
+                Nothing -> do
+                    marshall_to_terminal t (default_attr_required_bytes d) (serialize_default_attr d) 
+                    return $ FixedAttr default_style_mask Nothing Nothing
+                Just v -> return v
+    let attr = execState c current_attr
+        attr' = limit_attr_for_display d attr
+        fattr' = fix_display_attr fattr attr'
+        diffs = display_attr_diffs fattr fattr'
+    marshall_to_terminal t ( attr_required_bytes d fattr attr' diffs )
+                           ( serialize_set_attr d fattr attr' diffs )
+    liftIO $ modifyIORef ( state_ref t ) $ \s -> s { known_fattr = Just fattr' }
+    inline_hack d
+
diff --git a/src/Graphics/Vty/Picture.hs b/src/Graphics/Vty/Picture.hs
--- a/src/Graphics/Vty/Picture.hs
+++ b/src/Graphics/Vty/Picture.hs
@@ -10,10 +10,12 @@
                             , background_fill
                             , char
                             , string
-                            , iso_10464_string
+                            , iso_10646_string
                             , utf8_string
                             , utf8_bytestring
                             , char_fill
+                            , empty_image
+                            , translate
                             -- | The possible display attributes used in constructing an `Image`.
                             , module Graphics.Vty.Attributes
                             )
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
@@ -129,7 +129,7 @@
     | remaining_columns == 0 = return ()
     | y >= region_height region = return ()
     | otherwise = case image of
-        IdImage -> return ()
+        EmptyImage -> return ()
         -- The width provided is the number of columns this text span will occupy when displayed.
         -- if this is greater than the number of remaining columsn the output has to be produced a
         -- character at a time.
@@ -153,6 +153,7 @@
                                     then remaining_columns
                                     else width
             forM_ [y .. y + actual_height - 1] $ \y' -> snoc_bg_fill mrow_ops bg actual_width y'
+        Translation v i -> ops_for_row mrow_ops bg region i y remaining_columns
 
 snoc_text_span :: (Foldable.Foldable t) 
                 => Attr 
diff --git a/src/Graphics/Vty/Terminal.hs b/src/Graphics/Vty/Terminal.hs
--- a/src/Graphics/Vty/Terminal.hs
+++ b/src/Graphics/Vty/Terminal.hs
@@ -28,7 +28,10 @@
 import Graphics.Vty.Terminal.XTermColor as XTermColor
 import Graphics.Vty.Terminal.TerminfoBased as TerminfoBased
 
+import Control.Applicative
 import Control.Exception ( SomeException, try )
+import Control.Monad.Trans
+
 import Data.Either
 import Data.List ( isPrefixOf )
 import Data.Word
@@ -69,9 +72,9 @@
 -- with only what is provided in the haskell platform.
 --
 -- todo: The Terminal interface does not provide any input support.
-terminal_handle :: IO TerminalHandle
+terminal_handle :: ( Applicative m, MonadIO m ) => m TerminalHandle
 terminal_handle = do
-    term_type <- getEnv "TERM"
+    term_type <- liftIO $ getEnv "TERM"
     t <- if "xterm" `isPrefixOf` term_type
         then do
             maybe_terminal_app <- get_env "TERM_PROGRAM"
@@ -92,7 +95,7 @@
     return t
     where
         get_env var = do
-            mv <- try $ getEnv var
+            mv <- liftIO $ try $ getEnv var
             case mv of
                 Left (_e :: SomeException)  -> return $ Nothing
                 Right v -> return $ Just v
@@ -104,21 +107,21 @@
 --
 -- 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 output_picture or refresh.
-set_cursor_pos :: TerminalHandle -> Word -> Word -> IO ()
+set_cursor_pos :: MonadIO m => TerminalHandle -> Word -> Word -> m ()
 set_cursor_pos t x y = do
     bounds <- display_bounds t
     d <- display_context t bounds
     marshall_to_terminal t (move_cursor_required_bytes d x y) (serialize_move_cursor d x y)
 
 -- | Hides the cursor
-hide_cursor :: TerminalHandle -> IO ()
+hide_cursor :: MonadIO m => TerminalHandle -> m ()
 hide_cursor t = do
     bounds <- display_bounds t
     d <- display_context t bounds
     marshall_to_terminal t (hide_cursor_required_bytes d) (serialize_hide_cursor d) 
     
 -- | Shows the cursor
-show_cursor :: TerminalHandle -> IO ()
+show_cursor :: MonadIO m => TerminalHandle -> m ()
 show_cursor t = do
     bounds <- display_bounds t
     d <- display_context t bounds
diff --git a/src/Graphics/Vty/Terminal/Debug.hs b/src/Graphics/Vty/Terminal/Debug.hs
--- a/src/Graphics/Vty/Terminal/Debug.hs
+++ b/src/Graphics/Vty/Terminal/Debug.hs
@@ -11,6 +11,8 @@
 import Graphics.Vty.DisplayRegion
 import Graphics.Vty.Terminal.Generic
 
+import Control.Applicative
+import Control.Monad.Trans
 import Control.Monad.State.Strict
 
 import qualified Data.ByteString.UTF8 as BS
@@ -54,7 +56,7 @@
     display_bounds t = return $ debug_terminal_bounds t
     display_terminal_instance t r c = return $ c (DebugDisplay r)
     output_byte_buffer t out_buffer buffer_size 
-        =   do
+        =   liftIO $ do
             putStrLn $ "output_byte_buffer ?? " ++ show buffer_size
             peekArray (fromEnum buffer_size) out_buffer 
             >>= return . UTF8.fromRep . BSCore.pack
@@ -64,9 +66,9 @@
     { debug_display_bounds :: DisplayRegion
     } 
 
-terminal_instance :: DisplayRegion -> IO TerminalHandle
+terminal_instance :: ( Applicative m, MonadIO m ) => DisplayRegion -> m TerminalHandle
 terminal_instance r = do
-    output_ref <- newIORef undefined
+    output_ref <- liftIO $ newIORef undefined
     new_terminal_handle $ DebugTerminal output_ref r
 
 dehandle :: TerminalHandle -> DebugTerminal
@@ -81,7 +83,7 @@
 
     -- | A cursor move is always visualized as the single character 'M'
     serialize_move_cursor _d _x _y ptr = do
-        poke ptr (toEnum $ fromEnum 'M') 
+        liftIO $ poke ptr (toEnum $ fromEnum 'M') 
         return $ ptr `plusPtr` 1
 
     -- | Show cursor is always visualized as the single character 'S'
@@ -89,7 +91,7 @@
 
     -- | Show cursor is always visualized as the single character 'S'
     serialize_show_cursor _d ptr = do
-        poke ptr (toEnum $ fromEnum 'S') 
+        liftIO $ poke ptr (toEnum $ fromEnum 'S') 
         return $ ptr `plusPtr` 1
 
     -- | Hide cursor is always visualized as the single character 'H'
@@ -97,7 +99,7 @@
 
     -- | Hide cursor is always visualized as the single character 'H'
     serialize_hide_cursor _d ptr = do
-        poke ptr (toEnum $ fromEnum 'H') 
+        liftIO $ poke ptr (toEnum $ fromEnum 'H') 
         return $ ptr `plusPtr` 1
 
     -- | An attr change is always visualized as the single character 'A'
@@ -105,11 +107,11 @@
 
     -- | An attr change is always visualized as the single character 'A'
     serialize_set_attr _d _fattr _diffs _attr ptr = do
-        poke ptr (toEnum $ fromEnum 'A')
+        liftIO $ poke ptr (toEnum $ fromEnum 'A')
         return $ ptr `plusPtr` 1
 
     default_attr_required_bytes _d = 1
     serialize_default_attr _d ptr = do
-        poke ptr (toEnum $ fromEnum 'D')
+        liftIO $ poke ptr (toEnum $ fromEnum 'D')
         return $ ptr `plusPtr` 1
         
diff --git a/src/Graphics/Vty/Terminal/Generic.hs b/src/Graphics/Vty/Terminal/Generic.hs
--- a/src/Graphics/Vty/Terminal/Generic.hs
+++ b/src/Graphics/Vty/Terminal/Generic.hs
@@ -15,42 +15,46 @@
 import Graphics.Vty.Span
 import Graphics.Vty.DisplayRegion
 
+import Graphics.Vty.DisplayAttributes
+
 import Control.Monad ( liftM )
+import Control.Monad.Trans
 
 import Data.Array
-import Data.Bits ( (.&.) )
 import qualified Data.ByteString.Internal as BSCore
 import Data.Foldable
 import Data.IORef
-import Data.Monoid ( mconcat )
 import Data.Word
 import Data.String.UTF8 hiding ( foldl )
 
-import System.IO
-
 data TerminalHandle where
-    TerminalHandle :: Terminal t => t -> TerminalState -> TerminalHandle
+    TerminalHandle :: Terminal t => t -> IORef TerminalState -> TerminalHandle
 
-terminal_state :: TerminalHandle -> TerminalState
-terminal_state (TerminalHandle _ s) = s
+state_ref :: TerminalHandle -> IORef TerminalState
+state_ref (TerminalHandle _ s_ref) = s_ref
 
-new_terminal_handle :: forall t. Terminal t => t -> IO TerminalHandle
-new_terminal_handle t = liftM (TerminalHandle t) initial_terminal_state
+new_terminal_handle :: forall m t. ( MonadIO m, Terminal t ) => t -> m TerminalHandle
+new_terminal_handle t = do
+    s_ref <- liftIO $ newIORef initial_terminal_state
+    return $ TerminalHandle t s_ref
 
 data TerminalState = TerminalState
+    { -- | The current terminal display attributes or Nothing if they are not known.
+      known_fattr :: Maybe FixedAttr
+    }
 
-initial_terminal_state :: IO TerminalState
-initial_terminal_state = return $ TerminalState 
+initial_terminal_state :: TerminalState
+initial_terminal_state = TerminalState Nothing
 
 class Terminal t where
     -- | Text identifier for the terminal. Used for debugging.
     terminal_ID :: t -> String
     -- | 
-    release_terminal :: t -> IO ()
+    release_terminal :: MonadIO m => t -> m ()
     -- | Clear the display and initialize the terminal to some initial display state. 
     --
     -- The expectation of a program is that the display starts in some initial state. 
-    -- The initial state would consist of fixed values 
+    -- The initial state would consist of fixed values:
     --  - cursor at top left
     --  - UTF-8 character encoding
     --  - drawing characteristics are the default
@@ -58,26 +62,26 @@
     -- access to a display such that:
     --  - The previous state cannot be determined
     --  - When exclusive access to a display is release the display returns to the previous state.
-    --
-    reserve_display :: t -> IO ()
+    reserve_display :: MonadIO m => t -> m ()
 
     -- | Return the display to the state before reserve_display
     -- If no previous state then set the display state to the initial state.
-    release_display :: t -> IO ()
+    release_display :: MonadIO m => t -> m ()
     
     -- | Returns the current display bounds.
-    display_bounds :: t -> IO DisplayRegion
+    display_bounds :: MonadIO m => t -> m DisplayRegion
 
     -- Internal method used to provide the DisplayTerminal instance to the DisplayHandle
     -- constructor.
-    display_terminal_instance :: t 
+    display_terminal_instance :: MonadIO m 
+                              => t 
                               -> DisplayRegion 
                               -> (forall d. DisplayTerminal d => d -> DisplayHandle) 
-                              -> IO DisplayHandle
+                              -> m DisplayHandle
 
     -- | Output the byte buffer of the specified size to the terminal device.  The size is equal to
     -- end_ptr - start_ptr
-    output_byte_buffer :: t -> OutputBuffer -> Word -> IO ()
+    output_byte_buffer :: MonadIO m => t -> OutputBuffer -> Word -> m ()
 
 instance Terminal TerminalHandle where
     terminal_ID (TerminalHandle t _) = terminal_ID t
@@ -94,7 +98,7 @@
 -- | 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 display_width provided_width, max display_height provided_height)
-display_context :: TerminalHandle -> DisplayRegion -> IO DisplayHandle
+display_context :: MonadIO m => TerminalHandle -> DisplayRegion -> m DisplayHandle
 display_context t b = do
     s <- initial_display_state
     let c d = DisplayHandle d t s
@@ -104,8 +108,8 @@
     { previous_output_ref :: IORef (Maybe SpanOpSequence)
     }
 
-initial_display_state :: IO DisplayState
-initial_display_state = liftM DisplayState $ newIORef Nothing
+initial_display_state :: MonadIO m => m DisplayState
+initial_display_state = liftM DisplayState $ liftIO $ newIORef Nothing
 
 class DisplayTerminal d where
     -- | Provide the bounds of the display context. 
@@ -117,13 +121,13 @@
     --  | sets the output position to the specified row and column. Where the number of bytes
     --  required for the control codes can be specified seperate from the actual byte sequence.
     move_cursor_required_bytes :: d -> Word -> Word -> Word
-    serialize_move_cursor :: d -> Word -> Word -> OutputBuffer -> IO OutputBuffer
+    serialize_move_cursor :: MonadIO m => d -> Word -> Word -> OutputBuffer -> m OutputBuffer
 
     show_cursor_required_bytes :: d -> Word
-    serialize_show_cursor :: d -> OutputBuffer -> IO OutputBuffer
+    serialize_show_cursor :: MonadIO m => d -> OutputBuffer -> m OutputBuffer
 
     hide_cursor_required_bytes :: d -> Word
-    serialize_hide_cursor :: d -> OutputBuffer -> IO OutputBuffer
+    serialize_hide_cursor :: MonadIO m => d -> OutputBuffer -> m OutputBuffer
 
     --  | Assure the specified output attributes will be applied to all the following text until the
     --  next output attribute change. Where the number of bytes required for the control codes can
@@ -136,14 +140,18 @@
     --  attributes. In order to support this the currently applied display attributes are required.
     --  In addition it may be possible to optimize the state changes based off the currently applied
     --  display attributes.
-    attr_required_bytes :: d -> FixedAttr -> Attr -> DisplayAttrDiffs -> Word
-    serialize_set_attr :: d -> FixedAttr -> Attr -> DisplayAttrDiffs -> OutputBuffer -> IO OutputBuffer
+    attr_required_bytes :: d -> FixedAttr -> Attr -> DisplayAttrDiff -> Word
+    serialize_set_attr :: MonadIO m => d -> FixedAttr -> Attr -> DisplayAttrDiff -> OutputBuffer -> m OutputBuffer
 
     -- | Reset the display attributes to the default display attributes
     default_attr_required_bytes :: d -> Word
-    serialize_default_attr :: d -> OutputBuffer -> IO OutputBuffer
+    serialize_default_attr :: MonadIO m => d -> OutputBuffer -> m OutputBuffer
 
+    -- | See Graphics.Vty.Terminal.XTermColor.inline_hack
+    inline_hack :: MonadIO m => d -> m ()
+    inline_hack _d = return ()
 
+
 instance DisplayTerminal DisplayHandle where
     context_region (DisplayHandle d _ _) = context_region d
     context_color_count (DisplayHandle d _ _) = context_color_count d
@@ -157,6 +165,7 @@
     serialize_set_attr (DisplayHandle d _ _) = serialize_set_attr d
     default_attr_required_bytes (DisplayHandle d _ _) = default_attr_required_bytes d
     serialize_default_attr (DisplayHandle d _ _) = serialize_default_attr d
+    inline_hack (DisplayHandle d _ _) = inline_hack d 
     
 -- | All terminals serialize UTF8 text to the terminal device exactly as serialized in memory.
 utf8_text_required_bytes ::  UTF8 BSCore.ByteString -> Word
@@ -165,10 +174,10 @@
     in toEnum src_bytes_length
 
 -- | All terminals serialize UTF8 text to the terminal device exactly as serialized in memory.
-serialize_utf8_text  :: UTF8 BSCore.ByteString -> OutputBuffer -> IO OutputBuffer
+serialize_utf8_text  :: MonadIO m => UTF8 BSCore.ByteString -> OutputBuffer -> m OutputBuffer
 serialize_utf8_text str dest_ptr = 
     let (src_fptr, src_ptr_offset, src_bytes_length) = BSCore.toForeignPtr (toRep str)
-    in withForeignPtr src_fptr $ \src_ptr -> do
+    in liftIO $ withForeignPtr src_fptr $ \src_ptr -> do
         let src_ptr' = src_ptr `plusPtr` src_ptr_offset
         BSCore.memcpy dest_ptr src_ptr' (toEnum src_bytes_length) 
         return (dest_ptr `plusPtr` src_bytes_length)
@@ -189,7 +198,7 @@
 -- 
 -- todo: specify possible IO exceptions.
 -- abstract from IO monad to a MonadIO instance.
-output_picture :: DisplayHandle -> Picture -> IO ()
+output_picture :: MonadIO m => DisplayHandle -> Picture -> m ()
 output_picture (DisplayHandle d t s) pic = do
     let !r = context_region d
     let !ops = spans_for_pic pic r
@@ -197,7 +206,7 @@
     -- Diff the previous output against the requested output. Differences are currently on a per-row
     -- basis.
     diffs :: [Bool]
-        <- readIORef (previous_output_ref s) 
+        <- liftIO ( readIORef (previous_output_ref s) )
             >>= \mprevious_ops -> case mprevious_ops of
                 Nothing      
                     -> return $ replicate ( fromEnum $ region_height $ effected_region ops ) 
@@ -219,24 +228,23 @@
                                   + move_cursor_required_bytes d x y
 
     -- ... then serialize
-    start_ptr <- mallocBytes (fromEnum total)
-    ptr <- serialize_hide_cursor d start_ptr
-    ptr' <- serialize_default_attr d ptr
-    ptr'' <- serialize_output_ops d ptr' initial_attr diffs ops
-    end_ptr <- case pic_cursor pic of
-                    NoCursor -> return ptr''
-                    Cursor x y -> do
-                        let m = cursor_output_map ops $ pic_cursor pic
-                            (ox, oy) = char_to_output_pos m (x,y)
-                        serialize_show_cursor d ptr'' >>= serialize_move_cursor d ox oy
-    -- todo: How to handle exceptions?
-    case end_ptr `minusPtr` start_ptr of
-        count | count < 0 -> fail "End pointer before start of buffer."
-              | toEnum count > total -> fail $ "End pointer past end of buffer by " ++ show (toEnum count - total)
-              | otherwise -> output_byte_buffer t start_ptr (toEnum count)
-    free start_ptr
-    -- Cache the output spans.
-    writeIORef (previous_output_ref s) (Just ops)
+    liftIO $ allocaBytes (fromEnum total) $ \start_ptr -> do
+        ptr <- serialize_hide_cursor d start_ptr
+        ptr' <- serialize_default_attr d ptr
+        ptr'' <- serialize_output_ops d ptr' initial_attr diffs ops
+        end_ptr <- case pic_cursor pic of
+                        NoCursor -> return ptr''
+                        Cursor x y -> do
+                            let m = cursor_output_map ops $ pic_cursor pic
+                                (ox, oy) = char_to_output_pos m (x,y)
+                            serialize_show_cursor d ptr'' >>= serialize_move_cursor d ox oy
+        -- todo: How to handle exceptions?
+        case end_ptr `minusPtr` start_ptr of
+            count | count < 0 -> fail "End pointer before start of buffer."
+                  | toEnum count > total -> fail $ "End pointer past end of buffer by " ++ show (toEnum count - total)
+                  | otherwise -> output_byte_buffer t start_ptr (toEnum count)
+        -- Cache the output spans.
+        liftIO $ writeIORef (previous_output_ref s) (Just ops)
     return ()
 
 required_bytes :: DisplayTerminal d => d -> FixedAttr -> [Bool] -> SpanOpSequence -> Word
@@ -266,18 +274,19 @@
 span_op_required_bytes :: DisplayTerminal d => d -> FixedAttr -> SpanOp -> (Word, FixedAttr)
 span_op_required_bytes d fattr (AttributeChange attr) = 
     let attr' = limit_attr_for_display d attr
-        c = attr_required_bytes d fattr attr' (display_attr_diffs fattr fattr')
+        diffs = display_attr_diffs fattr fattr'
+        c = attr_required_bytes d fattr attr' diffs
         fattr' = fix_display_attr fattr attr'
     in (c, fattr')
 span_op_required_bytes _d fattr (TextSpan _ _ str) = (utf8_text_required_bytes str, fattr)
 
-serialize_output_ops :: DisplayTerminal d 
+serialize_output_ops :: ( MonadIO m, DisplayTerminal d )
                         => d 
                         -> OutputBuffer 
                         -> FixedAttr 
                         -> [Bool]
                         -> SpanOpSequence 
-                        -> IO OutputBuffer
+                        -> m OutputBuffer
 serialize_output_ops d start_ptr in_fattr diffs ops = do
     (_, end_ptr, _, _) <- foldlM serialize_output_ops' 
                               ( 0, start_ptr, in_fattr, diffs ) 
@@ -292,13 +301,13 @@
         serialize_output_ops' (_y, _out_ptr, _fattr, [] ) _span_ops
             = error "shouldn't be possible"
 
-serialize_span_ops :: DisplayTerminal d 
+serialize_span_ops :: ( MonadIO m, DisplayTerminal d )
                       => d 
                       -> Word 
                       -> OutputBuffer 
                       -> FixedAttr 
                       -> SpanOps 
-                      -> IO (OutputBuffer, FixedAttr)
+                      -> m (OutputBuffer, FixedAttr)
 serialize_span_ops d y out_ptr in_fattr span_ops = do
     -- The first operation is to set the cursor to the start of the row
     out_ptr' <- serialize_move_cursor d 0 y out_ptr
@@ -307,24 +316,26 @@
            (out_ptr', in_fattr)
            span_ops
 
-serialize_span_op :: DisplayTerminal d 
+serialize_span_op :: ( MonadIO m, DisplayTerminal d )
                      => d 
                      -> SpanOp 
                      -> OutputBuffer 
                      -> FixedAttr
-                     -> IO (OutputBuffer, FixedAttr)
+                     -> m (OutputBuffer, FixedAttr)
 serialize_span_op d (AttributeChange attr) out_ptr fattr = do
     let attr' = limit_attr_for_display d attr
         fattr' = fix_display_attr fattr attr'
-    out_ptr' <- serialize_set_attr d fattr attr' (display_attr_diffs fattr fattr') out_ptr
+        diffs = display_attr_diffs fattr fattr'
+    out_ptr' <- serialize_set_attr d fattr attr' diffs out_ptr
     return (out_ptr', fattr')
 serialize_span_op _d (TextSpan _ _ str) out_ptr fattr = do
     out_ptr' <- serialize_utf8_text str out_ptr
     return (out_ptr', fattr)
 
-marshall_to_terminal :: Terminal t => t -> Word -> (Ptr Word8 -> IO (Ptr Word8)) -> IO ()
+marshall_to_terminal :: ( MonadIO m, Terminal t )
+                     => t -> Word -> (Ptr Word8 -> m (Ptr Word8)) -> m ()
 marshall_to_terminal t c f = do
-    start_ptr <- mallocBytes (fromEnum c)
+    start_ptr <- liftIO $ mallocBytes (fromEnum c)
     -- 
     -- todo: capture exceptions?
     end_ptr <- f start_ptr
@@ -332,90 +343,9 @@
         count | count < 0 -> fail "End pointer before start pointer."
               | toEnum count > c -> fail $ "End pointer past end of buffer by " ++ show (toEnum count - c)
               | otherwise -> output_byte_buffer t start_ptr (toEnum count)
-    free start_ptr
+    liftIO $ free start_ptr
     return ()
 
-
--- | Given the previously applied display attributes as a FixedAttr and the current display
--- attributes as an Attr produces a FixedAttr that represents the current display attributes. This
--- is done by using the previously applied display attributes to remove the "KeepCurrent"
--- abstraction.
-fix_display_attr :: FixedAttr -> Attr -> FixedAttr
-fix_display_attr fattr attr 
-    = FixedAttr ( fix_style (fixed_style fattr) (style attr) )
-                ( fix_color (fixed_fore_color fattr) (fore_color attr) )
-                ( fix_color (fixed_back_color fattr) (back_color attr) )
-    where
-        fix_style _s Default = default_style_mask
-        fix_style s KeepCurrent = s
-        fix_style _s (SetTo new_style) = new_style
-        fix_color _c Default = Nothing
-        fix_color c KeepCurrent = c
-        fix_color _c (SetTo c) = Just c
-
-data DisplayAttrDiffs = DisplayAttrDiffs 
-    { style_diffs :: [ StyleStateChange ]
-    , fore_color_diff :: DisplayColorDiff
-    , back_color_diff :: DisplayColorDiff
-    }
-
-data DisplayColorDiff 
-    = ColorToDefault
-    | NoColorChange
-    | SetColor !Color
-    deriving Eq
-
-data StyleStateChange 
-    = ApplyStandout
-    | RemoveStandout
-    | ApplyUnderline
-    | RemoveUnderline
-    | ApplyReverseVideo
-    | RemoveReverseVideo
-    | ApplyBlink
-    | RemoveBlink
-    | ApplyDim
-    | RemoveDim
-    | ApplyBold
-    | RemoveBold
-
-display_attr_diffs :: FixedAttr -> FixedAttr -> DisplayAttrDiffs
-display_attr_diffs attr attr' = DisplayAttrDiffs
-    { style_diffs = diff_styles ( fixed_style attr ) ( fixed_style attr' )
-    , fore_color_diff = diff_color ( fixed_fore_color attr ) ( fixed_fore_color attr' )
-    , back_color_diff = diff_color ( fixed_back_color attr ) ( fixed_back_color attr' )
-    }
-
-diff_color :: Maybe Color -> Maybe Color -> DisplayColorDiff
-diff_color Nothing  (Just c') = SetColor c'
-diff_color (Just c) (Just c') 
-    | c == c'   = NoColorChange
-    | otherwise = SetColor c'
-diff_color Nothing  Nothing = NoColorChange
-diff_color (Just _) Nothing = ColorToDefault
-
-diff_styles :: Style -> Style -> [StyleStateChange]
-diff_styles prev cur 
-    = mconcat 
-    [ style_diff standout ApplyStandout RemoveStandout
-    , style_diff underline ApplyUnderline RemoveUnderline
-    , style_diff reverse_video ApplyReverseVideo RemoveReverseVideo
-    , style_diff blink ApplyBlink RemoveBlink
-    , style_diff dim ApplyDim RemoveDim
-    , style_diff bold ApplyBold RemoveBold
-    ]
-    where 
-        style_diff s sm rm 
-            = case ( 0 == prev .&. s, 0 == cur .&. s ) of
-                -- not set in either
-                ( True, True ) -> []
-                -- set in both
-                ( False, False ) -> []
-                -- now set
-                ( True, False) -> [ sm ]
-                -- now unset
-                ( False, True) -> [ rm ]
-
 data CursorOutputMap = CursorOutputMap
     { char_to_output_pos :: (Word, Word) -> (Word, Word)
     } 
@@ -452,8 +382,8 @@
 
 limit_attr_for_display :: DisplayTerminal d => d -> Attr -> Attr
 limit_attr_for_display d attr 
-    = attr { fore_color = clamp_color $ fore_color attr
-           , back_color = clamp_color $ back_color attr
+    = attr { attr_fore_color = clamp_color $ attr_fore_color attr
+           , attr_back_color = clamp_color $ attr_back_color attr
            }
     where
         clamp_color Default     = Default
diff --git a/src/Graphics/Vty/Terminal/MacOSX.hs b/src/Graphics/Vty/Terminal/MacOSX.hs
--- a/src/Graphics/Vty/Terminal/MacOSX.hs
+++ b/src/Graphics/Vty/Terminal/MacOSX.hs
@@ -17,6 +17,9 @@
 import Graphics.Vty.Terminal.Generic
 import qualified Graphics.Vty.Terminal.TerminfoBased as TerminfoBased
 
+import Control.Applicative
+import Control.Monad.Trans
+
 import System.IO
 
 data Term = Term 
@@ -25,17 +28,17 @@
     }
 
 -- for Terminal.app use "xterm". For iTerm.app use "xterm-256color"
-terminal_instance :: String -> IO Term
+terminal_instance :: ( Applicative m, MonadIO m ) => String -> m Term
 terminal_instance v = do
     let base_term "iTerm.app" = "xterm-256color"
         base_term _ = "xterm"
     t <- TerminfoBased.terminal_instance (base_term v) >>= new_terminal_handle
     return $ Term t v
 
-flushed_put :: String -> IO ()
+flushed_put :: MonadIO m => String -> m ()
 flushed_put str = do
-    hPutStr stdout str
-    hFlush stdout
+    liftIO $ hPutStr stdout str
+    liftIO $ hFlush stdout
 
 -- Terminal.app really does want the xterm-color smcup and rmcup caps. Not the generic xterm ones.
 smcup_str, rmcup_str :: String
diff --git a/src/Graphics/Vty/Terminal/TerminfoBased.hs b/src/Graphics/Vty/Terminal/TerminfoBased.hs
--- a/src/Graphics/Vty/Terminal/TerminfoBased.hs
+++ b/src/Graphics/Vty/Terminal/TerminfoBased.hs
@@ -10,11 +10,13 @@
 import Data.Terminfo.Eval
 
 import Graphics.Vty.Attributes
+import Graphics.Vty.DisplayAttributes
 import Graphics.Vty.Terminal.Generic
 import Graphics.Vty.DisplayRegion
 
 import Control.Applicative 
 import Control.Monad ( foldM )
+import Control.Monad.Trans
 
 import Data.Bits ( (.&.) )
 import Data.Maybe ( isJust, isNothing, fromJust )
@@ -51,10 +53,10 @@
     , enter_bold_mode :: Maybe CapExpression
     }
     
-marshall_cap_to_terminal :: Term -> (Term -> CapExpression) -> [CapParam] -> IO ()
+marshall_cap_to_terminal :: MonadIO m => Term -> (Term -> CapExpression) -> [CapParam] -> m ()
 marshall_cap_to_terminal t cap_selector cap_params = do
-    marshall_to_terminal t (cap_expression_required_bytes (cap_selector t) cap_params)
-                           (serialize_cap_expression (cap_selector t) cap_params)
+    marshall_to_terminal t ( cap_expression_required_bytes (cap_selector t) cap_params )
+                           ( serialize_cap_expression (cap_selector t) cap_params )
     return ()
 
 {- | Uses terminfo for all control codes. While this should provide the most compatible terminal
@@ -67,9 +69,9 @@
  - todo: Some display attributes like underline and bold have independent string capabilities that
  - should be used instead of the generic "sgr" string capability.
  -}
-terminal_instance :: String -> IO Term
+terminal_instance :: ( Applicative m, MonadIO m ) => String -> m Term
 terminal_instance in_ID = do
-    ti <- Terminfo.setupTerm in_ID
+    ti <- liftIO $ Terminfo.setupTerm in_ID
     let require_cap str 
             = case Terminfo.getCapability ti (Terminfo.tiGetStr str) of
                 Nothing -> fail $ "Terminal does not define required capability \"" ++ str ++ "\""
@@ -96,7 +98,9 @@
         <*> require_cap "clear"
         <*> current_display_attr_caps ti
 
-current_display_attr_caps :: Terminfo.Terminal -> IO DisplayAttrCaps
+current_display_attr_caps :: ( Applicative m, MonadIO m ) 
+                          => Terminfo.Terminal 
+                          -> m DisplayAttrCaps
 current_display_attr_caps ti 
     =   pure DisplayAttrCaps 
     <*> probe_cap "sgr"
@@ -147,15 +151,17 @@
         return $ c (DisplayContext b t color_count)
 
     display_bounds _t = do
-        raw_size <- get_window_size
+        raw_size <- liftIO $ get_window_size
         case raw_size of
             ( w, h )    | w < 0 || h < 0 -> fail $ "getwinsize returned < 0 : " ++ show raw_size
                         | otherwise      -> return $ DisplayRegion (toEnum w) (toEnum h)
 
     -- Output the byte buffer of the specified size to the terminal device.
     output_byte_buffer _t out_ptr out_byte_count = do
-        hPutBuf stdout out_ptr (fromEnum out_byte_count) 
-        hFlush stdout
+        if out_byte_count == 0
+            then return ()
+            else liftIO $ hPutBuf stdout out_ptr (fromEnum out_byte_count) 
+        liftIO $ hFlush stdout
 
 foreign import ccall "gwinsz.h c_get_window_size" c_get_window_size :: IO CLong
 
@@ -294,8 +300,7 @@
     default_attr_required_bytes d 
         = cap_expression_required_bytes (set_default_attr $ term d) []
     serialize_default_attr d out_ptr = do
-        out_ptr' <- serialize_cap_expression (set_default_attr $ term d) [] out_ptr
-        return out_ptr'
+        serialize_cap_expression ( set_default_attr $ term d ) [] out_ptr
 
 ansi_color_index :: Color -> Word
 ansi_color_index (ISOColor v) = toEnum $ fromEnum v
diff --git a/src/Graphics/Vty/Terminal/XTermColor.hs b/src/Graphics/Vty/Terminal/XTermColor.hs
--- a/src/Graphics/Vty/Terminal/XTermColor.hs
+++ b/src/Graphics/Vty/Terminal/XTermColor.hs
@@ -11,6 +11,9 @@
 import Graphics.Vty.Terminal.Generic
 import qualified Graphics.Vty.Terminal.TerminfoBased as TerminfoBased
 
+import Control.Applicative
+import Control.Monad.Trans
+
 import System.IO
 
 data XTermColor = XTermColor 
@@ -20,16 +23,19 @@
 
 -- Initialize the display to UTF-8
 -- Regardless of what is output the text encoding is assumed to be UTF-8
-terminal_instance :: String -> IO XTermColor
+terminal_instance :: ( Applicative m, MonadIO m ) => String -> m XTermColor
 terminal_instance variant = do
+    -- If the terminal variant is xterm-color use xterm instead since, more often than not,
+    -- xterm-color is broken.
+    let variant' = if variant == "xterm-color" then "xterm" else variant
     flushed_put set_utf8_char_set
-    t <- TerminfoBased.terminal_instance variant >>= new_terminal_handle
-    return $ XTermColor variant t
+    t <- TerminfoBased.terminal_instance variant' >>= new_terminal_handle
+    return $ XTermColor variant' t
 
-flushed_put :: String -> IO ()
+flushed_put :: MonadIO m => String -> m ()
 flushed_put str = do
-    hPutStr stdout str
-    hFlush stdout
+    liftIO $ hPutStr stdout str
+    liftIO $ hFlush stdout
 
 -- Since I don't know of a terminfo string cap that produces these strings these are hardcoded.
 set_utf8_char_set, set_default_char_set :: String
@@ -78,4 +84,11 @@
 
     default_attr_required_bytes d = default_attr_required_bytes (super_display d)
     serialize_default_attr d = serialize_default_attr (super_display d)
+
+    -- I think xterm is broken: Reseting the background color as the first bytes serialized on a new
+    -- line does not effect the background color xterm uses to clear the line. Which is used *after*
+    -- the next newline.
+    inline_hack _d = do
+        liftIO $ hPutStr stdout "\ESC[K"
+        liftIO $ hFlush stdout
 
diff --git a/test/Makefile b/test/Makefile
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,14 +1,18 @@
 VERIF_TESTS := \
 verify_attribute_ops \
+verify_display_attributes \
 verify_parse_terminfo_caps \
 verify_eval_terminfo_caps \
 verify_utf8_width \
 verify_image_ops \
 verify_image_trans \
+verify_empty_image_props \
 verify_picture_ops \
 verify_span_ops \
-verify_debug_terminal
+verify_debug_terminal \
+verify_inline \
 
+
 TESTS :=\
 Bench \
 Bench2 \
@@ -22,7 +26,7 @@
 $(shell mkdir -p objects )
 
 # TODO: Tests should also be buildable referencing the currently installed vty
-GHC_ARGS=--make -i../src -hide-package transformers -hide-package monads-fd -hide-package monads-tf -package QuickCheck-2.1.0.1 -ignore-package vty ../cbits/gwinsz.c ../cbits/set_term_timing.c  ../cbits/mk_wcwidth.c -O -funbox-strict-fields -Wall -threaded -fno-full-laziness -fspec-constr -odir objects -hidir objects
+GHC_ARGS=--make -i../src -package parallel-1.1.0.1 -hide-package transformers -hide-package monads-fd -hide-package monads-tf -package QuickCheck-2.1.0.2 -ignore-package vty ../cbits/gwinsz.c ../cbits/set_term_timing.c  ../cbits/mk_wcwidth.c -O -funbox-strict-fields -Wall -threaded -fno-full-laziness -fspec-constr -odir objects -hidir objects
 
 GHC_PROF_ARGS=-prof -auto-all $(GHC_ARGS)
 
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -41,4 +41,4 @@
             <-> char_fill pieceA ' ' sx (y - 1) 
             <-> char_fill pieceA ' ' x 1 <|> char pieceA '@' <|> char_fill pieceA ' ' (sx - x - 1) 1 
             <-> char_fill pieceA ' ' sx (sy - y - 2) 
-            <-> iso_10464_string dumpA btl
+            <-> iso_10646_string dumpA btl
diff --git a/test/Verify.hs b/test/Verify.hs
--- a/test/Verify.hs
+++ b/test/Verify.hs
@@ -1,3 +1,6 @@
+{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE StandaloneDeriving #-}
 {-# LANGUAGE DisambiguateRecordFields #-}
 {-# LANGUAGE NamedFieldPuns #-}
 module Verify ( module Verify
@@ -20,6 +23,7 @@
 
 import qualified Codec.Binary.UTF8.String as UTF8
 
+import Control.Applicative
 import Control.Monad.State.Strict
 import Control.Monad.Trans ( liftIO )
 
@@ -30,7 +34,11 @@
 
 import System.IO
 
-type Test v = StateT TestState IO v
+type Test = StateT TestState IO
+
+instance Applicative Test where
+    pure = return
+    ( <*> ) = ap
 
 data TestState = TestState
     { results_ref :: IORef [QC.Result]
diff --git a/test/interactive_terminal_test.hs b/test/interactive_terminal_test.hs
--- a/test/interactive_terminal_test.hs
+++ b/test/interactive_terminal_test.hs
@@ -4,6 +4,7 @@
 
 import Graphics.Vty.Attributes
 import Graphics.Vty.Image
+import Graphics.Vty.Inline
 import Graphics.Vty.Picture
 import Graphics.Vty.Terminal
 import Graphics.Vty.DisplayRegion
@@ -165,6 +166,8 @@
       , attributes_test_3
       , attributes_test_4
       , attributes_test_5
+      , inline_test_0
+      , inline_test_1
       ]
 
 reserve_output_test = Test 
@@ -363,8 +366,8 @@
              , [ 0x41 ]
              ]
 
-iso_10464_txt_0 :: String
-iso_10464_txt_0 = map toEnum
+iso_10646_txt_0 :: String
+iso_10646_txt_0 = map toEnum
     [ 8593 
     , 8593
     , 8595
@@ -404,7 +407,7 @@
         reserve_display t
         let pic = pic_for_image image
             image = line_0 <-> line_1
-            line_0 = iso_10464_string def_attr iso_10464_txt_0
+            line_0 = iso_10646_string def_attr iso_10646_txt_0
             line_1 = string def_attr "0123456789"
         d <- display_bounds t >>= display_context t
         output_picture d pic
@@ -456,8 +459,8 @@
              , [0xe5,0x90,0x97]
              ]
 
-iso_10464_txt_1 :: String
-iso_10464_txt_1 = map toEnum [20320,22909,21527]
+iso_10646_txt_1 :: String
+iso_10646_txt_1 = map toEnum [20320,22909,21527]
 
 unicode_double_width_0 = Test
     { test_name = "Verify terminal can display unicode double-width characters. (Direct UTF-8)"
@@ -486,7 +489,7 @@
         reserve_display t
         let pic = pic_for_image image
             image = line_0 <-> line_1
-            line_0 = iso_10464_string def_attr iso_10464_txt_1
+            line_0 = iso_10646_string def_attr iso_10646_txt_1
             line_1 = string def_attr "012345"
         d <- display_bounds t >>= display_context t
         output_picture d pic
@@ -860,3 +863,41 @@
         default_success_confirm_results
     }
 
+inline_test_0 = Test
+    { test_name = "Verify styled output can be performed without clearing the screen."
+    , test_ID = "inline_test_0"
+    , test_action = do
+        t <- terminal_handle
+        putStrLn "line 1."
+        put_attr_change t $ back_color red >> apply_style underline
+        putStrLn "line 2."
+        put_attr_change t $ default_all
+        putStrLn "line 3."
+        release_terminal t
+        return ()
+    , print_summary = putStr $ [$heredoc|
+lines are in order.
+The second line "line 2" should have a red background and the text underline.
+The third line "line 3" should be drawn in the same style as the first line.
+|]
+
+    , confirm_results = generic_output_match_confirm
+    }
+
+inline_test_1 = Test
+    { test_name = "Verify styled output can be performed without clearing the screen."
+    , test_ID = "inline_test_1"
+    , test_action = do
+        t <- terminal_handle
+        putStr "Not styled. "
+        put_attr_change t $ back_color red >> apply_style underline
+        putStr " Styled! "
+        put_attr_change t $ default_all
+        putStrLn "Not styled."
+        release_terminal t
+        return ()
+    , print_summary = putStr $ [$heredoc|
+|]
+
+    , confirm_results = generic_output_match_confirm
+    }
diff --git a/test/verify_picture_ops.hs b/test/verify_picture_ops.hs
--- a/test/verify_picture_ops.hs
+++ b/test/verify_picture_ops.hs
@@ -1,6 +1,6 @@
 module Main where
 
-import Graphics.Vty.Picture
+import Graphics.Vty.Picture ( translate )
 
 import Verify
 
diff --git a/vty.cabal b/vty.cabal
--- a/vty.cabal
+++ b/vty.cabal
@@ -1,5 +1,5 @@
 Name:                vty
-Version:             4.0.0.1
+Version:             4.2.1.0
 License:             BSD3
 License-file:        LICENSE
 Author:              Stefan O'Rear, Corey O'Connor
@@ -30,15 +30,17 @@
 Build-Depends:       terminfo >= 0.3 && < 0.4
 Build-Depends:       utf8-string >= 0.3 && < 0.4
 Build-Depends:       mtl >= 1.1.0.0 && < 1.2
-Build-Depends:       ghc-prim, parallel
+Build-Depends:       ghc-prim, parallel < 2
 Build-Depends:       array
 Build-Depends:       parsec >= 2 && < 4
+Build-Depends:       vector-space >= 0.5 && < 0.6
 Build-Type:          Simple
 Data-Files:          README, TODO
 Exposed-Modules:     Graphics.Vty
                      Graphics.Vty.Terminal
                      Graphics.Vty.LLInput
                      Graphics.Vty.Attributes
+                     Graphics.Vty.Inline
                      Graphics.Vty.Picture
                      Graphics.Vty.DisplayRegion
 
@@ -46,6 +48,7 @@
                      Data.Marshalling
                      Data.Terminfo.Parse
                      Data.Terminfo.Eval
+                     Graphics.Vty.DisplayAttributes
                      Graphics.Vty.Image
                      Graphics.Vty.Span
                      Graphics.Vty.Terminal.Generic
@@ -95,5 +98,5 @@
                     cbits/gwinsz.h
 
 ghc-options:         -funbox-strict-fields -Wall -fno-full-laziness -fspec-constr
-ghc-prof-options:    -funbox-strict-fields -auto-all -Wall -fno-full-laziness -fspec-constr
+ghc-prof-options:    -funbox-strict-fields -caf-all -Wall -fno-full-laziness -fspec-constr
 
