home *** CD-ROM | disk | FTP | other *** search
/ PC World 2002 May / PCWorld_2002-05_cd.bin / Software / TemaCD / activetcltk / ActiveTcl8.3.4.1-8.win32-ix86.exe / ActiveTcl8.3.4.1-win32-ix86 / lib / tk8.3 / xmfbox.tcl < prev   
Encoding:
Text File  |  2001-10-22  |  21.3 KB  |  833 lines

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