diff --git a/Graphics/Vty.hs b/Graphics/Vty.hs
--- a/Graphics/Vty.hs
+++ b/Graphics/Vty.hs
@@ -1,5 +1,10 @@
 {-# OPTIONS_GHC -fffi #-}
 {-# CFILES gwinsz.c #-}
+
+-- Good sources of documentation for terminal programming are:
+-- vt100 control sequences: http://vt100.net/docs/vt100-ug/chapter3.html#S3.3.3
+-- Xterm control sequences: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+
 module Graphics.Vty (Vty(..), beep, mkVty, module Graphics.Vty.Types, Key(..), Modifier(..), Button(..), Event(..)) where
 
 import Control.Concurrent
@@ -24,6 +29,10 @@
 		 getEvent :: IO Event,
                  -- |Get the size of the display.
                  getSize :: IO (Int,Int),
+                 -- |Refresh the display. Normally the library takes care of refreshing. 
+                 -- Nonetheless, some other program might output to the terminal and mess the display.
+                 -- In that case the user might want to force a refresh.
+                 refresh :: IO (),
                  -- |Clean up after vty.
                  shutdown :: IO () }
 
@@ -44,6 +53,7 @@
  rec = Vty { update = update' 
            , getEvent = gkey
            , getSize = ulift getwinsize
+           , refresh = refr
            , shutdown = fend }
 
  update' (Pic nc (T.Image wr w h)) = modifyMVar_ rstate $ \(ts0, fbw, fbh, oldptr) -> do
@@ -61,10 +71,14 @@
    free shd
    return (ts4, w, h, fb)
 
+ -- just refresh
+ refr = modifyMVar_ rstate $ \(ts0,_,_,p) ->
+         fmap (\(_,ts1) -> (ts1,(-1),(-1),p)) (getwinsize ts0)
+
+ -- refresh and return a state event
  inval = modifyMVar rstate $ \(ts0,_,_,p) ->
          fmap (\((x,y),ts1) -> ((ts1,(-1),(-1),p),EvResize x y)) (getwinsize ts0)
 
  gkey = do k <- kvar
-           case k of (EvKey (KASCII 'l') [MCtrl]) -> inval
-                     (EvResize _ _)               -> inval
+           case k of (EvResize _ _)               -> inval
                      _                            -> return k
diff --git a/Graphics/Vty/Cursor.hs b/Graphics/Vty/Cursor.hs
--- a/Graphics/Vty/Cursor.hs
+++ b/Graphics/Vty/Cursor.hs
@@ -17,7 +17,7 @@
 import Graphics.Vty.Types
 
 -- | An object representing the current state of the terminal.
-data TermState = TS !Int !Int !Attr
+data TermState = TS {_tsRow :: !Int,  _tsColumn :: !Int, _tsAttr :: !Attr}
 
 -- | Set up the terminal for output, and create an object representing the
 -- initial state.  Also returns a function for shutting down the terminal access.
@@ -125,17 +125,41 @@
 getwinsize ts = do (a,b) <- (`divMod` 65536) `fmap` c_get_window_size
                    return ((fromIntegral b, fromIntegral a), ts)
 
-cvis, civis, reset :: [Char]
 
-reset = "\ESCc\ESC%G\ESC[1;1H\ESC[2J"
+csi, cvis, civis, reset :: String
+
+csi = "\ESC["
+
+reset =  "\ESCc"  ++ -- full reset
+      utf8CharSet ++ 
+      setCursorPosition 1 1 ++
+      "\ESC[2J" -- erase all
+
+setCursorPosition :: Int -> Int -> String
+setCursorPosition row column = csi ++ show row ++ ";" ++ show column ++ "H"
+
 -- | Make the terminal beep.
 beep :: IO ()
 beep = putStr "\BEL" 
+
 -- | Show the cursor
-cvis = "\ESC[?25h" 
-civis = "\ESC[?25l"
+cvis = csi ++ "?25h" 
+
+-- | Hide the cursor
+civis = csi ++ "?25l"
+
+defaultCharSet, utf8CharSet :: String
+defaultCharSet = "\ESC%@"
+utf8CharSet    = "\ESC%G"
+
+-- | Restore the terminal to a good state for the shell.
+-- Parameter is the line where the cursor should appear.
 endterm :: Int -> [Char]
-endterm sy = "\ESC[" ++ show sy ++ ";1H\ESC[0;39;49m" ++
-             "\ESC%@\CR" ++ -- select default charset (\ESC%G would select UTF8)
+endterm sy = setCursorPosition sy 1 ++
+             "\ESC[0;39;49m" ++ -- graphic rendition
+             defaultCharSet ++ 
+             "\CR" ++ 
              cvis ++
-             "\ESC[K"
+             "\ESC[K" -- erase line
+
+
diff --git a/Graphics/Vty/LLInput.hs b/Graphics/Vty/LLInput.hs
--- a/Graphics/Vty/LLInput.hs
+++ b/Graphics/Vty/LLInput.hs
@@ -124,11 +124,13 @@
          [ let k c s = ("\ESC["++c,(s,[])) in [ k "G" KNP5, k "P" KPause,  k "A" KUp, k "B" KDown, k "C" KRight, k "D" KLeft ],
 
            -- Support for arrows
-           let k c s = [("\ESC[1;"++show mc++c,(s,m)) | (m,mc) <- 
-                        [([MShift],2::Int), ([MCtrl],5), ([MMeta],3), 
-                         ([MShift, MCtrl],6), ([MShift, MMeta],4)]]
-               in concat [ k "A" KUp, k "B" KDown, k "C" KRight, k "D" KLeft ],
-
+           [("\ESC[" ++ charCnt ++ show mc++c,(s,m)) 
+            | charCnt <- ["1;", ""], -- we can have a count or not
+            (m,mc) <- [([MShift],2::Int), ([MCtrl],5), ([MMeta],3), 
+                       ([MShift, MCtrl],6), ([MShift, MMeta],4)], -- modifiers and their codes
+            (c,s) <- [("A", KUp), ("B", KDown), ("C", KRight), ("D", KLeft)] -- directions and their codes
+           ],
+           
            let k n s = ("\ESC["++show n++"~",(s,[])) in zipWith k [2::Int,3,5,6] [KIns,KDel,KPageUp,KPageDown],
 
            -- Support for simple characters.
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -12,7 +12,8 @@
 
 play vt x y sx sy btl = do update vt (render x y sx sy btl)
                            k <- getEvent vt
-                           case k of EvKey KLeft  [] | x /= 0      -> play vt (x-1) y sx sy btl
+                           case k of EvKey (KASCII 'r') [MCtrl]    -> refresh vt >> play vt x y sx sy btl
+                                     EvKey KLeft  [] | x /= 0      -> play vt (x-1) y sx sy btl
                                      EvKey KRight [] | x /= (sx-1) -> play vt (x+1) y sx sy btl
                                      EvKey KUp    [] | y /= 0      -> play vt x (y-1) sx sy btl
                                      EvKey KDown  [] | y /= (sy-2) -> play vt x (y+1) sx sy btl
diff --git a/vty.cabal b/vty.cabal
--- a/vty.cabal
+++ b/vty.cabal
@@ -1,5 +1,5 @@
 Name:                vty
-Version:             3.0.4
+Version:             3.1.0
 License:             BSD3
 License-file:        LICENSE
 Author:              Stefan O'Rear
