html.tcl

Go to the documentation of this file.
00001 /*  html.tcl --*/
00002 /* */
00003 /*  Procedures to make generating HTML easier.*/
00004 /* */
00005 /*  This module depends on the ncgi module for the procedures*/
00006 /*  that initialize form elements based on current CGI values.*/
00007 /* */
00008 /*  Copyright (c) 1998-2000 by Ajuba Solutions.*/
00009 /*  Copyright (c) 2006 Michael Schlenker <mic42@users.sourceforge.net>*/
00010 /* */
00011 /*  See the file "license.terms" for information on usage and redistribution*/
00012 /*  of this file, and for a DISCLAIMER OF ALL WARRANTIES.*/
00013 /* */
00014 /*  Originally by Brent Welch, with help from Dan Kuchler and Melissa Chawla*/
00015 
00016 package require Tcl 8.2
00017 package require ncgi
00018 package provide html 1.4
00019 
00020 namespace ::html {
00021 
00022     /*  State about the current page*/
00023 
00024     variable page
00025 
00026     /*  A simple set of global defaults for tag parameters is implemented*/
00027     /*  by storing into elements indexed by "key.param", where key is*/
00028     /*  often the name of an HTML tag (anything for scoping), and*/
00029     /*  param must be the name of the HTML tag parameter (e.g., "href" or "size")*/
00030     /*  input.size*/
00031     /*  body.bgcolor*/
00032     /*  body.text*/
00033     /*  font.face*/
00034     /*  font.size*/
00035     /*  font.color*/
00036 
00037     variable defaults
00038     array  defaults =  {
00039     input.size  45
00040     body.bgcolor    white
00041     body.text   black
00042     }
00043 
00044     /*  In order to nandle nested calls to redefined control structures,*/
00045     /*  we need a temporary variable that is known not to exist.  We keep this*/
00046     /*  counter to append to the varname.  Each time we need a temporary*/
00047     /*  variable, we increment this counter.*/
00048 
00049     variable randVar 0
00050 
00051     /*  No more export, because this defines things like*/
00052     /*  foreach and if that do HTML things, not Tcl control*/
00053     /*  namespace export **/
00054 
00055     /*  Dictionary mapping from special characters to their entities.*/
00056 
00057     variable entities {
00058         \xa0 &nbsp; \xa1 &iexcl; \xa2 &cent; \xa3 &pound; \xa4 &curren;
00059         \xa5 &yen; \xa6 &brvbar; \xa7 &sect; \xa8 &uml; \xa9 &copy;
00060         \xaa &ordf; \xab &laquo; \xac &not; \xad &shy; \xae &reg;
00061         \xaf &macr; \xb0 &deg; \xb1 &plusmn; \xb2 &sup2; \xb3 &sup3;
00062         \xb4 &acute; \xb5 &micro; \xb6 &para; \xb7 &middot; \xb8 &cedil;
00063         \xb9 &sup1; \xba &ordm; \xbb &raquo; \xbc &frac14; \xbd &frac12;
00064         \xbe &frac34; \xbf &iquest; \xc0 &Agrave; \xc1 &Aacute; \xc2 &Acirc;
00065         \xc3 &Atilde; \xc4 &Auml; \xc5 &Aring; \xc6 &AElig; \xc7 &Ccedil;
00066         \xc8 &Egrave; \xc9 &Eacute; \xca &Ecirc; \xcb &Euml; \xcc &Igrave;
00067         \xcd &Iacute; \xce &Icirc; \xcf &Iuml; \xd0 &ETH; \xd1 &Ntilde;
00068         \xd2 &Ograve; \xd3 &Oacute; \xd4 &Ocirc; \xd5 &Otilde; \xd6 &Ouml;
00069         \xd7 &times; \xd8 &Oslash; \xd9 &Ugrave; \xda &Uacute; \xdb &Ucirc;
00070         \xdc &Uuml; \xdd &Yacute; \xde &THORN; \xdf &szlig; \xe0 &agrave;
00071         \xe1 &aacute; \xe2 &acirc; \xe3 &atilde; \xe4 &auml; \xe5 &aring;
00072         \xe6 &aelig; \xe7 &ccedil; \xe8 &egrave; \xe9 &eacute; \xea &ecirc;
00073         \xeb &euml; \xec &igrave; \xed &iacute; \xee &icirc; \xef &iuml;
00074         \xf0 &eth; \xf1 &ntilde; \xf2 &ograve; \xf3 &oacute; \xf4 &ocirc;
00075         \xf5 &otilde; \xf6 &ouml; \xf7 &divide; \xf8 &oslash; \xf9 &ugrave;
00076         \xfa &uacute; \xfb &ucirc; \xfc &uuml; \xfd &yacute; \xfe &thorn;
00077         \xff &yuml; \u192 &fnof; \u391 &Alpha; \u392 &Beta; \u393 &Gamma;
00078         \u394 &Delta; \u395 &Epsilon; \u396 &Zeta; \u397 &Eta; \u398 &Theta;
00079         \u399 &Iota; \u39A &Kappa; \u39B &Lambda; \u39C &Mu; \u39D &Nu;
00080         \u39E &Xi; \u39F &Omicron; \u3A0 &Pi; \u3A1 &Rho; \u3A3 &Sigma;
00081         \u3A4 &Tau; \u3A5 &Upsilon; \u3A6 &Phi; \u3A7 &Chi; \u3A8 &Psi;
00082         \u3A9 &Omega; \u3B1 &alpha; \u3B2 &beta; \u3B3 &gamma; \u3B4 &delta;
00083         \u3B5 &epsilon; \u3B6 &zeta; \u3B7 &eta; \u3B8 &theta; \u3B9 &iota;
00084         \u3BA &kappa; \u3BB &lambda; \u3BC &mu; \u3BD &nu; \u3BE &xi;
00085         \u3BF &omicron; \u3C0 &pi; \u3C1 &rho; \u3C2 &sigmaf; \u3C3 &sigma;
00086         \u3C4 &tau; \u3C5 &upsilon; \u3C6 &phi; \u3C7 &chi; \u3C8 &psi;
00087         \u3C9 &omega; \u3D1 &thetasym; \u3D2 &upsih; \u3D6 &piv;
00088         \u2022 &bull; \u2026 &hellip; \u2032 &prime; \u2033 &Prime;
00089         \u203E &oline; \u2044 &frasl; \u2118 &weierp; \u2111 &image;
00090         \u211C &real; \u2122 &trade; \u2135 &alefsym; \u2190 &larr;
00091         \u2191 &uarr; \u2192 &rarr; \u2193 &darr; \u2194 &harr; \u21B5 &crarr;
00092         \u21D0 &lArr; \u21D1 &uArr; \u21D2 &rArr; \u21D3 &dArr; \u21D4 &hArr;
00093         \u2200 &forall; \u2202 &part; \u2203 &exist; \u2205 &empty;
00094         \u2207 &nabla; \u2208 &isin; \u2209 &notin; \u220B &ni; \u220F &prod;
00095         \u2211 &sum; \u2212 &minus; \u2217 &lowast; \u221A &radic;
00096         \u221D &prop; \u221E &infin; \u2220 &ang; \u2227 &and; \u2228 &or;
00097         \u2229 &cap; \u222A &cup; \u222B &int; \u2234 &there4; \u223C &sim;
00098         \u2245 &cong; \u2248 &asymp; \u2260 &ne; \u2261 &equiv; \u2264 &le;
00099         \u2265 &ge; \u2282 &sub; \u2283 &sup; \u2284 &nsub; \u2286 &sube;
00100         \u2287 &supe; \u2295 &oplus; \u2297 &otimes; \u22A5 &perp;
00101         \u22C5 &sdot; \u2308 &lceil; \u2309 &rceil; \u230A &lfloor;
00102         \u230B &rfloor; \u2329 &lang; \u232A &rang; \u25CA &loz;
00103         \u2660 &spades; \u2663 &clubs; \u2665 &hearts; \u2666 &diams;
00104         \x22 &quot; \x26 &amp; \x3C &lt; \x3E &gt; \u152 &OElig;
00105         \u153 &oelig; \u160 &Scaron; \u161 &scaron; \u178 &Yuml;
00106         \u2C6 &circ; \u2DC &tilde; \u2002 &ensp; \u2003 &emsp; \u2009 &thinsp;
00107         \u200C &zwnj; \u200D &zwj; \u200E &lrm; \u200F &rlm; \u2013 &ndash;
00108         \u2014 &mdash; \u2018 &lsquo; \u2019 &rsquo; \u201A &sbquo;
00109         \u201C &ldquo; \u201D &rdquo; \u201E &bdquo; \u2020 &dagger;
00110         \u2021 &Dagger; \u2030 &permil; \u2039 &lsaquo; \u203A &rsaquo;
00111         \u20AC &euro;
00112     }
00113 }
00114 
00115 /*  ::html::foreach*/
00116 /* */
00117 /*  Rework the "foreach" command to blend into HTML template files.*/
00118 /*  Rather than evaluating the body, we return the subst'ed body.  Each*/
00119 /*  iteration of the loop causes another string to be concatenated to*/
00120 /*  the result value.  No error checking is done on any arguments.*/
00121 /* */
00122 /*  Arguments:*/
00123 /*  varlist Variables to instantiate with values from the next argument.*/
00124 /*  list    Values to set variables in varlist to.*/
00125 /*  args    ?varlist2 list2 ...? body, where body is the string to subst*/
00126 /*      during each iteration of the loop.*/
00127 /* */
00128 /*  Results:*/
00129 /*  Returns a string composed of multiple concatenations of the*/
00130 /*  substitued body.*/
00131 /* */
00132 /*  Side Effects:*/
00133 /*  None.*/
00134 
00135 ret  ::html::foreach (type vars , type vals , type args) {
00136     variable randVar
00137 
00138     # The body of the foreach loop must be run in the stack frame
00139     # above this one in order to have access to local variable at that stack
00140     # level.
00141 
00142     # To support nested foreach loops, we use a uniquely named
00143     # variable to store incremental results.
00144     incr randVar
00145     ::set resultVar "result_$randVar"
00146 
00147     # Extract the body and any varlists and valuelists from the args.
00148     ::set body [lindex $args end]
00149     ::set varvals [linsert [lreplace $args end end] 0 $vars $vals]
00150 
00151     # Create the script to eval in the stack frame above this one.
00152     ::set script "::foreach"
00153     ::foreach {vars vals} $varvals {
00154         append script " [list $vars] [list $vals]"
00155     }
00156     append script " \{\n"
00157     append script "  append $resultVar \[subst \{$body\}\]\n"
00158     append script "\}\n"
00159 
00160     # Create a temporary variable in the stack frame above this one,
00161     # and use it to store the incremental results of the multiple loop
00162     # iterations.  Remove the temporary variable when we're done so there's
00163     # no trace of this loop left in that stack frame.
00164 
00165     upvar 1 $resultVar tmp
00166     ::set tmp ""
00167     uplevel 1 $script
00168     ::set result $tmp
00169     unset tmp
00170     return $result
00171 }
00172 
00173 /*  ::html::for*/
00174 /* */
00175 /*  Rework the "for" command to blend into HTML template files.*/
00176 /*  Rather than evaluating the body, we return the subst'ed body.  Each*/
00177 /*  iteration of the loop causes another string to be concatenated to*/
00178 /*  the result value.  No error checking is done on any arguments.*/
00179 /* */
00180 /*  Arguments:*/
00181 /*  start   A script to evaluate once at the very beginning.*/
00182 /*  test    An expression to eval before each iteration of the loop.*/
00183 /*      Once the expression is false, the command returns.*/
00184 /*  next    A script to evaluate after each iteration of the loop.*/
00185 /*  body    The string to subst during each iteration of the loop.*/
00186 /* */
00187 /*  Results:*/
00188 /*  Returns a string composed of multiple concatenations of the*/
00189 /*  substitued body.*/
00190 /* */
00191 /*  Side Effects:*/
00192 /*  None.*/
00193 
00194 ret  ::html::for (type start , type test , type next , type body) {
00195     variable randVar
00196 
00197     # The body of the for loop must be run in the stack frame
00198     # above this one in order to have access to local variable at that stack
00199     # level.
00200 
00201     # To support nested for loops, we use a uniquely named
00202     # variable to store incremental results.
00203     incr randVar
00204     ::set resultVar "result_$randVar"
00205 
00206     # Create the script to eval in the stack frame above this one.
00207     ::set script "::for [list $start] [list $test] [list $next] \{\n"
00208     append script "  append $resultVar \[subst \{$body\}\]\n"
00209     append script "\}\n"
00210 
00211     # Create a temporary variable in the stack frame above this one,
00212     # and use it to store the incremental resutls of the multiple loop
00213     # iterations.  Remove the temporary variable when we're done so there's
00214     # no trace of this loop left in that stack frame.
00215 
00216     upvar 1 $resultVar tmp
00217     ::set tmp ""
00218     uplevel 1 $script
00219     ::set result $tmp
00220     unset tmp
00221     return $result
00222 }
00223 
00224 /*  ::html::while*/
00225 /* */
00226 /*  Rework the "while" command to blend into HTML template files.*/
00227 /*  Rather than evaluating the body, we return the subst'ed body.  Each*/
00228 /*  iteration of the loop causes another string to be concatenated to*/
00229 /*  the result value.  No error checking is done on any arguments.*/
00230 /* */
00231 /*  Arguments:*/
00232 /*  test    An expression to eval before each iteration of the loop.*/
00233 /*      Once the expression is false, the command returns.*/
00234 /*  body    The string to subst during each iteration of the loop.*/
00235 /* */
00236 /*  Results:*/
00237 /*  Returns a string composed of multiple concatenations of the*/
00238 /*  substitued body.*/
00239 /* */
00240 /*  Side Effects:*/
00241 /*  None.*/
00242 
00243 ret  ::html::while (type test , type body) {
00244     variable randVar
00245 
00246     # The body of the while loop must be run in the stack frame
00247     # above this one in order to have access to local variable at that stack
00248     # level.
00249 
00250     # To support nested while loops, we use a uniquely named
00251     # variable to store incremental results.
00252     incr randVar
00253     ::set resultVar "result_$randVar"
00254 
00255     # Create the script to eval in the stack frame above this one.
00256     ::set script "::while [list $test] \{\n"
00257     append script "  append $resultVar \[subst \{$body\}\]\n"
00258     append script "\}\n"
00259 
00260     # Create a temporary variable in the stack frame above this one,
00261     # and use it to store the incremental resutls of the multiple loop
00262     # iterations.  Remove the temporary variable when we're done so there's
00263     # no trace of this loop left in that stack frame.
00264 
00265     upvar 1 $resultVar tmp
00266     ::set tmp ""
00267     uplevel 1 $script
00268     ::set result $tmp
00269     unset tmp
00270     return $result
00271 }
00272 
00273 /*  ::html::if*/
00274 /* */
00275 /*  Rework the "if" command to blend into HTML template files.*/
00276 /*  Rather than evaluating a body clause, we return the subst'ed body.*/
00277 /*  No error checking is done on any arguments.*/
00278 /* */
00279 /*  Arguments:*/
00280 /*  test    An expression to eval to decide whether to use the then body.*/
00281 /*  body    The string to subst if the test case was true.*/
00282 /*  args    ?elseif test body2 ...? ?else bodyn?, where bodyn is the string*/
00283 /*      to subst if none of the tests are true.*/
00284 /* */
00285 /*  Results:*/
00286 /*  Returns a string composed by substituting a body clause.*/
00287 /* */
00288 /*  Side Effects:*/
00289 /*  None.*/
00290 
00291 ret  ::html::if (type test , type body , type args) {
00292     variable randVar
00293 
00294     # The body of the then/else clause must be run in the stack frame
00295     # above this one in order to have access to local variable at that stack
00296     # level.
00297 
00298     # To support nested if's, we use a uniquely named
00299     # variable to store incremental results.
00300     incr randVar
00301     ::set resultVar "result_$randVar"
00302 
00303     # Extract the elseif clauses and else clause if they exist.
00304     ::set cmd [linsert $args 0 "::if" $test $body]
00305 
00306     ::foreach {keyword test body} $cmd {
00307         ::if {[string equal $keyword "else"]} {
00308             append script " else \{\n"
00309             ::set body $test
00310         } else {
00311             append script " $keyword [list $test] \{\n"
00312         }
00313         append script "  append $resultVar \[subst \{$body\}\]\n"
00314         append script "\} "
00315     }
00316 
00317     # Create a temporary variable in the stack frame above this one,
00318     # and use it to store the incremental resutls of the multiple loop
00319     # iterations.  Remove the temporary variable when we're done so there's
00320     # no trace of this loop left in that stack frame.
00321 
00322     upvar $resultVar tmp
00323     ::set tmp ""
00324     uplevel $script
00325     ::set result $tmp
00326     unset tmp
00327     return $result
00328 }
00329 
00330 # ::html::set
00331 #
00332 #   Rework the "set" command to blend into HTML template files.
00333 #   The return value is always "" so nothing is appended in the
00334 #   template.  No error checking is done on any arguments.
00335 #
00336 # Arguments:
00337 #   var The variable to set.
00338 #   val The new value to give the variable.
00339 #
00340 # Results:
00341 #   Returns "".
00342 #
00343 # Side Effects:
00344 #   None.
00345 
00346 proc ::html::set {var val} {
00347 
00348     # The variable must be set in the stack frame above this one.
00349 
00350     ::set cmd [list set $var $val]
00351     uplevel 1 $cmd
00352     return ""
00353 }
00354 
00355 # ::html::eval
00356 #
00357 #   Rework the "eval" command to blend into HTML template files.
00358 #   The return value is always "" so nothing is appended in the
00359 #   template.  No error checking is done on any arguments.
00360 #
00361 # Arguments:
00362 #   args    The args to evaluate.  At least one must be given.
00363 #
00364 # Results:
00365 #   Returns "".
00366 #
00367 # Side Effects:
00368 #   Throws an error if no arguments are given.
00369 
00370 proc ::html::eval {args} {
00371 
00372     # The args must be evaluated in the stack frame above this one.
00373     ::eval [linsert $args 0 uplevel 1]
00374     return ""
00375 }
00376 
00377 # ::html::init
00378 #
00379 #   Reset state that gets accumulated for the current page.
00380 #
00381 # Arguments:
00382 #   nvlist  Name, value list that is used to initialize default namespace
00383 #       variables that set font, size, etc.
00384 #
00385 # Side Effects:
00386 #   Wipes the page state array
00387 
00388 proc ::html::init {{nvlist {}}} {
00389     variable page
00390     variable defaults
00391     ::if {[info exists page]} {
00392     unset page
00393     }
00394     ::if {[info exists defaults]} {
00395     unset defaults
00396     }
00397     array set defaults $nvlist
00398 }
00399 
00400 # ::html::head
00401 #
00402 #   Generate the <head> section.  There are a number of
00403 #   optional calls you make *before* this to inject
00404 #   meta tags - see everything between here and the bodyTag proc.
00405 #
00406 # Arguments:
00407 #   title   The page title
00408 #
00409 # Results:
00410 #   HTML for the <head> section
00411 
00412 proc ::html::head {title} {
00413     variable page
00414     ::set html "[openTag html][openTag head]\n"
00415     append html "\t[title $title]"
00416     ::if {[info exists page(author)]} {
00417     append html "\t$page(author)"
00418     }
00419     ::if {[info exists page(meta)]} {
00420     ::foreach line $page(meta) {
00421         append html "\t$line\n"
00422     }
00423     }
00424     ::if {[info exists page(css)]} {
00425     ::foreach style $page(css) {
00426         append html "\t$style\n"
00427     }
00428     }
00429     ::if {[info exists page(js)]} {
00430     ::foreach script $page(js) {
00431         append html "\t$script\n"
00432     }
00433     }
00434     append html "[closeTag]\n"
00435 }
00436 
00437 # ::html::title
00438 #
00439 #   Wrap up the <title> and tuck it away for use in the page later.
00440 #
00441 # Arguments:
00442 #   title   The page title
00443 #
00444 # Results:
00445 #   HTML for the <title> section
00446 
00447 proc ::html::title {title} {
00448     variable page
00449     ::set page(title) $title
00450     ::set html "<title>$title</title>\n"
00451     return $html
00452 }
00453 
00454 # ::html::getTitle
00455 #
00456 #   Return the title of the current page.
00457 #
00458 # Arguments:
00459 #   None
00460 #
00461 # Results:
00462 #   The title
00463 
00464 proc ::html::getTitle {} {
00465     variable page
00466     ::if {[info exists page(title)]} {
00467     return $page(title)
00468     } else {
00469     return ""
00470     }
00471 }
00472 
00473 # ::html::meta
00474 #
00475 #   Generate a meta tag.  This tag gets bundled into the <head>
00476 #   section generated by html::head
00477 #
00478 # Arguments:
00479 #   args    A name-value list of meta tag names and values.
00480 #
00481 # Side Effects:
00482 #   Stores HTML for the <meta> tag for use later by html::head
00483 
00484 proc ::html::meta {args} {
00485     variable page
00486     ::set html ""
00487     ::foreach {name value} $args {
00488     append html "<meta name=\"$name\" content=\"[quoteFormValue $value]\">"
00489     }
00490     lappend page(meta) $html
00491     return ""
00492 }
00493 
00494 # ::html::refresh
00495 #
00496 #   Generate a meta refresh tag.  This tag gets bundled into the <head>
00497 #   section generated by html::head
00498 #
00499 # Arguments:
00500 #   content Time period, in seconds, before the refresh
00501 #   url (option) new page to view. If not specified, then
00502 #       the current page is reloaded.
00503 #
00504 # Side Effects:
00505 #   Stores HTML for the <meta> tag for use later by html::head
00506 
00507 proc ::html::refresh {content {url {}}} {
00508     variable page
00509     ::set html "<meta http-equiv=\"Refresh\" content=\"$content"
00510     ::if {[string length $url]} {
00511     append html "; url=$url"
00512     }
00513     append html "\">\n"
00514     lappend page(meta) $html
00515     return ""
00516 }
00517 
00518 # ::html::headTag
00519 #
00520 #   Embed a tag into the HEAD section
00521 #   generated by html::head
00522 #
00523 # Arguments:
00524 #   string  Everything but the < > for the tag.
00525 #
00526 # Side Effects:
00527 #   Stores HTML for the tag for use later by html::head
00528 
00529 proc ::html::headTag {string} {
00530     variable page
00531     lappend page(meta) <$string>
00532     return ""
00533 }
00534 
00535 # ::html::keywords
00536 #
00537 #   Add META tag keywords to the <head> section.
00538 #   Call this before you call html::head
00539 #
00540 # Arguments:
00541 #   args    The keywords
00542 #
00543 # Side Effects:
00544 #   See html::meta
00545 
00546 proc ::html::keywords {args} {
00547     html::meta keywords [join $args ", "]
00548 }
00549 
00550 # ::html::description
00551 #
00552 #   Add a description META tag to the <head> section.
00553 #   Call this before you call html::head
00554 #
00555 # Arguments:
00556 #   description The description
00557 #
00558 # Side Effects:
00559 #   See html::meta
00560 
00561 proc ::html::description {description} {
00562     html::meta description $description
00563 }
00564 
00565 # ::html::author
00566 #
00567 #   Add an author comment to the <head> section.
00568 #   Call this before you call html::head
00569 #
00570 # Arguments:
00571 #   author  Author's name
00572 #
00573 # Side Effects:
00574 #   sets page(author)
00575 
00576 proc ::html::author {author} {
00577     variable page
00578     ::set page(author) "<!-- $author -->\n"
00579     return ""
00580 }
00581 
00582 # ::html::tagParam
00583 #
00584 #   Return a name, value string for the tag parameters.
00585 #   The values come from "hard-wired" values in the 
00586 #   param agrument, or from the defaults set with html::init.
00587 #
00588 # Arguments:
00589 #   tag Name of the HTML tag (case insensitive).
00590 #   param   pname=value info that overrides any default values
00591 #
00592 # Results
00593 #   A string of the form:
00594 #       pname="keyvalue" name2="2nd value"
00595 
00596 proc ::html::tagParam {tag {param {}}} {
00597     variable defaults
00598 
00599     ::set def ""
00600     ::foreach key [lsort [array names defaults $tag.*]] {
00601     append def [default $key $param]
00602     }
00603     return [string trimleft $param$def]
00604 }
00605 
00606 # ::html::default
00607 #
00608 #   Return a default value, if one has been registered
00609 #   and an overriding value does not occur in the existing
00610 #   tag parameters.
00611 #
00612 # Arguments:
00613 #   key Index into the defaults array defined by html::init
00614 #       This is expected to be in the form tag.pname where
00615 #       the pname part is used in the tag parameter name
00616 #   param   pname=value info that overrides any default values
00617 #
00618 # Results
00619 #   pname="keyvalue"
00620 
00621 proc ::html::default {key {param {}}} {
00622     variable defaults
00623     ::set pname [string tolower [lindex [split $key .] 1]]
00624     ::set key [string tolower $key]
00625     ::if {![regexp -nocase "(\[     \]|^)$pname=" $param] &&
00626         [info exists defaults($key)] &&
00627         [string length $defaults($key)]} {
00628     return " $pname=\"$defaults($key)\""
00629     } else {
00630     return ""
00631     }
00632 }
00633 
00634 # ::html::bodyTag
00635 #
00636 #   Generate a body tag
00637 #
00638 # Arguments:
00639 #   none
00640 #
00641 # Results
00642 #   A body tag
00643 
00644 proc ::html::bodyTag {args} {
00645     return [openTag body [join $args]]\n
00646 }
00647 
00648 # The following procedures are all related to generating form elements
00649 # that are initialized to store the current value of the form element
00650 # based on the CGI state.  These functions depend on the ncgi::value
00651 # procedure and assume that the caller has called ncgi::parse and/or
00652 # ncgi::init appropriately to initialize the ncgi module.
00653 
00654 # ::html::formValue
00655 #
00656 #   Return a name and value pair, where the value is initialized
00657 #   from existing form data, if any.
00658 #
00659 # Arguments:
00660 #   name        The name of the form element
00661 #   defvalue    A default value to use, if not appears in the CGI
00662 #           inputs.  DEPRECATED - use ncgi::defValue instead.
00663 #
00664 # Retults:
00665 #   A string like:
00666 #   name="fred" value="freds value"
00667 
00668 proc ::html::formValue {name {defvalue {}}} {
00669     ::set value [ncgi::value $name]
00670     ::if {[string length $value] == 0} {
00671     ::set value $defvalue
00672     }
00673     return "name=\"$name\" value=\"[quoteFormValue $value]\""
00674 }
00675 
00676 # ::html::quoteFormValue
00677 #
00678 #   Quote a value for use in a value=\"$value\" fragment.
00679 #
00680 # Arguments:
00681 #   value       The value to quote
00682 #
00683 # Retults:
00684 #   A string like:
00685 #   &#34;Hello, &lt;b&gt;World!&#34;
00686 
00687 proc ::html::quoteFormValue {value} {
00688     return [string map [list "&" "&amp;" "\"" "&#34;" \
00689                 "'" "&#39;" "<" "&lt;" ">" "&gt;"] $value]
00690 }
00691 
00692 # ::html::textInput --
00693 #
00694 #   Return an <input type=text> element.  This uses the
00695 #   input.size default falue.
00696 #
00697 # Arguments:
00698 #   name        The form element name
00699 #   args        Additional attributes for the INPUT tag
00700 #
00701 # Results:
00702 #   The html fragment
00703 
00704 proc ::html::textInput {name {value {}} args} {
00705     ::set html "<input type=\"text\" "
00706     append html [formValue $name $value]
00707     append html [default input.size $args]
00708     ::if {[llength $args] != 0} then {
00709     append html " " [join $args]
00710     }
00711     append html ">\n"
00712     return $html
00713 }
00714 
00715 # ::html::textInputRow --
00716 #
00717 #   Format a table row containing a text input element and a label.
00718 #
00719 # Arguments:
00720 #   label   Label to display next to the form element
00721 #   name    The form element name
00722 #   args    Additional attributes for the INPUT tag
00723 #
00724 # Results:
00725 #   The html fragment
00726 
00727 proc ::html::textInputRow {label name {value {}} args} {
00728     ::set html [row $label [::eval [linsert $args 0 html::textInput $name $value]]]
00729     return $html
00730 }
00731 
00732 # ::html::passwordInputRow --
00733 #
00734 #   Format a table row containing a password input element and a label.
00735 #
00736 # Arguments:
00737 #   label   Label to display next to the form element
00738 #   name    The form element name
00739 #
00740 # Results:
00741 #   The html fragment
00742 
00743 proc ::html::passwordInputRow {label {name password}} {
00744     ::set html [row $label [passwordInput $name]]
00745     return $html
00746 }
00747 
00748 # ::html::passwordInput --
00749 #
00750 #   Return an <input type=password> element.
00751 #
00752 # Arguments:
00753 #   name    The form element name. Defaults to "password"
00754 #
00755 # Results:
00756 #   The html fragment
00757 
00758 proc ::html::passwordInput {{name password}} {
00759     ::set html "<input type=\"password\" name=\"$name\">\n"
00760     return $html
00761 }
00762 
00763 # ::html::checkbox --
00764 #
00765 #   Format a checkbox so that it retains its state based on
00766 #   the current CGI values
00767 #
00768 # Arguments:
00769 #   name        The form element name
00770 #   value       The value associated with the checkbox
00771 #
00772 # Results:
00773 #   The html fragment
00774 
00775 proc ::html::checkbox {name value} {
00776     ::set html "<input type=\"checkbox\" [checkValue $name $value]>\n"
00777 }
00778 
00779 # ::html::checkValue
00780 #
00781 #   Like html::formalue, but for checkboxes that need CHECKED
00782 #
00783 # Arguments:
00784 #   name        The name of the form element
00785 #   defvalue    A default value to use, if not appears in the CGI
00786 #           inputs
00787 #
00788 # Retults:
00789 #   A string like:
00790 #   name="fred" value="freds value" CHECKED
00791 
00792 
00793 proc ::html::checkValue {name {value 1}} {
00794     ::foreach v [ncgi::valueList $name] {
00795 	::if {[string compare $value $v] == 0} {
00796         return "name=\"$name\" value=\"[quoteFormValue $value]\" checked"
00797     }
00798     }
00799     return "name=\"$name\" value=\"[quoteFormValue $value]\""
00800 }
00801 
00802 # ::html::radioValue
00803 #
00804 #   Like html::formValue, but for radioboxes that need CHECKED
00805 #
00806 # Arguments:
00807 #   name    The name of the form element
00808 #   value   The value associated with the radio button.
00809 #
00810 # Retults:
00811 #   A string like:
00812 #   name="fred" value="freds value" CHECKED
00813 
00814 proc ::html::radioValue {name value {defaultSelection {}}} {
00815     ::if {[string equal $value [ncgi::value $name $defaultSelection]]} {
00816     return "name=\"$name\" value=\"[quoteFormValue $value]\" checked"
00817     } else {
00818     return "name=\"$name\" value=\"[quoteFormValue $value]\""
00819     }
00820 }
00821 
00822 # ::html::radioSet --
00823 #
00824 #   Display a set of radio buttons while looking for an existing
00825 #   value from the query data, if any.
00826 
00827 proc ::html::radioSet {key sep list {defaultSelection {}}} {
00828     ::set html ""
00829     ::set s ""
00830     ::foreach {label v} $list {
00831     append html "$s<input type=\"radio\" [radioValue $key $v $defaultSelection]> $label"
00832     ::set s $sep
00833     }
00834     return $html
00835 }
00836 
00837 # ::html::checkSet --
00838 #
00839 #   Display a set of check buttons while looking for an existing
00840 #   value from the query data, if any.
00841 
00842 proc ::html::checkSet {key sep list} {
00843     ::set s ""
00844     ::foreach {label v} $list {
00845     append html "$s<input type=\"checkbox\" [checkValue $key $v]> $label"
00846     ::set s $sep
00847     }
00848     return $html
00849 }
00850 
00851 # ::html::select --
00852 #
00853 #   Format a <select> element that retains the state of the
00854 #   current CGI values.
00855 #
00856 # Arguments:
00857 #   name        The form element name
00858 #   param       The various size, multiple parameters for the tag
00859 #   choices     A simple list of choices
00860 #   current     Value to assume if nothing is in CGI state
00861 #
00862 # Results:
00863 #   The html fragment
00864 
00865 proc ::html::select {name param choices {current {}}} {
00866     ::set def [ncgi::valueList $name $current]
00867     ::set html "<select name=\"$name\"[string trimright  " $param"]>\n"
00868     ::foreach {label v} $choices {
00869 	::if {[lsearch -exact $def $v] != -1} {
00870         ::set SEL " selected"
00871     } else {
00872         ::set SEL ""
00873     }
00874     append html "<option value=\"$v\"$SEL>$label\n"
00875     }
00876     append html "</select>\n"
00877     return $html
00878 }
00879 
00880 # ::html::selectPlain --
00881 #
00882 #   Format a <select> element where the values are the same
00883 #   as those that are displayed.
00884 #
00885 # Arguments:
00886 #   name        The form element name
00887 #   param       Tag parameters
00888 #   choices     A simple list of choices
00889 #
00890 # Results:
00891 #   The html fragment
00892 
00893 proc ::html::selectPlain {name param choices {current {}}} {
00894     ::set namevalue {}
00895     ::foreach c $choices {
00896     lappend namevalue $c $c
00897     }
00898     return [select $name $param $namevalue $current]
00899 }
00900 
00901 # ::html::textarea --
00902 #
00903 #   Format a <textarea> element that retains the state of the
00904 #   current CGI values.
00905 #
00906 # Arguments:
00907 #   name        The form element name
00908 #   param       The various size, multiple parameters for the tag
00909 #   current     Value to assume if nothing is in CGI state
00910 #
00911 # Results:
00912 #   The html fragment
00913 
00914 proc ::html::textarea {name {param {}} {current {}}} {
00915     ::set value [ncgi::value $name $current]
00916     return "<[string trimright \
00917     "textarea name=\"$name\"\
00918         [tagParam textarea $param]"]>$value</textarea>\n"
00919 }
00920 
00921 # ::html::submit --
00922 #
00923 #   Format a submit button.
00924 #
00925 # Arguments:
00926 #   label       The string to appear in the submit button.
00927 #   name        The name for the submit button element
00928 #
00929 # Results:
00930 #   The html fragment
00931 
00932 
00933 proc ::html::submit {label {name submit}} {
00934     ::set html "<input type=\"submit\" name=\"$name\" value=\"$label\">\n"
00935 }
00936 
00937 # ::html::varEmpty --
00938 #
00939 #   Return true if the variable doesn't exist or is an empty string
00940 #
00941 # Arguments:
00942 #   varname Name of the variable
00943 #
00944 # Results:
00945 #   1 if the variable doesn't exist or has the empty value
00946 
00947 proc ::html::varEmpty {name} {
00948     upvar 1 $name var
00949     ::if {[info exists var]} {
00950     ::set value $var
00951     } else {
00952     ::set value ""
00953     }
00954     return [expr {[string length [string trim $value]] == 0}]
00955 }
00956 
00957 # ::html::getFormInfo --
00958 #
00959 #   Generate hidden fields to capture form values.
00960 #
00961 # Arguments:
00962 #   args    List of elements to save.  If this is empty, everything is
00963 #       saved in hidden fields.  This is a list of string match
00964 #       patterns.
00965 #
00966 # Results:
00967 #   A bunch of <input type=hidden> elements
00968 
00969 proc ::html::getFormInfo {args} {
00970     ::if {[llength $args] == 0} {
00971     ::set args *
00972     }
00973     ::set html ""
00974     ::foreach {n v} [ncgi::nvlist] {
00975     ::foreach pat $args {
00976 	    ::if {[string match $pat $n]} {
00977         append html "<input type=\"hidden\" name=\"$n\" \
00978                     value=\"[quoteFormValue $v]\">\n"
00979         }
00980     }
00981     }
00982     return $html
00983 }
00984 
00985 # ::html::h1
00986 #   Generate an H1 tag.
00987 #
00988 # Arguments:
00989 #   string
00990 #   param
00991 #
00992 # Results:
00993 #   Formats the tag.
00994 
00995 proc ::html::h1 {string {param {}}} {
00996     html::h 1 $string $param
00997 }
00998 proc ::html::h2 {string {param {}}} {
00999     html::h 2 $string $param
01000 }
01001 proc ::html::h3 {string {param {}}} {
01002     html::h 3 $string $param
01003 }
01004 proc ::html::h4 {string {param {}}} {
01005     html::h 4 $string $param
01006 }
01007 proc ::html::h5 {string {param {}}} {
01008     html::h 5 $string $param
01009 }
01010 proc ::html::h6 {string {param {}}} {
01011     html::h 6 $string $param
01012 }
01013 proc ::html::h {level string {param {}}} {
01014     return "<[string trimright "h$level [tagParam h$level $param]"]>$string</h$level>\n"
01015 }
01016 
01017 # ::html::openTag
01018 #   Remember that a tag  is opened so it can be closed later.
01019 #   This is used to automatically clean up at the end of a page.
01020 #
01021 # Arguments:
01022 #   tag The HTML tag name
01023 #   param   Any parameters for the tag
01024 #
01025 # Results:
01026 #   Formats the tag.  Also keeps it around in a per-page stack
01027 #   of open tags.
01028 
01029 proc ::html::openTag {tag {param {}}} {
01030     variable page
01031     lappend page(stack) $tag
01032     return "<[string trimright "$tag [tagParam $tag $param]"]>"
01033 }
01034 
01035 # ::html::closeTag
01036 #   Pop a tag from the stack and close it.
01037 #
01038 # Arguments:
01039 #   None
01040 #
01041 # Results:
01042 #   A close tag.  Also pops the stack.
01043 
01044 proc ::html::closeTag {} {
01045     variable page
01046     ::if {[info exists page(stack)]} {
01047     ::set top [lindex $page(stack) end]
01048     ::set page(stack) [lreplace $page(stack) end end]
01049     }
01050     ::if {[info exists top] && [string length $top]} {
01051     return </$top>
01052     } else {
01053     return ""
01054     }
01055 }
01056 
01057 # ::html::end
01058 #
01059 #   Close out all the open tags.  Especially useful for
01060 #   Tables that do not display at all if they are unclosed.
01061 #
01062 # Arguments:
01063 #   None
01064 #
01065 # Results:
01066 #   Some number of close HTML tags.
01067 
01068 proc ::html::end {} {
01069     variable page
01070     ::set html ""
01071     ::while {[llength $page(stack)]} {
01072     append html [closeTag]\n
01073     }
01074     return $html
01075 }
01076 
01077 # ::html::row
01078 #
01079 #   Format a table row.  If the default font has been set, this
01080 #   takes care of wrapping the table cell contents in a font tag.
01081 #
01082 # Arguments:
01083 #   args    Values to put into the row
01084 #
01085 # Results:
01086 #   A <tr><td>...</tr> fragment
01087 
01088 proc ::html::row {args} {
01089     ::set html <tr>\n
01090     ::foreach x $args {
01091     append html \t[cell "" $x td]\n
01092     }
01093     append html "</tr>\n"
01094     return $html
01095 }
01096 
01097 # ::html::hdrRow
01098 #
01099 #   Format a table row.  If the default font has been set, this
01100 #   takes care of wrapping the table cell contents in a font tag.
01101 #
01102 # Arguments:
01103 #   args    Values to put into the row
01104 #
01105 # Results:
01106 #   A <tr><th>...</tr> fragment
01107 
01108 proc ::html::hdrRow {args} {
01109     variable defaults
01110     ::set html <tr>\n
01111     ::foreach x $args {
01112     append html \t[cell "" $x th]\n
01113     }
01114     append html "</tr>\n"
01115     return $html
01116 }
01117 
01118 # ::html::paramRow
01119 #
01120 #   Format a table row.  If the default font has been set, this
01121 #   takes care of wrapping the table cell contents in a font tag.
01122 #
01123 #       Based on html::row
01124 #
01125 # Arguments:
01126 #   list    Values to put into the row
01127 #       rparam   Parameters for row
01128 #       cparam   Parameters for cells
01129 #
01130 # Results:
01131 #   A <tr><td>...</tr> fragment
01132 
01133 proc ::html::paramRow {list {rparam {}} {cparam {}}} {
01134     ::set html "<tr $rparam>\n"
01135     ::foreach x $list {
01136     append html \t[cell $cparam $x td]\n
01137     }
01138     append html "</tr>\n"
01139     return $html
01140 }
01141 
01142 # ::html::cell
01143 #
01144 #   Format a table cell.  If the default font has been set, this
01145 #   takes care of wrapping the table cell contents in a font tag.
01146 #
01147 # Arguments:
01148 #   param   Td tag parameters
01149 #   value   The value to put into the cell
01150 #   tag (option) defaults to TD
01151 #
01152 # Results:
01153 #   <td>...</td> fragment
01154 
01155 proc ::html::cell {param value {tag td}} {
01156     ::set font [font]
01157     ::if {[string length $font]} {
01158     ::set value $font$value</font>
01159     }
01160     return "<[string trimright "$tag $param"]>$value</$tag>"
01161 }
01162 
01163 # ::html::tableFromArray
01164 #
01165 #   Format a Tcl array into an HTML table
01166 #
01167 # Arguments:
01168 #   arrname The name of the array
01169 #   param   The <table> tag parameters, if any.
01170 #   pat A string match pattern for the element keys
01171 #
01172 # Results:
01173 #   A <table>
01174 
01175 proc ::html::tableFromArray {arrname {param {}} {pat *}} {
01176     upvar 1 $arrname arr
01177     ::set html ""
01178     ::if {[info exists arr]} {
01179     append html "<table $param>\n"
01180     append html "<tr><th colspan=2>$arrname</th></tr>\n"
01181     ::foreach name [lsort [array names arr $pat]] {
01182         append html [row $name $arr($name)]
01183     }
01184     append html </table>\n
01185     }
01186     return $html
01187 }
01188 
01189 # ::html::tableFromList
01190 #
01191 #   Format a table from a name, value list
01192 #
01193 # Arguments:
01194 #   querylist   A name, value list
01195 #   param       The <table> tag parameters, if any.
01196 #
01197 # Results:
01198 #   A <table>
01199 
01200 proc ::html::tableFromList {querylist {param {}}} {
01201     ::set html ""
01202     ::if {[llength $querylist]} {
01203     append html "<table $param>"
01204     ::foreach {label value} $querylist {
01205         append html [row $label $value]
01206     }
01207     append html </table>
01208     }
01209     return $html
01210 }
01211 
01212 # ::html::mailto
01213 #
01214 #   Format a mailto: HREF tag
01215 #
01216 # Arguments:
01217 #   email   The target
01218 #   subject The subject of the email, if any
01219 #
01220 # Results:
01221 #   A <a href=mailto> tag </a>
01222 
01223 proc ::html::mailto {email {subject {}}} {
01224     ::set html "<a href=\"mailto:$email"
01225     ::if {[string length $subject]} {
01226     append html ?subject=$subject
01227     }
01228     append html "\">$email</a>"
01229     return $html
01230 }
01231 
01232 # ::html::font
01233 #
01234 #   Generate a standard <font> tag.  This depends on defaults being
01235 #   set via html::init
01236 #
01237 # Arguments:
01238 #   args    Font parameters.  
01239 #
01240 # Results:
01241 #   HTML
01242 
01243 proc ::html::font {args} {
01244 
01245     # e.g., font.face, font.size, font.color
01246     ::set param [tagParam font [join $args]]
01247 
01248     ::if {[string length $param]} {
01249     return "<[string trimright "font $param"]>"
01250     } else {
01251     return ""
01252     }
01253 }
01254 
01255 # ::html::minorMenu
01256 #
01257 #   Create a menu of links given a list of label, URL pairs.
01258 #   If the URL is the current page, it is not highlighted.
01259 #
01260 # Arguments:
01261 #
01262 #   list    List that alternates label, url, label, url
01263 #   sep Separator between elements
01264 #
01265 # Results:
01266 #   html
01267 
01268 proc ::html::minorMenu {list {sep { | }}} {
01269     ::set s ""
01270     ::set html ""
01271     regsub -- {index.h?tml$} [ncgi::urlStub] {} this
01272     ::foreach {label url} $list {
01273     regsub -- {index.h?tml$} $url {} that
01274 	::if {[string compare $this $that] == 0} {
01275         append html "$s$label"
01276     } else {
01277         append html "$s<a href=\"$url\">$label</a>"
01278     }
01279     ::set s $sep
01280     }
01281     return $html
01282 }
01283 
01284 # ::html::minorList
01285 #
01286 #   Create a list of links given a list of label, URL pairs.
01287 #   If the URL is the current page, it is not highlighted.
01288 #
01289 #       Based on html::minorMenu
01290 #
01291 # Arguments:
01292 #
01293 #   list    List that alternates label, url, label, url
01294 #       ordered Boolean flag to choose between ordered and
01295 #               unordered lists. Defaults to 0, i.e. unordered.
01296 #
01297 # Results:
01298 #   A <ul><li><a...><\li>.....<\ul> fragment
01299 #    or a <ol><li><a...><\li>.....<\ol> fragment
01300 
01301 proc ::html::minorList {list {ordered 0}} {
01302     ::set s ""
01303     ::set html ""
01304     ::if { $ordered } {
01305     append html [openTag ol]
01306     } else {
01307     append html [openTag ul]
01308     }
01309     regsub -- {index.h?tml$} [ncgi::urlStub] {} this
01310     ::foreach {label url} $list {
01311     append html [openTag li]
01312     regsub -- {index.h?tml$} $url {} that
01313 	::if {[string compare $this $that] == 0} {
01314         append html "$s$label"
01315     } else {
01316         append html "$s<a href=\"$url\">$label</a>"
01317     }
01318     append html [closeTag]
01319     append html \n
01320     }
01321     append html [closeTag]
01322     return $html
01323 }
01324 
01325 # ::html::extractParam
01326 #
01327 #   Extract a value from parameter list (this needs a re-do)
01328 #
01329 # Arguments:
01330 #   param   A parameter list.  It should alredy have been processed to
01331 #       remove any entity references
01332 #   key     The parameter name
01333 #   varName The variable to put the value into (use key as default)
01334 #
01335 # Results:
01336 #   returns "1" if the keyword is found, "0" otherwise
01337 
01338 proc ::html::extractParam {param key {varName ""}} {
01339     ::if {$varName == ""} {
01340     upvar $key result
01341     } else {
01342     upvar $varName result
01343     }
01344     ::set ws " \t\n\r"
01345  
01346     # look for name=value combinations.  Either (') or (") are valid delimeters
01347     ::if {
01348       [regsub -nocase [format {.*%s[%s]*=[%s]*"([^"]*).*} $key $ws $ws] $param {\1} value] ||
01349       [regsub -nocase [format {.*%s[%s]*=[%s]*'([^']*).*} $key $ws $ws] $param {\1} value] ||
01350       [regsub -nocase [format {.*%s[%s]*=[%s]*([^%s]+).*} $key $ws $ws $ws] $param {\1} value] } {
01351         ::set result $value
01352         return 1
01353     }
01354 
01355     # now look for valueless names
01356     # I should strip out name=value pairs, so we don't end up with "name"
01357     # inside the "value" part of some other key word - some day
01358     
01359     ::set bad \[^a-zA-Z\]+
01360     ::if {[regexp -nocase  "$bad$key$bad" -$param-]} {
01361     return 1
01362     } else {
01363     return 0
01364     }
01365 }
01366 
01367 # ::html::urlParent --
01368 #   This is like "file dirname", but doesn't screw with the slashes
01369 #       (file dirname will collapse // into /)
01370 #
01371 # Arguments:
01372 #   url The URL
01373 #
01374 # Results:
01375 #   The parent directory of the URL.
01376 
01377 proc ::html::urlParent {url} {
01378     ::set url [string trimright $url /]
01379     regsub -- {[^/]+$} $url {} url
01380     return $url
01381 }
01382 
01383 # ::html::html_entities --
01384 #   Replaces all special characters in the text with their
01385 #   entities.
01386 #
01387 # Arguments:
01388 #   s   The near-HTML text
01389 #
01390 # Results:
01391 #   The text with entities in place of specials characters.
01392 
01393 proc ::html::html_entities {s} {
01394     variable entities
01395     return [string map $entities $s]
01396 }
01397 
01398 # ::html::nl2br --
01399 #   Replaces all line-endings in the text with <br> tags.
01400 #
01401 # Arguments:
01402 #   s   The near-HTML text
01403 #
01404 # Results:
01405 #   The text with <br> in place of line-endings.
01406 
01407 proc ::html::nl2br {s} {
01408     return [string map [list \n\r <br> \n <br> \r <br>] $s]
01409 }
01410 
01411 # ::html::doctype
01412 #   Create the DOCTYPE tag and tuck it away for usage
01413 #
01414 # Arguments:
01415 #   arg The DOCTYPE you want to declare
01416 #
01417 # Results:
01418 #   HTML for the doctype section
01419 
01420 proc ::html::doctype {arg} {
01421     variable doctypes
01422     set code [string toupper $arg]
01423     if {![info exists doctypes($code)]} {
01424     return -code error "Unknown doctype \"$arg\""
01425     }
01426     return $doctypes($code)
01427 }
01428 
01429 namespace eval ::html {
01430     variable  doctypes
01431     array set doctypes {
01432     HTML32   {<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">}
01433     HTML40   {<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">}
01434     HTML40T  {<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">}
01435     HTML40F  {<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN" "http://www.w3.org/TR/REC-html40/frameset.dtd">}
01436     HTML401  {<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">}
01437     HTML401T {<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">}
01438     HTML401F {<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">}
01439     XHTML10S {<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">}
01440     XHTML10T {<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">}
01441     XHTML10F {<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">}
01442     XHTML11  {<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">}
01443     XHTMLB   {<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">}
01444     }
01445 }
01446 
01447 # ::html::css
01448 #   Create the text/css tag and tuck it away for usage
01449 #
01450 # Arguments:
01451 #   href    The location of the css file to include the filename and path
01452 #
01453 # Results:
01454 #   HTML for the  section
01455 
01456 proc ::html::css {href} {
01457     variable page
01458     set page(css) \
01459     "<link rel=\"stylesheet\" type=\"text/css\" href=\"[quoteFormValue $href]\">\n"
01460     return
01461 }
01462 
01463 # ::html::js
01464 #   Create the text/javascript tag and tuck it away for usage
01465 #
01466 # Arguments:
01467 #   href    The location of the javascript file to include the filename and path
01468 #
01469 # Results:
01470 #   HTML for the  section
01471 
01472 proc ::html::js {href} {
01473     variable page
01474     set page(js) \
01475     "<script language=\"javascript\" type=\"text/javascript\" src=\"[quoteFormValue $href]\"></script>\n"
01476     return
01477 }
01478 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1