1# hiertable.tcl
2# ----------------------------------------------------------------------
3# Bindings for the BLT hiertable widget
4# ----------------------------------------------------------------------
5#   AUTHOR:  George Howlett
6#            Bell Labs Innovations for Lucent Technologies
7#            gah@lucent.com
8#            http://www.tcltk.com/blt
9#
10#      RCS:  $Id: hiertable.tcl,v 1.1.1.1 2009/05/09 16:27:21 pcmacdon Exp $
11#
12# ----------------------------------------------------------------------
13# Copyright (c) 1998  Lucent Technologies, Inc.
14# ======================================================================
15#
16# Permission to use, copy, modify, and distribute this software and its
17# documentation for any purpose and without fee is hereby granted,
18# provided that the above copyright notice appear in all copies and that
19# both that the copyright notice and warranty disclaimer appear in
20# supporting documentation, and that the names of Lucent Technologies
21# any of their entities not be used in advertising or publicity
22# pertaining to distribution of the software without specific, written
23# prior permission.
24#
25# Lucent Technologies disclaims all warranties with regard to this
26# software, including all implied warranties of merchantability and
27# fitness.  In no event shall Lucent be liable for any special, indirect
28# or consequential damages or any damages whatsoever resulting from loss
29# of use, data or profits, whether in an action of contract, negligence
30# or other tortuous action, arising out of or in connection with the use
31# or performance of this software.
32#
33# ======================================================================
34
35namespace eval blt::Hiertable {
36    variable afterId ""
37    variable scroll 0
38    variable column ""
39    variable space   off
40    variable x 0
41    variable y 0
42}
43
44#
45# ButtonPress assignments
46#
47#	B1-Enter	start auto-scrolling
48#	B1-Leave	stop auto-scrolling
49#	ButtonPress-2	start scan
50#	B2-Motion	adjust scan
51#	ButtonRelease-2 stop scan
52#
53
54bind Hiertable <ButtonPress-2> {
55    set blt::Hiertable::cursor [%W cget -cursor]
56    %W configure -cursor hand1
57    %W scan mark %x %y
58}
59
60bind Hiertable <B2-Motion> {
61    %W scan dragto %x %y
62}
63
64bind Hiertable <ButtonRelease-2> {
65    %W configure -cursor $blt::Hiertable::cursor
66}
67
68bind Hiertable <B1-Leave> {
69    if { $blt::Hiertable::scroll } {
70	blt::Hiertable::AutoScroll %W
71    }
72}
73
74bind Hiertable <B1-Enter> {
75    after cancel $blt::Hiertable::afterId
76}
77
78#
79# KeyPress assignments
80#
81#	Up
82#	Down
83#	Shift-Up
84#	Shift-Down
85#	Prior (PageUp)
86#	Next  (PageDn)
87#	Left
88#	Right
89#	space		Start selection toggle of entry currently with focus.
90#	Return		Start selection toggle of entry currently with focus.
91#	Home
92#	End
93#	F1
94#	F2
95#	ASCII char	Go to next open entry starting with character.
96#
97# KeyRelease
98#
99#	space		Stop selection toggle of entry currently with focus.
100#	Return		Stop selection toggle of entry currently with focus.
101
102
103bind Hiertable <KeyPress-Up> {
104    blt::Hiertable::MoveFocus %W up
105    if { $blt::Hiertable::space } {
106	%W selection toggle focus
107    }
108}
109
110bind Hiertable <KeyPress-Down> {
111    blt::Hiertable::MoveFocus %W down
112    if { $blt::Hiertable::space } {
113	%W selection toggle focus
114    }
115}
116
117bind Hiertable <Shift-KeyPress-Up> {
118    blt::Hiertable::MoveFocus %W prevsibling
119}
120
121bind Hiertable <Shift-KeyPress-Down> {
122    blt::Hiertable::MoveFocus %W nextsibling
123}
124
125bind Hiertable <KeyPress-Prior> {
126    blt::Hiertable::MovePage %W top
127}
128
129bind Hiertable <KeyPress-Next> {
130    blt::Hiertable::MovePage %W bottom
131}
132
133bind Hiertable <KeyPress-Left> {
134    %W close focus
135}
136bind Hiertable <KeyPress-Right> {
137    %W open focus
138    %W see focus -anchor w
139}
140
141bind Hiertable <KeyPress-space> {
142    if { [%W cget -selectmode] == "single" } {
143	if { [%W selection includes focus] } {
144	    %W selection clearall
145	} else {
146	    %W selection clearall
147	    %W selection set focus
148	}
149    } else {
150	%W selection toggle focus
151    }
152    set blt::Hiertable::space on
153}
154
155bind Hiertable <KeyRelease-space> {
156    set blt::Hiertable::space off
157}
158
159bind Hiertable <KeyPress-Return> {
160    blt::Hiertable::MoveFocus %W focus
161    set blt::Hiertable::space on
162}
163
164bind Hiertable <KeyRelease-Return> {
165    set blt::Hiertable::space off
166}
167
168bind Hiertable <KeyPress> {
169    blt::Hiertable::NextMatchingEntry %W %A
170}
171
172bind Hiertable <KeyPress-Home> {
173    blt::Hiertable::MoveFocus %W top
174}
175
176bind Hiertable <KeyPress-End> {
177    blt::Hiertable::MoveFocus %W bottom
178}
179
180bind Hiertable <KeyPress-F1> {
181    %W open -r root
182}
183
184bind Hiertable <KeyPress-F2> {
185    eval %W close -r [%W entry children root]
186}
187
188#
189# Differences between "current" and nearest.
190#
191#	set index [$widget index current]
192#	set index [$widget nearest $x $y]
193#
194#	o Nearest gives you the closest entry.
195#	o current is "" if
196#	   1) the pointer isn't over an entry.
197#	   2) the pointer is over a open/close button.
198#	   3)
199#
200#
201# ----------------------------------------------------------------------
202#
203# USAGE: blt::Hiertable::Init <hiertable>
204#
205# Invoked by internally by Hiertable_Init routine.  Initializes the
206# default bindings for the hiertable widget entries.  These are local
207# to the widget, so they can't be set through the widget's class
208# bind tags.
209#
210# Arguments:	hiertable		hierarchy widget
211#
212# ----------------------------------------------------------------------
213proc blt::Hiertable::Init { widget } {
214    #
215    # Active entry bindings
216    #
217    $widget bind Entry <Enter> {
218	%W entry highlight current
219    }
220    $widget bind Entry <Leave> {
221	%W entry highlight ""
222    }
223
224    #
225    # Button bindings
226    #
227    $widget button bind all <ButtonRelease-1> {
228	%W see -anchor nw current
229	%W toggle current
230    }
231    $widget button bind all <Enter> {
232	%W button highlight current
233    }
234    $widget button bind all <Leave> {
235	%W button highlight ""
236    }
237
238    #
239    # ButtonPress-1
240    #
241    #	Performs the following operations:
242    #
243    #	1. Clears the previous selection.
244    #	2. Selects the current entry.
245    #	3. Sets the focus to this entry.
246    #	4. Scrolls the entry into view.
247    #	5. Sets the selection anchor to this entry, just in case
248    #	   this is "multiple" mode.
249    #
250
251    $widget bind Entry <ButtonPress-1> {
252	blt::Hiertable::SetSelectionAnchor %W current
253	set blt::Hiertable::scroll 1
254    }
255
256    $widget bind Entry <Double-ButtonPress-1> {
257	%W toggle current
258    }
259
260    #
261    # B1-Motion
262    #
263    #	For "multiple" mode only.  Saves the current location of the
264    #	pointer for auto-scrolling.  Resets the selection mark.
265    #
266    $widget bind Entry <B1-Motion> {
267	set blt::Hiertable::x %x
268	set blt::Hiertable::y %y
269	set index [%W nearest %x %y]
270	if { [%W cget -selectmode] == "multiple" } {
271	    %W selection mark $index
272	} else {
273	    blt::Hiertable::SetSelectionAnchor %W $index
274	}
275    }
276
277    #
278    # ButtonRelease-1
279    #
280    #	For "multiple" mode only.
281    #
282    $widget bind Entry <ButtonRelease-1> {
283	if { [%W cget -selectmode] == "multiple" } {
284	    %W selection anchor current
285	}
286	after cancel $blt::Hiertable::afterId
287	set blt::Hiertable::scroll 0
288    }
289
290    #
291    # Shift-ButtonPress-1
292    #
293    #	For "multiple" mode only.
294    #
295
296    $widget bind Entry <Shift-ButtonPress-1> {
297	if { [%W cget -selectmode] == "multiple" && [%W selection present] } {
298	    if { [%W index anchor] == "" } {
299		%W selection anchor current
300	    }
301	    set index [%W index anchor]
302	    %W selection clearall
303	    %W selection set $index current
304	} else {
305	    blt::Hiertable::SetSelectionAnchor %W current
306	}
307    }
308    $widget bind Entry <Shift-Double-ButtonPress-1> {
309	puts <Shift-Double-ButtonPress-1>
310	# do nothing
311    }
312    $widget bind Entry <Shift-B1-Motion> {
313	# do nothing
314    }
315    $widget bind Entry <Shift-ButtonRelease-1> {
316	after cancel $blt::Hiertable::afterId
317	set blt::Hiertable::scroll 0
318    }
319
320    #
321    # Control-ButtonPress-1
322    #
323    #	For "multiple" mode only.
324    #
325    $widget bind Entry <Control-ButtonPress-1> {
326	if { [%W cget -selectmode] == "multiple" } {
327	    set index [%W index current]
328	    %W selection toggle $index
329	    %W selection anchor $index
330	} else {
331	    blt::Hiertable::SetSelectionAnchor %W current
332	}
333    }
334    $widget bind Entry <Control-Double-ButtonPress-1> {
335	puts <Control-Double-ButtonPress-1>
336	# do nothing
337    }
338    $widget bind Entry <Control-B1-Motion> {
339	# do nothing
340    }
341    $widget bind Entry <Control-ButtonRelease-1> {
342	after cancel $blt::Hiertable::afterId
343	set blt::Hiertable::scroll 0
344    }
345
346    $widget bind Entry <Control-Shift-ButtonPress-1> {
347	if { [%W cget -selectmode] == "multiple" && [%W selection present] } {
348	    if { [%W index anchor] == "" } {
349		%W selection anchor current
350	    }
351	    if { [%W selection includes anchor] } {
352		%W selection set anchor current
353	    } else {
354		%W selection clear anchor current
355		%W selection set current
356	    }
357	} else {
358	    blt::Hiertable::SetSelectionAnchor %W current
359	}
360    }
361    $widget bind Entry <Control-Shift-Double-ButtonPress-1> {
362	puts <Control-Shift-Double-ButtonPress-1>
363	# do nothing
364    }
365    $widget bind Entry <Control-Shift-B1-Motion> {
366	# do nothing
367    }
368    $widget column bind all <Enter> {
369	%W column highlight [%W column current]
370    }
371    $widget column bind all <Leave> {
372	%W column highlight ""
373    }
374    $widget column bind Rule <Enter> {
375	%W column highlight [%W column current]
376	%W column resize activate [%W column current]
377    }
378    $widget column bind Rule <Leave> {
379	%W column highlight ""
380	%W column resize activate ""
381    }
382    $widget column bind Rule <ButtonPress-1> {
383	%W column resize anchor %x
384    }
385    $widget column bind Rule <B1-Motion> {
386	%W column resize mark %x
387    }
388    $widget column bind Rule <ButtonRelease-1> {
389	%W column configure [%W column current] -width [%W column resize set]
390    }
391    $widget column bind all <ButtonRelease-1> {
392	set column [%W column nearest %x %y]
393	if { $column != "" } {
394	    %W column invoke $column
395	}
396    }
397}
398
399# ----------------------------------------------------------------------
400# USAGE: blt::Hiertable::AutoScroll <hiertable>
401#
402# Invoked when the user is selecting elements in a hiertable widget
403# and drags the mouse pointer outside of the widget.  Scrolls the
404# view in the direction of the pointer.
405#
406# Arguments:	hiertable		hierarchy widget
407#
408# ----------------------------------------------------------------------
409proc blt::Hiertable::AutoScroll { widget } {
410    if { ![winfo exists $widget] } {
411	return
412    }
413    set x $blt::Hiertable::x
414    set y $blt::Hiertable::y
415
416    set index [$widget nearest $x $y]
417
418    if {$y >= [winfo height $widget]} {
419	$widget yview scroll 1 units
420	set neighbor down
421    } elseif {$y < 0} {
422	$widget yview scroll -1 units
423	set neighbor up
424    } else {
425	set neighbor $index
426    }
427    if { [$widget cget -selectmode] == "single" } {
428	blt::Hiertable::SetSelectionAnchor $widget $neighbor
429    } else {
430	$widget selection mark $index
431    }
432    set ::blt::Hiertable::afterId [after 10 blt::Hiertable::AutoScroll $widget]
433}
434
435proc blt::Hiertable::SetSelectionAnchor { widget index } {
436    set index [$widget index $index]
437    # If the anchor hasn't changed, don't do anything
438    if { $index != [$widget index anchor] } {
439	$widget selection clearall
440	$widget see $index
441	$widget focus $index
442	$widget selection set $index
443	$widget selection anchor $index
444    }
445}
446
447# ----------------------------------------------------------------------
448# USAGE: blt::Hiertable::MoveFocus <hiertable> <where>
449#
450# Invoked by KeyPress bindings.  Moves the active selection to the
451# entry <where>, which is an index such as "up", "down", "prevsibling",
452# "nextsibling", etc.
453# ----------------------------------------------------------------------
454proc blt::Hiertable::MoveFocus { widget where } {
455    catch {$widget focus $where}
456    if { [$widget cget -selectmode] == "single" } {
457        $widget selection clearall
458        $widget selection set focus
459    }
460    $widget see focus
461}
462
463# ----------------------------------------------------------------------
464# USAGE: blt::Hiertable::MovePage <hiertable> <where>
465# Arguments:	hiertable		hierarchy widget
466#
467# Invoked by KeyPress bindings.  Pages the current view up or down.
468# The <where> argument should be either "top" or "bottom".
469# ----------------------------------------------------------------------
470
471proc blt::Hiertable::MovePage { widget where } {
472
473    # If the focus is already at the top/bottom of the window, we want
474    # to scroll a page. It's really one page minus an entry because we
475    # want to see the last entry on the next/last page.
476    if { [$widget index focus] == [$widget index view.$where] } {
477        if {$where == "top"} {
478	    $widget yview scroll -1 pages
479	    $widget yview scroll 1 units
480        } else {
481	    $widget yview scroll 1 pages
482	    $widget yview scroll -1 units
483        }
484    }
485    update
486
487    # Adjust the entry focus and the view.  Also activate the entry.
488    # just in case the mouse point is not in the widget.
489    $widget entry highlight view.$where
490    $widget focus view.$where
491    $widget see view.$where
492    if { [$widget cget -selectmode] == "single" } {
493        $widget selection clearall
494        $widget selection set focus
495    }
496}
497
498# ----------------------------------------------------------------------
499# USAGE: blt::Hiertable::NextMatchingEntry <hiertable> <char>
500# Arguments:	hiertable		hierarchy widget
501#
502# Invoked by KeyPress bindings.  Searches for an entry that starts
503# with the letter <char> and makes that entry active.
504# ----------------------------------------------------------------------
505
506proc blt::Hiertable::NextMatchingEntry { widget key } {
507    if {[string match {[ -~]} $key]} {
508	set last [$widget index focus]
509	set next [$widget index next]
510	while { $next != $last } {
511	    set label [$widget entry cget $next -label]
512	    if { [string index $label 0] == $key } {
513		break
514	    }
515	    set next [$widget index -at $next next]
516	}
517	$widget focus $next
518        if {[$widget cget -selectmode] == "single"} {
519            $widget selection clearall
520            $widget selection set focus
521        }
522	$widget see focus
523    }
524}
525
526#
527#  Edit mode assignments
528#
529#	ButtonPress-3   Enables/disables edit mode on entry.  Sets focus to
530#			entry.
531#
532#  KeyPress
533#
534#	Left		Move insertion position to previous.
535#	Right		Move insertion position to next.
536#	Up		Move insertion position up one line.
537#	Down		Move insertion position down one line.
538#	Return		End edit mode.
539#	Shift-Return	Line feed.
540#	Home		Move to first position.
541#	End		Move to last position.
542#	ASCII char	Insert character left of insertion point.
543#	Del		Delete character right of insertion point.
544#	Delete		Delete character left of insertion point.
545#	Ctrl-X		Cut
546#	Ctrl-V		Copy
547#	Ctrl-P		Paste
548#
549#  KeyRelease
550#
551#  ButtonPress-1	Start selection if in entry, otherwise clear selection.
552#  B1-Motion		Extend/reduce selection.
553#  ButtonRelease-1      End selection if in entry, otherwise use last selection.
554#  B1-Enter		Disabled.
555#  B1-Leave		Disabled.
556#  ButtonPress-2	Same as above.
557#  B2-Motion		Same as above.
558#  ButtonRelease-2	Same as above.
559#
560# All bindings in editting mode will "break" to override other bindings.
561#
562#
563
564bind xEditor <ButtonPress-3> {
565    set node [%W nearest %x %y]
566    %W entry insert $node @%x,%y ""
567#    %W entry insert $node 2 ""
568}
569
570image create photo blt::Hiertable::CloseNormalFolder -format gif -data {
571R0lGODlhEAANAMIAAAAAAH9/f///////AL+/vwAA/wAAAAAAACH5BAEAAAUALAAAAAAQAA0A
572AAM8WBrM+rAEQWmIb5KxiWjNInCkV32AJHRlGQBgDA7vdN4vUa8tC78qlrCWmvRKsJTquHkp
573ZTKAsiCtWq0JADs=
574}
575image create photo blt::Hiertable::OpenNormalFolder -format gif -data {
576R0lGODlhEAANAMIAAAAAAH9/f///////AL+/vwAA/wAAAAAAACH5BAEAAAUALAAAAAAQAA0A
577AAM1WBrM+rAEMigJ8c3Kb3OSII6kGABhp1JnaK1VGwjwKwtvHqNzzd263M3H4n2OH1QBwGw6
578nQkAOw==
579}
580image create photo blt::Hiertable::CloseActiveFolder -format gif -data {
581R0lGODlhEAANAMIAAAAAAH9/f/////+/AL+/vwAA/wAAAAAAACH5BAEAAAUALAAAAAAQAA0A
582AAM8WBrM+rAEQWmIb5KxiWjNInCkV32AJHRlGQBgDA7vdN4vUa8tC78qlrCWmvRKsJTquHkp
583ZTKAsiCtWq0JADs=
584}
585image create photo blt::Hiertable::OpenActiveFolder -format gif -data {
586R0lGODlhEAANAMIAAAAAAH9/f/////+/AL+/vwAA/wAAAAAAACH5BAEAAAUALAAAAAAQAA0A
587AAM1WBrM+rAEMigJ8c3Kb3OSII6kGABhp1JnaK1VGwjwKwtvHqNzzd263M3H4n2OH1QBwGw6
588nQkAOw==
589}
590
591
592if { $tcl_platform(platform) == "windows" } {
593    if { $tk_version >= 8.3 } {
594	set cursor "@[file join $blt_library treeview.cur]"
595    } else {
596	set cursor "size_we"
597    }
598    option add *Hiertable.ResizeCursor [list $cursor]
599} else {
600    option add *Hiertable.ResizeCursor \
601	"@$blt_library/treeview.xbm $blt_library/treeview_m.xbm black white"
602}
603
604# Standard Motif bindings:
605
606bind HiertableEditor <ButtonPress-1> {
607    %W text icursor @%x,%y
608}
609
610bind HiertableEditor <Left> {
611    %W text icursor last
612}
613bind HiertableEditor <Right> {
614    %W text icursor next
615}
616bind HiertableEditor <Shift-Left> {
617    set new [expr {[%W text index insert] - 1}]
618    if {![%W text selection present]} {
619	%W text selection from insert
620	%W text selection to $new
621    } else {
622	%W text selection adjust $new
623    }
624    %W text icursor $new
625}
626bind HiertableEditor <Shift-Right> {
627    set new [expr {[%W text index insert] + 1}]
628    if {![%W text selection present]} {
629	%W text selection from insert
630	%W text selection to $new
631    } else {
632	%W text selection adjust $new
633    }
634    %W text icursor $new
635}
636
637bind HiertableEditor <Home> {
638    %W text icursor 0
639}
640bind HiertableEditor <Shift-Home> {
641    set new 0
642    if {![%W text selection present]} {
643	%W text selection from insert
644	%W text selection to $new
645    } else {
646	%W text selection adjust $new
647    }
648    %W text icursor $new
649}
650bind HiertableEditor <End> {
651    %W text icursor end
652}
653bind HiertableEditor <Shift-End> {
654    set new end
655    if {![%W text selection present]} {
656	%W text selection from insert
657	%W text selection to $new
658    } else {
659	%W text selection adjust $new
660    }
661    %W text icursor $new
662}
663
664bind HiertableEditor <Delete> {
665    if { [%W text selection present]} {
666	%W text delete sel.first sel.last
667    } else {
668	%W text delete insert
669    }
670}
671
672bind HiertableEditor <BackSpace> {
673    if { [%W text selection present] } {
674	%W text delete sel.first sel.last
675    } else {
676	set index [expr [%W text index insert] - 1]
677	if { $index >= 0 } {
678	    %W text delete $index $index
679	}
680    }
681}
682
683bind HiertableEditor <Control-space> {
684    %W text selection from insert
685}
686
687bind HiertableEditor <Select> {
688    %W text selection from insert
689}
690
691bind HiertableEditor <Control-Shift-space> {
692    %W text selection adjust insert
693}
694
695bind HiertableEditor <Shift-Select> {
696    %W text selection adjust insert
697}
698
699bind HiertableEditor <Control-slash> {
700    %W text selection range 0 end
701}
702
703bind HiertableEditor <Control-backslash> {
704    %W text selection clear
705}
706
707bind HiertableEditor <KeyPress> {
708    blt::Hiertable::Insert %W %A
709}
710
711# Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
712# Otherwise, if a widget binding for one of these is defined, the
713# <KeyPress> class binding will also fire and insert the character,
714# which is wrong.  Ditto for Escape, Return, and Tab.
715
716bind HiertableEditor <Alt-KeyPress> {
717    # nothing
718}
719
720bind HiertableEditor <Meta-KeyPress> {
721    # nothing
722}
723
724bind HiertableEditor <Control-KeyPress> {
725    # nothing
726}
727
728bind HiertableEditor <Escape> {
729    %W text cancel
730    grab release %W
731}
732
733bind HiertableEditor <Return> {
734    %W text apply
735    grab release %W
736}
737
738bind HiertableEditor <Shift-Return> {
739    blt::Hiertable::Insert %W "\n"
740}
741
742bind HiertableEditor <KP_Enter> {
743    # nothing
744}
745
746bind HiertableEditor <Tab> {
747    # nothing
748}
749
750if {![string compare $tcl_platform(platform) "macintosh"]} {
751    bind HiertableEditor <Command-KeyPress> {
752	# nothing
753    }
754}
755
756# On Windows, paste is done using Shift-Insert.  Shift-Insert already
757# generates the <<Paste>> event, so we don't need to do anything here.
758if { [string compare $tcl_platform(platform) "windows"] != 0 } {
759    bind HiertableEditor <Insert> {
760	catch {blt::Hiertable::Insert %W [selection get -displayof %W]}
761    }
762}
763
764# Additional emacs-like bindings:
765bind HiertableEditor <ButtonPress-3> {
766    if { [winfo viewable %W] } {
767	grab release %W
768	%W text cancel
769    }
770}
771
772bind HiertableEditor <Control-a> {
773    %W text icursor 0
774    %W text selection clear
775}
776
777bind HiertableEditor <Control-b> {
778    %W text icursor [expr {[%W index insert] - 1}]
779    %W text selection clear
780}
781
782bind HiertableEditor <Control-d> {
783    %W text delete insert
784}
785
786bind HiertableEditor <Control-e> {
787    %W text icursor end
788    %W text selection clear
789}
790
791bind HiertableEditor <Control-f> {
792    %W text icursor [expr {[%W index insert] + 1}]
793    %W text selection clear
794}
795
796bind HiertableEditor <Control-h> {
797    if {[%W text selection present]} {
798	%W text delete sel.first sel.last
799    } else {
800	set index [expr [%W text index insert] - 1]
801	if { $index >= 0 } {
802	    %W text delete $index $index
803	}
804    }
805}
806
807bind HiertableEditor <Control-k> {
808    %W text delete insert end
809}
810
811
812
813# blt::Hiertable::Insert --
814# Insert a string into an entry at the point of the insertion cursor.
815# If there is a selection in the entry, and it covers the point of the
816# insertion cursor, then delete the selection before inserting.
817#
818# Arguments:
819# w -		The entry window in which to insert the string
820# s -		The string to insert (usually just a single character)
821
822proc blt::Hiertable::Insert {w s} {
823    if {![string compare $s ""]} {
824	return
825    }
826    catch {
827	set insert [$w text index insert]
828	if {([$w text index sel.first] <= $insert)
829		&& ([$w text index sel.last] >= $insert)} {
830	    $w delete sel.first sel.last
831	}
832    }
833    $w text insert insert $s
834}
835
836# tkEntryTranspose -
837# This procedure implements the "transpose" function for entry widgets.
838# It tranposes the characters on either side of the insertion cursor,
839# unless the cursor is at the end of the line.  In this case it
840# transposes the two characters to the left of the cursor.  In either
841# case, the cursor ends up to the right of the transposed characters.
842#
843# Arguments:
844# w -		The entry window.
845
846proc HiertableTranspose w {
847    set i [$w text index insert]
848    if {$i < [$w text index end]} {
849	incr i
850    }
851    set first [expr {$i-2}]
852    if {$first < 0} {
853	return
854    }
855    set new [string index [$w get] [expr {$i-1}]][string index [$w get] $first]
856    $w delete $first $i
857    $w insert insert $new
858}
859
860# Hiertable::GetSelection --
861#
862# Returns the selected text of the entry with respect to the -show option.
863#
864# Arguments:
865# w -         The entry window from which the text to get
866
867proc blt::Hiertable::GetSelection {w} {
868    set entryString [string range [$w get] [$w index sel.first] \
869                       [expr [$w index sel.last] - 1]]
870    if {[$w cget -show] != ""} {
871      regsub -all . $entryString [string index [$w cget -show] 0] entryString
872    }
873    return $entryString
874}
875
876if 0 {
877    bind HiertableEditor <Control-t> {
878	tkEntryTranspose %W
879    }
880    bind HiertableEditor <Meta-b> {
881	%W text icursor [blt::Hiertable::PreviousWord %W insert]
882	%W text selection clear
883    }
884    bind HiertableEditor <Meta-d> {
885	%W delete insert [blt::Hiertable::NextWord %W insert]
886    }
887    bind HiertableEditor <Meta-f> {
888	%W text icursor [blt::Hiertable::NextWord %W insert]
889	%W text selection clear
890    }
891    bind HiertableEditor <Meta-BackSpace> {
892	%W delete [blt::Hiertable::PreviousWord %W insert] insert
893    }
894    bind HiertableEditor <Meta-Delete> {
895	%W delete [blt::Hiertable::PreviousWord %W insert] insert
896    }
897    # tkEntryNextWord -- Returns the index of the next word position
898    # after a given position in the entry.  The next word is platform
899    # dependent and may be either the next end-of-word position or the
900    # next start-of-word position after the next end-of-word position.
901    #
902    # Arguments:
903    # w -		The entry window in which the cursor is to move.
904    # start -	Position at which to start search.
905
906    if {![string compare $tcl_platform(platform) "windows"]}  {
907	proc blt::Hiertable::NextWord {w start} {
908	    set pos [tcl_endOfWord [$w get] [$w index $start]]
909	    if {$pos >= 0} {
910		set pos [tcl_startOfNextWord [$w get] $pos]
911	    }
912	    if {$pos < 0} {
913		return end
914	    }
915	    return $pos
916	}
917    } else {
918	proc blt::Hiertable::NextWord {w start} {
919	    set pos [tcl_endOfWord [$w get] [$w index $start]]
920	    if {$pos < 0} {
921		return end
922	    }
923	    return $pos
924	}
925    }
926
927    # blt::Hiertable::PreviousWord --
928    #
929    # Returns the index of the previous word position before a given
930    # position in the entry.
931    #
932    # Arguments:
933    # w -		The entry window in which the cursor is to move.
934    # start -	Position at which to start search.
935
936    proc blt::Hiertable::PreviousWord {w start} {
937	set pos [tcl_startOfPreviousWord [$w get] [$w index $start]]
938	if {$pos < 0} {
939	    return 0
940	}
941	return $pos
942    }
943}
944