source: proiecte/pmake3d/make3d_original/Make3dSingleImageStanford_version0.1/third_party/vrippack-0.31/src/vrip/lib/tk/text.tcl @ 37

Last change on this file since 37 was 37, checked in by (none), 14 years ago

Added original make3d

File size: 27.6 KB
Line 
1# text.tcl --
2#
3# This file defines the default bindings for Tk text widgets and provides
4# procedures that help in implementing the bindings.
5#
6# RCS: @(#) $Id: text.tcl,v 1.12 2000/04/17 23:24:29 ericm Exp $
7#
8# Copyright (c) 1992-1994 The Regents of the University of California.
9# Copyright (c) 1994-1997 Sun Microsystems, Inc.
10# Copyright (c) 1998 by Scriptics Corporation.
11#
12# See the file "license.terms" for information on usage and redistribution
13# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14#
15
16#-------------------------------------------------------------------------
17# Elements of tkPriv that are used in this file:
18#
19# afterId -             If non-null, it means that auto-scanning is underway
20#                       and it gives the "after" id for the next auto-scan
21#                       command to be executed.
22# char -                Character position on the line;  kept in order
23#                       to allow moving up or down past short lines while
24#                       still remembering the desired position.
25# mouseMoved -          Non-zero means the mouse has moved a significant
26#                       amount since the button went down (so, for example,
27#                       start dragging out a selection).
28# prevPos -             Used when moving up or down lines via the keyboard.
29#                       Keeps track of the previous insert position, so
30#                       we can distinguish a series of ups and downs, all
31#                       in a row, from a new up or down.
32# selectMode -          The style of selection currently underway:
33#                       char, word, or line.
34# x, y -                Last known mouse coordinates for scanning
35#                       and auto-scanning.
36#-------------------------------------------------------------------------
37
38#-------------------------------------------------------------------------
39# The code below creates the default class bindings for entries.
40#-------------------------------------------------------------------------
41
42# Standard Motif bindings:
43
44bind Text <1> {
45    tkTextButton1 %W %x %y
46    %W tag remove sel 0.0 end
47}
48bind Text <B1-Motion> {
49    set tkPriv(x) %x
50    set tkPriv(y) %y
51    tkTextSelectTo %W %x %y
52}
53bind Text <Double-1> {
54    set tkPriv(selectMode) word
55    tkTextSelectTo %W %x %y
56    catch {%W mark set insert sel.last}
57    catch {%W mark set anchor sel.first}
58}
59bind Text <Triple-1> {
60    set tkPriv(selectMode) line
61    tkTextSelectTo %W %x %y
62    catch {%W mark set insert sel.last}
63    catch {%W mark set anchor sel.first}
64}
65bind Text <Shift-1> {
66    tkTextResetAnchor %W @%x,%y
67    set tkPriv(selectMode) char
68    tkTextSelectTo %W %x %y
69}
70bind Text <Double-Shift-1>      {
71    set tkPriv(selectMode) word
72    tkTextSelectTo %W %x %y 1
73}
74bind Text <Triple-Shift-1>      {
75    set tkPriv(selectMode) line
76    tkTextSelectTo %W %x %y
77}
78bind Text <B1-Leave> {
79    set tkPriv(x) %x
80    set tkPriv(y) %y
81    tkTextAutoScan %W
82}
83bind Text <B1-Enter> {
84    tkCancelRepeat
85}
86bind Text <ButtonRelease-1> {
87    tkCancelRepeat
88}
89bind Text <Control-1> {
90    %W mark set insert @%x,%y
91}
92bind Text <Left> {
93    tkTextSetCursor %W insert-1c
94}
95bind Text <Right> {
96    tkTextSetCursor %W insert+1c
97}
98bind Text <Up> {
99    tkTextSetCursor %W [tkTextUpDownLine %W -1]
100}
101bind Text <Down> {
102    tkTextSetCursor %W [tkTextUpDownLine %W 1]
103}
104bind Text <Shift-Left> {
105    tkTextKeySelect %W [%W index {insert - 1c}]
106}
107bind Text <Shift-Right> {
108    tkTextKeySelect %W [%W index {insert + 1c}]
109}
110bind Text <Shift-Up> {
111    tkTextKeySelect %W [tkTextUpDownLine %W -1]
112}
113bind Text <Shift-Down> {
114    tkTextKeySelect %W [tkTextUpDownLine %W 1]
115}
116bind Text <Control-Left> {
117    tkTextSetCursor %W [tkTextPrevPos %W insert tcl_startOfPreviousWord]
118}
119bind Text <Control-Right> {
120    tkTextSetCursor %W [tkTextNextWord %W insert]
121}
122bind Text <Control-Up> {
123    tkTextSetCursor %W [tkTextPrevPara %W insert]
124}
125bind Text <Control-Down> {
126    tkTextSetCursor %W [tkTextNextPara %W insert]
127}
128bind Text <Shift-Control-Left> {
129    tkTextKeySelect %W [tkTextPrevPos %W insert tcl_startOfPreviousWord]
130}
131bind Text <Shift-Control-Right> {
132    tkTextKeySelect %W [tkTextNextWord %W insert]
133}
134bind Text <Shift-Control-Up> {
135    tkTextKeySelect %W [tkTextPrevPara %W insert]
136}
137bind Text <Shift-Control-Down> {
138    tkTextKeySelect %W [tkTextNextPara %W insert]
139}
140bind Text <Prior> {
141    tkTextSetCursor %W [tkTextScrollPages %W -1]
142}
143bind Text <Shift-Prior> {
144    tkTextKeySelect %W [tkTextScrollPages %W -1]
145}
146bind Text <Next> {
147    tkTextSetCursor %W [tkTextScrollPages %W 1]
148}
149bind Text <Shift-Next> {
150    tkTextKeySelect %W [tkTextScrollPages %W 1]
151}
152bind Text <Control-Prior> {
153    %W xview scroll -1 page
154}
155bind Text <Control-Next> {
156    %W xview scroll 1 page
157}
158
159bind Text <Home> {
160    tkTextSetCursor %W {insert linestart}
161}
162bind Text <Shift-Home> {
163    tkTextKeySelect %W {insert linestart}
164}
165bind Text <End> {
166    tkTextSetCursor %W {insert lineend}
167}
168bind Text <Shift-End> {
169    tkTextKeySelect %W {insert lineend}
170}
171bind Text <Control-Home> {
172    tkTextSetCursor %W 1.0
173}
174bind Text <Control-Shift-Home> {
175    tkTextKeySelect %W 1.0
176}
177bind Text <Control-End> {
178    tkTextSetCursor %W {end - 1 char}
179}
180bind Text <Control-Shift-End> {
181    tkTextKeySelect %W {end - 1 char}
182}
183
184bind Text <Tab> {
185    tkTextInsert %W \t
186    focus %W
187    break
188}
189bind Text <Shift-Tab> {
190    # Needed only to keep <Tab> binding from triggering;  doesn't
191    # have to actually do anything.
192    break
193}
194bind Text <Control-Tab> {
195    focus [tk_focusNext %W]
196}
197bind Text <Control-Shift-Tab> {
198    focus [tk_focusPrev %W]
199}
200bind Text <Control-i> {
201    tkTextInsert %W \t
202}
203bind Text <Return> {
204    tkTextInsert %W \n
205}
206bind Text <Delete> {
207    if {[string compare [%W tag nextrange sel 1.0 end] ""]} {
208        %W delete sel.first sel.last
209    } else {
210        %W delete insert
211        %W see insert
212    }
213}
214bind Text <BackSpace> {
215    if {[string compare [%W tag nextrange sel 1.0 end] ""]} {
216        %W delete sel.first sel.last
217    } elseif {[%W compare insert != 1.0]} {
218        %W delete insert-1c
219        %W see insert
220    }
221}
222
223bind Text <Control-space> {
224    %W mark set anchor insert
225}
226bind Text <Select> {
227    %W mark set anchor insert
228}
229bind Text <Control-Shift-space> {
230    set tkPriv(selectMode) char
231    tkTextKeyExtend %W insert
232}
233bind Text <Shift-Select> {
234    set tkPriv(selectMode) char
235    tkTextKeyExtend %W insert
236}
237bind Text <Control-slash> {
238    %W tag add sel 1.0 end
239}
240bind Text <Control-backslash> {
241    %W tag remove sel 1.0 end
242}
243bind Text <<Cut>> {
244    tk_textCut %W
245}
246bind Text <<Copy>> {
247    tk_textCopy %W
248}
249bind Text <<Paste>> {
250    tk_textPaste %W
251}
252bind Text <<Clear>> {
253    catch {%W delete sel.first sel.last}
254}
255bind Text <<PasteSelection>> {
256    if {!$tkPriv(mouseMoved) || $tk_strictMotif} {
257        tkTextPaste %W %x %y
258    }
259}
260bind Text <Insert> {
261    catch {tkTextInsert %W [selection get -displayof %W]}
262}
263bind Text <KeyPress> {
264    tkTextInsert %W %A
265}
266
267# Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
268# Otherwise, if a widget binding for one of these is defined, the
269# <KeyPress> class binding will also fire and insert the character,
270# which is wrong.  Ditto for <Escape>.
271
272bind Text <Alt-KeyPress> {# nothing }
273bind Text <Meta-KeyPress> {# nothing}
274bind Text <Control-KeyPress> {# nothing}
275bind Text <Escape> {# nothing}
276bind Text <KP_Enter> {# nothing}
277if {[string equal $tcl_platform(platform) "macintosh"]} {
278    bind Text <Command-KeyPress> {# nothing}
279}
280
281# Additional emacs-like bindings:
282
283bind Text <Control-a> {
284    if {!$tk_strictMotif} {
285        tkTextSetCursor %W {insert linestart}
286    }
287}
288bind Text <Control-b> {
289    if {!$tk_strictMotif} {
290        tkTextSetCursor %W insert-1c
291    }
292}
293bind Text <Control-d> {
294    if {!$tk_strictMotif} {
295        %W delete insert
296    }
297}
298bind Text <Control-e> {
299    if {!$tk_strictMotif} {
300        tkTextSetCursor %W {insert lineend}
301    }
302}
303bind Text <Control-f> {
304    if {!$tk_strictMotif} {
305        tkTextSetCursor %W insert+1c
306    }
307}
308bind Text <Control-k> {
309    if {!$tk_strictMotif} {
310        if {[%W compare insert == {insert lineend}]} {
311            %W delete insert
312        } else {
313            %W delete insert {insert lineend}
314        }
315    }
316}
317bind Text <Control-n> {
318    if {!$tk_strictMotif} {
319        tkTextSetCursor %W [tkTextUpDownLine %W 1]
320    }
321}
322bind Text <Control-o> {
323    if {!$tk_strictMotif} {
324        %W insert insert \n
325        %W mark set insert insert-1c
326    }
327}
328bind Text <Control-p> {
329    if {!$tk_strictMotif} {
330        tkTextSetCursor %W [tkTextUpDownLine %W -1]
331    }
332}
333bind Text <Control-t> {
334    if {!$tk_strictMotif} {
335        tkTextTranspose %W
336    }
337}
338
339if {[string compare $tcl_platform(platform) "windows"]} {
340bind Text <Control-v> {
341    if {!$tk_strictMotif} {
342        tkTextScrollPages %W 1
343    }
344}
345}
346
347bind Text <Meta-b> {
348    if {!$tk_strictMotif} {
349        tkTextSetCursor %W [tkTextPrevPos %W insert tcl_startOfPreviousWord]
350    }
351}
352bind Text <Meta-d> {
353    if {!$tk_strictMotif} {
354        %W delete insert [tkTextNextWord %W insert]
355    }
356}
357bind Text <Meta-f> {
358    if {!$tk_strictMotif} {
359        tkTextSetCursor %W [tkTextNextWord %W insert]
360    }
361}
362bind Text <Meta-less> {
363    if {!$tk_strictMotif} {
364        tkTextSetCursor %W 1.0
365    }
366}
367bind Text <Meta-greater> {
368    if {!$tk_strictMotif} {
369        tkTextSetCursor %W end-1c
370    }
371}
372bind Text <Meta-BackSpace> {
373    if {!$tk_strictMotif} {
374        %W delete [tkTextPrevPos %W insert tcl_startOfPreviousWord] insert
375    }
376}
377bind Text <Meta-Delete> {
378    if {!$tk_strictMotif} {
379        %W delete [tkTextPrevPos %W insert tcl_startOfPreviousWord] insert
380    }
381}
382
383# Macintosh only bindings:
384
385# if text black & highlight black -> text white, other text the same
386if {[string equal $tcl_platform(platform) "macintosh"]} {
387bind Text <FocusIn> {
388    %W tag configure sel -borderwidth 0
389    %W configure -selectbackground systemHighlight -selectforeground systemHighlightText
390}
391bind Text <FocusOut> {
392    %W tag configure sel -borderwidth 1
393    %W configure -selectbackground white -selectforeground black
394}
395bind Text <Option-Left> {
396    tkTextSetCursor %W [tkTextPrevPos %W insert tcl_startOfPreviousWord]
397}
398bind Text <Option-Right> {
399    tkTextSetCursor %W [tkTextNextWord %W insert]
400}
401bind Text <Option-Up> {
402    tkTextSetCursor %W [tkTextPrevPara %W insert]
403}
404bind Text <Option-Down> {
405    tkTextSetCursor %W [tkTextNextPara %W insert]
406}
407bind Text <Shift-Option-Left> {
408    tkTextKeySelect %W [tkTextPrevPos %W insert tcl_startOfPreviousWord]
409}
410bind Text <Shift-Option-Right> {
411    tkTextKeySelect %W [tkTextNextWord %W insert]
412}
413bind Text <Shift-Option-Up> {
414    tkTextKeySelect %W [tkTextPrevPara %W insert]
415}
416bind Text <Shift-Option-Down> {
417    tkTextKeySelect %W [tkTextNextPara %W insert]
418}
419
420# End of Mac only bindings
421}
422
423# A few additional bindings of my own.
424
425bind Text <Control-h> {
426    if {!$tk_strictMotif} {
427        if {[%W compare insert != 1.0]} {
428            %W delete insert-1c
429            %W see insert
430        }
431    }
432}
433bind Text <2> {
434    if {!$tk_strictMotif} {
435        %W scan mark %x %y
436        set tkPriv(x) %x
437        set tkPriv(y) %y
438        set tkPriv(mouseMoved) 0
439    }
440}
441bind Text <B2-Motion> {
442    if {!$tk_strictMotif} {
443        if {(%x != $tkPriv(x)) || (%y != $tkPriv(y))} {
444            set tkPriv(mouseMoved) 1
445        }
446        if {$tkPriv(mouseMoved)} {
447            %W scan dragto %x %y
448        }
449    }
450}
451set tkPriv(prevPos) {}
452
453# The MouseWheel will typically only fire on Windows.  However,
454# someone could use the "event generate" command to produce one
455# on other platforms.
456
457bind Text <MouseWheel> {
458    %W yview scroll [expr {- (%D / 120) * 4}] units
459}
460
461if {[string equal "unix" $tcl_platform(platform)]} {
462    # Support for mousewheels on Linux/Unix commonly comes through mapping
463    # the wheel to the extended buttons.  If you have a mousewheel, find
464    # Linux configuration info at:
465    #   http://www.inria.fr/koala/colas/mouse-wheel-scroll/
466    bind Text <4> {
467        if {!$tk_strictMotif} {
468            %W yview scroll -5 units
469        }
470    }
471    bind Text <5> {
472        if {!$tk_strictMotif} {
473            %W yview scroll 5 units
474        }
475    }
476}
477
478# tkTextClosestGap --
479# Given x and y coordinates, this procedure finds the closest boundary
480# between characters to the given coordinates and returns the index
481# of the character just after the boundary.
482#
483# Arguments:
484# w -           The text window.
485# x -           X-coordinate within the window.
486# y -           Y-coordinate within the window.
487
488proc tkTextClosestGap {w x y} {
489    set pos [$w index @$x,$y]
490    set bbox [$w bbox $pos]
491    if {[string equal $bbox ""]} {
492        return $pos
493    }
494    if {($x - [lindex $bbox 0]) < ([lindex $bbox 2]/2)} {
495        return $pos
496    }
497    $w index "$pos + 1 char"
498}
499
500# tkTextButton1 --
501# This procedure is invoked to handle button-1 presses in text
502# widgets.  It moves the insertion cursor, sets the selection anchor,
503# and claims the input focus.
504#
505# Arguments:
506# w -           The text window in which the button was pressed.
507# x -           The x-coordinate of the button press.
508# y -           The x-coordinate of the button press.
509
510proc tkTextButton1 {w x y} {
511    global tkPriv
512
513    set tkPriv(selectMode) char
514    set tkPriv(mouseMoved) 0
515    set tkPriv(pressX) $x
516    $w mark set insert [tkTextClosestGap $w $x $y]
517    $w mark set anchor insert
518    if {[string equal [$w cget -state] "normal"]} {focus $w}
519}
520
521# tkTextSelectTo --
522# This procedure is invoked to extend the selection, typically when
523# dragging it with the mouse.  Depending on the selection mode (character,
524# word, line) it selects in different-sized units.  This procedure
525# ignores mouse motions initially until the mouse has moved from
526# one character to another or until there have been multiple clicks.
527#
528# Arguments:
529# w -           The text window in which the button was pressed.
530# x -           Mouse x position.
531# y -           Mouse y position.
532
533proc tkTextSelectTo {w x y {extend 0}} {
534    global tkPriv tcl_platform
535
536    set cur [tkTextClosestGap $w $x $y]
537    if {[catch {$w index anchor}]} {
538        $w mark set anchor $cur
539    }
540    set anchor [$w index anchor]
541    if {[$w compare $cur != $anchor] || (abs($tkPriv(pressX) - $x) >= 3)} {
542        set tkPriv(mouseMoved) 1
543    }
544    switch $tkPriv(selectMode) {
545        char {
546            if {[$w compare $cur < anchor]} {
547                set first $cur
548                set last anchor
549            } else {
550                set first anchor
551                set last $cur
552            }
553        }
554        word {
555            if {[$w compare $cur < anchor]} {
556                set first [tkTextPrevPos $w "$cur + 1c" tcl_wordBreakBefore]
557                if { !$extend } {
558                    set last [tkTextNextPos $w "anchor" tcl_wordBreakAfter]
559                } else {
560                    set last anchor
561                }
562            } else {
563                set last [tkTextNextPos $w "$cur - 1c" tcl_wordBreakAfter]
564                if { !$extend } {
565                    set first [tkTextPrevPos $w anchor tcl_wordBreakBefore]
566                } else {
567                    set first anchor
568                }
569            }
570        }
571        line {
572            if {[$w compare $cur < anchor]} {
573                set first [$w index "$cur linestart"]
574                set last [$w index "anchor - 1c lineend + 1c"]
575            } else {
576                set first [$w index "anchor linestart"]
577                set last [$w index "$cur lineend + 1c"]
578            }
579        }
580    }
581    if {$tkPriv(mouseMoved) || [string compare $tkPriv(selectMode) "char"]} {
582        if {[string compare $tcl_platform(platform) "unix"] \
583                && [$w compare $cur < anchor]} {
584            $w mark set insert $first
585        } else {
586            $w mark set insert $last
587        }
588        $w tag remove sel 0.0 $first
589        $w tag add sel $first $last
590        $w tag remove sel $last end
591        update idletasks
592    }
593}
594
595# tkTextKeyExtend --
596# This procedure handles extending the selection from the keyboard,
597# where the point to extend to is really the boundary between two
598# characters rather than a particular character.
599#
600# Arguments:
601# w -           The text window.
602# index -       The point to which the selection is to be extended.
603
604proc tkTextKeyExtend {w index} {
605    global tkPriv
606
607    set cur [$w index $index]
608    if {[catch {$w index anchor}]} {
609        $w mark set anchor $cur
610    }
611    set anchor [$w index anchor]
612    if {[$w compare $cur < anchor]} {
613        set first $cur
614        set last anchor
615    } else {
616        set first anchor
617        set last $cur
618    }
619    $w tag remove sel 0.0 $first
620    $w tag add sel $first $last
621    $w tag remove sel $last end
622}
623
624# tkTextPaste --
625# This procedure sets the insertion cursor to the mouse position,
626# inserts the selection, and sets the focus to the window.
627#
628# Arguments:
629# w -           The text window.
630# x, y -        Position of the mouse.
631
632proc tkTextPaste {w x y} {
633    $w mark set insert [tkTextClosestGap $w $x $y]
634    catch {$w insert insert [selection get -displayof $w]}
635    if {[string equal [$w cget -state] "normal"]} {focus $w}
636}
637
638# tkTextAutoScan --
639# This procedure is invoked when the mouse leaves a text window
640# with button 1 down.  It scrolls the window up, down, left, or right,
641# depending on where the mouse is (this information was saved in
642# tkPriv(x) and tkPriv(y)), and reschedules itself as an "after"
643# command so that the window continues to scroll until the mouse
644# moves back into the window or the mouse button is released.
645#
646# Arguments:
647# w -           The text window.
648
649proc tkTextAutoScan {w} {
650    global tkPriv
651    if {![winfo exists $w]} return
652    if {$tkPriv(y) >= [winfo height $w]} {
653        $w yview scroll 2 units
654    } elseif {$tkPriv(y) < 0} {
655        $w yview scroll -2 units
656    } elseif {$tkPriv(x) >= [winfo width $w]} {
657        $w xview scroll 2 units
658    } elseif {$tkPriv(x) < 0} {
659        $w xview scroll -2 units
660    } else {
661        return
662    }
663    tkTextSelectTo $w $tkPriv(x) $tkPriv(y)
664    set tkPriv(afterId) [after 50 [list tkTextAutoScan $w]]
665}
666
667# tkTextSetCursor
668# Move the insertion cursor to a given position in a text.  Also
669# clears the selection, if there is one in the text, and makes sure
670# that the insertion cursor is visible.  Also, don't let the insertion
671# cursor appear on the dummy last line of the text.
672#
673# Arguments:
674# w -           The text window.
675# pos -         The desired new position for the cursor in the window.
676
677proc tkTextSetCursor {w pos} {
678    global tkPriv
679
680    if {[$w compare $pos == end]} {
681        set pos {end - 1 chars}
682    }
683    $w mark set insert $pos
684    $w tag remove sel 1.0 end
685    $w see insert
686}
687
688# tkTextKeySelect
689# This procedure is invoked when stroking out selections using the
690# keyboard.  It moves the cursor to a new position, then extends
691# the selection to that position.
692#
693# Arguments:
694# w -           The text window.
695# new -         A new position for the insertion cursor (the cursor hasn't
696#               actually been moved to this position yet).
697
698proc tkTextKeySelect {w new} {
699    global tkPriv
700
701    if {[string equal [$w tag nextrange sel 1.0 end] ""]} {
702        if {[$w compare $new < insert]} {
703            $w tag add sel $new insert
704        } else {
705            $w tag add sel insert $new
706        }
707        $w mark set anchor insert
708    } else {
709        if {[$w compare $new < anchor]} {
710            set first $new
711            set last anchor
712        } else {
713            set first anchor
714            set last $new
715        }
716        $w tag remove sel 1.0 $first
717        $w tag add sel $first $last
718        $w tag remove sel $last end
719    }
720    $w mark set insert $new
721    $w see insert
722    update idletasks
723}
724
725# tkTextResetAnchor --
726# Set the selection anchor to whichever end is farthest from the
727# index argument.  One special trick: if the selection has two or
728# fewer characters, just leave the anchor where it is.  In this
729# case it doesn't matter which point gets chosen for the anchor,
730# and for the things like Shift-Left and Shift-Right this produces
731# better behavior when the cursor moves back and forth across the
732# anchor.
733#
734# Arguments:
735# w -           The text widget.
736# index -       Position at which mouse button was pressed, which determines
737#               which end of selection should be used as anchor point.
738
739proc tkTextResetAnchor {w index} {
740    global tkPriv
741
742    if {[string equal [$w tag ranges sel] ""]} {
743        $w mark set anchor $index
744        return
745    }
746    set a [$w index $index]
747    set b [$w index sel.first]
748    set c [$w index sel.last]
749    if {[$w compare $a < $b]} {
750        $w mark set anchor sel.last
751        return
752    }
753    if {[$w compare $a > $c]} {
754        $w mark set anchor sel.first
755        return
756    }
757    scan $a "%d.%d" lineA chA
758    scan $b "%d.%d" lineB chB
759    scan $c "%d.%d" lineC chC
760    if {$lineB < $lineC+2} {
761        set total [string length [$w get $b $c]]
762        if {$total <= 2} {
763            return
764        }
765        if {[string length [$w get $b $a]] < ($total/2)} {
766            $w mark set anchor sel.last
767        } else {
768            $w mark set anchor sel.first
769        }
770        return
771    }
772    if {($lineA-$lineB) < ($lineC-$lineA)} {
773        $w mark set anchor sel.last
774    } else {
775        $w mark set anchor sel.first
776    }
777}
778
779# tkTextInsert --
780# Insert a string into a text at the point of the insertion cursor.
781# If there is a selection in the text, and it covers the point of the
782# insertion cursor, then delete the selection before inserting.
783#
784# Arguments:
785# w -           The text window in which to insert the string
786# s -           The string to insert (usually just a single character)
787
788proc tkTextInsert {w s} {
789    if {[string equal $s ""] || [string equal [$w cget -state] "disabled"]} {
790        return
791    }
792    catch {
793        if {[$w compare sel.first <= insert] \
794                && [$w compare sel.last >= insert]} {
795            $w delete sel.first sel.last
796        }
797    }
798    $w insert insert $s
799    $w see insert
800}
801
802# tkTextUpDownLine --
803# Returns the index of the character one line above or below the
804# insertion cursor.  There are two tricky things here.  First,
805# we want to maintain the original column across repeated operations,
806# even though some lines that will get passed through don't have
807# enough characters to cover the original column.  Second, don't
808# try to scroll past the beginning or end of the text.
809#
810# Arguments:
811# w -           The text window in which the cursor is to move.
812# n -           The number of lines to move: -1 for up one line,
813#               +1 for down one line.
814
815proc tkTextUpDownLine {w n} {
816    global tkPriv
817
818    set i [$w index insert]
819    scan $i "%d.%d" line char
820    if {[string compare $tkPriv(prevPos) $i]} {
821        set tkPriv(char) $char
822    }
823    set new [$w index [expr {$line + $n}].$tkPriv(char)]
824    if {[$w compare $new == end] || [$w compare $new == "insert linestart"]} {
825        set new $i
826    }
827    set tkPriv(prevPos) $new
828    return $new
829}
830
831# tkTextPrevPara --
832# Returns the index of the beginning of the paragraph just before a given
833# position in the text (the beginning of a paragraph is the first non-blank
834# character after a blank line).
835#
836# Arguments:
837# w -           The text window in which the cursor is to move.
838# pos -         Position at which to start search.
839
840proc tkTextPrevPara {w pos} {
841    set pos [$w index "$pos linestart"]
842    while {1} {
843        if {([string equal [$w get "$pos - 1 line"] "\n"] \
844                && [string compare [$w get $pos] "\n"]) \
845                || [string equal $pos "1.0"]} {
846            if {[regexp -indices {^[    ]+(.)} [$w get $pos "$pos lineend"] \
847                    dummy index]} {
848                set pos [$w index "$pos + [lindex $index 0] chars"]
849            }
850            if {[$w compare $pos != insert] || [string equal $pos 1.0]} {
851                return $pos
852            }
853        }
854        set pos [$w index "$pos - 1 line"]
855    }
856}
857
858# tkTextNextPara --
859# Returns the index of the beginning of the paragraph just after a given
860# position in the text (the beginning of a paragraph is the first non-blank
861# character after a blank line).
862#
863# Arguments:
864# w -           The text window in which the cursor is to move.
865# start -       Position at which to start search.
866
867proc tkTextNextPara {w start} {
868    set pos [$w index "$start linestart + 1 line"]
869    while {[string compare [$w get $pos] "\n"]} {
870        if {[$w compare $pos == end]} {
871            return [$w index "end - 1c"]
872        }
873        set pos [$w index "$pos + 1 line"]
874    }
875    while {[string equal [$w get $pos] "\n"]} {
876        set pos [$w index "$pos + 1 line"]
877        if {[$w compare $pos == end]} {
878            return [$w index "end - 1c"]
879        }
880    }
881    if {[regexp -indices {^[    ]+(.)} [$w get $pos "$pos lineend"] \
882            dummy index]} {
883        return [$w index "$pos + [lindex $index 0] chars"]
884    }
885    return $pos
886}
887
888# tkTextScrollPages --
889# This is a utility procedure used in bindings for moving up and down
890# pages and possibly extending the selection along the way.  It scrolls
891# the view in the widget by the number of pages, and it returns the
892# index of the character that is at the same position in the new view
893# as the insertion cursor used to be in the old view.
894#
895# Arguments:
896# w -           The text window in which the cursor is to move.
897# count -       Number of pages forward to scroll;  may be negative
898#               to scroll backwards.
899
900proc tkTextScrollPages {w count} {
901    set bbox [$w bbox insert]
902    $w yview scroll $count pages
903    if {[string equal $bbox ""]} {
904        return [$w index @[expr {[winfo height $w]/2}],0]
905    }
906    return [$w index @[lindex $bbox 0],[lindex $bbox 1]]
907}
908
909# tkTextTranspose --
910# This procedure implements the "transpose" function for text widgets.
911# It tranposes the characters on either side of the insertion cursor,
912# unless the cursor is at the end of the line.  In this case it
913# transposes the two characters to the left of the cursor.  In either
914# case, the cursor ends up to the right of the transposed characters.
915#
916# Arguments:
917# w -           Text window in which to transpose.
918
919proc tkTextTranspose w {
920    set pos insert
921    if {[$w compare $pos != "$pos lineend"]} {
922        set pos [$w index "$pos + 1 char"]
923    }
924    set new [$w get "$pos - 1 char"][$w get  "$pos - 2 char"]
925    if {[$w compare "$pos - 1 char" == 1.0]} {
926        return
927    }
928    $w delete "$pos - 2 char" $pos
929    $w insert insert $new
930    $w see insert
931}
932
933# tk_textCopy --
934# This procedure copies the selection from a text widget into the
935# clipboard.
936#
937# Arguments:
938# w -           Name of a text widget.
939
940proc tk_textCopy w {
941    if {![catch {set data [$w get sel.first sel.last]}]} {
942        clipboard clear -displayof $w
943        clipboard append -displayof $w $data
944    }
945}
946
947# tk_textCut --
948# This procedure copies the selection from a text widget into the
949# clipboard, then deletes the selection (if it exists in the given
950# widget).
951#
952# Arguments:
953# w -           Name of a text widget.
954
955proc tk_textCut w {
956    if {![catch {set data [$w get sel.first sel.last]}]} {
957        clipboard clear -displayof $w
958        clipboard append -displayof $w $data
959        $w delete sel.first sel.last
960    }
961}
962
963# tk_textPaste --
964# This procedure pastes the contents of the clipboard to the insertion
965# point in a text widget.
966#
967# Arguments:
968# w -           Name of a text widget.
969
970proc tk_textPaste w {
971    global tcl_platform
972    catch {
973        if {[string compare $tcl_platform(platform) "unix"]} {
974            catch {
975                $w delete sel.first sel.last
976            }
977        }
978        $w insert insert [selection get -displayof $w -selection CLIPBOARD]
979    }
980}
981
982# tkTextNextWord --
983# Returns the index of the next word position after a given position in the
984# text.  The next word is platform dependent and may be either the next
985# end-of-word position or the next start-of-word position after the next
986# end-of-word position.
987#
988# Arguments:
989# w -           The text window in which the cursor is to move.
990# start -       Position at which to start search.
991
992if {[string equal $tcl_platform(platform) "windows"]}  {
993    proc tkTextNextWord {w start} {
994        tkTextNextPos $w [tkTextNextPos $w $start tcl_endOfWord] \
995            tcl_startOfNextWord
996    }
997} else {
998    proc tkTextNextWord {w start} {
999        tkTextNextPos $w $start tcl_endOfWord
1000    }
1001}
1002
1003# tkTextNextPos --
1004# Returns the index of the next position after the given starting
1005# position in the text as computed by a specified function.
1006#
1007# Arguments:
1008# w -           The text window in which the cursor is to move.
1009# start -       Position at which to start search.
1010# op -          Function to use to find next position.
1011
1012proc tkTextNextPos {w start op} {
1013    set text ""
1014    set cur $start
1015    while {[$w compare $cur < end]} {
1016        set text $text[$w get $cur "$cur lineend + 1c"]
1017        set pos [$op $text 0]
1018        if {$pos >= 0} {
1019            ## Adjust for embedded windows and images
1020            ## dump gives us 3 items per window/image
1021            set dump [$w dump -image -window $start "$start + $pos c"]
1022            if {[llength $dump]} {
1023                set pos [expr {$pos + ([llength $dump]/3)}]
1024            }
1025            return [$w index "$start + $pos c"]
1026        }
1027        set cur [$w index "$cur lineend +1c"]
1028    }
1029    return end
1030}
1031
1032# tkTextPrevPos --
1033# Returns the index of the previous position before the given starting
1034# position in the text as computed by a specified function.
1035#
1036# Arguments:
1037# w -           The text window in which the cursor is to move.
1038# start -       Position at which to start search.
1039# op -          Function to use to find next position.
1040
1041proc tkTextPrevPos {w start op} {
1042    set text ""
1043    set cur $start
1044    while {[$w compare $cur > 0.0]} {
1045        set text [$w get "$cur linestart - 1c" $cur]$text
1046        set pos [$op $text end]
1047        if {$pos >= 0} {
1048            ## Adjust for embedded windows and images
1049            ## dump gives us 3 items per window/image
1050            set dump [$w dump -image -window "$cur linestart" "$start - 1c"]
1051            if {[llength $dump]} {
1052                ## This is a hokey extra hack for control-arrow movement
1053                ## that should be in a while loop to be correct (hobbs)
1054                if {[$w compare [lindex $dump 2] > \
1055                        "$cur linestart - 1c + $pos c"]} {
1056                    incr pos -1
1057                }
1058                set pos [expr {$pos + ([llength $dump]/3)}]
1059            }
1060            return [$w index "$cur linestart - 1c + $pos c"]
1061        }
1062        set cur [$w index "$cur linestart - 1c"]
1063    }
1064    return 0.0
1065}
Note: See TracBrowser for help on using the repository browser.