# init-other.tcl --
#
#	This file is evaluated after the character has been generated.
#

# ReadGeometryFile --
#
#	Reads the "geometry" file which contains the desired geometry
#	of each of the game's windows. If the "geometry" file does not
#	exist, then the game uses the default window positions, as set
#	in HarcodeGeometry() below. To create the "geometry" file, the
#	user can choose "Save Window Positions" from the Other Menu.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc ReadGeometryFile {} {

	global Angband
	global Windows

	if {[catch {open [file join $Angband(dirTK) config geometry]} fileId]} {
		set msg "The following error occurred while attempting to open "
		append msg "the \"geometry\" file for reading:\n\n$fileId"
		tk_messageBox -title Oops -message $msg
		return
	}

	while {![eof $fileId]} {

		# Read a line
		gets $fileId geomInfo
		if {$geomInfo == {}} break

		# Split line into window keyword and geometry
		set window [lindex $geomInfo 0]
		set geometry [lindex $geomInfo 1]

		# Request geometry. The window may not exist yet.
		NSWindowManager::RequestGeometry $window $geometry

		# Sanity: Windows(...,win) exists?
		if {![info exists Windows($window,win)]} continue

		# Get the toplevel pathname
		set win $Windows($window,win)

		if {[scan $geometry "%dx%d+%d+%d" width height x y] != 4} continue

		# If this window is not resizeable, then ignore the given
		# height or width and use the dimension requested for the
		# window.
		set resize [wm resizable $win]
		if {![lindex $resize 0]} {set width [winfo reqwidth $win]}
		if {![lindex $resize 1]} {set height [winfo reqheight $win]}

		# If this is a gridded window, convert from dimensions in
		# pixels to grid units.
		set grid [wm grid $win]
		if {[llength $grid]} {
			set width [expr $width / [lindex $grid 2]]
			set height [expr $height / [lindex $grid 3]]
		}

		# Set the window geometry
		set geometry ${width}x$height+$x+$y

		# Get the toplevel state
		set state [wm state $win]

		# If this toplevel is showing, then hide it first
		# to make the geometry request work
		if {![string compare "normal" $state]} {
			wm withdraw $win
			update idletasks
		}

		# Set the toplevel geometry
		wm geometry $win $geometry

		# Restore the window if it was hidden by us
		if {![string compare "normal" $state]} {
			update idletasks
			wm deiconify $win
		}
	}

	close $fileId
}

# WriteGeometryFile --
#
#	Writes the "geometry" file with the current geometry of each of the
#	game's windows. The "geometry" file is created if it does not already
#	exist. To create the "geometry" file, the user can choose "Save
#	Window Positions" from the Other Menu.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	It seems a toplevel's geometry is not correct until is has been
#	displayed at least once. This routine brings any non-"normal"
#	windows to the front before getting its geometry. This looks bad.
#	It might be better to move the window offscreen first.
#	-> FixWindows() fixed this problem...?

proc WriteGeometryFile {} {

	global Angband
	global Windows

	if {[catch {open [file join $Angband(dirTK) config geometry] \
		[list CREAT WRONLY TRUNC]} fileId]} {
		set msg "The following error occurred while attempting to open "
		append msg "the \"geometry\" file for writing:\n\n$fileId"
		tk_messageBox -title Oops -message $msg
		return
	}

	foreach name [array names Windows "*,win"] {
		regexp "(.*),win" $name ignore window
		set win $Windows($window,win)

		# FixWindows() fixed this too (?)
		if 0 {
			set state [wm state $win]
			if {[string compare "normal" $state]} {
				WindowBringToFront $win
			}
		}

		# Get the window geometry
		scan [wm geometry $win] "%dx%d+%d+%d" width height x y

		# If this is a gridded window, the geometry information
		# is returned as {columns rows columnWidth rowWidth}. In
		# this case I save the total area of the grid in pixels.
		# This is needed because (1) the user can switch between
		# 16x16 and 32x32 icons at startup, and (2) the window
		# may not be gridded in the next version of the game.
		set grid [wm grid $win]
		if {[llength $grid]} {
			set width [expr $width * [lindex $grid 2]]
			set height [expr $height * [lindex $grid 3]]
		}

		# Save the window geometry
		puts $fileId "$window ${width}x$height+$x+$y"

		# FixWindows fixed this too (?)
		if 0 {
			if {[string compare "normal" $state]} {
				wm withdraw $win
			}
		}
	}

	close $fileId
}

# HardcodeGeometry --
#
#	Sets the position of all the game's windows to an appropriate
#	default position. This is done at startup if the "geometry" file does
#	not exist, and when the user chooses "Default Window Positions" from
#	the Other Menu.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc HardcodeGeometry {} {

	global Windows

	set spacing 0
	set offset [winfo screenwidth .]

	# Move each window offscreen, and show it.
	foreach name [array names Windows "*,win"] {
		regexp "(.*),win" $name ignore window
		set win $Windows($window,win)
		set visible($window) [winfo ismapped $win]
		wm geometry $win +$offset+0
		update idletasks
		wm deiconify $win
	}

	# Must be update, not "update idletasks", or the Main Window geometry
	# is silly (too tall). Don't know why.
	update

	# Message Window
	set win1 $Windows(message,win)
	set x 0 ; incr x $offset
	wm geometry $win1 +$x+0
	update idletasks

	# Main Window
	set x 0 ; incr x $offset
	set y [expr [NSToplevel::EdgeBottom $win1] + $spacing]
	set win1 $Windows(main,win)
	wm geometry $win1 +$x+$y
	update idletasks

	# Micro Map Window
	set win1 $Windows(main,win)
	set win2 $Windows(message,win)
	set x [expr [NSToplevel::EdgeRight $win1] + $spacing]
	set y [expr [NSToplevel::EdgeBottom $win2] + $spacing]
	set win3 $Windows(micromap,win)
	wm geometry $win3 +$x+$y
	update idletasks

	# Misc Window
	set y [expr [NSToplevel::EdgeBottom $win3] + $spacing]
	set win1 $Windows(misc,win)
	wm geometry $win1 +$x+$y
	update idletasks

	# Progress Window
	set y [expr [NSToplevel::EdgeBottom $win1] + $spacing]
	set win1 $Windows(progress,win)
	wm geometry $win1 +$x+$y
	update idletasks

	# Recall Window
	set win1 $Windows(main,win)
	set win2 $Windows(progress,win)
	set win3 $Windows(recall,win)
	set x 0 ; incr x $offset
	set y [expr [NSToplevel::EdgeBottom $win1] + $spacing]
	set width [NSToplevel::ContentWidth $win3 [expr [NSToplevel::EdgeRight $win1] - $x]]
	if {[winfo screenwidth .] >= 800} {
		set height 100
	} else {
		set height [expr [NSToplevel::EdgeBottom $win2] - $y]
	}
	set height [NSToplevel::ContentHeight $win3 $height]
	wm geometry $win3 ${width}x$height+$x+$y
	update idletasks

	# Message Window (width)
	set win1 $Windows(micromap,win)
	set win2 $Windows(message,win)
	set x 0 ; incr x $offset
	set width [NSToplevel::ContentWidth $win2 [expr [NSToplevel::EdgeRight $win1] - $x]]
	wm geometry $win2 ${width}x[winfo height $win2]+$x+0
	update idletasks

	# Inventory Window
	set win1 $Windows(micromap,win)
	set win2 $Windows(main,win)
	set win3 $Windows(inventory,win)
	set x 0 ; incr x $offset
	set y [winfo y $win2]
	set width [NSToplevel::ContentWidth $win3 [expr [NSToplevel::EdgeRight $win1] - $x]]
	set height [NSToplevel::ContentHeight $win3 [expr [NSToplevel::EdgeBottom $win2] - $y]]
	wm geometry $win3 ${width}x$height+$x+$y
	update idletasks

if 0 {
	# Book Window
	if {[info exists Windows(book,win)]} {
		set win3 $Windows(book,win)
		set height [NSToplevel::ContentHeight $win3 [expr [NSToplevel::EdgeBottom $win2] - $y]]
		wm geometry $win3 ${width}x$height+$x+$y
		update idletasks
	}
}

	# Messages Window
	set win3 $Windows(messages,win)
	set height [NSToplevel::ContentHeight $win3 [expr [NSToplevel::EdgeBottom $win2] - $y]]
	wm geometry $win3 ${width}x$height+$x+$y
	update idletasks

	# Info Window
	set win3 $Windows(info,win)
	set height [NSToplevel::ContentHeight $win3 [expr [NSToplevel::EdgeBottom $win2] - $y]]
	wm geometry $win3 ${width}x$height+$x+$y
	update idletasks

if 0 {
	# Mindcraft Window
	if {[info exists Windows(mindcraft,win)]} {
		set win3 $Windows(mindcraft,win)
		set height [NSToplevel::ContentHeight $win3 [expr [NSToplevel::EdgeBottom $win2] - $y]]
		wm geometry $win3 ${width}x$height+$x+$y
		update idletasks
	}
}

	# Power Window
	set win3 $Windows(power,win)
	set height [NSToplevel::ContentHeight $win3 [expr [NSToplevel::EdgeBottom $win2] - $y]]
	wm geometry $win3 ${width}x$height+$x+$y
	update idletasks

	lappend winList alternate assign book choosemonster color help highscore
	lappend winList keymap knowledge macros options player playerflags sound
	lappend winList sprite store

	foreach winName $winList {
		NSWindowManager::Arrange $winName
	}

	# Iterate over each window. Move the mapped window from its offscreen
	# position onto the screen again. If it wasn't mapped previously, then
	# hide the window.
	foreach name [array names Windows "*,win"] {
		regexp "(.*),win" $name ignore window
		set win $Windows($window,win)
		set x [winfo x $win] ; incr x -$offset
		set y [winfo y $win]
		wm geometry $win +$x+$y
		if $visible($window) continue
		wm withdraw $win
	}
	update
}

# FixWindows --
#
#	Here's a stinker for you. In "inventory.tcl" the command CalcLineLength()
#	calls "winfo width $canvas". Well, if the Inventory Window was never
#	shown, then "winfo width $canvas" returns a useless value. Ditto for the
#	Store Window. So to avoid this problem (and any other similar ones)
#	I call this command to move all the windows offscreen, show them, then
#	hide them again, once, during startup. This isn't a problem when
#	starting up with HarcodeGeometry(), only when setting window positions
#	with ReadGeometryFile().
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc FixWindows {} {

	global Windows

	set offset [winfo screenwidth .]

	# Can anyone make this simpler? It is completely beyond me.

	foreach name [array names Windows "*,win"] {
		regexp "(.*),win" $name ignore window
		set win $Windows($window,win)

		# "winfo geometry" returns bad x,y values, as do both
		# "winfo x" and "winfo"y" at this point...
		set geomList [split [wm geometry $win] +x]
		set x [lindex $geomList 2]
		set y [lindex $geomList 3]

		wm geometry $win +$offset+0
		update idletasks
		wm deiconify $win

		# "update idletasks" does NOT work here
		update

		wm withdraw $win
		update idletasks
		wm geometry $win +$x+$y
		update idletasks
	}
}

# InitImageIfNeeded --
#
#	Creates a new photo image from the given file. If the image
#	already exists, nothing happens.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitImageIfNeeded {imageName fileName} {

	global Angband

	set imageList [image names]
	if {[lsearch -exact $imageList $imageName] == -1} {
		image create photo $imageName \
			-file [file join $Angband(dirTK) image $fileName]
	}
}

# ProcessPrefFile --
#
#	Get a filename from the user then read in the given pref file.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc ProcessPrefFile parent {

	global Angband

	set filename [tk_getOpenFile -initialdir [file join $Angband(dir) lib user] \
		-parent $parent]
	if {![string compare $filename ""]} {
		return 1
	}

	if {![IsUserFile $filename]} {
		tk_messageBox -title "Pref File Error" -icon info -message \
			"Pref files must be located in the lib/user directory."
		return 1
	}

	set filename [file tail $filename]
	if {[catch {angband game process_pref_file $filename} result]} {
		tk_messageBox -title "Pref File Error" -icon error -message $result
		return 1
	}

	# Success
	return 0
}

# IsUserFile --
#
#	Determine whether the given file is inside the lib/user directory.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc IsUserFile path {

	global Angband
	set LowerFileNames 1

	set pathUser [file join $Angband(dir) lib user]
	if $LowerFileNames {
		set pathUser [string tolower $pathUser]
		set path [string tolower $path]
	}
	if {[string compare $pathUser [file dirname $path]]} {
		return 0
	}
	return 1
}

# WriteAlternateFile --
#
#	Writes the tk/config/$prefix-alternate file.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc WriteAlternateFile {} {

	global Angband

	set fileName [file join $Angband(dirTK) config [Global config,alternate]]
dbwin "WriteAlternateFile $fileName\n"
	if {[catch {open $fileName w} fileId]} {
		set msg "The following error occurred while attempting to open "
		append msg "the \"alternate\" file for writing:\n\n$fileId"
		tk_messageBox -title Oops -message $msg
		return
	}

	puts $fileId "# Automatically generated. Do not edit.\n"

	set typeList [icon gettypes]
	foreach type $typeList {
		puts $fileId "alternate::type $type"
	}
	puts $fileId ""

	set max [alternate count]
	for {set i 0} {$i < $max} {incr i} {
		puts $fileId "alternate::new [alternate configure $i -reason]"
		foreach frame [alternate get $i] {
			set type [lindex $frame 0]
			set index [lindex $frame 1]
			puts $fileId "alternate::ins [lsearch $typeList $type] $index"
		}
		puts $fileId ""
	}

	close $fileId
}

# WriteAssignFile --
#
#	Writes the tk/config/assign file.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc WriteAssignFile {} {

	global Angband

	set fileName [file join $Angband(dirTK) config [Global config,assign]]
dbwin "WriteAssignFile $fileName\n"
	if {[catch {open $fileName w} fileId]} {
		set msg "The following error occurred while attempting to open "
		append msg "the \"assign\" file for writing:\n\n$fileId"
		tk_messageBox -title Oops -message $msg
		return
	}

	puts $fileId "# Automatically generated. Do not edit.\n"

	set typeList [icon gettypes]
	foreach type $typeList {
		puts $fileId "asgn::type $type"
	}
	puts $fileId ""

	# I'm going to ignore "flavor" assignments. They need to be rethunk.
	# Also ignore ascii-type assignments, since the user can't change
	# them.
	foreach iconType [icon gettypes] {
		if {$iconType == "flavor"} {
			lappend ignoreType $iconType
		} elseif {![catch {icon ascii font $iconType}]} {
			lappend ignoreType $iconType
		}
	}
	
	# Adam Bolt has a different icon for every race/class combination.
	# The original graphics do not. If autoAssign is TRUE, the icon
	# was automatically assigned by calling AutoAssignCharacterIcon(),
	# in which case we do not save the assignment to the "assign" file.
	if {![Global autoAssign]} {

		# Character
		puts $fileId "asgn::to character"
		set icon [angband player char_attr]
		set iconType [lindex $icon 0]
		set iconIndex [lindex $icon 1]
		if {[string compare $iconType flavor]} {
			set typeIndex [lsearch $typeList $iconType]
			puts $fileId "asgn::one 0 $typeIndex $iconIndex"
		}
		puts $fileId ""
	}

	# Features
	set max [angband f_info max]
	puts $fileId "asgn::to feature"
	for {set f_idx 1} {$f_idx < $max} {incr f_idx} {
		set icon [icon assign -to feature -toindex $f_idx]
		set iconType [lindex $icon 0]
		set iconIndex [lindex $icon 1]
		if {[lsearch -exact $ignoreType $iconType] != -1} continue
		set typeIndex [lsearch $typeList $iconType]
		puts $fileId "asgn::one $f_idx $typeIndex $iconIndex"
		set light [feature configure $f_idx -light]
		set background [feature configure $f_idx -background]
		puts $fileId "asgn::feat $f_idx $light $background"
	}
	puts $fileId ""

	# Monsters
	set max [angband r_info max]
	puts $fileId "asgn::to monster"
	for {set r_idx 1} {$r_idx < $max} {incr r_idx} {
		set icon [icon assign -to monster -toindex $r_idx]
		set iconType [lindex $icon 0]
		set iconIndex [lindex $icon 1]
		if {[lsearch -exact $ignoreType $iconType] != -1} continue
		set typeIndex [lsearch $typeList $iconType]
		puts $fileId "asgn::one $r_idx $typeIndex $iconIndex"
	}
	puts $fileId ""

	# Objects
	set max [angband k_info max]
	puts $fileId "asgn::to object"
	for {set k_idx 1} {$k_idx < $max} {incr k_idx} {
		set icon [icon assign -to object -toindex $k_idx]
		set iconType [lindex $icon 0]
		set iconIndex [lindex $icon 1]
		if {[lsearch -exact $ignoreType $iconType] != -1} continue
		set typeIndex [lsearch $typeList $iconType]
		puts $fileId "asgn::one $k_idx $typeIndex $iconIndex"
	}
	puts $fileId ""

	# Effect (ball)
	puts $fileId "asgn::to ball"
	foreach effect [effect names] {
		set icon [effect assign ball $effect]
		set iconType [lindex $icon 0]
		set iconIndex [lindex $icon 1]
		if {[lsearch -exact $ignoreType $iconType] != -1} continue
		set typeIndex [lsearch $typeList $iconType]
		puts $fileId "asgn::effect $effect $typeIndex $iconIndex"
	}
	puts $fileId ""

	# Effect (bolt)
	puts $fileId "asgn::to bolt"
	foreach effect [effect names] {
		set icon [effect assign bolt $effect]
		set iconType [lindex $icon 0]
		set iconIndex [lindex $icon 1]
		if {[lsearch -exact $ignoreType $iconType] != -1} continue
		set typeIndex [lsearch $typeList $iconType]
		puts $fileId "asgn::effect $effect $typeIndex $iconIndex"
	}
	puts $fileId ""

	close $fileId
}

# WriteSoundFile --
#
#	Writes the tk/config/sound file.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc WriteSoundFile {} {

	global Angband

	set fileName [file join $Angband(dirTK) config sound]
	if {[catch {open $fileName w} fileId]} {
		set msg "The following error occurred while attempting to open "
		append msg "the \"sound\" file for writing:\n\n$fileId"
		tk_messageBox -title Oops -message $msg
		return
	}

	puts $fileId "# Automatically generated. Do not edit.\n"

	set groupList [angband sound groups]
	foreach group $groupList {
		puts $fileId "snd::grp $group"
	}
	puts $fileId ""

	foreach group $groupList {

		set groupIndex [lsearch -exact $groupList $group]
		set max [angband sound count $group]
		for {set i 0} {$i < $max} {incr i} {
			if {![angband sound exists $group $i]} continue
			set keyword [angband sound keyword $group $i]
			foreach sound [angband sound assign $group $keyword] {
				puts $fileId "snd::one $groupIndex $keyword \"$sound\""
			}
		}
		puts $fileId ""
	}

	close $fileId
}

# WriteSpriteFile --
#
#	Writes the tk/config/sprite file.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc WriteSpriteFile {} {

	global Angband

	set fileName [file join $Angband(dirTK) config [Global config,sprite]]
dbwin "WriteSpriteFile $fileName\n"
	if {[catch {open $fileName w} fileId]} {
		set msg "The following error occurred while attempting to open "
		append msg "the \"sprite\" file for writing:\n\n$fileId"
		tk_messageBox -title Oops -message $msg
		return
	}

	puts $fileId "# Automatically generated. Do not edit.\n"

	set typeList [icon gettypes]
	foreach type $typeList {
		puts $fileId "sprite::type $type"
	}
	puts $fileId ""

	set max [sprite count]
	for {set i 0} {$i < $max} {incr i} {
		puts $fileId "sprite::new [sprite configure $i -delay] \
			[sprite configure $i -reverse]"
		foreach frame [sprite get $i] {
			set type [lindex $frame 0]
			set index [lindex $frame 1]
			puts $fileId "sprite::ins [lsearch $typeList $type] $index"
		}
		puts $fileId ""
	}

	close $fileId
}

# alternate --
#
#	A namespace with commands called when the tk/config/alternate file
#	is sourced.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

namespace eval alternate {

variable alternatePriv

proc type type {

	variable alternatePriv

	lappend alternatePriv(type) $type
}

proc new reason {

	variable alternatePriv

	set alternatePriv(id) [alternate create $reason]
}

proc ins {typeIndex iconIndex} {

	variable alternatePriv

	set type [lindex $alternatePriv(type) $typeIndex]
	alternate insert $alternatePriv(id) 1000 -type $type -index $iconIndex
}

# namespace eval alternate
}

# asgn --
#
#	A namespace with commands called when the tk/config/assign file
#	is sourced.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

namespace eval asgn {

variable asgnPriv

proc type type {

	variable asgnPriv

	lappend asgnPriv(type) $type
}

proc to to {

	variable asgnPriv

	set asgnPriv(to) $to
}

proc one {idx typeIndex iconIndex} {

	variable asgnPriv

	### Hack -- Don't override "flavor" assignments
	set icon [icon assign -to $asgnPriv(to) -toindex $idx]
	if {[lindex $icon 0] == "flavor"} return

	### Hack -- Don't override "none" assignments
	if {[lindex $icon 0] == "none"} return

	set type [lindex $asgnPriv(type) $typeIndex]
	if {[catch {icon validate $type $iconIndex}]} {
		set type default
		set iconIndex 0
	}
	icon assign -to $asgnPriv(to) -toindex $idx -type $type -index $iconIndex

	# Did we just assign to the character?
	if {$asgnPriv(to) == "character"} {
		Global autoAssign 0
	}
}

proc effect {effect typeIndex iconIndex} {

	variable asgnPriv

	set type [lindex $asgnPriv(type) $typeIndex]
	if {[catch {icon validate $type $iconIndex}]} {
		set type default
		set iconIndex 0
	}
	::effect assign $asgnPriv(to) $effect -type $type -index $iconIndex
}

proc feat {f_idx light background} {

	feature configure $f_idx -light $light -background $background
}

# namespace eval asgn
}

# snd --
#
#	A namespace with commands called when the tk/config/sound file
#	is sourced.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

namespace eval snd {

variable Priv

proc grp group {

	variable Priv

	lappend Priv(group) $group
}

proc one {groupIndex keyword {sound ""}} {

	variable Priv

	if {![string length $sound]} return
	set group [lindex $Priv(group) $groupIndex]

	# Ignore errors/incompatiblities
	catch {
		angband sound insert $group $keyword 1000 $sound
	}
}

# namespace eval snd
}

# sprite --
#
#	A namespace with commands called when the tk/config/sprite file
#	is sourced.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

namespace eval sprite {

variable spritePriv

proc type type {

	variable spritePriv

	lappend spritePriv(type) $type
}

proc new {delay reverse} {

	variable spritePriv

	set spritePriv(id) [sprite create]
	sprite configure $spritePriv(id) -delay $delay -reverse $reverse
}

proc ins {typeIndex iconIndex} {

	variable spritePriv

	set type [lindex $spritePriv(type) $typeIndex]
	if {[catch {icon validate $type $iconIndex}]} {
		set type default
		set iconIndex 0
	}
	sprite insert $spritePriv(id) 1000 -type $type -index $iconIndex
}

# namespace eval sprite
}

# Purge --
#
#	It is intended that this command delete all the once-only commands
#	and variables (startup code). Does it work? 
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc Purge {} {

	global DEBUG
	global Windows

	namespace delete asgn
	namespace delete snd
	namespace delete sprite
	namespace delete NSConfig

	rename InitStartupScreen ""
	rename angband_startup ""
	rename angband_initialized ""
	rename angband_birth ""
	rename InitLoadWindow ""
	rename angband_load ""
	rename FixWindows ""

	if {[info exists Windows(book,win)]} {
		rename NSBookWindow::NSBookWindow ""
		rename NSBookWindow::InitWindow ""
		rename NSBookWindow::InitMenus ""
	}

if 0 {
	rename NSHelp::InitModule ""
	rename NSHelp::NSHelp ""
	rename NSHelp::InitWindow ""
	rename NSHelp::InitMenus ""

	# Don't delete! See "angband_display highscore"
	if 0 {
		rename NSHighScore::InitModule ""
		rename NSHighScore::NSHighScore ""
		rename NSHighScore::InitWindow ""
	}
}

	rename NSInventory::NSInventory ""
	rename NSInventory::InitWindow ""
	rename NSInventory::InitMenus ""

if 0 {
	rename NSKnowledge::InitModule ""
	rename NSKnowledge::NSKnowledge ""
	rename NSKnowledge::InitWindow ""
	rename NSKnowledge::InitMenus ""

	rename NSMacros::InitModule ""
	rename NSMacros::NSMacros ""
	rename NSMacros::InitWindow ""
	rename NSMacros::InitMenus ""
}

	rename NSMap::NSMap ""

	rename NSMessage::NSMessage ""
	rename NSMessage::InitWindow ""

	rename NSMiscWindow::InitAuxWindows ""
	rename NSMiscWindow::InitDisplay_Toolbar ""
	rename NSMiscWindow::InitDisplay_Message ""
	rename NSMiscWindow::InitDisplay_MicroMap ""
	rename NSMiscWindow::InitDisplay_Misc ""
	rename NSMiscWindow::InitDisplay_Progress ""
#	rename NSMiscWindow::CanvasAddTextItem ""

	### Think about NSModule::LoadIfNeeded for faster startup
if 0 {
	rename NSOptions::InitModule ""
	rename NSOptions::NSOptions ""
	rename NSOptions::InitWindow ""
	rename NSOptions::InitMenus ""

	rename NSPlayer::NSPlayer ""
	rename NSPlayer::InitWindow ""
	rename NSPlayer::InitMenus ""
}

	rename NSRecall::NSRecall ""
	rename NSRecall::InitWindow ""

	rename NSStatus::InitModule ""

if 0 {
	rename NSStore::NSStore ""
	rename NSStore::InitWindow ""
	rename NSStore::InitMenus ""
}

	if $DEBUG {
		rename InitCommandWindow ""
	}
}

if {[catch {

angband_load progress 0.25
angband_load note "Sourcing scripts..."

source [file join $Angband(dirTK) keyboard.tcl]
source [file join $Angband(dirTK) angband.tcl]
source [file join $Angband(dirTK) main-window.tcl]
source [file join $Angband(dirTK) inventory.tcl]
source [file join $Angband(dirTK) store.tcl]
source [file join $Angband(dirTK) message.tcl]
source [file join $Angband(dirTK) recall.tcl]
source [file join $Angband(dirTK) map.tcl]
source [file join $Angband(dirTK) misc-window.tcl]
source [file join $Angband(dirTK) status.tcl]
source [file join $Angband(dirTK) tomb.tcl]
source [file join $Angband(dirTK) value-manager.tcl]
source [file join $Angband(dirTK) widget.tcl]
source [file join $Angband(dirTK) info-window.tcl]
source [file join $Angband(dirTK) power.tcl]
if {[llength [angband player spell_book]]} {
	source [file join $Angband(dirTK) book-menu.tcl]
	source [file join $Angband(dirTK) book-window.tcl]
}
if {![string compare [angband player class] Mindcrafter]} {
	source [file join $Angband(dirTK) mindcraft.tcl]
}

# Set some options here. This is not a good thing.
angband setting hilite_player no
angband setting view_yellow_lite yes
angband setting view_bright_lite yes
angband setting view_granite_lite yes
angband setting view_special_lite yes

# Playing sounds on Windoze is totally f*cked, in my opinion. Microsoft
# has managed to require you to have an active window or you cannot
# play a sound, and only one application can play a sound at once. Since
# my app has a lot of windows, I have SoundWindowBindTag tag which
# activates and deactivates the sound system as window's claim and
# lose the input focus. This is not needed for DirectSound, which
# thankfully recognizes child windows.

set SoundAfterId ""
bind SoundWindowBindTag <FocusIn> {
	after cancel $SoundAfterId
	angband sound activate yes
}
bind SoundWindowBindTag <FocusOut> {
	set SoundAfterId [after 1000 angband sound activate no]
}
proc SoundWindow win {
	bindtags $win [concat [bindtags $win] SoundWindowBindTag]
}

angband_load progress 0.45
angband_load note "Initializing icons..."

# Load the configuration files from the "current" set
NSConfig::Load

if {[file exists [file join $Angband(dirTK) config sound]]} {
	angband_load prompt "Reading sound file..."
	source [file join $Angband(dirTK) config sound] 
}

angband_load progress 0.50
angband_load note "Initializing modules..."

	angband_load prompt "Initializing: Values"
NSValueManager::InitModule

# XXX Hack -- If this is a new character, then read in the "default"
# settings from the tk/config/setting file
if {[angband player turn] == 1} {
	set fileName [file join $Angband(dirTK) config setting]
	if {[file exists $fileName]} {
		source $fileName
	}
}

	angband_load prompt "Initializing: Main Window"
NSMainWindow::InitModule
	angband_load progress 0.60
	angband_load prompt "Initializing: Map"
NSMap::InitModule
	angband_load prompt "Initializing: Aux Window"
NSMiscWindow::InitAuxWindows
	angband_load prompt "Initializing: Status"
NSStatus::InitModule
	angband_load progress 0.74
	angband_load prompt "Initializing: Inventory"
NSObject::New NSInventory
	angband_load progress 0.78
	angband_load prompt "Initializing: Message"
NSObject::New NSMessage
	angband_load prompt "Initializing: Recall"
NSRecall::InitModule
	angband_load progress 0.82
	angband_load progress 0.86
	angband_load prompt "Initializing: Info"
NSObject::New NSInfoWindow
	angband_load prompt "Initializing: Power"
NSPower::InitModule
	angband_load progress 0.90
if {[llength [angband player spell_book]]} {
	angband_load prompt "Initializing: Book Window"
	NSObject::New NSBookWindow
}
if {![string compare [angband player class] Mindcrafter]} {
	angband_load prompt "Initializing: Mindcraft"
	NSMindcraft::InitModule
}

angband_load progress 0.95
if {[file exists [file join $Angband(dirTK) config geometry]]} {
	angband_load note "Reading geometry file..."
	ReadGeometryFile
	FixWindows
} else {
	angband_load note "Setting default window positions..."
	HardcodeGeometry
}
update idletasks


NSModule::AddModule NSAlternate [file join $Angband(dirTK) alternate.tcl]
NSModule::AddModule NSAssign [file join $Angband(dirTK) assign.tcl]
NSModule::AddModule NSBuilding [file join $Angband(dirTK) building.tcl]
NSModule::AddModule NSChooseMonster [file join $Angband(dirTK) choose-monster.tcl]
NSModule::AddModule NSColorPreferences [file join $Angband(dirTK) color.tcl]
NSModule::AddModule NSHelp [file join $Angband(dirTK) help.tcl]
NSModule::AddModule NSHighScore [file join $Angband(dirTK) highscore.tcl]
NSModule::AddModule NSIconBrowser [file join $Angband(dirTK) icon-browser.tcl]
NSModule::AddModule NSKeymap [file join $Angband(dirTK) keymap.tcl]
NSModule::AddModule NSKnowledge [file join $Angband(dirTK) knowledge.tcl]
NSModule::AddModule NSMacros [file join $Angband(dirTK) macros.tcl]
NSModule::AddModule NSOptions [file join $Angband(dirTK) options.tcl]
NSModule::AddModule NSPhoto [file join $Angband(dirTK) photo.tcl]
NSModule::AddModule NSPlayer [file join $Angband(dirTK) player.tcl]
NSModule::AddModule NSPlayerFlags [file join $Angband(dirTK) player-flags.tcl]
NSModule::AddModule NSSound [file join $Angband(dirTK) sound.tcl]
NSModule::AddModule NSSprite [file join $Angband(dirTK) sprite.tcl]
NSModule::AddModule NSStore [file join $Angband(dirTK) store.tcl]
NSModule::AddModule NSTips [file join $Angband(dirTK) tips.tcl]


if $DEBUG {
NSModule::AddModule NSDebug [file join $Angband(dirTK) debug.tcl]
NSModule::AddModule NSDebugAlloc [file join $Angband(dirTK) debug-alloc.tcl]
NSModule::LoadIfNeeded NSDebug
NSModule::LoadIfNeeded NSDebugAlloc
}

# The load window is obscured below
angband_load progress 1.0

# Show windows which should be shown
wm deiconify $Windows(main,win)
wm deiconify $Windows(recall,win)
wm deiconify $Windows(micromap,win)
wm deiconify $Windows(misc,win)
wm deiconify $Windows(progress,win)
wm deiconify $Windows(message,win)

	update

# Focus on Main Window
# It seems important to do this before hiding the Load Window,
# otherwise the application swaps into the background
focus $Windows(main,win)

# Done with "load" window
angband_load kill

# Purge once-only commands and variables
Purge

# Begin!

# This call is only needed for DirectSound. It must appear after the
# window was actually created or it bombs. It turns out that DirectSound
# recognizes all the child windows of Main and plays sound when any
# of them are active. This call does nothing under WaveMix.
angband sound window $Windows(main,win)

# Show the Tips Window if desired
if {[Value tip,show]} {
	NSModule::LoadIfNeeded NSTips
}

if 1 {

# nothing

} elseif 0 {

angband brightness 0 -60
angband contrast 0 0
angband brightness 1 -111
angband contrast 1 0
angband brightness 2 -127
angband contrast 2 50

set Darken 0
set Brightness(cur) [angband brightness 0]
set Contrast(cur) [angband contrast 0]

proc AdjustBrightnessContrast {what value} {
	angband $what $::Darken $value
	[Global main,widget] wipe
}

proc SetDarken which {
	set ::Darken $which
	set ::Brightness(cur) [angband brightness $which]
	set ::Contrast(cur) [angband contrast $which]
}

proc InitBrightnessContrast {} {

	set win .brightnesscontrast
	toplevel $win
	scale $win.brightness \
		-orient horizontal -label "Brightness" -variable ::Brightness(cur) \
		-width 15 -sliderlength 20 -length 255 -from -127 -to 127 \
		-command "AdjustBrightnessContrast brightness" -showvalue yes
	scale $win.contrast \
		-orient horizontal -label "Contrast"  -variable ::Contrast(cur) \
		-width 15 -sliderlength 20 -length 255 -from -127 -to 127 \
		-command "AdjustBrightnessContrast contrast" -showvalue yes
	pack $win.brightness
	pack $win.contrast

	bind $win <KeyPress-0> {SetDarken 0}
	bind $win <KeyPress-1> {SetDarken 1}
	bind $win <KeyPress-2> {SetDarken 2}
}

InitBrightnessContrast

} else {

set darkenFile [file join $Angband(dirTK) image darken.gif]
if {[file exists $darkenFile]} {
	image create photo Image_Darken -file $darkenFile
	for {set i 0} {$i < 3} {incr i} {
		set color {}
		for {set y 0} {$y < 16} {incr y} {
			for {set x 0} {$x < 16} {incr x} {
				set rgb [Image_Darken get [expr $x + $i * 16] $y]
				lappend color [eval format #%02x%02x%02x $rgb]
			}
		}
		angband tint $i $color
	}
	image delete Image_Darken
}

}

if 0 {

catch {
for {set y 0} {$y < 16} {incr y} {
	set row {}
	for {set x 0} {$x < 16} {incr x} {
		lappend row [angband palette [expr $x + $y * 16]]
	}
	lappend data $row
}
image create photo Palette -height 16 -width 16 -palette 256/256/256
Palette put $data -to 0 0
toplevel .palette
label .palette.label -image Palette
pack .palette.label
} result
dbwin $result

}

} error]} {
	set message "An error occured during startup:\n    $error\nQuit now?"
	set answer [tk_messageBox -title "$Angband(name) Error" -message $message \
		-type yesno -icon question]
	if {$answer == "yes"} [angband game abort]
}

# Program initialized
set Angband(init) 1

