Bwidget Source Code
Artifact [43b206970e]
Not logged in

Artifact 43b206970ee59a5e8a58389c702a3fc7329a33c5:

Attachment "combobox.patch" to ticket [6c6704e40f] added by oehhar 2013-10-15 18:49:04.
--- U:/elmicron/tech/tcl/bwidget/checkout_bwidget/combobox.tcl	Mon Oct 14 17:16:57 2013
+++ U:/elmicron/tech/tcl/bwidget/checkout_bwidget/combobox_kech2.tcl	Tue Oct 15 13:30:12 2013
@@ -1,944 +1,973 @@
-# ----------------------------------------------------------------------------
-#  combobox.tcl
-#  This file is part of Unifix BWidget Toolkit
-#  $Id: combobox.tcl,v 1.42.2.3 2012/04/02 09:53:41 oehhar Exp $
-# ----------------------------------------------------------------------------
-#  Index of commands:
-#     - ComboBox::create
-#     - ComboBox::configure
-#     - ComboBox::cget
-#     - ComboBox::setvalue
-#     - ComboBox::getvalue
-#     - ComboBox::clearvalue
-#     - ComboBox::getentry
-#     - ComboBox::_create_popup
-#     - ComboBox::_mapliste
-#     - ComboBox::_unmapliste
-#     - ComboBox::_select
-#     - ComboBox::_modify_value
-# ----------------------------------------------------------------------------
-
-# ComboBox uses the 8.3 -listvariable listbox option
-package require Tk 8.3
-
-namespace eval ComboBox {
-    Widget::define ComboBox combobox ArrowButton Entry ListBox
-
-    Widget::tkinclude ComboBox frame :cmd \
-	include {-relief -borderwidth -bd -background} \
-	initialize {-relief sunken -borderwidth 2}
-
-    if {[Widget::theme]} {
-	Widget::bwinclude ComboBox Entry .e
-    } else {
-	Widget::bwinclude ComboBox Entry .e \
-	    remove {-relief -bd -borderwidth -bg} \
-	    rename {-background -entrybg}
-    }
-
-    Widget::declare ComboBox {
-	{-height       TkResource 0    0 listbox}
-	{-values       String	  ""   0}
-	{-images       String	  ""   0}
-	{-indents      String	  ""   0}
-	{-modifycmd    String	  ""   0}
-	{-postcommand  String	  ""   0}
-	{-expand       Enum	  none 0 {none tab}}
-	{-autocomplete Boolean	  0    0}
-        {-autopost     Boolean    0    0}
-        {-bwlistbox    Boolean    0    0}
-        {-listboxwidth Int        0    0}
-        {-hottrack     Boolean    0    0}
-    }
-
-    if {[Widget::theme]} {
-	Widget::addmap ComboBox ArrowButton .a {
-	    -background {} -state {}
-	}
-    } else {
-	Widget::addmap ComboBox ArrowButton .a {
-	    -background {} -foreground {} -disabledforeground {} -state {}
-	}
-    }
-
-    Widget::syncoptions ComboBox Entry .e {-text {}}
-
-    ::bind BwComboBox <FocusIn> [list after idle {BWidget::refocus %W %W.e}]
-    ::bind BwComboBox <Destroy> [list ComboBox::_destroy %W]
-
-    ::bind ListBoxHotTrack <Motion> {
-        %W selection clear 0 end
-        %W activate @%x,%y
-        %W selection set @%x,%y
-    }
-
-    variable _index
-}
-
-
-# ComboBox::create --
-#
-#	Create a combobox widget with the given options.
-#
-# Arguments:
-#	path	name of the new widget.
-#	args	optional arguments to the widget.
-#
-# Results:
-#	path	name of the new widget.
-
-proc ComboBox::create { path args } {
-    array set maps [list ComboBox {} :cmd {} .e {} .a {}]
-    array set maps [Widget::parseArgs ComboBox $args]
-
-    eval [list frame $path] $maps(:cmd) \
-	[list -highlightthickness 0 -takefocus 0 -class ComboBox]
-    Widget::initFromODB ComboBox $path $maps(ComboBox)
-
-    bindtags $path [list $path BwComboBox [winfo toplevel $path] all]
-
-    if {[Widget::theme]} {
-        set entry [eval [list Entry::create $path.e] $maps(.e) \
-            [list -takefocus 1]]
-    } else {
-        set entry [eval [list Entry::create $path.e] $maps(.e) \
-            [list -relief flat -borderwidth 0 -takefocus 1]]
-    }
-
-    ::bind $path.e <FocusOut>      [list $path _focus_out]
-    ::bind $path   <<TraverseIn>>  [list $path _traverse_in]
-
-    if {[Widget::cget $path -autocomplete]} {
-	::bind $path.e <KeyRelease> [list $path _auto_complete %K]
-    }
-
-    if {[Widget::cget $path -autopost]} {
-        ::bind $path.e <KeyRelease> +[list $path _auto_post %K]
-    } else {
-        ::bind $entry <Key-Up>	  [list ComboBox::_unmapliste $path]
-        ::bind $entry <Key-Down>  [list ComboBox::_mapliste $path]
-    }
-
-    if {[string equal [tk windowingsystem] "x11"]} {
-	set ipadx 0
-	set width 11
-    } else {
-	set ipadx 2
-	set width 15
-    }
-    set height [winfo reqheight $entry]
-    set arrow [eval [list ArrowButton::create $path.a] $maps(.a) \
-		   [list -width $width -height $height \
-			-highlightthickness 0 -borderwidth 1 -takefocus 0 \
-			-dir bottom -type  button -ipadx $ipadx \
-			-command [list ComboBox::_mapliste $path] \
-		       ]]
-
-    pack $arrow -side right -fill y
-    pack $entry -side left  -fill both -expand yes
-
-    set editable [Widget::cget $path -editable]
-    Entry::configure $path.e -editable $editable
-    if {$editable} {
-	::bind $entry <ButtonPress-1> [list ComboBox::_unmapliste $path]
-    } else {
-	::bind $entry <ButtonPress-1> [list ArrowButton::invoke $path.a]
-	if { ![string equal [Widget::cget $path -state] "disabled"] } {
-	    Entry::configure $path.e -takefocus 1
-	}
-    }
-
-    ::bind $path  <ButtonPress-1> [list ComboBox::_unmapliste $path]
-    ::bind $entry <Control-Up>	  [list ComboBox::_modify_value $path previous]
-    ::bind $entry <Control-Down>  [list ComboBox::_modify_value $path next]
-    ::bind $entry <Control-Prior> [list ComboBox::_modify_value $path first]
-    ::bind $entry <Control-Next>  [list ComboBox::_modify_value $path last]
-
-    if {$editable} {
-	set expand [Widget::cget $path -expand]
-	if {[string equal "tab" $expand]} {
-	    # Expand entry value on Tab (from -values)
-	    ::bind $entry <Tab> "[list ComboBox::_expand $path]; break"
-	} elseif {[string equal "auto" $expand]} {
-	    # Expand entry value anytime (from -values)
-	    #::bind $entry <Key> "[list ComboBox::_expand $path]; break"
-	}
-    }
-
-    ## If we have images, we have to use a BWidget ListBox.
-    set bw [Widget::cget $path -bwlistbox]
-    if {[llength [Widget::cget $path -images]]} {
-        Widget::configure $path [list -bwlistbox 1]
-    } else {
-        Widget::configure $path [list -bwlistbox $bw]
-    }
-
-    set ComboBox::_index($path) -1
-
-    return [Widget::create ComboBox $path]
-}
-
-
-# ComboBox::configure --
-#
-#	Configure subcommand for ComboBox widgets.  Works like regular
-#	widget configure command.
-#
-# Arguments:
-#	path	Name of the ComboBox widget.
-#	args	Additional optional arguments:
-#			?-option?
-#			?-option value ...?
-#
-# Results:
-#	Depends on arguments.  If no arguments are given, returns a complete
-#	list of configuration information.  If one argument is given, returns
-#	the configuration information for that option.  If more than one
-#	argument is given, returns nothing.
-
-proc ComboBox::configure { path args } {
-    set res [Widget::configure $path $args]
-    set entry $path.e
-
-
-    set list [list -images -values -bwlistbox -hottrack -autocomplete -autopost]
-    foreach {ci cv cb ch cac cap} [eval [linsert $list 0 Widget::hasChangedX $path]] { break }
-
-    if { $ci } {
-        set images [Widget::cget $path -images]
-        if {[llength $images]} {
-            Widget::configure $path [list -bwlistbox 1]
-        } else {
-            Widget::configure $path [list -bwlistbox 0]
-        }
-    }
-
-    ## If autocomplete toggled, turn bindings on/off
-    if { $cac } {
-        if {[Widget::cget $path -autocomplete]} {
-            ::bind $entry <KeyRelease> +[list $path _auto_complete %K]
-        } else {
-            set bindings [split [::bind $entry <KeyRelease>] \n]
-            if {[set idx [lsearch $bindings [list $path _auto_complete %K]]] != -1} {
-                ::bind $entry <KeyRelease> [join [lreplace $bindings $idx $idx] \n]
-            }
-        }
-    }
-
-    ## If autopost toggled, turn bindings on/off
-    if { $cap } {
-        if {[Widget::cget $path -autopost]} {
-            ::bind $entry <KeyRelease> +[list $path _auto_post %K]
-            set bindings [split [::bind $entry <Key-Up>] \n]
-            if {[set idx [lsearch $bindings [list ComboBox::_unmapliste $path]]] != -1} {
-                ::bind $entry <Key-Up> [join [lreplace $bindings $idx $idx] \n]
-            }
-            set bindings [split [::bind $entry <Key-Down>] \n]
-            if {[set idx [lsearch $bindings [list ComboBox::_mapliste $path]]] != -1} {
-                ::bind $entry <Key-Down> [join [lreplace $bindings $idx $idx] \n]
-            }
-        } else {
-            set bindings [split [::bind $entry <KeyRelease>] \n]
-            if {[set idx [lsearch $bindings [list $path _auto_post %K]]] != -1} {
-                ::bind $entry <KeyRelease> [join [lreplace $bindings $idx $idx] \n]
-            }
-            ::bind $entry <Key-Up> +[list ComboBox::_unmapliste $path]
-            ::bind $entry <Key-Down> +[list ComboBox::_mapliste $path]
-        }
-    }
-
-    set bw [Widget::cget $path -bwlistbox]
-
-    ## If the images, bwlistbox, hottrack or values have changed,
-    ## destroy the shell so that it will re-create itself the next
-    ## time around.
-    if { $ci || $cb || $ch || ($bw && $cv) } {
-        destroy $path.shell
-    }
-
-    set chgedit [Widget::hasChangedX $path -editable]
-    if {$chgedit} {
-        if {[Widget::cget $path -editable]} {
-            ::bind $entry <ButtonPress-1> [list ComboBox::_unmapliste $path]
-	    Entry::configure $entry -editable true
-	} else {
-	    ::bind $entry <ButtonPress-1> [list ArrowButton::invoke $path.a]
-	    Entry::configure $entry -editable false
-
-	    # Make sure that non-editable comboboxes can still be tabbed to.
-
-	    if { ![string equal [Widget::cget $path -state] "disabled"] } {
-		Entry::configure $entry -takefocus 1
-	    }
-        }
-    }
-
-    if {$chgedit || [Widget::hasChangedX $path -expand]} {
-	# Unset what we may have created.
-	::bind $entry <Tab> {}
-	if {[Widget::cget $path -editable]} {
-	    set expand [Widget::cget $path -expand]
-	    if {[string equal "tab" $expand]} {
-		# Expand entry value on Tab (from -values)
-		::bind $entry <Tab> "[list ComboBox::_expand $path]; break"
-	    } elseif {[string equal "auto" $expand]} {
-		# Expand entry value anytime (from -values)
-		#::bind $entry <Key> "[list ComboBox::_expand $path]; break"
-	    }
-	}
-    }
-
-    # if state changed to normal and -editable false, the edit must take focus
-    if {    [Widget::hasChangedX $path -state] \
-        && ![string equal [Widget::cget $path -state] "disabled"] \
-        && ![Widget::cget $path -editable] } {
-        Entry::configure $entry -takefocus 1
-    }
-
-    # if the dropdown listbox is shown, simply force the actual entry
-    #  colors into it. If it is not shown, the next time the dropdown
-    #  is shown it'll get the actual colors anyway
-    if {[winfo exists $path.shell.listb]} {
-	if {[Widget::theme]} {
-	    $path.shell.listb configure \
-		-fg [_getfg $path]
-	} else {
-	    $path.shell.listb configure \
-		-bg [Widget::cget $path -entrybg] \
-		-fg [Widget::cget $path -foreground] \
-		-selectbackground [Widget::cget $path -selectbackground] \
-		-selectforeground [Widget::cget $path -selectforeground]
-	}
-    }
-
-    return $res
-}
-
-
-# ----------------------------------------------------------------------------
-#  Command ComboBox::cget
-# ----------------------------------------------------------------------------
-proc ComboBox::cget { path option } {
-    return [Widget::cget $path $option]
-}
-
-
-# ----------------------------------------------------------------------------
-#  Command ComboBox::setvalue
-# ----------------------------------------------------------------------------
-proc ComboBox::setvalue { path index } {
-    variable _index
-
-    set values [Widget::getMegawidgetOption $path -values]
-    set value  [Entry::cget $path.e -text]
-    switch -- $index {
-        next {
-            if { [set idx [lsearch -exact $values $value]] != -1 } {
-                incr idx
-            } else {
-                set idx [lsearch -exact $values "$value*"]
-            }
-        }
-        previous {
-            if { [set idx [lsearch -exact $values $value]] != -1 } {
-                incr idx -1
-            } else {
-                set idx [lsearch -exact $values "$value*"]
-            }
-        }
-        first {
-            set idx 0
-        }
-        last {
-            set idx [expr {[llength $values]-1}]
-        }
-        default {
-            if { [string index $index 0] == "@" } {
-                set idx [string range $index 1 end]
-		if { ![string is integer -strict $idx] } {
-                    return -code error "bad index \"$index\""
-                }
-            } else {
-                return -code error "bad index \"$index\""
-            }
-        }
-    }
-    if { $idx >= 0 && $idx < [llength $values] } {
-        set newval [lindex $values $idx]
-        set _index($path) $idx
-	Entry::configure $path.e -text $newval
-        return 1
-    }
-    return 0
-}
-
-
-proc ComboBox::icursor { path idx } {
-    return [$path.e icursor $idx]
-}
-
-
-proc ComboBox::get { path } {
-    return [$path.e get]
-}
-
-
-# ----------------------------------------------------------------------------
-#  Command ComboBox::getvalue
-# ----------------------------------------------------------------------------
-proc ComboBox::getvalue { path } {
-    variable _index
-    set values [Widget::getMegawidgetOption $path -values]
-    set value  [Entry::cget $path.e -text]
-    # Check if an index was saved by the last setvalue operation
-    # If this index still matches it is returned
-    # This is necessary for the case when values is not unique
-    if { $_index($path) >= 0 \
-        && $_index($path) < [llength $values] \
-        && $value eq [lindex $values $_index($path)]} {
-        return $_index($path)
-    }
-
-    return [lsearch -exact $values $value]
-}
-
-
-proc ComboBox::getlistbox { path } {
-    _create_popup $path
-    return $path.shell.listb
-}
-
-
-# ----------------------------------------------------------------------------
-#  Command ComboBox::post
-# ----------------------------------------------------------------------------
-proc ComboBox::post { path } {
-    _mapliste $path
-    return
-}
-
-
-proc ComboBox::unpost { path } {
-    _unmapliste $path
-    return
-}
-
-
-# ----------------------------------------------------------------------------
-#  Command ComboBox::bind
-# ----------------------------------------------------------------------------
-proc ComboBox::bind { path args } {
-    return [eval [list ::bind $path.e] $args]
-}
-
-
-proc ComboBox::insert { path idx args } {
-    upvar #0 [Widget::varForOption $path -values] values
-
-    if {[Widget::cget $path -bwlistbox]} {
-        set l [$path getlistbox]
-        set i [eval [linsert $args 0 $l insert $idx #auto]]
-        set text [$l itemcget $i -text]
-        if {$idx == "end"} {
-            lappend values $text
-        } else {
-            set values [linsert $values $idx $text]
-        }
-    } else {
-        set values [eval [list linsert $values $idx] $args]
-    }
-}
-
-# ----------------------------------------------------------------------------
-#  Command ComboBox::clearvalue
-# ----------------------------------------------------------------------------
-proc ComboBox::clearvalue { path } {
-    Entry::configure $path.e -text ""
-}
-
-# ----------------------------------------------------------------------------
-#  Command ComboBox::getentry
-# ----------------------------------------------------------------------------
-proc ComboBox::getentry { path } {
-    return $path.e
-}
-
-proc ComboBox::_getfg {path} {
-    # First try to retrieve option
-    set fg [Widget::cget $path -foreground];
-    if { 0 == [string length $fg] && [Widget::theme] } {
-	# fall back to style settings when not configured for widget
-	return [::ttk::style lookup TEntry -foreground];
-    }
-    return $fg;
-}
-# ----------------------------------------------------------------------------
-#  Command ComboBox::_create_popup
-# ----------------------------------------------------------------------------
-proc ComboBox::_create_popup { path } {
-    set shell $path.shell
-
-    if {[winfo exists $shell]} { return }
-
-    set lval   [Widget::cget $path -values]
-    set h      [Widget::cget $path -height]
-    set bw     [Widget::cget $path -bwlistbox]
-
-    if { $h <= 0 } {
-	set len [llength $lval]
-	if { $len < 3 } {
-	    set h 3
-	} elseif { $len > 10 } {
-	    set h 10
-	} else {
-	    set h $len
-	}
-    }
-
-    if {[string equal [tk windowingsystem] "x11"]} {
-	set sbwidth 11
-    } else {
-	set sbwidth 15
-    }
-
-    toplevel            $shell -relief solid -bd 1
-    wm withdraw         $shell
-    wm overrideredirect $shell 1
-    # these commands cause the combobox to behave strangely on OS X
-    if {! $Widget::_aqua } {
-        update idle
-        wm transient    $shell [winfo toplevel $path]
-        catch { wm attributes $shell -topmost 1 }
-    }
-
-    set sw [ScrolledWindow $shell.sw -managed 1 -size $sbwidth -ipad 0]
-
-    if {$bw} {
-        if {[Widget::theme]} {
-            set listb  [ListBox $shell.listb \
-                    -relief flat -borderwidth 0 -highlightthickness 0 \
-                    -selectmode single -selectfill 1 -autofocus 0 -height $h \
-                    -font [Widget::cget $path -font]  \
-                    -bg [Widget::cget $path -entrybg] \
-                    -fg [_getfg $path]]
-        } else {
-            set listb  [ListBox $shell.listb \
-                    -relief flat -borderwidth 0 -highlightthickness 0 \
-                    -selectmode single -selectfill 1 -autofocus 0 -height $h \
-                    -font [Widget::cget $path -font]  \
-                    -bg [Widget::cget $path -entrybg] \
-                    -fg [Widget::cget $path -foreground] \
-                    -selectbackground [Widget::cget $path -selectbackground] \
-                    -selectforeground [Widget::cget $path -selectforeground]]
-        }
-
-        set values [Widget::cget $path -values]
-        set images [Widget::cget $path -images]
-        foreach value $values image $images {
-            $listb insert end #auto -text $value -image $image
-        }
-	$listb bindText  <1> [list ComboBox::_select $path]
-	$listb bindImage <1> [list ComboBox::_select $path]
-        if {[Widget::cget $path -hottrack]} {
-            $listb bindText  <Enter> [list $listb selection set]
-            $listb bindImage <Enter> [list $listb selection set]
-        }
-    } else {
-        if {[Widget::theme]} {
-            set listb  [listbox $shell.listb \
-                    -relief flat -borderwidth 0 -highlightthickness 0 \
-                    -exportselection false \
-                    -font	[Widget::cget $path -font]  \
-                    -height $h \
-                    -fg [_getfg $path] \
-                    -listvariable [Widget::varForOption $path -values]]
-        } else {
-            set listb  [listbox $shell.listb \
-                    -relief flat -borderwidth 0 -highlightthickness 0 \
-                    -exportselection false \
-                    -font	[Widget::cget $path -font]  \
-                    -height $h \
-                    -bg [Widget::cget $path -entrybg] \
-                    -fg [Widget::cget $path -foreground] \
-                    -selectbackground [Widget::cget $path -selectbackground] \
-                    -selectforeground [Widget::cget $path -selectforeground] \
-                    -listvariable [Widget::varForOption $path -values]]
-        }
-        ::bind $listb <ButtonRelease-1> [list ComboBox::_select $path @%x,%y]
-
-        if {[Widget::cget $path -hottrack]} {
-            bindtags $listb [concat [bindtags $listb] ListBoxHotTrack]
-        }
-    }
-    pack $sw -fill both -expand yes
-    $sw setwidget $listb
-
-    ::bind $listb <Return> "ComboBox::_select [list $path] \[$listb curselection\]"
-    ::bind $listb <Escape>   [list ComboBox::_unmapliste $path]
-    ::bind $listb <FocusOut> [list ComboBox::_focus_out $path]
-}
-
-
-proc ComboBox::_recreate_popup { path } {
-    variable background
-    variable foreground
-
-    set shell $path.shell
-    set lval  [Widget::cget $path -values]
-    set h     [Widget::cget $path -height]
-    set bw    [Widget::cget $path -bwlistbox]
-
-    if { $h <= 0 } {
-	set len [llength $lval]
-	if { $len < 3 } {
-	    set h 3
-	} elseif { $len > 10 } {
-	    set h 10
-	} else {
-	    set h $len
-	}
-    }
-
-    if { [string equal [tk windowingsystem] "x11"] } {
-	set sbwidth 11
-    } else {
-	set sbwidth 15
-    }
-
-    _create_popup $path
-
-    if {![Widget::cget $path -editable]} {
-        if {[info exists background]} {
-            $path.e configure -bg $background
-            $path.e configure -fg $foreground
-            unset background
-            unset foreground
-        }
-    }
-
-    set listb $shell.listb
-    destroy $shell.sw
-    set sw [ScrolledWindow $shell.sw -managed 1 -size $sbwidth -ipad 0]
-    $listb configure \
-            -height $h \
-            -font   [Widget::cget $path -font] \
-            -fg     [_getfg $path]
-    if {![Widget::theme]} {
-        $listb configure \
-                -bg [Widget::cget $path -entrybg] \
-                -selectbackground [Widget::cget $path -selectbackground] \
-                -selectforeground [Widget::cget $path -selectforeground]
-    }
-    pack $sw -fill both -expand yes
-    $sw setwidget $listb
-    raise $listb
-}
-
-
-# ----------------------------------------------------------------------------
-#  Command ComboBox::_mapliste
-# ----------------------------------------------------------------------------
-proc ComboBox::_mapliste { path } {
-    set listb $path.shell.listb
-    if {[winfo exists $path.shell] &&
-        [string equal [wm state $path.shell] "normal"]} {
-	_unmapliste $path
-        return
-    }
-
-    if { [Widget::cget $path -state] == "disabled" } {
-        return
-    }
-    if {[llength [set cmd [Widget::getMegawidgetOption $path -postcommand]]]} {
-        uplevel \#0 $cmd
-    }
-    if { ![llength [Widget::getMegawidgetOption $path -values]] } {
-        return
-    }
-
-    _recreate_popup $path
-
-    ArrowButton::configure $path.a -relief sunken
-    update
-
-    set bw [Widget::cget $path -bwlistbox]
-
-    $listb selection clear 0 end
-    set values [Widget::getMegawidgetOption $path -values]
-    set curval [Entry::cget $path.e -text]
-    if { [set idx [lsearch -exact $values $curval]] != -1 ||
-         [set idx [lsearch -exact $values "$curval*"]] != -1 } {
-        if {$bw} {
-            set idx [$listb items $idx]
-        } else {
-            $listb activate $idx
-        }
-        $listb selection set $idx
-        $listb see $idx
-    } else {
-        set idx 0
-        if {$bw} {
-            set idx [$listb items 0]
-        } else {
-            $listb activate $idx
-        }
-	$listb selection set $idx
-        $listb see $idx
-    }
-
-    set width [Widget::cget $path -listboxwidth]
-    if {!$width} { set width [winfo width $path] }
-    BWidget::place $path.shell $width 0 below $path
-    wm deiconify $path.shell
-    raise $path.shell
-    BWidget::focus set $listb
-    if {! $Widget::_aqua } {
-        BWidget::grab global $path
-    }
-}
-
-
-# ----------------------------------------------------------------------------
-#  Command ComboBox::_unmapliste
-# ----------------------------------------------------------------------------
-proc ComboBox::_unmapliste { path {refocus 1} } {
-    # On aqua, state is zoomed, otherwise normal
-    if {[winfo exists $path.shell] && \
-      ( [string equal [wm state $path.shell] "normal"] ||
-	[string equal [wm state $path.shell] "zoomed"] ) } {
-        if {! $Widget::_aqua } {
-            BWidget::grab release $path
-            BWidget::focus release $path.shell.listb $refocus
-            # Update now because otherwise [focus -force...] makes the app hang!
-            if {$refocus} {
-                update
-                focus -force $path.e
-            }
-        }
-        wm withdraw $path.shell
-        ArrowButton::configure $path.a -relief raised
-    }
-}
-
-
-# ----------------------------------------------------------------------------
-#  Command ComboBox::_select
-# ----------------------------------------------------------------------------
-proc ComboBox::_select { path index } {
-    set index [$path.shell.listb index $index]
-    _unmapliste $path
-    if { $index != -1 } {
-        if { [setvalue $path @$index] } {
-	    set cmd [Widget::getMegawidgetOption $path -modifycmd]
-            if {[llength $cmd]} {
-                uplevel \#0 $cmd
-            }
-        }
-    }
-    $path.e selection clear
-    if {[$path.e cget -exportselection]} {
-        $path.e selection range 0 end
-    }
-}
-
-
-# ----------------------------------------------------------------------------
-#  Command ComboBox::_modify_value
-# ----------------------------------------------------------------------------
-proc ComboBox::_modify_value { path direction } {
-    if {[setvalue $path $direction]
-        && [llength [set cmd [Widget::getMegawidgetOption $path -modifycmd]]]} {
-	uplevel \#0 $cmd
-    }
-}
-
-# ----------------------------------------------------------------------------
-#  Command ComboBox::_expand
-# ----------------------------------------------------------------------------
-proc ComboBox::_expand {path} {
-    set values [Widget::getMegawidgetOption $path -values]
-    if {![llength $values]} {
-	bell
-	return 0
-    }
-
-    set found  {}
-    set curval [Entry::cget $path.e -text]
-    set curlen [$path.e index insert]
-    if {$curlen < [string length $curval]} {
-	# we are somewhere in the middle of a string.
-	# if the full value matches some string in the listbox,
-	# reorder values to start matching after that string.
-	set idx [lsearch -exact $values $curval]
-	if {$idx >= 0} {
-	    set values [concat [lrange $values [expr {$idx+1}] end] \
-			    [lrange $values 0 $idx]]
-	}
-    }
-    if {$curlen == 0} {
-	set found $values
-    } else {
-	foreach val $values {
-	    if {[string equal -length $curlen $curval $val]} {
-		lappend found $val
-	    }
-	}
-    }
-    if {[llength $found]} {
-	Entry::configure $path.e -text [lindex $found 0]
-	if {[llength $found] > 1} {
-	    set best [_best_match $found [string range $curval 0 $curlen]]
-	    set blen [string length $best]
-	    $path.e icursor $blen
-	    $path.e selection range $blen end
-	}
-    } else {
-	bell
-    }
-    return [llength $found]
-}
-
-# best_match --
-#   finds the best unique match in a list of names
-#   The extra $e in this argument allows us to limit the innermost loop a
-#   little further.
-# Arguments:
-#   l		list to find best unique match in
-#   e		currently best known unique match
-# Returns:
-#   longest unique match in the list
-#
-proc ComboBox::_best_match {l {e {}}} {
-    set ec [lindex $l 0]
-    if {[llength $l]>1} {
-	set e  [string length $e]; incr e -1
-	set ei [string length $ec]; incr ei -1
-	foreach l $l {
-	    while {$ei>=$e && [string first $ec $l]} {
-		set ec [string range $ec 0 [incr ei -1]]
-	    }
-	}
-    }
-    return $ec
-}
-# possibly faster
-#proc match {string1 string2} {
-#   set i 1
-#   while {[string equal -length $i $string1 $string2]} { incr i }
-#   return [string range $string1 0 [expr {$i-2}]]
-#}
-#proc matchlist {list} {
-#   set list [lsort $list]
-#   return [match [lindex $list 0] [lindex $list end]]
-#}
-
-
-# ----------------------------------------------------------------------------
-#  Command ComboBox::_traverse_in
-#  Called when widget receives keyboard focus due to keyboard traversal.
-# ----------------------------------------------------------------------------
-proc ComboBox::_traverse_in { path } {
-    if {[$path.e selection present] != 1} {
-	# Autohighlight the selection, but not if one existed
-	$path.e selection range 0 end
-    }
-}
-
-
-# ----------------------------------------------------------------------------
-#  Command ComboBox::_focus_out
-# ----------------------------------------------------------------------------
-proc ComboBox::_focus_out { path } {
-    if {[string first $path [focus]] != 0} {
-	# we lost focus to some other app or window, so remove the listbox
-	return [_unmapliste $path 0]
-    }
-}
-
-proc ComboBox::_auto_complete { path key } {
-    ## Any key string with more than one character and is not entirely
-    ## lower-case is considered a function key and is thus ignored.
-    if {[string length $key] > 1 && [string tolower $key] != $key} { return }
-
-    set text [string map [list {[} {\[} {]} {\]}] [$path.e get]]
-    if {[string equal $text ""]} { return }
-    set values [Widget::cget $path -values]
-    set x [lsearch $values $text*]
-    if {$x < 0} { return }
-
-    set idx [$path.e index insert]
-    $path.e configure -text [lindex $values $x]
-    $path.e icursor $idx
-    $path.e select range insert end
-}
-
-proc ComboBox::_auto_post { path key } {
-    if {[string equal $key "Escape"] || [string equal $key "Return"]} {
-        _unmapliste $path
-        return
-    }
-    if {[catch {$path.shell.listb curselection} x] || $x == ""} {
-        if {[string equal $key "Up"]} {
-            _unmapliste $path
-            return
-        }
-        set x -1
-    }
-    if {([string length $key] > 1 && [string tolower $key] != $key) && \
-            [string equal $key "BackSpace"] != 0 && \
-            [string equal $key "Up"] != 0 && \
-            [string equal $key "Down"] != 0} {
-        return
-    }
-
-    # post the listbox
-    _create_popup $path
-    set width [Widget::cget $path -listboxwidth]
-    if {!$width} { set width [winfo width $path] }
-    BWidget::place $path.shell $width 0 below $path
-    wm deiconify $path.shell
-    BWidget::grab release $path
-    BWidget::focus release $path.shell.listb 1
-    focus -force $path.e
-
-    set values [Widget::cget $path -values]
-    switch -- $key {
-        Up {
-            if {[incr x -1] < 0} {
-                set x 0
-            } else {
-                Entry::configure $path.e -text [lindex $values $x]
-            }
-        }
-        Down {
-            if {[incr x] >= [llength $values]} {
-                set x [expr {[llength $values] - 1}]
-            } else {
-                Entry::configure $path.e -text [lindex $values $x]
-            }
-        }
-        default {
-            # auto-select within the listbox the item closest to the entry's value
-            set text [string map [list {[} {\[} {]} {\]}] [$path.e get]]
-            if {[string equal $text ""]} {
-                set x 0
-            } else {
-                set x [lsearch $values $text*]
-            }
-        }
-    }
-
-    if {$x >= 0} {
-        $path.shell.listb selection clear 0 end
-        $path.shell.listb selection set $x
-        $path.shell.listb see $x
-    }
-}
-# ------------------------------------------------------------------------------
-#  Command ComboBox::_destroy
-# ------------------------------------------------------------------------------
-proc ComboBox::_destroy { path } {
-    variable _index
-    Widget::destroy $path
-    unset _index($path)
-}
+# ----------------------------------------------------------------------------
+#  combobox.tcl
+#  This file is part of Unifix BWidget Toolkit
+#  $Id: combobox.tcl,v 1.42.2.3 2012/04/02 09:53:41 oehhar Exp $
+# ----------------------------------------------------------------------------
+#  Index of commands:
+#     - ComboBox::create
+#     - ComboBox::configure
+#     - ComboBox::cget
+#     - ComboBox::setvalue
+#     - ComboBox::getvalue
+#     - ComboBox::clearvalue
+#     - ComboBox::getentry
+#     - ComboBox::_create_popup
+#     - ComboBox::_mapliste
+#     - ComboBox::_unmapliste
+#     - ComboBox::_select
+#     - ComboBox::_modify_value
+# ----------------------------------------------------------------------------
+
+# ComboBox uses the 8.3 -listvariable listbox option
+package require Tk 8.3
+
+namespace eval ComboBox {
+    Widget::define ComboBox combobox ArrowButton Entry ListBox
+
+    Widget::tkinclude ComboBox frame :cmd \
+	include {-relief -borderwidth -bd -background} \
+	initialize {-relief sunken -borderwidth 2}
+
+    if {[Widget::theme]} {
+	Widget::bwinclude ComboBox Entry .e
+    } else {
+	Widget::bwinclude ComboBox Entry .e \
+	    remove {-relief -bd -borderwidth -bg} \
+	    rename {-background -entrybg}
+    }
+
+    Widget::declare ComboBox {
+	{-height       TkResource 0    0 listbox}
+	{-values       String	  ""   0}
+	{-images       String	  ""   0}
+	{-indents      String	  ""   0}
+	{-modifycmd    String	  ""   0}
+	{-postcommand  String	  ""   0}
+	{-expand       Enum	  none 0 {none tab}}
+	{-autocomplete Boolean	  0    0}
+        {-autopost     Boolean    0    0}
+        {-bwlistbox    Boolean    0    0}
+        {-listboxwidth Int        0    0}
+        {-hottrack     Boolean    0    0}
+    }
+
+    if {[Widget::theme]} {
+	Widget::addmap ComboBox ArrowButton .a {
+	    -background {} -state {}
+	}
+    } else {
+	Widget::addmap ComboBox ArrowButton .a {
+	    -background {} -foreground {} -disabledforeground {} -state {}
+	}
+    }
+
+    Widget::syncoptions ComboBox Entry .e {-text {}}
+
+    ::bind BwComboBox <FocusIn> [list after idle {BWidget::refocus %W %W.e}]
+    ::bind BwComboBox <Destroy> [list ComboBox::_destroy %W]
+
+    ::bind ListBoxHotTrack <Motion> {
+        %W selection clear 0 end
+        %W activate @%x,%y
+        %W selection set @%x,%y
+    }
+
+    variable _index
+}
+
+
+# ComboBox::create --
+#
+#	Create a combobox widget with the given options.
+#
+# Arguments:
+#	path	name of the new widget.
+#	args	optional arguments to the widget.
+#
+# Results:
+#	path	name of the new widget.
+
+proc ComboBox::create { path args } {
+    array set maps [list ComboBox {} :cmd {} .e {} .a {}]
+    array set maps [Widget::parseArgs ComboBox $args]
+
+    eval [list frame $path] $maps(:cmd) \
+	[list -highlightthickness 0 -takefocus 0 -class ComboBox]
+    Widget::initFromODB ComboBox $path $maps(ComboBox)
+
+    bindtags $path [list $path BwComboBox [winfo toplevel $path] all]
+
+    if {[Widget::theme]} {
+        set entry [eval [list Entry::create $path.e] $maps(.e) \
+            [list -takefocus 1]]
+    } else {
+        set entry [eval [list Entry::create $path.e] $maps(.e) \
+            [list -relief flat -borderwidth 0 -takefocus 1]]
+    }
+
+    ::bind $path.e <FocusOut>      [list $path _focus_out]
+    ::bind $path   <<TraverseIn>>  [list $path _traverse_in]
+
+    if {[Widget::cget $path -autocomplete]} {
+	::bind $path.e <KeyRelease> [list $path _auto_complete %K]
+    }
+
+    if {[Widget::cget $path -autopost]} {
+        ::bind $path.e <KeyRelease> +[list $path _auto_post %K]
+    } else {
+        ::bind $entry <Key-Up>	  [list ComboBox::_unmapliste $path]
+        ::bind $entry <Key-Down>  [list ComboBox::_mapliste $path]
+    }
+
+    if {[string equal [tk windowingsystem] "x11"]} {
+	set ipadx 0
+	set width 11
+    } else {
+	set ipadx 2
+	set width 15
+    }
+    set height [winfo reqheight $entry]
+    set arrow [eval [list ArrowButton::create $path.a] $maps(.a) \
+		   [list -width $width -height $height \
+			-highlightthickness 0 -borderwidth 1 -takefocus 0 \
+			-dir bottom -type  button -ipadx $ipadx \
+			-command [list ComboBox::_mapliste $path] \
+		       ]]
+
+    pack $arrow -side right -fill y
+    pack $entry -side left  -fill both -expand yes
+
+    set editable [Widget::cget $path -editable]
+    Entry::configure $path.e -editable $editable
+    if {$editable} {
+	::bind $entry <ButtonPress-1> [list ComboBox::_unmapliste $path]
+    } else {
+	::bind $entry <ButtonPress-1> [list ArrowButton::invoke $path.a]
+	if { ![string equal [Widget::cget $path -state] "disabled"] } {
+	    Entry::configure $path.e -takefocus 1
+	}
+    }
+
+    ::bind $path  <ButtonPress-1> [list ComboBox::_unmapliste $path]
+    ::bind $entry <Control-Up>	  [list ComboBox::_modify_value $path previous]
+    ::bind $entry <Control-Down>  [list ComboBox::_modify_value $path next]
+    ::bind $entry <Control-Prior> [list ComboBox::_modify_value $path first]
+    ::bind $entry <Control-Next>  [list ComboBox::_modify_value $path last]
+
+    if {$editable} {
+	set expand [Widget::cget $path -expand]
+	if {[string equal "tab" $expand]} {
+	    # Expand entry value on Tab (from -values)
+	    ::bind $entry <Tab> "[list ComboBox::_expand $path]; break"
+	} elseif {[string equal "auto" $expand]} {
+	    # Expand entry value anytime (from -values)
+	    #::bind $entry <Key> "[list ComboBox::_expand $path]; break"
+	}
+    }
+
+    ## If we have images, we have to use a BWidget ListBox.
+    set bw [Widget::cget $path -bwlistbox]
+    if {[llength [Widget::cget $path -images]]} {
+        Widget::configure $path [list -bwlistbox 1]
+    } else {
+        Widget::configure $path [list -bwlistbox $bw]
+    }
+
+    set ComboBox::_index($path) -1
+
+    return [Widget::create ComboBox $path]
+}
+
+
+# ComboBox::configure --
+#
+#	Configure subcommand for ComboBox widgets.  Works like regular
+#	widget configure command.
+#
+# Arguments:
+#	path	Name of the ComboBox widget.
+#	args	Additional optional arguments:
+#			?-option?
+#			?-option value ...?
+#
+# Results:
+#	Depends on arguments.  If no arguments are given, returns a complete
+#	list of configuration information.  If one argument is given, returns
+#	the configuration information for that option.  If more than one
+#	argument is given, returns nothing.
+
+proc ComboBox::configure { path args } {
+    set res [Widget::configure $path $args]
+    set entry $path.e
+
+
+    set list [list -images -values -bwlistbox -hottrack -autocomplete -autopost]
+    foreach {ci cv cb ch cac cap} [eval [linsert $list 0 Widget::hasChangedX $path]] { break }
+
+    if { $ci } {
+        set images [Widget::cget $path -images]
+        if {[llength $images]} {
+            Widget::configure $path [list -bwlistbox 1]
+        } else {
+            Widget::configure $path [list -bwlistbox 0]
+        }
+    }
+
+    ## If autocomplete toggled, turn bindings on/off
+    if { $cac } {
+        if {[Widget::cget $path -autocomplete]} {
+            ::bind $entry <KeyRelease> +[list $path _auto_complete %K]
+        } else {
+            set bindings [split [::bind $entry <KeyRelease>] \n]
+            if {[set idx [lsearch $bindings [list $path _auto_complete %K]]] != -1} {
+                ::bind $entry <KeyRelease> [join [lreplace $bindings $idx $idx] \n]
+            }
+        }
+    }
+
+    ## If autopost toggled, turn bindings on/off
+    if { $cap } {
+        if {[Widget::cget $path -autopost]} {
+            ::bind $entry <KeyRelease> +[list $path _auto_post %K]
+            set bindings [split [::bind $entry <Key-Up>] \n]
+            if {[set idx [lsearch $bindings [list ComboBox::_unmapliste $path]]] != -1} {
+                ::bind $entry <Key-Up> [join [lreplace $bindings $idx $idx] \n]
+            }
+            set bindings [split [::bind $entry <Key-Down>] \n]
+            if {[set idx [lsearch $bindings [list ComboBox::_mapliste $path]]] != -1} {
+                ::bind $entry <Key-Down> [join [lreplace $bindings $idx $idx] \n]
+            }
+        } else {
+            set bindings [split [::bind $entry <KeyRelease>] \n]
+            if {[set idx [lsearch $bindings [list $path _auto_post %K]]] != -1} {
+                ::bind $entry <KeyRelease> [join [lreplace $bindings $idx $idx] \n]
+            }
+            ::bind $entry <Key-Up> +[list ComboBox::_unmapliste $path]
+            ::bind $entry <Key-Down> +[list ComboBox::_mapliste $path]
+        }
+    }
+
+    set bw [Widget::cget $path -bwlistbox]
+
+    ## If the images, bwlistbox, hottrack or values have changed,
+    ## destroy the shell so that it will re-create itself the next
+    ## time around.
+    if { $ci || $cb || $ch || ($bw && $cv) } {
+        destroy $path.shell
+    }
+
+    set chgedit [Widget::hasChangedX $path -editable]
+    if {$chgedit} {
+        if {[Widget::cget $path -editable]} {
+            ::bind $entry <ButtonPress-1> [list ComboBox::_unmapliste $path]
+	    Entry::configure $entry -editable true
+	} else {
+	    ::bind $entry <ButtonPress-1> [list ArrowButton::invoke $path.a]
+	    Entry::configure $entry -editable false
+
+	    # Make sure that non-editable comboboxes can still be tabbed to.
+
+	    if { ![string equal [Widget::cget $path -state] "disabled"] } {
+		Entry::configure $entry -takefocus 1
+	    }
+        }
+    }
+
+    if {$chgedit || [Widget::hasChangedX $path -expand]} {
+	# Unset what we may have created.
+	::bind $entry <Tab> {}
+	if {[Widget::cget $path -editable]} {
+	    set expand [Widget::cget $path -expand]
+	    if {[string equal "tab" $expand]} {
+		# Expand entry value on Tab (from -values)
+		::bind $entry <Tab> "[list ComboBox::_expand $path]; break"
+	    } elseif {[string equal "auto" $expand]} {
+		# Expand entry value anytime (from -values)
+		#::bind $entry <Key> "[list ComboBox::_expand $path]; break"
+	    }
+	}
+    }
+
+    # if state changed to normal and -editable false, the edit must take focus
+    if {    [Widget::hasChangedX $path -state] \
+        && ![string equal [Widget::cget $path -state] "disabled"] \
+        && ![Widget::cget $path -editable] } {
+        Entry::configure $entry -takefocus 1
+    }
+
+    # if the dropdown listbox is shown, simply force the actual entry
+    #  colors into it. If it is not shown, the next time the dropdown
+    #  is shown it'll get the actual colors anyway
+    if {[winfo exists $path.shell.listb]} {
+	$path.shell.listb configure \
+	    -bg [_getbg $path] \
+	    -fg [_getfg $path]
+	if {![Widget::theme]} {
+	    $path.shell.listb configure \
+		-selectbackground [Widget::cget $path -selectbackground] \
+		-selectforeground [Widget::cget $path -selectforeground]
+	}
+    }
+
+    return $res
+}
+
+
+# ----------------------------------------------------------------------------
+#  Command ComboBox::cget
+# ----------------------------------------------------------------------------
+proc ComboBox::cget { path option } {
+    return [Widget::cget $path $option]
+}
+
+
+# ----------------------------------------------------------------------------
+#  Command ComboBox::setvalue
+# ----------------------------------------------------------------------------
+proc ComboBox::setvalue { path index } {
+    variable _index
+
+    set values [Widget::getMegawidgetOption $path -values]
+    set value  [Entry::cget $path.e -text]
+    switch -- $index {
+        next {
+            if { [set idx [lsearch -exact $values $value]] != -1 } {
+                incr idx
+            } else {
+                set idx [lsearch -exact $values "$value*"]
+            }
+        }
+        previous {
+            if { [set idx [lsearch -exact $values $value]] != -1 } {
+                incr idx -1
+            } else {
+                set idx [lsearch -exact $values "$value*"]
+            }
+        }
+        first {
+            set idx 0
+        }
+        last {
+            set idx [expr {[llength $values]-1}]
+        }
+        default {
+            if { [string index $index 0] == "@" } {
+                set idx [string range $index 1 end]
+		if { ![string is integer -strict $idx] } {
+                    return -code error "bad index \"$index\""
+                }
+            } else {
+                return -code error "bad index \"$index\""
+            }
+        }
+    }
+    if { $idx >= 0 && $idx < [llength $values] } {
+        set newval [lindex $values $idx]
+        set _index($path) $idx
+	Entry::configure $path.e -text $newval
+        return 1
+    }
+    return 0
+}
+
+
+proc ComboBox::icursor { path idx } {
+    return [$path.e icursor $idx]
+}
+
+
+proc ComboBox::get { path } {
+    return [$path.e get]
+}
+
+
+# ----------------------------------------------------------------------------
+#  Command ComboBox::getvalue
+# ----------------------------------------------------------------------------
+proc ComboBox::getvalue { path } {
+    variable _index
+    set values [Widget::getMegawidgetOption $path -values]
+    set value  [Entry::cget $path.e -text]
+    # Check if an index was saved by the last setvalue operation
+    # If this index still matches it is returned
+    # This is necessary for the case when values is not unique
+    if { $_index($path) >= 0 \
+        && $_index($path) < [llength $values] \
+        && $value eq [lindex $values $_index($path)]} {
+        return $_index($path)
+    }
+
+    return [lsearch -exact $values $value]
+}
+
+
+proc ComboBox::getlistbox { path } {
+    _create_popup $path
+    return $path.shell.listb
+}
+
+
+# ----------------------------------------------------------------------------
+#  Command ComboBox::post
+# ----------------------------------------------------------------------------
+proc ComboBox::post { path } {
+    _mapliste $path
+    return
+}
+
+
+proc ComboBox::unpost { path } {
+    _unmapliste $path
+    return
+}
+
+
+# ----------------------------------------------------------------------------
+#  Command ComboBox::bind
+# ----------------------------------------------------------------------------
+proc ComboBox::bind { path args } {
+    return [eval [list ::bind $path.e] $args]
+}
+
+
+proc ComboBox::insert { path idx args } {
+    upvar #0 [Widget::varForOption $path -values] values
+
+    if {[Widget::cget $path -bwlistbox]} {
+        set l [$path getlistbox]
+        set i [eval [linsert $args 0 $l insert $idx #auto]]
+        set text [$l itemcget $i -text]
+        if {$idx == "end"} {
+            lappend values $text
+        } else {
+            set values [linsert $values $idx $text]
+        }
+    } else {
+        set values [eval [list linsert $values $idx] $args]
+    }
+}
+
+# ----------------------------------------------------------------------------
+#  Command ComboBox::clearvalue
+# ----------------------------------------------------------------------------
+proc ComboBox::clearvalue { path } {
+    Entry::configure $path.e -text ""
+}
+
+# ----------------------------------------------------------------------------
+#  Command ComboBox::getentry
+# ----------------------------------------------------------------------------
+proc ComboBox::getentry { path } {
+    return $path.e
+}
+
+proc ComboBox::_getfg {path} {
+    set res "";
+    if {[Widget::theme]} {
+	# First try to retrieve option
+	set fg [Widget::cget $path -foreground];
+	if {[string length $fg]} {
+	    set res $fg;
+	} else {
+	    # fall back to style settings when not configured for widget
+	    set res [::ttk::style lookup TEntry -foreground];
+	}
+    } else {
+	set res [Widget::cget $path -foreground]
+    }
+    return $res;
+}
+
+proc ComboBox::_getbg {path} {
+    set res "";
+    if {[Widget::theme]} {
+	# First try to retrieve option
+	set bg [Widget::cget $path -background];
+	if {[string length $bg]} {
+	    set res $bg;
+	} else {
+	    # fall back to style settings when not configured for widget
+	    set res [::ttk::style lookup TEntry -backround];
+	}
+    } else {
+	# fetch the entrybg resource value
+	set res [Widget::cget $path -entrybg]
+    }
+    return $res;
+}
+
+# ----------------------------------------------------------------------------
+#  Command ComboBox::_create_popup
+# ----------------------------------------------------------------------------
+proc ComboBox::_create_popup { path } {
+    set shell $path.shell
+
+    if {[winfo exists $shell]} { return }
+
+    set lval   [Widget::cget $path -values]
+    set h      [Widget::cget $path -height]
+    set bw     [Widget::cget $path -bwlistbox]
+
+    if { $h <= 0 } {
+	set len [llength $lval]
+	if { $len < 3 } {
+	    set h 3
+	} elseif { $len > 10 } {
+	    set h 10
+	} else {
+	    set h $len
+	}
+    }
+
+    if {[string equal [tk windowingsystem] "x11"]} {
+	set sbwidth 11
+    } else {
+	set sbwidth 15
+    }
+
+    toplevel            $shell -relief solid -bd 1
+    wm withdraw         $shell
+    wm overrideredirect $shell 1
+    # these commands cause the combobox to behave strangely on OS X
+    if {! $Widget::_aqua } {
+        update idle
+        wm transient    $shell [winfo toplevel $path]
+        catch { wm attributes $shell -topmost 1 }
+    }
+
+    set sw [ScrolledWindow $shell.sw -managed 1 -size $sbwidth -ipad 0]
+
+    if {$bw} {
+        if {[Widget::theme]} {
+            set listb \
+		[ListBox $shell.listb \
+		     -relief flat -borderwidth 0 -highlightthickness 0 \
+		     -selectmode single -selectfill 1 -autofocus 0 -height $h \
+		     -font [Widget::cget $path -font] \
+		     -bg [_getbg $path] \
+		     -fg [_getfg $path]]
+        } else {
+            set listb \
+		[ListBox $shell.listb \
+		     -relief flat -borderwidth 0 -highlightthickness 0 \
+		     -selectmode single -selectfill 1 -autofocus 0 -height $h \
+		     -font [Widget::cget $path -font]  \
+		     -bg [_getbg $path] \
+		     -fg [_getfg $path] \
+		     -selectbackground [Widget::cget $path -selectbackground] \
+		     -selectforeground [Widget::cget $path -selectforeground]]
+        }
+
+        set values [Widget::cget $path -values]
+        set images [Widget::cget $path -images]
+        foreach value $values image $images {
+            $listb insert end #auto -text $value -image $image
+        }
+	$listb bindText  <1> [list ComboBox::_select $path]
+	$listb bindImage <1> [list ComboBox::_select $path]
+        if {[Widget::cget $path -hottrack]} {
+            $listb bindText  <Enter> [list $listb selection set]
+            $listb bindImage <Enter> [list $listb selection set]
+        }
+    } else {
+        if {[Widget::theme]} {
+            set listb \
+		[listbox $shell.listb \
+		     -relief flat -borderwidth 0 -highlightthickness 0 \
+		     -exportselection false \
+		     -font	[Widget::cget $path -font]  \
+		     -height $h \
+		     -bg [_getbg $path] \
+		     -fg [_getfg $path] \
+		     -listvariable [Widget::varForOption $path -values]]
+        } else {
+            set listb \
+		[listbox $shell.listb \
+		     -relief flat -borderwidth 0 -highlightthickness 0 \
+		     -exportselection false \
+		     -font	[Widget::cget $path -font]  \
+		     -height $h \
+		     -bg [_getbg $path] \
+		     -fg [_getfg $path] \
+		     -selectbackground [Widget::cget $path -selectbackground] \
+		     -selectforeground [Widget::cget $path -selectforeground] \
+		     -listvariable [Widget::varForOption $path -values]]
+        }
+        ::bind $listb <ButtonRelease-1> [list ComboBox::_select $path @%x,%y]
+
+        if {[Widget::cget $path -hottrack]} {
+            bindtags $listb [concat [bindtags $listb] ListBoxHotTrack]
+        }
+    }
+    pack $sw -fill both -expand yes
+    $sw setwidget $listb
+
+    ::bind $listb <Return> "ComboBox::_select [list $path] \[$listb curselection\]"
+    ::bind $listb <Escape>   [list ComboBox::_unmapliste $path]
+    ::bind $listb <FocusOut> [list ComboBox::_focus_out $path]
+}
+
+
+proc ComboBox::_recreate_popup { path } {
+    variable background
+    variable foreground
+
+    set shell $path.shell
+    set lval  [Widget::cget $path -values]
+    set h     [Widget::cget $path -height]
+    set bw    [Widget::cget $path -bwlistbox]
+
+    if { $h <= 0 } {
+	set len [llength $lval]
+	if { $len < 3 } {
+	    set h 3
+	} elseif { $len > 10 } {
+	    set h 10
+	} else {
+	    set h $len
+	}
+    }
+
+    if { [string equal [tk windowingsystem] "x11"] } {
+	set sbwidth 11
+    } else {
+	set sbwidth 15
+    }
+
+    _create_popup $path
+
+    if {![Widget::cget $path -editable]} {
+        if {[info exists background]} {
+            $path.e configure -bg $background
+            $path.e configure -fg $foreground
+            unset background
+            unset foreground
+        }
+    }
+
+    set listb $shell.listb
+    destroy $shell.sw
+    set sw [ScrolledWindow $shell.sw -managed 1 -size $sbwidth -ipad 0]
+    $listb configure \
+	-height $h \
+	-font   [Widget::cget $path -font] \
+	-bg [_getbg $path] \
+	-fg     [_getfg $path]
+    if {![Widget::theme]} {
+        $listb configure \
+	    -selectbackground [Widget::cget $path -selectbackground] \
+	    -selectforeground [Widget::cget $path -selectforeground]
+    }
+    pack $sw -fill both -expand yes
+    $sw setwidget $listb
+    raise $listb
+}
+
+
+# ----------------------------------------------------------------------------
+#  Command ComboBox::_mapliste
+# ----------------------------------------------------------------------------
+proc ComboBox::_mapliste { path } {
+    set listb $path.shell.listb
+    if {[winfo exists $path.shell] &&
+        [string equal [wm state $path.shell] "normal"]} {
+	_unmapliste $path
+        return
+    }
+
+    if { [Widget::cget $path -state] == "disabled" } {
+        return
+    }
+    if {[llength [set cmd [Widget::getMegawidgetOption $path -postcommand]]]} {
+        uplevel \#0 $cmd
+    }
+    if { ![llength [Widget::getMegawidgetOption $path -values]] } {
+        return
+    }
+
+    _recreate_popup $path
+
+    ArrowButton::configure $path.a -relief sunken
+    update
+
+    set bw [Widget::cget $path -bwlistbox]
+
+    $listb selection clear 0 end
+    set values [Widget::getMegawidgetOption $path -values]
+    set curval [Entry::cget $path.e -text]
+    if { [set idx [lsearch -exact $values $curval]] != -1 ||
+         [set idx [lsearch -exact $values "$curval*"]] != -1 } {
+        if {$bw} {
+            set idx [$listb items $idx]
+        } else {
+            $listb activate $idx
+        }
+        $listb selection set $idx
+        $listb see $idx
+    } else {
+        set idx 0
+        if {$bw} {
+            set idx [$listb items 0]
+        } else {
+            $listb activate $idx
+        }
+	$listb selection set $idx
+        $listb see $idx
+    }
+
+    set width [Widget::cget $path -listboxwidth]
+    if {!$width} { set width [winfo width $path] }
+    BWidget::place $path.shell $width 0 below $path
+    wm deiconify $path.shell
+    raise $path.shell
+    BWidget::focus set $listb
+    if {! $Widget::_aqua } {
+        BWidget::grab global $path
+    }
+}
+
+
+# ----------------------------------------------------------------------------
+#  Command ComboBox::_unmapliste
+# ----------------------------------------------------------------------------
+proc ComboBox::_unmapliste { path {refocus 1} } {
+    # On aqua, state is zoomed, otherwise normal
+    if {[winfo exists $path.shell] && \
+      ( [string equal [wm state $path.shell] "normal"] ||
+	[string equal [wm state $path.shell] "zoomed"] ) } {
+        if {! $Widget::_aqua } {
+            BWidget::grab release $path
+            BWidget::focus release $path.shell.listb $refocus
+            # Update now because otherwise [focus -force...] makes the app hang!
+            if {$refocus} {
+                update
+                focus -force $path.e
+            }
+        }
+        wm withdraw $path.shell
+        ArrowButton::configure $path.a -relief raised
+    }
+}
+
+
+# ----------------------------------------------------------------------------
+#  Command ComboBox::_select
+# ----------------------------------------------------------------------------
+proc ComboBox::_select { path index } {
+    set index [$path.shell.listb index $index]
+    _unmapliste $path
+    if { $index != -1 } {
+        if { [setvalue $path @$index] } {
+	    set cmd [Widget::getMegawidgetOption $path -modifycmd]
+            if {[llength $cmd]} {
+                uplevel \#0 $cmd
+            }
+        }
+    }
+    $path.e selection clear
+    if {[$path.e cget -exportselection]} {
+        $path.e selection range 0 end
+    }
+}
+
+
+# ----------------------------------------------------------------------------
+#  Command ComboBox::_modify_value
+# ----------------------------------------------------------------------------
+proc ComboBox::_modify_value { path direction } {
+    if {[setvalue $path $direction]
+        && [llength [set cmd [Widget::getMegawidgetOption $path -modifycmd]]]} {
+	uplevel \#0 $cmd
+    }
+}
+
+# ----------------------------------------------------------------------------
+#  Command ComboBox::_expand
+# ----------------------------------------------------------------------------
+proc ComboBox::_expand {path} {
+    set values [Widget::getMegawidgetOption $path -values]
+    if {![llength $values]} {
+	bell
+	return 0
+    }
+
+    set found  {}
+    set curval [Entry::cget $path.e -text]
+    set curlen [$path.e index insert]
+    if {$curlen < [string length $curval]} {
+	# we are somewhere in the middle of a string.
+	# if the full value matches some string in the listbox,
+	# reorder values to start matching after that string.
+	set idx [lsearch -exact $values $curval]
+	if {$idx >= 0} {
+	    set values [concat [lrange $values [expr {$idx+1}] end] \
+			    [lrange $values 0 $idx]]
+	}
+    }
+    if {$curlen == 0} {
+	set found $values
+    } else {
+	foreach val $values {
+	    if {[string equal -length $curlen $curval $val]} {
+		lappend found $val
+	    }
+	}
+    }
+    if {[llength $found]} {
+	Entry::configure $path.e -text [lindex $found 0]
+	if {[llength $found] > 1} {
+	    set best [_best_match $found [string range $curval 0 $curlen]]
+	    set blen [string length $best]
+	    $path.e icursor $blen
+	    $path.e selection range $blen end
+	}
+    } else {
+	bell
+    }
+    return [llength $found]
+}
+
+# best_match --
+#   finds the best unique match in a list of names
+#   The extra $e in this argument allows us to limit the innermost loop a
+#   little further.
+# Arguments:
+#   l		list to find best unique match in
+#   e		currently best known unique match
+# Returns:
+#   longest unique match in the list
+#
+proc ComboBox::_best_match {l {e {}}} {
+    set ec [lindex $l 0]
+    if {[llength $l]>1} {
+	set e  [string length $e]; incr e -1
+	set ei [string length $ec]; incr ei -1
+	foreach l $l {
+	    while {$ei>=$e && [string first $ec $l]} {
+		set ec [string range $ec 0 [incr ei -1]]
+	    }
+	}
+    }
+    return $ec
+}
+# possibly faster
+#proc match {string1 string2} {
+#   set i 1
+#   while {[string equal -length $i $string1 $string2]} { incr i }
+#   return [string range $string1 0 [expr {$i-2}]]
+#}
+#proc matchlist {list} {
+#   set list [lsort $list]
+#   return [match [lindex $list 0] [lindex $list end]]
+#}
+
+
+# ----------------------------------------------------------------------------
+#  Command ComboBox::_traverse_in
+#  Called when widget receives keyboard focus due to keyboard traversal.
+# ----------------------------------------------------------------------------
+proc ComboBox::_traverse_in { path } {
+    if {[$path.e selection present] != 1} {
+	# Autohighlight the selection, but not if one existed
+	$path.e selection range 0 end
+    }
+}
+
+
+# ----------------------------------------------------------------------------
+#  Command ComboBox::_focus_out
+# ----------------------------------------------------------------------------
+proc ComboBox::_focus_out { path } {
+    if {[string first $path [focus]] != 0} {
+	# we lost focus to some other app or window, so remove the listbox
+	return [_unmapliste $path 0]
+    }
+}
+
+proc ComboBox::_auto_complete { path key } {
+    ## Any key string with more than one character and is not entirely
+    ## lower-case is considered a function key and is thus ignored.
+    if {[string length $key] > 1 && [string tolower $key] != $key} { return }
+
+    set text [string map [list {[} {\[} {]} {\]}] [$path.e get]]
+    if {[string equal $text ""]} { return }
+    set values [Widget::cget $path -values]
+    set x [lsearch $values $text*]
+    if {$x < 0} { return }
+
+    set idx [$path.e index insert]
+    $path.e configure -text [lindex $values $x]
+    $path.e icursor $idx
+    $path.e select range insert end
+}
+
+proc ComboBox::_auto_post { path key } {
+    if {[string equal $key "Escape"] || [string equal $key "Return"]} {
+        _unmapliste $path
+        return
+    }
+    if {[catch {$path.shell.listb curselection} x] || $x == ""} {
+        if {[string equal $key "Up"]} {
+            _unmapliste $path
+            return
+        }
+        set x -1
+    }
+    if {([string length $key] > 1 && [string tolower $key] != $key) && \
+            [string equal $key "BackSpace"] != 0 && \
+            [string equal $key "Up"] != 0 && \
+            [string equal $key "Down"] != 0} {
+        return
+    }
+
+    # post the listbox
+    _create_popup $path
+    set width [Widget::cget $path -listboxwidth]
+    if {!$width} { set width [winfo width $path] }
+    BWidget::place $path.shell $width 0 below $path
+    wm deiconify $path.shell
+    BWidget::grab release $path
+    BWidget::focus release $path.shell.listb 1
+    focus -force $path.e
+
+    set values [Widget::cget $path -values]
+    switch -- $key {
+        Up {
+            if {[incr x -1] < 0} {
+                set x 0
+            } else {
+                Entry::configure $path.e -text [lindex $values $x]
+            }
+        }
+        Down {
+            if {[incr x] >= [llength $values]} {
+                set x [expr {[llength $values] - 1}]
+            } else {
+                Entry::configure $path.e -text [lindex $values $x]
+            }
+        }
+        default {
+            # auto-select within the listbox the item closest to the entry's value
+            set text [string map [list {[} {\[} {]} {\]}] [$path.e get]]
+            if {[string equal $text ""]} {
+                set x 0
+            } else {
+                set x [lsearch $values $text*]
+            }
+        }
+    }
+
+    if {$x >= 0} {
+        $path.shell.listb selection clear 0 end
+        $path.shell.listb selection set $x
+        $path.shell.listb see $x
+    }
+}
+# ------------------------------------------------------------------------------
+#  Command ComboBox::_destroy
+# ------------------------------------------------------------------------------
+proc ComboBox::_destroy { path } {
+    variable _index
+    Widget::destroy $path
+    unset _index($path)
+}