# linkui.tcl
# Edit user interface for links.

proc Url_InsertLink { win args } {
    upvar #0 HM$win var

    foreach htag [Mark_FullStack $win insert all] {
	if {[string match "a *" $htag]} {
	    return [Url_EditLink $win]
	}
    }
    if [catch {$win index sel.first}] {
	DialogInfo $win "No link here.  Select the text for the link first."
	return
    }
    set message \
"To create a link to another page, enter the URL of the
other page in the HREF field.

To create an anchor within the document that can be the
destination of other links, enter a descriptive name
in the NAME field.

To create an link to another frame within the document,
enter the name of the frame in the TARGET field."

    set sel.first [$win index sel.first]
    set sel.last [$win index sel.last]

    set info [Dialog_Htag $win {a HREF= NAME= TARGET=} {} $message [list UrlChooseHook1 $win]]
    if {[llength $info] != 0} {
	Undo_Mark $win Url_InsertLink
	set htag [lindex $info 0]
	set params [lindex $info 1]
	regsub { nuke!=".+"} $params {} params
	regsub {^a *} $params {} params
	Text_TagAdd $win sel ${sel.first} ${sel.last}
	Input_Tag $win "$htag $params"
	Undo_Mark $win Url_InsertLinkEnd
    }
}
proc UrlEditLink {win htag mark} {
    LogBegin $win UrlEditLink $htag $mark
    HMextract_param $htag href oldhref
    HMextract_param $htag name oldname

    set message \
"To create a link to another page, enter the URL of the
other page in the HREF field.

To create an anchor within the document that can be the
destination of other links, enter a descriptive name
in the NAME field.

To create an link to another frame within the document,
enter the name of the frame in the TARGET field."
    set info [Dialog_Htag $win {a HREF= NAME= TARGET=} $htag $message \
	    [list UrlChooseHook2 $win]]
    if {[llength $info] != 0} {
	set tag H:$htag
	set clear 1
	set nuke! {}
	HMextract_param $info nuke!
	switch -- ${nuke!} {
	    "Clear link from selection" {
		if [catch {$win index sel.first}] {
		    Status $win "No selection to clear link from"
		    return
		}
		set range [list [$win index sel.first] [$win index sel.last]]
	    }
	    "Delete entire link" {
		set range [Edit_CurrentRange $win $tag $mark]
	    }
	    default {
		set range [Edit_CurrentRange $win $tag $mark]
		set clear 0
	    }
	}
	if {[llength $range] == 0} {
	    Status $win "Lost range for $tag ?"
	    return
	}
	Undo_Mark $win EditLink
	eval {Text_TagRemove $win $tag} $range
	if [info exists oldhref] {
	    eval {Text_TagRemove $win link} $range
	}
	if [info exists oldname] {
	    eval {Text_TagRemove $win anchor} $range
	    Text_MarkUnset $win N:$oldname
	    if $clear {
		lassign {beg end} [$win tag nextrange $tag 1.0]
		if {[string length $beg]} {
		    Text_MarkSet $win N:$oldname [$win index $beg]
		}
	    }
	}
	Input_Dirty $win
	if {$clear} {
	    Undo_Mark $win EditLinkDone
	    return
	}
	set params [lindex $info 1]
	regsub { nuke!=".+"} $params {} params
	set htag "a $params"
	eval {Text_TagAdd $win H:$htag} $range
	HMextract_param $htag href
	HMextract_param $htag name
	if [info exists name] {
	    eval {Text_TagAdd $win anchor} $range
	    $win mark set N:$name [lindex $range 0]
	}
	if [info exists href] {
	    eval {Text_TagAdd $win link} $range
	    HMlink_setup $win $htag
	}
	Undo_Mark $win EditLinkDone
    }
}
proc UrlChooseHook1 {win f dialogVar} {
    upvar #0 $dialogVar dialog
    # The first entry is the HREF, and we want different bindings

    set e $f.f0.entry
    set g [frame $f.url1]
    label $g.label -text "Browse:"
    button $g.hist -text "Url History" \
	-command [list UrlHistoryChooser $win $f $e $dialogVar]
    button $g.rel -text "Files..." \
	-command [list UrlRelativeChooser $win $f $e $dialogVar]
    button $g.anchor -text "Anchor Names" \
	-command [list UrlAnchorChooser $win $f $e $dialogVar]
    pack $g -side top -padx 5
    pack $g.label $g.hist $g.rel $g.anchor -side left

}
proc UrlChooseHook2 {win f dialogVar} {
    upvar #0 $dialogVar dialog
    # The first entry is the HREF, and we want different bindings

    UrlChooseHook1 $win $f $dialogVar

    tk_optionMenu $f.but.nuke $dialogVar\(nuke!) "Do not delete" "Delete entire link" "Clear link from selection"
    lappend dialog(_names) nuke!
    set dialog(required,nuke!) 0
    pack $f.but.nuke -side bottom -expand true
}

proc UrlChoiceFrame {f {list {}}} {
    if [winfo exists $f.url] {
	eval destroy [winfo children $f.url]
	set g $f.url
    } else {
	set g [frame $f.url -bd 4 -relief ridge]
	pack $g -side top -fill both -padx 10
    } 
    if {$list != {}} {
	set l [listbox $g.list -xscrollcommand "$g.scrollx set" \
		-yscrollcommand "$g.scrolly set" -height 6 -width 40]
	scrollbar $g.scrollx -command "$l xview" -orient horiz
	scrollbar $g.scrolly -command "$l yview" -orient vert
	pack $g.scrollx -side bottom -fill x
	pack $g.scrolly -side right -fill y
	pack $g.list -side top -fill both
    }
    return $g
}
proc Url_Open {win} {
    upvar #0 URL$win urlwin
    set urlwin(status) 0
    set urlwin(newwin) 0

    set t $win.urlopen
    if [winfo exists $t] {
	destroy $t
    }
    toplevel $t -bd 4 -relief ridge
    set f [frame $t.top -bd 5]
    label $f.label -text URL:
    set e [entry $f.entry -textvariable URL$win\(HREF)]
    pack $f -side top -fill x
    pack $f.label -side left
    pack $f.entry -side top -fill x
    frame $t.rim ; pack $t.rim -side top -fill x
    UrlHistoryChooser $win $t.rim $e URL$win
    bind $e <Return> "
	set URL$win\(status) 1
	destroy $win.urlopen
	break"
    bind $e <Shift-Return> "
	set URL$win\(status) 1
	set URL$win\(newwin) 1
	destroy $win.urlopen
	break"

    set f [frame $t.bot -bd 5]
    button $f.ok -text OK -command "set URL$win\(status) 1 ; destroy $win.urlopen"
    checkbutton $f.new -text "New Window" -variable URL$win\(newwin)
    button $f.cancel -text Cancel -command "set URL$win\(status) 0 ; destroy $win.urlopen"
    pack $f -side top -fill x
    pack $f.ok -side left 
    pack $f.cancel -side right
    pack $f.new -side top -pady 4

    focus $e
    tkwait window $win.urlopen

    if $urlwin(status) {
	if $urlwin(newwin) {
	    Url_DisplayNew $urlwin(HREF) $win
	} else {
	    Url_Display $win $urlwin(HREF)
	}
    }
}
proc UrlHistoryChooser {win f e dialogVar} {
    upvar $dialogVar dialog
    set g [UrlChoiceFrame $f list]
    set l $g.list

    global History
    foreach url [lsort [array names History]] {
	$l insert end $url
    }
    bind $l <ButtonRelease-1> "
	set $dialogVar\(HREF) \[$l get \[$l index @%x,%y]] 
    "
    # Reach in and add leap search bindings to the HREF entry
    UrlEntry_Setup $e $l
}
proc UrlAnchorChooser {win f e dialogVar} {
    upvar $dialogVar dialog
    set g [UrlChoiceFrame $f list]
    set l $g.list

    global History
    foreach m [$win mark names] {
	if [regexp {^N:(.*)$} $m x anchor] {
	    $l insert end $anchor
	}
    }
    bind $l <ButtonRelease-1> "
	set $dialogVar\(HREF) #\[$l get \[$l index @%x,%y]] 
    "
}
proc UrlRelativeChooser {win f e dialogVar} {
    upvar $dialogVar dialog
    upvar #0 HM$win var
    if {[string length $var(S_url)] == 0} {
	# New file w/out save
	File_SaveAs $win	;# Force a base for the URLs.
	return
    }
    catch {destroy $f.url}
    set path [fileselect "Choose a File" "" file]
    if {[string length $path]} {
	set x file:$path
	UrlRelative $var(S_url) x
	$e delete 0 end
	$e insert 0 $x
    }
}
proc UrlRelativeChooserOld {win f e dialogVar} {
    upvar $dialogVar dialog
    upvar #0 HM$win var
    if {[string length $var(S_url)] == 0} {
	# New file w/out save
	File_SaveAs $win	;# Force a base for the URLs.
	return
    }
    set g [UrlChoiceFrame $f]
    set path [$e get]
    set base $var(S_url)
    UrlResolve $base path
    regsub ^file: $path {} path
    regsub ^/+ $path / path
    set lb [fileselectEmbedded $g $path]

    bind $lb <Button-1> [list UrlRelativeClick %W %y $base $e]
    bind $lb <Double-Button-1> break	;# Make this a no-op

    trace variable fileselect(done) w [list UrlPathTrace $base $e]

    bindtags $e [list RelEntry $e Entry]
    bind RelEntry <space> [list UrlRelativeSpace $win $e $base $dialogVar]
    bind RelEntry <Return> [list UrlRelativeReturn $win $e $base $dialogVar]
    bind RelEntry <Control-u> [list $e delete 0 end]

}
proc UrlRelativeReturn {win e base dialogVar} {
    upvar #0 HM$win var
    global fileselect
    if $fileselect(done) {
	return		;# Assume user is happy
    }
    set fileselect(path) [$e get]
    UrlRelativeSelect $base $e
    if !$fileselect(done) {
	return -code break
    } else {
	# normal return and let $e <Return> binding fire
	return
    }
}
proc UrlRelativeSpace {win e base dialogVar} {
    upvar #0 HM$win var
    global fileselect
    set fileselect(path) [$e get]
    fileselectComplete
    UrlRelativeSelect $base $e
    return -code break
}
proc UrlRelativeClick {lb y base e} { 
    global fileselect
    set x [$lb get [$lb nearest $y]]
    set fileselect(path) $x
    UrlRelativeSelect $base $e
}
proc UrlRelativeSelect {base e} {
    global fileselect
    fileselectOK
    $e delete 0 end
    if {[string length $fileselect(path)]} {
	if $fileselect(done) {
	    set x file:$fileselect(path)
	} else {
	    set x file:[file join $fileselect(dir) $fileselect(path)]
	}
	UrlRelative $base x
	$e insert 0 $x
    } elseif {[string length $fileselect(dir)]} {
	set x file:$fileselect(dir)
	UrlRelative $base x
	$e insert 0 $x
    }
}
proc UrlPathTrace {base e args} {
    global fileselect
    if $fileselect(done) {
	UrlRelativeSelect $base $e
    }
}

