Tk Source Code

Check-in [f3b0b975]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:[Bug 3558535]: Factor out the filtered-sorted globbing code into one procedure that knows how to avoid nasty problems when non-list filters are used.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: f3b0b97579c1940979e47720c7de3d89ba4992e6
User & Date: dkf 2012-08-24 15:12:34
Context
2012-08-25
01:55
3554026 3561016 Better fix from Emiliano Gavilan. check-in: ca2a716c user: dgp tags: trunk
2012-08-24
15:12
[Bug 3558535]: Factor out the filtered-sorted globbing code into one procedure that knows how to avoid nasty problems when non-list filters are used. check-in: f3b0b975 user: dkf tags: trunk
14:59
[Bug 3558535]: Factor out the filtered-sorted globbing code into one procedure that knows how to avoid nasty problems when non-list filters are used. check-in: 89300ed4 user: dkf tags: core-8-5-branch
2012-08-23
21:42
3554026,3561016 Stop crash with tearoff menus check-in: 2eee9b6a user: dgp tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ChangeLog.









1
2
3

4
5
6
7
8
9
10








2012-08-23  Don Porter  <[email protected]>

	* unix/tkUnixWm.c: [Bugs 3554026,3561016] Stop crash with tearoff menus.


2012-08-23  Jan Nijtmans  <[email protected]>

	* library/tk.tcl:        [Bug 3555644]: Better use of virtual events,
	* library/ttk/entry.tcl  Add <<ToggleSelection>> virtual event.
	* library/ttk/treeview.tcl

>
>
>
>
>
>
>
>


|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2012-08-24  Donal K. Fellows  <[email protected]>

	* library/tkfbox.tcl (GlobFiltered): [Bug 3558535]: Factor out the
	filtered-sorted globbing code into one procedure that knows how to
	avoid nasty problems when non-list filters are used. This allows the
	rest of the [tk_getOpenFile] implementation to be ignorant of the
	considerable complexities of globbing.

2012-08-23  Don Porter  <[email protected]>

	* unix/tkUnixWm.c: [Bugs 3554026,3561016]: Stop crash with tearoff
	menus.

2012-08-23  Jan Nijtmans  <[email protected]>

	* library/tk.tcl:        [Bug 3555644]: Better use of virtual events,
	* library/ttk/entry.tcl  Add <<ToggleSelection>> virtual event.
	* library/ttk/treeview.tcl

Changes to library/tkfbox.tcl.

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
    $w         configure -cursor watch
    update idletasks

    $data(icons) deleteall

    set showHidden $showHiddenVar

    # Make the dir list
    # Using -directory [pwd] is better in some VFS cases.
    set cmd [list glob -tails -directory [pwd] -type d -nocomplain *]
    if {$showHidden} {
	lappend cmd .*
    }
    set dirs [lsort -dictionary -unique [{*}$cmd]]
    set dirList {}
    foreach d $dirs {
	if {$d eq "." || $d eq ".."} {
	    continue
	}
	lappend dirList $d
    }
    $data(icons) add $folder $dirList

    if {$class eq "TkFDialog"} {
	# Make the file list if this is a File Dialog, selecting all but
	# 'd'irectory type files.
	#
	set cmd [list glob -tails -directory [pwd] \
		-type {f b c l p s} -nocomplain]
	if {$data(filter) eq "*"} {
	    lappend cmd *
	    if {$showHidden} {
		lappend cmd .*
	    }
	} else {
	    lappend cmd {*}$data(filter)
	}
	set fileList [lsort -dictionary -unique [{*}$cmd]]
	$data(icons) add $file $fileList
    }

    # Update the Directory: option menu
    #
    set list ""
    set dir ""
    foreach subdir [file split $data(selectPath)] {







|
|
<
<
<
<
<
<
<
<
<
<
<
<
|





<
<
<
<
<
<
<
<
<
<
<
|







584
585
586
587
588
589
590
591
592












593
594
595
596
597
598











599
600
601
602
603
604
605
606
    $w         configure -cursor watch
    update idletasks

    $data(icons) deleteall

    set showHidden $showHiddenVar

    # Make the dir list. Note that using an explicit [pwd] (instead of '.') is
    # better in some VFS cases.












    $data(icons) add $folder [GlobFiltered [pwd] d 1]

    if {$class eq "TkFDialog"} {
	# Make the file list if this is a File Dialog, selecting all but
	# 'd'irectory type files.
	#











	$data(icons) add $file [GlobFiltered [pwd] {f b c l p s}]
    }

    # Update the Directory: option menu
    #
    set list ""
    set dir ""
    foreach subdir [file split $data(selectPath)] {
1143
1144
1145
1146
1147
1148
1149
1150

















































1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
	    upvar #0 $data(-typevariable) typeVariable
	    set typeVariable [lindex $data(filterType) 0]
	}
    }
    bind $data(okBtn) <Destroy> {}
    set Priv(selectFilePath) $selectFilePath
}


















































proc ::tk::dialog::file::CompleteEnt {w} {
    variable showHiddenVar
    upvar ::tk::dialog::file::[winfo name $w] data
    set f [$data(ent) get]
    if {$data(-multiple)} {
	if {[catch {llength $f} len] || $len != 1} {
	    return -code break
	}
	set f [lindex $f 0]
    }

    # Get list of matching filenames and dirnames
    set globF [list glob -tails -directory $data(selectPath) \
		-type {f b c l p s} -nocomplain]
    set globD [list glob -tails -directory $data(selectPath) -type d \
		       -nocomplain *]
    if {$data(filter) eq "*"} {
	lappend globF *
	if {$showHiddenVar} {
	    lappend globF .*
	    lappend globD .*
	}
	if {[winfo class $w] eq "TkFDialog"} {
	    set files [lsort -dictionary -unique [{*}$globF]]
	} else {
	    set files {}
	}
	set dirs [lsort -dictionary -unique [{*}$globD]]
    } else {
	if {$showHiddenVar} {
	    lappend globD .*
	}
	if {[winfo class $w] eq "TkFDialog"} {
	    set files [lsort -dictionary -unique [{*}$globF {*}$data(filter)]]
	} else {
	    set files {}
	}
	set dirs [lsort -dictionary -unique [{*}$globD]]
    }
    # Filter specials
    set dirs [lsearch -all -not -exact -inline $dirs .]
    set dirs [lsearch -all -not -exact -inline $dirs ..]
    set dirs2 {}
    foreach d $dirs {lappend dirs2 $d/}

    set targets [concat \
	    [lsearch -glob -all -inline $files $f*] \
	    [lsearch -glob -all -inline $dirs2 $f*]]

    if {[llength $targets] == 1} {
	# We have a winner!








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|






<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
<

|







1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188










1189










1190


1191





1192
1193
1194
1195
1196
1197
1198
1199
1200
	    upvar #0 $data(-typevariable) typeVariable
	    set typeVariable [lindex $data(filterType) 0]
	}
    }
    bind $data(okBtn) <Destroy> {}
    set Priv(selectFilePath) $selectFilePath
}

# ::tk::dialog::file::GlobFiltered --
#
#	Gets called to do globbing, returning the results and filtering them
#	according to the current filter (and removing the entries for '.' and
#	'..' which are never shown). Deals with evil cases such as where the
#	user is supplying a filter which is an invalid list or where it has an
#	unbalanced brace. The resulting list will be dictionary sorted.
#
#	Arguments:
#	  dir		 Which directory to search
#	  type		 List of filetypes to look for ('d' or 'f b c l p s')
#	  overrideFilter Whether to ignore the filter for this search.
#
#	NB: Assumes that the caller has mapped the state variable to 'data'.
#
proc ::tk::dialog::file::GlobFiltered {dir type {overrideFilter 0}} {
    variable showHiddenVar
    upvar 1 data(filter) filter

    if {$filter eq "*" || $overrideFilter} {
	set patterns [list *]
	if {$showHiddenVar} {
	    lappend patterns .*
	}
    } elseif {[string is list $filter]} {
	set patterns $filter
    } else {
	# Invalid list; assume we can use non-whitespace sequences as words
	set patterns [regexp -inline -all {\S+} $filter]
    }

    set opts [list -tails -directory $dir -type $type -nocomplain]

    set result {}
    catch {
	# We have a catch because we might have a really bad pattern (e.g.,
	# with an unbalanced brace); even [glob -nocomplain] doesn't like it.
	# Using a catch ensures that it just means we match nothing instead of
	# throwing a nasty error at the user...
	foreach f [glob {*}$opts -- {*}$patterns] {
	    if {$f eq "." || $f eq ".."} {
		continue
	    }
	    lappend result $f
	}
    }
    return [lsort -dictionary -unique $result]
}

proc ::tk::dialog::file::CompleteEnt {w} {
    variable showHiddenVar
    upvar ::tk::dialog::file::[winfo name $w] data
    set f [$data(ent) get]
    if {$data(-multiple)} {
	if {![string is list $f] || [llength $f] != 1} {
	    return -code break
	}
	set f [lindex $f 0]
    }

    # Get list of matching filenames and dirnames










    set files [if {[winfo class $w] eq "TkFDialog"} {










	GlobFiltered $data(selectPath) {f b c l p s}


    }]





    set dirs2 {}
    foreach d [GlobFiltered $data(selectPath) d] {lappend dirs2 $d/}

    set targets [concat \
	    [lsearch -glob -all -inline $files $f*] \
	    [lsearch -glob -all -inline $dirs2 $f*]]

    if {[llength $targets] == 1} {
	# We have a winner!