
# lappend auto_path /c/compasser/addons
# lappend auto_path /c/TclTk/RamDebugger/addons
# lappend auto_path /compasser/addons

#lappend auto_path [file dirname [file dirname [info script]]]

################################################################################
#  This software is copyrighted by Ramon Ribó (RAMSAN) ramsan@cimne.upc.es.
#  (http://gid.cimne.upc.es/ramsan) The following terms apply to all files
#  associated with the software unless explicitly disclaimed in individual files.

#  The authors hereby grant permission to use, copy, modify, distribute,
#  and license this software and its documentation for any purpose, provided
#  that existing copyright notices are retained in all copies and that this
#  notice is included verbatim in any distributions. No written agreement,
#  license, or royalty fee is required for any of the authorized uses.
#  Modifications to this software may be copyrighted by their authors
#  and need not follow the licensing terms described here, provided that
#  the new terms are clearly indicated on the first page of each file where
#  they apply.

#  IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
#  FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
#  ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
#  DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
#  POSSIBILITY OF SUCH DAMAGE.

#  THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
#  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
#  FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
#  IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
#  NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
#  MODIFICATIONS.
################################################################################

package provide helpviewer 1.0
# requiring exactly 2.1 to avoid getting the one from Activestate
#catch { package require -exact Tkhtml 2.1 }
#package require Tkhtml

#package require BWidgetR
#package require BWidget
#package require supergrid
#package require dialogwin
#package require fileutil
#package require htmlparse

proc filenormalize { file } {

    if { $file == "New file" } { return $file }
    if { $file == "" } { return "" }

    set pwd [pwd]
    catch {
	cd [file dirname $file]
	set file [file join [pwd] [file tail $file]]
    }
    cd $pwd

    if { $::tcl_platform(platform) == "windows" } {
	catch { set file [file attributes $file -longname] }
    }

    return $file
}

if { [info command tkTabToWindow] == "" } {
    proc tkTabToWindow {w} {
	focus $w
	after 100 {
	    set w [focus]
	    if {[string equal [winfo class $w] Entry]} {
		$w selection range 0 end
		$w icursor end
	    }
	}
    }
}

set comms [list tkButtonInvoke tkTextSelectTo tkEntryInsert tkEntryBackspace \
    tk_textCut tk_textCopy tk_textPaste tk_focusNext tk_focusPrev tkTextClosestGap \
    tkTextAutoScan tkCancelRepeat]

foreach i $comms {
    auto_load $i
    if {![llength [info commands $i]]} {
	tk::unsupported::ExposePrivateCommand $i
    }
}

namespace eval GiDHistory {
    variable list
    variable pos
    variable menu

    proc Init { w menu } {
	variable list
	variable pos
	variable menu
	
	set list($w) ""
	set pos($w) -1
	set menu($w) $menu
    }

    proc Add { w name } {
	variable list
	variable pos
	variable menu

	lappend list($w) $name
	set pos($w) [expr [llength $list($w)]-1]
	if { $pos($w) == 0 } {
	    if { [info exists menu($w)] && [winfo exists $menu($w)] } {
		$menu($w) entryconf Backward -state disabled
	    }
	} else {
	    if { [info exists menu($w)] && [winfo exists $menu($w)] } {
		$menu($w) entryconf Backward -state normal
	    }
	}
	if { [info exists menu($w)] && [winfo exists $menu($w)] } {
	    $menu($w) entryconf Forward -state disabled
	}
    }
    proc GoHome { w } {
	variable list
	variable pos
	variable menu

	set pos($w) 0
	if { [info exists menu($w)] && [winfo exists $menu($w)] } {
	    $menu($w) entryconf Backward -state disabled
	}
	if { [info exists menu($w)] && [winfo exists $menu($w)] } {
	    $menu($w) entryconf Forward -state normal
	}
	GiDHelpViewer::LoadRef $w [lindex $list($w) $pos($w)] 0
    }
    proc GoBackward { w } {
	variable list
	variable pos
	variable menu

	incr pos($w) -1
	if { $pos($w) == 0 } {
	    if { [info exists menu($w)] && [winfo exists $menu($w)] } {
		$menu($w) entryconf Backward -state disabled
	    }
	}
	if { [info exists menu($w)] && [winfo exists $menu($w)] } {
	    $menu($w) entryconf Forward -state normal
	}
	GiDHelpViewer::LoadRef $w [lindex $list($w) $pos($w)] 0
    }
    proc GoForward { w } {
	variable list
	variable pos
	variable menu

	incr pos($w) 1
	if { $pos($w) == [expr [llength $list($w)]-1] } {
	    if { [info exists menu($w)] && [winfo exists $menu($w)] } {
		$menu($w) entryconf Forward -state disabled
	    }
	}
	if { [info exists menu($w)] && [winfo exists $menu($w)] } {
	    $menu($w) entryconf Backward -state normal
	}
	GiDHelpViewer::LoadRef $w [lindex $list($w) $pos($w)] 0
    }
}

namespace eval HelpPrefs {
    variable tttrick 0
    variable RunningAlone 0
}

namespace eval GiDHelpViewer {

    variable HelpBaseDir
    variable LastFileList
    variable images
    variable waiting
}

proc GiDHelpViewer::Init { w } {
    # variables de tipo array
    variable LastFileList
    variable Index
    variable FindWordInFileCache
    variable TitleCache
    variable IndexInfo
    # variables de tipo list
    variable indexlist1
    variable indexlist2
    variable indexstring
    variable searchstring
    variable IndexFilesTitles
    variable SearchFound
    variable SearchFound2
    variable SearchFound2data
    # otros tipos
    variable waiting
    variable searchmode
    variable searchcase
    variable searchFromBegin
    variable SearchType
    variable data

    catch { destroy $w }
    
    foreach trace [trace vinfo indexstring($w)] {
	trace vdelete indexstring($w) [lindex $trace 0] [lindex $trace 1]
    }
 
   foreach varr {LastFileList Index IndexInfo FindWordInFileCache TitleCache} {
	array unset $varr ${w},*
    }
    set IndexInfo($w,pages) ""
    foreach vlarr {indexlist1 indexlist2 indexstring searchstring \
		      IndexFilesTitles SearchFound SearchFound2 \
		      SearchFound2data} {
	set ${vlarr}($w) ""        
    } 
    set waiting($w) 0
    set searchmode($w) -exact
    set searchcase($w) 0
    set searchFromBegin($w) 0
    set SearchType($w) -forwards
    set data($w,sync) 0
    set data($w,draw) enabled
}

proc GiDHelpViewer::GiveLastFile { w } {
    variable LastFileList
    set retval ""
    catch {
	set w [winfo toplevel $w]
	set retval $LastFileList($w)
    }
    return $retval
}
proc GiDHelpViewer::EnterLastFile { w file } {
    variable LastFileList
    set w [winfo toplevel $w]
    set LastFileList($w) $file
}

#A font chooser routine.
#
#  $base.h.h config -fontcommand pickFont
proc GiDHelpViewer::pickFont {size attrs} {
    global tcl_platform

    if { [lsearch [font names] HelpFont] != -1 } {
	set family [font conf HelpFont -family]
	set fsize [font conf HelpFont -size]
    } else {
	set family Helvetica
	switch $::tcl_platform(platform) {
	    windows { set fsize 11 }
	    default { set fsize 15 }
	}
    }

    if { $HelpPrefs::tttrick } {
	set a [expr {-1<[lsearch $attrs fixed]?{Symbol}:"$family"}]
    } else {
	set a [expr {-1<[lsearch $attrs fixed]?{Courier}:"$family"}]
    }
    set b [expr {-1<[lsearch $attrs italic]?{italic}:{roman}}]
    set c [expr {-1<[lsearch $attrs bold]?{bold}:{normal}}]
    set d [expr int($fsize*pow(1.2,$size-4))]
#     if { $tcl_platform(platform) != "windows"} {
#          set d [expr {3+int(12*pow(1.2,$size-4))}]
#     } else {
#          set d [expr {3+int(12*pow(1.2,$size-6))}]
#     }

    list $a $d $b $c
}

proc GiDHelpViewer::CreateFrame { frame { hscroll 1 } {vscroll 1 }         } {
    frame $frame
    frame $frame.f1
    frame $frame.f2
    if { $hscroll } {
	set hscrollcommand "$frame.f2hsb set"
    } else { set xscrollcommand "" }
    if { $vscroll } {
	set yscrollcommand "$frame.f1vsb set"
    } else { set yscrollcommand "" }
    html $frame.f1.h \
    -xscrollcommand $hscrollcommand \
    -yscrollcommand $yscrollcommand \
    -padx 5 \
    -pady 9 \
    -formcommand FormCmd \
    -imagecommand ImageCmd \
    -scriptcommand ScriptCmd \
    -appletcommand AppletCmd \
    -underlinehyperlinks 0 \
    -bg white -tablerelief raised \
    -resolvercommand ResolveUri \
    -exportselection 1 \
    -takefocus 1

    bind $frame.f1.h.x <1> "GiDHelpViewer::HrefBinding $frame.h %x %y"
    if { $hscroll } {
	frame $frame.f2.sp -width [winfo reqwidth $base.h.vsb] -bd 2 -relief raised
	scrollbar $frame.f2.hsb -orient horizontal -command "$frame.f1.h xview"
	pack $base.f2.sp -side right -fill y
	pack $frame.f2.hsb -side left -fill x -expand 1
    }
    if { $vscroll } {
	scrollbar $frame.f1.vsb -orient vertical -command "$frame.f1.h yview"
	pack $frame.f1.vsb -side right -fill y -expand 1
    }
    pack $frame.f1.h -side left -fill both -expand 1
    pack $frame.f1 -side top -fill both -expand 1
    pack $frame.f2 -side bottom -fill x -expand 1
}

proc GiDHelpViewer::FrameCmd { base type arglist } {
    global HelpPriv
    switch $type {
	frameset {
	    set HelpPriv(frameset) $arglist
	    foreach i [array names frame*] {
		uset HelpPriv($i)
	    }
	}
	frame {
	    set i 0
	    while { [info exists HelpPriv(frame$i)] } { incr i }
	    set HelpPriv(frame$i) $arglist
	}
	/frameset {
	    foreach "name args" "$HelpPriv(frameset)" {
		switch $name {
		    rows {
		    }
		}
	    }
	    set i 0
	    while { [info exists HelpPriv(frame$i)] } {
		foreach "name args" "$HelpPriv(frame$i)" {


		}
		incr i
	    }
	}
    }
    tk_messageBox -icon error -message $type----$arglist-- -type ok
}

# This routine is called for each form element
#
proc GiDHelpViewer::FormCmd {n cmd args} {
    switch $cmd {
	select -
	textarea -
	input {
	    set w [lindex $args 0]
	    label $w -image nogifsm
	}
    }
}

proc GiDHelpViewer::ImageCmd {args} {
    global OldImages Images showImages
    if {!$showImages} {
	return smgray
    }
    set fn [lindex $args 0]

    set list [file split $fn]
    if { [lindex $list 0] == "." } {
	set list [lrange $list 1 end]
    }
    set fn [eval [concat "file join $list"]]

    if { [file dirname $fn] == "." } {
	set fn [file tail $fn]
    }
    if {[info exists OldImages($fn)]} {
	set Images($fn) $OldImages($fn)
	unset OldImages($fn)
	return $Images($fn)
    }
    if {[catch {image create photo -file $fn} img]} {
	return smgray
    }
    set width [lindex $args 1]
    if { [string is integer -strict $width] && $width != [image width $img] } {
	set height [expr {int([image height $img]*$width/[image width $img])}]
	set img_old $img
	set img [image create photo -width $width -height $height]
	img_zoom $img $img_old
    }


    if {[image width $img]*[image height $img]>20000} {
	global BigImages
	set b [image create photo -width [image width $img] \
	    -height [image height $img]]
	set BigImages($b) $img
	set img $b
	after idle "GiDHelpViewer::MoveBigImage $b"
    }
    set Images($fn) $img
    return $img
}

proc GiDHelpViewer::MoveBigImage b {
    global BigImages
    if {![info exists BigImages($b)]} return
    $b copy $BigImages($b)
    image delete $BigImages($b)
    unset BigImages($b)
    update
}


# This routine is called for every <SCRIPT> markup
#
proc GiDHelpViewer::ScriptCmd {args} {
    # puts "ScriptCmd: $args"
}

# This routine is called for every <APPLET> markup
#
proc GiDHelpViewer::AppletCmd {w arglist} {
    # puts "AppletCmd: w=$w arglist=$arglist"
    #label $w -text "The Applet $w" -bd 2 -relief raised
}

# This procedure is called when the user clicks on a hyperlink.
# See the "bind $base.h.h.x" below for the binding that invokes this
# procedure
#
proc GiDHelpViewer::HrefBinding {w x y} {
    variable html

    set new [$html($w) href $x $y]
    catch {
	if { [llength $new] == 1 } {
	    set new [lindex $new 0]
	    if { [llength $new] == 1 } {
		set new [lindex $new 0]
	    }
	}
    }
    LoadRef $w $new
}

proc GiDHelpViewer::LoadRef { w new { enterinhistory 1 } } {
    global tcl_platform
    variable html

    WaitState $w 1

    if { 0 && [regexp {http:/localhost/cgi-bin/man/man2html\?(\w+)\+(\w+)} $new {} sec word] } {
	SearchManHelpFor $w $word $sec
	WaitState $w 0
	return
    } elseif { $new != "" && [regexp {([a-zA-Z]+[a-zA-Z]:.*$)} $new url] } {
	#regexp {[^/\\]*:.*} $new url
	if { [regexp {:/[^/]} $url] } {
	    regsub {:/} $url {://} url
	}
        browser::urlOpen $url
#	if { $tcl_platform(platform) != "windows"} {
#	    VisitWeb $url
#	} else {
#	    VisitWeb $url
#	}
	WaitState $w 0        
	return
    }

    if {$new!=""} {
	set LastFile [GiveLastFile $w]
	if { [string match \#* [file tail $new]] } {
	    set new $LastFile[file tail $new]
	}
	set pattern $LastFile#
	set len [string length $pattern]
	incr len -1
	if {[string range $new 0 $len]==$pattern} {
	    incr len
	    $html($w) yview [string range $new $len end]
	    if { $enterinhistory } {
		GiDHistory::Add $w $new
	    }
	} elseif { [regexp {(.*)\#(.*)} $new {} file tag] } {
	    LoadFile $w $file $enterinhistory $tag
	} else {
	    LoadFile $w $new $enterinhistory
	}
    }
    WaitState $w 0
}

proc GiDHelpViewer::Load { w } {
    set filetypes {
	{{Html Files} {.html .htm}}
	{{All Files} *}
    }
    global lastDir htmltext
    set f [tk_getOpenFile -initialdir $lastDir -filetypes $filetypes]

    if {$f!=""} {
	LoadFile $w $f
	set lastDir [file dirname $f]
    }
}

# Clear the screen.
#
# Clear the screen.
#
proc GiDHelpViewer::Clear { w } {
    variable html
    global Images OldImages hotkey
    $html($w) clear
    catch {unset hotkey}
}

proc GiDHelpViewer::ClearOldImages {} {
    global OldImages
    #               foreach fn [array names OldImages] {
    #                   image delete $OldImages($fn)
    #               }
    #               catch {unset OldImages}
}
proc GiDHelpViewer::ClearBigImages {} {
    global BigImages
    #               foreach b [array names BigImages] {
    #                   image delete $BigImages($b)
    #               }
    #               catch {unset BigImages}
}

# Read a file
#
proc GiDHelpViewer::ReadFile {name} {
    if { [file dirname $name] == "." } {
	set name [file tail $name]
    }
    if {[catch {open $name r} fp]} {
	tk_messageBox -icon error -message $fp -type ok
	return {}
    } else {
	fconfigure $fp -translation binary
	set r [read $fp [file size $name]]
	close $fp
	if { [regexp {<meta\s+[^>]*charset=utf-8[^>]*>} $r] } {
	    set fp [open $name r]
	    fconfigure $fp -encoding utf-8
	    set r [read $fp]
	    close $fp
	}
	return $r
    }
}

# Load a file into the HTML widget
#
proc GiDHelpViewer::LoadFile {w name { enterinhistory 1 } { tag "" } } {
    global HelpPriv
    variable html
    variable data

    if { $name == "" } { return }

    WaitState $w 1

    if { [file isdir $name] } {
	set files [glob -dir $name *]
	set ipos [lsearch -regexp $files {(?i)(index|contents|_toc)\.(htm|html)}]
	if { $ipos != -1 } {
	    set name [lindex $files $ipos]
	} else {
	    WaitState $w 0
	    return
	}
    }

    if {[GiveLastFile $w] eq $name} {
	if { $enterinhistory } {
	    if { $tag == "" } {
		GiDHistory::Add $w $name
	    } else {
		GiDHistory::Add $w $name#$tag
		update idletasks
		$html($w) yview $tag
	    }
	}
    } else {
	# es un archivo nuevo y por tanto hay que
	set htmlcont [ReadFile $name]
	if {$htmlcont==""} {
	    WaitState $w 0
	    return
	}
	Clear $w
	EnterLastFile $w $name
	
	$html($w) config -base $name
	if { $enterinhistory } {
	    if { $tag == "" } {
		GiDHistory::Add $w $name
	    } else {
		GiDHistory::Add $w $name#$tag
	    }
	}
	$html($w) sel clear
	$html($w) parse $htmlcont
	ClearOldImages
	if {$tag ne ""} {
	    $html($w) draw disabled
	    update
	    $html($w) draw $data($w,draw)
 	    $html($w) yview $tag
            # este refresh me parecio solo necesario al mostrar 
            # la ayuda html del propio texinfo
            $html($w) refresh
	}
	if {$data($w,sync)} {
	    #TryToSelect $w $name
	    SyncContents $w $name
	    set data($w,sync) 0
	}
    }
    variable SearchPos
    set SearchPos($w) ""
    WaitState $w 0
}

proc GiDHelpViewer::GiveManHelpNames { word } {

    return ""

    if { [auto_execok man2html] == "" } { return "" }

    set err [catch { exec man -aw $word } file]
    if { $err } { return "" }

    set words ""
    foreach i [split $file \n] {
	set ext [string trimleft [file ext $i] .]
	if { $ext == "gz" } { set ext [string trimleft [file ext [file root $i]] .] }
	if { [lsearch $words "$word (man $ext)"] == -1 } {
	    lappend words "$word (man $ext)"
	}
    }
    return $words
}

proc GiDHelpViewer::SearchManHelpFor { w word { mansection "" } } {
    variable html

    if { $mansection == "" } {
	regexp {(\S*)\s+\(man\s+(.*)\)} $word {} word mansection
    }

    set err [catch { exec man -aw $word } file]
    if { $err } { return }

    set files [split $file \n]

    if { [llength $files] > 1 } {
	set found 0
	foreach i $files {
	    set ext [string trimleft [file ext $i] .]
	    if { $ext == "gz" } { set ext [string trimleft [file ext [file root $i]] .] }
	    if { $mansection == $ext } {
		set found 1
		set file $i
		break
	    }
	}
	if { !$found } { set file [lindex $files 0] }
    } else { set file [lindex $files 0] }

    if { [file ext $file] == ".gz" } {
	set comm [list exec gunzip -c $file | man2html]
    } else { set comm [list exec man2html $file] }

    set err [catch { eval $comm } html($w)]
    #if { $err } { return }

    Clear $w

    $html($w) sel clear
    $html($w) parse $html
    ClearOldImages
    variable SearchPos
    set SearchPos($w) ""
}

# Refresh the current file.
#
proc GiDHelpViewer::Refresh {w args} {
    set LastFile [GiveLastFile $w]
    if {![info exists LastFile] || ![winfo exists $w] } return
    LoadFile $w $LastFile 0
}

proc GiDHelpViewer::ResolveUri { args } {
    return [file join [file dirname [lindex $args 0]] [lindex $args 1]]
}

proc GiDHelpViewer::MouseWheel { W d x y } {
    set parent [winfo parent $W]
    if {(([winfo class $W] eq "Canvas") && ([winfo class $parent] eq "Tree")) ||
	(([winfo class $W] eq "HtmlClip") && ([winfo class $parent] eq "Html"))} {
	$parent yview scroll $d units
    } elseif { [winfo class $W] == "Html" } {
	$W yview scroll $d units
    }
}

proc GiDHelpViewer::ManageSel { w W x y type } {
    global HelpPriv tcl_platform
    variable html

    if { ![winfo exists         $W] } { return }
    if { [winfo parent $W] != $html($w) } { return }
    if { [info exists HelpPriv(lastafter)] } {
	after cancel $HelpPriv(lastafter)
    }

    switch -glob $type {
	press {
	    update idletasks
	    $html($w) sel clear
	    set idx [$html($w) index @$x,$y]
	    if { $idx == "" } { return }
	    $html($w) insert $idx
	    $html($w) sel set $idx $idx
	}
	motion* {
	    if { $type == "motion" } {
		#set ini [$htmlw index sel.first]
		set ini [$html($w) index insert]
		if { $ini == "" } {
		    $html($w) sel clear
		} else {
		    set idx [$html($w) index @$x,$y]
		    if { $idx <= $ini } {
		        $html($w) sel set $idx $ini
		    } else {
		        $html($w) sel set $ini $idx
		    }
		}
	    }
	    set isout 0
	    if { $x > [winfo width $html($w)] } {
		$html($w) xview scroll 1 units
		set isout 1
	    } elseif { $x <0 } {
		$html($w) xview scroll -1 units
		set isout 1
	    }
	    if { $y > [winfo height $html($w)] } {
		$html($w) yview scroll 1 units
		set isout 1
	    } elseif { $y <0 } {
		$html($w) yview scroll -1 units
		set isout 1
	    }
	    if { $isout } {
		set HelpPriv(lastafter) [after 100 GiDHelpViewer::ManageSel \
		                             $w $W $x $y motionout]
	    }
	}
	release {
	    #set ini [$htmlw index sel.first]
	    set ini [$html($w) index insert]
	    if { $ini == "" } {
		$html($w) sel clear
		return
	    }
	    set idx [$html($w) index @$x,$y]
	    if { $idx == $ini } {
		$html($w) sel clear
	    } else {
		if { $idx <= $ini } {
		    $html($w) sel set $idx $ini
		} else {
		    $html($w) sel set $ini $idx
		}
	    }
	    if { $tcl_platform(platform) != "windows"} {
		selection own -command "GiDHelpViewer::LooseSelection $w" $html($w)
	    }
	}
    }
}


proc GiDHelpViewer::LooseSelection { w } {
    variable html

    $html($w) sel clear
}

proc GiDHelpViewer::CopySelected { w { offset 0 } { maxBytes 0} } {
    global tcl_platform
    variable html

    set ini [$html($w) index sel.first]
    set end [$html($w) index sel.last]
    if { $ini == "" || $end == "" } { return }

    regexp {([0-9]+)[.]([0-9]+)} $ini {} initoc inipos
    regexp {([0-9]+)[.]([0-9]+)} $end {} endtoc endpos
    #puts [$w token list $initoc $endtoc]
    set rettext ""
    set iposlast [expr $endtoc-$initoc]
    set ipos 0

    foreach i [$html($w) token list $initoc $endtoc] {
	set type [lindex $i 1]
	set contents [join [lrange $i 2 end]]
	switch -- $type {
	    Text {
		set inichar 0
		set endchar [string length $contents]
		if { $ipos == 0 } {
		    set inichar $inipos
		}
		if { $ipos == $iposlast } {
		    set endchar [expr $endpos-1]
		}
		append rettext [string range $contents $inichar $endchar]
	    }
	    Space {
		if { [lindex $contents 1] == 0 } {
		    append rettext " "
		} else {
		    append rettext "\n"
		}
	    }
	}
	incr ipos
    }
    if { $tcl_platform(platform) == "windows"} {
	clipboard clear -displayof $html($w)
	clipboard append -displayof $html($w) $rettext
    } else {
	return [string range $rettext $offset [expr $offset+$maxBytes-1]]
    }
}

# what can be: HTML or Word or CSV
proc GiDHelpViewer::SaveHTMLAs { w what } {

    set fromfile [GiveLastFile $w]
    switch $what {
	HTML {
	    set types {
		{{HTML file}          {.html .htm}         }
		{{All Files}           *                 }
	    }
	    set ext ".html"
	    set initial [file tail $fromfile]
	}
	Word {
	    set types {
		{{Word file}          {.doc}         }
		{{All Files}           *                 }
	    }
	    set ext ".doc"
	    set initial [file root [file tail $fromfile]].doc
	}
	CSV {
	    set types {
		{{CSV file}         {.csv .txt}         }
		{{All Files}           *                 }
	    }
	    set ext ".csv"
	    set initial [file root [file tail $fromfile]].csv
	}
    }
    if { [file exists ConcretePrefs::reportexportdir] && \
	[file isdir $ConcretePrefs::reportexportdir] } {
	set defaultdir $ConcretePrefs::reportexportdir
    } else { set defaultdir "" }

    if { $::tcl_platform(platform) == "windows" } {
	set tofile [tk_getSaveFile -defaultextension $ext -filetypes $types \
	    -initialfile $initial -parent $w -initialdir $defaultdir \
	    -title "Save Results"]
    } else {
	set tofile [Browser-ramR file save]
    }


    if { $tofile == "" } { return }

    catch {
	set ConcretePrefs::reportexportdir [file dirname $filename]
    }

    if { [file ext $tofile] == ".html" || [file ext $tofile] == ".htm" } {
	set reportexportdir [file dirname $tofile]
	set imgdir [file join $reportexportdir timages]
	if { [file exists $imgdir] } {
	    set retval [tk_dialogRAM  $w._tmp Warning \
		[concat "Are you sure to delete directory "\
		    " '$imgdir' and all its contents?"]\
		warning 0 OK Cancel]
	    if { $retval == 1 } { return }
	    if { [catch {
		file delete -force $imgdir
	    } err] } {
		WarnWin "error: Could not delete directory '$imgdir' ($err)"
		return
	    }
	}

	if { [catch {
	    file copy -force [file join [file dirname $fromfile] timages] \
	    $imgdir
	    file copy -force $fromfile $tofile
	} err] } {
	    WarnWin [concat "Problems exporting report to '$tofile' ($err). "\
		"Check write permissions and disk space"]
	    return
	}
    } elseif { [file ext $tofile] == ".doc" || [file ext $tofile] == ".rtf" } {
	rtf:HTML2RTF $fromfile $tofile "Ram Series"
    } elseif { [file ext $tofile] == ".csv" || [file ext $tofile] == ".txt" } {
	rtf:HTML2CSV $fromfile $tofile "Ram Series"
    } else {
	WarnWin "Unknown extension for file '$tofile'"
	return
    }
    set comm [FindApplicationForOpening $tofile]
    # do not visualize
    set comm ""
    if { $comm == "" } {
	WarnWin "Report exported OK to file '$tofile'"
    } else {
	set text "Report exported OK to file '$tofile' Do you want to visualize it?"
	set retval [tk_messageBox -default no -icon question -message $text \
	    -parent $w -title "Report exported" -type yesno]
	if { $retval == "yes" } {
	    eval exec $comm [list [file native $tofile]] &
	}
    }
}
proc GiDHelpViewer::HTMLToClipBoardCSV { w } {
    set fromfile [GiveLastFile $w]
    rtf:HTML2CSV $fromfile "" "Ram Series"
    WarnWin Done
}
proc GiDHelpViewer::FindApplicationForOpening { file } {
    if { $::tcl_platform(platform) == "windows" } {
	return [auto_execok start]
    } else {
	set comm ""
	switch [string tolower [file extension $file]] {
	    ".htm" - ".html" {
		set comm [auto_execok konqueror]
		if { $comm == "" } {
		    set comm [auto_execok netscape]
		}
	    }
	    ".csv" - ".txt" {
		set comm [auto_execok kspread]
	    }
	}
    }
    return $comm
}

proc GiDHelpViewer::Clean { w } {
    variable indexstring
    variable HelpBaseDir

    array unset HelpBaseDir $w

    foreach trace [trace vinfo indexstring($w)] {
	trace vdelete indexstring($w) [lindex $trace 0] [lindex $trace 1]
    }
}

proc GiDHelpViewer::CloseWindow { w } {
    Clean $w
    destroy $w
}

proc GiDHelpViewer::SetInitialTab { w tab try } {
  variable notebook
  variable HelpBaseDir
  variable tree
  
  if {[lsearch "tree index search" $tab] == -1} {
    set tab tree
  }
  $notebook($w) raise $tab
  if {$tab eq "tree"} {
    if {$try eq ""} {
      set node_data [$tree($w) itemcget [lindex [$tree($w) nodes root] 0] -data]
      set link [lindex $node_data 1]
    } else {
      set link [file join $HelpBaseDir($w) $try]
    }
    JumpToLink $w $link
  }
}

proc GiDHelpViewer::Show {file args} {
    variable HelpBaseDir
    variable html
    variable tree
    variable searchlistbox1
    variable searchlistbox2
    variable notebook
    variable indexlistbox1
    variable indexlistbox2
    variable indexlist1
    variable indexlist2
    variable indexstring
    variable IndexInfo
    variable TitleCache
    variable waiting

    array set options {
	-title "Help"
	-try ""
	-report 0
	-base ""
	-tab "tree"
    }
    array set options $args
    if {$options(-base) eq ""} {
	if { $options(-report)} {
	    set options(-base) .gidreport
	    set GeometryName GiDReportWindowGeom
	} else {
	    set options(-base) .helpref
	    set GeometryName GiDHelpWindowGeom
	}
    } else {
	set GeometryName CustomHelpWindowGeom
    }

    set file [file normalize $file]
    if { [file isdir $file] } {
	set _HelpBaseDir $file
    } else {
	set _HelpBaseDir [file dirname $file]
    }

    set base $options(-base)
    set title $options(-title)
    
  if {[winfo exists $base] && [info exist HelpBaseDir($base)] && !$options(-report) && ($_HelpBaseDir eq $HelpBaseDir($base))} {
	# is the same window
	raise $base
	SetInitialTab $base $options(-tab) $options(-try) 

	#JumpToLink $base [file join $HelpBaseDir($base) $options(-try)]
	return $html($base)
    }
    # reinit the state
    Init $base
    set HelpBaseDir($base) $_HelpBaseDir

    if { [info command html] == "" } {
	set text "Package tkhtml could not be load, and so, it is not possible to see the help.\n"
	append text "The RamDebugger distribution only contains tkhtml libraries "
	append text "for Windows and Linux.\n"
	append text "You must get Tkhtml for other OS separately and install it in order to use the help"
	WarnWin $text
	return
    }
    
    global lastDir tcl_platform argv0

    #set imagesdir [file join [file dirname [info script]] images]

    if { $tcl_platform(platform) != "windows" } {
	option add *Scrollbar*Width 10
	option add *Scrollbar*BorderWidth 1
	option add *Button*BorderWidth 1
    }
    option add *Menu*TearOff 0

    if { $tcl_platform(platform) != "windows" } {
#           option add *background AntiqueWhite3
#           option add *Button*background bisque3
#           option add *Menu*background bisque3
#           option add *Button*foreground black
#           option add *Entry*background thistle
#           option add *DisabledForeground grey60
#           option add *HighlightBackground AntiqueWhite3
    }

    if { $title == "" } { set title Help }

    if { [info commands InitWindow] != "" } {
	InitWindow $base $title $GeometryName
    } else {
	toplevel $base
	wm title $base $title
    }
    wm protocol $base WM_DELETE_WINDOW "GiDHelpViewer::CloseWindow $base"
    wm withdraw $base

    # These images are used in place of GIFs or of form elements
    #

    if { [lsearch [image names] biggray] == -1 } {

	image create photo biggray -data {
	    R0lGODdhPAA+APAAALi4uAAAACwAAAAAPAA+AAACQISPqcvtD6OctNqLs968+w+G4kiW5omm
	    6sq27gvH8kzX9o3n+s73/g8MCofEovGITCqXzKbzCY1Kp9Sq9YrNFgsAO///
	}
	image create photo smgray -data {
	    R0lGODdhOAAYAPAAALi4uAAAACwAAAAAOAAYAAACI4SPqcvtD6OctNqLs968+w+G4kiW5omm
	    6sq27gvH8kzX9m0VADv/
	}
	image create photo nogifbig -data {
	    R0lGODdhJAAkAPEAAACQkADQ0PgAAAAAACwAAAAAJAAkAAACmISPqcsQD6OcdJqKM71PeK15
	    AsSJH0iZY1CqqKSurfsGsex08XuTuU7L9HywHWZILAaVJssvgoREk5PolFo1XrHZ29IZ8oo0
	    HKEYVDYbyc/jFhz2otvdcyZdF68qeKh2DZd3AtS0QWcDSDgWKJXY+MXS9qY4+JA2+Vho+YPp
	    FzSjiTIEWslDQ1rDhPOY2sXVOgeb2kBbu1AAADv/
	}
	image create photo nogifsm -data {
	    R0lGODdhEAAQAPEAAACQkADQ0PgAAAAAACwAAAAAEAAQAAACNISPacHtD4IQz80QJ60as25d
	    3idKZdR0IIOm2ta0Lhw/Lz2S1JqvK8ozbTKlEIVYceWSjwIAO///
	}
    }

    if { [lsearch [image names] imatge_fletxa_e] == -1 } {

	image create photo imatge_fletxa_e -data {
	    R0lGODlhJwAeAJECAE5qmoWh0f///wAAACH5BAEAAAIALAAAAAAnAB4AAAJb
	    lI+py+0Po5y00mBzCCDf3XnRBooQWZoNmqoK27oHTNc2Y+c69+4+HJr9hqSg
	    gIjkIZJDo4Hpcz6hOemUSrNeUYCu9wsOdx1AGY5rPsfSyzVbqH0r34s4/Y4v
	    AAA7
	}
	image create photo imatge_fletxa_d -data {
	    R0lGODlhJwAeAJECAE5qmoWh0f///wAAACH5BAEAAAIALAAAAAAnAB4AAAJa
	    lI+py+0Po5y0WhfuDVlT3nkRGIoYaT4klzYr677yPMf0fTP4Ti/8/1IAh6AE
	    cQgAII6/pJGJcz6hM6kiic1qtwCZtWV4fcGC1ZhMOqM56nUb/SYLlPK63VAA
	    ADs=
	}
	image create photo imatge_quit -data {
	    R0lGODlhIAAeAJECAE5qmoWh0f///wAAACH5BAEAAAIALAAAAAAgAB4AAAJm
	    lI+py+0Powq02kulwNwC2YVfVAHmiaYgNWpP6QYvG8sNrFU3nesLHgr+eEFh
	    AlgMHYlJ5QHZxJiezKintalaA1METpAKm64T3oqLpXJr3fI613anIXPvtmet
	    D/MasT/uEig4eFAAADs=
	}
	image create photo imatge_save -data {
	    R0lGODlhIAAeAOcAAEdjk05qmktnl1VxoWuHt2yIuUhklUlllVJunmSAsHuX
	    x4ik1Iml1YSg0EhklE9rm197q3aSwoai0oej04Wh0YSg0V57q01pmVt3p3GN
	    vYGez3yazpuy2YGe0XWRwVdzo2yIuIGdzYKf0IGe0KC229Lc7vz9/v///4Og
	    0FFtnUpmllNvn2eDs32ZyX2bzn+cz5ev2MfU6vT3+6W63YSh02N/r1BsnGJ+
	    rnmVxYSh0X6cz4+o1bvL5uzw+Njh8HqWxkpnl4Cdz4ij0rDC4eLp9P7+/1Rw
	    oExomIKezoKg0miEtEdklGmFtY2o1Pj6/H6by4ql04+p1Yej1Fh0pNvj8evw
	    +L/N54mk022JuWSAsYOh06i83vT2+8bT6pau14Kez/r7/fv8/dHc7qC123iY
	    zVx4qHaTw36c0NDb7dzk8qq933mYzXuZz4ah0aK11ZSs04Kf0XKOvmB8rIWi
	    1J602ufs9rXG44ul03qZzXmYzoOf0Zmv1LvH2Nbb3OPk3b/K2X+d0Pn6/fH1
	    +sDP55Kr1niYzoCd0JKq07PC19HX297g3d3f3djc3Nfb3Iai0WF9rXGOvoOg
	    0pCq1X+dz3uZzn2bz42n07LD3MvT2tzf3d3g3dnd3KG11XiUxMXP2tXY16Kp
	    p8vPz9vf39ve3MPN2X+c0MnT4H+Kiic5PomTluLl5drd3Iul0mWBsaK32b7D
	    wDlKTlRjZt3h4eXl3qm61oqm1tne4FNiZTpKT7rAwd3h4Nre3MTO2aO21Yei
	    0V56qsLO4Y6Xlig7P3mFh+Pl5Kq71oum0oCe0YSi1Jmw1svOzIaPj8fLyLLB
	    15Gq04Oh1Iek1H6aylNvoM3U2sPP4Jyy14Kg04ej1YOg0YCe0oaj1XeTw3yY
	    yIWh0YWh0YWh0YWh0YWh0YWh0YWh0YWh0YWh0YWh0YWh0YWh0YWh0YWh0YWh
	    0YWh0YWh0YWh0YWh0YWh0YWh0YWh0YWh0YWh0YWh0YWh0YWh0YWh0YWh0YWh
	    0YWh0YWh0YWh0YWh0YWh0SH5BAEAAP8ALAAAAAAgAB4AAAj+AP8JHEiwoEEA
	    AQwqXHhQwAACBQwwnFjwAIIEChYwaJCQIkMHDyBEkMBgAoUKDCx4NOjgAoYM
	    DUpS0LCBAocOHg6s/AdAwAcQIRgsoCBiwwgSJUycQCEhhUcVK1i0WLBAAgoX
	    L2DEkHGi64kZNGowPGDjBo4JDCTk0OFiB48eXuP60PEDiMIUESjIDLJByBAi
	    cQOfKCJkghGFR5BIKIpiho8igiMPSaJkCUsmDJqUcBK58wkiOp4cUThgAhTP
	    qKNImaJQgAIdVFALrmLlCgMsDg5m0bJFdlcuXbywrUDhywWFCCRUAOM5jJgx
	    GsiIoEBdbxmFB8ycQRM5jRoKa9j+tHHzBk71BXF0GpQzh07cOnbu4MmjZw+f
	    Pn7+AKpO3YbCBw1oEIgggxCyQSGGHIJIIooswggjjTjCHwOPYAdJJJJMQkkl
	    llyCSSaabPLgg4pwMkJ1E3SigkIYMECdI558Akoooow44iik7IciAgpdEIIE
	    FJRiyimopKKKjSOuwgpx1DHQCgAsFTBUB668AksssiDJyCiz0NIBdRPUosBo
	    Bn0wFAU52HILLrno8uAuiuzCSy++oCWBB78EcJxBR7QAJCDABCPMMMRokgkm
	    xRhzDDIT/FBDCuotBAALLsKRjDLLMJNIM8508Aw00ShhxIorSWMSBXBMQ001
	    elhzDRI1WExxBJQ7/aPCWRRgQ0E22lAQRxkX5FYrQTekVdI2cjwQ6bAEpbAA
	    N60gQCqziK0gAK3UBgQAOw==
	}

	image create photo appbook16 -data {
	    R0lGODlhEAAQAIQAAPwCBAQCBDyKhDSChGSinFSWlEySjCx+fHSqrGSipESO
	    jCR6dKTGxISytIy6vFSalBxydAQeHHyurAxubARmZCR+fBx2dDyKjPz+/MzK
	    zLTS1IyOjAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVkICCOZGmK
	    QXCWqTCoa0oUxnDAZIrsSaEMCxwgwGggHI3E47eA4AKRogQxcy0mFFhgEW3M
	    CoOKBZsdUrhFxSUMyT7P3bAlhcnk4BoHvb4RBuABGHwpJn+BGX1CLAGJKzmK
	    jpF+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0K
	    qSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpo
	    dHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
	}
	image create photo appbookopen16 -data {
	    R0lGODlhEAAQAIUAAPwCBAQCBExCNGSenHRmVCwqJPTq1GxeTHRqXPz+/Dwy
	    JPTq3Ny+lOzexPzy5HRuVFSWlNzClPTexIR2ZOzevPz29AxqbPz6/IR+ZDyK
	    jPTy5IyCZPz27ESOjJySfDSGhPTm1PTizJSKdDSChNzWxMS2nIR6ZKyijNzO
	    rOzWtIx+bLSifNTGrMy6lIx+ZCRWRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAae
	    QEAAQCwWBYJiYEAoGAFIw0E5QCScAIVikUgQqNargtFwdB9KSDhxiEjMiUlg
	    HlB3E48IpdKdLCxzEAQJFxUTblwJGH9zGQgVGhUbbhxdG4wBHQQaCwaTb10e
	    mB8EBiAhInp8CSKYIw8kDRSfDiUmJ4xCIxMoKSoRJRMrJyy5uhMtLisTLCQk
	    C8bHGBMj1daARgEjLyN03kPZc09FfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJ
	    RiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwg
	    cmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
	}
	image create photo filedocument16 -data {
	    R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJSWjPz+/Ozq7GxqbJyanPT29HRy
	    dMzOzDQyNIyKjERCROTi3Pz69PTy7Pzy7PTu5Ozm3LyqlJyWlJSSjJSOhOzi
	    1LyulPz27PTq3PTm1OzezLyqjIyKhJSKfOzaxPz29OzizLyidIyGdIyCdOTO
	    pLymhOzavOTStMTCtMS+rMS6pMSynMSulLyedAAAAAAAAAAAAAAAAAAAAAAA
	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaQ
	    QIAQECgajcNkQMBkDgKEQFK4LFgLhkMBIVUKroWEYlEgMLxbBKLQUBwc52Hg
	    AQ4LBo049atWQyIPA3pEdFcQEhMUFYNVagQWFxgZGoxfYRsTHB0eH5UJCJAY
	    ICEinUoPIxIcHCQkIiIllQYEGCEhJicoKYwPmiQeKisrKLFKLCwtLi8wHyUl
	    MYwM0tPUDH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24g
	    Mi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZl
	    ZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
	}
    }

    global showImages
    set showImages 1

    ################################################################################
    # the HTML viewer
    ################################################################################

    if {$options(-report)} {
	set sw [ScrolledWindow $base.lf -relief sunken -borderwidth 0]
    } else {
	set pw [PanedWindow $base.pw -side top -pad 0 -weights available -grid 0 -activator line]

	if { [catch {
	    foreach "weight1 weight2" [RamDebugger::ManagePanes $pw h "2 6"] break
	}]} {
	    set weight1 2
	    set weight2 6
	}
	set pane1 [$pw add -weight $weight1]
	
	$pane1 configure -bg \#add8d8
	NoteBook $pane1.nb -homogeneous 1 -bd 1 -internalborderwidth 3 -bg \#add8d8 \
	    -activebackground \#add8d8        -disabledforeground \#add8d8 -grid "0 py3"
	
	set notebook($base) $pane1.nb
	
	set f1 [$pane1.nb insert end tree -text "Contents"]
	
	set sw [ScrolledWindow $f1.lf -relief sunken -borderwidth 1 -grid "0"]
	set tree($base) [Tree $sw.tree -bg white\
		             -relief flat -borderwidth 2 -width 10 -highlightthickness 0\
		             -redraw 1 -deltay 18 -bg #add8d8 \
                             -showlines no \
		             -opencmd   "GiDHelpViewer::moddir $base 1" \
		             -closecmd  "GiDHelpViewer::moddir $base 0" \
		            ]

	$sw setwidget $tree($base)
	
	set font [option get $tree($base) font Font]

	if { $font != "" } {
          if {[set fm_ls [expr [font metrics $font -linespace]]]>18} {
            $tree($base) configure -deltay $fm_ls
          }
	}
	
	if { $::tcl_platform(platform) != "windows" } {
	    $tree($base) configure -selectbackground \#48c96f -selectforeground white
	}
	$pane1.nb itemconfigure tree -raisecmd "focus $tree($base)"
	
	set f2 [$pane1.nb insert end search -text "Search"]
	
	label $f2.l1 -text "S:" -bg #add8d8 -grid 0
	entry $f2.e1 -textvariable GiDHelpViewer::searchstring($base) -bg #add8d8 -grid "1 py3"
	
	$pane1.nb itemconfigure search -raisecmd "tkTabToWindow $f2.e1"
	bind $f2.e1 <Return> "focus $f2.lf1.lb; GiDHelpViewer::SearchInAllHelp $base"
	
	
	ScrolledWindow $f2.lf1 -relief sunken -borderwidth 1 -grid "0 2"
	set searchlistbox1($base) [listbox $f2.lf1.lb -listvar GiDHelpViewer::SearchFound($base) -bg white \
		                       -exportselection 0]
	$f2.lf1 setwidget $f2.lf1.lb
	
	ScrolledWindow $f2.lf2 -relief sunken -borderwidth 1 -grid "0 2"
	set searchlistbox2($base) [listbox $f2.lf2.lb -listvar GiDHelpViewer::SearchFound2($base) -grid "0 2" \
		                       -bg white -exportselection 0]
	$f2.lf2 setwidget $f2.lf2.lb
	
	set f3 [$pane1.nb insert 1 index -text "Index"]
	label $f3.l1 -text "S:" -bg #add8d8 -grid 0
	entry $f3.e1 -textvariable GiDHelpViewer::indexstring($base) -bg #add8d8 -grid "1 py3"
	bind $f3.e1 <Return> "focus $f3.sw1.lb; GiDHelpViewer::ShowItemIndex $base $f3.e1"
	trace variable indexstring($base) w "::GiDHelpViewer::FollowItemIndex $base"
	ScrolledWindow $f3.sw1 -relief sunken -borderwidth 1 -grid "0 2"
	listbox $f3.sw1.lb -listvar GiDHelpViewer::indexlist1($base) -grid "0 2" -bg white -exportselection 0
	ScrolledWindow $f3.sw2 -relief sunken -borderwidth 1 -grid "0 2"
	listbox $f3.sw2.lb -listvar GiDHelpViewer::indexlist2($base) -grid "0 2" -bg white -exportselection 0
	$pane1.nb itemconfigure index -raisecmd "GiDHelpViewer::CreateIndexTab $base; tkTabToWindow $f3.e1"
	bind $f3.sw1.lb <1> +[list focus $f3.sw1.lb]
	bind $f3.sw1.lb <FocusIn> "if { \[%W curselection] == {} } { %W selection set 0 }"
	bind  $f3.sw1.lb <Double-1> "focus $f3.sw1.lb; GiDHelpViewer::ShowItemIndex $base $f3.e1"
	bind  $f3.sw1.lb <Return> "focus $f3.sw1.lb; GiDHelpViewer::ShowItemIndex $base $f3.e1"
	bind  $f3.sw1.lb <<ListboxSelect>> "::GiDHelpViewer::UpdateIndexTitles $base"
	bind $f3.sw2.lb <1> +[list focus $f3.sw2.lb]
	bind $f3.sw2.lb <FocusIn> "if { \[%W curselection] == {} } { %W selection set 0 }"
	bind  $f3.sw2.lb <Double-1> "focus $f3.sw2.lb; GiDHelpViewer::ShowItemIndex $base $f3.e1"
	bind  $f3.sw2.lb <Return> "focus $f3.sw2.lb; GiDHelpViewer::ShowItemIndex $base $f3.e1"
	set indexlistbox1($base) $f3.sw1.lb
	set indexlistbox2($base) $f3.sw2.lb
	$f3.sw1 setwidget $f3.sw1.lb
	$f3.sw2 setwidget $f3.sw2.lb
	
	bind $f2.lf1.lb <FocusIn> "if { \[%W curselection] == {} } { %W selection set 0 }"
	bind $f2.lf1.lb <Double-1> "focus $f2.lf2.lb; GiDHelpViewer::SearchInAllHelpL1 $base"
	bind $f2.lf1.lb <Return> "focus $f2.lf2.lb; GiDHelpViewer::SearchInAllHelpL1 $base"
	bind $f2.lf2.lb <FocusIn> "if { \[%W curselection] == {} } { %W selection set 0 }"
	bind $f2.lf2.lb <Double-1> "GiDHelpViewer::SearchInAllHelpL2 $base"
	bind $f2.lf2.lb <Return> "GiDHelpViewer::SearchInAllHelpL2 $base"
	
	set GiDHelpViewer::SearchFound($base) ""
	set GiDHelpViewer::SearchFound2($base) ""
	
	supergrid::go $f1
	supergrid::go $f2
	supergrid::go $f3
	$pane1.nb compute_size
	#$pane1.nb raise tree
	
	set pane2 [$pw add -weight $weight2]
	
	set sw [ScrolledWindow $pane2.lf -relief sunken -borderwidth 0 -grid "0 2"]
    }

    set html($base) [html $sw.h \
		         -padx 5 \
		         -pady 9 \
		         -formcommand "GiDHelpViewer::FormCmd" \
		         -imagecommand "GiDHelpViewer::ImageCmd" \
		         -scriptcommand "GiDHelpViewer::ScriptCmd" \
		         -appletcommand "GiDHelpViewer::AppletCmd" \
		         -underlinehyperlinks 0 \
		         -bg white -tablerelief raised \
		         -resolvercommand "GiDHelpViewer::ResolveUri" \
		         -exportselection 1 \
		         -takefocus 1 \
		         -fontcommand "GiDHelpViewer::pickFont" \
		         -width 550 \
		         -height 500 \
		         -borderwidth 0 \
		         -selectioncolor        skyblue \
		         -unvisitedcolor blue1 \
		         -visitedcolor   blue3]
    $sw setwidget $html($base)

    bind $html($base).x <1> "focus $html($base); GiDHelpViewer::HrefBinding $base %x %y"

    bind $base <Control-c> "GiDHelpViewer::CopySelected $base"

    frame $base.buts -bg grey93 -grid "0 ew"

     if {$options(-report)} {
	 button $base.buts.b1 -image imatge_fletxa_e -bg grey93 -relief flat \
	     -command "GiDHistory::GoBackward $base" -height 50 \
	     -highlightthickness 0
	 button $base.buts.b2 -image imatge_fletxa_d -bg grey93 -relief flat \
	     -command "GiDHistory::GoForward $base" -height 50 \
	     -highlightthickness 0         
	 menubutton $base.buts.b3 -text "More..." -bg grey93 -fg \#add8d8 -relief flat \
	     -menu $base.buts.b3.m -activebackground grey93
     } else {
	 button $base.buts.b1 -image imatge_fletxa_e -bg grey93 -relief flat \
	     -command "GiDHistory::GoBackward $base" -height 50 -grid "0 e" \
	     -highlightthickness 0
	 button $base.buts.b2 -image imatge_fletxa_d -bg grey93 -relief flat \
	     -command "GiDHistory::GoForward $base" -height 50 -grid "1 w" \
	     -highlightthickness 0         
	 menubutton $base.buts.b3 -text "More..." -bg grey93 -fg \#add8d8 -relief flat \
	     -menu $base.buts.b3.m -grid "2 e" -activebackground grey93
     }
    
    menu $base.buts.b3.m
    $base.buts.b3.m add command -label "Home" -acc "" -command \
	     "GiDHistory::GoHome $base"
    $base.buts.b3.m add command -label "Previus" -acc "Alt-Left" -command \
	     "GiDHistory::GoBackward $base"
    $base.buts.b3.m add command -label "Next" -acc "Alt-Right" -command \
	     "GiDHistory::GoForward $base"
    $base.buts.b3.m add separator
    $base.buts.b3.m add command -label "Search in page..." -acc "Ctrl+F" -command \
	     "focus $html($base); GiDHelpViewer::SearchWindow $base"
    $base.buts.b3.m add command -label "Search more" -acc "F3" -command \
	     "focus $html($base); GiDHelpViewer::Search $base"
    $base.buts.b3.m add separator
    $base.buts.b3.m add command -label "Close" -acc "ESC" -command \
	     "GiDHelpViewer::CloseWindow $base"


#     menubutton $base.buts.b3 -image imatge_save -bg grey93 -relief flat \
#              -menu $base.buts.b3.m -height 50 -grid "2 e" -activebackground grey93

#     menu $base.buts.b3.m
#     $base.buts.b3.m add command -label "As HTML" -command \
#              "GiDHelpViewer::SaveHTMLAs $base HTML"
#     $base.buts.b3.m add command -label "As RTF file (Word)" -command \
#              "GiDHelpViewer::SaveHTMLAs $base Word"
#     $base.buts.b3.m add command -label "As CSV file (Excel)" -command \
#              "GiDHelpViewer::SaveHTMLAs $base CSV"
#     $base.buts.b3.m add command -label "Copy to clipboard (Excel)" -command \
#              "GiDHelpViewer::HTMLToClipBoardCSV $base"

    if { $HelpPrefs::RunningAlone } {
	button $base.buts.b4 -image imatge_quit -bg grey93 -relief flat \
		-command "exit" -height 50 -grid "3 e" \
	    -highlightthickness 0
    } else {
	if {$options(-report)} {
	    button $base.buts.b4 -image imatge_quit -bg grey93 -relief flat \
		-command "GiDHelpViewer::CloseWindow $base" -height 50 \
		-highlightthickness 0
	} else {
	    button $base.buts.b4 -image imatge_quit -bg grey93 -relief flat \
		-command "GiDHelpViewer::CloseWindow $base" -height 50 -grid "3 e" \
		-highlightthickness 0
	}
    }

    if {$options(-report)} {
	grid $base.buts.b1 -row 0 -column 0 -sticky w
	grid $base.buts.b2 -row 0 -column 1 -sticky w
	grid $base.buts.b3 -row 0 -column 3 -sticky e
	grid $base.buts.b4 -row 0 -column 4 -sticky e
	
	grid columnconf $base.buts 2 -weight 1
	grid $sw -row 0 -column 0 -sticky "snew"
	 grid $base.buts -row 1 -column 0 -sticky "ew"
	grid columnconfigure $base 0 -weight 1
	grid rowconfigure $base 0 -weight 1
	grid rowconfigure $base 1 -weight 0
    } else {
	supergrid::go $base

	supergrid::go $pane1
	supergrid::go $pane2
    }

    if {!$options(-report)} {
	grid columnconf $base.buts "0 1" -weight 1
	grid columnconf $base.buts "2 3 4 " -weight 0
    }


    # This procedure is called when the user selects the File/Open
    # menu option.
    #
    set lastDir [pwd]

    #           $base.h.h token handler Frameset "FrameCmd $base"
    #           $base.h.h token handler Frame "FrameCmd $base"
    #           $base.h.h token handler /Frameset "FrameCmd $base"


    # This binding changes the cursor when the mouse move over
    # top of a hyperlink.
    #
    bind HtmlClip <Motion> {
	set parent [winfo parent %W]
	set url [$parent href %x %y]
	if {[string length $url] > 0} {
	    $parent configure -cursor hand2
	} else {
	    $parent configure -cursor {}
	}
    }

    focus $html($base)

    bind $html($base)
    bind $html($base) <Prior> {
	%W yview scroll -1 pages
    }

    bind $html($base) <Next> {
	%W yview scroll 1 pages
    }
    bind $html($base) <Up> {
	%W yview scroll -1 units
    }

    bind $html($base) <Down> {
	%W yview scroll 1 units
    }
    bind $html($base) <Left> {
	%W xview scroll -1 units
    }

    bind $html($base) <Right> {
	%W xview scroll 1 units
    }
    bind $html($base) <Home> {
	%W yview moveto 0
    }

    if {"unix" eq $::tcl_platform(platform)} {
	foreach "but units" [list 4 -1 5 1] {
	    set comm [string map "%d $units" {
		::GiDHelpViewer::MouseWheel %W %d %x %y
	    }]
	    bind $base <$but> $comm
	}
    } else {
	bind $html($base) <MouseWheel> {
	    ::GiDHelpViewer::MouseWheel %W [expr int(-1*%D/36)] %x %y
	}
    }

    bind $html($base) <End> {
	%W yview moveto 1
    }

    
    bind $base <1> "GiDHelpViewer::ManageSel $base %W %x %y press"
    bind $base <B1-Motion> "GiDHelpViewer::ManageSel $base %W %x %y motion"
    bind $base <ButtonRelease-1> "GiDHelpViewer::ManageSel $base %W %x %y release"
    if { $tcl_platform(platform) != "windows"} {
	selection handle $html($base) "GiDHelpViewer::CopySelected $base"
    }
    
    if {!$options(-report)} {
	$tree($base) bindText  <ButtonPress-1>             "GiDHelpViewer::Select $base 1"
	$tree($base) bindText  <Double-ButtonPress-1>    "GiDHelpViewer::Select $base 2"
	$tree($base) bindImage  <ButtonPress-1>             "GiDHelpViewer::Select $base 1"
	$tree($base) bindImage  <Double-ButtonPress-1>   "GiDHelpViewer::Select $base 2"
	$tree($base) bindText <Control-ButtonPress-1>    "GiDHelpViewer::Select $base 3"
	$tree($base) bindImage  <Control-ButtonPress-1>  "GiDHelpViewer::Select $base 3"
	$tree($base) bindText <Shift-ButtonPress-1>             "GiDHelpViewer::Select $base 4"
	$tree($base) bindImage  <Shift-ButtonPress-1>    "GiDHelpViewer::Select $base 4"
	# dirty trick
	foreach i [bind $tree($base).c] {
	    bind $tree($base).c $i "+ [list after idle [list GiDHelpViewer::Select $base 0 {}]]"
	}
	bind $tree($base).c <Return> "GiDHelpViewer::Select $base 1 {}"
	bind $tree($base).c <KeyPress> "if \[string is wordchar -strict {%A}] {GiDHelpViewer::KeyPress $base %A}"
	bind $tree($base).c <Alt-KeyPress-Left> ""
	bind $tree($base).c <Alt-KeyPress-Right> ""
	bind $tree($base).c <Alt-KeyPress> { break }
	FillDir $base root
    }
	
    bind [winfo toplevel $html($base)] <Alt-Left> "GiDHistory::GoBackward $base; break"
    bind [winfo toplevel $html($base)] <Alt-Right> "GiDHistory::GoForward $base; break"
	

    bind $base <Control-f> "focus $html($base); GiDHelpViewer::SearchWindow $base; break"
    bind $base <F3> "focus $html($base); GiDHelpViewer::Search $base; break"
    bind $base <Escape> "GiDHelpViewer::CloseWindow $base"
    
    # If an arguent was specified, read it into the HTML widget.
    #
    update
    if {$file!=""} {
	# ES ESTO NECESARIO??????
	#LoadFile $html $file
    }
    #set x [expr [winfo screenwidth $base]/2-400]
    #set y [expr [winfo screenheight $base]/2-300]
    #wm geom $base 800x600+${x}+$y

    update idletasks
    wm deiconify $base
    EnterLastFile $base ""
    if {$options(-report)} {
	LoadFile $base $file
    } else {
	SetInitialTab $base $options(-tab) $options(-try)
    }

    return $html($base)
}

proc GiDHelpViewer::HelpSearchWord { w word } {
    variable notebook

    set GiDHelpViewer::searchstring($w) $word
    $notebook($w) raise search
    SearchInAllHelp $w
}

proc GiDHelpViewer::HelpDirs { args } {
    variable FillInfo
    eval wHelpDirs $FillInfo(toplevel) $args
}

proc GiDHelpViewer::wHelpDirs { w args } {
  variable FillInfo
  variable tree
  variable tmp
  
  set idxfolder 0
  set node $FillInfo($w,node)
  
  foreach dinfo $args {
    set dir [lindex $dinfo 0]
    set fullpath [file join $FillInfo($w,dir) $dir]
    if {[set ldinfo [llength $dinfo]] == 1} {
      # try to set the name as the title of the possible
      # table of contents defined in $fullpath/help.conf
      set name [FigureOutNodeName $w $fullpath]
    } else {
      set name [lindex $dinfo 1]
    }
    if {$ldinfo < 3} {
      if {$ldinfo == 2} {
        # this will find out a possible tocpage
        FigureOutNodeName $w $fullpath
      }
      set intro_page $tmp(tocpage)
    } else {
      set intro_page [lindex $dinfo 2]
    }
    if { [file isdir $fullpath] } {
      regsub -all {\s} $fullpath _ item
      $tree($w) insert $idxfolder $node $item -image appbook16 -text $name \
          -data [eval list folder [list $fullpath] $intro_page] -drawcross allways
      incr idxfolder
    }
  }
}

proc GiDHelpViewer::GetHREFValue {param} {
    # esta lsearch quizas con -regexp con la expresion que aparece debajo!!!
    set idx [lsearch -glob [string toupper $param] HREF=*]
    if {$idx == -1} {
	set link ""
    } else  {
      if {![regexp -nocase -- {HREF(?:\s*)=(?:\s*)"(.*)"} [lindex $param $idx] {} link]} {
        WarnWinText "fallo en $param"
      }
    }
    set link
}

proc GiDHelpViewer::GetTITLE { w file } {
    variable TitleCache

    if {[info exists TitleCache($w,$file)]} {
	return $TitleCache($w,$file)
    }
    set content [::fileutil::cat $file]
    if {![regexp -nocase <title>(.+)</title> $content {} title]} {
	set title "[file tail $file] (No TITLE)"
    }
    set TitleCache($w,$file) $title
}

proc  GiDHelpViewer::ProcessIndexUL {w tag slash param text} {
  variable IndexInfo
  variable indexlist1
  
  set tag [string toupper $tag]
  switch $tag {
    UL {
      if {$slash eq ""} {
        set IndexInfo($w,TAGState) "INDEXOPEN"
      } else {
        set IndexInfo($w,TAGState) "INDEXCLOSE"
      }
    }
    LI {
      # ignore </li>
      if {$slash eq "" && $IndexInfo($w,TAGState) eq "INDEXOPEN"} {
        set IndexInfo($w,TAGState) "LI"
        set IndexInfo($w,LI,text) [string trim [::htmlparse::mapEscapes $text]] 
      }
    }
    A {
      IndexOnA $w $tag $slash $param $text
    }
    default {
      if {$IndexInfo($w,TAGState) eq "LI"} {
        append IndexInfo($w,INATAG,text) "[::htmlparse::mapEscapes $text]"
      }
    }
  }
}

proc GiDHelpViewer::IndexOnA {w tag slash param text} {
  variable IndexInfo
  variable indexlist1

  if {$IndexInfo($w,TAGState) eq "LI"} {
    if {$slash eq ""} {
      set IndexInfo($w,INATAG) 1
      set IndexInfo($w,INATAG,link) [GetHREFValue $param]
      set IndexInfo($w,INATAG,text) $text
    } else {
      set IndexInfo($w,INATAG) 0
      if {![regexp {(.*)\#(.*)} $IndexInfo($w,INATAG,link) {} file tag]} {
        set file $IndexInfo($w,INATAG,link)
        set tag ""
      }
      # find the Title of page
      set file [file join $IndexInfo($w,BaseDir) $file]
      set TITLE [GetTITLE $w $file]
      foreach txt [list $IndexInfo($w,LI,text) $IndexInfo($w,INATAG,text)] {
        if {$txt eq ""} continue
        if {[lsearch $indexlist1($w) $txt]==-1} {
          lappend indexlist1($w) $txt
        }
        if {![info exists IndexInfo($w,$txt)] || 
            [lsearch -regexp $IndexInfo($w,$txt) $TITLE]==-1} {
          lappend IndexInfo($w,$txt) [list $TITLE $file $tag]
        }
      }
      set IndexInfo($w,TAGState) "INDEXOPEN"
    }
  }
}

proc  GiDHelpViewer::ProcessIndexDIR {w tag slash param text} {
  variable IndexInfo
  variable indexlist1
  
  set tag [string toupper $tag]
  switch $tag {
    DIR {
      if {$slash eq ""} {
        set IndexInfo($w,TAGState) "INDEXOPEN"
      } else {
        set IndexInfo($w,TAGState) "INDEXCLOSE"
      }
    }
    LI {
      # ignore </li>
      if {$slash eq "" && $IndexInfo($w,TAGState) eq "INDEXOPEN"} {
        set IndexInfo($w,TAGState) "LI"
        set IndexInfo($w,LI,text) [string trim [::htmlparse::mapEscapes $text]]
      }
    }
    A {
      IndexOnA $w $tag $slash $param $text
    }
    default {
      if {$IndexInfo($w,TAGState) eq "LI"} {
        append IndexInfo($w,INATAG,text) "[::htmlparse::mapEscapes $text]"
      }
    }
  }
}

proc GiDHelpViewer::IndexPage { args } {
  variable FillInfo
  
  eval wIndexPage $FillInfo(toplevel) $args
}

proc GiDHelpViewer::wIndexPage { w args } {
  variable IndexInfo
  variable FillInfo
  variable indexstring
  
  foreach arg $args {
    set page [lindex $arg 0]
    set type DIR
    if {[llength $arg] > 1} {
      set type [lindex $arg 1]
    }
    set fullpath [file join $FillInfo($w,dir) $page]
    lappend IndexInfo($w,pages) [list $fullpath $type]
    set IndexInfo($w,$fullpath,created) 0
  }
}

proc GiDHelpViewer::CreateIndexTab { w } {
  variable HelpBaseDir
  variable IndexInfo
  variable indexlist1
  
  if {![llength $indexlist1($w)]} {
    WaitState $w 1
    foreach indexpage $IndexInfo($w,pages) {
      set IndexInfo($w,TAGState) ""
      set page [lindex $indexpage 0]
      if {!$IndexInfo($w,$page,created)} {
        set type [lindex $indexpage 1]
        set IndexInfo($w,BaseDir) [file dir $page]
        htmlparse::parse -cmd "GiDHelpViewer::ProcessIndex$type $w" \
            [fileutil::cat $page]
        set IndexInfo($w,$page,created) 1
      }
    }
    set indexlist1($w) [lsort $indexlist1($w)]
    FollowItemIndex $w
    WaitState $w 0
  }
}

proc GiDHelpViewer::FollowItemIndex { w args } {
    variable indexstring
    variable indexlist1
    variable indexlistbox1
    variable indexlistbox2

    set idx [lsearch -glob $indexlist1($w) $indexstring($w)*]
    $indexlistbox1($w) selection clear 0 end

    if { $idx != -1} {
	$indexlistbox1($w) see $idx
	$indexlistbox1($w) selection set $idx
	$indexlistbox1($w) selection anchor $idx
    }
    UpdateIndexTitles $w
}

# -------------------------------------------------------------------------------
# GiDHelpViewer::UpdateIndexTitles --
#
# -------------------------------------------------------------------------------

proc GiDHelpViewer::UpdateIndexTitles { w } {
    variable indexlistbox1
    variable indexlistbox2
    variable indexlist1
    variable IndexInfo
    variable indexlist2

    set cursel1 [$indexlistbox1($w) curselection]
    set indexlist2($w) ""
    set IndexInfo($w,titles) ""
    if {$cursel1 ne ""} {
	foreach idxinfo $IndexInfo($w,[lindex $indexlist1($w) $cursel1]) {
	    lappend indexlist2($w) [lindex $idxinfo 0]
	}
	$indexlistbox2($w) selection set 0
    }
}

proc GiDHelpViewer::ShowItemIndex { w eindex } {
    variable html
    variable indexlistbox1
    variable indexlistbox2
    variable indexlist1
    variable IndexInfo
    variable data
    
    set idxttl [$indexlistbox2($w) curselection]
    if {$idxttl eq ""} {
	focus $eindex
    } else {
	# Asumo que si idxttl != "" es porque $indexlistbox1 curselection != ""
	set idxinfo [lindex $IndexInfo($w,[lindex $indexlist1($w) [$indexlistbox1($w) curselection]]) $idxttl]
	#puts " LoadFile $html [lindex $idxinfo 1] 1 [lindex $idxinfo 2]"
	set data($w,sync) 1
	LoadFile $w [lindex $idxinfo 1] 1 [lindex $idxinfo 2]
    }
}

proc GiDHelpViewer::FindContentsStructure {w tag slash param text} {
  variable FillInfo

  if {$FillInfo($w,STOPPED)} {
    return
  }
  if {$slash eq "" && [string equal -nocase $tag "div"]} {
    if {[regexp -nocase -- {class(?:\s*)=(?:\s*)\"(.+)\"} $param => class]} {
      if {[string equal -nocase $class "contents"]} {
        # found "<div class="contents">
        set FillInfo($w,STOPPED) 1
        set FillInfo($w,contents,class) [string toupper $class]
      } elseif {[string equal -nocase $class "shortcontents"]} {
        # found "<div class="shortcontents">
        set FillInfo($w,contents,class) [string toupper $class]
        # but not stop looking for
      }
    }
  }
}


proc GiDHelpViewer::ContentsOnA {w tag slash param text} {
  variable FillInfo
  variable tree

  if {$slash eq ""} {
    set FillInfo($w,INATAG) 1
    set FillInfo($w,INATAG,link) [GetHREFValue $param]
    set FillInfo($w,INATAG,text) [::htmlparse::mapEscapes $text]
  } else {
    set FillInfo($w,INATAG) 0
    set fullpath [file join $FillInfo($w,dir) $FillInfo($w,INATAG,link)]
    regsub -all {\s} $fullpath _ item
    while {[$tree($w) exists $item]} {
      append item 1
    }
    $tree($w) insert end $FillInfo($w,parent) $item -image filedocument16 \
        -text [string trim $FillInfo($w,INATAG,text)] -data [list file $fullpath]
    set FillInfo($w,LastNode) $item
  }
}

proc GiDHelpViewer::ProcessTOCUL {w tag slash param text} {
  variable FillInfo
  variable tree
  
  if {$FillInfo($w,STOPPED)} {
    return
  }
  set tag [string toupper $tag]
  switch $tag {
    TITLE {
      if {$slash eq ""} {
        set FillInfo($w,contents,title) [::htmlparse::mapEscapes $text]
      }
    }
    DIV {
      if {$slash eq ""} {
        if {[regexp -nocase -- {class(?:\s*)=(?:\s*)\"(.+)\"} $param => class]} {
          if {[string equal -nocase $class $FillInfo($w,contents,class)]} {
            set FillInfo($w,contents,class) "inside"
          }
        }
      } else {
        if {$FillInfo($w,contents,class) eq "inside"} {
          set FillInfo($w,contents,class) "outside"
          set FillInfo($w,STOPPED) 1
        }
      }
    }
    UL {
      if {$FillInfo($w,contents,class) eq "inside"} {
        if {$slash eq "" } {
          $FillInfo($w,stack) push $FillInfo($w,parent)
          if {$FillInfo($w,LastNode) ne ""} {
            set FillInfo($w,parent) $FillInfo($w,LastNode)
          }
        } else {
          # si el ultimo parent tiene ahora hijos entonces le pongo 
          # la imagen de book.
          if {$FillInfo($w,parent) ne "root" && [llength [$tree($w) nodes $FillInfo($w,parent)]]} {
            set data_node [$tree($w) itemcget $FillInfo($w,parent) -data]
            $tree($w) itemconfigure $FillInfo($w,parent) -image appbook16 \
                -data [lreplace $data_node 0 0 folder]
          }

          if {[$FillInfo($w,stack) size]} {
            set FillInfo($w,parent) [$FillInfo($w,stack) pop]
          } 
          set FillInfo($w,STOPPED) [expr ![$FillInfo($w,stack) size]]
        }
      }
    }
    LI {
      # ignore </li>
      if {$slash eq "" && $FillInfo($w,contents,class) eq "inside"} {
        set FillInfo($w,TAGState) "LI"
      }
    }
    A {
      if {$FillInfo($w,TAGState) eq "LI"} {
        ContentsOnA $w $tag $slash $param  $text
        if {$slash ne ""} {
          set FillInfo($w,TAGState) ""
        }
      }
    }
    default {
      if {$FillInfo($w,INATAG)} {
        append FillInfo($w,INATAG,text) "[::htmlparse::mapEscapes $text]"
      }
    }
  }
}

proc GiDHelpViewer::ProcessTOCDL {w tag slash param text} {
  variable FillInfo
  variable tree
  
  set tag [string toupper $tag]
  switch $tag {
    TITLE {
      if {$slash eq ""} {
        set FillInfo($w,contents,title) [::htmlparse::mapEscapes $text]
      }
    }
    DL {
      if {$slash eq ""} {
        set FillInfo($w,TAGState) DLOPEN
      } else {
        set FillInfo($w,TAGState) DLCLOSE
      }
    }
    DD {
      if {$FillInfo($w,TAGState) eq "DLOPEN"} {
        #puts "   $text"
      }
    }
    A {
      if {$FillInfo($w,TAGState) eq "DLOPEN"} {
        ContentsOnA $w $tag $slash $param $text
      }
    }
    default {
      if {$FillInfo($w,INATAG)} {
        append FillInfo($w,INATAG,text) [::htmlparse::mapEscapes $text]
      }
    }
  }
}

proc GiDHelpViewer::FigureOutNodeName { w path } {
  variable tmp

  foreach cmd {TocPage IndexPage HelpDirs} {
    rename $cmd ${cmd}Saved
  }
  proc ::TocPage {page {type UL}} {
    set ::GiDHelpViewer::tmp(tocpage) $page
    set page [file normalize [file join $::GiDHelpViewer::tmp(path) $page]]
    set ::GiDHelpViewer::tmp(title) \
        [GiDHelpViewer::GetTITLE $::GiDHelpViewer::FillInfo(toplevel) $page]
  }
  proc ::IndexPage {args} {
  }
  proc ::HelpDirs {args} {
  }
  set tmp(tocpage) ""
  set tmp(path) $path
  set helpconf [file join $path "help.conf"]
  if {[file exists $helpconf]} {
    eval [fileutil::cat $helpconf]
  }
  if {[set tmp(title) [string trim $tmp(title)]] eq ""} {
    set tmp(title) "UNNAMED - $path"
  }
  # restore the original commands
  foreach cmd {TocPage IndexPage HelpDirs} {
    rename ${cmd}Saved $cmd
  }
  set tmp(title)  
}

proc GiDHelpViewer::TocPage { page {type UL}} {
    variable FillInfo

    eval wTocPage $FillInfo(toplevel) $page $type
}

proc GiDHelpViewer::wTocPage { w page {type UL}} {
  variable FillInfo
  # aqui lleno a partir de FillInfo(node)
  
  set FillInfo($w,TAGState) ""
  set FillInfo($w,parent) $FillInfo($w,node)
  set FillInfo($w,LastNode) ""
  set FillInfo($w,stack) [::struct::stack::stack]
  set FillInfo($w,STOPPED) 0
  set FillInfo($w,INATAG) 0
  set FillInfo($w,contents,class) "inside"
  # look for the contents structure, could be in this order of priority:
  #   contents
  #   shortconstents
  #   unstructured
  set toc_file [fileutil::cat [file join $FillInfo($w,dir) $page]]
  htmlparse::parse -cmd "GiDHelpViewer::FindContentsStructure $w" $toc_file
  set FillInfo($w,STOPPED) 0
  # now fill the structure
  set save_dir $FillInfo($w,dir)
  set FillInfo($w,dir) [file normalize [file join $FillInfo($w,dir) [file dirname $page]]]
  htmlparse::parse -cmd "GiDHelpViewer::ProcessTOC$type $w" $toc_file
  set FillInfo($w,dir) $save_dir
  $FillInfo($w,stack) destroy
}

proc GiDHelpViewer::FillDir { w node } {
  variable HelpBaseDir
  variable FillInfo
  variable tree
  
  if { $node == "root" } {
    set dir $HelpBaseDir($w)
  } else {
    set dir [lindex [$tree($w) itemcget $node -data] 1]
  }
  
  set idxfolder 0
  set files ""
  
  set FillInfo(toplevel) $w
  
  set FillInfo($w,node) $node
  set FillInfo($w,dir) $dir
  set FillInfo($w,contents,title) ""
  
  # check for hlpdir.conf file
  set hlpconf [file join $dir "help.conf"]
  if {[file exists $hlpconf]} {
    eval [fileutil::cat $hlpconf]
    if {$node ne "root"} {
      if {[regexp -- ^UNNAMED [$tree($w) itemcget $node -text]] && 
          $FillInfo($w,contents,title) ne ""} {
        $tree($w) itemconfigure $node -text $FillInfo($w,contents,title)
      }
    }
  } else {        
    foreach i [glob -nocomplain -dir $dir *] {
      lappend files [file tail $i]
    }
    
    foreach i [lsort -dictionary $files] {
      set fullpath [file join $dir $i]
      regsub {^[0-9]+} $i {} name
      regsub -all {\s} $fullpath _ item
      if { [file isdir $fullpath] } {
        if { $i == "images" } { continue }
        $tree($w) insert $idxfolder $node $item -image appbook16 -text $name \
            -data [list folder $fullpath] -drawcross allways
        incr idxfolder
      } elseif { [string match .htm* [file ext $i]] } {
        set name [file root $i]
        $tree($w) insert end $node $item -image filedocument16 -text $name \
            -data [list file $fullpath]
      }
    }
  }
}

proc GiDHelpViewer::moddir { w idx node } {
  variable HelpBaseDir
  variable tree
  
  if { $idx && [$tree($w) itemcget $node -drawcross] == "allways" } {
    FillDir $w $node
    $tree($w) itemconfigure $node -drawcross "auto"
    
    if { [llength [$tree($w) nodes $node]] } {
      $tree($w) itemconfigure $node -image appbookopen16
    } else {
      $tree($w) itemconfigure $node -image appbook16
    }
  } else {
    if { [lindex [$tree($w) itemcget $node -data] 0] == "folder" } {
      switch $idx {
        0 { set img appbook16 }
        1 { set img appbookopen16 }
      }
      $tree($w) itemconfigure $node -image $img
    }
  }
}

proc GiDHelpViewer::KeyPress { w a } {
    variable tree
    variable searchstring

    set node [$tree($w) selection get]
    if { [llength $node] != 1 } { return }

    append searchstring($w) $a
    after 300 [list set GiDHelpViewer::searchstring($w) ""]

    if { [$tree($w) itemcget $node -open] == 1 && [llength [$tree($w) nodes $node]] > 0 } {
	set parent $node
	set after 1
    } else {
	set parent [$tree($w) parent $node]
	set after 0
    }

    foreach i [$tree($w) nodes $parent] {
	if { !$after } {
	    if { $i == $node } {
		if { [string length $GiDHelpViewer::searchstring($w)] > 1 } {
		    set after 2
		} else {
		    set after 1
		}
	    }
	}
	if { $after == 2 && [string match -nocase $GiDHelpViewer::searchstring($w)* \
		[$tree($w) itemcget $i -text]] } {
	    $tree($w) selection clear
	    $tree($w) selection set $i
	    $tree($w) see $i
	    return
	}
	if { $after == 1 } { set after 2 }
    }
    foreach i [$tree($w) nodes [$tree($w) parent $node]] {
	if { $i == $node } { return }
	if { [string match -nocase $GiDHelpViewer::searchstring($w)* [$tree($w) itemcget $i -text]] } {
	    $tree($w) selection clear
	    $tree($w) selection set $i
	    $tree($w) see $i
	    return
	}
    }
}

proc GiDHelpViewer::FindTopicNode { w node {from root}} {
    variable tree

    foreach n [$tree($w) nodes $from] {
	if {$node eq [string range $n 0 [expr [string length $node]-1]]} {
	    if {[$tree($w) itemcget $n -drawcross] == "allways"} {
		#node wait to be filled
		FillDir $w $n
		$tree($w) itemconfigure $n -drawcross "auto"
	    }
	    return [list $n]
	}
	if {[$tree($w) itemcget $n -drawcross] == "allways"} {
	    #node wait to be filled
	    FillDir $w $n
	    $tree($w) itemconfigure $n -drawcross "auto"
	}
	# now we can try inside $n
	set node_path [FindTopicNode $w $node $n]
	if {[llength $node_path]} {
	    return [linsert $node_path 0 $n]
	}
    }
    return [list]
}

proc  GiDHelpViewer::FindTopicNodeForPage { w page } {
    regsub -all {\s} $page _ nodeid
    set node_path [FindTopicNode $w $nodeid]
}

proc GiDHelpViewer::OpenNodePath { w node_path } {
    variable tree

    if {[llength $node_path]} {
	foreach parent $node_path {
	    $tree($w) itemconfigure $parent -open 1
	    if {[$tree($w) itemcget $parent -image] ne "filedocument16"} {
		$tree($w) itemconfigure $parent -image "appbookopen16"
	    }
	}
	set nodeid [lindex $node_path end]
	$tree($w) selection set $nodeid
	$tree($w) see $nodeid
	$tree($w) xview moveto 0
    }
}

proc GiDHelpViewer::SyncContents { w page } {
    OpenNodePath $w [FindTopicNodeForPage $w $page]
}

proc GiDHelpViewer::JumpToLink { w link } {
    variable tree
    variable html
    variable notebook
    # extract tag
    
    WaitState $w 1
    $notebook($w) raise tree
    if {![regexp {(.*)\#(.*)} $link {} file tag]} {
	set file $link
	set tag ""
    }

    regsub -all {\s} $link _ nodeid
    
    set node_path [FindTopicNode $w $nodeid]
    if {[llength $node_path]} {
	OpenNodePath $w $node_path
	set data [$tree($w) itemcget $nodeid -data]
	if {[llength $data] > 2} {
	    set file [file join [lindex $data 1] [lindex $data 2]]
	}
	if {$tag eq ""} {
	    LoadFile $w $file
	} else {
	    # este update lo necesito para que funcione el yview de $html
	    update idletasks
	    LoadFile $w $file 1 $tag
	}
    }
    WaitState $w 0
}

proc GiDHelpViewer::Select { w num node } {
  variable tree
  variable dblclick
  variable html
    
  focus $tree($w)
  
  if { $node == "" } {
    set node [$tree($w) selection get]
    if { [llength $node] != 1 } { return }
  } elseif { ![$tree($w) exists $node] } {
    return
  }
  set dblclick 1
  
  WaitState $w 1
  
  if { $num >= 1 } {
    if { [$tree($w) itemcget $node -open] == 0 } {
      $tree($w) itemconfigure $node -open 1
      set idx 1
    } else {
      $tree($w) itemconfigure $node -open 0
      set idx 0
    }
    moddir $w $idx $node
    if {[$tree($w) itemcget $node -drawcross] eq "auto" &&
        ![llength [$tree($w) nodes $node]]} {
      set isleaf 1 
    } else {
      set isleaf 0
    }
    if { $num == 1 && $idx == 0 && !$isleaf} {
      WaitState $w 0
      return
    }
    $tree($w) selection set $node
    if { [llength [$tree($w) selection get]] == 1 } {
      # no se por que no se sigue trabajando con $node
      # trabaje con node y no con selection get
      # set data [$tree($w) itemcget [$tree($w) selection get] -data]
      set data [$tree($w) itemcget $node -data]
      if { $num >= 1 && $num <= 2 } {
        if {[llength $data] == 2} {
          set fref [lindex $data 1]
        } else {
          set fref [file join [lindex $data 1] [lindex $data 2]]
        }
        if {[regexp {(.*)\#(.*)} $fref {} file tag]} {
          LoadFile $w $file 1 $tag
        } else {
          LoadFile $w $fref
        }
      }
    }
    WaitState $w 0
    return
  }
  WaitState $w 0
}

proc GiDHelpViewer::TryToSelect { w name {num 3}} {
    variable HelpBaseDir
    variable tree

    set nameL [file split $name]

    set level [llength [file split $HelpBaseDir($w)]]
    set node root
    while 1 {
	set found 0
	foreach i [$tree($w) nodes $node] {
	    if { [lindex [$tree($w) itemcget $i -data] 1] == [eval file join [lrange $nameL 0 $level]] } {
		set found 1
		break
	    }
	}
	if { !$found } { return }
	if { [lindex [$tree($w) itemcget $i -data] 0] == "folder" } {
	    if { [$tree($w) itemcget $i -open] == 0 } {
		$tree($w) itemconfigure $i -open 1
	    }
	    moddir $w 1 $i
	}

	if { $level == [llength $nameL]-1 } {
	    Select $w $num $i
	    return
	}
	set node $i
	incr level
    }
}

proc GiDHelpViewer::Search { w } {
    variable html

    if { ![info exists ::GiDHelpViewer::searchstring($w)] } {
	WarnWin "Before using 'Continue search', use 'Search'" $w
	return
    }
    if { $GiDHelpViewer::searchstring($w) != "" } {

	set comm [list $html($w) text find $GiDHelpViewer::searchstring($w)]
	if { $::GiDHelpViewer::searchcase($w) == 0 } {
	    lappend comm nocase
	}

	if { $GiDHelpViewer::SearchType($w) == "-forwards" } {
	    if { $GiDHelpViewer::SearchPos($w) != "" } {
		lappend comm after $GiDHelpViewer::SearchPos($w)
	    } else {
		lappend comm after 1.0
	    }
	} else {
	    if { $GiDHelpViewer::SearchPos($w) != "" } {
		lappend comm before $GiDHelpViewer::SearchPos($w)
	    } else {
		lappend comm before end
	    }
	}
	set idx1 ""
	foreach "idx1 idx2" [eval $comm] break

	if { $idx1 == "" } {
	    bell
	} else {
	    scan $idx2 "%d.%d" line char
	    set idx2 $line.[expr $char+1]
	    $html($w) selection set $idx1 [$html($w) index $idx2]

	    set y [lindex [$html($w) coords $idx1] 1]

	    if { $y == "" } { set y 0 }

	    set height [lindex [$html($w) coords end] end]

	    foreach "f1 f2" [$html($w) yview] break
	    set ys [expr $y/double($height)-($f2-$f1)/2.0]
	    if { $ys < 0 } { set ys 0 }
	    $html($w) yview moveto $ys
	    #$html($w) refresh
	    set GiDHelpViewer::SearchPos($w) $idx1
	}
    }
}

proc GiDHelpViewer::SearchWindow { w } {
    variable html

    set f [DialogWin::Init $html($w) "Search" separator]
    set top [winfo toplevel $f]

    label $f.l1 -text "Text:" -grid 0
    entry $f.e1 -textvariable ::GiDHelpViewer::searchstring($w) -grid "1 px3 py3"

    set f25 [frame $f.f25 -bd 1 -relief ridge -grid "0 2 w px3"]
    radiobutton $f25.r1 -text Forward -variable ::GiDHelpViewer::SearchType($w) \
	-value -forwards -grid "0 w"
    radiobutton $f25.r2 -text Backward -variable ::GiDHelpViewer::SearchType($w) \
	-value -backwards -grid "0 w"

    set f3 [frame $f.f3 -grid "0 2 w"]
    checkbutton $f3.cb1 -text "Consider case" -variable ::GiDHelpViewer::searchcase($w) \
	-grid 0
    checkbutton $f3.cb2 -text "From beginning" -variable ::GiDHelpViewer::searchFromBegin($w) \
	-grid 1

    supergrid::go $f

    if { ![info exists ::GiDHelpViewer::searchstring($w)] } {
	set ::GiDHelpViewer::searchstring($w) ""
    }

#     set ::GiDHelpViewer::searchmode($w) -exact
#     set ::GiDHelpViewer::searchcase($w) 0
#     set ::GiDHelpViewer::searchFromBegin($w) 0
#     set ::GiDHelpViewer::SearchType($w) -forwards

    tkTabToWindow $f.e1
    bind $top <Return> "DialogWin::InvokeOK"

    set action [DialogWin::CreateWindow]
    switch $action {
	0 {
	    DialogWin::DestroyWindow
	    return
	}
	1 {
	    if { $::GiDHelpViewer::searchstring($w) == "" } {
		DialogWin::DestroyWindow
		return
	    }
	    set ::GiDHelpViewer::SearchPos($w) ""
	    Search $w
	    DialogWin::DestroyWindow
	}
    }
}

proc GiDHelpViewer::CreateIndex { w } {
    variable HelpBaseDir
    variable Index
    variable IndexFilesTitles
    variable progressbar
    variable progressbarStop
    variable html

    if {[llength [array names Index $w,*]]} { return }
    if { [file exists [file join $HelpBaseDir($w) wordindex]] } {
	set fin [open [file join $HelpBaseDir($w) wordindex] r]
	foreach "IndexFilesTitles($w) aa" [read $fin] break
	#array set Index $aa
	foreach "idx value" $aa {
	    set Index($w,$idx) $value
	}
	close $fin
	return
    }

    WaitState $w 1

    ProgressDlg $html($w).prdg -textvariable GiDHelpViewer::progressbarT($w) -variable \
	    GiDHelpViewer::progressbar($w) -title "Creating search index" \
	     -troughcolor \#48c96f -stop Stop -command "set GiDHelpViewer::progressbarStop($w) 1"

    set progressbar($w) 0
    set progressbarStop($w) 0

    array unset Index $w,*

    set files [::fileutil::findByPattern $HelpBaseDir($w) "*.htm *.html"]

    set len [llength [file split $HelpBaseDir($w)]]
    set ipos 0
    set numfiles [llength $files]

    set IndexFilesTitles($w) ""

    foreach i $files {
	set GiDHelpViewer::progressbar($w) [expr int($ipos*50/$numfiles)]
	set GiDHelpViewer::progressbarT($w) $GiDHelpViewer::progressbar($w)%
	if { $GiDHelpViewer::progressbarStop($w) } {
	    destroy $html($w).prdg
	    return
	}

	set fin [open $i r]
	set aa [read $fin]

	set file [eval file join [lrange [file split $i] $len end]]
	set title ""
	regexp {(?i)<title>(.*?)</title>} $aa {} title
	if { $title == "" } {
	    regexp {(?i)<h([1234])>(.*?)</h\1>} $aa {} {} title
	}
	lappend IndexFilesTitles($w) [list $file $title]
	set IndexPos [expr [llength $IndexFilesTitles($w)]-1]

	foreach j [regexp -inline -all -- {-?\w{3,}} $aa] {
	    if { [string is integer $j] || [string length $j] > 25 || [regexp {_[0-9]+$} $j] } {
		continue
	    }
	    lappend Index($w,[string tolower $j]) $IndexPos
	}
	close $fin
	incr ipos
    }

    proc IndexesSortCommand { e1 e2 } {
	upvar freqs freqsL
	if { $freqsL($e1) > $freqsL($e2) } { return -1 }
	if { $freqsL($e1) < $freqsL($e2) } { return 1 }
	return 0
    }

    set names [array names Index]
    set len [llength $names]
    set ipos 0
    foreach i $names {
	set GiDHelpViewer::progressbar($w) [expr 50+int($ipos*50/$len)]
	set GiDHelpViewer::progressbarT($w) $GiDHelpViewer::progressbar($w)%
	if { $GiDHelpViewer::progressbarStop($w) } {
	    destroy $html($w).prdg
	    return
	}
	foreach j $Index($i) {
	    set title [lindex [lindex $IndexFilesTitles($w) $j] 1]
	    if { [string match -nocase *$i* $title] } {
		set icr 10
	    } else { set icr 1 }
	    if { ![info exists freqs($j)] } {
		set freqs($j) $icr
	    } else { incr freqs($j) $icr }
	}
#           if { $i == "variable" } {
#               puts "-----variable-----"
#               foreach j $Index($i) {
#                   puts [lindex $IndexFilesTitles $j]-----$j
#               }
#               parray freqs
#           }
	set Index($i) [lrange [lsort -command GiDHelpViewer::IndexesSortCommand [array names freqs]] \
		0 4]

#           if { $i == "variable" } {
#               puts "-----variable-----"
#               foreach j [lsort -command GiDHelpViewer::IndexesSortCommand [array names freqs]] {
#                   puts [lindex $IndexFilesTitles $j]-----$j
#               }
#           }
	unset freqs
	incr ipos
    }

    set GiDHelpViewer::progressbar($w) 100
    set GiDHelpViewer::progressbarT($w) $GiDHelpViewer::progressbar($w)%
    destroy $html($w).prdg
    set fout [open [file join $HelpBaseDir($w) wordindex] w]
    # aqui tengo que eliminar el nombre de la ventana $w del get
    set pairs [list]
    set starti [expr [string length $w]+1]
    foreach {idx value} [array get Index $w,*] {
	set i [string range $idx $starti end]
	lappend pairs $i $value
    }
#    puts -nonewline $fout [list $IndexFilesTitles($w) [array get Index $w,*]]
    puts -nonewline $fout [list $IndexFilesTitles($w) $pairs]
    close $fout
    WaitState $w 0
}

proc GiDHelpViewer::IsWordGood { w word otherwords } {
    variable Index
    variable IndexFilesTitles

    if { $otherwords == "" } { return 1 }

    if { ![info exists Index($w,$word)] } { return 0 }

    foreach i $Index($w,$word) {
	set file [lindex [lindex $IndexFilesTitles($w) $i] 0]
	if { [HasFileTheWord $w $file $otherwords] } { return 1 }
    }
    return 0
}

proc GiDHelpViewer::HasFileTheWord { w file otherwords } {
    variable HelpBaseDir
    variable Index
    variable IndexFilesTitles
    variable FindWordInFileCache

    set fullfile [file join $HelpBaseDir($w) $file]

    foreach word $otherwords {
	if { [info exists FindWordInFileCache($w,$file,$word)] } {
	    if { !$FindWordInFileCache($w,$file,$word) } { return 0 }
	    continue
	}
	set fin [open $fullfile r]
	set aa [read $fin]
	close $fin
	if { [string match -nocase *$word* $aa] } {
	    set FindWordInFileCache($w,$file,$word) 1
	} else {
	    set FindWordInFileCache($w,$file,$word) 0
	    return 0
	}
    }
    return 1
}

proc GiDHelpViewer::SearchInAllHelp { w } {
    variable HelpBaseDir
    variable Index
    variable searchlistbox1

    set word [string tolower $GiDHelpViewer::searchstring($w)]
    CreateIndex $w

    set GiDHelpViewer::SearchFound($w) ""
    set GiDHelpViewer::SearchFound2($w) ""

    if { [string trim $word] == "" } { return }

    set words [regexp -all -inline {\S+} $word]
    if { [llength $words] > 1 } {
	set word [lindex $words 0]
	set otherwords [lrange $words 1 end]
    } else { set otherwords "" }

    set ipos 0
    set iposgood -1
    set starti [expr [string length $w]+1]
    foreach idx [array names Index $w,*$word*] {
	set i [string range $idx $starti end]
	if { ![IsWordGood $w $i $otherwords] } { continue }

	lappend GiDHelpViewer::SearchFound($w) $i
	if { [string equal $word [lindex $i 0]] } { set iposgood $ipos }
	incr ipos
    }
    if { $iposgood == -1 && [llength [GiveManHelpNames $GiDHelpViewer::searchstring($w)]] > 0 } {
	lappend GiDHelpViewer::SearchFound($w) $GiDHelpViewer::searchstring($w)
	set iposgood $ipos
    }

    if { $iposgood >= 0 } {
	$searchlistbox1($w) selection clear 0 end
	$searchlistbox1($w) selection set $iposgood
	$searchlistbox1($w) see $iposgood
	SearchInAllHelpL1 $w
    }
}

proc GiDHelpViewer::SearchInAllHelpL1 { w } {
    variable Index
    variable IndexFilesTitles
    variable SearchFound2
    variable SearchFound2data
    variable searchlistbox1
    variable searchlistbox2

    set SearchFound2($w) ""
    set SearchFound2data($w) ""

    set sels [$searchlistbox1($w) curselection]
    if { $sels == "" } {
	bell
	return
    }

    set words [regexp -all -inline {\S+} $GiDHelpViewer::searchstring($w)]
    if { [llength $words] > 1 } {
	set otherwords [lrange $words 1 end]
    } else { set otherwords "" }

    set ipos 0
    set iposgood -1
    set iposgoodW -1
    foreach i $sels {
	set word [$searchlistbox1($w) get $i]
	if { [info exists Index($w,$word)] } {
	    foreach i $Index($w,$word) {
		foreach "file title" [lindex $IndexFilesTitles($w) $i] break

		if { ![HasFileTheWord $w $file $otherwords] } { continue }

		if { [lsearch $GiDHelpViewer::SearchFound2($w) $title] != -1 } { continue }

		lappend SearchFound2($w) $title
		lappend SearchFound2data($w) $i
		if { [string match -nocase *$word* $title] } {
		    set W 1
		    foreach i $otherwords {
		        if { [string match -nocase *$i* $title] } { incr W }
		    }
		    if { [string match -nocase *$GiDHelpViewer::searchstring($w)* $title] } { incr W }
		    if { [string equal -nocase $GiDHelpViewer::searchstring($w) $title] } { incr W }

		    if { $W > $iposgoodW } {
		        set iposgood $ipos
		        set iposgoodW $W
		    }
		}
		incr ipos
	    }
	}
	foreach i [GiveManHelpNames $word] {
	    lappend SearchFound2($w) $i
	    if { $iposgood == -1 } {
		set iposgood $ipos
	    } else { set iposgood -2 }
	    incr ipos
	}
    }
    if { $iposgood < 0 && $ipos > 0 } { set iposgood 0 }
    if { $iposgood >= 0 } {
	focus $searchlistbox2($w)
	$searchlistbox2($w) selection clear 0 end
	$searchlistbox2($w) selection set $iposgood
	$searchlistbox2($w) see $iposgood
	SearchInAllHelpL2 $w
    }
}

proc GiDHelpViewer::SearchInAllHelpL2 { w } {
    variable HelpBaseDir
    variable SearchFound2data
    variable IndexFilesTitles
    variable SearchFound
    variable SearchFound2
    variable html
    variable searchlistbox1
    variable searchlistbox2
    variable searchstring
    variable data

    set sels [$searchlistbox2($w) curselection]
    if { [llength $sels] != 1 } {
	bell
	return
    }
    if { [regexp {(.*)\(man (.*)\)} [lindex $SearchFound2($w) $sels]] } {
	SearchManHelpFor $w [lindex $SearchFound2($w) $sels]
    } else {
	set i [lindex $SearchFound2data($w) $sels]
	set file [file join $HelpBaseDir($w) [lindex [lindex $IndexFilesTitles($w) $i] 0]]

	set word [lindex $SearchFound($w) [lindex [$searchlistbox1($w) cursel] 0]]
	# deshabilito el draw del html
	$html($w) draw disabled
	# esto es para que load lo deje deshabilitado
	set data($w,draw) disabled
	# para sincronizar con el arbol
	set data($w,sync) 1
	LoadFile $w $file 1
	set searchstring($w) $word
	Search $w
	set data($w,draw) enabled
	$html($w) draw enabled
    }
}

proc GiDHelpViewer::WaitState { w what } {
    variable tree
    variable html
    variable indexlistbox1
    variable indexlistbox2
    variable waiting

    if {$what && $waiting($w)} return

    if {$what} {
	set cursor watch
    } else {
	set cursor ""
    }
    foreach _w [list $w $html($w)] {
	    $_w configure -cursor $cursor
    }
    catch {
	foreach _w [list $tree($w) $indexlistbox1($w) $indexlistbox2($w)] {
	    $_w configure -cursor $cursor
	}
    }
    set waiting($w) $what
    update idletasks
}

# taken from http://mini.net/tcl/557.

namespace eval browser {
  variable data
}

proc browser::findExecutable {progname} {
  variable data

  set progs [auto_execok $progname]
  if {[llength $progs]} {
    set data(BROWSER) $progs
    return 1
  }
  return 0
}

proc browser::urlOpen {url} {
  variable data
  switch $::tcl_platform(platform) {
    "unix" {
      expr {
            [info exists data(BROWSER)] ||
            [findExecutable netscape]   ||
            [findExecutable mozilla]    ||
            [findExecutable konqueror]    ||
            [findExecutable iexplorer]  ||
            [findExecutable lynx]
          }
      # lynx can also output formatted text to a variable
      # with the -dump option, as a last resort:
      # set formatted_text [ exec lynx -dump $url ] - PSE
      if {[catch {exec $data(BROWSER) -remote openurl($url)}]} {
        # perhaps browser doesn't understand -remote flag
        if {[catch {exec $data(BROWSER) $url &} emsg]} {
          error "Error displaying $url in browser\n$emsg"
          # Another possibility is to just pop a window up
          # with the URL to visit in it. - DKF
        }
      }
    }
    "windows" {
      catch {
        eval exec [auto_execok start] $url >& NUL: &
      }
    }
    "macintosh" {
      if {0 == [info exists data(BROWSER)]} {
        set data(BROWSER) "Browse the Internet"
      }
      if {[catch {
        AppleScript execute\
            "tell application \"$data(BROWSER)\"
                         open url \"$url\"
                     end tell
                "} emsg]
        } then {
        error "Error displaying $url in browser\n$emsg"
      }
    }
  } ;## end of switch
}

if { 0 || [info exists argv0] && [info script] == $argv0 } {
    wm withdraw .
    package require Tkhtml
    if { $::tcl_platform(platform) != "windows"} {
	set file {/c/TclTk/RamDebugger/help}
    } else {
	set file {/TclTk/RamDebugger/help}
    }
    GiDHelpViewer::HelpWindow $file
}

if { 0 } {
    set dirload [file dir [info script]]
    
    proc LoadAddons { } {
	foreach f {dialogwin.tcl supergrid.tcl} {
	    source [file join $::dirload $f]
	}
    }
    
    LoadAddons
}

# force supergrid autoload

supergrid::autoload