# help.tcl --
#
#	Implements the AngbandTk Help System.
#

namespace eval NSHelp {

variable Priv

# NSHelp::InitModule --
#
#	One-time-only-ever initialization.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitModule {} {

	global Windows
	variable Priv

	set Priv(font) [Global font,fixed,normal]
	set Priv(find,string) ""
	set Priv(find,index) 1.0

	NSObject::New NSHelp
}

# NSHelp::NSHelp --
#
#	Create a help window.
#
# Arguments:
#	oop					OOP ID. See above.
#
# Results:
#	.

proc NSHelp oop {

	global Windows

	InitWindow $oop

#update

	SetText $oop command.txt

	NSWindowManager::RegisterWindow help [Info $oop win] \
		"NSHelp::GeometryCmd $oop" "" "NSHelp::DisplayCmd $oop"

	#
	# Global list of application windows
	#

	set Windows(help,win) [Info $oop win]
	set Windows(help,class) NSHelp
	set Windows(help,oop) $oop
}

# NSHelp::Info --
#
#	Query and modify info.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc Info {oop info args} {

	global NSHelp

	# Set info
	if {[llength $args]} {
		switch -- $info {
			default {
				set NSHelp($oop,$info) [lindex $args 0]
			}
		}

	# Get info
	} else {
		switch -- $info {
			default {
				return $NSHelp($oop,$info)
			}
		}
	}
}

# NSHelp::InitWindow --
#
#	Create a help window.
#
# Arguments:
#	oop					OOP ID. See above.
#
# Results:
#	.

proc InitWindow oop {

	global Windows
	variable Priv

	set win .help$oop
	toplevel $win
	wm title $win Help

	wm transient $win $Windows(main,win)
 
	# Do stuff when window closes
	wm protocol $win WM_DELETE_WINDOW "NSHelp::Close $oop"

	# Start out withdrawn (hidden)
	wm withdraw $win

	# Set instance variables
	Info $oop win $win

	# Turn off geometry propagation for the window
#	pack propagate $win no

	# Create menus
	InitMenus $oop

	frame $win.divider1 \
		-borderwidth 1 -relief sunken -height 2

	# Text and scroll bars
	frame $win.textFrame -relief sunken -borderwidth 1

	scrollbar $win.yscroll \
		-orient vertical -command [list $win.text yview] \
		-highlightthickness 0 -takefocus 1

	scrollbar $win.xscroll \
		-orient horizontal -command [list $win.text xview] \
		-highlightthickness 0 -takefocus 1

	text $win.text \
		-yscrollcommand [list $win.yscroll set] -wrap none \
		-xscrollcommand [list $win.xscroll set] \
		-width 82 -height 30 -font $Priv(font) -borderwidth 0 \
		-setgrid no -highlightthickness 0 -padx 4 -pady 2 \
		-background Black -foreground White -cursor {}

	grid rowconfig $win.textFrame 0 -weight 1 -minsize 0
	grid columnconfig $win.textFrame 0 -weight 1 -minsize 0
	grid $win.text -in $win.textFrame \
		-row 0 -column 0 -rowspan 1 -columnspan 1 -sticky news
	grid $win.yscroll -in $win.textFrame \
		-row 0 -column 1 -rowspan 1 -columnspan 1 -sticky ns
	grid $win.xscroll -in $win.textFrame \
		-row 1 -column 0 -rowspan 1 -columnspan 1 -sticky ew

	grid rowconfigure $win 0 -weight 0 -minsize 0
	grid rowconfigure $win 1 -weight 1 -minsize 0
	grid columnconfigure $win 0 -weight 1 -minsize 0
	grid $win.divider1 \
		-row 0 -column 0 -rowspan 1 -columnspan 1 -sticky ew -pady 2
	grid $win.textFrame \
		-row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news

	#
	# Feed Term when keys pressed
	#

	bind $win <KeyPress-Escape> "NSHelp::Close $oop"
	bind $win <Control-KeyPress-w> "NSHelp::Close $oop"
	bind $win <KeyPress-f> "NSHelp::Find $oop 0"
	bind $win <KeyPress-g> "NSHelp::Find $oop 1"
}

# NSHelp::InitMenus --
#
#	Create the menus for a new editor window.
#
# Arguments:
#	oop					OOP ID. See above.
#
# Results:
#

proc InitMenus oop {

	global NSMenu

	# Default accelerator modifier
	set mod "Ctrl"

	set win [Info $oop win]

	#
	# Menu bar
	#

	set menuDef "-tearoff 0 -postcommand \"NSHelp::SetupMenus $oop\" \
		-identifier MENUBAR"
	Info $oop mbar [NSObject::New NSMenu $win $menuDef]
	set mbar [Info $oop mbar]

	#
	# Help Menu
	#

	NSObject::New NSMenu $mbar {-tearoff 0 -identifier MENU_HELP}
	NSMenu::MenuInsertEntry $mbar -end MENUBAR {-type cascade -menu MENU_HELP -label "Help" -underline 0 -identifier M_HELP}

	lappend entries "-type command -label \"Find...\" \
		-command \"NSHelp::Find $oop 0\" \
		-accelerator f -underline 0 -identifier E_FIND"
	lappend entries "-type command -label \"Find Again\" \
		-command \"NSHelp::Find $oop 1\" \
		-accelerator g -underline 6 -identifier E_FIND_AGAIN"
	lappend entries "-type separator"
	lappend entries "-type command -label \"Close\" \
		-command \"NSHelp::Close $oop\" -underline 0 \
		-accelerator $mod+W -identifier E_CLOSE"

	NSMenu::MenuInsertEntries $mbar -end MENU_HELP $entries

	#
	# Section Menu
	#

	NSObject::New NSMenu $mbar {-tearoff 0 -identifier MENU_SECTION}
	NSMenu::MenuInsertEntry $mbar -end MENUBAR {-type cascade \
		-menu MENU_SECTION -label "Section" -underline 0 -identifier M_SECTION}

	set identCnt 0
	set entries {}
	set data {
		"About AngbandTk" about.txt
		"Alleged Bugs" bugs.txt
		"Changes" changes.txt
		"The Interface" interface.txt
		"-" ""
		"General Information" general.txt
		"Creating A Character" birth.txt
		"Exploring The Dungeon" dungeon.txt
		"Attacking Monsters" attack.txt
		"Command Descriptions" command.txt
		"Option Descriptions" option.txt
		"Version Information" version.txt
		"-" ""
		"ZAngband Magic System" magic.txt
		"-" ""
	}
	foreach {label file} $data {
		if {$label == "-"} {
			lappend entries "-type separator"
			continue
		}
		incr identCnt
		lappend entries "-type radiobutton -label \"$label\" \
			-value $file -variable NSHelp::Priv(radio) 
			-command \"NSHelp::SetText $oop $file\" \
			-identifier E_HELP_$identCnt"
	}

	lappend entries "-type radiobutton -label \"Spoiler Menu \" \
		-value spoiler.txt -variable NSHelp::Priv(radio) \
		-command \"NSHelp::SetText $oop spoiler.hlp\" -identifier E_SPOILER"
	lappend entries "-type radiobutton -label \"User Menu\" \
		-value user.txt -variable NSHelp::Priv(radio) \
		-command \"NSHelp::SetText $oop user.hlp\" -identifier E_USER"

	NSMenu::MenuInsertEntries $mbar -end MENU_SECTION $entries

	Info $oop identCnt $identCnt
}

# NSHelp::SetupMenus --
#
#	Description
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc SetupMenus {oop mbarId} {

	global Angband

	lappend identList E_FIND E_FIND_AGAIN

	for {set i 1} {$i <= [Info $oop identCnt]} {incr i} {
		lappend identList E_HELP_$i
	}

	if {[file exists [file join $Angband(dir) lib help spoiler.hlp]]} {
		lappend identList E_SPOILER
	}

	if {[file exists [file join $Angband(dir) lib help user.hlp]]} {
		lappend identList E_USER
	}
	lappend identList E_CLOSE

	NSMenu::MenuEnable $mbarId $identList
}

# NSHelp::DisplayCmd --
#
#	Called by NSWindowManager::Display().
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc DisplayCmd {oop message first {file ""}} {

	set win [Info $oop win]
	
	switch -- $message {
		preDisplay {
			if {[string length $file]} {
				SetText $oop $file
			}
		}
		postDisplay {
			eval $win.xscroll set [$win.text xview]
			eval $win.yscroll set [$win.text yview]
		}
	}
}

# NSHelp::GeometryCmd --
#
#	Called by NSWindowManager::Setup(). Returns the desired (default)
#	geometry for the window.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc GeometryCmd oop {

	global Windows

	set win [Info $oop win]
	set winMain $Windows(main,win)
	set winMicro $Windows(micromap,win)
	set x [winfo x $winMain]
	set y [winfo y $winMain]
	set width [NSToplevel::ContentWidth $win [expr [NSToplevel::EdgeRight $winMicro] - $x]]
	set height [NSToplevel::ContentHeight $win [expr [NSToplevel::EdgeBottom $winMain] - $y]]
	return ${width}x$height+$x+$y
}

# NSHelp::Close --
#
#	Description.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc Close oop {

	angband keypress \033
}

# NSHelp::SetText --
#
#	Read a help file's contents into the text display. 
#
# Arguments:
#	oop					OOP ID. See above.
#
# Results:
#	What happened.

proc SetText {oop fileName} {

	global Angband
	variable Priv

	set win [Info $oop win]
	set text $win.text

	# Look in the lib/help and tk/doc directories
	if {[file exists [file join $Angband(dir) lib help $fileName]]} {
		set filePath [file join $Angband(dir) lib help $fileName]
	} elseif {[file exists [file join $Angband(dirTK) doc $fileName]]} {
		set filePath [file join $Angband(dirTK) doc $fileName]
	} elseif {[file exists $fileName]} {
		set filePath $fileName
	} else {
		return
	}

	# Now attempt to open the file
	if {[catch {open $filePath} fileId]} {
		return
	}

	$text configure -state normal

	# Delete the old text and insert the new
	$text delete 1.0 end
	$text insert 1.0 [read -nonewline $fileId]
	$text mark set insert 1.0

	$text configure -state disabled

	# Close the file
	close $fileId

	# Set the window title
	wm title $win "Help ($fileName)"

	# Search
	set Priv(find,index) 1.0

	# Radiobutton menu entries
	set Priv(radio) $fileName
}

# NSHelp::Find --
#
#	Simple search routine to search current file for a string.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc Find {oop again} {

	variable Priv

	set win [Info $oop win]

	# Repeat the last search
	if {$again && [string length $Priv(find,string)]} {
		set string $Priv(find,string)

	# Enter a string to find, start from the beginning
	} else {

		# Ask the user for a string
		set string [NSUtils::StringBox "Find" $Priv(find,string) \
			"String" "Cancel Find" $win]
		if {$string == ""} return
		set Priv(find,string) $string
	}

	set index [$win.text search -nocase \
		-- [list $Priv(find,string)] $Priv(find,index)]
	if {$index == ""} return

	focus $win.text

	set index2 [$win.text index "$index + [string length $string] chars"]
	$win.text tag remove sel 1.0 end
	$win.text tag add sel $index $index2
	$win.text see $index

	set Priv(find,index) $index2
}

# namespace eval NSHelp
}
