#
# Module for performing searches in Entry widgets
#


# Searches w for next instance of string.
proc th_Entry_find {w string {next 1} {direction "forward"} {type "string"}} {
  global TH
  set border(forward) -1
  if {![catch "$w index sel.first" was_search_start]} {
    set was_search_end [$w index sel.last]
    incr was_search_end -1
    set insert [$w index insert]
    if {($was_search_start <= $insert) && ($insert <= $was_search_end)} {
      $w select clear
      if $next {
        set border(forward) [incr was_search_start]
        set border(backward) [incr was_search_end -1]
      } else {
        set border(forward) $was_search_start
        set border(backward) [incr was_search_end]
  }}}
  if {$border(forward) == -1} {
    if $next {
      set border(forward) [expr [$w index insert] +1]
      set border(backward) [expr [$w index insert] -1]
    } else {
      set border(forward) [$w index insert]
      set border(backward) [expr [$w index insert] + [string length $string] - 1]
  }}

  if {[catch "set TH(Search,Failed,$w)"]} {set TH(Search,Failed,$w) 0}
  if $TH(Search,Failed,$w) {
    set border(forward) 0
    set border(backward) end
  }

  set length [string length $string]
  if {($length == 0)} {return 0}

  set slist [th_Entry_[set type]_[set direction] $w $border($direction) $string]
  if {($slist != "")} {
    $w icursor [lindex $slist 0]
    th_Entry_goto $w [lindex $slist 0] 0
    if {$TH(Search,Select,[winfo class $w]) == "sel"} {
      th_Entry_select_range $w [lindex $slist 0] [expr [lindex $slist 1] + 1]
    }
    set TH(Search,Failed,$w) 0
    return 1
  } else {
    set TH(Search,Failed,$w) 1
    return 0
}}


# Finds first occurrence of string after point in widget w
# Returns start and end of occurance or "" if unsuccessful.
proc th_Entry_string_forward {w point string} {
  global TH
  set text [string range [$w get] $point end]
  if $TH(Search,Case,$w) {set text [string tolower $text]}
  set answer [string first $string $text]
  if {($answer == -1)} {return ""
  } else {
    incr answer $point
    return [list $answer [expr $answer + [string length $string] - 1]]
}}

# Finds last occurrence of string before point in widget w
# Returns start and end of occurance or "" if unsuccessful.
proc th_Entry_string_backward {w point string} {
  global TH
  set text [string range [$w get] 0 $point]
  if $TH(Search,Case,$w) {set text [string tolower $text]}
  set answer [string last $string $text]
  if {($answer == -1)} {return ""
  } else {return [list $answer [expr $answer + [string length $string] - 1]]
}}


# Finds first occurrence of string after point in widget w using regexp.
# Returns start and end of occurance or "" if unsuccessful.
proc th_Entry_regexp_forward {w point string} {
  global TH
  if $TH(Search,Case,$w) {
    if {[catch {regexp -indices -nocase -- $string [string range [$w get] $point end] where} result]} {bell ; return}
  } else {if {[catch {regexp -indices -- $string [string range [$w get] $point end] where} result]} {bell ; return}
  }
  if {!$result} {return ""}

  return [list [expr $point + [lindex $where 0]] \
               [expr $point + [lindex $where 1]]]
}

# Like regexp_forward, but searches from beginning to point.
proc th_Entry_regexp_backward {w point string} {
  global TH
  set text [string range [$w get] 0 $point]
  set text_range $text
  set offset 0
  set answer ""
  while {1} {
    if $TH(Search,Case,$w) {
      if {[catch {regexp -indices -nocase -- $string $text_range where} result]} {bell ; return}
    } else {if {[catch {regexp -indices -- $string $text_range where} result]} {bell ; return}
    }
    if $result {
      set answer [list [expr $offset + [lindex $where 0]] \
			[expr $offset + [lindex $where 1]]]
    } else {break}
    incr offset [expr [lindex $where 0] +1]
    set text_range [string range $text $offset end]
  }
  return $answer
}
