Index: trunk/bin/module_maker/module.cli.php
===================================================================
--- trunk/bin/module_maker/module.cli.php	(revision 412)
+++ trunk/bin/module_maker/module.cli.php	(revision 413)
@@ -136,16 +136,18 @@
 }
 
-// Ensure essential directories exist.
-if (!is_dir("$admin_dir")) {
-    die(basename($_SERVER['argv'][0]) . " Error: admin_dir '$admin_dir' directory not found.\n");
-}
-if (!is_dir("$admin_tpl_dir")) {
-    die(basename($_SERVER['argv'][0]) . " Error: admin_tpl_dir '$admin_tpl_dir' directory not found.\n");
-}
-if (!is_dir("$public_dir")) {
-    die(basename($_SERVER['argv'][0]) . " Error: public_dir '$public_dir' directory not found.\n");
-}
-if (!is_dir("$public_tpl_dir")) {
-    die(basename($_SERVER['argv'][0]) . " Error: public_tpl_dir '$public_tpl_dir' directory not found.\n");
+if (!isset($_SERVER['argv'][4]) || 'var' != $_SERVER['argv'][4]) {
+    // Ensure essential directories exist, except for 'var' op.
+    if (!is_dir("$admin_dir")) {
+        die(basename($_SERVER['argv'][0]) . " Error: admin_dir '$admin_dir' directory not found.\n");
+    }
+    if (!is_dir("$admin_tpl_dir")) {
+        die(basename($_SERVER['argv'][0]) . " Error: admin_tpl_dir '$admin_tpl_dir' directory not found.\n");
+    }
+    if (!is_dir("$public_dir")) {
+        die(basename($_SERVER['argv'][0]) . " Error: public_dir '$public_dir' directory not found.\n");
+    }
+    if (!is_dir("$public_tpl_dir")) {
+        die(basename($_SERVER['argv'][0]) . " Error: public_tpl_dir '$public_tpl_dir' directory not found.\n");
+    }    
 }
 
Index: trunk/docs/examples/contact_form/contact.php
===================================================================
--- trunk/docs/examples/contact_form/contact.php	(revision 412)
+++ trunk/docs/examples/contact_form/contact.php	(revision 413)
@@ -51,14 +51,5 @@
 if (!empty($_POST)) {
     // Validate submitted data.
-    $fv->notEmpty('name', sprintf(_("%s cannot be blank."), _("Name")));
-    $fv->stringLength('name', 0, 255, sprintf(_("%s must be %d-to-%d characters in length."), _("Name"), 0, 255));
-    
-    $fv->notEmpty('email', sprintf(_("%s cannot be blank."), _("Email")));
-    $fv->stringLength('email', 0, 255, sprintf(_("%s must be %d-to-%d characters in length."), _("Email"), 0, 255));
-    $fv->validateEmail('email');
-    
-    $fv->notEmpty('message', sprintf(_("%s cannot be blank."), _("Message")));
-    $fv->stringLength('message', 0, 32000, sprintf(_("%s must be %d-to-%d characters in length."), _("Message"), 0, 32000));
-        
+    validateInput();
 	if ($fv->anyErrors()) {
         // Re-populate form values with the user data so they can make corrections.
@@ -68,12 +59,12 @@
         $email = new Email(array(
             'to' => $email_to,
-            'from' => sprintf('%s <%s>', $frm['name'], $frm['email']),
+            'from' => sprintf('%s <%s>', getFormData('name'), getFormData('email')),
             'subject' => 'Contact form email',
         ));
         $email->setTemplate('contact.eml');
         $email->replace(array(
-            'name' => $frm['name'],
-            'email' => $frm['email'],
-            'message' => $frm['question'],
+            'name' => getFormData('name'),
+            'email' => getFormData('email'),
+            'message' => getFormData('message'),
         ));
         // Send email!
@@ -113,3 +104,18 @@
 }
 
+function validateInput()
+{
+    global $fv;
+
+    $fv->notEmpty('name', sprintf(_("%s cannot be blank."), _("Name")));
+    $fv->stringLength('name', 0, 255, sprintf(_("%s must be %d-to-%d characters in length."), _("Name"), 0, 255));
+    
+    $fv->notEmpty('email', sprintf(_("%s cannot be blank."), _("Email")));
+    $fv->stringLength('email', 0, 255, sprintf(_("%s must be %d-to-%d characters in length."), _("Email"), 0, 255));
+    $fv->validateEmail('email');
+    
+    $fv->notEmpty('message', sprintf(_("%s cannot be blank."), _("Message")));
+    $fv->stringLength('message', 0, 32000, sprintf(_("%s must be %d-to-%d characters in length."), _("Message"), 0, 32000));
+}
+
 ?>
Index: trunk/docs/examples/contact_form/footer.ihtml
===================================================================
--- trunk/docs/examples/contact_form/footer.ihtml	(revision 413)
+++ trunk/docs/examples/contact_form/footer.ihtml	(revision 413)
@@ -0,0 +1,16 @@
+<div id="footer">
+    <div class="nav">
+        <a href="/one" class="first">One</a> &middot;
+        <a href="/two">Two</a> &middot;
+        <a href="/three">Three</a>
+    </div>
+    <div id="addr">
+        123 Main Street, Chico, CA 95927 â <span class="sc-email">hello at example dot com</span>
+    </div>
+</div>
+</body>
+</html>
+<?php
+// The end is nigh!
+$app->stop();
+?>
Index: trunk/docs/examples/contact_form/header.ihtml
===================================================================
--- trunk/docs/examples/contact_form/header.ihtml	(revision 413)
+++ trunk/docs/examples/contact_form/header.ihtml	(revision 413)
@@ -0,0 +1,21 @@
+<<?php echo '?xml version="1.0" encoding="' . $app->getParam('character_set') . '"?'; ?>>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+    <meta http-equiv="content-type" content="text/html; charset=<?php echo $app->getParam('character_set'); ?>" />
+    <title><?php printf('%s %s %s', $app->getParam('site_name'), $nav->getParam('path_delimiter'), strip_tags($nav->getPath('head_title'))) ?></title> 
+</head>
+<body<?php echo $nav->get('body_id') ? ' id="' . $nav->get('body_id') . '"' : ''; ?>>
+    <div id="header">
+        <ul class="nav">
+            <li><a href="/one" class="first">One</a></li>
+            <li><a href="/two">Two</a></li>
+            <li><a href="/three">Three</a></li>
+        </ul>
+    </div>
+    <?php if ($nav->getParam('body_title')) { ?>
+        <h1><?php echo $nav->get('body_title'); ?></h1>
+    <?php } ?>
+    <?php $app->printRaisedMessages(); ?>
+        
Index: trunk/lib/App.inc.php
===================================================================
--- trunk/lib/App.inc.php	(revision 412)
+++ trunk/lib/App.inc.php	(revision 413)
@@ -492,9 +492,13 @@
      * Prints the HTML for displaying raised messages.
      *
+     * @param   string  $above    Additional message to print above error messages (e.g. "Oops!").
+     * @param   string  $below    Additional message to print below error messages (e.g. "Please fix and resubmit").
+     * @param   string  $print_gotohash_js  Print a line of javascript that scrolls the browser window down to view any error messages.
+     * @param   string  $hash     The #hashtag to scroll to.
      * @access  public
      * @author  Quinn Comendant <quinn@strangecode.com>
      * @since   15 Jul 2005 01:39:14
      */
-    function printRaisedMessages()
+    function printRaisedMessages($above='', $below='', $print_gotohash_js=false, $hash='sc-msg')
     {
         if (!$this->running) {
@@ -506,4 +510,7 @@
         if (!empty($messages)) {
             ?><div id="sc-msg" class="sc-msg"><?php
+            if ('' != $above) {
+                ?><div class="sc-above"><?php echo oTxt($above); ?></div><?php
+            }
             foreach ($messages as $m) {
                 if (error_reporting() > 0 && $this->getParam('display_errors') && isset($m['file']) && isset($m['line'])) {
@@ -530,5 +537,17 @@
                 }
             }
+            if ('' != $below) {
+                ?><div class="sc-below"><?php echo oTxt($below); ?></div><?php
+            }
             ?></div><?php
+            if ($print_gotohash_js) {
+                ?>
+                <script type="text/javascript">
+                /* <![CDATA[ */
+                window.location.hash = '#<?php echo urlencode($hash); ?>';
+                /* ]]> */
+                </script>
+                <?php
+            }
         }
         $this->clearRaisedMessages();
Index: trunk/lib/FormValidator.inc.php
===================================================================
--- trunk/lib/FormValidator.inc.php	(revision 412)
+++ trunk/lib/FormValidator.inc.php	(revision 413)
@@ -176,9 +176,11 @@
      * @param   string  $above    Additional message to print above error messages (e.g. "Oops!").
      * @param   string  $below    Additional message to print below error messages (e.g. "Please fix and resubmit").
+     * @param   string  $print_gotohash_js  Print a line of javascript that scrolls the browser window down to view any error messages.
+     * @param   string  $hash     The #hashtag to scroll to.
      * @access  public
      * @author  Quinn Comendant <quinn@strangecode.com>
      * @since   15 Jul 2005 01:39:14
      */
-    function printErrorMessages($above='', $below='')
+    function printErrorMessages($above='', $below='', $print_gotohash_js=false, $hash='sc-msg-formvalidator')
     {
         $app =& App::getInstance();
@@ -217,4 +219,13 @@
             }
             ?></div><?php
+            if ($print_gotohash_js) {
+                ?>
+                <script type="text/javascript">
+                /* <![CDATA[ */
+                window.location.hash = '#<?php echo urlencode($hash); ?>';
+                /* ]]> */
+                </script>
+                <?php
+            }
         }
     }
