Mostly small changes.

- Fixed broken HTML in edit form that swallowed <BR> tags
- Removed "another one" link in roulette, replaced with "use Reload" message
- show() now has edit=1 by default; changed all calls
- Display last-changed date, author, email when present and edit=1
- Added back pointers at bottom
- Added a copy of the bootstrap script at the end of the file
diff --git a/Tools/faqwiz/faqmain.py b/Tools/faqwiz/faqmain.py
index c3d9c7d..a202e30 100644
--- a/Tools/faqwiz/faqmain.py
+++ b/Tools/faqwiz/faqmain.py
@@ -1,7 +1,9 @@
-#! /depot/sundry/plat/bin/python1.4
-
 """Interactive FAQ project.
 
+Note that this is not an executable script; it's an importable module.
+The actual CGI script can be kept minimal; it's appended at the end of
+this file as a string constant.
+
 XXX TO DO
 
 - generic error handler
@@ -22,6 +24,7 @@
 - Browse should display menu of 7 sections & let you pick
   (or frontpage should have the option to browse a section or all)
 - support adding annotations, too
+- make it more generic (so you can create your own FAQ)
 
 """
 
@@ -52,6 +55,11 @@
 	if key not in self.KEYS:
 	    raise AttributeError
 	try:
+	    form = self.form
+	    try:
+		item = form[key]
+	    except TypeError, msg:
+		raise KeyError, msg, sys.exc_traceback
 	    value = self.form[key].value
 	    setattr(self, key, value)
 	    return value
@@ -121,7 +129,7 @@
 	if not headers:
 	    print "Invalid file name", name
 	    return
-	self.show(name, headers['title'], text, 1)
+	self.show(name, headers['title'], text)
 
     def do_all(self):
 	self.prologue("The Whole Python FAQ")
@@ -139,7 +147,7 @@
 		    section = nsec
 		    print "<H1>Section %s</H1>" % section
 		    print "<HR>"
-		self.show(name, title, text, 1)
+		self.show(name, title, text)
 	if not section:
 	    print "No FAQ entries?!?!"
 
@@ -157,8 +165,8 @@
 	    name = whrandom.choice(names)
 	    headers, text = self.read(name)
 	    if headers:
-		self.show(name, headers['title'], text, 1)
-		print '<P><A HREF="faq.py?req=roulette">Show another one</A>'
+		self.show(name, headers['title'], text)
+		print "<P>Use `Reload' to show another one."
 		break
 	    else:
 		names.remove(name)
@@ -187,7 +195,7 @@
 	for (mtime, name) in list:
 	    headers, text = self.read(name)
 	    if headers:
-		self.show(name, headers['title'], text, 1)
+		self.show(name, headers['title'], text)
 		n = n+1
 	if not n:
 	    print "No FAQ entries?!?!"
@@ -209,7 +217,7 @@
 	    if headers:
 		title = headers['title']
 		if p.search(title) >= 0 or p.search(text) >= 0:
-		    self.show(name, title, text, 1)
+		    self.show(name, title, text)
 		    n = n+1
 	if not n:
 	    print "No hits."
@@ -274,7 +282,7 @@
 	</FORM>
 	<HR>
 	""" % (name, version)
-	self.show(name, title, text)
+	self.show(name, title, text, edit=0)
 
     def do_review(self):
 	if self.commit:
@@ -289,7 +297,7 @@
 	    return
 	self.prologue("Python FAQ Review Form")
 	print "<HR>"
-	self.show(name, title, text)
+	self.show(name, title, text, edit=0)
 	print "<FORM METHOD=POST ACTION=faq.py>"
 	if self.log and self.author and '@' in self.email:
 	    print """
@@ -447,7 +455,7 @@
 	if not sts:
 	    self.prologue("Python FAQ Entry Edited")
 	    print "<HR>"
-	    self.show(name, title, text, 1)
+	    self.show(name, title, text)
 	    if output:
 		print "<PRE>%s</PRE>" % cgi.escape(output)
 	else:
@@ -460,15 +468,17 @@
 
     def showedit(self, name, title, text):
 	print """
-	Title: <INPUT TYPE=text SIZE=70 NAME=title VALUE="%s"<BR>
+	Title: <INPUT TYPE=text SIZE=70 NAME=title VALUE="%s"><BR>
 	<TEXTAREA COLS=80 ROWS=20 NAME=text>""" % title
 	print cgi.escape(string.strip(text))
 	print """</TEXTAREA>
 	<BR>
 	Please provide the following information for logging purposes:
 	<BR>
-	<CODE>Name : </CODE><INPUT TYPE=text SIZE=70 NAME=author VALUE="%s"<BR>
-	<CODE>Email: </CODE><INPUT TYPE=text SIZE=70 NAME=email VALUE="%s"<BR>
+	<CODE>Name : </CODE><INPUT TYPE=text SIZE=40 NAME=author VALUE="%s">
+	<BR>
+	<CODE>Email: </CODE><INPUT TYPE=text SIZE=40 NAME=email VALUE="%s">
+	<BR>
 	Log message (reason for the change):<BR>
 	<TEXTAREA COLS=80 ROWS=5 NAME=log>\n%s\n</TEXTAREA>
 	""" % (self.author, self.email, self.log)
@@ -482,7 +492,10 @@
 					 headers[key] or '')
 	print "</UL>"
 
+    headers = None
+
     def read(self, name):
+	self.headers = None
 	import fnmatch, rfc822
 	if not fnmatch.fnmatch(name, NAMEPAT):
 	    return None, None
@@ -496,14 +509,15 @@
 		return None, None
 	    headers = {'title': "%s.%s. " % (self.section, self.number)}
 	    text = ""
-	    return headers, text
-	f = open(name)
-	headers = rfc822.Message(f)
-	text = f.read()
-	f.close()
+	else:
+	    f = open(name)
+	    headers = rfc822.Message(f)
+	    text = f.read()
+	    f.close()
+	self.headers = headers
 	return headers, text
 
-    def show(self, name, title, text, edit=0):
+    def show(self, name, title, text, edit=1):
 	# XXX Should put <A> tags around recognizable URLs
 	# XXX Should also turn "see section N" into hyperlinks
 	print "<H2>%s</H2>" % cgi.escape(title)
@@ -534,6 +548,16 @@
 	    <A HREF="faq.py?req=edit&name=%s">Edit this entry</A> /
 	    <A HREF="faq.py?req=info&name=%s" TARGET=_blank>Log info</A>
 	    """ % (name, name)
+	    if self.headers:
+		try:
+		    date = self.headers['last-changed-date']
+		    author = self.headers['last-changed-author']
+		    email = self.headers['last-changed-email']
+		except KeyError:
+		    pass
+		else:
+		    s = '(last changed on %s by <A HREF="%s">%s</A>)'
+		    print s % (date, email, author)
 	    print '<P>'
 	print "<HR>"
 
@@ -568,6 +592,8 @@
 	print '''
 	<P>
 	<HR>
+	<A HREF="http://www.python.org">Python home</A> /
+	<A HREF="faq.py">FAQ home</A> /
 	<A HREF="mailto:guido@python.org">GvR</A>
 	</BODY>
 	</HTML>
@@ -587,3 +613,13 @@
     print "<HR>Sorry, an error occurred"
     cgi.print_exception()
 print "<P>(running time = %s seconds)" % str(round(dt, 3))
+
+# The following bootstrap script must be placed in cgi-bin/faq.py:
+BOOTSTRAP = """
+#! /usr/local/bin/python
+FAQDIR = "/usr/people/guido/python/FAQ"
+import os, sys
+os.chdir(FAQDIR)
+sys.path.insert(0, os.curdir)
+import faqmain
+"""