# Copyright (c) 2000, Red Hat, Inc.
# 
# This file is part of Source-Navigator.
# 
# Source-Navigator is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation; either version 2, or (at your option)
# any later version.
# 
# Source-Navigator is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along
# with Source-Navigator; see the file COPYING.  If not, write to
# the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
# MA 02111-1307, USA.
# 
########################################
##
## Grep (Find in Files...)
##
########################################
itcl_class Grep& {
	constructor {{config ""}} {
		global sn_options
		global grep_MaxFound
		global grep_Nocase
		global grep_PatternFormats grep_PatternFormatsCombo
		
		set class [$this info class]
		@@rename $this $this-tmp-
		@@frame $this -class $class -bd 0
		@@rename $this $this-win-
		@@rename $this-tmp- $this
#		@@bind $this <FocusIn> {focus [tk_focusNext %W]}
		
		#grep pattern
		global $this-GrepString
		global $this-GrepFilePat
		global $this-GrepPatFilter
		global $this-GrepNocase
		global $this-BreakBy
		
		set topw [winfo toplevel $this]
		set s $this
		if {![info exists grep_MaxFound]} {
			@@set grep_MaxFound 100
		}
		#load formats for pattern
		if {![info exists grep_PatternFormats]} {
			@@set grep_PatternFormats ""
			
			set fil_file [sn_search_file grep.fil]
			if {[file isfile $fil_file]} {
				set fd [@@open $fil_file]
				@@fconfigure $fd -encoding $sn_options(def,system-encoding)
				foreach l [split [read -nonewline $fd] "\n"] {
					@@lappend grep_PatternFormats [list \
							[lindex [split $l \"] 1] \
							[lindex [split $l \"] 3]]
				}
				close $fd
			}
			
			#make entries for the combo box
			set grep_PatternFormatsCombo ""
			foreach l $grep_PatternFormats {
				lappend grep_PatternFormatsCombo [lindex $l 0]
			}
		}
		
		#add menu entries
		if {$menu != ""} {
		}
		#add toolbar icons
		if {$toolbar != ""} {
			set grepfr $toolbar.grepfr
			pack [frame $grepfr] -side left
			#prev
			button $grepfr.prev \
				-takefocus 0 \
				-text [get_indep String Prev] \
				-image del_image \
				-command "$this next_entry -1"
			balloon_bind_info $grepfr.prev [get_indep String PrevINFO]
			pack $grepfr.prev -side left -fill x -expand n
			#next
			button $grepfr.next \
				-takefocus 0 \
				-text [get_indep String Next] \
				-image add_image \
				-command "$this next_entry +1"
			balloon_bind_info $grepfr.next [get_indep String NextINFO]
			pack $grepfr.next -side left -fill x -expand n
		}
		
		#Frame for input
		set input $this.input
		frame $input
		pack $input -side top -padx 5 -fill x
		
		#Entries for pattern and filter
		set entries $input.entries
		frame $entries
		pack $entries -side left -padx 5 -expand y -fill x
		
		#Pattern
		Combo& $entries.entry \
				-labelwidth 13 \
				-anchor ne \
				-label [get_indep String MultiGrepPattern] \
				-underline [get_indep Pos MultiGrepPattern] \
				-textvariable $this-GrepString \
				-exportselection n \
				-expand y \
				-filter "" \
				-contents "" \
				-selectcommand "$this grep_select_command $entries.entry" \
				-readonly 0 \
				-sort ""
		[$entries.entry entry] select to end
		[$entries.entry entry] select to end
		bind [$entries.entry entry] <Return> "$this ExecGrep"
		pack $entries.entry -side top -fill x
		
		#Files
		set $this-GrepFilePat "*"
		Combo& $entries.filter \
				-label [get_indep String UtilFiles] \
				-underline [get_indep Pos UtilFiles] \
				-labelwidth 13 \
				-anchor ne \
		  		-textvariable $this-GrepFilePat \
				-exportselection n \
				-expand y \
				-filter "" \
				-contents "" \
				-selectcommand "$this grep_select_file_filter $entries.filter" \
				-readonly 0 \
				-sort ""
		bind [$entries.filter entry] <Return> "$this ExecGrep"
		pack $entries.filter -side top -fill x
	
		#Category
		set catframe $entries.catfr
		pack [frame $catframe] -side top -fill x
		set catcombo $catframe.catcombo
		Combo& $catcombo \
				-filter "" \
				-label [get_indep String MultiGrepFormat] \
				-underline [get_indep Pos MultiGrepFormat] \
				-labelwidth 13 \
				-anchor ne \
				-textvariable $this-GrepPatFilter \
				-contents $grep_PatternFormatsCombo \
				-selectcommand "$this disp_filter $catcombo" \
				-sort "" \
				-width 0 \
				-readonly 0 \
				-expand y
		pack $catcombo -side left -expand y -fill x
		
		#Buttons start
		set btns $input.buttons
		frame $btns
		pack $btns -side right -anchor nw -fill x
		button $btns.start \
				-text [get_indep String UtilSearch] \
				-underline [get_indep Pos UtilSearch] \
				-command "$this ExecGrep"
		balloon_bind_info $btns.start [get_indep String GrepSearchINFO]
		pack $btns.start  -side top -padx 8 -pady 4 -fill x
		
		#Button cancel, if needed
		if {$withcancel} {
			button $btns.cancel \
					-text [get_indep String Cancel] \
					-underline [get_indep Pos Cancel] \
					-command "$this close_grep" \
					-state disabled
			balloon_bind_info $btns.cancel [get_indep String GrepCancelINFO]
			pack $btns.cancel -side top -padx 8 -pady 4 -fill x
		}
		
		#format button, that formats the string entered
		#in the pattern-entry
		button $btns.frmt \
				-text [get_indep String Format]\
				-underline [get_indep Pos Format]\
				-command "set $this-GrepString \[Grep& @@ FormatPattern \$\{$this-GrepString\}\]"
		balloon_bind_info $btns.frmt [get_indep String GrepFormatINFO]
		pack $btns.frmt -side top -padx 8 -pady 4 -fill x
		
		#Flags
		set flags $entries.options
		frame $flags
		pack $flags -side top -fill x -padx 5
		
		#Case sensitive
		if {[info exists grep_Nocase]} {
			@@set $this-GrepNocase $grep_Nocase
		}
		label $flags.blank -text "" -bd 0 -width 10
		pack $flags.blank -side left
		checkbutton $flags.case \
				-onvalue "i" \
				-offvalue "" \
				-variable $this-GrepNocase \
				-text [get_indep String IgnoreCase] \
				-underline [get_indep Pos IgnoreCase]
		pack $flags.case -side left -fill x
		
		#How many entries are to be found
		@@set $this-BreakBy $grep_MaxFound
		Entry& $flags.breakby \
				-labelwidth 10 \
				-width 4 \
				-anchor ne \
				-label [get_indep String MultiGrepBreakBy] \
		  		-textvariable $this-BreakBy \
				-exportselection n
		bind [$flags.breakby entry] <Return> "$this ExecGrep"
		pack $flags.breakby -side left
		label $flags.lines -text [get_indep String MultiGrepLines]
		pack $flags.lines -side left
		
		#Slider for grep status
		if {![winfo exists $mesg_area.grep_status]} {
			ProgressBar $mesg_area.grep_status \
				-variable $this-scalevalue
			balloon_bind_info $mesg_area.grep_status [get_indep String GrepProcessing]
		}
		
		#Results
		set browser $this.list
		Browser& $browser\
			-exportselection n \
			-sort "" \
			-tabs "" \
			-filter_window 0 \
			-width $width \
			-height $height

		$browser tag config sel \
			-background $sn_options(def,select-bg)

		Editor& @@ set_tab $browser 2

		$browser bind <ButtonRelease-1> "$this handle_click"
		$browser bind <Return>   "$this handle_return"
		$browser bind <space>    "$this handle_return"
		$browser bind <Double-1> "$this handle_return"
		#bind_focus_enter $browser.t {focus %W}
		pack $browser -side bottom -fill both -expand y
		
		#add history to the combo boxes
		refresh_combo_history $entries.entry $entries.filter
		
		Update_Layout
		
		#init global variables
		upvar #0 $this-buffer buffer
		upvar #0 $this-ButtonPressed pressed
		@@set buffer ""
		@@set pressed ""
		
		#call user defined function
		catch {sn_rc_grep $this $browser} err
		sn_log "trying to execute sn_rc_grep:$err"
		
		focus [$entries.entry entry]
	}
	destructor {
		#to be sure that the process is terminated
		catch {close $grep_fd}
		foreach v [@@info globals "$this-*"] {
			catch {uplevel #0 unset $v}
		}
	}
	method cget {item} {
		set item [string range $item 1 end]
		return [set $item]
	}
	method config {config} {
	}
	
	method handle_cancel {} {
		if {$cancelcommand != ""} {
			@@eval $cancelcommand
		}
	}
	
	method disp_filter {combo txt} {
		global grep_PatternFormats
		global $this-GrepPatFilter
		foreach l $grep_PatternFormats {
			if {$txt == [lindex $l 0]} {
				@@set $this-GrepPatFilter [lindex $l end]
				break
			}
		}
	}
	
	proc FormatPattern {sym} {
		if {$sym != ""} {
			#convert string to be used for grep
			regsub -all {\^|\\|\.|\*|\$|\-|\[|\]} $sym {\\&} sym
			regsub -all {\<|\>} $sym {[&]} sym
		}
		return $sym
	}
	
	method refresh_combo_history {{patternw ""} {filterw ""}} {
		global sn_options
		global history_List
		
		if {$patternw != ""} {
			if {![info exists history_List(grep)]} {
				@@set history_List(grep) ""
			}
			set lbls ""
			foreach e $history_List(grep) {
				set lbl [lindex $e 2]
				set len [string first " " $lbl]
				lappend lbls [string range $lbl [expr $len + 1] end]
			}
			$patternw contents $lbls
		}
		
		#add file filter to the history stack of the file filters
		if {$filterw != ""} {
			sn_add_to_histroy_stack \
					sn_options(history,grep,file) \
					[$filterw getentry]
			$filterw contents $sn_options(history,grep,file)
		}
	}
	
	#restore the grep result
	method grep_select_command {patternw txt} {
		global sn_options
		global history_List
		foreach l $history_List(grep) {
			if {[lindex $l 2] == "grep $txt"} {
				eval $this DisplayFromHistory [lindex $l 1]
				return
			}
		}
	}
	
	method grep_select_file_filter {patternw txt} {
	}
	
	method ExecGrep {} {
		global sn_options
		global grep_File grep_Options
		global errorInfo errorCode
		global grep_MaxFound
		global grep_Nocase
		global tcl_platform
		
		upvar #0 $this-GrepString GrepString
		upvar #0 $this-GrepFilePat GrepFilePat
		upvar #0 $this-GrepPatFilter GrepPatFilter
		upvar #0 $this-GrepNocase GrepNocase
		upvar #0 $this-BreakBy BreakBy
		
		#grep is running
		if {$Proceed != 0} {
			$btns.start config -state disabled
			catch {close_grep}
			return
		}
		
		set pattern $GrepString
		if {[string compare [string trim $pattern] ""] == 0} {
			return
		}
	
		#save nocase/count
		@@set grep_Nocase $GrepNocase
		@@set grep_MaxFound $BreakBy
	
		if {[string compare [string index $pattern 0] "-"] == 0} {
			set pattern "\\$pattern"
		}
	
		#actualize title to current string
		SetTitle
	
		#file filter for files
		if {[catch {set filter $GrepFilePat}]} {
			set filter "*"
		}
		
		#convert pathes including "\" into "/"
		if {$tcl_platform(platform) == "windows"} {
			regsub -all {\\} $filter {/} filter
		}
	
		#read matched files from the project file
		set fls [@@lsort -command sn_compare [lmatch -glob [sn_project_file_list 0] $filter]]
		#count files
		set files_Count [llength $fls]
	
		#no files found!
		if {[string compare $fls ""] == 0} {
			sn_error_dialog "[get_indep String ErrorNoMatches] \"$GrepFilePat\" !"
			return
		}
	
		#Read pattern filter and make with the grep pattern
		#a new string
		if {![catch {set pat_filt $GrepPatFilter}] &&
			[string compare $pat_filt ""] != 0} {
			if {[regsub -all {%s} $pat_filt $pattern pat_filt]} {
				set pattern $pat_filt
			}
		} else {
			regsub -all {\<} $pattern {\\<} pattern
			regsub -all {\>} $pattern {\\>} pattern
		}
	
		#remove tabs from pattern
		regsub -all {\\t} $pattern "\t" pattern
	
		#get a temporary file and write the file names
		#into it
		set file_list [sn_tmpFileName]
		set fd [@@open $file_list "w+"]
		@@fconfigure $fd -encoding $sn_options(def,system-encoding)
		puts $fd [join $fls "\n"]
		close $fd
	
		#grep command
		lappend cmd $grep_File
		#We want to display the status of the grep command
		lappend cmd "-zz"

		#ignore case ?
		if {$GrepNocase != "" || $grep_Options != ""} {
			lappend cmd "-${GrepNocase}${grep_Options}"
		}
		
		#to highlight the found patterns in the found lines
		set highl_file [sn_tmpFileName]
		#append opt " -na $highl_file"
		lappend cmd $highl_file
		
		#add file with filenames to the arguments command
		lappend cmd "-y" "$file_list"
		
		#add max readed lines
		if {$BreakBy == "" || $BreakBy <= 0} {
			@@set BreakBy 100
		}
		lappend cmd "-m" "$BreakBy"
		
		#construct the grep command
		lappend cmd $pattern
		#set cmd [list $grep_File $cmd $pattern]
	
		#delete old contents
		$browser config -contents ""; update idletasks; update
	
		sn_log "Executing: $cmd"
		ExecGrepEvent $cmd
	}

	method ExecGrepEvent {cmd} {
		global sn_options
		global errorInfo errorCode env
		global tcl_platform
	
	    #make sure we stay in project directory (different interpeters).
		catch {cd $sn_options(sys,project-dir)}
		
		if {$tcl_platform(platform) != "windows"} {
			set home $env(HOME)
			if {[string compare $home "/"] != 0} {
				append home "/"
			}
			regsub -all "~/" $cmd $home cmd
		}
		
		sn_log "ExecGrepEvent: $cmd"
	
		#close older descriptor to be secure that no other grep
		#is started
		catch {close $grep_fd}
		
		if {[catch {@@set grep_fd [@@open "| $cmd" r]} errmsg]} {
			sn_error_dialog "-code error -errorinfo $errorInfo -errorcode $errorCode $errmsg"
			return
		}

		@@fconfigure $grep_fd -encoding $sn_options(def,system-encoding)

		#enable vertical scrolling during the grep process
		#and delete configure event
		set browser_Configure [@@bind $browser.t <Configure>]
		@@bind $browser.t <Configure> { }
		pack $browser.y -side right -fill y -before $browser.t
		
		$mesg_area.grep_status config -maxvalue $files_Count
		upvar #0 $this-scalevalue scalevalue; @@set scalevalue 0
		
		set errorInfo ""
		upvar #0 $this-counter counter; @@set counter 0
		upvar #0 $this-buffer buffer; @@set buffer ""
		
		if {[catch {@@fileevent $grep_fd readable "dispatch_GrepEvent $this $browser $mesg_area.grep_status $grep_fd"}]} {
			catch {close_grep}
		} else {
			handle_proceed disabled
		}
	}
	
	method close_grep {} {
		global sn_options

		#display the rest of buffer
		upvar #0 $this-buffer buffer
		upvar #0 $this-ButtonPressed pressed
		global sn_options
		
		if {$buffer != ""} {
			$browser.t config -state normal
			$browser.t insert end $buffer
			if {!$pressed} {
				$browser.t see active
			}
		}
		#restore normal state
		handle_proceed normal
		
		#color found positions
		Sn_Highlight_Text -delete $browser.t $highl_file
		
		#add the result into cache
		set lst [$browser.t get 0.0 {end -1c}]
		if {$lst != ""} {
			if {[file exists $highl_file]} {
				set fd [@@open $highl_file]
				@@fconfigure $fd -encoding $sn_options(def,system-encoding)
				set highl_pos [read $fd]
				close $fd
			} else {
				set highl_pos ""
			}
			sn_add_history grep \
				[list $pattern $filter $lst $highl_pos] \
				[sn_make_history_title grep $filter $pattern] \
				sn_grep_from_history
			
			refresh_combo_history $entries.entry $entries.filter
		}

		#remove temporary files
		file delete -- $file_list
		file delete -- $highl_file
	}

	#this function is called from history to display the cached
	#result
	method DisplayFromHistory {str flt lst highlights} {
		global sn_options
		global $this-GrepString
		global $this-GrepFilePat
		
		@@set $this-GrepString $str
		@@set $this-GrepFilePat $flt
		
		#store highlight list
		set highl_pos $highlights
		
		set highl [sn_tmpFileName]
		set fd [@@open $highl "w+"]
		@@fconfigure $fd -encoding $sn_options(def,system-encoding)
		puts $fd $highlights
		close $fd
		
		$browser.t config -state normal
		$browser.t delete 0.0 end
		$browser.t insert 0.0 $lst
		$browser.t config -state disabled
		
		Sn_Highlight_Text -delete $browser.t $highl
		file delete -- $highl
		
		Browser& @@ resize_widget $browser.t
	}
	
	#disable/enable input fields when the process is running/terminated
	method handle_proceed {state} {
		upvar #0 $this-ButtonPressed pressed
		
		if {$state == "normal"} {
			catch {close $grep_fd}
			
			@@set pressed 0
			
			$btns.start config -state $state
			$btns.cancel config -state disabled
			
			#rebind configure event
			@@bind $browser.t <Configure> $browser_Configure
			$browser.t config -state disabled
			Browser& @@ resize_widget $browser.t
			
			#hide the state displayer of grep
			#$mesg_area.grep_status config -state disabled
			catch {pack forget $mesg_area.grep_status}
			
			set Proceed 0
			
			$btns.start config -state $state
		} else {
			set Proceed 1
			@@set pressed 0
			
			$btns.start config -state $state
			$btns.cancel config -state normal
			
			#display the state of the grep command
			uplevel #0 "set $this-scalevalue 0"
			pack $mesg_area.grep_status -side right -fill y
		}
		
		[$entries.entry entry]  config -state $state
		[$entries.filter entry] config -state $state
		$catcombo				config -state $state
		$flags.case             config -state $state
		[$flags.breakby entry]  config -state $state
	}

	method Split_Line {} {
		global sn_options
	
		$browser tag remove sel 0.0 end
		$browser tag add sel {active linestart} {active lineend + 1c}
		set line [$browser get {active linestart} {active lineend}]
		
		#calculate the remaining line in the source file to highlight
		#the found grep pattern
		if {$line != ""} {
			set foundidx [expr {[string length [lrange [split $line :] 0 1]] + 1}]
			set textualline [string range $line $foundidx end]
		} else {
			return ""
		}
		set pars [sn_goto_comp_error_or_grep $line]
		if {$pars == ""} {
			return ""
		}
		set file [lindex $pars 0]
		set pos  [lindex $pars 1]
		set file [sn_convert_FileName $file]
		
		return [list $file $pos]
	}
	
	method next_entry {amount} {
		$browser select "active${amount}line"
		return [handle_click]
	}
	
	method Title {{full 1}} {
		global sn_options
		set t [string trimright [get_indep String MultiGrep] "."]
		set txt [[$entries.entry entry] get]
		if {$txt != ""} {
			set t "$t: $txt"
		}
		if {$full} {
			return [sn_title $t]
		} else {
			return $t
		}
	}
	method Icon {} {
		return [sn_view_icon [get_indep String MultiGrep]]
	}
	
	method SetTitle {} {
		#it can happen, that the string contains unmatched brackets
		#and Tcl respones with error message.
		catch {$topw title [Title]}
		$topw iconname [Icon]
	}
	
	method handle_return {} {
		$browser clear_search_pat
		if {[$browser index active] != ""} {
			$browser tag remove sel 0.0 end
			$browser select active
			set res [sn_grep_edit_file [$browser get {active linestart} {active lineend}]]
			if {$res == "" && !$hold} {
				catch {destroy $topw}
			}
		}
		upvar #0 $this-ButtonPressed pressed
		@@set pressed 1
	}
	
	#Click can goto a symbol
	method handle_click {} {
		upvar #0 $this-ButtonPressed pressed
		if {$selectcommand != ""} {
			watch y $this
			
			set ret [@@eval $selectcommand [Selection]]
			highlight_editor_matches
			
			watch n $this
		} else {
			set ret 0
		}
		@@set pressed 1
		
		return $ret
	}
	
	method highlight_editor_matches {} {
		global sn_options
		
		#highlight the match in the editor.
		if {$next != "" && [$next whoami] == "edit" && $foundranges != ""} {
			set ed [$next editor]

			#verify if the line in the editor has been changed
			if {$textualline != [$ed get "$foundline.0" "$foundline.end"]} {
				if {$sn_options(def,grep-mark-all)} {
					$ed tag remove sel 0.0 end
				}
				return 0
			}

			set lineranges ""
			foreach pos $foundranges {
				set col [expr {[lindex [split $pos .] end] - $foundidx}]
				lappend lineranges "$foundline.$col"
			}
			$ed tag remove sel  0.0 end
			$ed tag remove grep 0.0 end
			
			foreach {from to} $lineranges {
				$ed tag add sel $from $to
				if {! $sn_options(def,grep-mark-all)} {
					break
				}
			}
			
			#move to the first selection position in the editor.
			$ed mark set lastpos insert
			$ed mark set insert [lindex $lineranges 0]
			$ed see insert
			
			return 1
		}
		return 0
	}
	
	method print {} {
		if {$next != ""} {
			$next print
		} else {
			Editor& @@ print_dialog $browser.t
		}
	}
	
	method filter {{all 0}} {
	}
	
	#this function is called, when the symbols combobox
	#is called
	method postcommand {m} {
		set ed [MultiWindow& @@ list_find $next edit]
		if {$symbols == "" || $ed == ""} {
			return
		}
		$ed postcommand $m
	}

	method activate {} {
		if {$symbols != ""} {
			#delete old contents
			$symbols contents ""
			$symbols selecttext ""
			if {[MultiWindow& @@ list_find $next edit] == ""} {
				$symbols disable
			} else {
				$symbols enable
			}
		}
		if {$menu != ""} {
		}
		if {$toolbar != ""} {
			pack $toolbar.grepfr -side left
		}
	}
	
	method deactivate {} {
		if {$symbols != ""} {
			$symbols disable
		}
		if {$menu != ""} {
		}
		if {$toolbar != ""} {
			pack forget $toolbar.grepfr
		}
	}
	
	method Selection {} {
		global tcl_platform
		set sel [Split_Line]
		
		if {$sel != ""} {
			set active      [lindex [split [$browser index active] .] 0]
			set tags        [$browser tag ranges grep]
			set foundranges [lmatch $tags "$active.*"]
			set file [file nativename [lindex $sel 0]]
			if {$tcl_platform(platform) == "windows"} {
				regsub -all {\\} $file {/} file
			}
			set foundline [lindex $sel 1]
			
			if {$tcl_platform(platform) != "windows"} {
				set last [string last "/" $file]
				set len  [string length $file]
				#sometimes we get strang results from 'sn_goto_comp_error_or_grep'
				if {$last != -1 && [expr $last + 1] == $len || [string first "**" $file] == 0} {
					set file ""
					set foundline ""
				}
			}
		} else {
			set file ""
			set foundline ""
			set foundranges ""
		}
		return [list "" "" "" $file $foundline "" "" ""]
	}
	
	method gotosymbol {{scope ""} {sym ""} {cls ""} {file ""} \
				{from ""} {type ""} {prm ""} {to ""} {always 1}} {
		global $this-GrepString
		@@set $this-GrepString [FormatPattern $sym]
		return 1
	}
	
	method clearselection {} {
		$browser clear
	}
	
	method Update_Layout {} {
		global sn_options
		$browser tag configure grep \
				-font $sn_options(def,grep-found-font) \
				-foreground $sn_options(def,grep-found-fg)
		#\
				-background $sn_options(def,grep-found-bg)
		$browser config \
				-font $sn_options(def,grep-font) \
				-selectforeground $sn_options(def,select-fg) \
				-selectbackground $sn_options(def,select-bg)
	}
	
	method Focus {} {
		focus $browser.t
	}

	#make a title for the Dump position, this is usefull
	#for the views stack (prev/next)
	method DumpTitle {{dump ""}} {
		if {$dump == ""} {
			set dump [Dump]
		}
		set GrepString    [lindex $dump 0]
		set GrepFilePat   [lindex $dump 1]
		set GrepPatFilter [lindex $dump 2]
		set GrepNocase    [lindex $dump 3]
		set BreakBy       [lindex $dump 4]
		return "Grep [string trim ${GrepString}($GrepFilePat)]"
	}

	method AddHistoryFromDump {dump title} {
	}

	#return the important data to restore this widget
	#in later time again (used by saving the project)
	method Dump {} {
		upvar #0 $this-GrepString    GrepString
		upvar #0 $this-GrepFilePat   GrepFilePat
		upvar #0 $this-GrepPatFilter GrepPatFilter
		upvar #0 $this-GrepNocase    GrepNocase
		upvar #0 $this-BreakBy       BreakBy
		
		set cnts [$browser.t get 0.0 end]
		
		return [list $GrepString $GrepFilePat $GrepPatFilter $GrepNocase $BreakBy $cnts $highl_pos]
	}
	
	#gets the result from the function "Dump" to
	#restore the older state (used by restoring the project)
	method Restore {str} {
		upvar #0 $this-GrepString    GrepString
		upvar #0 $this-GrepFilePat   GrepFilePat
		upvar #0 $this-GrepPatFilter GrepPatFilter
		upvar #0 $this-GrepNocase    GrepNocase
		upvar #0 $this-BreakBy       BreakBy
		
		@@set GrepString    [lindex $str 0]
		@@set GrepFilePat   [lindex $str 1]
		@@set GrepPatFilter [lindex $str 2]
		@@set GrepNocase    [lindex $str 3]
		@@set BreakBy       [lindex $str 4]
		set cnt             [lindex $str 5]
		set highlights      [lindex $str 6]
		
		#restore result and it's highlights
		DisplayFromHistory $GrepString $GrepFilePat $cnt $highlights
	}
	
	method Close {{mode 0}} {
		return 1
	}
	
	method whoami {} {
		return grep
	}
	method next {} {
		return $next
	}
	
	#if an editor is added to the grep, call the
	#goto function of the editor
	method goto {combo txt} {
		set ed [MultiWindow& @@ list_find $next edit]
		if {$symbols != "" && $ed != ""} {
		
			#dump the current view into the history stack
			$topw history_stack_add_point $ed
		
			$ed goto $combo $txt
		}
	}

	protected progressbar ""
	protected foundidx 0
	protected foundline 0
	protected foundranges ""
	protected lineranges ""
	protected textualline ""
	
	protected filter "*"
	protected grep_fd ""
	protected file_list ""
	protected highl_file ""
	protected browser_Configure " "
	protected fd ""
	protected Proceed 0
	protected topw "."
	protected entries ""
	protected btns ""
	protected flags ""
	protected browser ""
	protected catcombo ""
	protected files_Count 0
	#last highlight positions
	protected highl_pos ""

	public pattern "" {
		global $this-GrepString
		if {$pattern != ""} {
			@@set $this-GrepString $pattern
		}
	}
	#don't close window after selecting an entry
	public hold 1
	public width 80
	public height 10
	public symbols ""
	public symbols_filter ""
	public mesg_area ""
	public mesg_linenumber ""
	public menu ""
	public toolbar ""
	public selectcommand ""
	public doubleclickcommand ""
	public withcancel 1
	public cancelcommand ""
	
	#contains the next widget, when the window is spliten
	#into more than one area
	#Simulate a single chain
	public next ""
}

proc dispatch_GrepEvent {cls browser scale fd} {
	upvar #0 $cls-ButtonPressed pressed
	upvar #0 $cls-counter counter
	upvar #0 $cls-buffer buffer
	upvar #0 $cls-scalevalue scalevalue
	
	if {[catch {set res [gets $fd line]}]} {
		catch {$cls close_grep}
		return
	}
	if {$res > -1} {
		#view position in the scale widget
		if {[string first "FILE_POSITION<" $line] == 0} {
			incr scalevalue
			update idletasks
			return
		}
		if {$line != ""} {
			append buffer $line
			append buffer "\n"
			incr counter
		}
		if {[expr $counter % 10] == 0} {
			$browser.t config -state normal
			$browser.t insert end $buffer
			if {!$pressed} {
				$browser.t see active
			}
			$browser.t config -state disabled
			set buffer ""
		}
	} elseif {$res < 0} {
		catch {$cls close_grep}
	}
	update idletasks
}



