Wednesday, March 09, 2011 at 12:00 AM.

on browser (adroutline, pagename="Preferences", flAddSubmitButton=true, nextLinkText="Next", prevLinkText="Previous", submitButtonText="Submit", adrToolsPrefs=nil, flShowNavigation=true) {
		<<3/8/11; 10:59:23 AM by DW
			<<New optional param, flShowNavigation, if false we don't show the navigation part of the display. This is for the prefs of a Tool that all fits on one page. There's no need for navigation, and it's a major distraction away from the functionality of the product. 
		<<8/8/08; 11:41:52 AM by DW
			<<Added optional param adrToolsPrefs, if not nil, points to a table of addresses of prefs outlines that are included with this outline.
		<<8/3/08; 10:49:44 AM by DW
			<<Added support for a new "title" argument, if present use that to determine the navigation path.  Now links into the prefs don't break if they get reorganized. Nice.
		<<12/3/07; 2:31:09 PM by DW
			<<Add a space before and after the slash in Next/Prev links.
		<<10/12/02; 1:44:56 AM by JES
			<<Three new parameters to facilitate localization: nextLinkText, prevLinkText and submitButtonText. These parameters specify the text for the next and previous links, and the text for the submit button.
		<<9/24/02; 12:51:38 AM by JES
			<<Decode ampersand entities in category and topic names. Needed for localization.
		<<6/26/02; 11:51:52 PM by JES
			<<Before adding the Submit button, check to see if pta^.flAddSubmitButton is defined. If defined and false, don't add the button. This allows macros in a prefs outline to suppress the Submit button, and add their own button(s) if desired.
		<<2/5/02; 11:26:46 AM by PBS
			<<Conditionalized to work in Frontier.
		<<1/9/02; 5:03:56 PM by JES
			<<Call radio.prefs.compileIfDirty, instead of compiling the xml and caching home page text, next-prev links, and page titles here.
		<<12/10/01; 10:21:06 PM by JES
			<<Include the full path in the link to sub-pages, since Opera doesn't know how to link to the same page, adding just the searchArgs. Fixes a bug where none of the Prefs or Help sub-pages could be reached in Opera.
		<<11/24/01; 5:18:15 PM by JES
			<<Set pta^.headTitle, which is used for the <%title%> in the header of the page (when rendered in the context of an #flUseHomeTitle true directive).
			<<See radio.webserver.setTemplate for the code that handles the #flUseHomeTitle directive.
			<<New optional parameter, flAddSubmitButton. If true, then the Submit button will be added at the bottom of the page. If false, there's no submit button. Default is true. This is needed in order to remove the Submit button from the bottom of the help pages.
		<<11/23/01; 9:17:39 PM by DW
			<<Put the address of the prefs outline into pta^.radioResponder.adrPrefsOutline.
			<<It's picked up in radio.prefs.seeAlso, to determine which element of the cache it should use.
		<<11/23/01; 9:06:49 PM by DW
			<<Add a second parameter which is the name of the home page of the sub-site.
		<<11/18/01; 5:48:45 PM by DW
			<<Not content with my most recent one, now I'm swingin for the fences.
			<<This browser runs off a single outline. It's not XML. It's just an outline.
			<<Where it requires user input -- a checkbox or a number-entry box, it calls macros.
			<<We do a directory-like browser for prefs, breaking it down to sections.
			<<The key thing about this approach is that the writer gets to use a writing tool, not an XML editor, and not a bunch of scattered strings. This makes it possible for docs and settings to be mixed in a single presentation. This is how docs were supposed to work.
	local (pta = html.getpagetableaddress ());
	<< = pta^; scratchpad.adroutline = adroutline //debugging
	if system.environment.isRadio { //PBS 02/05/02: conditionalized for Frontier
		pta^.radioResponder.adrPrefsOutline = adroutline}
	else {
		pta^.adrPrefsOutline = adroutline};
	pta^.title = " ";
	local (titleBarColor = "#" + gainsboro, titleBarTextColor = "#" + black);
	titleBarColor = "#859EC9"; titleBarTextColor = "#" + white; //matches the coffee-cup background color
	titleBarcolor = "#C5CEDE";
	titleBarcolor = "#" + whitesmoke;
	<<scratchpad.params = pta^
	<<1/9/02; 7:08:11 PM by JES: call radio.prefs.compileIfDirty to set home page cache, build next/prev's and get page titles
		<<This prevents a crash on Help pages which link to related Prefs pages, when the Prefs have not been viewed since Radio was launched.
		<<bundle //original code
			<<local (adrcache)
			<<bundle //find the cache for this outline
				<<local (adr =
				<<if not defined (adr^)
					<<new (tabletype, adr)
				<<adr = @adr^.[string (adroutline)]
				<<if not defined (adr^)
					<<new (tabletype, adr)
				<<adrcache = adr
			<<local (flcompile, adrxstruct = @adrcache^.xstruct)
			<<bundle //compile the outline if it changed
				<<flcompile = true
				<<if defined (adrxstruct^)
					<<if timemodified (adroutline) <= timemodified (adrxstruct)
						<<flcompile = false
				<<if flcompile
					<<xml.compile (op.outlinetoxml (adroutline), adrxstruct)
			<<local (adropml = xml.getAddress (adrxstruct, "opml"))
			<<local (adrbody = xml.getAddress (adropml, "body"))
			<<local (adrhomepagehtml = @adrcache^.homePageHtml, adrnextprevlist = @adrcache^.nextPrevList, adrpagetitles = @adrcache^.pagetitles)
			<<if flcompile //cache the text for the home page, create next-prevs list and cache it, and the page-titles table
				<<adrnextprevlist^ = {}
				<<new (tabletype, adrpagetitles)
				<<local (htmltext = "", indentlevel = 0)
				<<on add (s)
					<<htmltext = htmltext + string.filledstring ("\t", indentlevel) + s + "\r\n"
				<<local (adrcat, catnum = 1)
				<<for adrcat in adrbody
					<<if not (nameof (adrcat^) beginswith "/")
						<<local (catname = xml.getattributevalue (adrcat, "text"), adrtopic, topicnum = 1)
						<<add ("<h4>" + catname + "</h4>")
						<<add ("<ul>"); indentlevel++
						<<for adrtopic in adrcat
							<<if not (nameof (adrtopic^) beginswith "/")
								<<local (dottedid = catnum + "." + topicnum)
								<<adrnextprevlist^ = adrnextprevlist^ + {dottedid}
								<<local (url = pta^.URI + "?page=" + dottedid)
								<<local (pagetitle = xml.getattributevalue (adrtopic, "text"))
								<<adrpagetitles^.[pagetitle] = dottedid
								<<add ("<li><a href=\"" + url + "\">" + pagetitle + "</a></li>")
						<<add ("</ul>"); indentlevel--
				<<adrhomepagehtml^ = htmltext
	local (adrcache = radio.prefs.compileIfDirty (adroutline, adrToolsPrefs)); //8/8/08 by DW -- added adrToolsPrefs param
	local (adrxstruct = @adrcache^.xstruct);
	local (adropml = xml.getAddress (adrxstruct, "opml"));
	local (adrbody = xml.getAddress (adropml, "body"));
	local (adrhomepagehtml = @adrcache^.homePageHtml, adrnextprevlist = @adrcache^.nextPrevList);
	local (navigationpath = "");
	if system.environment.isRadio { //PBS 02/05/02: conditionalized for Frontier
		if defined (pta^ {
			navigationpath = pta^}}
	else {
		if defined (pta^ {
			navigationpath = pta^}};
	bundle { //8/3/08 by DW -- look for "title" arg
		local (title = "");
		if system.environment.isRadio {
			if defined (pta^.radioresponder.getargs.title) {
				title = string.urldecode (pta^.radioresponder.getargs.title)}}
		else {
			if defined (pta^.searchArgTable.title) {
				title = string.urldecode (pta^.searchArgTable.title)}};
		if title != "" { //got one!
			if defined (adrcache^.pagetitles.[title]) {
				navigationpath = adrcache^.pagetitles.[title]}}};
	local (adrframe, fltoplevel);
	bundle { //set adrframe, fltoplevel
		local (ctfields = string.countfields (navigationpath, "."));
		if ctfields >= 2 {
			local (i, ix, nomad = adrbody);
			for i = 1 to ctfields {
				ix = number (string.nthfield (navigationpath, ".", i));
				if defined (nomad^.["/atts"]) { //skip over /atts
				nomad = @nomad^ [ix]};
			adrframe = nomad;
			fltoplevel = false}
		else {
			adrframe = adrbody;
			fltoplevel = true}};
	local (htmltext = "", indentlevel = 0);
	on add (s) {
		htmltext = htmltext + string.filledstring ("\t", indentlevel) + s + "\r\n"};
	bundle { //display the frame
		if fltoplevel { //adrframe points to the first category
			add (adrhomepagehtml^);
			pta^.headTitle = pagename}
			<<bundle //discarded method -- displays the topics in an array
				<<Too bad the topic names are too long for this to look reasonable.
				<<local (adrcat, catnames = {}, tableofcontents)
				<<new (tabletype, @tableofcontents)
				<<for adrcat in adrframe //loop over the top-level
					<<if not (nameof (adrcat^) beginswith "/")
						<<local (catname = xml.getattributevalue (adrcat, "text"))
						<<catnames = catnames + {catname}
						<<local (adrtopic, topics)
						<<new (tabletype, @topics)
						<<for adrtopic in adrcat
							<<if not (nameof (adrtopic^) beginswith "/")
								<<topics.[string.padwithzeros (sizeof (topics), 3)] = xml.getattributevalue (adrtopic, "text")
						<<tableofcontents.[catname] = topics
				<<scratchpad.tableofcontents = tableofcontents
				<<add ("<table border=\"0\" cellspacing=\"0\" cellpadding=\"4\">"); indentlevel++
				<<bundle //add top row of the table, the category names
					<<local (catname, width)
					<<width = 33
					<<add ("<tr>"); indentlevel++
					<<for catname in catnames
						<<add ("<td width=\"" + width + "%\"><b>" + catname + "</b></td>")
					<<add ("</tr>"); indentlevel--
				<<bundle //add rows of topics
					<<local (rownum = 1, catname)
					<<loop //do a row
						<<local (rowtext = "<tr>", flallblank = true)
						<<for catname in catnames
							<<msg (sizeof (tableofcontents.[catname]) + " " + rownum); clock.waitseconds (1)
							<<if sizeof (tableofcontents.[catname]) >= rownum
								<<s = tableofcontents.[catname] [rownum]
								<<flallblank = false
								<<s = " "
							<<rowtext = rowtext + "<td>" + s + "</td>"
						<<rowtext = rowtext + "</tr>"
						<<if flallblank
						<<add (rowtext)
				<<add ("</table>"); indentlevel--
		else {
			local (category);
			bundle { //set category
				local (categoryname = xml.getattributevalue (parentof (adrframe^), "text"));
				categoryname = string.replaceAll (categoryname, "&", "&");
				category = categoryname};
			local (nextprev);
			bundle { //set nextprev
				local (ixmyself, i);
				for i = 1 to sizeof (adrnextprevlist^) {
					if adrnextprevlist^ [i] == navigationpath {
						ixmyself = i;
				local (next, prev);
				if ixmyself == sizeof (adrnextprevlist^) {
					next = nextLinkText}
				else {
					next = "<a href=\"?page=" + adrnextprevlist^ [ixmyself + 1] + "\">" + nextLinkText + "</a>"};
				if ixmyself == 1 {
					prev = prevLinkText}
				else {
					prev = "<a href=\"?page=" + adrnextprevlist^ [ixmyself - 1] + "\">" + prevLinkText + "</a>"};
				nextprev = prev + " / " + next};
			on blankLine () {
				return ("<tr height=\"15\"><td colspan=\"2\"> </td></tr>")};
			on titleBar (s) {
				return ("<tr bgcolor=\"" + titleBarColor + "\"><td colspan=\"2\"><b><font color=\"" + titlebartextcolor + "\">" + s + "</font></b></td></tr>")};
			if flShowNavigation { //3/8/11 by DW
				add ("<table border=\"0\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\"><tr><td><a href=\"?page=1\">" + pagename + "</a> > " + category + "</td><td align=\"right\">" + nextprev + "</td></tr></table>")};
			add ("<h3>" + string.replaceAll (adrframe^.["/atts"].text, "&", "&") + "</h3>");
			add ("<form method=\"POST\">"); indentlevel++;
			pta^.headTitle = category + ": " + adrframe^.["/atts"].text;
			add ("<table border=\"0\" cellspacing=\"0\" cellpadding=\"4\" width=\"100%\">"); indentlevel++;
			bundle { //add the sub-elements
				local (adr);
				for adr in adrframe {
					if not (nameof (adr^) beginswith "/") {
						local (s = xml.entitydecode (adr^.["/atts"].text, true));
						if s beginswith "<%" {
							add (html.processmacros (s, adrPageTable:pta))}
						else {
							add ("<tr><td colspan=\"2\">" + html.processmacros (s, adrPageTable:pta) + "</td></tr>")}}}};
			if defined (pta^.flAddSubmitButton) { //JES 6/26/02: allow macros to suppress the Submit button
				flAddSubmitButton = pta^.flAddSubmitButton};
			if flAddSubmitButton { //add the Submit button
				add (blankline () + "<tr><td colspan=\"2\"><input type=\"submit\" value=\"" + submitButtonText + "\"></td></tr>")};
			add ("</table>"); indentlevel--;
			add ("</form>"); indentlevel--}};
	return (htmltext)}
<<bundle //test code
	<<html.setpagetableaddress (
	<<radio.prefs.browser (, adrToolsPrefs:@user.opmlEditor.prefs.toolsWithPrefs)

This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.