aboutsummaryrefslogtreecommitdiff
path: root/library/zincText.tcl
blob: 2141a2a433b15899176049e0387feb9a476d856a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#
# ZincText - Zinc extension for text input on text items and fields
#
# $Id: zincText.tcl 1642 2005-04-27 08:03:05Z lecoanet $
#
# AUTHOR
#
# Patrick Lecoanet <lecoanet@cena.fr>
# (and documentation by Christophe Mertz <mertz@cena.fr>)
#
# Copyright (c) 2002 - 2003 CENA, Patrick Lecoanet
#
# See the file "Copyright" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
#
# SYNOPSIS
#
#  package require zincText;
#
#  zn_TextBindings $zinc
#
#  $zinc addtag text withtag $a_text
#  $zinc addtag text withtag $a_track
#  $zinc addtag text withtag $a_waypoint
#  $zinc addtag text withtag $a_tabular
#
#
# DESCRIPTION
#
# This module implements text input with the mouse and keyboard 'a la emacs'.
# Text items must have the 'text' tag and must of course be sensitive.
# Track, waypoint and tabular items have fields and these fields can
# be edited the same way. Only sensitive fields can be edited. the following
# interactions are supported:
#
#   <click 1>      To set the cursor position
#   <click 2>      To paste the current selection
#   <drag 1>       To make a selection
#   <shift drag 1> To extend the current selection
#   <shift 1>      To extend the current selection
#   <left arrow>,
#   <right arrow>  To move the cursor to the left or to the right
#   <up arrow>,
#   <down arrow>   To move the cursor up or down a line
#   <ctrl+a>,
#   <home>         To move the cursor at the begining of the line
#   <ctrl+e>
#   <end>          To move the cursor at the end of the line
#   <meta+<>,
#   <meta+>>       To move the cursor at the beginning / end of the text
#   <BackSpace>
#   <ctrl+h>       To delete the char just before the cursor
#   <Delete>       To delete the char just after the cursor
#   <Return>       To insert a return char. This does not validate the input!
#
#

proc zn_TextBindings {zinc} {
    $zinc bind text <1>              "startSel $zinc %x %y"
    $zinc bind text <2>              "pasteSel $zinc %x %y"
    $zinc bind text <B1-Motion>      "extendSel $zinc %x %y"
    $zinc bind text <Shift-B1-Motion> "extendSel $zinc %x %y"
    $zinc bind text <Shift-1>        "$zinc select adjust current @%x,%y"
    $zinc bind text <Left>           "moveCur $zinc -1"
    $zinc bind text <Right>          "moveCur $zinc 1"
    $zinc bind text <Up>             "setCur $zinc up"
    $zinc bind text <Down>           "setCur $zinc down"
    $zinc bind text <Control-a>      "setCur $zinc bol"
    $zinc bind text <Home>           "setCur $zinc bol"
    $zinc bind text <Control-e>      "setCur $zinc eol"
    $zinc bind text <End>            "setCur $zinc eol"
    $zinc bind text <Meta-less>      "setCur $zinc 0"
    $zinc bind text <Meta-greater>   "setCur $zinc end"
    $zinc bind text <KeyPress>       "insertKey $zinc %A"
    $zinc bind text <Shift-KeyPress> "insertKey $zinc %A"
    $zinc bind text <Return>         "insertChar $zinc \\n"
    $zinc bind text <BackSpace>      "textDel $zinc -1"
    $zinc bind text <Control-h>      "textDel $zinc -1"
    $zinc bind text <Delete>         "textDel $zinc 0"
}


proc pasteSel {w x y} {
    set item [$w focus]

    if {[llength $item] != 0} {
	catch {$w insert [lindex $item 0] [lindex $item 1] @$x,$y [selection get]}
    }
}


proc insertChar {w c} {
    set item [$w focus]
    set selItem [$w select item]

    if {[llength $item] == 0} {
	return;
    }
    
    if {([llength $selItem]!= 0) &&
	([lindex $selItem 0] == [lindex $item 0]) &&
	([lindex $selItem 1] == [lindex $item 1])} {
	$w dchars [lindex $item 0] [lindex $item 1] sel.first sel.last
    }
    $w insert [lindex $item 0] [lindex $item 1] insert $c
}


proc insertKey {w c} {
    if {! [binary scan $c {c} code]} {
	return
    }
    set code [expr $code & 0xFF]
    if {($code < 32) || ($code == 128)} {
	puts "rejet $code"
	return
    }
    
    insertChar $w $c
}


proc setCur {w where} {
    set item [$w focus]

    if {[llength $item] != 0} {
	$w cursor [lindex $item 0] [lindex $item 1] $where
    }
}


proc moveCur {w dir} {
    set item [$w focus]

    if {[llength $item] != 0} {
	set index [$w index [lindex $item 0] [lindex $item 1] insert]
	$w cursor [lindex $item 0] [lindex $item 1]  [expr $index + $dir]
    }
}


proc startSel {w x y} {
    set part [$w currentpart t]

    $w cursor current $part @$x,$y
    $w focus current $part
    focus $w
    $w select from current $part @$x,$y
}


proc extendSel {w x y} {
    set part [$w currentpart t]

    $w select to current $part @$x,$y
}


proc textDel {w dir} {
    set item [$w focus]
    set selItem [$w select item]

    if {[llength $item] == 0} {
	return;
    }

    if {([llength $selItem] != 0) &&
	([lindex $selItem 0] == [lindex $item 0]) &&
	([lindex $selItem 1] == [lindex $item 1])} {
	$w dchars [lindex $item 0] [lindex $item 1] sel.first sel.last
    } else {
	set ind [expr [$w index [lindex $item 0] [lindex $item 1] insert] + $dir]
	if { $ind >= 0 } {
	    $w dchars [lindex $item 0] [lindex $item 1] $ind $ind
	}
    }
}

package provide zincText 1.0