#
# l2x processing file for HTML
#
# Environments \begin{foo} .. \end{foo} are handled by the
#    'begin' and 'end' proc's. cmdlist should contain args=1.
#
#  command name     args opt. proc_name do_not_expand
set cmdlist {
  {@writefile        2}
  {abstract}
  {appendix}
  {addtocounter      2 0 NoOp}
  {addtolength       2 0 NoOp}
  {AA}
  {aa}
  {AE}
  {ae}
  {author            1}
  {begin             1 0 begin r}
  {bf                0 0 "Property b b"}
  {bibitem           1 1}
  {bibliography      1}
  {c                 1}
  {caption           1 1}
  {centerline        0 0 1}
  {chapter           1 1 "Section 1"}
  {chapter*          1 0 "Section 1"}
  {cite              1 1}
  {cite*             1 1}
  {clearpage         0 0 NoOp}
  {cline             1}
  {contentsline      3}
  {copyright}
  {dag               0 0 "UnknownCmd dag"}
  {date              1}
  {ddag              0 0 "UnknownCmd ddag"}
  {deflist           2 1}
  {description       1 0}
  {displaymath       1}
  {document          1 0}
  {documentclass     1 1}
  {documentstyle     1 1}
  {em                0 0 "Property em em"}
  {end               1}
  {equation          1}
  {eqnarray          1}
  {eqnarray*         1}
  {fbox              1 0 "UnknownCmd fbox"}
  {figure            1 1}
  {footnote          1}
  {footnotesize      0 0 "Property {font size=1} font"}
  {framebox          2 1 "UnknownCmd framebox"}
  {hfill             0 0 NoOp}
  {hline             0 0 NoOp}
  {hspace            1 0 NoOp}
  {huge              0 0 "Property {font size=7} font"}
  {Huge              0 0 "Property {font size=7} font"}
  {include           1}
  {includeonly       1}
  {input             1}
  {it                0 0 "Property i i"}
  {item              0 1}
  {l}
  {L}
  {label             1}
  {LARGE             0 0 "Property {font size=6} font"}
  {Large             0 0 "Property {font size=5} font"}
  {large             0 0 "Property {font size=4} font"}
  {LaTeX}
  {ldots}
  {linebreak         0 1 NoOp}
  {lquote}
  {maketitle}
  {math              1}
  {mbox              1 0 ReturnArg}
  {minipage          2 1 NoOp}
  {multicolumn       3 0}
  {newcommand        2 1 newcommand e}
  {newlength         1 0 NoOp}
  {newsavebox        1 0 NoOp}
  {newlabel          2 0 newlabel   e}
  {newpage           0 0 NoOp}
  {nolinebreak       0 1 NoOp}
  {nopagebreak       0 1 NoOp}
  {normalsize        0 0 "Property {font size=3} font"}
  {numberline        1 0 ReturnArg}
  {O}
  {o}
  {OE}
  {oe}
  {P                 0 0 UnknownCmd P}
  {pagebreak         0 1 NoOp}
  {pagestyle         1 0 NoOp}
  {paragraph         1 1 "Section 5"}
  {paragraph*        1 0 "Section 5"}
  {parbox            1 2 NoOp}
  {part              1 1 "Section 0"}
  {part*             1 0 "Section 0"}
  {picture           1}
  {pounds            0 0 "UnknownCmd pounds"}
  {quotation         1 0}
  {quote             1 0}
  {ref               1 0}
  {relax             0 0 NoOp}
  {rm                0 0 NoOp}
  {rquote}
  {S                 0 0 "UnknownCmd S"} 
  {samepage          0 0 NoOp}
  {savebox           3 2 NoOp}
  {sbox              2 0 NoOp}
  {sc                0 0 NoOp}
  {scriptsize        0 0 "Property {font size=1} font"}
  {section           1 1 "Section 2"}
  {section*          1 1 "Section 2"}
  {setcounter        2 0 NoOp}
  {setlength         2 0 NoOp}
  {settowidth        2 0 NoOp}
  {sf                0 0 NoOp}
  {sloppy            0 0 NoOp}
  {sloppypar         1 0 NoOp}
  {small             0 0 "Property {font size=2} font"}
  {ss}
  {subparagraph      1 1 "Section 6"}
  {subparagraph*     1 0 "Section 6"}
  {subsection        1 1 "Section 3"}
  {subsection*       1 0 "Section 3"}
  {subsubsection     1 1 "Section 4"}
  {subsubsection*    1 0 "Section 4"}
  {tabbing           1}
  {table             1 1}
  {tableofcontents}
  {tabular           2 1}
  {thanks            1}
  {thebibliography   2}
  {tiny              0 0 "Property {font size=1} font"}
  {title             1}
  {titlepage         1}
  {today}
  {tt                0 0 "Property tt tt"}
  {usebox            1 0 NoOp}
  {usepackage        1 1}
  {verb              1}
  {verbatim}
  {verse             1}
  {vspace            1 0 NoOp}
  {"\\["}
  {"("}
  {\\                0 1 double_backslash}
  {\"                1 0 umlaut}
  {'                 1 0 acute}
  {"^"               1 0 circ}
  {`                 1 0 grave}
  {                  1 0 cedil}
  {"~"               1 0 tilde}
  {" "               0 0 space}
  {&                 0 0 amp}
  {%                 0 0 percent}
  {"\#"              0 0 hash}
  {\$                0 0 dollar}
  {"\{"              0 0 brace_left}
  {"\}"              0 0 brace_right}
  {_}
}

foreach e $cmdlist {
  parser_init [lindex $e 0] [lindex $e 1] \
              [lindex $e 2] [lindex $e 3] [lindex $e 4]
}

# depth up to which output should be split (-1: don't, 0: parts, 1:
# chapter, 2: section, ...)
set split_depth 3

# directory containing navigation icons
set icons "/icons"

set contents {}
set style_dir $env(L2X)

# row format
set tabular(rows) {}
# tabular is part of table environment, possibly with caption
set tabular(table) 0
# current column counter (0..)
set tabular(col) 0
# current caption
set tabular(caption) ""

# current figure caption
set figure(caption) ""

# if ToC exists, index into list
set toc {}
set tableofcontents -1

# file descriptor for equations, etc.
set image_file 0
# file for footnotes
set footnote_file 0
# file and directory to use; if none given, use current
if {$argv != ""} {
  set dir [file rootname ./$argv]
  catch {exec mkdir $dir}
  set file [file rootname [lindex $argv 0]]
} else {
  set dir .
  set file -
}

# footer at each page
set footer "<br><hr>Henning Schulzrinne"

# lowest sectioning level; 99: none
set min_level 99

#
# generic routines
#
# call environment with 'begin' or 'end'
proc begin {type opt cmd {arg ""}} {
  eval $cmd begin "{$opt}" $arg
}

proc end {type opt cmd} {
  eval $cmd end $opt
}

#
# Handles unknown command by passing it to LaTeX for evaluation.
#
proc UnknownCmd {cmd type {opt ""} args} {
  set cmd "\\$cmd"
  foreach arg $args {
    set cmd "${cmd}\{[string trimleft $arg]\}"
  }
  puts stderr "unknown type=$type opt=$opt args=$args cmd=$cmd"
  return [mathematics $type $cmd]
}

proc NoOp {type args} {
  return ""
}

proc ReturnArg {type opt arg} {
  return $arg
}

# specific routines
# commands are invoked with command type (command, begin, end)
#   and optional and fixed arguments
set authors ""
set title   ""
set llevel     0

foreach e {footnote equation} {
  set counter($e) 0
}

# counters for parts (0), chapters (1), sections (2), subsections (3),
#   subsubsection (4), paragraphs (5), subparagraphs (6), table (7),
#   figure (8)
proc ResetCounters {} {
  global counter

  for {set i 0} {$i < 9} {incr i} {
    set counter($i) 0
  }
}

# increment counter of 'level', reset all lower counters
# return new counter string
proc IncrCounter {level} {
  global counter

  incr counter($level)
  for {set i [expr $level+1]} {$i < 7} {incr i} {
    set counter($i) 0
  }
  return "$counter(0).$counter(1).$counter(2).$counter(3).$counter(4).$counter(5).$counter(6)"
}

proc ShowCounter {} {
  global counter
  return "$counter(0).$counter(1).$counter(2).$counter(3).$counter(4).$counter(5).$counter(6)"
}

proc @writefile {type opt file what} {
  return ""
}

proc AA {type opt} {
  format "%c" 197
}

proc aa {type opt} {
  format "%c" 229
}

proc abstract {type {opt ""}} {
  if {$type == "begin"} {
    return "<abstract><H3>Abstract</H3>"
  } else {
    return "</abstract>"
  }
}

proc AE {type} {
  format "%c" 198 
}

proc ae {type} {
  format "%c" 230
}

proc acute {type opt arg} {
  mapping {A 193 E 201 I 205 O 211 U 218 Y 221 \
           a 225 e 233 i 237 o 243 u 250 y 253} $arg
}

proc amp {type {opt ""}} {
  return "&amp;"
}

#
# In LaTeX, & is a column separator; HTML only knows column
# containers. Since we can't backspace over the column, we have
# every \\ start a new column and hope that the LaTeX doesn't have
# \\ in the last row.
# 
proc ampersand {} {
  global tabular

  if {$tabular(rows) != {}} {
    set tabular(end_of_row) 0
    incr tabular(col)
    return "</td><td [lindex $tabular(rows) $tabular(col)]>"
  } else {
    return &
  }
}

proc appendix {type} {
  return ""
}

proc author {type opt arg} {
  global authors
  set authors $arg
  return ""
}

proc brace_left {type opt} {
  return "\{"
}

proc brace_right {type opt} {
  return "\}"
}

#
# Set caption if in figure.
# If after tabular, close <table>.
#
proc caption {type opt arg} {
  global tabular figure

  # within table
  if {$tabular(table)} {
    set tabular(caption) $arg
	# after tabular environment -> close table
    if {$tabular(rows) != {}} {
      set tabular(rows) {}
      return "<caption>$tabular(caption)</caption></table>"
    }
  } else {
    set figure(caption) $arg
    return ""
  }
}

proc cedil {type opt arg} {
  mapping {C 199 c 231} $arg
}

#
# We also close any open tables since <CENTER> can't be part of <TABLE>
#
proc center {type {opt ""} {arg ""}} {
  global tabular

  if {$type == "begin"} {
    return "<center>"
  } else {
    set s ""
    if {$tabular(rows) != {}} {
      set tabular(rows) {}
      set s "</table>"
    }
    return "$s</center>"
  }
}

proc circ {type opt arg} {
  mapping {A 194 E 202 I 206 O 212 U 219 \
           a 226 e 234 i 238 o 244 u 251} $arg
}

proc cite {type opt arg} {
  return "<a href=\"?$arg\">$arg</a>"
}

proc contentsline {type opt level text page} {
  global contents min_level

  set level [lsearch \
    {part chapter section subsection subsubsection paragraph
     subparagraph table figure} \
    $level]
  if {$level < $min_level} {set min_level $level}
  lappend contents [list $level [IncrCounter $level] $text]
  return ""
}

proc copyright {type {opt ""}} {
  return "&copy;"
}


proc dash {c} {
  if {$c == 1} {return "-"}
  return "--"
}

proc date {type opt {arg ""}} {
  global date
  set date $arg
  return ""
}

proc deflist {type {opt ""} args} {
  global llevel ltype

  set v ""
  if {$type == "begin"} {
    incr llevel
    set ltype($llevel) description
    set v "<dl>"
  } else {
    set v "</dl>"
    incr llevel -1
  }
  return $v
}

proc description {type {opt ""}} {
  global llevel ltype

  set v ""
  if {$type == "begin"} {
    incr llevel
    set ltype($llevel) description
    set v "<dl>"
  } else {
    set v "</dl>"
    incr llevel -1
  }
  return $v
}

proc document {type args} {
  global title toc

  # prepend front matter to TOC for splitting
  if {$type == "begin"} {
    set toc [linsert $toc 0 [list -1 0 "$title"]]
  }
  return ""
}

proc documentclass {type opt arg} {
  return ""
}

proc documentstyle {type opt arg} {
  global errorInfo style_dir

  set plist [split $opt ,]
  foreach e $plist {
    if {[catch "source ${e}.tcl" msg]} {
      if {[catch "source ${style_dir}/html/${e}.tcl" msg]} {
      }
    }
  }
  return ""
}

proc dollar {type opt} {
  return "$"
}

#
# A \\ ends and starts a row.
#
proc double_backslash {type opt} {
  global tabular

  if {$tabular(rows) != ""} {
    set tabular(end_of_row) 1
    set tabular(col) 0
    return "</td></tr><tr><td [lindex $tabular(rows) $tabular(col)]>"
  } {
    return "<br>"
  }
}

proc Property {on off args} {
  global prop g
  lappend prop($g) "</$off>"
  return "<$on>"
}

proc enumerate {type {opt ""}} {
  global llevel ltype

  set v ""
  if {$type == "begin"} {
    incr llevel
    set ltype($llevel) itemize
    set v "<ol>"
  } else {
    set v "</ol>"
    incr llevel -1
  }
  return $v
}

proc figure {type {opt ""}} {
  global figure

  if {$type == "begin"} {
    set figure(caption) ""
  } else {
  }
  return ""
}

proc figure* {type {opt ""}} {
  global figure

  if {$type == "begin"} {
    set figure(caption) ""
  } else {
  }
  return ""
}

proc flushleft {type {opt ""}} {
  return ""
}

proc flushright {type {opt ""}} {
  return ""
}

#
# append to footnote file and create link
#
proc footnote {type opt arg} {
  global counter footnote_file title dir icons

  if {$footnote_file == 0} {
    set footnote_file [open "${dir}/footnotes.html" w]
    puts $footnote_file "<HTML><HEAD>\n<TITLE>$title: Footnotes</TITLE></HEAD><BODY>"
  }
  incr counter(footnote)

  puts $footnote_file "<A NAME=\"#F$counter(footnote)\">$arg<hr>"
  return \
"<A HREF=\"footnotes.html#F$counter(footnote)\"><IMG\
ALIGN=BOTTOM ALT=\"footnote\" SRC=\"$icons/foot_motif.gif\"></A>"
}

proc grave {type opt arg} {
  mapping {A 192 E 200 I 204 O 210 U 217 \
           a 224 e 232 i 236 o 242 u 249} $arg
}

proc group {type level} {
  global prop g
  if {$type == "begin"} {
    set g $level
    set prop($g) ""
    return ""
  } else {
    set s ""
    foreach e $prop($g) {
      set s "$s$e"
    }
    return $s
  }
}

proc gt {} {
  return "&gt;"
}

proc hash {type opt} {
  return "#"
}

proc item {type {opt ""}} {
  global llevel ltype

  case $ltype($llevel) in {
    itemize     {return "<li>"}
    enumerate   {return "<li>"}
    description {return "<dt>$opt<dd>"}
  }
}

proc itemize {type {opt ""}} {
  global llevel ltype

  set v ""
  if {$type == "begin"} {
    incr llevel
    set ltype($llevel) itemize
    set v "<ul>"
  } else {
    set v "</ul>"
    incr llevel -1
  }
  return $v
}

proc label {type opt arg} {
  return "<a name=\"$arg\">" 
  return ""
}

proc LARGE {type opt} {
}

proc Large {type opt} {
}

proc large {type opt} {
}

proc LaTeX {type opt} {
  return "LaTeX"
}

proc ldots {type opt} {
  return "..."
}

proc lquote {} {
  return "\""
}

proc lt {} {
  return "&lt;"
}

proc maketitle {type opt {arg ""}} {
  global title authors date
  if {[info exists date] == 0} {
    set date [today "" ""]
  }
  return "<H1>$title</H1>$authors<br>$date<P>"
}

# map character to new character according to list 'm'
proc mapping {m arg} {
  set x [lsearch $m $arg]
  format "%c" [lindex $m [expr $x+1]]
}

#
# \begin{math} \end{math}
proc math {type {equ ""}} {
  if {$type == "begin"} {
    parser_suspend math "\\end{math}"
  } else {
    mathematics math "$equ"
  }
}

# \begin{displaymath} \end{displaymath}
proc displaymath {type {equ ""}} {
  if {$type == "begin"} {
    parser_suspend displaymath "\\end{displaymath}"
  } else {
    mathematics displaymath "$equ"
  }
}

proc equation {type {equ ""}} {
  if {$type == "begin"} {
    parser_suspend equation "\\end{equation}"
  } else {
    mathematics equation "$equ"
  }
}

proc eqnarray {type {equ ""}} {
  if {$type == "begin"} {
    parser_suspend eqnarray "\\end{eqnarray}"
  } else {
    mathematics eqnarray "$equ"
  }
}

proc eqnarray* {type {equ ""}} {
  if {$type == "begin"} {
    parser_suspend eqnarray* "\\end{eqnarray*}"
  } else {
    mathematics eqnarray* "$equ"
  }
}

proc $ {} {
  parser_suspend math "$"
}

proc ( {} {
  parser_suspend math "\\)"
}

proc \[ {type opt} {
  parser_suspend displaymath "\\]"
}

#
# Called for all mathematics (type=math, displaymath, eqnarray)
# Write equation to file and apply latex to it. Also handles unknown
# commands and environments.
#
proc mathematics {type equ} {
  global counter image_file

  if {$type == "begin"} {
    parser_suspend $type "\\end
    return ""
  }

  incr counter(equation)

  # output to temporary file
  if {$image_file == 0} {
    set image_file [open /tmp/l2x-equ.tex w]
    puts $image_file "\\documentclass{article}\\pagestyle{empty}\\begin{document}"
  }

  case $type in {
    "\\("          -
    "\$"           -
    "math"         {set type math; puts $image_file "\$$equ\$"}
    "\\["          -
    "displaymath"  {set type displaymath; puts $image_file "\\begin{displaymath}$equ\\end{displaymath}"}
    "equation"     {puts $image_file "\\begin{equation}$equ\\end{equation}"}
    "eqnarray"     {puts $image_file "\\begin{eqnarray}$equ\\end{eqnarray}"}
    "eqnarray*"    {puts $image_file "\\begin{eqnarray*}$equ\\end{eqnarray*}"}
    "unknown"      -
    "command"      {puts $image_file $equ}
  }
  puts $image_file "\\newpage\n"
  set s ""
  if {[lsearch {displaymath equation eqnarray eqnarray*} $type] >= 0} {set s "<br>"}
  return "$s<img src=\"equ$counter(equation).gif\" alt=\"$equ\">$s"
}

#
# must erase last item <td ...>
#
proc multicolumn {type opt num col item} {
  switch -glob $col {
    l* {set col "align=left"}
    c* {set col "align=center"}
    r* {set col "align=right"}
  }
  return "<td colspan=$num $col>$item"
}

# create a new procedure
proc newcommand {type argc cmd f} {
  global dir

  set cmd [string range $cmd 1 end]
  set out [open "$dir/newcommand" w]
  puts $out "proc $cmd \{" nonewline
  lappend args type opt
  for {set i 1} {$i <= $argc} {incr i} {
    lappend args arg$i
  }
  puts $out "$args\} \{"
  regsub -all {\\} $f {\\\\} f
  puts $out "  set x \"$f\""
  for {set i 1} {$i <= $argc} {incr i} {
    puts $out "  regsub -all \#$i \$x \$arg$i x" 
  }
  puts $out "  return \[parse \$x\]"
  puts $out "\}"
  close $out
  source "$dir/newcommand"
  exec rm "$dir/newcommand"
  parser_init $cmd $argc
  return ""
}

# \newlabel{label}{{1}{9}}
proc newlabel {type opt label sec_pg} {
  return ""
}

proc numberline {type opt arg} {
  return $arg
}

proc O {cmd opt} {
  format "%c" 216
}

proc o {cmd opt} {
  format "%c" 248
}

proc oe {cmd opt} {
  format "%c" 100
}

proc para {} {
  return "<P>"
}

proc percent {cmd opt} {
  return "%"
}

proc quotation {type {opt ""} args} {
  if {$type == "begin"} {
    return "<blockquote>"
  } else {
    return "</blockquote>"
  }
}

proc quote {type {opt ""} args} {
  if {$type == "begin"} {
    return "<blockquote>"
  } else {
    return "</blockquote>"
  }
}

proc ref {type opt arg} {
  return "<a href=\"#$arg\">$arg</a>"
}

proc rquote {} {
  return "\""
}

#
# Generic sectioning command for parts, ..., subparagraphs
#
proc Section {level type opt arg} {
  global split_depth toc min_level

  IncrCounter $level
  # insert formfeed if splitting
  set s ""
  if {$level <= $split_depth} {
    set s "\f"
    lappend toc [list $level [ShowCounter] $arg]
  }
  # keep track of highest sectioning command used
  if {$level < $min_level} {set min_level $level}

  return "$s<A NAME=\"[ShowCounter]\"><H$level>$arg</H$level>"
}

proc space {type opt} {
  return " "
}

proc ss {type} {
  format "%c" 223
}

proc table {type {opt ""}} {
  global tabular

  if {$type == "begin"} {
    set tabular(table) 1
  } else {
    set tabular(table) 0
    set tabular(caption) ""
    # still need to close HTML table
    if {$tabular(rows) != {}} {
      set tabular(rows) {}
      return "</table>"
    }
  }
  return ""
}

proc tableofcontents {type {opt ""}} {
  global contents min_level file split_depth tableofcontents toc

  set CL [expr $min_level-1]
  set node 1
  set s [Section $min_level command "" "Contents"]
  set tableofcontents [expr [llength $toc]-1]
  foreach e $contents {
    set L [lindex $e 0]
    if {$L <= $split_depth} {incr node}

    if {$L > $CL} {
      for {set k $CL} {$k < $L} {incr k} {
        set s "$s<ul>"
      }
      set CL $L
    } elseif {$L < $CL} {
      for {set k $CL} {$k > $L} {incr k -1} {
        set s "$s</ul>"
      }
      set CL $L
    }
    if {$node == 0} {set n ""} {set n $node} 
    set s "$s<li><a href=\"${file}${n}.html#[lindex $e 1]\">[lindex $e 2]</a>"
  }
  for {set k $CL} {$k >= $min_level} {incr k -1} {
    set s "$s</ul>"
  }

  return $s
}

#
# We only handle non-nested tabular environments.
# Column descriptors: l, r, c, | (not p, @)
# If | is present, table is drawn with border.
# Doesn't handle columnspan
#
proc tabular {type {opt ""} {arg ""}} {
  global tabular

  set s ""
  if {$type == "begin"} {
    set border ""
    foreach e [split $arg {}] {
      case $e in {
      l {lappend tabular(rows) "align=left"}
      r {lappend tabular(rows) "align=right"}
      c {lappend tabular(rows) "align=center"}
      | {set border "border"}
      }
    }
    if {$tabular(caption) != ""} {set s "<caption>$tabular(caption)</caption>"}
    return "<table $border>$s<tr><td [lindex $tabular(rows) 0]>"
  } else {
    set s "</td></tr>"
    if {$tabular(table)} {
      return "$s"
    } else {
      set tabular(rows) {}
      set tabular(caption) ""
      return "$s</table>"
    }
  }
}

proc thanks {type opt arg} {
  footnote $type $opt $arg
}

proc tie {} {
  return " "
}

proc tilde {type opt arg} {
  if {$arg == ""} {return "~"}
  mapping {A 195 N 209 O 213 a 227 n 241 o 245} $arg
}

proc title {type opt {arg ""}} {
  global title

  set title $arg
  return ""
}

proc today {type opt} {
  exec date "+%B %e, %Y"
}

proc umlaut {type opt arg} {
  mapping {A 196 O 214 U 220 a 228 o 246 u 252 y 255} $arg
}

# called if command is undefined
proc undefined {cmd} {
  return "\\$cmd"
}

proc usepackage {type opt arg} {
  global errorInfo style_dir

  set plist [split $arg ,]
  foreach e $plist {
    if {[catch "source ./${e}.tcl" msg] && [catch "source ${style_dir}/html/${e}.tcl" msg]} {
      puts stderr "$e: $msg"
    }
  }
  return ""
}

proc verb {type opt arg} {
  parser_suspend verb $arg
}

proc verbatim {type {arg ""}} {
  if {$type == "begin"} {
    parser_suspend verbatim "\\end{verbatim}"
    return "<pre>"
  } elseif {$type == "end"} {
    parser_resume
    return "</pre>"
  } else {
    return $arg
  }
}

proc _ {type opt} {
  return "_"
}

# split into sections and output to files
proc Output {dir file title footer html} {
  global toc split_depth min_level tableofcontents icons

  set node ""
  foreach page [split $html "\f"] {
    set f [open "${dir}/${file}${node}.html" w]
    if {$node == ""} {set node 0}
    set toc_  [lindex $toc $node]
    set level [lindex $toc_ 0]
    puts $f "<html><title>$title: [lindex $toc_ 2]</title></head><body>"

    puts stdout "Part $node: [lindex $toc_ 2]"

    #
    # navigation panel
    #
    puts $f "<br><hr>"

    # Next: sequential (regardless of level)
    set j [expr $node+1]
    set toc_j [lindex $toc $j]
    if {$toc_j != ""} {
      puts $f "<a href=\"${file}$j.html#[lindex $toc_j 1]\">\
<img alt=\"next\" align=bottom src=\"$icons/next_motif.gif\"></a>"
    } else {
      puts $f "<img alt=\"next\" align=bottom src=\"$icons/next_motif_gr.gif\">"
    }

    # Up: prior heading with smaller level value
    set up -1
    for {set j [expr $node-1]} {[lindex $toc $j] != ""} {incr j -1} {
      set toc_j [lindex $toc $j]
      if {[lindex $toc_j 0] < $level} {
        set up $j
        if {$up == 0} {set n ""} {set n $up}
        puts $f "<a href=\"${file}${n}.html#[lindex $toc_j 1]\">\
<img alt=\"up\" align=bottom src=\"$icons/up_motif.gif\"></a>"
        break
      }
    }
    if {$up == -1} {
      puts $f "<img alt=\"up\" align=bottom src=\"$icons/up_motif_gr.gif\">"
    }

    # Previous: prior heading 
    set previous [expr $node-1]
    set toc_j [lindex $toc $previous]
    if {$toc_j != "" && $previous >= 0} {
      if {$previous == 0} {set n ""} {set n $previous}
      puts $f "<a href=\"${file}${n}.html#[lindex $toc_j 1]\">\
<img alt=\"previous\" align=bottom src=\"$icons/previous_motif.gif\"></a>"
    } else {
      set previous -1
    }

    # Contents
    if {$tableofcontents > 0} {
      puts $f "<a href=><img alt=\"contents\" align=bottom src=\"$icons/contents_mofi.gif\"></a>"
    }

    #
    # textual links
    #
    puts $f "<br>"
    # Next
    set j [expr $node+1]
    set toc_j [lindex $toc $j]
    if {$toc_j != ""} {
      puts $f "<b>Next:</b> <a href=\"${file}$j.html#[lindex $toc_j 1]\">\
        [lindex $toc_j 2]</a>"
    }

    # Up
    if {$up >= 0} {
      set toc_j [lindex $toc $up]
      if {$up == 0} {set n ""} {set n $up}
      puts $f "<b>Up:</b> <a href=\"${file}${n}.html#[lindex $toc_j 1]\">\
        [lindex $toc_j 2]</a>"
    }

    # Previous
    if {$previous >= 0} {
      set toc_j [lindex $toc $previous]
      if {$previous == 0} {set n ""} {set n $previous}
      puts $f "<b>Previous:</b> <a href=\"${file}${n}.html#[lindex $toc_j 1]\">\
        [lindex $toc_j 2]</a>"
    }
    puts $f "<hr>"

    # contents

    # for frontmatter, show links to top-level sections
    if {$level == -1 && $min_level < 99} {
      puts $f "<hr><ul>"
      for {set j [expr $node+1]} {[lindex $toc $j] != ""} {incr j} {
        set toc_j [lindex $toc $j]
        set L [lindex $toc_j 0]
        if {$L == $min_level} {
          if {$j == 0} {set n ""} {set n $j} 
          puts $f "<li><a href=\"${file}$n.html#[lindex $toc_j 1]\">[lindex $toc_j 2]</a>"
        }
      }
      puts $f "</ul><hr>"
    }

    # for others, show tree underneath current
    if {$level < $split_depth && $level >= 0} {
      set s ""
      set CL $level
      for {set j [expr $node+1]} {[lindex $toc $j] != ""} {incr j} {
        set e [lindex $toc $j]
        set L [lindex $e 0]
        if {$L == $level} break
        if {$s == ""} {
          set s "<hr>"
        }
        if {$L > $CL} {
          for {set k $CL} {$k < $L} {incr k} {
            set s "$s<ul>"
          }
          set CL $L
        } elseif {$L < $CL} {
          for {set k $CL} {$k > $L} {incr k -1} {
            set s "$s</ul>"
          }
          set CL $L
        }
        set s "$s<li><a href=\"${file}${j}.html#[lindex $e 1]\">[lindex $e 2]</a>"
      }
      for {set k $CL} {$k > $level} {incr k -1} {
        set s "$s</ul>"
      }
      if {$s != ""} {
        puts $f "$s<hr>"
      }
    }

    # body of page
    puts $f $page 

    # footer
    puts $f "$footer</body></html>"
    close $f
    incr node
  }
}

# include auxiliary file (.aux) if available
ResetCounters
catch {include command {} ${file}.aux} msg
ResetCounters

# fix up missing look-ahead parsing:
# \multicolumn{}: <td ...><td colspan -> <td colspan
set html [include command {} ${file}.tex]
regsub {<td[a-z =]*><td colspan} $html "<td colspan" html

# convert equations, etc. to GIF files using LaTeX and dvips
# Doing it once preserves equation numbering (assuming the LaTeX file
# didn't mess with it or used per-section numbering) and saves time.
if {$image_file != 0} {
  puts $image_file "\\end{document}"
  close $image_file
  exec latex /tmp/l2x-equ.tex
  # force dvips to split it into one-page sections
  catch {exec dvips -S 1 -i l2x-equ}
  # convert these one-by-one into transparent GIF files
  set e 0
  catch {exec rm -f equ*.gif}
  foreach f [lsort [glob {l2x-equ.0[0-9][0-9]}]] {
    incr e
    exec mv $f $f.ps
    catch {exec pstogif -transparent "#ffffff" -out ${dir}/equ${e}.gif $f.ps} msg
    puts "Converting $f.ps: $msg"
  }
  catch {exec rm -f /tmp/l2x-equ.tex l2x-equ.*}
}

# close footnote file
if {$footnote_file != 0} {
  puts $footnote_file "</BODY></HTML>"
  close $footnote_file
}

Output $dir $file $title $footer $html
