3 # Some functions needed for the common dialog boxes. Probably need to go
6 # RCS: @(#) $Id: comdlg.tcl,v 1.9 2003/02/21 13:32:14 dkf Exp $
8 # Copyright (c) 1996 Sun Microsystems, Inc.
10 # See the file "license.terms" for information on usage and redistribution
11 # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 # tclParseConfigSpec --
16 # Parses a list of "-option value" pairs. If all options and
17 # values are legal, the values are stored in
18 # $data($option). Otherwise an error message is returned. When
19 # an error happens, the data() array may have been partially
20 # modified, but all the modified members of the data(0 array are
21 # guaranteed to have valid values. This is different than
22 # Tk_ConfigureWidget() which does not modify the value of a
23 # widget record if any error occurs.
27 # w = widget record to modify. Must be the pathname of a widget.
30 # {-commandlineswitch resourceName ResourceClass defaultValue verifier}
34 # flags = currently unused.
36 # argList = The list of "-option value" pairs.
38 proc tclParseConfigSpec {w specs flags argList} {
41 # 1: Put the specs in associative arrays for faster access
44 if {[llength $spec] < 4} {
45 error "\"spec\" should contain 5 or 4 elements"
47 set cmdsw [lindex $spec 0]
49 set rname($cmdsw) [lindex $spec 1]
50 set rclass($cmdsw) [lindex $spec 2]
51 set def($cmdsw) [lindex $spec 3]
52 set verproc($cmdsw) [lindex $spec 4]
55 if {[llength $argList] & 1} {
56 set cmdsw [lindex $argList end]
57 if {![info exists cmd($cmdsw)]} {
58 error "bad option \"$cmdsw\": must be [tclListValidFlags cmd]"
60 error "value for \"$cmdsw\" missing"
63 # 2: set the default values
65 foreach cmdsw [array names cmd] {
66 set data($cmdsw) $def($cmdsw)
69 # 3: parse the argument list
71 foreach {cmdsw value} $argList {
72 if {![info exists cmd($cmdsw)]} {
73 error "bad option \"$cmdsw\": must be [tclListValidFlags cmd]"
75 set data($cmdsw) $value
81 proc tclListValidFlags {v} {
84 set len [llength [array names cmd]]
88 foreach cmdsw [lsort [array names cmd]] {
89 append errormsg "$separator$cmdsw"
100 #----------------------------------------------------------------------
104 # Focus groups are used to handle the user's focusing actions inside a
107 # One example of using focus groups is: when the user focuses on an
108 # entry, the text in the entry is highlighted and the cursor is put to
109 # the end of the text. When the user changes focus to another widget,
110 # the text in the previously focused entry is validated.
112 #----------------------------------------------------------------------
115 # ::tk::FocusGroup_Create --
117 # Create a focus group. All the widgets in a focus group must be
118 # within the same focus toplevel. Each toplevel can have only
119 # one focus group, which is identified by the name of the
122 proc ::tk::FocusGroup_Create {t} {
124 if {[string compare [winfo toplevel $t] $t]} {
125 error "$t is not a toplevel window"
127 if {![info exists Priv(fg,$t)]} {
129 set Priv(focus,$t) ""
130 bind $t <FocusIn> [list tk::FocusGroup_In $t %W %d]
131 bind $t <FocusOut> [list tk::FocusGroup_Out $t %W %d]
132 bind $t <Destroy> [list tk::FocusGroup_Destroy $t %W]
136 # ::tk::FocusGroup_BindIn --
138 # Add a widget into the "FocusIn" list of the focus group. The $cmd will be
139 # called when the widget is focused on by the user.
141 proc ::tk::FocusGroup_BindIn {t w cmd} {
144 if {![info exists Priv(fg,$t)]} {
145 error "focus group \"$t\" doesn't exist"
147 set FocusIn($t,$w) $cmd
151 # ::tk::FocusGroup_BindOut --
153 # Add a widget into the "FocusOut" list of the focus group. The
154 # $cmd will be called when the widget loses the focus (User
155 # types Tab or click on another widget).
157 proc ::tk::FocusGroup_BindOut {t w cmd} {
160 if {![info exists Priv(fg,$t)]} {
161 error "focus group \"$t\" doesn't exist"
163 set FocusOut($t,$w) $cmd
166 # ::tk::FocusGroup_Destroy --
168 # Cleans up when members of the focus group is deleted, or when the
169 # toplevel itself gets deleted.
171 proc ::tk::FocusGroup_Destroy {t w} {
176 if {[string equal $t $w]} {
180 foreach name [array names FocusIn $t,*] {
183 foreach name [array names FocusOut $t,*] {
184 unset FocusOut($name)
187 if {[info exists Priv(focus,$t)] && \
188 [string equal $Priv(focus,$t) $w]} {
189 set Priv(focus,$t) ""
195 unset FocusOut($t,$w)
200 # ::tk::FocusGroup_In --
202 # Handles the <FocusIn> event. Calls the FocusIn command for the newly
203 # focused widget in the focus group.
205 proc ::tk::FocusGroup_In {t w detail} {
209 if {[string compare $detail NotifyNonlinear] && \
210 [string compare $detail NotifyNonlinearVirtual]} {
211 # This is caused by mouse moving out&in of the window *or*
212 # ordinary keypresses some window managers (ie: CDE [Bug: 2960]).
215 if {![info exists FocusIn($t,$w)]} {
216 set FocusIn($t,$w) ""
219 if {![info exists Priv(focus,$t)]} {
222 if {[string equal $Priv(focus,$t) $w]} {
223 # This is already in focus
227 set Priv(focus,$t) $w
232 # ::tk::FocusGroup_Out --
234 # Handles the <FocusOut> event. Checks if this is really a lose
235 # focus event, not one generated by the mouse moving out of the
236 # toplevel window. Calls the FocusOut command for the widget
237 # who loses its focus.
239 proc ::tk::FocusGroup_Out {t w detail} {
243 if {[string compare $detail NotifyNonlinear] && \
244 [string compare $detail NotifyNonlinearVirtual]} {
245 # This is caused by mouse moving out of the window
248 if {![info exists Priv(focus,$t)]} {
251 if {![info exists FocusOut($t,$w)]} {
254 eval $FocusOut($t,$w)
255 set Priv(focus,$t) ""
259 # ::tk::FDGetFileTypes --
261 # Process the string given by the -filetypes option of the file
262 # dialogs. Similar to the C function TkGetFileFilters() on the Mac
263 # and Windows platform.
265 proc ::tk::FDGetFileTypes {string} {
267 if {[llength $t] < 2 || [llength $t] > 3} {
268 error "bad file type \"$t\", should be \"typeName {extension ?extensions ...?} ?{macType ?macTypes ...?}?\""
270 eval lappend [list fileTypes([lindex $t 0])] [lindex $t 1]
275 set label [lindex $t 0]
278 if {[info exists hasDoneType($label)]} {
285 foreach ext $fileTypes($label) {
286 if {[string equal $ext ""]} {
289 regsub {^[.]} $ext "*." ext
290 if {![info exists hasGotExt($label,$ext)]} {
292 if {[string length $sep] && [string length $name]>40} {
300 set hasGotExt($label,$ext) 1
305 lappend types [list $name $exts]
307 set hasDoneType($label) 1