#####################################################################
#
# Search
#	inported from Tcl/Tk programing nyuumon
#	Thank you Mr.Miyata & Mr.Haga

set direction "down"
set searchCmd "searchDown"
set replaceCmd "replaceDown"
set selRange ""

proc searchDown {t search flag} {
	global selRange moved strC

	scan [$t index insert] %d.%d line char
	scan [$t index end] %d numLines

	if !$flag {set search [$strC tolower $search]}

	$t tag remove sel 0.0 end

	for {set i $line} {$i <= $numLines} {incr i} {
		if {$i==$line} {
			set string [$t get $i.$char "$i.0 lineend"]
		} else {
			set string [$t get $i.0 "$i.0 lineend"]
		}

		if !$flag {set string [$strC tolower $string]}

		if {[set index [$strC first $search $string]]==-1} {
			continue
		}

		if {$i==$line} {incr index $char}
		set end [expr $index + [$strC length $search]]
		set selRange "$i.$index $i.$end"
		eval $t tag add sel $selRange
		$t mark set insert $i.$end
		$t yview -pickplace insert
		set moved 1
		return
	}
	tk_dialog .d Search "No match" {} 0 "O.K."
}

proc searchUp {t search flag} {
	global selRange moved strC

	set range [$t tag nextrange sel 1.0]
	scan [$t index insert] %d.%d line char

	if {$range != "" && $range == $selRange} {
		if [$t compare [lindex $range 1] == $line.$char] {
			scan $range %d.%d line char
		}
	}

	if !$flag {set search [$strC tolower $search]}

	$t tag remove sel 0.0 end

	for {set i $line} {$i > 0} {incr i -1} {
		if {$i == $line} {
			set string [$t get $i.0 $i.$char]
		} else {
			set string [$t get $i.0 "$i.0 lineend"]
		}

		if !$flag {set search [$strC tolower $string]}

		if {[set index [$strC last $search $string]] == -1} {
			continue
		}

		set end [expr $index + [$strC length $search]]
		set selRange "$i.$index $i.$end"
		eval $t tag add sel $selRange

		$t mark set insert $i.$end
		$t yview -pickplace insert
		set moved 1
		return
	}

	tk_dialog .d Search "No match" {} 0 "O.K."
}

proc replaceString {t replace} {
	global selRange strC

	set range [$t tag nextrange sel 1.0]

	if {$range == "" || $range != $selRange} return

	if ![$t compare [lindex $selRange 1] == insert] return

	set first [lindex $selRange 0]
	set last [lindex $selRange 1]

	$t delete $first $last
	$t insert $first $replace

	set last [$t index "$first +[$strC length $replace] c"]
	$t tag add sel $first $last
	set selRange "$first $last"
}

proc replaceDown {t search replace flag} {
	global strC

	scan [$t index insert] %d.%d line char
	scan [$t index end] %d numLines

	if !$flag {
		set search [$strC tolower $search]
	}

	set ls [$strC length $search]
	set lr [$strC length $replace]
	set cnt 0

	for {set i $line} {$i <= $numLines} {incr i} {
		if {$i == $line} {
			set string [$t get $i.$char "$i.0 lineend"]
		} else {
			set string [$t get $i.0 "$i.0 lineend"]
		}

		if !$flag {
			set string [$strC tolower $string]
		}

		if {[set index [$strC first $search $string]] == -1} {
			continue
		}

		if {$i == $line} {incr index $char}

		while 1 {
			$t delete $i.[expr $index] $i.[expr $index+$ls]
			$t insert $i.[expr $index] $replace
			incr cnt

			set offset [expr $index + $lr]
			set string [$t get $i.offset "$i.0 lineend"]

			if !$flag {
				set string [$strC tolower $string]
			}

			if {[set index [$strC first $search $string]] == -1} {
				break
			}

			incr index $offset
		}
	}

	tk_dialog .d replace "Replace count:$cnt" {} 0 "O.K."
}

proc replaceUp {t search replace flag} {
	global selRange strC

	set range [$t tag nextrange sel 1.0]

	if {$range != "" && $range == $selRange} {
		scan [lindex $range 0] %d.%d line char
	} else {
		scan [$t index insert] %d.%d line char
	}

	if !$flag {
		set search [$strC tolower $search]
	}

	set ls [$strC length $search]
	set lr [$strC length $replace]
	set cnt 0

	for {set i $line} {$i > 0} {incr i -1} {
		if {$i == $line} {
			set string [$t get $i.0 $i.$char]
		} else {
			set string [$t get $i.0 "$i.0 lineend"]
		}

		if !$flag {
			set string [$strC tolower $string]
		}

		if {[set index [$strC last $search $string]] == -1} {
			continue
		}

		while 1 {
			$t delete $i.$index $i.[expr $index+$ls]
			$t insert $i.$index $replace
			incr cnt

			set string [$strC tolower $string]

			if !$flag {
				set string [$strC tolower $string]
			}

			if {[set index \
				[$strC last $search $string]] == -1} {
				break
			}
		}
	}

	tk_dialog .d Replace "Replace count:$cnt" {} 0 "O.K."
}

proc SearchString {w title t flag} {
	global selRange searchString muggyMode

	.upper.m.find configure -relief flat

	if {$muggyMode == "view"} {
		muggy_modeChange
	}

	toplevel $w
	wm title $w $title

	bind $w <Alt-F4> "destroy $w"

	frame $w.require
	frame $w.require.search
	label $w.require.search.label -width 16
	entry $w.require.search.entry -width 20 -bd 2 -relief sunken \
		-textvariable searchString
	checkbutton $w.require.case -relief flat \
		-text "Enable identify case" -variable check
	radiobutton $w.require.up -relief flat -value up\
		-text "To the begin of the text" -variable direction
	radiobutton $w.require.down -relief flat -value down\
		-text "To the end of the text" -variable direction
	button $w.next -width 14 -text "Search next" -command \
		"\$searchCmd $t \$searchString \$check"
	button $w.quit -width 14 -text "Quit" -command "destroy $w"

	if $flag {
		frame $w.require.replace
		label $w.require.replace.label -width 16 -text \
			"The text after replacing"
		entry $w.require.replace.entry -width 20 -bd 2 -relief \
			sunken -textvariable replaceString
		button $w.replace -width 14 -text "Replace" -command \
			"replaceString $t \$replaceString;\
			 \$SearchCmd $t \$SearchString \$Check"
		button $w.all -width 14 -text "Replace all" -command \
			"\$replaceCmd $t \$searchString \$replaceString \
			 \$check"
	}

	pack $w.require.search.label $w.require.search.entry -side left
	pack $w.require.search $w.require.case $w.require.up \
		$w.require.down -anchor w -padx 5 -pady 5
	pack $w.require -side left -anchor n -padx 5 -pady 5
	pack $w.next $w.quit -padx 5 -pady 5

	if $flag {
		pack $w.require.replace.label $w.require.replace.entry \
			-side left
		pack $w.require.replace -after $w.require.search \
			-padx 5 -pady 5
		pack $w.replace $w.all -after $w.next -padx 5 -pady 5
	}

	if $flag {
		$w.require.search.label configure -text "Before replacing:"
	} else {
		$w.require.search.label configure -text "Search string:"
	}

	bind $w.require.search.entry <Any-Return> "$w.next invoke"
	if $flag {
		bind $w.require.replace.entry <Any-Return> "$w.next invoke"
	}

	$t tag remove sel 0.0 end
	set selRange {}

	checkSearch $w $flag dummy dummy dummy
	trace variable searchString w "checkSearch $w $flag"

	set oldFocus [focus]
	focus $w

	tkwait window $w

	trace vdelete searchString w "checkSearch $w $flag"

	focus $oldFocus
}

proc checkSearch {w flag name1 name2 op} {
	global searchString

	if {$searchString == ""} {
		$w.next configure -state disabled
		if $flag {
			$w.replace configure -state disabled
			$w.all configure -state disabled
		}
	} else {
		$w.next configure -state normal
		if $flag {
			$w.replace configure -state normal
			$w.all configure -state normal
		}
	}
}

proc ChangeCmd {name1 name2 op} {
	global direction searchCmd replaceCmd

	if {$direction == "up"} {
		set searchCmd "searchUp"
		set replaceCmd "replaceUp"
	} else {
		set searchCmd "searchDown"
		set replaceCmd "replaceDown"
	}
}

trace variable direction w {ChangeCmd}
