Mark msysGit as obsolete
[msysgit.git] / mingw / lib / tk8.5 / xmfbox.tcl
blob0cbf2513f02e44eadcf4a292816e64e624f32bd8
1 # xmfbox.tcl --
3 # Implements the "Motif" style file selection dialog for the
4 # Unix platform. This implementation is used only if the
5 # "::tk_strictMotif" flag is set.
7 # Copyright (c) 1996 Sun Microsystems, Inc.
8 # Copyright (c) 1998-2000 Scriptics Corporation
10 # See the file "license.terms" for information on usage and redistribution
11 # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 namespace eval ::tk::dialog {}
14 namespace eval ::tk::dialog::file {}
17 # ::tk::MotifFDialog --
19 # Implements a file dialog similar to the standard Motif file
20 # selection box.
22 # Arguments:
23 # type "open" or "save"
24 # args Options parsed by the procedure.
26 # Results:
27 # When -multiple is set to 0, this returns the absolute pathname
28 # of the selected file. (NOTE: This is not the same as a single
29 # element list.)
31 # When -multiple is set to > 0, this returns a Tcl list of absolute
32 # pathnames. The argument for -multiple is ignored, but for consistency
33 # with Windows it defines the maximum amount of memory to allocate for
34 # the returned filenames.
36 proc ::tk::MotifFDialog {type args} {
37 variable ::tk::Priv
38 set dataName __tk_filedialog
39 upvar ::tk::dialog::file::$dataName data
41 set w [MotifFDialog_Create $dataName $type $args]
43 # Set a grab and claim the focus too.
45 ::tk::SetFocusGrab $w $data(sEnt)
46 $data(sEnt) selection range 0 end
48 # Wait for the user to respond, then restore the focus and
49 # return the index of the selected button. Restore the focus
50 # before deleting the window, since otherwise the window manager
51 # may take the focus away so we can't redirect it. Finally,
52 # restore any grab that was in effect.
54 vwait ::tk::Priv(selectFilePath)
55 set result $Priv(selectFilePath)
56 ::tk::RestoreFocusGrab $w $data(sEnt) withdraw
58 return $result
61 # ::tk::MotifFDialog_Create --
63 # Creates the Motif file dialog (if it doesn't exist yet) and
64 # initialize the internal data structure associated with the
65 # dialog.
67 # This procedure is used by ::tk::MotifFDialog to create the
68 # dialog. It's also used by the test suite to test the Motif
69 # file dialog implementation. User code shouldn't call this
70 # procedure directly.
72 # Arguments:
73 # dataName Name of the global "data" array for the file dialog.
74 # type "Save" or "Open"
75 # argList Options parsed by the procedure.
77 # Results:
78 # Pathname of the file dialog.
80 proc ::tk::MotifFDialog_Create {dataName type argList} {
81 upvar ::tk::dialog::file::$dataName data
83 MotifFDialog_Config $dataName $type $argList
85 if {$data(-parent) eq "."} {
86 set w .$dataName
87 } else {
88 set w $data(-parent).$dataName
91 # (re)create the dialog box if necessary
93 if {![winfo exists $w]} {
94 MotifFDialog_BuildUI $w
95 } elseif {[winfo class $w] ne "TkMotifFDialog"} {
96 destroy $w
97 MotifFDialog_BuildUI $w
98 } else {
99 set data(fEnt) $w.top.f1.ent
100 set data(dList) $w.top.f2.a.l
101 set data(fList) $w.top.f2.b.l
102 set data(sEnt) $w.top.f3.ent
103 set data(okBtn) $w.bot.ok
104 set data(filterBtn) $w.bot.filter
105 set data(cancelBtn) $w.bot.cancel
107 MotifFDialog_SetListMode $w
109 # Dialog boxes should be transient with respect to their parent,
110 # so that they will always stay on top of their parent window. However,
111 # some window managers will create the window as withdrawn if the parent
112 # window is withdrawn or iconified. Combined with the grab we put on the
113 # window, this can hang the entire application. Therefore we only make
114 # the dialog transient if the parent is viewable.
116 if {[winfo viewable [winfo toplevel $data(-parent)]] } {
117 wm transient $w $data(-parent)
120 MotifFDialog_FileTypes $w
121 MotifFDialog_Update $w
123 # Withdraw the window, then update all the geometry information
124 # so we know how big it wants to be, then center the window in the
125 # display (Motif style) and de-iconify it.
127 ::tk::PlaceWindow $w
128 wm title $w $data(-title)
130 return $w
133 # ::tk::MotifFDialog_FileTypes --
135 # Checks the -filetypes option. If present this adds a list of radio-
136 # buttons to pick the file types from.
138 # Arguments:
139 # w Pathname of the tk_get*File dialogue.
141 # Results:
142 # none
144 proc ::tk::MotifFDialog_FileTypes {w} {
145 upvar ::tk::dialog::file::[winfo name $w] data
147 set f $w.top.f3.types
148 destroy $f
150 # No file types: use "*" as the filter and display no radio-buttons
151 if {$data(-filetypes) eq ""} {
152 set data(filter) *
153 return
156 # The filetypes radiobuttons
157 # set data(fileType) $data(-defaulttype)
158 # Default type to first entry
159 set initialTypeName [lindex $data(-filetypes) 0 0]
160 if {$data(-typevariable) ne ""} {
161 upvar #0 $data(-typevariable) typeVariable
162 if {[info exist typeVariable]} {
163 set initialTypeName $typeVariable
166 set ix 0
167 set data(fileType) 0
168 foreach fltr $data(-filetypes) {
169 set fname [lindex $fltr 0]
170 if {[string first $initialTypeName $fname] == 0} {
171 set data(fileType) $ix
172 break
174 incr ix
177 MotifFDialog_SetFilter $w [lindex $data(-filetypes) $data(fileType)]
179 #don't produce radiobuttons for only one filetype
180 if {[llength $data(-filetypes)] == 1} {
181 return
184 frame $f
185 set cnt 0
186 if {$data(-filetypes) ne {}} {
187 foreach type $data(-filetypes) {
188 set title [lindex [lindex $type 0] 0]
189 set filter [lindex $type 1]
190 radiobutton $f.b$cnt \
191 -text $title \
192 -variable ::tk::dialog::file::[winfo name $w](fileType) \
193 -value $cnt \
194 -command [list tk::MotifFDialog_SetFilter $w $type]
195 pack $f.b$cnt -side left
196 incr cnt
199 $f.b$data(fileType) invoke
201 pack $f -side bottom -fill both
203 return
206 # This proc gets called whenever data(filter) is set
208 proc ::tk::MotifFDialog_SetFilter {w type} {
209 upvar ::tk::dialog::file::[winfo name $w] data
210 variable ::tk::Priv
212 set data(filter) [lindex $type 1]
213 set Priv(selectFileType) [lindex [lindex $type 0] 0]
215 MotifFDialog_Update $w
218 # ::tk::MotifFDialog_Config --
220 # Iterates over the optional arguments to determine the option
221 # values for the Motif file dialog; gives default values to
222 # unspecified options.
224 # Arguments:
225 # dataName The name of the global variable in which
226 # data for the file dialog is stored.
227 # type "Save" or "Open"
228 # argList Options parsed by the procedure.
230 proc ::tk::MotifFDialog_Config {dataName type argList} {
231 upvar ::tk::dialog::file::$dataName data
233 set data(type) $type
235 # 1: the configuration specs
237 set specs {
238 {-defaultextension "" "" ""}
239 {-filetypes "" "" ""}
240 {-initialdir "" "" ""}
241 {-initialfile "" "" ""}
242 {-parent "" "" "."}
243 {-title "" "" ""}
244 {-typevariable "" "" ""}
246 if {$type eq "open"} {
247 lappend specs {-multiple "" "" "0"}
249 if {$type eq "save"} {
250 lappend specs {-confirmoverwrite "" "" "1"}
253 set data(-multiple) 0
254 set data(-confirmoverwrite) 1
255 # 2: default values depending on the type of the dialog
257 if {![info exists data(selectPath)]} {
258 # first time the dialog has been popped up
259 set data(selectPath) [pwd]
260 set data(selectFile) ""
263 # 3: parse the arguments
265 tclParseConfigSpec ::tk::dialog::file::$dataName $specs "" $argList
267 if {$data(-title) eq ""} {
268 if {$type eq "open"} {
269 if {$data(-multiple) != 0} {
270 set data(-title) "[mc {Open Multiple Files}]"
271 } else {
272 set data(-title) [mc "Open"]
274 } else {
275 set data(-title) [mc "Save As"]
279 # 4: set the default directory and selection according to the -initial
280 # settings
282 if {$data(-initialdir) ne ""} {
283 if {[file isdirectory $data(-initialdir)]} {
284 set data(selectPath) [lindex [glob $data(-initialdir)] 0]
285 } else {
286 set data(selectPath) [pwd]
289 # Convert the initialdir to an absolute path name.
291 set old [pwd]
292 cd $data(selectPath)
293 set data(selectPath) [pwd]
294 cd $old
296 set data(selectFile) $data(-initialfile)
298 # 5. Parse the -filetypes option. It is not used by the motif
299 # file dialog, but we check for validity of the value to make sure
300 # the application code also runs fine with the TK file dialog.
302 set data(-filetypes) [::tk::FDGetFileTypes $data(-filetypes)]
304 if {![info exists data(filter)]} {
305 set data(filter) *
307 if {![winfo exists $data(-parent)]} {
308 error "bad window path name \"$data(-parent)\""
312 # ::tk::MotifFDialog_BuildUI --
314 # Builds the UI components of the Motif file dialog.
316 # Arguments:
317 # w Pathname of the dialog to build.
319 # Results:
320 # None.
322 proc ::tk::MotifFDialog_BuildUI {w} {
323 set dataName [lindex [split $w .] end]
324 upvar ::tk::dialog::file::$dataName data
326 # Create the dialog toplevel and internal frames.
328 toplevel $w -class TkMotifFDialog
329 set top [frame $w.top -relief raised -bd 1]
330 set bot [frame $w.bot -relief raised -bd 1]
332 pack $w.bot -side bottom -fill x
333 pack $w.top -side top -expand yes -fill both
335 set f1 [frame $top.f1]
336 set f2 [frame $top.f2]
337 set f3 [frame $top.f3]
339 pack $f1 -side top -fill x
340 pack $f3 -side bottom -fill x
341 pack $f2 -expand yes -fill both
343 set f2a [frame $f2.a]
344 set f2b [frame $f2.b]
346 grid $f2a -row 0 -column 0 -rowspan 1 -columnspan 1 -padx 4 -pady 4 \
347 -sticky news
348 grid $f2b -row 0 -column 1 -rowspan 1 -columnspan 1 -padx 4 -pady 4 \
349 -sticky news
350 grid rowconfigure $f2 0 -minsize 0 -weight 1
351 grid columnconfigure $f2 0 -minsize 0 -weight 1
352 grid columnconfigure $f2 1 -minsize 150 -weight 2
354 # The Filter box
356 bind [::tk::AmpWidget label $f1.lab -text [mc "Fil&ter:"] -anchor w] \
357 <<AltUnderlined>> [list focus $f1.ent]
358 entry $f1.ent
359 pack $f1.lab -side top -fill x -padx 6 -pady 4
360 pack $f1.ent -side top -fill x -padx 4 -pady 0
361 set data(fEnt) $f1.ent
363 # The file and directory lists
365 set data(dList) [MotifFDialog_MakeSList $w $f2a \
366 [mc "&Directory:"] DList]
367 set data(fList) [MotifFDialog_MakeSList $w $f2b \
368 [mc "Fi&les:"] FList]
370 # The Selection box
372 bind [::tk::AmpWidget label $f3.lab -text [mc "&Selection:"] -anchor w] \
373 <<AltUnderlined>> [list focus $f3.ent]
374 entry $f3.ent
375 pack $f3.lab -side top -fill x -padx 6 -pady 0
376 pack $f3.ent -side top -fill x -padx 4 -pady 4
377 set data(sEnt) $f3.ent
379 # The buttons
381 set maxWidth [::tk::mcmaxamp &OK &Filter &Cancel]
382 set maxWidth [expr {$maxWidth<6?6:$maxWidth}]
383 set data(okBtn) [::tk::AmpWidget button $bot.ok -text [mc "&OK"] \
384 -width $maxWidth \
385 -command [list tk::MotifFDialog_OkCmd $w]]
386 set data(filterBtn) [::tk::AmpWidget button $bot.filter -text [mc "&Filter"] \
387 -width $maxWidth \
388 -command [list tk::MotifFDialog_FilterCmd $w]]
389 set data(cancelBtn) [::tk::AmpWidget button $bot.cancel -text [mc "&Cancel"] \
390 -width $maxWidth \
391 -command [list tk::MotifFDialog_CancelCmd $w]]
393 pack $bot.ok $bot.filter $bot.cancel -padx 10 -pady 10 -expand yes \
394 -side left
396 # Create the bindings:
398 bind $w <Alt-Key> [list ::tk::AltKeyInDialog $w %A]
400 bind $data(fEnt) <Return> [list tk::MotifFDialog_ActivateFEnt $w]
401 bind $data(sEnt) <Return> [list tk::MotifFDialog_ActivateSEnt $w]
402 bind $w <Escape> [list tk::MotifFDialog_CancelCmd $w]
403 bind $w.bot <Destroy> {set ::tk::Priv(selectFilePath) {}}
405 wm protocol $w WM_DELETE_WINDOW [list tk::MotifFDialog_CancelCmd $w]
408 proc ::tk::MotifFDialog_SetListMode {w} {
409 upvar ::tk::dialog::file::[winfo name $w] data
411 if {$data(-multiple) != 0} {
412 set selectmode extended
413 } else {
414 set selectmode browse
416 set f $w.top.f2.b
417 $f.l configure -selectmode $selectmode
420 # ::tk::MotifFDialog_MakeSList --
422 # Create a scrolled-listbox and set the keyboard accelerator
423 # bindings so that the list selection follows what the user
424 # types.
426 # Arguments:
427 # w Pathname of the dialog box.
428 # f Frame widget inside which to create the scrolled
429 # listbox. This frame widget already exists.
430 # label The string to display on top of the listbox.
431 # under Sets the -under option of the label.
432 # cmdPrefix Specifies procedures to call when the listbox is
433 # browsed or activated.
435 proc ::tk::MotifFDialog_MakeSList {w f label cmdPrefix} {
436 bind [::tk::AmpWidget label $f.lab -text $label -anchor w] \
437 <<AltUnderlined>> [list focus $f.l]
438 listbox $f.l -width 12 -height 5 -exportselection 0\
439 -xscrollcommand [list $f.h set] -yscrollcommand [list $f.v set]
440 scrollbar $f.v -orient vertical -takefocus 0 -command [list $f.l yview]
441 scrollbar $f.h -orient horizontal -takefocus 0 -command [list $f.l xview]
442 grid $f.lab -row 0 -column 0 -sticky news -rowspan 1 -columnspan 2 \
443 -padx 2 -pady 2
444 grid $f.l -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news
445 grid $f.v -row 1 -column 1 -rowspan 1 -columnspan 1 -sticky news
446 grid $f.h -row 2 -column 0 -rowspan 1 -columnspan 1 -sticky news
448 grid rowconfigure $f 0 -weight 0 -minsize 0
449 grid rowconfigure $f 1 -weight 1 -minsize 0
450 grid columnconfigure $f 0 -weight 1 -minsize 0
452 # bindings for the listboxes
454 set list $f.l
455 bind $list <<ListboxSelect>> [list tk::MotifFDialog_Browse$cmdPrefix $w]
456 bind $list <Double-ButtonRelease-1> \
457 [list tk::MotifFDialog_Activate$cmdPrefix $w]
458 bind $list <Return> "tk::MotifFDialog_Browse$cmdPrefix [list $w]; \
459 tk::MotifFDialog_Activate$cmdPrefix [list $w]"
461 bindtags $list [list Listbox $list [winfo toplevel $list] all]
462 ListBoxKeyAccel_Set $list
464 return $f.l
467 # ::tk::MotifFDialog_InterpFilter --
469 # Interpret the string in the filter entry into two components:
470 # the directory and the pattern. If the string is a relative
471 # pathname, give a warning to the user and restore the pattern
472 # to original.
474 # Arguments:
475 # w pathname of the dialog box.
477 # Results:
478 # A list of two elements. The first element is the directory
479 # specified # by the filter. The second element is the filter
480 # pattern itself.
482 proc ::tk::MotifFDialog_InterpFilter {w} {
483 upvar ::tk::dialog::file::[winfo name $w] data
485 set text [string trim [$data(fEnt) get]]
487 # Perform tilde substitution
489 set badTilde 0
490 if {[string index $text 0] eq "~"} {
491 set list [file split $text]
492 set tilde [lindex $list 0]
493 if {[catch {set tilde [glob $tilde]}]} {
494 set badTilde 1
495 } else {
496 set text [eval file join [concat $tilde [lrange $list 1 end]]]
500 # If the string is a relative pathname, combine it
501 # with the current selectPath.
503 set relative 0
504 if {[file pathtype $text] eq "relative"} {
505 set relative 1
506 } elseif {$badTilde} {
507 set relative 1
510 if {$relative} {
511 tk_messageBox -icon warning -type ok \
512 -message "\"$text\" must be an absolute pathname"
514 $data(fEnt) delete 0 end
515 $data(fEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \
516 $data(filter)]
518 return [list $data(selectPath) $data(filter)]
521 set resolved [::tk::dialog::file::JoinFile [file dirname $text] [file tail $text]]
523 if {[file isdirectory $resolved]} {
524 set dir $resolved
525 set fil $data(filter)
526 } else {
527 set dir [file dirname $resolved]
528 set fil [file tail $resolved]
531 return [list $dir $fil]
534 # ::tk::MotifFDialog_Update
536 # Load the files and synchronize the "filter" and "selection" fields
537 # boxes.
539 # Arguments:
540 # w pathname of the dialog box.
542 # Results:
543 # None.
545 proc ::tk::MotifFDialog_Update {w} {
546 upvar ::tk::dialog::file::[winfo name $w] data
548 $data(fEnt) delete 0 end
549 $data(fEnt) insert 0 \
550 [::tk::dialog::file::JoinFile $data(selectPath) $data(filter)]
551 $data(sEnt) delete 0 end
552 $data(sEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \
553 $data(selectFile)]
555 MotifFDialog_LoadFiles $w
558 # ::tk::MotifFDialog_LoadFiles --
560 # Loads the files and directories into the two listboxes according
561 # to the filter setting.
563 # Arguments:
564 # w pathname of the dialog box.
566 # Results:
567 # None.
569 proc ::tk::MotifFDialog_LoadFiles {w} {
570 upvar ::tk::dialog::file::[winfo name $w] data
572 $data(dList) delete 0 end
573 $data(fList) delete 0 end
575 set appPWD [pwd]
576 if {[catch {cd $data(selectPath)}]} {
577 cd $appPWD
579 $data(dList) insert end ".."
580 return
583 # Make the dir and file lists
585 # For speed we only have one glob, which reduces the file system
586 # calls (good for slow NFS networks).
588 # We also do two smaller sorts (files + dirs) instead of one large sort,
589 # which gives a small speed increase.
591 set top 0
592 set dlist ""
593 set flist ""
594 foreach f [glob -nocomplain .* *] {
595 if {[file isdir ./$f]} {
596 lappend dlist $f
597 } else {
598 foreach pat $data(filter) {
599 if {[string match $pat $f]} {
600 if {[string match .* $f]} {
601 incr top
603 lappend flist $f
604 break
609 eval [list $data(dList) insert end] [lsort -dictionary $dlist]
610 eval [list $data(fList) insert end] [lsort -dictionary $flist]
612 # The user probably doesn't want to see the . files. We adjust the view
613 # so that the listbox displays all the non-dot files
614 $data(fList) yview $top
616 cd $appPWD
619 # ::tk::MotifFDialog_BrowseDList --
621 # This procedure is called when the directory list is browsed
622 # (clicked-over) by the user.
624 # Arguments:
625 # w The pathname of the dialog box.
627 # Results:
628 # None.
630 proc ::tk::MotifFDialog_BrowseDList {w} {
631 upvar ::tk::dialog::file::[winfo name $w] data
633 focus $data(dList)
634 if {[$data(dList) curselection] eq ""} {
635 return
637 set subdir [$data(dList) get [$data(dList) curselection]]
638 if {$subdir eq ""} {
639 return
642 $data(fList) selection clear 0 end
644 set list [MotifFDialog_InterpFilter $w]
645 set data(filter) [lindex $list 1]
647 switch -- $subdir {
649 set newSpec [::tk::dialog::file::JoinFile $data(selectPath) $data(filter)]
651 .. {
652 set newSpec [::tk::dialog::file::JoinFile [file dirname $data(selectPath)] \
653 $data(filter)]
655 default {
656 set newSpec [::tk::dialog::file::JoinFile [::tk::dialog::file::JoinFile \
657 $data(selectPath) $subdir] $data(filter)]
661 $data(fEnt) delete 0 end
662 $data(fEnt) insert 0 $newSpec
665 # ::tk::MotifFDialog_ActivateDList --
667 # This procedure is called when the directory list is activated
668 # (double-clicked) by the user.
670 # Arguments:
671 # w The pathname of the dialog box.
673 # Results:
674 # None.
676 proc ::tk::MotifFDialog_ActivateDList {w} {
677 upvar ::tk::dialog::file::[winfo name $w] data
679 if {[$data(dList) curselection] eq ""} {
680 return
682 set subdir [$data(dList) get [$data(dList) curselection]]
683 if {$subdir eq ""} {
684 return
687 $data(fList) selection clear 0 end
689 switch -- $subdir {
691 set newDir $data(selectPath)
693 .. {
694 set newDir [file dirname $data(selectPath)]
696 default {
697 set newDir [::tk::dialog::file::JoinFile $data(selectPath) $subdir]
701 set data(selectPath) $newDir
702 MotifFDialog_Update $w
704 if {$subdir ne ".."} {
705 $data(dList) selection set 0
706 $data(dList) activate 0
707 } else {
708 $data(dList) selection set 1
709 $data(dList) activate 1
713 # ::tk::MotifFDialog_BrowseFList --
715 # This procedure is called when the file list is browsed
716 # (clicked-over) by the user.
718 # Arguments:
719 # w The pathname of the dialog box.
721 # Results:
722 # None.
724 proc ::tk::MotifFDialog_BrowseFList {w} {
725 upvar ::tk::dialog::file::[winfo name $w] data
727 focus $data(fList)
728 set data(selectFile) ""
729 foreach item [$data(fList) curselection] {
730 lappend data(selectFile) [$data(fList) get $item]
732 if {[llength $data(selectFile)] == 0} {
733 return
736 $data(dList) selection clear 0 end
738 $data(fEnt) delete 0 end
739 $data(fEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \
740 $data(filter)]
741 $data(fEnt) xview end
743 # if it's a multiple selection box, just put in the filenames
744 # otherwise put in the full path as usual
745 $data(sEnt) delete 0 end
746 if {$data(-multiple) != 0} {
747 $data(sEnt) insert 0 $data(selectFile)
748 } else {
749 $data(sEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \
750 [lindex $data(selectFile) 0]]
752 $data(sEnt) xview end
755 # ::tk::MotifFDialog_ActivateFList --
757 # This procedure is called when the file list is activated
758 # (double-clicked) by the user.
760 # Arguments:
761 # w The pathname of the dialog box.
763 # Results:
764 # None.
766 proc ::tk::MotifFDialog_ActivateFList {w} {
767 upvar ::tk::dialog::file::[winfo name $w] data
769 if {[$data(fList) curselection] eq ""} {
770 return
772 set data(selectFile) [$data(fList) get [$data(fList) curselection]]
773 if {$data(selectFile) eq ""} {
774 return
775 } else {
776 MotifFDialog_ActivateSEnt $w
780 # ::tk::MotifFDialog_ActivateFEnt --
782 # This procedure is called when the user presses Return inside
783 # the "filter" entry. It updates the dialog according to the
784 # text inside the filter entry.
786 # Arguments:
787 # w The pathname of the dialog box.
789 # Results:
790 # None.
792 proc ::tk::MotifFDialog_ActivateFEnt {w} {
793 upvar ::tk::dialog::file::[winfo name $w] data
795 set list [MotifFDialog_InterpFilter $w]
796 set data(selectPath) [lindex $list 0]
797 set data(filter) [lindex $list 1]
799 MotifFDialog_Update $w
802 # ::tk::MotifFDialog_ActivateSEnt --
804 # This procedure is called when the user presses Return inside
805 # the "selection" entry. It sets the ::tk::Priv(selectFilePath)
806 # variable so that the vwait loop in tk::MotifFDialog will be
807 # terminated.
809 # Arguments:
810 # w The pathname of the dialog box.
812 # Results:
813 # None.
815 proc ::tk::MotifFDialog_ActivateSEnt {w} {
816 variable ::tk::Priv
817 upvar ::tk::dialog::file::[winfo name $w] data
819 set selectFilePath [string trim [$data(sEnt) get]]
821 if {$selectFilePath eq ""} {
822 MotifFDialog_FilterCmd $w
823 return
826 if {$data(-multiple) == 0} {
827 set selectFilePath [list $selectFilePath]
830 if {[file isdirectory [lindex $selectFilePath 0]]} {
831 set data(selectPath) [lindex [glob $selectFilePath] 0]
832 set data(selectFile) ""
833 MotifFDialog_Update $w
834 return
837 set newFileList ""
838 foreach item $selectFilePath {
839 if {[file pathtype $item] ne "absolute"} {
840 set item [file join $data(selectPath) $item]
841 } elseif {![file exists [file dirname $item]]} {
842 tk_messageBox -icon warning -type ok \
843 -message [mc {Directory "%1$s" does not exist.} \
844 [file dirname $item]]
845 return
848 if {![file exists $item]} {
849 if {$data(type) eq "open"} {
850 tk_messageBox -icon warning -type ok \
851 -message [mc {File "%1$s" does not exist.} $item]
852 return
854 } elseif {$data(type) eq "save" && $data(-confirmoverwrite)} {
855 set message [format %s%s \
856 [mc "File \"%1\$s\" already exists.\n\n" $selectFilePath] \
857 [mc {Replace existing file?}]]
858 set answer [tk_messageBox -icon warning -type yesno \
859 -message $message]
860 if {$answer eq "no"} {
861 return
865 lappend newFileList $item
868 # Return selected filter
869 if {[info exists data(-typevariable)] && $data(-typevariable) ne ""
870 && [info exists data(-filetypes)] && $data(-filetypes) ne ""} {
871 upvar #0 $data(-typevariable) typeVariable
872 set typeVariable [lindex $data(-filetypes) $data(fileType) 0]
875 if {$data(-multiple) != 0} {
876 set Priv(selectFilePath) $newFileList
877 } else {
878 set Priv(selectFilePath) [lindex $newFileList 0]
881 # Set selectFile and selectPath to first item in list
882 set Priv(selectFile) [file tail [lindex $newFileList 0]]
883 set Priv(selectPath) [file dirname [lindex $newFileList 0]]
887 proc ::tk::MotifFDialog_OkCmd {w} {
888 upvar ::tk::dialog::file::[winfo name $w] data
890 MotifFDialog_ActivateSEnt $w
893 proc ::tk::MotifFDialog_FilterCmd {w} {
894 upvar ::tk::dialog::file::[winfo name $w] data
896 MotifFDialog_ActivateFEnt $w
899 proc ::tk::MotifFDialog_CancelCmd {w} {
900 variable ::tk::Priv
902 set Priv(selectFilePath) ""
903 set Priv(selectFile) ""
904 set Priv(selectPath) ""
907 proc ::tk::ListBoxKeyAccel_Set {w} {
908 bind Listbox <Any-KeyPress> ""
909 bind $w <Destroy> [list tk::ListBoxKeyAccel_Unset $w]
910 bind $w <Any-KeyPress> [list tk::ListBoxKeyAccel_Key $w %A]
913 proc ::tk::ListBoxKeyAccel_Unset {w} {
914 variable ::tk::Priv
916 catch {after cancel $Priv(lbAccel,$w,afterId)}
917 unset -nocomplain Priv(lbAccel,$w) Priv(lbAccel,$w,afterId)
920 # ::tk::ListBoxKeyAccel_Key--
922 # This procedure maintains a list of recently entered keystrokes
923 # over a listbox widget. It arranges an idle event to move the
924 # selection of the listbox to the entry that begins with the
925 # keystrokes.
927 # Arguments:
928 # w The pathname of the listbox.
929 # key The key which the user just pressed.
931 # Results:
932 # None.
934 proc ::tk::ListBoxKeyAccel_Key {w key} {
935 variable ::tk::Priv
937 if { $key eq "" } {
938 return
940 append Priv(lbAccel,$w) $key
941 ListBoxKeyAccel_Goto $w $Priv(lbAccel,$w)
942 catch {
943 after cancel $Priv(lbAccel,$w,afterId)
945 set Priv(lbAccel,$w,afterId) [after 500 \
946 [list tk::ListBoxKeyAccel_Reset $w]]
949 proc ::tk::ListBoxKeyAccel_Goto {w string} {
950 variable ::tk::Priv
952 set string [string tolower $string]
953 set end [$w index end]
954 set theIndex -1
956 for {set i 0} {$i < $end} {incr i} {
957 set item [string tolower [$w get $i]]
958 if {[string compare $string $item] >= 0} {
959 set theIndex $i
961 if {[string compare $string $item] <= 0} {
962 set theIndex $i
963 break
967 if {$theIndex >= 0} {
968 $w selection clear 0 end
969 $w selection set $theIndex $theIndex
970 $w activate $theIndex
971 $w see $theIndex
972 event generate $w <<ListboxSelect>>
976 proc ::tk::ListBoxKeyAccel_Reset {w} {
977 variable ::tk::Priv
979 unset -nocomplain Priv(lbAccel,$w)
982 proc ::tk_getFileType {} {
983 variable ::tk::Priv
985 return $Priv(selectFileType)