diff --git a/CmdParams.hs b/CmdParams.hs
new file mode 100644
--- /dev/null
+++ b/CmdParams.hs
@@ -0,0 +1,84 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  CmdParams
+-- Copyright   :  (C) Peter Robinson 2010-2013
+-- License     :  GPL-2
+--
+-- Maintainer  :  Peter Robinson <thaldyron@gmail.com>
+-- Stability   :  experimental
+-- Portability :  portable 
+-- 
+-- Contains the command line parameter definitions.
+--
+-----------------------------------------------------------------------------
+module CmdParams
+where
+import System.Console.CmdArgs
+
+data OutputFile = FileSVG | FilePDF | FilePNG 
+  deriving(Eq,Data,Typeable)
+
+instance Show OutputFile where
+  show FileSVG = ".svg"
+  show FilePDF = ".pdf"
+  show FilePNG = ".png"
+
+outputFileToGraphviz :: OutputFile -> String
+outputFileToGraphviz FileSVG = " -Tsvg "
+outputFileToGraphviz FilePDF = " -Tpdf "
+outputFileToGraphviz FilePNG = " -Tpng "
+
+
+instance Default OutputFile where
+  def = FilePDF
+
+-- | Command line arguments:
+data MathGenealogy = MathGenealogy 
+  { prefix              :: String 
+  , keepDotFile         :: Bool
+  , graphvizArgs        :: String
+--  , onlyDotFile         :: Bool
+  , verbose             :: Bool
+  , includeTheses       :: Bool
+  , startURL            :: String
+  , outputFile          :: OutputFile
+  , font                :: String
+  , fontHeading         :: String
+  , fontSize            :: Double
+  , fontSizeHeading     :: Double
+  , fontSizeFirst       :: Double
+  , fontSizeFirstHeading:: Double
+  , nodeBackgroundColor :: String
+  , edgeColor           :: String
+  , oldTextLabels       :: Bool
+  }
+  deriving(Eq,Data,Typeable,Show)
+
+
+mathGenealogy :: MathGenealogy
+mathGenealogy = MathGenealogy
+  { startURL     = def &= args &= typ "URL" 
+  , prefix       = "output" &= typ "PREFIX" 
+  , keepDotFile  = False 
+  , graphvizArgs = " -Gcharset=utf8 " &= typ "<graphviz parameters>" -- &= opt " -Gcharset=utf8 "
+--  , onlyDotFile  = False &= help "Only create a GraphViz '.dot' file."
+  , verbose      = False &= help "Print data to terminal."
+  , includeTheses= False &= help "Include PhD thesis in output"
+  , outputFile   = enum [ FileSVG &= help "create SVG file (default - best supported by GraphViz; use this if you run into issues.)"
+                        , FilePDF &= help "create PDF file"
+                        , FilePNG &= help "create PNG file"
+                        ]
+  , font         = "Helvetica" &= help "Fonts included with GraphViz (see http://www.graphviz.org/doc/fontfaq.txt): AvantGarde-Book AvantGarde-BookOblique AvantGarde-Demi AvantGarde-DemiOblique Bookman-Demi Bookman-DemiItalic Bookman-Light Bookman-LightItalic Courier Courier-Bold Courier-BoldOblique Courier-Oblique Helvetica Helvetica-Bold Helvetica-BoldOblique Helvetica-Narrow Helvetica-Narrow-Bold Helvetica-Narrow-BoldOblique Helvetica-Narrow-Oblique Helvetica-Oblique NewCenturySchlbk-Bold NewCenturySchlbk-BoldItalic NewCenturySchlbk-Italic NewCenturySchlbk-Roman Palatino-Bold Palatino-BoldItalic Palatino-Italic Palatino-Roman Symbol Times-Bold Times-BoldItalic Times-Italic Times-Roman ZapfChancery-MediumItalic ZapfDingbats  "
+  , fontSize             = 12 &= help "Font size of the additional information of all entries except the first one."
+  , fontHeading          = "Helvetica" &= help "Font used for names"
+  , fontSizeHeading      = 16 &= help "Font size used for names"
+  , fontSizeFirstHeading = 20 &= help "Font size of first entry."
+  , fontSizeFirst        = 16 &= help "Font size of first entry."
+  , nodeBackgroundColor  = "LightBlue1" &= help "Node background color. See http://hackage.haskell.org/packages/archive/graphviz/2999.15.0.1/doc/html/Data-GraphViz-Attributes-Colors-X11.html"
+  , edgeColor            = "Gray" &= help "Edge color. See http://hackage.haskell.org/packages/archive/graphviz/2999.15.0.1/doc/html/Data-GraphViz-Attributes-Colors-X11.html"
+  , oldTextLabels        = False &= help "Fall back to non-HTML text labels. Use this if you are having issues with the rendering of the HTML-like labels. Note that all font parameters except 'font', 'fontsize', and 'fontsizefirst' are ignored with this setting."
+  } &= summary "Mathematics Genealogy Visualizer (C) 2010-2013 Peter Robinson thaldyron@gmail.com" 
+    &= details[ "Run the program with a start-URL, for example:"
+              ,"# mathgenealogy http://genealogy.math.ndsu.nodak.edu/id.php?id=18231"
+              ,"Disclaimer: This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose.  See the GNU General Public License (version 2) for full details."
+              ]
diff --git a/Entry.hs b/Entry.hs
--- a/Entry.hs
+++ b/Entry.hs
@@ -15,16 +15,18 @@
 import Data.List(intercalate)
 import Data.Text.Lazy(Text)
 import qualified Data.Text.Lazy as T
+import qualified Data.GraphViz.Attributes.HTML as GA
+import Data.Text.Lazy.Encoding 
+import Data.Binary
+import Control.Monad(liftM)
 
 data Entry = Entry 
   { entryName :: Text 
   , entryGraduationInfo :: [GraduationInfo]
   , entryAdvisors :: [(Text,Text)]
   }
-  deriving(Ord,Eq)
+  deriving(Eq,Ord)
 
-urlAdvisors :: Entry -> [Text]
-urlAdvisors = map (T.pack . (++) "http://genealogy.math.ndsu.nodak.edu/" . T.unpack . snd) . entryAdvisors
 
 data GraduationInfo = GraduationInfo
   { gradDegree :: Maybe Text
@@ -32,22 +34,42 @@
   , gradYear :: Maybe Text
   , gradThesis :: Maybe Text
   }
-  deriving(Ord,Eq)
+  deriving(Eq,Ord)
 
-entryToText :: Entry -> Text
-entryToText e =
-    entryName e `T.append` (T.concat $ map graduationInfoToText (entryGraduationInfo e))
-                `T.append` (T.concat $ map fst (entryAdvisors e))
+instance Binary Text where
+    put = put . encodeUtf8
+    get = liftM decodeUtf8 get
 
+instance Binary Entry where
+        put (Entry x1 x2 x3) = put x1 >> put x2 >> put x3
+        get = do 
+            x1 <- get
+            x2 <- get
+            x3 <- get
+            return $ Entry x1 x2 x3
+ 
+instance Binary GraduationInfo where
+        put (GraduationInfo x1 x2 x3 x4) = put x1 >> put x2 >> put x3 >> put x4
+        get = do 
+            x1 <- get
+            x2 <- get
+            x3 <- get
+            x4 <- get
+            return $ GraduationInfo x1 x2 x3 x4
+
+
+
+urlAdvisors :: Entry -> [Text]
+urlAdvisors = map (T.pack . (++) "http://genealogy.math.ndsu.nodak.edu/" . T.unpack . snd) . entryAdvisors
+
+
 instance Show Entry where
   show e = 
     let ginfos = concatMap show (entryGraduationInfo e) in
     T.unpack (entryName e)
-      ++ if ginfos /= [] then "\n" ++ ginfos else ""
-    where 
-      maybeShow (Just g) = "\\n" ++ show g
-      maybeShow Nothing  = ""
+      ++ if length ginfos > 2 then "\\n" ++ ginfos else ""
 
+
 instance Show GraduationInfo where
   show g = 
     let ls  = map T.unpack $ catMaybes [gradDegree g, gradUniversity g, gradYear g] in
@@ -56,19 +78,54 @@
       maybeShow (Just gi) = T.unpack gi 
       maybeShow Nothing   = "" 
 
+
+-- | Transform an `Entry` to plaintext. 
+entryToText :: Entry -> Text
+entryToText e =
+  let ginfos = T.intercalate (T.pack "\\n") $ map graduationInfoToText (entryGraduationInfo e) in
+  entryName e `T.append` (if T.length ginfos > 2 then T.pack "\\n" `T.append` ginfos else T.pack "")
+
+
 graduationInfoToText :: GraduationInfo -> Text
 graduationInfoToText g = 
-    let ls  = catMaybes [gradDegree g, gradUniversity g, gradYear g] in
-    T.intercalate (T.pack ", ") ls  `T.append` (T.pack "\\n") `T.append` (maybeText (gradThesis g))
-    where
-      maybeText (Just gi) = gi 
-      maybeText Nothing   = T.pack "" 
+  let ls  = catMaybes [gradDegree g, gradUniversity g, gradYear g] in
+  T.intercalate (T.pack ", ") ls  `T.append` (maybeText (gradThesis g))
+  where
+    maybeText (Just gi) = T.pack "\\n" `T.append` gi 
+    maybeText Nothing   = T.pack "" 
 
 
+-- | Transform an `Entry` to an HTML-like label.
+entryToHtml :: GA.Attributes  -- ^ table attributes
+            -> GA.Attributes  -- ^ font options for header
+            -> GA.Attributes  -- ^ font options for body text
+            -> Entry
+            -> GA.Label
+entryToHtml tableAtts headingAtts fontAtts e = 
+  let ginfos = intercalate [GA.Newline []] $ map graduationInfoToHtml (entryGraduationInfo e) in
+  GA.Table $ GA.HTable Nothing tableAtts $
+      (GA.Cells [GA.LabelCell [GA.Align GA.HCenter] $ 
+          GA.Text [GA.Font headingAtts [GA.Str (entryName e)]]]) :
+              [GA.Cells [GA.LabelCell [] $ GA.Text [GA.Font fontAtts ginfos]]
+              | not $ null ginfos ]
+
+
+graduationInfoToHtml :: GraduationInfo -> [GA.TextItem]
+graduationInfoToHtml g = 
+  let ls     = catMaybes [gradDegree g, gradUniversity g, gradYear g] 
+      thesis = maybeText (gradThesis g) in
+  case (null ls,isNothing $ gradThesis g) of 
+     (True,True)   -> []
+     (True,False)  -> [thesis] 
+     (False,True)  -> [GA.Str (T.intercalate (T.pack ", ") ls)]
+     (False,False) -> GA.Str (T.intercalate (T.pack ", ") ls) : (GA.Newline [] : [thesis])
+      
+  where
+    maybeText (Just gi) = GA.Str gi
+    maybeText Nothing   = GA.Str $ T.pack ""
+
+
 removeThesis :: Entry -> Entry
 removeThesis e = 
-    e{ entryGraduationInfo = map (\g -> g{ gradThesis = Nothing }) $ entryGraduationInfo e }
--- e{ entryGraduationInfo = case entryGraduationInfo e of
---                       Nothing -> Nothing
---                       Just g  -> Just g{gradThesis = Nothing}}
+  e{ entryGraduationInfo = map (\g -> g{ gradThesis = Nothing }) $ entryGraduationInfo e }
 
diff --git a/Extract.hs b/Extract.hs
--- a/Extract.hs
+++ b/Extract.hs
@@ -15,12 +15,10 @@
 where
 import Network.HTTP
 import Text.HTML.TagSoup
-import Control.Monad
-import Control.Exception
 import Data.Char(isSpace)
-import Data.Maybe
 import Data.Text.Lazy(Text)
 import Data.Text.Lazy.Encoding 
+import Control.Exception
 import qualified Data.Text.Lazy as T
 import qualified Data.ByteString.Lazy.Char8 as B
 import Control.Applicative
@@ -29,6 +27,7 @@
 import Entry
 
 
+openURL :: String -> IO Text
 openURL x = return . T.pack =<<  getResponseBody =<< simpleHTTP (getRequest x)
 
 
@@ -58,7 +57,7 @@
     let suffixes = sections (~== "<span style=\"margin-right: 0.5em\">") tags in
     map (graduationInfo tags) suffixes
     where
-        graduationInfo tags suffix = 
+        graduationInfo _ suffix = 
             let getTag i = notEmptyMaybeTagText $ removeClutter $ suffix !! i 
                 degree = getTag 1
                 univ = getTag 3 
@@ -71,6 +70,7 @@
                     | length s >= 6  = GraduationInfo degree univ year Nothing
                     | length s >= 4  = GraduationInfo degree univ Nothing Nothing
                     | length s >= 2  = GraduationInfo degree Nothing Nothing Nothing
+                    | otherwise      = throw $ AssertionFailed "Error - Could not parse downloaded data!"
 
 
 advisors :: [Tag Text] -> [(Text,Text)] 
@@ -99,7 +99,7 @@
     catMaybes' :: [(Maybe a,Maybe b)] -> [(a,b)]
     catMaybes' [] = []
     catMaybes' ((Just a,Just l):xs) = (a,l) : catMaybes' xs
-    catMaybes' ((Just a,Nothing):xs)=  catMaybes' xs
+    catMaybes' ((Just _,Nothing):xs)=  catMaybes' xs
     catMaybes' ((Nothing,_):xs) = catMaybes' xs
 
     maybeAdv adv@(Just t)
diff --git a/Graph.hs b/Graph.hs
--- a/Graph.hs
+++ b/Graph.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Graph
--- Copyright   :  (C) Peter Robinson 2010-2012
+-- Copyright   :  (C) Peter Robinson 2010-2013
 -- License     :  GPL-2
 --
 -- Maintainer  :  Peter Robinson <thaldyron@gmail.com>
@@ -9,19 +9,18 @@
 -- Portability :  portable 
 --
 -----------------------------------------------------------------------------
-module Graph
+module Graph(entryGraph)
 where
 import qualified Data.Map as M
 import Data.Graph.Inductive
 import Data.Text.Lazy(Text)
-import qualified Data.Text.Lazy as T
 import Entry
 
 -- | Maps scientist names to Entries
 type EntryMap = M.Map Text Entry
 
 mkEntryMap :: [Entry] -> EntryMap -> EntryMap
-mkEntryMap es theMap = foldl (\theMap e -> M.insert (entryName e) e theMap) theMap es
+mkEntryMap es theMap = foldl (\m e -> M.insert (entryName e) e m) theMap es
 
 
 entryGraph :: [Entry] -> Gr Entry ()
diff --git a/Main.hs b/Main.hs
--- a/Main.hs
+++ b/Main.hs
@@ -15,155 +15,180 @@
 import Control.Applicative
 import Control.Concurrent
 import Control.Exception
+import Prelude hiding(catch)
+import Data.Char(toUpper)
 import Data.GraphViz
 import Data.GraphViz.Attributes.Complete
+import qualified Data.GraphViz.Attributes.HTML as GA
 import qualified Data.ByteString.Lazy.Char8 as B
 import qualified Data.List as L
+import System.Console.CmdArgs hiding (args)
 import System.Cmd(system)
 import System.IO(hFlush,stdout)
 import System.Exit
 import System.Directory
-import Data.Maybe
 import Data.Text.Lazy(Text)
-import qualified Data.Text.Lazy.IO as TI
 import Data.Text.Lazy.Encoding 
 import qualified Data.Text.Lazy as T
-import System.Console.CmdArgs
-import Prelude hiding(catch)
+import qualified Data.Text.Lazy.IO as TI
+import Safe(readDef)
+import Data.Binary(encodeFile,decodeFile)
+import System.FilePath(pathSeparator)
 
+import CmdParams(mathGenealogy,MathGenealogy(..),outputFileToGraphviz)
 import Extract
 import Entry
 import Graph
 
-data OutputFile = FilePDF | FilePNG | FileSVG
-  deriving(Eq,Data,Typeable)
-
-instance Show OutputFile where
-  show FilePDF = ".pdf"
-  show FilePNG = ".png"
-  show FileSVG = ".svg"
-
-outputFileToGraphviz :: OutputFile -> String
-outputFileToGraphviz FilePDF = " -Tpdf "
-outputFileToGraphviz FilePNG = " -Tpng "
-outputFileToGraphviz FileSVG = " -Tsvg "
-
-
-instance Default OutputFile where
-  def = FilePDF
-
--- command line arguments:
-data MathGenealogy = MathGenealogy 
-  { filePrefix   :: String 
-  , keepDotFile  :: Bool
-  , graphvizArgs :: String
-  , onlyDotFile  :: Bool
---  , verbose      :: Bool
-  , includeTheses:: Bool
-  , startURL     :: String
-  , outputFile   :: OutputFile
-  }
-  deriving(Eq,Data,Typeable,Show)
-
-mathGenealogy = MathGenealogy
-  { startURL     = def &= args &= typ "URL" 
-  , filePrefix   = "output" &= typ "PREFIX" 
-  , keepDotFile  = False 
---  , graphvizArgs = " -Tpdf -Gcharset=utf8 " &= typ "<graphviz parameters>" &= opt " -Tpdf -Gcharset=utf8 "
-  , graphvizArgs = " -Gcharset=utf8 " &= typ "<graphviz parameters>" -- &= opt " -Gcharset=utf8 "
-  , onlyDotFile  = False &= help "Only create the GraphViz '.dot' file"
---  , verbose      = False &= help "Print data to terminal."
-  , includeTheses= False &= help "Include PhD thesis in output"
-  , outputFile   = enum [ FilePDF &= help "create PDF file (default)"
-                        , FilePNG &= help "create PNG file"
-                        , FileSVG &= help "create SVG file"
-                        ]
-  } &= summary "Mathematics Genealogy Visualizer (C) 2010-2012 Peter Robinson thaldyron@gmail.com" 
-    &= details[ "Run the program with a start-URL, for example:"
-              ,"# mathgenealogy http://genealogy.math.ndsu.nodak.edu/id.php?id=18231"
-              ,"This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose.  See the GNU General Public License (version 2) for more details."
-              ]
-
--- | GraphViz style attributes for edges and nodes.
--- See: http://hackage.haskell.org/packages/archive/graphviz/2999.12.0.4/doc/html/Data-GraphViz-Attributes.html
--- TODO: figure out if GraphViz supports CSS files or similar. 
-edgeAtt = const [ Dir Forward
-                , color LightBlue2
-                ] 
-
-nodeAtt (num,e) = 
-  [ textLabel (T.pack (show e)) 
-  , Shape BoxShape
-  , FontSize (if num == 1 then 18 else 14)
-  , styles [rounded,filled,bold]
-  , color LightYellow1
-  , FontName (T.pack "ZapfChancery-MediumItalic") -- "Helvetica")
-  ]
-
-
+main :: IO ()
 main = do
   args <- cmdArgs mathGenealogy
-  let targs = args
   when (null $ startURL args) $ 
     throw (AssertionFailed "Missing start-URL.\nTry 'mathgenealogy --help' for more information.")
 
-  gvExecutable <- (do m <- findExecutable "dot" 
-                      if m == Nothing 
-                        then throw $ AssertionFailed "Error - Couldn't find 'dot' program. Did you install graphviz?"
-                        else return (fromJust m))
+  gvExecutable <- findExecutable "dot"  >>=
+                      maybe (throw $ AssertionFailed "Error - Couldn't find the 'dot' program. Did you install GraphViz?")
+                            return
 
   let traverseEntries :: [Text] -> IO [Entry]
       traverseEntries = traverseEntries' 1 [] []
         where
+          traverseEntries' :: Int -> [Entry] -> [Text] -> [Text] -> IO [Entry]
           traverseEntries' _ acc _        []         = return $ L.nub acc
           traverseEntries' c acc prevUrls (url:urls) = do
             e <- (if includeTheses args then id else removeThesis)
                  `liftM` downloadEntry url
             threadDelay 1000000
---            if verbose args 
---                then  TI.putStrLn $ entryToText e
---                else do 
-            putStr $ show c ++ " "
-            hFlush stdout
+            if verbose args then  
+                TI.putStrLn $ entryToText e
+            else do 
+                putStr $ "..."  ++ show c
+                hFlush stdout
             let newUrls = urlAdvisors e
             traverseEntries' (c+1) (e:acc) (url:prevUrls) 
                              ((newUrls L.\\ prevUrls) ++ urls)
 
-  putStrLn "Downloading entries from http://genealogy.math.ndsu.nodak.edu..."
-  putStrLn "(this might take a few minutes)"
-  theGraph <- entryGraph <$> traverseEntries [T.pack $ startURL args]
-  putStrLn "done. :)"
-  let dotFileName = filePrefix args ++ ".dot"         
-  putStr $ "Writing DOT-file " ++ dotFileName ++ "..."
+  appDir   <- getAppUserDataDirectory "mathgenealogy"
+  doesDirectoryExist appDir >>= \exAppDir -> 
+      unless exAppDir $ createDirectory appDir
+  let entryFilename = tail $ L.dropWhile (/='=') $ startURL args
+  mEntryFile <- findFile [appDir] entryFilename
+  doDownload <- case mEntryFile of
+                    Nothing -> return True
+                    Just _  -> yesno False "Found locally stored data for this entry. Download new data and overwrite it?"
+
+  let dotFileName = prefix args ++ ".dot"         
+  theGraph <- if doDownload then do
+                  putStrLn "Fetching entries from http://genealogy.math.ndsu.nodak.edu..."
+                  putStrLn "(this might take a few minutes)"
+                  putStr "Downloading entry number"
+                  entries  <- traverseEntries [T.pack $ startURL args]
+                  putStrLn ". Done. :)"
+                  encodeFile (appDir ++ [pathSeparator] ++ entryFilename) entries
+                  putStr $ "Building DOT-file '" ++ dotFileName ++ "' from downloaded data..."
+                  return $ entryGraph entries
+              else do
+                  (entries::[Entry]) <- decodeFile (appDir ++ [pathSeparator] ++ entryFilename)
+                  putStr $ "Building DOT-file '" ++ dotFileName ++ "' from locally stored data..."
+                  return $ entryGraph entries
+
+  
+  let edgeAtt = const [ Dir Forward
+                      , parseColor "Error - Could not parse edge color!" $ edgeColor args
+                      ] 
+  let bgcolorX11 = parseColorX11 "Error - Could not parse node background color!" $ 
+                         nodeBackgroundColor args
+  let nodeAtt (num,e) = 
+        if not $ oldTextLabels args then
+            [ styles [rounded,filled]
+            , Shape PlainText
+            , parseColor "Error - Could not parse node backgroundcolor!" $ 
+                           nodeBackgroundColor args
+            , toLabel $ 
+                let fshead = if num == 1 then fontSizeFirstHeading args 
+                                         else fontSizeHeading args 
+                    fs = if num == 1 then fontSizeFirst args 
+                                     else fontSize args in
+                entryToHtml [ GA.BGColor $ X11Color bgcolorX11
+                            , GA.Border 0
+                            , GA.CellBorder 0
+                            ]
+                            [ GA.Face (T.pack $ fontHeading args)
+                            , GA.PointSize fshead
+                            ]
+                            [ GA.Face (T.pack $ font args)
+                            , GA.PointSize fs
+                            ] e 
+            ]
+        else
+            [ styles [rounded,filled]
+            , textLabel $ entryToText e
+            , Shape BoxShape
+            , FontSize (if num == 1 then fontSizeFirst args else fontSize args)
+            , parseColor "Error - Could not parse node background color!" $ 
+                         nodeBackgroundColor args
+            , FontName (T.pack $ font args) 
+            ]
   let output = printDotGraph $ 
                  graphToDot nonClusteredParams{ fmtNode = nodeAtt 
                                               , fmtEdge = edgeAtt
                                               } theGraph
   B.writeFile dotFileName (encodeUtf8 output)
     `catch` (\(e::IOException) -> do { print e ; throw e })
-  putStrLn "done. :)"
+  putStrLn "success! :)"
 
-  unless (onlyDotFile args) $ do
-    putStr "Generating graphics file..."
-    let command = gvExecutable ++ " " ++ outputFileToGraphviz (outputFile args) ++ graphvizArgs args
-                               ++ " " ++ dotFileName ++ " > " 
-                               ++ filePrefix args ++ show (outputFile args)
-    print command
-    result <- system command
-    when (isExitFailure result) $ do
-      print $ "Error running the graphviz (dot) program. I tried: " ++ command
-      throw $ AssertionFailed "Exiting."
-    putStrLn "done. :)"
+  putStr $ "Generating graphics file " ++ prefix args ++ show (outputFile args) ++ "..."
+  let command = gvExecutable ++ " " ++ outputFileToGraphviz (outputFile args) ++ graphvizArgs args
+                             ++ " " ++ dotFileName ++ " > " 
+                             ++ prefix args ++ show (outputFile args)
+  when (verbose args) $
+      print command
+  result <- system command
+  when (isExitFailure result) $ do
+    print $ "Error running the graphviz (dot) program. I tried: " ++ command
+    throw $ AssertionFailed "Exiting."
+  putStrLn "done. :)"
   unless (keepDotFile args) $ removeFile dotFileName
   where
     isExitFailure (ExitFailure _) = True
     isExitFailure _               = False
+  
+    parseColor :: String -> String -> Attribute
+    parseColor errMsg colStr = 
+        let colStr1 = headToUpper colStr in
+        color (readDef (throw $ AssertionFailed errMsg) colStr1 :: X11Color)
 
+    parseColorX11 :: String -> String -> X11Color
+    parseColorX11 errMsg colStr = 
+        let colStr1 = headToUpper colStr in
+        readDef (throw $ AssertionFailed errMsg) colStr1 :: X11Color
+
+-- | Conver the first character of the string to upper-case.
+headToUpper :: String -> String
+headToUpper str = toUpper  (head str) : tail str
+
     
+-- | Download and parse an entry.
 downloadEntry :: Text -> IO Entry
 downloadEntry t = do 
     res <- parseEntry <$> getTags t
     case res of
-        Nothing -> throw $ AssertionFailed "Error parsing fetched data. Did you provide a valid URL to an existing math-genealogy entry?"
+        Nothing -> throw $ AssertionFailed "Error - Could not parse fetched data. Did you provide a valid URL to an existing math-genealogy entry?"
         Just r -> return r
 
+
+yesno :: Bool    -- Set to 'True' iff "y" is the default value.
+      -> String  -- Prompt string.
+      -> IO Bool -- 'True' if the user answered affirmatively.
+yesno defval prompt = do
+          putStr $ prompt ++ if defval then " (Y/n) " else " (y/N) "
+          hFlush stdout
+          str <- getLine
+          if null str then
+              return defval
+          else case headToUpper str of
+                "Y" -> return True
+                "N" -> return False
+                _   -> do
+                  putStrLn "Invalid input."
+                  yesno defval prompt
diff --git a/mathgenealogy.cabal b/mathgenealogy.cabal
--- a/mathgenealogy.cabal
+++ b/mathgenealogy.cabal
@@ -1,11 +1,12 @@
 Name:                mathgenealogy
 
-Version:             1.2.0
+Version:             1.3.0
 
 Synopsis:            Discover your (academic) ancestors!
 
-Description:         A simple command line program for extracting data from the
+Description:         A command line program for extracting data from the
   Mathematics Genealogy Project (<http://genealogy.math.ndsu.nodak.edu/index.php>).
+  Note that this database also contains many entries of computer scientists.
   .
   Lookup your entry at <http://genealogy.math.ndsu.nodak.edu/index.php> and
   then use that URL as a command line argument.  
@@ -15,15 +16,34 @@
   > mathgenealogy http://genealogy.math.ndsu.nodak.edu/id.php?id=18231 
   .
   which produces the directed acyclic graph
-  <http://dl.dropbox.com/u/22490968/genealogy_of_gauss.png>. See 
+  <http://dl.dropbox.com/u/22490968/genealogy_of_gauss.svg>. See 
   .
   > mathgenealogy --help
   .
-  for more options. Requires GraphViz (in particular the /dot/ program) to run.
+  for the complete list of options. Requires the /dot/ program, which is
+  part of the GraphViz package (/version 2.28.0 or later!/) to run.
   .
+  Feedback and bug reports are appreciated!
+  .
+  /Changes in 1.3.0:/
+  .
+  * Switched to HTML-like labels in GraphViz. This is required for the advanced
+    font formatting options. ATTENTION: this needs a recent
+    installation of GraphViz (Linux: 2.28.0; MacOS: 2.29) and will yield
+    best results for SVG output files. If you have an older version of GraphViz
+    or run into issues, try the '--oldtextlabels' option.
+  .
+  * Downloaded entries are stored locally. This avoids re-downloading the same
+    data if you want to generate multiple graphs of the same entry with
+    different formatting options.
+  .
+  * Added more options for fine-tuning the fonts and colors. (requested by users)
+  .
+  * Default output is now SVG, as this is the format best supported by GraphViz.
+  .
   /Changes in 1.2.0:/
   .
-  * Correct handling of entries with multiple PhDs (reported by Dima Pasechnik)
+  * Fixed handling of entries that have multiple degrees. (reported by Dima Pasechnik)
   . 
   /Changes in 1.1.1:/
   .
@@ -39,7 +59,7 @@
   .
   /Changes in 0.0.2:/
   .
-  * Fixed bug regarding trailing commas (reported by Alexander Koessler) 
+  * Fixed handling of trailing commas (reported by Alexander Koessler) 
 
 -- Homepage:            http://darcs.monoid.at/mathgenealogy
 
@@ -69,7 +89,7 @@
 Executable mathgenealogy
       build-depends: base >= 4 && < 5
                    , text >= 0.11 && <0.13
-                   , directory >= 1.1 && <1.3
+                   , directory >= 1.2 && <1.3
 --                   , haskell98 >= 1.1 && <2.1
                    , process >= 1.1 && < 1.2
                    , bytestring >= 0.9 && <1.0
@@ -80,11 +100,15 @@
                    , tagsoup >= 0.12.6 && <0.13
                    , HTTP >= 4000.1.2 && <5000
                    , safe >= 0.3.3 && <0.5
+                   , binary >= 0.6.4 && <0.7
+                   , filepath >= 1.3.0 && <1.4
       Main-Is: Main.hs
       Other-modules: Graph
                    , Extract 
                    , Entry
+                   , CmdParams
       extensions: ScopedTypeVariables
                 , DeriveDataTypeable
---      ghc-options:     -O
+                , DoAndIfThenElse
+      ghc-options:     -Wall
 --      ld-options: -static -pthread
