# specBM.tcl -- PDF-like bookmarks for DVI files with TkDVI
# Copyright © 2001 Anselm Lingnau <anselm@strathspey.org>
# See file COPYING for conditions on use and distribution.
# $Id: specBM.tcl,v 1.2 2001/08/10 09:36:09 anselm Exp $

namespace eval ::tkdvi::browser::special {}

option add *m.windows.l_bookmarks {&Bookmarks ...} userDefault
option add *m.windows.c_bookmarks [list ::tkdvi::browser::bookmarks::show %T] \
	userDefault
option add *m.windows.a_bookmarks Ctrl+B userDefault

::tkdvi::menu::extra windows bookmarks

proc ::tkdvi::browser::special::bookmark {name key x y cookie s} {
    variable ::tkdvi::browser::State
    # puts stderr "bookmark: »$s«"
    if {[::info exists State($name-bmFinalized)] \
	    && $State($name-bmFinalized)} {
	return
    } elseif {[string equal $s {bookmark begin}]} {
	::tkdvi::browser::bookmarks::begin $name
    } elseif {[string equal $s {bookmark end}]} {
	set State($name-bmFinalized) 1
	::tkdvi::browser::bookmarks::end $name
    } elseif {[regexp {bookmark add ([0-9]+) ([^ ]+) ([^ ]*) (.*)} \
	    $s junk level mark parent title]} {
	::tkdvi::browser::bookmarks::add $name $level $mark $title
    }
}

namespace eval ::tkdvi::browser::bookmarks {}

::tkdvi::browser::addHook open ::tkdvi::browser::bookmarks::disable

proc ::tkdvi::browser::bookmarks::disable {name} {
    foreach {menu idx} [::tkdvi::menu::finditem $name \
	    [::msgcat::mc "Bookmarks *"]] {
	$menu entryconfigure $idx -state disabled
    }
}

proc ::tkdvi::browser::bookmarks::begin {name} {
    variable ::tkdvi::browser::State

    if {[info exists State($name-bookmarks)]} {
	destroy $State($name-bookmarks)
    }
    set State($name-bookmarks) [toplevel $State($name-top).bookmarks]
    wm withdraw $State($name-bookmarks)
    wm title $State($name-bookmarks) \
	    [::msgcat::mc {Bookmarks: %s} [file tail \
	    [file rootname [$State($name-code) info filename]]]]
    set t [text $State($name-bookmarks).t -width 40 -height 20 -wrap word \
	    -cursor arrow -background white -font {Helvetica -12} \
	    -yscrollcommand [list $State($name-bookmarks).sy set]]
    $t tag configure level0 -lmargin1 0 -lmargin2 30
    $t tag configure level1 -lmargin1 20 -lmargin2 50
    $t tag configure level2 -lmargin1 40 -lmargin2 70
    $t tag configure level3 -lmargin1 60 -lmargin2 90
    $t tag configure level4 -lmargin1 80 -lmargin2 110
    bindtags $t [list bookmark Text]
    bind bookmark <1> [namespace code [list goto $name]]
    grid $t -row 0 -column 0 -sticky nwse
    scrollbar $State($name-bookmarks).sy -orient vertical \
	    -command [list $t yview]
    grid $State($name-bookmarks).sy -row 0 -column 1 -sticky ns
    grid rowconfigure $State($name-bookmarks) 0 -weight 1
    grid columnconfigure $State($name-bookmarks) 0 -weight 1
    frame $State($name-bookmarks).f
    button $State($name-bookmarks).f.close -text [::msgcat::mc Close] \
	    -command [list wm withdraw $State($name-bookmarks)]
    pack $State($name-bookmarks).f.close
    grid $State($name-bookmarks).f -row 1 -column 0 -columnspan 2
}

proc ::tkdvi::browser::bookmarks::end {name} {
    variable ::tkdvi::browser::State
    $State($name-bookmarks).t configure -state disabled
    foreach {menu idx} [::tkdvi::menu::finditem $name \
	    [::msgcat::mc "Bookmarks *"]] {
	$menu entryconfigure $idx -state normal
    }
}

proc ::tkdvi::browser::bookmarks::add {name level mark title} {
    variable ::tkdvi::browser::State
    regsub -all {\\([0-7][0-7][0-7])} $title {[format "%c" 0\1]} title
    regsub -all {\\\(} $title {(} title
    regsub -all {\\\)} $title {)} title
    set title [subst -nobackslashes -novariables $title]
    $State($name-bookmarks).t insert end \
	    $title [list level$level m-$mark] "\n"
}

proc ::tkdvi::browser::bookmarks::goto {name} {
    variable ::tkdvi::browser::State
    variable ::tkdvi::browser::Configure
    foreach tag [$State($name-bookmarks).t tag names current] {
	if {[string match m-* $tag]} {
	    set anchor [string range $tag 2 end]
	    set page [$State($name-code) findanchor $anchor]
	    if {$page >= 0} {
		if {[string equal $Configure($name-mode) spread] \
			&& $page % 2 == 1} {
		    incr page -1
		}
		::$name gotopage $page
	    }
	}
    }
}

proc ::tkdvi::browser::bookmarks::show {name} {
    variable ::tkdvi::browser::State
    wm deiconify $State($name-bookmarks)
}

package provide tkdvi::browser::special::bookmark 1.0
