#!/usr/bin/wish

font create normal -family Helvetica -weight normal
font create bold   -family Helvetica -weight bold

# two text widgets...

text .view1 -width 60 -height 10 -wrap none \
	-xscrollcommand ".hsb1 set" -yscrollcommand ".vsb1 set" \
	-font normal
text .view2 -width 60 -height 10 -wrap none \
	-xscrollcommand ".hsb2 set" -yscrollcommand ".vsb2 set" \
	-font normal

# two vertical scrollbars

scrollbar .vsb1 -orient vertical -command ".view1 yview"
scrollbar .vsb2 -orient vertical -command ".view2 yview"

# and two horizontal scrollbars

scrollbar .hsb1 -orient horizontal -command ".view1 xview"
scrollbar .hsb2 -orient horizontal -command ".view2 xview"

# and a toolbar with buttons to make a region bold or normal

frame .toolbar
button .toolbar.bold -text "Bold" -command "highlight bold" -bd 1
button .toolbar.normal -text "Normal" -command "highlight normal" -bd 1
pack .toolbar.bold .toolbar.normal -side left

grid .toolbar -sticky ew   -row 0 -column 0 -columnspan 2
grid .view1   -sticky nsew -row 1 -column 0
grid .vsb1    -sticky ns   -row 1 -column 1
grid .hsb1    -sticky ew   -row 2 -column 0
grid .view2   -sticky nsew -row 3 -column 0
grid .vsb2    -sticky ns   -row 3 -column 1
grid .hsb2    -sticky ew   -row 4 -column 0

grid rowconfigure . 1 -weight 1
grid rowconfigure . 3 -weight 1
grid columnconfigure . 0 -weight 1

# just for fun, set a binding on <Esc> to move between the two windows
# it makes playing around with this demo a little easier...

bind .view1 <Escape> {focus .view2}
bind .view2 <Escape> {focus .view1}

# here's the fun part: redefining each widget's proc to send commands
# to the other.

rename .view1 _.view1_
rename .view2 _.view2_

proc .view1 {args} {
     # request the other widget to do the very same thing. Only,
     # we'll get a little clever and *not* replicate scrolling commands
     # in the other window so you can truly have two different views
     # into the text
     set cmd [lindex $args 0]
     if {$cmd != "see" && $cmd != "xview" && $cmd != "yview"} {
	eval _.view2_ $args
     }

     # now, let the original widget do its thing
     set result [eval _.view1_ $args]


     return $result
}

proc .view2 {args} {
     # request the other widget to do the very same thing. Only,
     # we'll get a little clever and *not* replicate scrolling commands
     # in the other window so you can truly have two different views
     # into the text
     set cmd [lindex $args 0]
     if {$cmd != "see" && $cmd != "xview" && $cmd != "yview"} {
	eval _.view1_ $args
     }

     # now, let the original widget do its thing
     set result [eval _.view2_ $args]

     return $result
}

# now that they are linked, define some tags just to prove that tags
# are linked, too

.view1 tag configure bold -font bold
.view1 tag configure normal -font normal

# let's go ahead and add some data in the widgets so we have a starting
# point. We'll insert one long line, then insert a whole bunch of short
# lines, just to prove the scrollbars work...

.view1 insert 1.0 "To make text bold or normal, highlight a region in
either window and click on the \"Bold\" or \"Normal\" button.

Here's a list of commands, just to give enough text to scroll around;
it should be one long line so you can scroll horizontally

[join [info commands]. {, }]

Here's the same list, one command per line:

[join [info commands] \n]
"

proc highlight {which} {
     # get window with focus
     set w [focus]

     # see if something is selected
     set sel ""
     catch {set sel [$w tag ranges sel]}
     if {$sel != ""} {
	    if {$which == "normal"} {
		    eval \$w tag remove bold $sel
		    eval \$w tag add normal $sel
	    } else {
		    eval \$w tag remove normal $sel
		    eval \$w tag add bold $sel
	    }
     }
}
