#!/afs/ece/usr/tcl/bin/wish -f
# The next line is executed by most shells, but not Tcl \
wish $0 $*


set Bind_Keyword [file tail [info script]]
source "[file dirname [info script]]/../aux/frame.tcl"

# Help text.
set Help "" ; append Help {Searcheth -- Add keybindings to search for strings in textual widgets.

This program teaches widgets that contain text how to search for a particular
string, or glob expression, or regular expression. You can also replace any or
all matches found.

} $TH_Bindings_Help {

Widgets of Searcheth

The Implicit Case Button

Searcheth can decide whether searches are case-sensitive by two models. The
explicit model provides a keybinding whereby one can turn case sensitivity on
and off. The 'implicit' model, which is used if this button is set, makes
searches case-insensitive except if the search string contains uppercase
characters, or replacements are being done.


The Select Button

When a match is found, the widget is scrolled to view the found string, but some
means must be employed to highlight the text. If this button is turned on, then
the matching text will be selected, with the cursor at the beginning and the
anchor at the end of the selection (for Text and Entries). If turned off, the
text will not be highlighted with the selection, but searcheth will try to
indicate the found item by moving the cursor to the item and adjusting the view.
In addition, text widgets will mark the highlighted text with the 'search' tag.


The Replacement Button

If this button is on, then the functions for replacing any or all matches of a
search string are added.


Old Found Text Entry

Whenever searches are performed on a text widget, all text that has ever been
the object of a search gets a tag. This entry specifies configurations for that
tag, so that text can be displayed differently. The tag disappears whenever a
search is exited.


Current Found Text Entry

The text found under a search on a text widget also gets a tag. If the 'Select'
button is on, it gets the 'sel' tag. Otherwise, it gets a search tag, with
configurations specified on this line to highlight the text. The tag is removed
whenever a search is exited or another search is performed.


Replaced Text Entry

The text substituted during a replace operation gets a tag. This line specifies
the configurations for that tag. This replacement tag can coincide with the
old-found-text tag, but it is higher in priority, so its configurations will
dominate the other tag's configurations if they collide.

} $TH_Frame_Help {

Leaving the selection off for all but text widgets means that only the cursor
will serve to indicate the found text. Since, during search operations, the
focus will usually be in the search (or replace) entry, the cursor in the
searched widget will not be visible. It is recommended, though not necessary
that you keep the selection on for all but text widgets.

Case-sensitive string and regexp searches in Text widgets now use Tk's new
'search' command. This is faster than searcheth's routines, but it behaves
slightly differently. You cannot find a string at the upper left point on a text
widget using case-sensitive searches. Also the case-insensitive regexp search
works on multiple lines, though the case-sensitive regexp search does not, so
they can behave differently on the same range of text.}


# Gives app all the code necessary to do our functions.
proc teach_code {} {
  global TH_Dir Class
  if {![file exists "$TH_Dir/lib/search.[set Class].tcl"]} {return ""}

  include_files {search.Misc.tcl th_Misc_search}
  if {[file exists "$TH_Dir/lib/search.[set Class].tcl"]} {
    include_files [list search.$Class.tcl "th_[set Class]_find"]
  }
  if {[file exists "$TH_Dir/lib/browse.[set Class].tcl"]} {
    include_files [list browse.$Class.tcl "th_[set Class]_goto"]
  }
  if {$Class == "Text"} {
    include_files {mark.tcl th_mark_region}
  }

  teach_frame_code
  foreach binding {Search_Forward Search_Backward
		 Toggle_Case_Sensitivity Toggle_Incremental_Search} {
    teach_binding_code $binding ; teach_menuentry_code $binding}

  global Search_Select Replace Search_Implicit
  if $Search_Select {set tag "sel"} else {set tag "search"}
  do_cmd_set TH(Search,Select,$Class) $tag
  do_cmd_set TH(Search,Case,Implicit) $Search_Implicit

  if {$Replace && [file exists "$TH_Dir/lib/replace.$Class.tcl"]} {
    include_files {replace.Misc.tcl th_Misc_replace_setup} \
	[list replace.$Class.tcl th_[set Class]_replace_one]
    foreach binding {Replace_One Replace_All} {
       teach_binding_code $binding ; teach_menuentry_code $binding
  }}

  if {[lsearch "Text Listbox" $Class] >= 0} {
    teach_binding_code Highlight_Searches ; teach_menuentry_code Highlight_Searches
    if {$Class == "Text"} {
      teach_binding_code Mark_Text ; teach_menuentry_code Mark_Text
      teach_binding_code Unmark_Text ; teach_menuentry_code Unmark_Text
  }}
  if {$Class == "Text"} {
    global Old_Search_Tag Search_Tag Replace_Tag
    do_cmd_set TH(Search,Text,Oldtag) $Old_Search_Tag
    if {!$Search_Select} {
      do_cmd_set TH(Search,Text,Tag) $Search_Tag
    }
    if $Replace {
      do_cmd_set TH(Replace,Tag) $Replace_Tag
}}}

# For a widget, returns the appropriate bindings. (They will depend on the
# widget)
proc widget_bindings {} {
  global TH_Dir Bindings Class Search_Implicit
  set bindings ""
  if {[file exists "$TH_Dir/lib/search.[set Class].tcl"]} {
    set bindings $Bindings(Search)} else {return ""}
  if {!$Search_Implicit} {set bindings [concat $bindings $Bindings(Search,Case)]}
  return [widget_frame_bindings $bindings]
}


create_form_entry .st "Configuration of Current Found Text:" Search_Tag \
          "-background yellow -foreground black"
create_form_entry .ost "Configuration of Old Found Text:" Old_Search_Tag \
          "-background yellow4 -foreground white" 
create_form_entry .rt "Configuration of Replacement Text:" Replace_Tag \
          "-background orange4 -foreground white"
frame .searchframe ; pack .searchframe -fill x
create_form_checkbutton .searchframe.implicit "Implicit Case" Search_Implicit \
          1 left
create_form_checkbutton .searchframe.select "Select Found Item" Search_Select \
          1 left
create_form_checkbutton .searchframe.replace "Add Replacement" Replace 1 left
