diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,21 @@
 Brick changelog
 ---------------
 
+0.20
+----
+
+Package changes:
+ * Added a dependency on "word-wrap" for text-wrapping.
+ * Added a new TextWrapDemo demo program to illustrate text wrapping
+   support
+
+API changes:
+ * Brick.Widgets.Core: added new functions txtWrap and strWrap to do
+   wrapping of long lines of text.
+
+Miscellaneous:
+ * Guide: fixed event type (#126)
+
 0.19
 ----
 
diff --git a/brick.cabal b/brick.cabal
--- a/brick.cabal
+++ b/brick.cabal
@@ -1,5 +1,5 @@
 name:                brick
-version:             0.19
+version:             0.20
 synopsis:            A declarative terminal user interface library
 description:
   Write terminal applications painlessly with 'brick'! You write an
@@ -93,7 +93,8 @@
                        text,
                        text-zipper >= 0.7.1,
                        template-haskell,
-                       deepseq >= 1.3 && < 1.5
+                       deepseq >= 1.3 && < 1.5,
+                       word-wrap
 
 executable brick-readme-demo
   if !flag(demos)
@@ -103,6 +104,18 @@
   default-language:    Haskell2010
   default-extensions:  CPP
   main-is:             ReadmeDemo.hs
+  build-depends:       base,
+                       brick,
+                       text
+
+executable brick-text-wrap-demo
+  if !flag(demos)
+    Buildable: False
+  hs-source-dirs:      programs
+  ghc-options:         -threaded -Wall -fno-warn-unused-do-bind -O3
+  default-language:    Haskell2010
+  default-extensions:  CPP
+  main-is:             TextWrapDemo.hs
   build-depends:       base,
                        brick,
                        text
diff --git a/docs/guide.rst b/docs/guide.rst
--- a/docs/guide.rst
+++ b/docs/guide.rst
@@ -103,7 +103,7 @@
    data App s e n =
        App { appDraw         :: s -> [Widget n]
            , appChooseCursor :: s -> [CursorLocation n] -> Maybe (CursorLocation n)
-           , appHandleEvent  :: s -> e -> EventM n (Next s)
+           , appHandleEvent  :: s -> BrickEvent n e -> EventM n (Next s)
            , appStartEvent   :: s -> EventM n s
            , appAttrMap      :: s -> AttrMap
            }
diff --git a/programs/TextWrapDemo.hs b/programs/TextWrapDemo.hs
new file mode 100644
--- /dev/null
+++ b/programs/TextWrapDemo.hs
@@ -0,0 +1,13 @@
+module Main where
+
+import Data.Monoid ((<>))
+import Brick
+
+ui :: Widget ()
+ui = strWrap $ "Hello, world! This line is long enough that " <>
+               "it's likely to wrap on your terminal if your window " <>
+               "isn't especially wide. Try narrowing and widening " <>
+               "the window to see what happens to this text."
+
+main :: IO ()
+main = simpleMain ui
diff --git a/src/Brick/Widgets/Core.hs b/src/Brick/Widgets/Core.hs
--- a/src/Brick/Widgets/Core.hs
+++ b/src/Brick/Widgets/Core.hs
@@ -2,6 +2,7 @@
 {-# LANGUAGE TupleSections #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE OverloadedStrings #-}
 -- | This module provides the core widget combinators and rendering
 -- routines. Everything this library does is in terms of these basic
 -- primitives.
@@ -11,7 +12,9 @@
   , emptyWidget
   , raw
   , txt
+  , txtWrap
   , str
+  , strWrap
   , fill
 
   -- * Padding
@@ -100,6 +103,8 @@
 import qualified Graphics.Vty as V
 import Control.DeepSeq
 
+import Text.Wrap (wrapTextToLines)
+
 import Brick.Types
 import Brick.Types.Internal
 import Brick.Widgets.Border.Style
@@ -195,6 +200,33 @@
             then c : takeColumns (numCols - w) cs
             else ""
 
+-- | Make a widget from a string, but wrap the words in the input's
+-- lines at the available width.
+strWrap :: String -> Widget n
+strWrap = txtWrap . T.pack
+
+safeTextWidth :: T.Text -> Int
+safeTextWidth = V.safeWcswidth . T.unpack
+
+-- | Make a widget from text, but wrap the words in the input's lines at
+-- the available width.
+txtWrap :: T.Text -> Widget n
+txtWrap s =
+    Widget Fixed Fixed $ do
+      c <- getContext
+      let theLines = fixEmpty <$> wrapTextToLines (c^.availWidthL) s
+          fixEmpty l | T.null l = " "
+                     | otherwise = l
+      case force theLines of
+          [] -> return emptyResult
+          [one] -> return $ emptyResult & imageL .~ (V.text' (c^.attrL) one)
+          multiple ->
+              let maxLength = maximum $ safeTextWidth <$> multiple
+                  lineImgs = lineImg <$> multiple
+                  lineImg lStr = V.text' (c^.attrL)
+                                   (lStr <> T.replicate (maxLength - safeTextWidth lStr) " ")
+              in return $ emptyResult & imageL .~ (V.vertCat lineImgs)
+
 -- | Build a widget from a 'String'. Breaks newlines up and space-pads
 -- short lines out to the length of the longest line.
 str :: String -> Widget n
@@ -214,8 +246,8 @@
                   lineImg lStr = V.string (c^.attrL) (lStr ++ replicate (maxLength - V.safeWcswidth lStr) ' ')
               in return $ emptyResult & imageL .~ (V.vertCat lineImgs)
 
--- | Build a widget from a one-line 'T.Text' value. Behaves the same as
--- 'str'.
+-- | Build a widget from a 'T.Text' value. Behaves the same as 'str'
+-- when the input contains multiple lines.
 txt :: T.Text -> Widget n
 txt = str . T.unpack
 
