#
# Brings up a menu for tags in Text widgets
#


# Ensures name is a valid window name
proc th_validate_widget {name} {
  regsub -all -- {\?|\:|\/|\-|\.} $name {_} new_name
  return [string tolower $new_name]
}

# Fills w's menu with the tags in w. This should only be invoked by a menuoption
# becuase it adds the menu to the menuoption currently active.
# Don't use the args, those are so it can call itself recursively.
proc th_Text_make_tags_menu {w args} {
  if {[catch "[focus -displayof [winfo toplevel $w]] entrycget active -menu" menu]} {return}
  if {$menu == ""} {return}

# Destroy old submenus and remove all elements in menu.
  if {[winfo exists $menu]} {
    foreach submenu [winfo children $menu] {destroy $submenu}
    $menu delete [$menu cget -tearoff] last
  } else {menu $menu}
  $menu configure -tearoff 0

# Now add elements in menu, allow elements to be added in submenus.
  global TH
  set tag_flag 1

  if {$args != ""} {set rest $args
  } elseif {[set rest [$w tag names]] == ""} {
    $menu add command -label "(None)"
    return
  }

  if {$TH(Tag,Entries,Max) <= 0} {set tags $rest} else {
    set tags ""
    foreach tag $rest {
      set rest [lrange $rest 1 end]
      if {!$TH(Tag,Empty) && [catch {$w index $tag.first}]} {continue}
      lappend tags $tag
      if {$TH(Tag,Entries,Max) <= [llength $tags]} {
        catch "menu $menu.more -tearoff 0 -postcommand \
		\"th_Text_make_tags_menu $w $rest\""
        $menu add cascade -label "More..." -menu $menu.more
        break
  }}}
  if {$tags == ""} {$menu add command -label "(None)"} else {
    foreach tag $tags {
      if {!$TH(Tag,Empty) && [catch {$w index $tag.first}]} {continue}
      set submenu "$menu.[th_validate_widget $tag]"
      catch {menu $submenu -tearoff 0 \
  	-postcommand "th_Text_make_tag_ranges_menu $w \"$tag\" $submenu"}
      $menu add cascade -label "$tag" -menu $submenu
}}}

# Fills menu with the tag ranges of tag, If ranges are specified, uses those as
# tag range (args can be a subset of the ranges) Should only be called by the
# previous procedure.
proc th_Text_make_tag_ranges_menu {w tag menu args} {
  global TH
  set count 0
  catch {$menu delete [$menu cget -tearoff] last}
  set begin_flag 1
  if {$args != ""} {set ranges $args
  } elseif {[set ranges [$w tag ranges $tag]] == ""} {
    $menu add command -label "(None)"
    return
  }
  if {$TH(Tag,Entries,Max) > 0} {
    set stop [expr $TH(Tag,Entries,Max) * 2]
    if {[llength $ranges] > $stop} {
      set rest [lrange $ranges $stop end]
      set ranges [lrange $ranges 0 [expr $stop - 1]]
      catch "menu $menu.more  -tearoff 0 -postcommand \
		\"th_Text_make_tag_ranges_menu $w $tag $menu.more $rest\""
      $menu add cascade -label "More..." -menu $menu.more
  }}

  foreach index $ranges {
    if $begin_flag {set begin_index $index ; set begin_flag 0 ; continue}

    set begin_flag 1 ; set end_index $index
    set text [string trim [$w get $begin_index $end_index] "\n"]
    if {([string length $text] < $TH(Tag,Menu,Length)) && \
	([string first "\n" $text] == -1)} {
      set begin_text $text
    } else {
      set begin_text [string range $text 0 [expr $TH(Tag,Menu,Length) / 2]]
      if {[set break [string first "\n" $begin_text]] > 0} {
        incr break -1
        set tmp $begin_text ; set text [string range $tmp 0 $break]
      }
      append begin_text "..."

      set end_text [string range $text [expr [string length $text] - \
			($TH(Tag,Menu,Length) / 2)] end]
      if {[set break [string last "\n" $end_text]] >= 0} {
        incr break
        set tmp $end_text ; set end_text [string range $tmp $break end]
      }
      append begin_text $end_text
    }
    set cmd "th_Text_goto $w $begin_index 0"
    if {[catch "set TH(Tag,Select)"]} {set TH(Tag,Select) 0}
    if $TH(Tag,Select) {
      append cmd " ; th_Text_select_range $w insert $end_index"}
    $menu add command -label $begin_text -command $cmd
}}
