/share/tcltk: add private .gitignore
[msysgit.git] / mingw / lib / tk8.4 / entry.tcl
blob3fb4e673f0fa76b23f48e8f00859581deb0f5d38
1 # entry.tcl --
3 # This file defines the default bindings for Tk entry widgets and provides
4 # procedures that help in implementing those bindings.
6 # RCS: @(#) $Id: entry.tcl,v 1.21.2.1 2006/01/25 18:21:41 dgp Exp $
8 # Copyright (c) 1992-1994 The Regents of the University of California.
9 # Copyright (c) 1994-1997 Sun Microsystems, Inc.
11 # See the file "license.terms" for information on usage and redistribution
12 # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15 #-------------------------------------------------------------------------
16 # Elements of tk::Priv that are used in this file:
18 # afterId - If non-null, it means that auto-scanning is underway
19 # and it gives the "after" id for the next auto-scan
20 # command to be executed.
21 # mouseMoved - Non-zero means the mouse has moved a significant
22 # amount since the button went down (so, for example,
23 # start dragging out a selection).
24 # pressX - X-coordinate at which the mouse button was pressed.
25 # selectMode - The style of selection currently underway:
26 # char, word, or line.
27 # x, y - Last known mouse coordinates for scanning
28 # and auto-scanning.
29 # data - Used for Cut and Copy
30 #-------------------------------------------------------------------------
32 #-------------------------------------------------------------------------
33 # The code below creates the default class bindings for entries.
34 #-------------------------------------------------------------------------
35 bind Entry <<Cut>> {
36 if {![catch {tk::EntryGetSelection %W} tk::Priv(data)]} {
37 clipboard clear -displayof %W
38 clipboard append -displayof %W $tk::Priv(data)
39 %W delete sel.first sel.last
40 unset tk::Priv(data)
43 bind Entry <<Copy>> {
44 if {![catch {tk::EntryGetSelection %W} tk::Priv(data)]} {
45 clipboard clear -displayof %W
46 clipboard append -displayof %W $tk::Priv(data)
47 unset tk::Priv(data)
50 bind Entry <<Paste>> {
51 global tcl_platform
52 catch {
53 if {[tk windowingsystem] ne "x11"} {
54 catch {
55 %W delete sel.first sel.last
58 %W insert insert [::tk::GetSelection %W CLIPBOARD]
59 tk::EntrySeeInsert %W
62 bind Entry <<Clear>> {
63 %W delete sel.first sel.last
65 bind Entry <<PasteSelection>> {
66 if {$tk_strictMotif || ![info exists tk::Priv(mouseMoved)]
67 || !$tk::Priv(mouseMoved)} {
68 tk::EntryPaste %W %x
72 # Standard Motif bindings:
74 bind Entry <1> {
75 tk::EntryButton1 %W %x
76 %W selection clear
78 bind Entry <B1-Motion> {
79 set tk::Priv(x) %x
80 tk::EntryMouseSelect %W %x
82 bind Entry <Double-1> {
83 set tk::Priv(selectMode) word
84 tk::EntryMouseSelect %W %x
85 catch {%W icursor sel.last}
87 bind Entry <Triple-1> {
88 set tk::Priv(selectMode) line
89 tk::EntryMouseSelect %W %x
90 catch {%W icursor sel.last}
92 bind Entry <Shift-1> {
93 set tk::Priv(selectMode) char
94 %W selection adjust @%x
96 bind Entry <Double-Shift-1> {
97 set tk::Priv(selectMode) word
98 tk::EntryMouseSelect %W %x
100 bind Entry <Triple-Shift-1> {
101 set tk::Priv(selectMode) line
102 tk::EntryMouseSelect %W %x
104 bind Entry <B1-Leave> {
105 set tk::Priv(x) %x
106 tk::EntryAutoScan %W
108 bind Entry <B1-Enter> {
109 tk::CancelRepeat
111 bind Entry <ButtonRelease-1> {
112 tk::CancelRepeat
114 bind Entry <Control-1> {
115 %W icursor @%x
118 bind Entry <Left> {
119 tk::EntrySetCursor %W [expr {[%W index insert] - 1}]
121 bind Entry <Right> {
122 tk::EntrySetCursor %W [expr {[%W index insert] + 1}]
124 bind Entry <Shift-Left> {
125 tk::EntryKeySelect %W [expr {[%W index insert] - 1}]
126 tk::EntrySeeInsert %W
128 bind Entry <Shift-Right> {
129 tk::EntryKeySelect %W [expr {[%W index insert] + 1}]
130 tk::EntrySeeInsert %W
132 bind Entry <Control-Left> {
133 tk::EntrySetCursor %W [tk::EntryPreviousWord %W insert]
135 bind Entry <Control-Right> {
136 tk::EntrySetCursor %W [tk::EntryNextWord %W insert]
138 bind Entry <Shift-Control-Left> {
139 tk::EntryKeySelect %W [tk::EntryPreviousWord %W insert]
140 tk::EntrySeeInsert %W
142 bind Entry <Shift-Control-Right> {
143 tk::EntryKeySelect %W [tk::EntryNextWord %W insert]
144 tk::EntrySeeInsert %W
146 bind Entry <Home> {
147 tk::EntrySetCursor %W 0
149 bind Entry <Shift-Home> {
150 tk::EntryKeySelect %W 0
151 tk::EntrySeeInsert %W
153 bind Entry <End> {
154 tk::EntrySetCursor %W end
156 bind Entry <Shift-End> {
157 tk::EntryKeySelect %W end
158 tk::EntrySeeInsert %W
161 bind Entry <Delete> {
162 if {[%W selection present]} {
163 %W delete sel.first sel.last
164 } else {
165 %W delete insert
168 bind Entry <BackSpace> {
169 tk::EntryBackspace %W
172 bind Entry <Control-space> {
173 %W selection from insert
175 bind Entry <Select> {
176 %W selection from insert
178 bind Entry <Control-Shift-space> {
179 %W selection adjust insert
181 bind Entry <Shift-Select> {
182 %W selection adjust insert
184 bind Entry <Control-slash> {
185 %W selection range 0 end
187 bind Entry <Control-backslash> {
188 %W selection clear
190 bind Entry <KeyPress> {
191 tk::CancelRepeat
192 tk::EntryInsert %W %A
195 # Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
196 # Otherwise, if a widget binding for one of these is defined, the
197 # <KeyPress> class binding will also fire and insert the character,
198 # which is wrong. Ditto for Escape, Return, and Tab.
200 bind Entry <Alt-KeyPress> {# nothing}
201 bind Entry <Meta-KeyPress> {# nothing}
202 bind Entry <Control-KeyPress> {# nothing}
203 bind Entry <Escape> {# nothing}
204 bind Entry <Return> {# nothing}
205 bind Entry <KP_Enter> {# nothing}
206 bind Entry <Tab> {# nothing}
207 if {[tk windowingsystem] eq "classic" || [tk windowingsystem] eq "aqua"} {
208 bind Entry <Command-KeyPress> {# nothing}
211 # On Windows, paste is done using Shift-Insert. Shift-Insert already
212 # generates the <<Paste>> event, so we don't need to do anything here.
213 if {$tcl_platform(platform) ne "windows"} {
214 bind Entry <Insert> {
215 catch {tk::EntryInsert %W [::tk::GetSelection %W PRIMARY]}
219 # Additional emacs-like bindings:
221 bind Entry <Control-a> {
222 if {!$tk_strictMotif} {
223 tk::EntrySetCursor %W 0
226 bind Entry <Control-b> {
227 if {!$tk_strictMotif} {
228 tk::EntrySetCursor %W [expr {[%W index insert] - 1}]
231 bind Entry <Control-d> {
232 if {!$tk_strictMotif} {
233 %W delete insert
236 bind Entry <Control-e> {
237 if {!$tk_strictMotif} {
238 tk::EntrySetCursor %W end
241 bind Entry <Control-f> {
242 if {!$tk_strictMotif} {
243 tk::EntrySetCursor %W [expr {[%W index insert] + 1}]
246 bind Entry <Control-h> {
247 if {!$tk_strictMotif} {
248 tk::EntryBackspace %W
251 bind Entry <Control-k> {
252 if {!$tk_strictMotif} {
253 %W delete insert end
256 bind Entry <Control-t> {
257 if {!$tk_strictMotif} {
258 tk::EntryTranspose %W
261 bind Entry <Meta-b> {
262 if {!$tk_strictMotif} {
263 tk::EntrySetCursor %W [tk::EntryPreviousWord %W insert]
266 bind Entry <Meta-d> {
267 if {!$tk_strictMotif} {
268 %W delete insert [tk::EntryNextWord %W insert]
271 bind Entry <Meta-f> {
272 if {!$tk_strictMotif} {
273 tk::EntrySetCursor %W [tk::EntryNextWord %W insert]
276 bind Entry <Meta-BackSpace> {
277 if {!$tk_strictMotif} {
278 %W delete [tk::EntryPreviousWord %W insert] insert
281 bind Entry <Meta-Delete> {
282 if {!$tk_strictMotif} {
283 %W delete [tk::EntryPreviousWord %W insert] insert
287 # A few additional bindings of my own.
289 bind Entry <2> {
290 if {!$tk_strictMotif} {
291 ::tk::EntryScanMark %W %x
294 bind Entry <B2-Motion> {
295 if {!$tk_strictMotif} {
296 ::tk::EntryScanDrag %W %x
300 # ::tk::EntryClosestGap --
301 # Given x and y coordinates, this procedure finds the closest boundary
302 # between characters to the given coordinates and returns the index
303 # of the character just after the boundary.
305 # Arguments:
306 # w - The entry window.
307 # x - X-coordinate within the window.
309 proc ::tk::EntryClosestGap {w x} {
310 set pos [$w index @$x]
311 set bbox [$w bbox $pos]
312 if {($x - [lindex $bbox 0]) < ([lindex $bbox 2]/2)} {
313 return $pos
315 incr pos
318 # ::tk::EntryButton1 --
319 # This procedure is invoked to handle button-1 presses in entry
320 # widgets. It moves the insertion cursor, sets the selection anchor,
321 # and claims the input focus.
323 # Arguments:
324 # w - The entry window in which the button was pressed.
325 # x - The x-coordinate of the button press.
327 proc ::tk::EntryButton1 {w x} {
328 variable ::tk::Priv
330 set Priv(selectMode) char
331 set Priv(mouseMoved) 0
332 set Priv(pressX) $x
333 $w icursor [EntryClosestGap $w $x]
334 $w selection from insert
335 if {"disabled" ne [$w cget -state]} {focus $w}
338 # ::tk::EntryMouseSelect --
339 # This procedure is invoked when dragging out a selection with
340 # the mouse. Depending on the selection mode (character, word,
341 # line) it selects in different-sized units. This procedure
342 # ignores mouse motions initially until the mouse has moved from
343 # one character to another or until there have been multiple clicks.
345 # Arguments:
346 # w - The entry window in which the button was pressed.
347 # x - The x-coordinate of the mouse.
349 proc ::tk::EntryMouseSelect {w x} {
350 variable ::tk::Priv
352 set cur [EntryClosestGap $w $x]
353 set anchor [$w index anchor]
354 if {($cur != $anchor) || (abs($Priv(pressX) - $x) >= 3)} {
355 set Priv(mouseMoved) 1
357 switch $Priv(selectMode) {
358 char {
359 if {$Priv(mouseMoved)} {
360 if {$cur < $anchor} {
361 $w selection range $cur $anchor
362 } elseif {$cur > $anchor} {
363 $w selection range $anchor $cur
364 } else {
365 $w selection clear
369 word {
370 if {$cur < [$w index anchor]} {
371 set before [tcl_wordBreakBefore [$w get] $cur]
372 set after [tcl_wordBreakAfter [$w get] [expr {$anchor-1}]]
373 } else {
374 set before [tcl_wordBreakBefore [$w get] $anchor]
375 set after [tcl_wordBreakAfter [$w get] [expr {$cur - 1}]]
377 if {$before < 0} {
378 set before 0
380 if {$after < 0} {
381 set after end
383 $w selection range $before $after
385 line {
386 $w selection range 0 end
389 if {$Priv(mouseMoved)} {
390 $w icursor $cur
392 update idletasks
395 # ::tk::EntryPaste --
396 # This procedure sets the insertion cursor to the current mouse position,
397 # pastes the selection there, and sets the focus to the window.
399 # Arguments:
400 # w - The entry window.
401 # x - X position of the mouse.
403 proc ::tk::EntryPaste {w x} {
404 $w icursor [EntryClosestGap $w $x]
405 catch {$w insert insert [::tk::GetSelection $w PRIMARY]}
406 if {"disabled" ne [$w cget -state]} {focus $w}
409 # ::tk::EntryAutoScan --
410 # This procedure is invoked when the mouse leaves an entry window
411 # with button 1 down. It scrolls the window left or right,
412 # depending on where the mouse is, and reschedules itself as an
413 # "after" command so that the window continues to scroll until the
414 # mouse moves back into the window or the mouse button is released.
416 # Arguments:
417 # w - The entry window.
419 proc ::tk::EntryAutoScan {w} {
420 variable ::tk::Priv
421 set x $Priv(x)
422 if {![winfo exists $w]} return
423 if {$x >= [winfo width $w]} {
424 $w xview scroll 2 units
425 EntryMouseSelect $w $x
426 } elseif {$x < 0} {
427 $w xview scroll -2 units
428 EntryMouseSelect $w $x
430 set Priv(afterId) [after 50 [list tk::EntryAutoScan $w]]
433 # ::tk::EntryKeySelect --
434 # This procedure is invoked when stroking out selections using the
435 # keyboard. It moves the cursor to a new position, then extends
436 # the selection to that position.
438 # Arguments:
439 # w - The entry window.
440 # new - A new position for the insertion cursor (the cursor hasn't
441 # actually been moved to this position yet).
443 proc ::tk::EntryKeySelect {w new} {
444 if {![$w selection present]} {
445 $w selection from insert
446 $w selection to $new
447 } else {
448 $w selection adjust $new
450 $w icursor $new
453 # ::tk::EntryInsert --
454 # Insert a string into an entry at the point of the insertion cursor.
455 # If there is a selection in the entry, and it covers the point of the
456 # insertion cursor, then delete the selection before inserting.
458 # Arguments:
459 # w - The entry window in which to insert the string
460 # s - The string to insert (usually just a single character)
462 proc ::tk::EntryInsert {w s} {
463 if {$s eq ""} {
464 return
466 catch {
467 set insert [$w index insert]
468 if {([$w index sel.first] <= $insert)
469 && ([$w index sel.last] >= $insert)} {
470 $w delete sel.first sel.last
473 $w insert insert $s
474 EntrySeeInsert $w
477 # ::tk::EntryBackspace --
478 # Backspace over the character just before the insertion cursor.
479 # If backspacing would move the cursor off the left edge of the
480 # window, reposition the cursor at about the middle of the window.
482 # Arguments:
483 # w - The entry window in which to backspace.
485 proc ::tk::EntryBackspace w {
486 if {[$w selection present]} {
487 $w delete sel.first sel.last
488 } else {
489 set x [expr {[$w index insert] - 1}]
490 if {$x >= 0} {$w delete $x}
491 if {[$w index @0] >= [$w index insert]} {
492 set range [$w xview]
493 set left [lindex $range 0]
494 set right [lindex $range 1]
495 $w xview moveto [expr {$left - ($right - $left)/2.0}]
500 # ::tk::EntrySeeInsert --
501 # Make sure that the insertion cursor is visible in the entry window.
502 # If not, adjust the view so that it is.
504 # Arguments:
505 # w - The entry window.
507 proc ::tk::EntrySeeInsert w {
508 set c [$w index insert]
509 if {($c < [$w index @0]) || ($c > [$w index @[winfo width $w]])} {
510 $w xview $c
514 # ::tk::EntrySetCursor -
515 # Move the insertion cursor to a given position in an entry. Also
516 # clears the selection, if there is one in the entry, and makes sure
517 # that the insertion cursor is visible.
519 # Arguments:
520 # w - The entry window.
521 # pos - The desired new position for the cursor in the window.
523 proc ::tk::EntrySetCursor {w pos} {
524 $w icursor $pos
525 $w selection clear
526 EntrySeeInsert $w
529 # ::tk::EntryTranspose -
530 # This procedure implements the "transpose" function for entry widgets.
531 # It tranposes the characters on either side of the insertion cursor,
532 # unless the cursor is at the end of the line. In this case it
533 # transposes the two characters to the left of the cursor. In either
534 # case, the cursor ends up to the right of the transposed characters.
536 # Arguments:
537 # w - The entry window.
539 proc ::tk::EntryTranspose w {
540 set i [$w index insert]
541 if {$i < [$w index end]} {
542 incr i
544 set first [expr {$i-2}]
545 if {$first < 0} {
546 return
548 set data [$w get]
549 set new [string index $data [expr {$i-1}]][string index $data $first]
550 $w delete $first $i
551 $w insert insert $new
552 EntrySeeInsert $w
555 # ::tk::EntryNextWord --
556 # Returns the index of the next word position after a given position in the
557 # entry. The next word is platform dependent and may be either the next
558 # end-of-word position or the next start-of-word position after the next
559 # end-of-word position.
561 # Arguments:
562 # w - The entry window in which the cursor is to move.
563 # start - Position at which to start search.
565 if {$tcl_platform(platform) eq "windows"} {
566 proc ::tk::EntryNextWord {w start} {
567 set pos [tcl_endOfWord [$w get] [$w index $start]]
568 if {$pos >= 0} {
569 set pos [tcl_startOfNextWord [$w get] $pos]
571 if {$pos < 0} {
572 return end
574 return $pos
576 } else {
577 proc ::tk::EntryNextWord {w start} {
578 set pos [tcl_endOfWord [$w get] [$w index $start]]
579 if {$pos < 0} {
580 return end
582 return $pos
586 # ::tk::EntryPreviousWord --
588 # Returns the index of the previous word position before a given
589 # position in the entry.
591 # Arguments:
592 # w - The entry window in which the cursor is to move.
593 # start - Position at which to start search.
595 proc ::tk::EntryPreviousWord {w start} {
596 set pos [tcl_startOfPreviousWord [$w get] [$w index $start]]
597 if {$pos < 0} {
598 return 0
600 return $pos
603 # ::tk::EntryScanMark --
605 # Marks the start of a possible scan drag operation
607 # Arguments:
608 # w - The entry window from which the text to get
609 # x - x location on screen
611 proc ::tk::EntryScanMark {w x} {
612 $w scan mark $x
613 set ::tk::Priv(x) $x
614 set ::tk::Priv(y) 0 ; # not used
615 set ::tk::Priv(mouseMoved) 0
618 # ::tk::EntryScanDrag --
620 # Marks the start of a possible scan drag operation
622 # Arguments:
623 # w - The entry window from which the text to get
624 # x - x location on screen
626 proc ::tk::EntryScanDrag {w x} {
627 # Make sure these exist, as some weird situations can trigger the
628 # motion binding without the initial press. [Bug #220269]
629 if {![info exists ::tk::Priv(x)]} { set ::tk::Priv(x) $x }
630 # allow for a delta
631 if {abs($x-$::tk::Priv(x)) > 2} {
632 set ::tk::Priv(mouseMoved) 1
634 $w scan dragto $x
637 # ::tk::EntryGetSelection --
639 # Returns the selected text of the entry with respect to the -show option.
641 # Arguments:
642 # w - The entry window from which the text to get
644 proc ::tk::EntryGetSelection {w} {
645 set entryString [string range [$w get] [$w index sel.first] \
646 [expr {[$w index sel.last] - 1}]]
647 if {[$w cget -show] ne ""} {
648 return [string repeat [string index [$w cget -show] 0] \
649 [string length $entryString]]
651 return $entryString