# Hey, Emacs, this is CoST (-*- tcl -*-) script for TEI Lite to HTML transformation.
#
# $Id: script,v 1.152 2003/08/22 08:25:00 tobotras Exp $
#
#   <div type='Abstract'>    <body>,    <front>.  ?
#
#   <byLine> .      .

require TEItools.tcl
require Simple.tcl
require textutil.tcl
require TEItoolsEPN.tcl
require TEItoolsHTML.tcl

if { ![info exist TEItools_toc_depth_value] } {
    set TEItools_toc_depth_value 3
}

TEItoolsSetup "html"

# Globals
set baseFileName $argv
set silence 0
set endNotesPass 0
set endNotesCount 0
set insideEndNode 0

environment outSpec fileHandle [open ${baseFileName}.html "w"]
if { [useUnicode] } { fconfigure [outSpec get fileHandle] -encoding identity }

rename output {}
proc output { text } {
    global silence
    if { $silence == 0 } {
	puts [outSpec get fileHandle] $text nonewline
    }
}

#FIXME!! This is REALLY SHORT of error checking
proc processTeXfile { texFile gifFile } {
    puts -nonewline stderr "\[$texFile"
    debug "latex $texFile"
    exec latex $texFile
    set EPSfile "tex2gif.[pid].eps"
    debug "dvips -E $texFile -o $EPSfile"
    catch {exec dvips -E $texFile -o $EPSfile}
    debug "convert -density 150x150 $EPSfile $gifFile"
    exec convert -density 150x150 $EPSfile $gifFile
    file delete $EPSfile
    debug "convert done"
    #
    # Make transparent GIF. Looks very ugly 'cause of antialiasing.
    # So better let's keep antialiasing and let background be white.
    #
    #    exec giftrans -t \#FFFFFF -o tex2gif.[pid].gif $gifFile
    #    file delete $gifFile
    #    file rename tex2gif.[pid].gif $gifFile
    #
    puts -nonewline stderr "\]" 
    return
}

proc appendprop { name value } {
    set oldValue [query propval $name]
    append oldValue $value
    setprop $name $oldValue
}

proc openAlign { { defRend "" } } {
    set rendVal [attVal REND]
    if { $rendVal == "" } {
	set rendVal $defRend
    }

    foreach re [split $rendVal " ,"] {
	switch $re {
	    "left" {
		return " ALIGN=\"left\""
	    }
	    "right" {
		return " ALIGN=\"right\""
	    }
	    "center" {
		return " ALIGN=\"center\""
	    }
	    "justify" {
		return " ALIGN=\"justify\""
	    }
	    "middle" {
		return " ALIGN='middle'"
	    }
	}
    }
    return
}

proc endNotes {} {
    global endNotesText endNotesCount endNotesPass
    if { $endNotesCount == 0 } {
	return
    }

    debug "Generating end notes"
    
    set endNotesPass 1
    set opened 0
    foreachNode docroot descendant element NOTE {
	if { $opened == 0 } {
	    set opened 1
	    openDivision "notes"
	    output "
<BR><HR><BR>
<CENTER><STRONG>[localize endNotes]</STRONG></CENTER>
<DIV>
"
	}
	set place [attVal PLACE]
	debug "Found note, place='$place', content=`[content]'"
	if { "$place" == "end" || "$place" == "foot" || "$place" == "side" \
	     || "$place" == "unspecified" } {
	    translateHandler
	    incr endNotesCount
	}
    }
    output "\n</DIV>\n"
    closeDivision
    set endNotesPass 0
}

proc endNotePrefix {} {
    global endNotesPass endNotesCount
    set anchor [AddrToName [query address]]

    debug "endNotePrefix: $endNotesPass, `[content]'"
    
    if { $endNotesPass == 0 } {
	incr endNotesCount
	setprop counter $endNotesCount
	return "<A NAME='NOTE_${anchor}'><[Link] HREF='[DivisionFileName notes]#${anchor}'>\[${endNotesCount}\]</A></A>"
    }

    return "<[elt P]><[Link] HREF='[DivisionFileName [query address]]#NOTE_${anchor}'>\[[query propval counter]\]</A> <A NAME='${anchor}'>"
}

proc endNoteSuffix {} {
    global endNotesPass
    if { $endNotesPass == 0 } {
	return
    } else {
	return "</A>\n"
    }
}

proc endNoteCFilter { text } {
    global endNotesPass
    if { $endNotesPass == 0 } {
	return
    }
    return [textCdataFilter $text]
}

proc endNoteSFilter { text } {
    global endNotesPass
    if { $endNotesPass == 0 } {
	return
    }
    return [textSdataFilter $text]
}

proc openFigHead {} {
    return "<br><[elt STRONG]><FONT SIZE='+1'>"
}

proc closeFigHead {} {
    return "</A></FONT></STRONG>\n"
}

proc openRend { { defaultRend "" } } {
    set rend {}

    set rendVal [attVal REND]
    if { $rendVal == "" } {
	set rendVal $defaultRend
    }

    foreach re [split $rendVal " ,"] {
	switch -regexp $re {
	    "underline" {
		appendprop highlightState "<U>"
		prepend rend "<[elt U]>"
	    }
	    "(super)|(superscript)" {
		appendprop highlightState "<SUP>"
		prepend rend "<[elt SUP]>"
	    }
	    "(super)|(superscript)" {
		appendprop highlightState "<SUB>"
		prepend rend "<[elt SUB]>"
	    }
	    "italic" {
		appendprop highlightState "<I>"
		prepend rend "<[elt I]>"
	    }
	    "small" {
		appendprop highlightState "<SMALL>"
		prepend rend "<[elt SMALL]>"
	    }
	    "large" {
		appendprop highlightState "<BIG>"
		prepend rend "<[elt BIG]>"
	    }
	    "normal" {
		#FIXME!!
	    }
	    "slanted" {
		appendprop highlightState "<I>"
		prepend rend "<[elt I]>"
	    }
	    "(bold)|(smallcap)" {
		appendprop highlightState "<STRONG>"
		prepend rend "<[elt STRONG]>"
	    }
	    "typewriter" {
		appendprop highlightState "<TT>"
		prepend rend "<[elt TT]>"
	    }
	    "(block)|(display)" {
		appendprop highlightState "<BLOCKQUOTE>"
		prepend rend "<[elt BLOCKQUOTE]>"
	    }
	    "(quoted)|(inline)" {
		appendprop highlightState [rightQuote]
		prepend rend [leftQuote]
	    }
	    "(left)|(right)|(center)|(centered)|(justify)|(justified)|(sans)" {
		# do nothing
	    }
	    default {
		appendprop highlightState "<FONT>"
		prepend rend "<[elt FONT] COLOR='Red'>"
	    }
	}
    }
    return $rend
}

proc closeRend {} {
    set ret [query propval highlightState]
    unsetprop highlightState
    regsub -all "<" $ret "</" rett
    return $rett
}

proc speaker {} {
    withNode child element SPEAKER {
	return
    }
    set who [attVal WHO]
    if { "$who" == "" } {
	Error "Don't know who speaks"
	return
    }
    withNode docroot descendant element NAME withattval ID $who {
	return "<[elt STRONG]>[content]. </STRONG>"
    }
    Error "No <NAME ID='$who'>"
}

proc Link {} {
    return "A"
}

proc TOCfileName {} {
    return
}

proc shouldBeSplitOff {} {
    global endNotesPass
    if { $endNotesPass == 1 && "[regexp DIV(\[0-9\])? [query gi]]" == 0 } {
	return 1
    }
    
    set type [typeVal]
    global splitNames
    if { $type == $splitNames([splitLevel]) } {
	return 1
    }

    return 0
}

proc TEItools_PI_nextdivname { name } {
    global TEItoolsNextDivName
    set TEItoolsNextDivName $name
}

proc openDivision { address } {

    global baseFileName splitNames 

    puts stderr . nonewline

    checkDivType
    
    set type [typeVal]
    if { ![regexp DIV(\[0-9\]) [query gi] dummy divLevel] } {
	set divLevel 0
    }

    if { ( [splitLevel] > 0 && \
	     ( ( "[query gi]" == "DIV" && \
		     [lsearch $splitNames([splitLevel]) [typeVal]] != -1 ) \
		   || $divLevel <= [splitLevel] ) \
	       || [shouldBeSplitOff] ) \
	     && ![firstDivInDiv] } {
	global TEItoolsNextDivName
	if { [info exist TEItoolsNextDivName] } {
	    set newFileName $TEItoolsNextDivName
	    unset TEItoolsNextDivName
	} else {
	    set newFileName "${baseFileName}-[AddrToName $address].html"
	}
	debug "opening new HTML file `${newFileName}'"
	outSpec save fileHandle \
	    [open $newFileName "w"] \
	    toBeClosed "true"
	if { [useUnicode] } {
	    fconfigure [outSpec get fileHandle] -encoding identity
	}
	output "[HtmlHeader][HtmlTitle]</HEAD><[elt BODY]>[FileHeader]"
    } else {
	outSpec save toBeClosed "false"
    }
}

proc HtmlTitle {} {
    withNode child element HEAD {
	return "<TITLE>[filteredContent]</TITLE>"
    }
    return "part [query address]"
}

proc closeDivision {} {
    if { "[outSpec get toBeClosed]" == "true" } {
	output "[FileFooter][HtmlFooter]"
	close [outSpec get fileHandle]
    }
    outSpec restore
}

proc ThreeButtons {} {
    global baseFileName
    set ret {}

    #       type
    #    set ourType [typeVal]
    # withattval TYPE $ourType
    withNode prev element [query gi] {
	append ret "<[Link] [DivHref [query address]]>[localize prev]</A>"
    }

    append ret [TOCref]

    # 
    #withattval TYPE $ourType 


    #
    # splitlevel ==  level + 1
    #
    #    >2 
    #
    # next     next element,
    #     child next element  gi == DIV[ + 1]. ?
    set destination { next element [query gi] }
    set weAreDiv [regexp "DIV(\[0-9\])?" [query gi] dummy divLevel]
    if { $weAreDiv } {
	set nextLevel [expr $divLevel + 1]
	if { [countq child element "DIV${nextLevel}"] > 1 \
		 && [splitLevel] == $nextLevel } {
	    set destination {child next element "DIV${nextLevel}" next}
	}
	# 
	# splitlevel ==  level
	#
	#     
	#
	# next       
	if { [splitLevel] == $divLevel \
		 && [countq next element [query gi]] == 0 } {
	    set destination {ancestor next}
	}
	eval withNode $destination {{
	    append ret "&nbsp;<[Link] [DivHref [query address]]>[localize next]</A>"
	}}
    }
    return $ret
}

proc TOCref {} {
    return "&nbsp;
<[TOClink] HREF=\"[TOCfileName]\#__TOC\">[localize contents]</A>
"
}

proc TOClink {} {
    return "A"
}

proc FileHeader {} {
    return "[ThreeButtons]<HR>"
}

proc FileFooter {} {
    return "<HR>[ThreeButtons]"
}

proc divgenStart {} {
}

proc divgenEnd {} {
}

proc divGen {} {
    set type [typeVal]
    if { "[info commands generate$type]" == "generate$type" } {
	pushMode generate$type
	withNode docroot {
	    translateHandler
	}
	popMode
    } else {
	Error "Unknown divGen type: $type"
    }
    return
}

proc doneTranslation {} {
    return "\n"
}

specification generateindex {
    {element TEI.2} {
	prefix		"\n<CENTER><A NAME='__IDX'><H1>[localize index]</H1></A></CENTER>\n"
	suffix		[doneTranslation]
    }
    {element INDEX} {
	prefix		"[formatIndex]<br>"
    }
    {el} {
	cdataFilter	null
	sdataFilter	null
    }
}

proc formatIndex {} {
    set format [query attval LEVEL1]
    set level2 [query attval LEVEL2]
    set prefix	""
    if { "$level2" != "" } {
	set format $level2
	set prefix "&nbsp;&nbsp;&nbsp;&nbsp;"
    }
    set hyperlink "<[Link] HREF='[DivisionFileName [query address]]#IDX_[AddrToName [query address]]'>[textSdataFilter $format]</A>"
    
    return "${prefix}${hyperlink}"
}

specification generatelot {
    {element TEI.2} {
	prefix		"\n<CENTER><A NAME='__LOT'><H1>[localize listoftables]</H1></A></CENTER>\n<OL>\n"
	suffix		"\n</OL>\n"
    }
    {element HEAD in TABLE} {
	prefix		"<LI><[Link] [DivHref [query parent address]]>"
	suffix		"</A></LI>\n"
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element Q in HEAD in TABLE} {
	prefix		[openQuote]
	suffix		[closeRend]
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element LB within HEAD in TABLE} {
	suffix		"\n<BR>\n"
    }
    {el} {
	cdataFilter	null
	sdataFilter	null
    }
}

specification generatelof {
    {element TEI.2} {
	prefix		"\n<CENTER><A NAME='__LOT'><H1>[localize listoffigures]</H1></A></CENTER>\n<OL>\n"
	suffix		"\n</OL>\n"
    }
    {element HEAD in FIGURE} {
	prefix		"<LI><[Link] [DivHref [query address]]>"
	suffix		"</A></LI>\n"
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element Q in HEAD in FIGURE} {
	prefix		[openQuote]
	suffix		[closeRend]
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element LB within HEAD in FIGURE} {
	suffix		"\n<BR>\n"
    }
    {element KW in HEAD in FIGURE} {
	prefix		"[openRend {typewriter,bold}]"
	suffix		"[closeRend]"
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {el} {
	cdataFilter	null
	sdataFilter	null
    }
}

specification generatetoc {
    {element TEI.2} {
	prefix		"
<CENTER><A NAME=\"__TOC\"><H1>[localize contents]</H1></A></CENTER>
"
    }
    {element HEAD in DIV4} {
	prefix		"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<[Link] [DivHref [query parent address]]>"
	suffix		"</A><BR>\n"
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element HEAD in DIV in DIV in DIV in DIV} {
	prefix		"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<[Link] [DivHref [query parent address]]>"
	suffix		"</A><BR>\n"
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element HEAD in DIV3} {
	prefix		"&nbsp;&nbsp;&nbsp;&nbsp;<[Link] [DivHref [query parent address]]>"
	suffix		"</A><BR>\n"
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element HEAD in DIV in DIV in DIV} {
	prefix		"&nbsp;&nbsp;&nbsp;&nbsp;<[Link] [DivHref [query parent address]]>"
	suffix		"</A><BR>\n"
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element HEAD in DIV2} {
	prefix		"&nbsp;&nbsp;<[Link] [DivHref [query parent address]]>"
	suffix		"</A><BR>\n"
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element HEAD in DIV in DIV} {
	prefix		"&nbsp;&nbsp;<[Link] [DivHref [query parent address]]>"
	suffix		"</A><BR>\n"
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element HEAD in DIV1} {
	prefix		"<[Link] [DivHref [query parent address]]>\n<FONT SIZE='+1'>"
	suffix		"</FONT></A><BR>\n"
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element HEAD in DIV} {
	prefix		"<[Link] [DivHref [query parent address]]>\n<FONT SIZE='+1'>"
	suffix		"</FONT></A><BR>\n"
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element Q in HEAD in DIV} {
	prefix		[openQuote]
	suffix		[closeRend]
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element Q in HEAD in DIV1} {
	prefix		[openQuote]
	suffix		[closeRend]
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element Q in HEAD in DIV2} {
	prefix		[openQuote]
	suffix		[closeRend]
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element Q in HEAD in DIV3} {
	prefix		[openQuote]
	suffix		[closeRend]
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element Q in HEAD in DIV4} {
	prefix		[openQuote]
	suffix		[closeRend]
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element Q in HEAD in DIV5} {
	prefix		[openQuote]
	suffix		[closeRend]
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element LB in HEAD in DIV} {
	suffix		"\n<BR>\n"
    }
    {element LB in HEAD in DIV1} {
	suffix		"\n<BR>\n"
    }
    {element LB in HEAD in DIV2} {
	suffix		"\n<BR>\n"
    }
    {element LB in HEAD in DIV3} {
	suffix		"\n<BR>\n"
    }
    {element LB in HEAD in DIV4} {
	suffix		"\n<BR>\n"
    }
    {element LB in HEAD in DIV5} {
	suffix		"\n<BR>\n"
    }
    {element KW in HEAD in DIV} {
	prefix		"[openRend {typewriter,bold}]"
	suffix		"[closeRend]"
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element KW in HEAD in DIV1} {
	prefix		"[openRend {typewriter,bold}]"
	suffix		"[closeRend]"
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element KW in HEAD in DIV2} {
	prefix		"[openRend {typewriter,bold}]"
	suffix		"[closeRend]"
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element KW in HEAD in DIV3} {
	prefix		"[openRend {typewriter,bold}]"
	suffix		"[closeRend]"
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element KW in HEAD in DIV4} {
	prefix		"[openRend {typewriter,bold}]"
	suffix		"[closeRend]"
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element KW in HEAD in DIV5} {
	prefix		"[openRend {typewriter,bold}]"
	suffix		"[closeRend]"
	cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {el} {
	cdataFilter	null
	sdataFilter	null
    }
}

proc DivHref { addr } {
    return "HREF='[DivisionFileName ${addr}]\#[AddrToName ${addr}]'"
}

proc trimSpaces { text } {
    return [string trim $text " \t\n"]
}

proc startDiv {} {
    switch [typeVal] {
	"abstract" {
	    setprop closing "\n</EM></BLOCKQUOTE>\n"
	    return "\n<[elt BLOCKQUOTE]><EM>\n"
	}
	"colophon" {
	    setprop closing "\n</SMALL><HR>\n"
	    return "\n<HR><[elt SMALL]>\n"
	}
	"bibl" {
	    withNode child element HEAD {
		return
	    }
	    return "\n<CENTER><H1>[localize thebibliography]</H1></CENTER>\n"
	}
	default {
	    return
	}
    }
}

proc endDiv {} {
    set closing [query propval closing]
    if { "$closing" != "" } {
	return $closing
    }
    global splitNames
    if { [splitLevel] == 0 && \
	     ( "[query gi]" == "DIV" && \
		   [lsearch $splitNames(1) [typeVal]] != -1 \
		   || "[query gi]" == "DIV1" ) } {
	if { [doTocRef] } {
	    return "[TOCref]<HR>"
	} else {
	    return "<HR>"
	}
    }
    return
}

proc doTocRef {} {
    # To be overriden in styles
    return 0
}

proc BodyFileName {} {
    return
}

proc DivisionFileName { addr } {
    global baseFileName splitNames

    if { [splitLevel] == 0 } {
	return [BodyFileName]
    }

    if { $addr == "notes" } {
	return "${baseFileName}-notes.html"
    }
    
    Debug "DivisionFileName for [query gi], [content]"

    
    set topLevel {}
    foreachNode node $addr ancestor {
#	if { [string match DIV* [query gi]] } {
#	    if { ( "[query gi]" == "DIV" && \
#		       [lsearch $splitNames([splitLevel]) [typeVal]] != -1 ) \
#		     || "[query gi]" == "DIV[splitLevel]" \
#		     || [shouldBeSplitOff] } {
#		if { [firstDivInDiv] } {
#		    set topLevel [query parent address]
#		} else {
#		    return "${baseFileName}-[AddrToName [query address]].html"
#		}
#	    } else {
#		set topLevel [query address]
#	    }
#       }
	if { ![regexp DIV(\[0-9\])? [query gi] dummy divLevel] } {
	    set divLevel 0
	}
	if { [splitLevel] > 0 } {
	    if { ( ( "[query gi]" == "DIV" \
			 && [lsearch $splitNames([splitLevel]) [typeVal]] != -1 ) \
		       || $divLevel <= [splitLevel] \
		       || [shouldBeSplitOff] ) && ![firstDivInDiv] } {
		return "${baseFileName}-[AddrToName [query address]].html"
	    }
	}
    }
	#    Error "INTERNAL ERROR: can't generate file name (addr $addr)"
    return [BodyFileName]
}

proc firstDivInDiv {} {
    if { [string range [query parent gi] 0 2] == "DIV" \
	     && [countq prev element [query gi]] == 0 } {
	return 1
    }
    return 0
}

proc startFigure { { place "" } } {
    set image {}
    set entName [query attval ENTITY]
    if { $entName != "" } {
	set align [openAlign]
	set alt [query attval N]
	if { "$alt" != "" } {
	    set alt " ALT='${alt}'"
	}
	if { $place == "inline" } {
	    set align " ALIGN='middle'"
	}
        withNode entity $entName {
            set image "<[elt IMG] SRC='[graphicFileName [query sysid]]'${align}${alt}>"
        }
    }
    set anchor ""
    withNode child element "HEAD" {
	set anchor "<A NAME='[AddrToName [query address]]'>"
    }
    return "${anchor}${image}"
}

proc doPointer { { ptrRef "" } } {
    set target [attVal TARGET]
    
    #Pointer to numbered paragraph
    withNode doctree element P withattval ID $target {
	set n [paragraphNumber]
	if { "$n" != "" } {
	    return $n
	} else {
	    error "***ERROR: reference to unnumbered paragraph"
	}
    }

    withNode doctree element ITEM withattval ID $target {
	set ordered 0
	withNode parent element LIST {
	    if { "[attVal type]" == "ordered" } {
		set ordered 1
	    }
	}
	if { $ordered == 1 } {
	    set ptrRef [expr [countq prev element ITEM] + 1]
	}
    }
    
    #Pointers to labels (for <list gloss>, for example)
    withNode doctree element LABEL withattval ID $target {
	#FIXME!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	return [filteredContent]
    }
    
    withNode doctree withattval ID $target {
	foreachNode child {
	    withNode element HEAD {
		return [encoding convertfrom "<[Link] HREF='[DivisionFileName [query address]]\#$target'><EM>[filteredContent]</EM></A>"]
	    }
	}
	if { "$ptrRef" == "" } {
	    Warning "No HEAD in PTR/REF target, inserting empty HREF"
	    global TEItools_ptr_img_value
	    if { [info exists TEItools_ptr_img_value] } {
		set ptrRef "<[elt IMG] SRC='${TEItools_ptr_img_value}' ALT='***'>"
	    } else {
		if { [query gi] == "BIBL" } {
		    set ptrRef "\[[expr [countq prev element BIBL] + 1]\]"
		} else {
		    set ptrRef "***"
		}
	    }
	}
	return "<[Link] HREF='\#$target'>${ptrRef}</A>"
    }
    Error "No such target for <PTR TARGET='$target'>"
    return
}

proc openPointer {} {
    set target [attVal TARGET]
    foreachNode doctree withattval ID $target {
	return "[DivisionFileName [query address]]\#$target"
    }
    Warning "No such target for <REF TARGET=$target>"
    return
}

proc tableBorder {} {
    if { [string match "*notlined*" [attVal N]] } {
	return 0
    } else {
	return 1
    }
}

proc openTD {} {
    set role [attVal ROLE]
    withNode parent {
	set rowRole [attVal ROLE]
    }
    set ret "<[elt TD]"
    set cols [query attval COLS]
    set rows [query attval ROWS]
    if { $cols != "" && $cols != 1 } {
	append ret " COLSPAN=\"$cols\""
    }
    if { $rows != "" && $rows != 1 } {
	append ret " ROWSPAN=\"$rows\""
    }
    append ret " [TD_align]>"
    if { $role == "label" || $rowRole == "label" } {
	append ret "<STRONG>"
	setprop highlightState "<STRONG>[query propval highlightState]"
    }
    append ret [openRend]

    set content [string trim [content] " \t\n"]
    if { "$content" == "" } {
	append ret "&nbsp;"
    }
    
    return $ret
}

proc TD_align {} {

    set cellNo 0
    foreachNode prev {
	set span [attVal COLS]
	if { "$span" == "" } {
	    set span 1
	}
	incr cellNo $span
    }

    withNode ancestor element TABLE {
	set w [query propval colWidth]
	if { "$w" != "" } {
	    array set width $w
	    array set align [query propval colAlign]
	    set colWidth $width($cellNo)
	    set colAlign $align($cellNo)
	} else {
	    set colWidth ""
	    set colAlign ""
	}
    }
    
    set localAlign [openAlign]

    if { "$localAlign" != "" } {
	return "$colWidth $localAlign"
    }

    withNode parent parent {
	set tableRend [attVal REND]
    }

    if { "$tableRend" == "" } {
	return
    }

    if { [isdigit [string index $tableRend 0]] } {
	return "$colWidth [letterAlign ${colAlign}]"
    }

    if { [string length $tableRend] < $cellNo } {
	Error "REND value for TABLE is shorter than required."
	return
    }
    return "$colWidth [letterAlign [string index $tableRend $cellNo]]"
}

proc letterAlign { alignLetter } {
    switch -- $alignLetter {
	"l" {
	    return " ALIGN=\"left\""
	} 
	"c" {
	    return " ALIGN=\"center\""
	}
	"r" {
	    return " ALIGN=\"right\""
	}
	"j" {
	    return " ALIGN=\"justify\""
	}
	"" {
	    return 
	}
	default {
	    Error "Unknown letter in TABLE REND value: \"$alignLetter\""
	    return
	}
    }
}

proc closeTD {} {
    return "[closeRend]</TD>"
}

proc IDanchor {} {
    set id [attVal ID]
    if { "$id" != "" } {
	debug "IDanchor found id: $id"
	return "<A NAME='$id'></A>"
    } else {
	return
    }
}

proc openHead {} {
    withNode parent {
	set id [attVal ID]
	set addr [query address]
	set div [query gi]
	set type [typeVal]
    }
    if { "$id" != "" } {
	set anchor "<A NAME='${id}'></A>"
    } else {
	set anchor ""
    }

    append anchor "<A NAME=\"[AddrToName $addr]\"></A>"

    switch $div {
	"DIV" {
	    set depthLevel [countq ancestor element DIV]
	    setprop closing "</H${depthLevel}>"
	    return "${anchor}<[elt H${depthLevel}] align='center'>"
	}
        "DIV1" {
	    setprop closing "</H2>"
	    return "${anchor}<[elt H2] ALIGN=\"center\">"
	}
	"DIV2" {
	    setprop closing "</H3>"
	    return "${anchor}<[elt H3]>"
	}
	default {
	    setprop closing "</H4>"
	    return "${anchor}<[elt H4]>"
	}
    }
}

proc closeHead {} {
    return "[query propval closing]\n"
}

proc HeadOfList {} {
    foreachNode child {
	withNode element HEAD {
	    return "<[elt BLOCKQUOTE]><STRONG>[filteredContent]</STRONG></BLOCKQUOTE>"
	}
    }
    return
}

proc listHeader { type } {
    switch -regexp $type {
	"(bulleted)|(simple)|(bullets)" {
	    setprop closing "</UL>"
	    return "<[elt UL]>"
	}
	"ordered" {
	    setprop closing "</OL>"
	    return "<[elt OL]>"
	}
	"gloss" {
	    setprop closing "</DL>"
	    return "<[elt DL]>"
	}
	"alpha" {
	    setprop closing ""
	    return ""
	}
	default {
	    Error "Unknown list type: $type"
	    return "<P>"
	}
    }
}

proc listFooter {} {
    return [query propval closing]
}

proc listItem {} {
    set letter [listLetter [expr [countq prev element ITEM] + 1]]
    withNode parent {
	if { "[typeVal]" == "alpha" } {
	    return "<BR>[alphaItem $letter]"
	}
	if { "[query propval closing]" == "</DL>" } {
	    return "<[elt DD]>"
	}
	return "<[elt LI][itemRend]>"
    }
}

proc alphaItem { letter } {
    return "&nbsp;&nbsp;&nbsp;&nbsp;${letter}.&nbsp;"
}

proc itemRend {} {

    set n [attVal N]

    if { "$n" == "" } {
	return
    } else {
	return " value='${n}'"
    }
}

proc splitLevel {} {
    return 0
}

proc openQuote {} {
    if { "[attVal REND]" == "" || "[attVal REND]" == "\#IMPLIED" } {
	return [openRend quoted]
    } else {
	return [openRend]
    }
}

# Can return extra indentation or something
proc openPara {} {
    return
}

proc paraNumber {} {
    set n [paragraphNumber]
    if { "$n" == "" } return
    return "${n}&nbsp;"
}

proc openTitleOrHead {} {
    set inline 0
    foreachNode ancestor {
	switch -regexp "[query gi]" {
	    "(BIBL)|(P)|(ITEM)|(NOTE)|(CELL)|(HEAD)" {
		set inline 1
		break
	    }
	    default {
		continue
	    }
	}
	break
    }
    
    if { $inline == 1 } {
	set ret [openRend italic]
	return $ret
    } else {
	set ret [openRend bold,slanted]
	setprop highlightState "<FONT>[query propval highlightState]\n<CENTER>\n"
	return "\n<CENTER>${ret}<FONT SIZE=\"+2\">"
    }
}

proc OpenBody {} {
    output "[HtmlHeader]"
}

proc CloseBody {} {
    output "[HtmlFooter]"
}

proc tableWidths {} {
    set rend [attVal REND]

    if { "$rend" == "" || [isdigit [string index $rend 0]] == 0 } {
	return
    }

    set rend [split $rend " ,"]

    set colNo 0
    set totalWidth 0
    foreach r "$rend" {
	if { [regexp "(\[0-9\]+)(\[lrcj\]?)" $r dummy w a] } {
	    incr totalWidth $w
	    set width($colNo) $w
	    set align($colNo) $a
	} else {
	    Error "Unknown REND item: $r"
	    return
	}
	incr colNo
    }

    foreach col [array names width] {
	set width($col) "width='[expr $width($col) * 100 / $totalWidth]%'"
    }

    setprop colWidth [array get width]
    setprop colAlign [array get align]

    return "width='100%'"
}

proc openXref {} {
    set doc [query attval DOC]
    set from [attVal FROM]
    if { "$doc" != "" } {
	setprop closing "</A>"
	withNode entity $doc {
	    debug "sysid [query sysid], basename [sysIdToBasename [query sysid]]"
	    set doc [sysIdToBasename [query sysid]]
	    return "<[Link] HREF='$doc[maybeAnchor $from]'>"
	}
    }
    return
}

proc maybeAnchor { EPN } {
    debug "maybeAnchor `$EPN'"
    if { [regexp "\[ \t\]*\[iI\]\[dD\]\[ \t\]*\\(\(\[ \t\]*\[^)\]*\[ \t\]*\)\\)" \
	      $EPN dummy idref] } {
	debug "idref `$idref'"
	return "\#[string trim $idref]"
    }
    return
}

proc closeXref {} {
    return [query propval closing]
}

proc openEG {} {
    #    return "\n<P class='aux'><[elt TABLE] ALIGN='left'><TR><TD><PRE>\n"
    return "\n<P class='aux'><PRE>\n"
}

proc closeEG {} {
    #    return "</PRE></TD></TR></TABLE></P>\n"
    return "</PRE></P>\n"
}

set TEItools_formula_no 1

# All known elements should redefine 'prefix' property.

specification translate {
    {elements "FRONT DOCTITLE FILEDESC TITLESTMT EDITIONSTMT PUBLICATIONSTMT BODY BACK GAP PROFILEDESC LANGUSAGE LANGUAGE"} {
	prefix {}
	cdataFilter null
	sdataFilter null
    }
    {element INDEX} {
	prefix	"<A NAME='IDX_[AddrToName [query address]]'>"
    }
    {element MILESTONE} {
	prefix	"\n<CENTER>*&nbsp;*&nbsp;*</CENTER>\n"
    }
    {element NAME within STAGE} {
	prefix	"[openRend bold]"
    }
    {element NAME} {
	prefix	[openRend]
	suffix	[closeRend]
    }
    {element SOURCEDESC} {
	prefix {}
	cdataFilter null
	sdataFilter null
    }
    {element TEI.2} {
	startAction {
	    global silence
	    set silence 0
	    OpenBody
	}
	prefix		{}
	endAction {
	    CloseBody
	    global silence
	    set silence 1
	}
    }
    {element TEIHEADER} {
	endAction {
	    global silence
	    set silence 0
	}
	prefix		""
    }
    {element TEXT} {
	prefix		"\n</HEAD>\n<[elt BODY]>\n"
	endAction	endNotes
    }
    {element TITLE in TITLESTMT in FILEDESC in TEIHEADER} {
	prefix		"<TITLE>\\n"
	suffix		"\\n</TITLE>\\n"
	cdataFilter	identity
	startAction {
	    global silence
	    # Let's lie to output procedure
	    set silence 0
	}
	endAction {
	    global silence
	    set silence 1
	}
    }
    {element TITLEPART in DOCTITLE} {
	prefix	"\\n<[elt H1]>"
	suffix	"</H1>\\n"
    }
    {element TITLEPART} {
	prefix	"\\n<[elt P]>"
	suffix	"</P>\\n"
    }
    {element DOCAUTHOR within TITLEPAGE} {
	prefix	"\\n<[elt P]>"
	suffix	"</P>\\n"
    }
    {element DOCDATE in TITLEPAGE in FRONT} {
	prefix	"\\n<[elt P]>"
	suffix	"</P>\\n"
    }
    {element BYLINE in TITLEPAGE in FRONT} {
	prefix	"\\n<[elt P]>"
	suffix	"</P>\\n"
    }
    {element DOCIMPRINT in TITLEPAGE in FRONT} {
	prefix	"\\n<P><P><[elt P]><STRONG>"
	suffix	"</STRONG></P>\\n"
    }
    {element TITLEPAGE} {
	prefix	"\\n<[elt DIV] align='center'>\\n"
	suffix		"\\n</DIV>\\n<HR NOSHADE>\\n"
    }
    {element EG} {
	prefix		[openEG]
	suffix		[closeEG]
	cdataFilter	verbatimCdataFilter
    }
    {element EPIGRAPH} {
	prefix		{
	    <P><TABLE BORDER='0' WIDTH='100%'><TR><TD WIDTH='50%'></TD><TD>}
	suffix		{</TD></TR></TABLE>\n}
    }
    {element BIBL within EPIGRAPH} {
	prefix		{
	    <TABLE BORDER='0' WIDTH='100%'><TR><TD></TD><TD WIDTH='70%'>}
	suffix		{</TD></TR></TABLE>\n}
    }
    {element FORMULA} {
	startAction {
	    if { [attVal NOTATION] != "tex" } {
		error "Unknown formula notation: [attVal NOTATION], only `TeX' is supported."
	    }
	    set texFile "formula.[pid]"
	    outSpec save fileHandle [open "${texFile}.tex" w]
	    if { [useUnicode] } {
		fconfigure [outSpec get fileHandle] -encoding identity
	    }
	    output "
		\\documentclass{article}
		[localize LaTeX_preamble]
		\\begin{document}
		\\thispagestyle{empty}
		\\begin{displaymath}
	    "
	}
	endAction {
	    output {
		\end{displaymath}
		\end{document}
	    }
	    close [outSpec get fileHandle]
	    outSpec restore
	    global TEItools_formula_no baseFileName
	    set pictureFileName ${baseFileName}_formula_${TEItools_formula_no}.jpeg
	    incr TEItools_formula_no
	    processTeXfile $texFile $pictureFileName
	    file delete "${texFile}.tex"
	    #Fight multipage EPS. Why do we get them in first place?!
	    # Check processTeXfile.
	    catch {
		file rename ${pictureFileName}.0 ${pictureFileName}
		file delete ${pictureFileName}.1
	    }
	    set closing {}
	    if { [attVal REND] == "display" || [attVal REND] == "block" } {
		output "\n<CENTER>\n"
		set closing "\n</CENTER>\n"
	    }
	    output "<[elt IMG] SRC='$pictureFileName' ALIGN='bottom'></IMG>${closing}"
	}
	prefix		{}
	cdataFilter	eatNLs
    }
    {element P within SP} {
	prefix		""
	suffix		""
    }
    {element P withattval REND eg} {
	prefix		"\\n<PRE>\\n"
	suffix		"\\n</PRE>\\n"
	cdataFilter	verbatimCdataFilter
    }
    {element P} {
	prefix		"\n<P[openAlign]>[openRend][openPara][paraNumber]"
	suffix		"[closeRend]</P>\\n"
    }
    {element IDENT} {
	prefix		"[openRend italic]"
	suffix		"[closeRend]"
    }
    {element TERM} {
	prefix		"[openRend {italic,bold}]"
	suffix		"[closeRend]"
    }
    {element SOCALLED} {
	prefix		"[openRend quoted]"
	suffix		"[closeRend]"
    }
    {element LIST} {
	prefix		"[listHeader [typeVal]]\\n"
	suffix		"\\n[listFooter]\\n"
    }
    {element ITEM in LIST} {
	prefix		"\\n[listItem][openRend]"
	suffix		"[closeRend]<!-- /LI -->"
    }
    {element LABEL in LIST} {
	prefix		"<P><[elt DT]>[openRend bold]"
	suffix		"[closeRend]"
    }
    {element KW} {
	prefix		"[openRend {typewriter,bold}]"
	suffix		"[closeRend]"
    }
    {element CODE in XREF} {
	prefix		{}
	suffix		{}
	cdataFilter	null
	sdataFilter	null
    }
    {element CODE} {
	prefix		"[openRend typewriter]"
	suffix		"[closeRend]"
    }
    {element FOREIGN within DIV withattval TYPE ABSTRACT} {
	prefix		"</EM>"
	suffix		"<EM>"
    }
    {element EMPH within DIV withattval TYPE ABSTRACT} {
	prefix		"</EM>"
	suffix		"<EM>"
    }
    {element MENTIONED within DIV withattval TYPE ABSTRACT} {
	prefix		"</EM>"
	suffix		"<EM>"
    }
    {element HI within DIV withattval TYPE ABSTRACT} {
	prefix		"</EM>"
	suffix		"<EM>"
    }
    {elements "FOREIGN EMPH MENTIONED HI"} {
	prefix		"[openRend italic]"
	suffix		"[closeRend]"
    }
    {element XREF withattval TYPE URL} {
	prefix		"<[Link] HREF='"
	suffix		"'>[XREF2HREF]</A>"
	cdataFilter	trimSpaces
    }
    {element XREF} {
	prefix		"[openRend bold][openXref]"
	suffix		"[closeXref][closeRend]"
    }
    {element XPTR} {
	prefix		"[openTitleOrHead][doXptr NodeReferenceName]"
	suffix		"[closeRend]"
    }
    {element NOTE withattval PLACE INTERLINE} {
	before		{}
	startAction	{}
	endAction	{}
	prefix		"\\n<BLOCKQUOTE><HR>[openRend italic]"
	suffix		"\\n[closeRend]<HR></BLOCKQUOTE>\\n"
	sdataFilter	textSdataFilter
	cdataFilter	textCdataFilter
    }
    {element NOTE withattval PLACE INTERLINEAR} {
	before		{}
	startAction	{}
	endAction	{}
	prefix		"\\n<BLOCKQUOTE><HR>[openRend italic]"
	suffix		"\\n[closeRend]<HR></BLOCKQUOTE>\\n"
	sdataFilter	textSdataFilter
	cdataFilter	textCdataFilter
    }
    {element NOTE withattval PLACE INLINE} {
	before		{}
	startAction	{}
	endAction	{}
	prefix		" ([openRend]"
	suffix		"[closeRend])"
	cdataFilter	inlineNoteFilter
	sdataFilter	textSdataFilter
    }
    {element NOTE} {
	before		[endNotePrefix]
	startAction {
	    global silence endNotesPass
	    if { $endNotesPass == 0 } {
		set silence 1
	    }
	}
	prefix		{}
	suffix		[endNoteSuffix]
	endAction {
	    global silence
	    set silence 0
	}
	cdataFilter	endNoteCFilter
	sdataFilter	endNoteSFilter
    }
    {element AUTHOR in BIBL} {
	prefix		{}
	suffix		", "
    }
    {element PUBLISHER in BIBL} {
	prefix		", "
    }
    {element DATE in BIBL} {
	prefix		", "
    }
    {element BIBLSCOPE in BIBL} {
	prefix		" ("
	suffix		")"
    }
    {element LISTBIBL} {
	prefix		"\\n<OL>\\n"
	suffix		"\\n</OL>\\n"
    }
    {element PB} {
	prefix		"<[elt P]><TABLE BORDER=\"0\" WIDTH=\"100%\" ALIGN=\"center\">
<TR><TD><HR></TD><TD WIDTH=\"1%\"> [localize pageBreak] </TD><TD><HR></TD></TR>
</TABLE><P>"
    }
    {element DIVGEN} {
	startAction	divgenStart 
	prefix		"\n<[elt DIV]>\n[divGen]\n</DIV>\n"
	endAction	divgenEnd
    }
    {element GI} {
	prefix		"[openRend {typewriter,bold}]&lt;"
	suffix		">[closeRend]"
    }
    {element Q} {
	prefix		"[openQuote]"
	suffix		"[closeRend]"
    }
    {elements "DIV DIV0 DIV1"} {
	startAction	{openDivision [query address]}
	prefix		"\n<[elt DIV]>[startDiv]"
	suffix		"[endDiv]</DIV>\n"
	endAction	{closeDivision}
    }
    {elements "DIV2 DIV3 DIV4 DIV5 DIV6 DIV7 DIV8"} {
	prefix		"\n<[elt DIV]>"
	suffix		"</DIV>\n"
	startAction	{openDivision [query address]}
	endAction	{closeDivision}
    }
    {element DIV in DIV} {
	prefix		"\n<[elt DIV]>"
	suffix		"</DIV>\n"
	startAction	{openDivision [query address]}
	endAction	{closeDivision}
    }
    {element DIV in DIV in DIV} {
	prefix		"\n<[elt DIV]>"
	suffix		"</DIV>\n"
	endAction	{closeDivision}
    }
    {element DIV in DIV in DIV in DIV} {
	prefix		"\n<[elt DIV]>"
	suffix		"</DIV>\n"
	startAction	{openDivision [query address]}
	endAction	{closeDivision}
    }
    {element DIV in DIV in DIV in DIV in DIV} {
	prefix		"\n<[elt DIV]>"
	suffix		"</DIV>\n"
	startAction	{openDivision [query address]}
	endAction	{closeDivision}
    }
    {element DIV in DIV in DIV in DIV in DIV in DIV} {
	prefix		"\n<[elt DIV]>"
	suffix		"</DIV>\n"
	startAction	{openDivision [query address]}
	endAction	{closeDivision}
    }
    {element HEAD in DIV} {
	prefix		"[openHead][openRend]"
	suffix		"[closeRend][closeHead]"
    }
    {element HEAD in DIV1} {
	prefix		"[openHead][openRend]"
	suffix		"[closeRend][closeHead]"
    }
    {element HEAD in DIV2} {
	prefix		"[openHead][openRend]"
	suffix		"[closeRend][closeHead]"
    }
    {element HEAD in DIV3} {
	prefix		"[openHead][openRend]"
	suffix		"[closeRend][closeHead]"
    }
    {element HEAD in DIV4} {
	prefix		"[openHead][openRend]"
	suffix		"[closeRend][closeHead]"
    }
    {element HEAD in DIV5} {
	prefix		"[openHead][openRend]"
	suffix		"[closeRend][closeHead]"
    }
    {element HEAD in DIV6} {
	prefix		"[openHead][openRend]"
	suffix		"[closeRend][closeHead]"
    }
    {element HEAD in FIGURE} {
	prefix		[openFigHead]
	suffix		[closeFigHead]
    }
    {element HEAD in LIST} {
	prefix		"<[elt LH]>[openRend {block,bold}]"
	suffix		"[closeRend]</LH>\\n"
    }
    {element HEAD in TABLE} {
	prefix		"\\n<[elt CAPTION][openAlign]>"
	suffix		"</CAPTION>\\n"
    }
    {element HEAD in LISTBIBL} {
	prefix		{}
	cdataFilter	null
	sdataFilter	null
    }
    {element PTR} {
	prefix		"[doPointer]"
    }
    {element REF} {
	prefix		"<[Link] HREF=\"[openPointer]\">"
	suffix		"</A>"
    }
    {elements "SEG ANCHOR"} {
	# everything does default startAction
	prefix		{}
    }
    {element TABLE} {
	prefix		"\\n<[elt TABLE] BORDER=\"[tableBorder]\" [tableWidths]>"
	suffix		"</TABLE>\\n"
	endAction {
	    global tableRend
	    set tableRend {}
	}
    }
    {element ROW in TABLE} {
	prefix		"\\n<[elt TR]>"
	suffix		"</TR>"
    }
    {element CELL in ROW in TABLE} {
	prefix		"[openTD]"
	suffix		"[closeTD]"
    }
    {element FIGURE withattval REND INLINE} {
	prefix		"[startFigure inline]"
	suffix		{}
    }
    {element FIGURE} {
	prefix		"\\n</P><[elt DIV][openAlign center]>[startFigure]"
	suffix		"\\n<BR></DIV></P><P>\\n"
    }
    {element FIGDESC in FIGURE} {
	prefix		"\\n<[elt BLOCKQUOTE]><EM>"
	suffix		"</EM></BLOCKQUOTE>\\n"
    }
    {element TITLE hasatt LEVEL in BIBL} {
	prefix		"<B>"
	suffix		"</B>"
    }
    {element HEAD withattval TYPE SHORT} {
	prefix		{}
	cdataFilter	null
	sdataFilter	null
    }
    {elements "TITLE HEAD"} {
	prefix		"[openTitleOrHead]"
	suffix		"[closeRend]"
    }
    {element BIBL} {
	prefix		"<LI>"
	suffix		"</LI>\\n"
        cdataFilter	textCdataFilter
	sdataFilter	textSdataFilter
    }
    {element ABBR} {
	prefix		""
	cdataFilter	toUpper
    }
    {element LG} {
	prefix		"\\n<[elt BLOCKQUOTE]>\\n"
	suffix		"\\n</BLOCKQUOTE>\\n"
    }
    {elements "L LB"} {
	prefix		{}
	suffix		"\\n<BR>\\n"
    }
    {element DEL} {
	prefix		{}
	cdataFilter	null
	sdataFilter	null
    }
    {element SP} {
	prefix		"<[elt P]>[speaker]"
    }
    {element SPEAKER} {
	prefix		"<[elt STRONG]>"
	suffix		". </STRONG>"
    }
    {element STAGE within SP} {
	prefix		"<[elt I]>"
	suffix		"</I>"
    }
    {element STAGE} {
	prefix		"\n<[elt BLOCKQUOTE]>\n<DIV align='center'><SMALL>\n"
	suffix		"\n</SMALL></DIV></BLOCKQUOTE>\n"
    }
    {el} {
	prefix		[openUnknown]
	before		[IDanchor]
	sdataFilter	textSdataFilter
	cdataFilter	textCdataFilter
    }
    {pi} {
	piAction {
	    set content [query content]
	    set space [string first " " $content]
	    if { "[string toupper [lindex [split $content " \t"] 0]]" \
		     == "TEITOOLS" } {
		TEItools_do_PI [string trim [string range $content $space end]]
	    }
	}
    }
}


# This is used, for example, by CGIs. Set -style XPointer=<XPointer>, and
# tei2html will slide to the said starting point before processing.

if { [info exists TEItools_XPointer_value] } {
    debug "Going to XPointer `$TEItools_XPointer_value', now at [query address]"
    proc noop {} {
	debug "In XPointer, address is [query address]"
    }
    XPointer {} [string tolower $TEItools_XPointer_value] {} noop
    debug "There, now at [query address]"

    proc beforeTranslate {} {
	output [HtmlHeader]
    }

    proc afterTranslate {} {
	output [HtmlFooter]
    }
    
}
