diff --git a/Main.hs b/Main.hs
--- a/Main.hs
+++ b/Main.hs
@@ -1,10 +1,30 @@
 import System.Environment
 import System.Exit
 import System.IO
+import Data.Array.IArray
 
 import Data.ByteString.Char8 (pack)
 import Graphics.Vty
 
+-- pad left fills the left side with pad chars, pad right fills the right side
+-- with pad chars
+data Pad = Pad { padLeft     :: String -> String
+               , padRight    :: String -> String }
+
+type Frame = [String]
+
+-- an immutable array of frames, one-indexed
+type Presentation = Array Int Frame
+
+newPad :: Char -> Int -> Pad
+newPad c w = Pad { padLeft     = padl
+                 , padRight    = padr }
+    where
+      pad' t = replicate (w - length t) c
+      shorten = take w
+      padl t = pad' t ++ shorten t
+      padr t = shorten t ++ pad' t
+
 -- |Split an input list
 split :: Eq a => [a] -> [[a]] -> [[[a]]]
 split _ [] = [[]]
@@ -12,48 +32,80 @@
       | tok == x  = [] : split tok xs
       | otherwise = let (x':xs') = split tok xs in (x:x') : xs'
 
--- |Render a string as an Image, and right pad it with some character.
-bsLine :: String -> Char -> Int -> Image
-bsLine txt fill width = renderBS attr $ pack txt'
+-- |Convert a string to an image
+toImage :: String -> Image
+toImage = renderBS attr . pack
+
+-- |Render a frame. The first pair of Ints is the tuple (screen width, screen
+-- height), the second pair of Ints is the two numbers to display in the lower
+-- right corner, likely the tuple (slide num, total slides).
+renderFrame :: Frame -> (Int, Int) -> (Int, Int) -> Image
+renderFrame (title:body) (w, h) (num, tot) = vertcat $ map toImage text
     where
-      txt' = ' ' : txt ++ (replicate (width - length txt - 2) fill)
+      p = newPad ' ' w
+      t = padRight p (' ' : title)
+      sep = replicate w '-'
+      body' = take (min (h - 3) (length body)) body -- maybe shorten body
+      bodyLines = [padRight p (' ':b) | b <- body']
+      vsep = [padRight p "" | _ <- [1 .. h - length body - 3]]
+      foot = padLeft p (show num ++ " / " ++ show tot)
+      text = foldl (++) [] [[t, sep], bodyLines, vsep, [foot]]
 
+
 -- |Take a Vty and a list of frames, and do the presentation; this function
 -- terminates when q or Ctrl-C are entered.
-loop :: Vty -> [[String]] -> IO ()
-loop vty frames = loop' 0
+loop :: Vty -> Presentation -> IO ()
+loop vty pres = loop' minFrame
     where
-      maxframe = length frames - 1
-      formatText w [] = empty
-      formatText w (x:xs) = (bsLine x ' ' w) <-> (formatText w xs)
+      (minFrame, maxFrame) = bounds pres
       loop' n = do
-        let (title:text) = frames !! n
-        (w, h) <- getSize vty
-        let im = bsLine title ' ' w <->
-                 bsLine "" '-' w <->
-                 formatText w text
-        update vty (pic { pCursor = NoCursor,
-                          pImage = im })
-        ev <- getEvent vty
-        case ev of
-          EvKey KLeft _  -> loop' (max 0 (n-1))
-          EvKey KRight _ -> loop' (min maxframe (n+1))
-          EvKey (KASCII 'q') _       -> return ()
-          EvKey (KASCII 'c') [MCtrl] -> return ()
-          _              -> loop' n
+        let frame = pres ! n
+        dims <- getSize vty
+        blankVty vty
+        update vty $ pic { pCursor = NoCursor,
+                           pImage  = renderFrame frame dims (n, maxFrame) }
+        eventLoop
+        where
+          eventLoop = do ev <- getEvent vty
+                         case ev of
+                           EvKey KLeft _  -> loop' (max minFrame (n-1))
+                           EvKey KRight _ -> loop' (min maxFrame (n+1))
+                           EvKey KHome _  -> loop' minFrame
+                           EvKey KEnd _   -> loop' maxFrame
+                           EvKey (KASCII 'q') _       -> return ()
+                           EvKey (KASCII 'c') [MCtrl] -> return ()
+                           EvKey (KASCII 'r') _ -> blankVty vty >> loop' n
+                           _              -> eventLoop
 
+-- |Sometimes the vty module gets confused and leaves artifacts from previous
+-- slides on the screen. Calling blankvty a few times seems to fix this.
+blankVty :: Vty -> IO ()
+blankVty vty = do
+  (w, h) <- getSize vty
+  let lines = [replicate w ' ' | _ <- [1..h]]
+  update vty $ pic { pCursor = NoCursor
+                   , pImage = vertcat $ map toImage lines}
+  refresh vty
+
+-- |Parse an input file, representing a presentation, into a presentation
+makeFrames :: String -> Presentation
+makeFrames xs = listArray (1, length frames) frames
+    where
+      frames = concatMap copyFrames $ basicSplit xs
+      basicSplit = split "--" . lines
+      copyFrames = cf [] . split "."
+      cf _ [] = []
+      cf h (x:xs) = let p = h ++ x in p : cf (p ++ [[]]) xs
+
 main = do
   args <- getArgs
   presentation <- parse args
   h <- openFile presentation ReadMode
   frames <- fmap makeFrames $ hGetContents h
   vty <- mkVty
-  refresh vty
   loop vty frames
   shutdown vty
   where
-    makeFrames s = split "--" $ lines s
-
     parse ["-h"] = usage
     parse [x]    = return x
     parse _      = usage
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -10,15 +10,23 @@
 
 This will compile hspresent, and install an `hspresent` command line program.
 
+You can download the latest stable release of hspresent on
+[Hackage](http://hackage.haskell.org/package/hspresent). The git repository is
+online at `git://github.com/eklitzke/hspresent.git`.
+
 Usage
 -----
 Invoke like `hspresent /path/to/your/presentation`. Left and right arrow keys
 move between slides, and hitting `q` or `Ctrl-C` quits the presentation.
 
 The file format is really simple right now. Slides are separated by lines
-consisting of the characters `--`. That's it. Here's an example presentation:
+consisting of the characters `--`. You can put the single character `.` on a
+line to demarcate a "split" frame. A split frame really creates a new frame with
+the contents of the previous frame copied at the front (this is similar to how
+beamer works). That's it. Here's an example presentation:
     the title of the first slide
     this is
+    .
     really cool
     --
     the title of the second slide
diff --git a/hspresent.cabal b/hspresent.cabal
--- a/hspresent.cabal
+++ b/hspresent.cabal
@@ -1,7 +1,7 @@
 Author:        Evan Klitzke
 Maintainer:    Evan Klitzke <evan@eklitzke.org>
 Name:          hspresent
-Version:       0.1
+Version:       0.2
 Cabal-Version: >= 1.2
 License:       BSD3
 License-File:  LICENSE
@@ -9,14 +9,26 @@
 Copyright:     (c) 2009 by Evan Klitzke
 Synopsis:      A terminal presentation tool
 Description:
-  Give fancy presentations in your terminal.
- 
+  Hspresent is a simple program that lets you give powerpoint-like presentations
+  in your terminal (for certain definitions of powerpoint-like). It's extremely
+  basic and unintelligent. Don't expect much.
+  .
+  Invoke like `hspresent /path/to/your/presentation`. Left and right arrow keys
+  move between slides, and hitting `q` or `Ctrl-C` quits the presentation.
+  .
+  The file format is really simple right now. Slides are separated by lines
+  consisting of the characters `--`. You can put the single character `.` on a
+  line to demarcate a split frame. A split frame really creates a new frame with
+  the contents of the previous frame copied at the front (this is similar to how
+  beamer works).
+
 Build-Type: Simple
 
 Executable hspresent
   Main-Is: Main.hs
 
 Library
-  Build-Depends: base < 5
-               , bytestring
-               , vty
+  Build-Depends:  array
+                , base < 5
+                , bytestring
+                , vty
