xmfbox.tcl
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:25k
源码类别:

通讯编程

开发平台:

Visual C++

  1. # xmfbox.tcl --
  2. #
  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.
  6. #
  7. # RCS: @(#) $Id: xmfbox.tcl,v 1.25.2.3 2006/03/17 10:50:11 patthoyts Exp $
  8. #
  9. # Copyright (c) 1996 Sun Microsystems, Inc.
  10. # Copyright (c) 1998-2000 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. namespace eval ::tk::dialog {}
  15. namespace eval ::tk::dialog::file {}
  16. # ::tk::MotifFDialog --
  17. #
  18. # Implements a file dialog similar to the standard Motif file
  19. # selection box.
  20. #
  21. # Arguments:
  22. # type "open" or "save"
  23. # args Options parsed by the procedure.
  24. #
  25. # Results:
  26. # When -multiple is set to 0, this returns the absolute pathname
  27. # of the selected file. (NOTE: This is not the same as a single
  28. # element list.)
  29. # When -multiple is set to > 0, this returns a Tcl list of absolute
  30. #       pathnames. The argument for -multiple is ignored, but for consistency
  31. #       with Windows it defines the maximum amount of memory to allocate for
  32. #       the returned filenames.
  33. proc ::tk::MotifFDialog {type args} {
  34.     variable ::tk::Priv
  35.     set dataName __tk_filedialog
  36.     upvar ::tk::dialog::file::$dataName data
  37.     set w [MotifFDialog_Create $dataName $type $args]
  38.     # Set a grab and claim the focus too.
  39.     ::tk::SetFocusGrab $w $data(sEnt)
  40.     $data(sEnt) selection range 0 end
  41.     # Wait for the user to respond, then restore the focus and
  42.     # return the index of the selected button.  Restore the focus
  43.     # before deleting the window, since otherwise the window manager
  44.     # may take the focus away so we can't redirect it.  Finally,
  45.     # restore any grab that was in effect.
  46.     vwait ::tk::Priv(selectFilePath)
  47.     set result $Priv(selectFilePath)
  48.     ::tk::RestoreFocusGrab $w $data(sEnt) withdraw
  49.     return $result
  50. }
  51. # ::tk::MotifFDialog_Create --
  52. #
  53. # Creates the Motif file dialog (if it doesn't exist yet) and
  54. # initialize the internal data structure associated with the
  55. # dialog.
  56. #
  57. # This procedure is used by ::tk::MotifFDialog to create the
  58. # dialog. It's also used by the test suite to test the Motif
  59. # file dialog implementation. User code shouldn't call this
  60. # procedure directly.
  61. #
  62. # Arguments:
  63. # dataName Name of the global "data" array for the file dialog.
  64. # type "Save" or "Open"
  65. # argList Options parsed by the procedure.
  66. #
  67. # Results:
  68. # Pathname of the file dialog.
  69. proc ::tk::MotifFDialog_Create {dataName type argList} {
  70.     upvar ::tk::dialog::file::$dataName data
  71.     MotifFDialog_Config $dataName $type $argList
  72.     if {$data(-parent) eq "."} {
  73.         set w .$dataName
  74.     } else {
  75.         set w $data(-parent).$dataName
  76.     }
  77.     # (re)create the dialog box if necessary
  78.     #
  79.     if {![winfo exists $w]} {
  80. MotifFDialog_BuildUI $w
  81.     } elseif {[winfo class $w] ne "TkMotifFDialog"} {
  82. destroy $w
  83. MotifFDialog_BuildUI $w
  84.     } else {
  85. set data(fEnt) $w.top.f1.ent
  86. set data(dList) $w.top.f2.a.l
  87. set data(fList) $w.top.f2.b.l
  88. set data(sEnt) $w.top.f3.ent
  89. set data(okBtn) $w.bot.ok
  90. set data(filterBtn) $w.bot.filter
  91. set data(cancelBtn) $w.bot.cancel
  92.     }
  93.     MotifFDialog_SetListMode $w
  94.     # Dialog boxes should be transient with respect to their parent,
  95.     # so that they will always stay on top of their parent window.  However,
  96.     # some window managers will create the window as withdrawn if the parent
  97.     # window is withdrawn or iconified.  Combined with the grab we put on the
  98.     # window, this can hang the entire application.  Therefore we only make
  99.     # the dialog transient if the parent is viewable.
  100.     if {[winfo viewable [winfo toplevel $data(-parent)]] } {
  101. wm transient $w $data(-parent)
  102.     }
  103.     MotifFDialog_FileTypes $w
  104.     MotifFDialog_Update $w
  105.     # Withdraw the window, then update all the geometry information
  106.     # so we know how big it wants to be, then center the window in the
  107.     # display (Motif style) and de-iconify it.
  108.     ::tk::PlaceWindow $w
  109.     wm title $w $data(-title)
  110.     return $w
  111. }
  112. # ::tk::MotifFDialog_FileTypes --
  113. #
  114. # Checks the -filetypes option. If present this adds a list of radio-
  115. # buttons to pick the file types from.
  116. #
  117. # Arguments:
  118. # w Pathname of the tk_get*File dialogue.
  119. #
  120. # Results:
  121. # none
  122. proc ::tk::MotifFDialog_FileTypes {w} {
  123.     upvar ::tk::dialog::file::[winfo name $w] data
  124.     set f $w.top.f3.types
  125.     destroy $f
  126.     # No file types: use "*" as the filter and display no radio-buttons
  127.     if {$data(-filetypes) eq ""} {
  128. set data(filter) *
  129. return
  130.     }
  131.     # The filetypes radiobuttons
  132.     # set data(fileType) $data(-defaulttype)
  133.     set data(fileType) 0
  134.     MotifFDialog_SetFilter $w [lindex $data(-filetypes) $data(fileType)]
  135.     #don't produce radiobuttons for only one filetype
  136.     if {[llength $data(-filetypes)] == 1} {
  137. return
  138.     }
  139.     frame $f
  140.     set cnt 0
  141.     if {$data(-filetypes) ne ""} {
  142. foreach type $data(-filetypes) {
  143.     set title  [lindex [lindex $type 0] 0]
  144.     set filter [lindex $type 1]
  145.     radiobutton $f.b$cnt 
  146. -text $title 
  147. -variable ::tk::dialog::file::[winfo name $w](fileType) 
  148. -value $cnt 
  149. -command "[list tk::MotifFDialog_SetFilter $w $type]"
  150.     pack $f.b$cnt -side left
  151.     incr cnt
  152. }
  153.     }
  154.     $f.b$data(fileType) invoke
  155.     pack $f -side bottom -fill both
  156.     return
  157. }
  158. # This proc gets called whenever data(filter) is set
  159. #
  160. proc ::tk::MotifFDialog_SetFilter {w type} {
  161.     upvar ::tk::dialog::file::[winfo name $w] data
  162.     variable ::tk::Priv
  163.     set data(filter) [lindex $type 1]
  164.     set Priv(selectFileType) [lindex [lindex $type 0] 0]
  165.     MotifFDialog_Update $w
  166. }
  167. # ::tk::MotifFDialog_Config --
  168. #
  169. # Iterates over the optional arguments to determine the option
  170. # values for the Motif file dialog; gives default values to
  171. # unspecified options.
  172. #
  173. # Arguments:
  174. # dataName The name of the global variable in which
  175. # data for the file dialog is stored.
  176. # type "Save" or "Open"
  177. # argList Options parsed by the procedure.
  178. proc ::tk::MotifFDialog_Config {dataName type argList} {
  179.     upvar ::tk::dialog::file::$dataName data
  180.     set data(type) $type
  181.     # 1: the configuration specs
  182.     #
  183.     set specs {
  184. {-defaultextension "" "" ""}
  185. {-filetypes "" "" ""}
  186. {-initialdir "" "" ""}
  187. {-initialfile "" "" ""}
  188. {-parent "" "" "."}
  189. {-title "" "" ""}
  190.     }
  191.     if { $type eq "open" } {
  192. lappend specs {-multiple "" "" "0"}
  193.     }
  194.     set data(-multiple) 0
  195.     # 2: default values depending on the type of the dialog
  196.     #
  197.     if {![info exists data(selectPath)]} {
  198. # first time the dialog has been popped up
  199. set data(selectPath) [pwd]
  200. set data(selectFile) ""
  201.     }
  202.     # 3: parse the arguments
  203.     #
  204.     tclParseConfigSpec ::tk::dialog::file::$dataName $specs "" $argList
  205.     if {$data(-title) eq ""} {
  206. if {$type eq "open"} {
  207.     if {$data(-multiple) != 0} {
  208. set data(-title) "[mc {Open Multiple Files}]"
  209.     } else {
  210.     set data(-title) [mc "Open"]
  211.     }
  212. } else {
  213.     set data(-title) [mc "Save As"]
  214. }
  215.     }
  216.     # 4: set the default directory and selection according to the -initial
  217.     #    settings
  218.     #
  219.     if {$data(-initialdir) ne ""} {
  220. if {[file isdirectory $data(-initialdir)]} {
  221.     set data(selectPath) [lindex [glob $data(-initialdir)] 0]
  222. } else {
  223.     set data(selectPath) [pwd]
  224. }
  225. # Convert the initialdir to an absolute path name.
  226. set old [pwd]
  227. cd $data(selectPath)
  228. set data(selectPath) [pwd]
  229. cd $old
  230.     }
  231.     set data(selectFile) $data(-initialfile)
  232.     # 5. Parse the -filetypes option. It is not used by the motif
  233.     #    file dialog, but we check for validity of the value to make sure
  234.     #    the application code also runs fine with the TK file dialog.
  235.     #
  236.     set data(-filetypes) [::tk::FDGetFileTypes $data(-filetypes)]
  237.     if {![info exists data(filter)]} {
  238. set data(filter) *
  239.     }
  240.     if {![winfo exists $data(-parent)]} {
  241. error "bad window path name "$data(-parent)""
  242.     }
  243. }
  244. # ::tk::MotifFDialog_BuildUI --
  245. #
  246. # Builds the UI components of the Motif file dialog.
  247. #
  248. # Arguments:
  249. #  w Pathname of the dialog to build.
  250. #
  251. # Results:
  252. #  None.
  253. proc ::tk::MotifFDialog_BuildUI {w} {
  254.     set dataName [lindex [split $w .] end]
  255.     upvar ::tk::dialog::file::$dataName data
  256.     # Create the dialog toplevel and internal frames.
  257.     #
  258.     toplevel $w -class TkMotifFDialog
  259.     set top [frame $w.top -relief raised -bd 1]
  260.     set bot [frame $w.bot -relief raised -bd 1]
  261.     pack $w.bot -side bottom -fill x
  262.     pack $w.top -side top -expand yes -fill both
  263.     set f1 [frame $top.f1]
  264.     set f2 [frame $top.f2]
  265.     set f3 [frame $top.f3]
  266.     pack $f1 -side top    -fill x
  267.     pack $f3 -side bottom -fill x
  268.     pack $f2 -expand yes -fill both
  269.     set f2a [frame $f2.a]
  270.     set f2b [frame $f2.b]
  271.     grid $f2a -row 0 -column 0 -rowspan 1 -columnspan 1 -padx 4 -pady 4 
  272. -sticky news
  273.     grid $f2b -row 0 -column 1 -rowspan 1 -columnspan 1 -padx 4 -pady 4 
  274. -sticky news
  275.     grid rowconfigure $f2 0    -minsize 0   -weight 1
  276.     grid columnconfigure $f2 0 -minsize 0   -weight 1
  277.     grid columnconfigure $f2 1 -minsize 150 -weight 2
  278.     # The Filter box
  279.     #
  280.     bind [::tk::AmpWidget label $f1.lab -text [mc "Fil&ter:"] -anchor w] 
  281. <<AltUnderlined>> [list focus $f1.ent]
  282.     entry $f1.ent
  283.     pack $f1.lab -side top -fill x -padx 6 -pady 4
  284.     pack $f1.ent -side top -fill x -padx 4 -pady 0
  285.     set data(fEnt) $f1.ent
  286.     # The file and directory lists
  287.     #
  288.     set data(dList) [MotifFDialog_MakeSList $w $f2a 
  289.     [mc "&Directory:"] DList]
  290.     set data(fList) [MotifFDialog_MakeSList $w $f2b 
  291.     [mc "Fi&les:"]     FList]
  292.     # The Selection box
  293.     #
  294.     bind [::tk::AmpWidget label $f3.lab -text [mc "&Selection:"] -anchor w] 
  295. <<AltUnderlined>> [list focus $f3.ent]
  296.     entry $f3.ent
  297.     pack $f3.lab -side top -fill x -padx 6 -pady 0
  298.     pack $f3.ent -side top -fill x -padx 4 -pady 4
  299.     set data(sEnt) $f3.ent
  300.     # The buttons
  301.     #
  302.     set maxWidth [::tk::mcmaxamp &OK &Filter &Cancel]
  303.     set maxWidth [expr {$maxWidth<6?6:$maxWidth}]
  304.     set data(okBtn) [::tk::AmpWidget button $bot.ok -text [mc "&OK"] 
  305.     -width $maxWidth 
  306.     -command [list tk::MotifFDialog_OkCmd $w]]
  307.     set data(filterBtn) [::tk::AmpWidget button $bot.filter -text [mc "&Filter"] 
  308.     -width $maxWidth 
  309.     -command [list tk::MotifFDialog_FilterCmd $w]]
  310.     set data(cancelBtn) [::tk::AmpWidget button $bot.cancel -text [mc "&Cancel"] 
  311.     -width $maxWidth 
  312.     -command [list tk::MotifFDialog_CancelCmd $w]]
  313.     pack $bot.ok $bot.filter $bot.cancel -padx 10 -pady 10 -expand yes 
  314. -side left
  315.     # Create the bindings:
  316.     #
  317.     bind $w <Alt-Key> [list ::tk::AltKeyInDialog $w %A]
  318.     bind $data(fEnt) <Return> [list tk::MotifFDialog_ActivateFEnt $w]
  319.     bind $data(sEnt) <Return> [list tk::MotifFDialog_ActivateSEnt $w]
  320.     bind $w <Escape> [list tk::MotifFDialog_CancelCmd $w]
  321.     bind $w.bot <Destroy> {set ::tk::Priv(selectFilePath) {}}
  322.     wm protocol $w WM_DELETE_WINDOW [list tk::MotifFDialog_CancelCmd $w]
  323. }
  324. proc ::tk::MotifFDialog_SetListMode {w} {
  325.     upvar ::tk::dialog::file::[winfo name $w] data
  326.     if {$data(-multiple) != 0} {
  327. set selectmode extended
  328.     } else {
  329. set selectmode browse
  330.     }
  331.     set f $w.top.f2.b
  332.     $f.l configure -selectmode $selectmode
  333. }
  334. # ::tk::MotifFDialog_MakeSList --
  335. #
  336. # Create a scrolled-listbox and set the keyboard accelerator
  337. # bindings so that the list selection follows what the user
  338. # types.
  339. #
  340. # Arguments:
  341. # w Pathname of the dialog box.
  342. # f Frame widget inside which to create the scrolled
  343. # listbox. This frame widget already exists.
  344. # label The string to display on top of the listbox.
  345. # under Sets the -under option of the label.
  346. # cmdPrefix Specifies procedures to call when the listbox is
  347. # browsed or activated.
  348. proc ::tk::MotifFDialog_MakeSList {w f label cmdPrefix} {
  349.     bind [::tk::AmpWidget label $f.lab -text $label -anchor w] 
  350. <<AltUnderlined>> [list focus $f.l]
  351.     listbox $f.l -width 12 -height 5 -exportselection 0
  352. -xscrollcommand [list $f.h set] -yscrollcommand [list $f.v set]
  353.     scrollbar $f.v -orient vertical   -takefocus 0 -command [list $f.l yview]
  354.     scrollbar $f.h -orient horizontal -takefocus 0 -command [list $f.l xview]
  355.     grid $f.lab -row 0 -column 0 -sticky news -rowspan 1 -columnspan 2 
  356. -padx 2 -pady 2
  357.     grid $f.l -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news
  358.     grid $f.v -row 1 -column 1 -rowspan 1 -columnspan 1 -sticky news
  359.     grid $f.h -row 2 -column 0 -rowspan 1 -columnspan 1 -sticky news
  360.     grid rowconfigure    $f 0 -weight 0 -minsize 0
  361.     grid rowconfigure    $f 1 -weight 1 -minsize 0
  362.     grid columnconfigure $f 0 -weight 1 -minsize 0
  363.     # bindings for the listboxes
  364.     #
  365.     set list $f.l
  366.     bind $list <<ListboxSelect>> [list tk::MotifFDialog_Browse$cmdPrefix $w]
  367.     bind $list <Double-ButtonRelease-1> 
  368.     [list tk::MotifFDialog_Activate$cmdPrefix $w]
  369.     bind $list <Return> "tk::MotifFDialog_Browse$cmdPrefix [list $w]; 
  370.     tk::MotifFDialog_Activate$cmdPrefix [list $w]"
  371.     bindtags $list [list Listbox $list [winfo toplevel $list] all]
  372.     ListBoxKeyAccel_Set $list
  373.     return $f.l
  374. }
  375. # ::tk::MotifFDialog_InterpFilter --
  376. #
  377. # Interpret the string in the filter entry into two components:
  378. # the directory and the pattern. If the string is a relative
  379. # pathname, give a warning to the user and restore the pattern
  380. # to original.
  381. #
  382. # Arguments:
  383. # w pathname of the dialog box.
  384. #
  385. # Results:
  386. #  A list of two elements. The first element is the directory
  387. #  specified # by the filter. The second element is the filter
  388. #  pattern itself.
  389. proc ::tk::MotifFDialog_InterpFilter {w} {
  390.     upvar ::tk::dialog::file::[winfo name $w] data
  391.     set text [string trim [$data(fEnt) get]]
  392.     # Perform tilde substitution
  393.     #
  394.     set badTilde 0
  395.     if {[string index $text 0] eq "~"} {
  396. set list [file split $text]
  397. set tilde [lindex $list 0]
  398. if {[catch {set tilde [glob $tilde]}]} {
  399.     set badTilde 1
  400. } else {
  401.     set text [eval file join [concat $tilde [lrange $list 1 end]]]
  402. }
  403.     }
  404.     # If the string is a relative pathname, combine it
  405.     # with the current selectPath.
  406.     set relative 0
  407.     if {[file pathtype $text] eq "relative"} {
  408. set relative 1
  409.     } elseif {$badTilde} {
  410. set relative 1
  411.     }
  412.     if {$relative} {
  413. tk_messageBox -icon warning -type ok 
  414.     -message ""$text" must be an absolute pathname"
  415. $data(fEnt) delete 0 end
  416. $data(fEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) 
  417. $data(filter)]
  418. return [list $data(selectPath) $data(filter)]
  419.     }
  420.     set resolved [::tk::dialog::file::JoinFile [file dirname $text] [file tail $text]]
  421.     if {[file isdirectory $resolved]} {
  422. set dir $resolved
  423. set fil $data(filter)
  424.     } else {
  425. set dir [file dirname $resolved]
  426. set fil [file tail    $resolved]
  427.     }
  428.     return [list $dir $fil]
  429. }
  430. # ::tk::MotifFDialog_Update
  431. #
  432. # Load the files and synchronize the "filter" and "selection" fields
  433. # boxes.
  434. #
  435. # Arguments:
  436. #  w  pathname of the dialog box.
  437. #
  438. # Results:
  439. # None.
  440. proc ::tk::MotifFDialog_Update {w} {
  441.     upvar ::tk::dialog::file::[winfo name $w] data
  442.     $data(fEnt) delete 0 end
  443.     $data(fEnt) insert 0 
  444.             [::tk::dialog::file::JoinFile $data(selectPath) $data(filter)]
  445.     $data(sEnt) delete 0 end
  446.     $data(sEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) 
  447.     $data(selectFile)]
  448.  
  449.     MotifFDialog_LoadFiles $w
  450. }
  451. # ::tk::MotifFDialog_LoadFiles --
  452. #
  453. # Loads the files and directories into the two listboxes according
  454. # to the filter setting.
  455. #
  456. # Arguments:
  457. #  w  pathname of the dialog box.
  458. #
  459. # Results:
  460. # None.
  461. proc ::tk::MotifFDialog_LoadFiles {w} {
  462.     upvar ::tk::dialog::file::[winfo name $w] data
  463.     $data(dList) delete 0 end
  464.     $data(fList) delete 0 end
  465.     set appPWD [pwd]
  466.     if {[catch {cd $data(selectPath)}]} {
  467. cd $appPWD
  468. $data(dList) insert end ".."
  469. return
  470.     }
  471.     # Make the dir and file lists
  472.     #
  473.     # For speed we only have one glob, which reduces the file system
  474.     # calls (good for slow NFS networks).
  475.     #
  476.     # We also do two smaller sorts (files + dirs) instead of one large sort,
  477.     # which gives a small speed increase.
  478.     #
  479.     set top 0
  480.     set dlist ""
  481.     set flist ""
  482.     foreach f [glob -nocomplain .* *] {
  483. if {[file isdir ./$f]} {
  484.     lappend dlist $f
  485. } else {
  486.             foreach pat $data(filter) {
  487.                 if {[string match $pat $f]} {
  488. if {[string match .* $f]} {
  489.     incr top
  490. }
  491. lappend flist $f
  492.                     break
  493.     }
  494.             }
  495. }
  496.     }
  497.     eval [list $data(dList) insert end] [lsort -dictionary $dlist]
  498.     eval [list $data(fList) insert end] [lsort -dictionary $flist]
  499.     # The user probably doesn't want to see the . files. We adjust the view
  500.     # so that the listbox displays all the non-dot files
  501.     $data(fList) yview $top
  502.     cd $appPWD
  503. }
  504. # ::tk::MotifFDialog_BrowseDList --
  505. #
  506. # This procedure is called when the directory list is browsed
  507. # (clicked-over) by the user.
  508. #
  509. # Arguments:
  510. #  w The pathname of the dialog box.
  511. #
  512. # Results:
  513. # None.
  514. proc ::tk::MotifFDialog_BrowseDList {w} {
  515.     upvar ::tk::dialog::file::[winfo name $w] data
  516.     focus $data(dList)
  517.     if {[$data(dList) curselection] eq ""} {
  518. return
  519.     }
  520.     set subdir [$data(dList) get [$data(dList) curselection]]
  521.     if {$subdir eq ""} {
  522. return
  523.     }
  524.     $data(fList) selection clear 0 end
  525.     set list [MotifFDialog_InterpFilter $w]
  526.     set data(filter) [lindex $list 1]
  527.     switch -- $subdir {
  528. . {
  529.     set newSpec [::tk::dialog::file::JoinFile $data(selectPath) $data(filter)]
  530. }
  531. .. {
  532.     set newSpec [::tk::dialog::file::JoinFile [file dirname $data(selectPath)] 
  533. $data(filter)]
  534. }
  535. default {
  536.     set newSpec [::tk::dialog::file::JoinFile [::tk::dialog::file::JoinFile 
  537.     $data(selectPath) $subdir] $data(filter)]
  538. }
  539.     }
  540.     $data(fEnt) delete 0 end
  541.     $data(fEnt) insert 0 $newSpec
  542. }
  543. # ::tk::MotifFDialog_ActivateDList --
  544. #
  545. # This procedure is called when the directory list is activated
  546. # (double-clicked) by the user.
  547. #
  548. # Arguments:
  549. #  w The pathname of the dialog box.
  550. #
  551. # Results:
  552. # None.
  553. proc ::tk::MotifFDialog_ActivateDList {w} {
  554.     upvar ::tk::dialog::file::[winfo name $w] data
  555.     if {[$data(dList) curselection] eq ""} {
  556. return
  557.     }
  558.     set subdir [$data(dList) get [$data(dList) curselection]]
  559.     if {$subdir eq ""} {
  560. return
  561.     }
  562.     $data(fList) selection clear 0 end
  563.     switch -- $subdir {
  564. . {
  565.     set newDir $data(selectPath)
  566. }
  567. .. {
  568.     set newDir [file dirname $data(selectPath)]
  569. }
  570. default {
  571.     set newDir [::tk::dialog::file::JoinFile $data(selectPath) $subdir]
  572. }
  573.     }
  574.     set data(selectPath) $newDir
  575.     MotifFDialog_Update $w
  576.     if {$subdir ne ".."} {
  577. $data(dList) selection set 0
  578. $data(dList) activate 0
  579.     } else {
  580. $data(dList) selection set 1
  581. $data(dList) activate 1
  582.     }
  583. }
  584. # ::tk::MotifFDialog_BrowseFList --
  585. #
  586. # This procedure is called when the file list is browsed
  587. # (clicked-over) by the user.
  588. #
  589. # Arguments:
  590. #  w The pathname of the dialog box.
  591. #
  592. # Results:
  593. # None.
  594. proc ::tk::MotifFDialog_BrowseFList {w} {
  595.     upvar ::tk::dialog::file::[winfo name $w] data
  596.     focus $data(fList)
  597.     set data(selectFile) ""
  598.     foreach item [$data(fList) curselection] {
  599. lappend data(selectFile) [$data(fList) get $item]
  600.     }
  601.     if {[llength $data(selectFile)] == 0} {
  602. return
  603.     }
  604.     $data(dList) selection clear 0 end
  605.     $data(fEnt) delete 0 end
  606.     $data(fEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) 
  607.     $data(filter)]
  608.     $data(fEnt) xview end
  609.  
  610.     # if it's a multiple selection box, just put in the filenames 
  611.     # otherwise put in the full path as usual 
  612.     $data(sEnt) delete 0 end
  613.     if {$data(-multiple) != 0} {
  614. $data(sEnt) insert 0 $data(selectFile)
  615.     } else {
  616. $data(sEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) 
  617.   [lindex $data(selectFile) 0]]
  618.     }
  619.     $data(sEnt) xview end
  620. }
  621. # ::tk::MotifFDialog_ActivateFList --
  622. #
  623. # This procedure is called when the file list is activated
  624. # (double-clicked) by the user.
  625. #
  626. # Arguments:
  627. #  w The pathname of the dialog box.
  628. #
  629. # Results:
  630. # None.
  631. proc ::tk::MotifFDialog_ActivateFList {w} {
  632.     upvar ::tk::dialog::file::[winfo name $w] data
  633.     if {[$data(fList) curselection] eq ""} {
  634. return
  635.     }
  636.     set data(selectFile) [$data(fList) get [$data(fList) curselection]]
  637.     if {$data(selectFile) eq ""} {
  638. return
  639.     } else {
  640. MotifFDialog_ActivateSEnt $w
  641.     }
  642. }
  643. # ::tk::MotifFDialog_ActivateFEnt --
  644. #
  645. # This procedure is called when the user presses Return inside
  646. # the "filter" entry. It updates the dialog according to the
  647. # text inside the filter entry.
  648. #
  649. # Arguments:
  650. #  w The pathname of the dialog box.
  651. #
  652. # Results:
  653. # None.
  654. proc ::tk::MotifFDialog_ActivateFEnt {w} {
  655.     upvar ::tk::dialog::file::[winfo name $w] data
  656.     set list [MotifFDialog_InterpFilter $w]
  657.     set data(selectPath) [lindex $list 0]
  658.     set data(filter)    [lindex $list 1]
  659.     MotifFDialog_Update $w
  660. }
  661. # ::tk::MotifFDialog_ActivateSEnt --
  662. #
  663. # This procedure is called when the user presses Return inside
  664. # the "selection" entry. It sets the ::tk::Priv(selectFilePath) 
  665. # variable so that the vwait loop in tk::MotifFDialog will be
  666. # terminated.
  667. #
  668. # Arguments:
  669. #  w The pathname of the dialog box.
  670. #
  671. # Results:
  672. # None.
  673. proc ::tk::MotifFDialog_ActivateSEnt {w} {
  674.     variable ::tk::Priv
  675.     upvar ::tk::dialog::file::[winfo name $w] data
  676.     set selectFilePath [string trim [$data(sEnt) get]]
  677.     if {$selectFilePath eq ""} {
  678. MotifFDialog_FilterCmd $w
  679. return
  680.     }
  681.     if {$data(-multiple) == 0} {
  682. set selectFilePath [list $selectFilePath]
  683.     }
  684.     if {[file isdirectory [lindex $selectFilePath 0]]} {
  685. set data(selectPath) [lindex [glob $selectFilePath] 0]
  686. set data(selectFile) ""
  687. MotifFDialog_Update $w
  688. return
  689.     }
  690.     set newFileList ""
  691.     foreach item $selectFilePath {
  692. if {[file pathtype $item] ne "absolute"} {
  693.     set item [file join $data(selectPath) $item]
  694. } elseif {![file exists [file dirname $item]]} {
  695.     tk_messageBox -icon warning -type ok 
  696.     -message [mc {Directory "%1$s" does not exist.} 
  697.     [file dirname $item]]
  698.     return
  699. }
  700. if {![file exists $item]} {
  701.     if {$data(type) eq "open"} {
  702. tk_messageBox -icon warning -type ok 
  703. -message [mc {File "%1$s" does not exist.} $item]
  704. return
  705.     }
  706. } else {
  707.     if {$data(type) eq "save"} {
  708. set message [format %s%s 
  709. [mc "File "%1$s" already exists.nn" 
  710. $selectFilePath] 
  711. [mc {Replace existing file?}]]
  712. set answer [tk_messageBox -icon warning -type yesno 
  713. -message $message]
  714. if {$answer eq "no"} {
  715.     return
  716. }
  717.     }
  718. }
  719. lappend newFileList $item
  720.     }
  721.     if {$data(-multiple) != 0} {
  722. set Priv(selectFilePath) $newFileList
  723.     } else {
  724. set Priv(selectFilePath) [lindex $newFileList 0]
  725.     }
  726.     # Set selectFile and selectPath to first item in list
  727.     set Priv(selectFile)     [file tail    [lindex $newFileList 0]]
  728.     set Priv(selectPath)     [file dirname [lindex $newFileList 0]]
  729. }
  730. proc ::tk::MotifFDialog_OkCmd {w} {
  731.     upvar ::tk::dialog::file::[winfo name $w] data
  732.     MotifFDialog_ActivateSEnt $w
  733. }
  734. proc ::tk::MotifFDialog_FilterCmd {w} {
  735.     upvar ::tk::dialog::file::[winfo name $w] data
  736.     MotifFDialog_ActivateFEnt $w
  737. }
  738. proc ::tk::MotifFDialog_CancelCmd {w} {
  739.     variable ::tk::Priv
  740.     set Priv(selectFilePath) ""
  741.     set Priv(selectFile)     ""
  742.     set Priv(selectPath)     ""
  743. }
  744. proc ::tk::ListBoxKeyAccel_Set {w} {
  745.     bind Listbox <Any-KeyPress> ""
  746.     bind $w <Destroy> [list tk::ListBoxKeyAccel_Unset $w]
  747.     bind $w <Any-KeyPress> [list tk::ListBoxKeyAccel_Key $w %A]
  748. }
  749. proc ::tk::ListBoxKeyAccel_Unset {w} {
  750.     variable ::tk::Priv
  751.     catch {after cancel $Priv(lbAccel,$w,afterId)}
  752.     unset -nocomplain Priv(lbAccel,$w) Priv(lbAccel,$w,afterId)
  753. }
  754. # ::tk::ListBoxKeyAccel_Key--
  755. #
  756. # This procedure maintains a list of recently entered keystrokes
  757. # over a listbox widget. It arranges an idle event to move the
  758. # selection of the listbox to the entry that begins with the
  759. # keystrokes.
  760. #
  761. # Arguments:
  762. #  w The pathname of the listbox.
  763. # key The key which the user just pressed.
  764. #
  765. # Results:
  766. # None.
  767. proc ::tk::ListBoxKeyAccel_Key {w key} {
  768.     variable ::tk::Priv
  769.     if { $key eq "" } {
  770. return
  771.     }
  772.     append Priv(lbAccel,$w) $key
  773.     ListBoxKeyAccel_Goto $w $Priv(lbAccel,$w)
  774.     catch {
  775. after cancel $Priv(lbAccel,$w,afterId)
  776.     }
  777.     set Priv(lbAccel,$w,afterId) [after 500 
  778.     [list tk::ListBoxKeyAccel_Reset $w]]
  779. }
  780. proc ::tk::ListBoxKeyAccel_Goto {w string} {
  781.     variable ::tk::Priv
  782.     set string [string tolower $string]
  783.     set end [$w index end]
  784.     set theIndex -1
  785.     for {set i 0} {$i < $end} {incr i} {
  786. set item [string tolower [$w get $i]]
  787. if {[string compare $string $item] >= 0} {
  788.     set theIndex $i
  789. }
  790. if {[string compare $string $item] <= 0} {
  791.     set theIndex $i
  792.     break
  793. }
  794.     }
  795.     if {$theIndex >= 0} {
  796. $w selection clear 0 end
  797. $w selection set $theIndex $theIndex
  798. $w activate $theIndex
  799. $w see $theIndex
  800. event generate $w <<ListboxSelect>>
  801.     }
  802. }
  803. proc ::tk::ListBoxKeyAccel_Reset {w} {
  804.     variable ::tk::Priv
  805.     unset -nocomplain Priv(lbAccel,$w)
  806. }
  807. proc ::tk_getFileType {} {
  808.     variable ::tk::Priv
  809.     return $Priv(selectFileType)
  810. }