home *** CD-ROM | disk | FTP | other *** search
/ PC World 2000 December / PCWorld_2000-12_cd.bin / Komunikace / Comanche / comanche.exe / lib / iwidgets3.0.0 / scripts / combobox.itk < prev    next >
Text File  |  1999-02-24  |  42KB  |  1,340 lines

  1. # Combobox
  2. # ----------------------------------------------------------------------
  3. # Implements a Combobox widget. A Combobox has 2 basic styles: simple and
  4. # dropdown. Dropdowns display an entry field with an arrow button to the 
  5. # right of it. When the arrow button is pressed a selectable list of
  6. # items is popped up. A simple Combobox displays an entry field and a listbox 
  7. # just beneath it which is always displayed. In both types, if the user 
  8. # selects an item in the listbox, the contents of the entry field are 
  9. # replaced with the text from the selected item. If the Combobox is 
  10. # editable, the user can type in the entry field and when <Return> is
  11. # pressed the item will be inserted into the list.
  12. #
  13. # WISH LIST:
  14. #    This section lists possible future enhancements.  
  15. #
  16. #      Combobox 1.x:
  17. #          - convert bindings to bindtags.
  18. #
  19. # ----------------------------------------------------------------------
  20. #  ORIGINAL AUTHOR: John S. Sigler        EMAIL: jsigler@spd.dsccc.com
  21. #                                               sigler@onramp.net
  22. # ----------------------------------------------------------------------
  23. #  CURRENT MAINTAINER: Mitch Gorman                EMAIL: logain@erols.com
  24. #                    Copyright (c) 1995    John S. Sigler
  25. #                    Copyright (c) 1997    Mitch Gorman
  26. # ======================================================================
  27. # Permission is hereby granted, without written agreement and without
  28. # license or royalty fees, to use, copy, modify, and distribute this
  29. # software and its documentation for any purpose, provided that the
  30. # above copyright notice and the following two paragraphs appear in
  31. # all copies of this software.
  32. # IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
  33. # DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 
  34. # ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 
  35. # IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
  36. # DAMAGE.
  37. #
  38. # THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 
  39. # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
  40. # FITNESS FOR A PARTICULAR PURPOSE.     THE SOFTWARE PROVIDED HEREUNDER IS
  41. # ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  42. # PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  43. # ======================================================================
  44.  
  45. #
  46. # Default resources.
  47. #
  48. option add *Combobox.borderWidth 2 widgetDefault
  49. option add *Combobox.labelPos wn widgetDefault
  50. option add *Combobox.listHeight 150 widgetDefault
  51. option add *Combobox.hscrollMode dynamic widgetDefault
  52. option add *Combobox.vscrollMode dynamic widgetDefault
  53.  
  54. #
  55. # Usual options.
  56. #
  57. itk::usual Combobox {
  58.     keep -background -borderwidth -cursor -foreground -highlightcolor \
  59.     -highlightthickness -insertbackground -insertborderwidth \
  60.     -insertofftime -insertontime -insertwidth -labelfont -popupcursor \
  61.     -selectbackground -selectborderwidth -selectforeground \
  62.     -textbackground -textfont
  63. }
  64.  
  65. # ------------------------------------------------------------------
  66. #                             COMBOBOX
  67. # ------------------------------------------------------------------
  68. class iwidgets::Combobox {
  69.     inherit iwidgets::Entryfield
  70.     
  71.     constructor {args} {}
  72.     destructor {}
  73.  
  74.     itk_option define -arrowrelief arrowRelief Relief raised
  75.     itk_option define -completion completion Completion true
  76.     itk_option define -dropdown dropdown Dropdown true
  77.     itk_option define -editable editable Editable true
  78.     itk_option define -grab grab Grab local
  79.     itk_option define -listheight listHeight Height 150
  80.     itk_option define -margin margin Margin 1
  81.     itk_option define -popupcursor popupCursor Cursor arrow
  82.     itk_option define -selectioncommand selectionCommand SelectionCommand {}
  83.     itk_option define -state state State normal
  84.     itk_option define -unique unique Unique true
  85.  
  86.     public method clear {{component all}}
  87.     public method curselection {}
  88.     public method delete {component first {last {}}}
  89.     public method get {{index {}}}
  90.     public method getcurselection {}
  91.     public method insert {component index args}
  92.     public method invoke {}
  93.     public method justify {direction}
  94.     public method see {index}
  95.     public method selection {option first {last {}}}
  96.     public method size {}
  97.     public method sort {{mode ascending}}
  98.     public method xview {args}
  99.     public method yview {args}
  100.  
  101.     protected method _addToList {}
  102.     protected method _createComponents {}
  103.     protected method _deleteList {first {last {}}}
  104.     protected method _deleteText {first {last {}}}
  105.     protected method _doLayout {{when later}}
  106.     protected method _drawArrow {}
  107.     protected method _dropdownBtnRelease {{window {}} {x 1} {y 1}}
  108.     protected method _ignoreNextBtnRelease {ignore}
  109.     protected method _next {}
  110.     protected method _packComponents {{when later}}
  111.     protected method _positionList {}
  112.     protected method _postList {}
  113.     protected method _previous {}
  114.     protected method _resizeArrow {}
  115.     protected method _selectCmd {}
  116.     protected method _toggleList {}
  117.     protected method _unpostList {}
  118.     protected method _commonBindings {}
  119.     protected method _dropdownBindings {}
  120.     protected method _simpleBindings {}
  121.     protected method _listShowing {{val ""}}
  122.  
  123.     private method _bs {}
  124.     private method _lookup {key}
  125.     private method _slbListbox {}
  126.     private method _stateSelect {}
  127.  
  128.     private variable _doit 0;
  129.     private variable _inbs 0;
  130.     private variable _inlookup 0;
  131.     private variable _currItem {};             ;# current selected item.
  132.     private variable _ignoreRelease false     ;# next button release ignored.
  133.     private variable _isPosted false;         ;# is the dropdown popped up.
  134.     private variable _repacking {}      ;# non-null => _packComponents pending.
  135.     private common _listShowing
  136.     private common count 0
  137. }     
  138.  
  139. #
  140. # Provide a lowercase access method for the Combobox class.
  141. proc ::iwidgets::combobox {pathName args} {
  142.     uplevel ::iwidgets::Combobox $pathName $args
  143. }
  144.  
  145. # ------------------------------------------------------------------
  146. #                        CONSTRUCTOR
  147. # ------------------------------------------------------------------
  148. body iwidgets::Combobox::constructor {args} {
  149.     set _listShowing($this) 0
  150.  
  151.     # combobox is different as all components are created 
  152.     # after determining what the dropdown style is...
  153.  
  154.     # configure args
  155.     eval itk_initialize $args
  156.     
  157.     # create components that are dependent on options 
  158.     # (Scrolledlistbox, arrow button) and pack them.
  159.     if {$count == 0} {
  160.     image create bitmap downarrow -data {
  161.         #define down_width 16
  162.         #define down_height 16
  163.         static unsigned char down_bits[] = {
  164.         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  165.         0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0xf8, 0x3f, 
  166.         0xf0, 0x1f, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03, 
  167.         0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  168.         };
  169.     }
  170.     image create bitmap uparrow -data {
  171.         #define up_width 16
  172.         #define up_height 16
  173.         static unsigned char up_bits[] = {
  174.         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 
  175.         0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, 0xf8, 0x0f, 
  176.         0xfc, 0x1f, 0xfe, 0x3f, 0x00, 0x00, 0x00, 0x00,
  177.         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  178.         };
  179.     }
  180.     }
  181.     incr count
  182.     _doLayout
  183. }
  184.  
  185. # ------------------------------------------------------------------
  186. #                           DESTRUCTOR
  187. # ------------------------------------------------------------------
  188. body iwidgets::Combobox::destructor {} {
  189.     # catch any repacking that may be waiting for idle time
  190.     if {$_repacking != ""} {
  191.     after cancel $_repacking
  192.     }
  193.     incr count -1
  194.     if {$count == 0} {
  195.     image delete uparrow
  196.     image delete downarrow
  197.     }
  198. }
  199.  
  200. # ================================================================
  201. #                            OPTIONS
  202. # ================================================================
  203.  
  204. # --------------------------------------------------------------------
  205. # OPTION:  -arrowrelief
  206. #
  207. # Relief style used on the arrow button.
  208. # --------------------------------------------------------------------
  209. configbody iwidgets::Combobox::arrowrelief {}
  210.  
  211. # --------------------------------------------------------------------
  212. # OPTION:  -completion
  213. #
  214. # Relief style used on the arrow button.
  215. # --------------------------------------------------------------------
  216. configbody iwidgets::Combobox::completion {
  217.     switch -- $itk_option(-completion) {
  218.     0 - no - false - off { }
  219.     1 - yes - true - on { }
  220.     default {
  221.         error "bad completion option \"$itk_option(-completion)\":\
  222.                        should be boolean"
  223.     }
  224.     }
  225. }
  226.  
  227. # --------------------------------------------------------------------
  228. # OPTION:  -dropdown  
  229. #
  230. # Boolean which determines the Combobox style: dropdown or simple.
  231. # Because the two style's lists reside in different toplevel widgets
  232. # this is more complicated than it should be.
  233. # --------------------------------------------------------------------
  234. configbody iwidgets::Combobox::dropdown {
  235.     switch -- $itk_option(-dropdown) {
  236.     1 - yes - true - on {
  237.         if {[winfo exists $itk_interior.list]} {
  238.         set vals [$itk_component(list) get 0 end]
  239.         destroy $itk_component(list)
  240.         _doLayout
  241.         if [llength $vals] {
  242.             eval insert list end $vals
  243.         }
  244.         }
  245.     }
  246.     0 - no - false - off {
  247.         if {[winfo exists $itk_interior.popup.list]} {
  248.         set vals [$itk_component(list) get 0 end]
  249.         catch {destroy $itk_component(arrowBtn)}
  250.         destroy $itk_component(popup)  ;# this deletes the list too
  251.         _doLayout
  252.         if [llength $vals] {
  253.             eval insert list end $vals
  254.         }
  255.         }
  256.     }
  257.     default {
  258.         error "bad dropdown option \"$itk_option(-dropdown)\":\
  259.                        should be boolean"
  260.     }
  261.     }
  262. }
  263.  
  264. # --------------------------------------------------------------------
  265. # OPTION: -editable     
  266. #
  267. # Boolean which allows/disallows user input to the entry field area.
  268. # --------------------------------------------------------------------
  269. configbody iwidgets::Combobox::editable {
  270.     switch -- $itk_option(-editable) {
  271.     1 - true - yes - on {
  272.         switch -- $itk_option(-state) {
  273.         normal {
  274.             $itk_component(entry) configure -state normal
  275.         }
  276.         }
  277.     }
  278.     0 - false - no - off {
  279.         $itk_component(entry) configure -state disabled
  280.     }
  281.     default {
  282.         error "bad editable option \"$itk_option(-editable)\":\
  283.                    should be boolean"
  284.     }
  285.     }
  286. }
  287.  
  288. # --------------------------------------------------------------------
  289. # OPTION:  -grab
  290. #
  291. # grab-state of megawidget
  292. # --------------------------------------------------------------------
  293. configbody iwidgets::Combobox::grab {
  294.     switch -- $itk_option(-grab) {
  295.     local { }
  296.     global { }
  297.     default {
  298.         error "bad grab value \"$itk_option(-grab)\":\
  299.                    must be global or local"
  300.     }
  301.     }
  302. }
  303.  
  304. # --------------------------------------------------------------------
  305. # OPTION: -listheight  
  306. #
  307. # Listbox height in pixels. (Need to integrate the scrolledlistbox
  308. # -visibleitems option here - at least for simple listbox.)
  309. # --------------------------------------------------------------------
  310. configbody iwidgets::Combobox::listheight {}
  311.  
  312. # --------------------------------------------------------------------
  313. # OPTION:  -margin
  314. #
  315. # Spacer between the entry field and arrow button of dropdown style
  316. # Comboboxes.
  317. # --------------------------------------------------------------------
  318. configbody iwidgets::Combobox::margin {
  319.     grid columnconfigure $itk_interior 0 -minsize $itk_option(-margin)
  320. }
  321.  
  322. # --------------------------------------------------------------------
  323. # OPTION:  -popupcursor
  324. #
  325. # Set the cursor for the popup list.
  326. # --------------------------------------------------------------------
  327. configbody iwidgets::Combobox::popupcursor {}
  328.  
  329. # --------------------------------------------------------------------
  330. # OPTION:  -selectioncommand
  331. #
  332. # Defines the proc to be called when an item is selected in the list.
  333. # --------------------------------------------------------------------
  334. configbody iwidgets::Combobox::selectioncommand {}
  335.  
  336. # --------------------------------------------------------------------
  337. # OPTION:  -state
  338. #
  339. # overall state of megawidget
  340. # --------------------------------------------------------------------
  341. configbody iwidgets::Combobox::state {
  342.     switch -- $itk_option(-state) {
  343.     disabled {
  344.         $itk_component(entry) configure -state disabled
  345.     }
  346.     normal {
  347.         switch -- $itk_option(-editable) {
  348.         1 - true - yes - on {
  349.             $itk_component(entry) configure -state normal
  350.         }
  351.         0 - false - no - off {
  352.             $itk_component(entry) configure -state disabled
  353.         }
  354.         }
  355.     }
  356.     default {
  357.         error "bad state value \"$itk_option(-state)\":\
  358.                    must be normal  or disabled"
  359.     }
  360.     }
  361.     if {[info exists itk_component(arrowBtn)]} {
  362.     $itk_component(arrowBtn) configure -state $itk_option(-state)
  363.     }
  364. }
  365.  
  366. # --------------------------------------------------------------------
  367. # OPTION: -unique  
  368. #
  369. # Boolean which disallows/allows adding duplicate items to the listbox.
  370. # --------------------------------------------------------------------
  371. configbody iwidgets::Combobox::unique {
  372.     # boolean error check
  373.     switch -- $itk_option(-unique) {
  374.     1 - true - yes - on { }
  375.     0 - false - no - off { }
  376.     default {
  377.         error "bad unique value \"$itk_option(-unique)\":\
  378.                    should be boolean"
  379.     }
  380.     }
  381. }
  382.  
  383. # =================================================================
  384. #                             METHODS
  385. # =================================================================
  386.  
  387. # ------------------------------------------------------
  388. #  PUBLIC METHOD: clear ?component?
  389. #
  390. #  Remove all elements from the listbox, all contents
  391. #  from the entry component, or both (if all).
  392. #
  393. # ------------------------------------------------------
  394. body iwidgets::Combobox::clear {{component all}} {
  395.     switch -- $component {
  396.     entry {
  397.         iwidgets::Entryfield::clear
  398.     }
  399.     list {
  400.         delete list 0 end
  401.     }
  402.     all {
  403.         delete list 0 end
  404.         iwidgets::Entryfield::clear
  405.     }
  406.     default {
  407.         error "bad Combobox component \"$component\":\
  408.                    must be entry, list, or all."
  409.     }
  410.     }
  411.     return
  412. }
  413.  
  414. # ------------------------------------------------------
  415. # PUBLIC METHOD: curselection
  416. #
  417. # Return the current selection index.
  418. #
  419. # ------------------------------------------------------
  420. body iwidgets::Combobox::curselection {} {
  421.     return [$itk_component(list) curselection]
  422. }
  423.  
  424. # ------------------------------------------------------
  425. # PUBLIC METHOD: delete component first ?last?
  426. #
  427. # Delete an item or items from the listbox OR delete
  428. # text from the entry field. First argument determines
  429. # which component deletion occurs in - valid values are
  430. # entry or list.
  431. #
  432. # ------------------------------------------------------
  433. body iwidgets::Combobox::delete {component first {last {}}} {
  434.     switch -- $component {
  435.     entry {
  436.         iwidgets::Entryfield::delete $first $last
  437.     }
  438.     list {
  439.         _deleteList $first $last
  440.     }
  441.     default {
  442.         error "bad Combobox component \"$component\":\
  443.                    must be entry or list."
  444.     }
  445.     }
  446. }
  447.  
  448. # ------------------------------------------------------
  449. # PUBLIC METHOD: get ?index?
  450. #
  451. #
  452. # Retrieve entry contents if no args OR use args as list 
  453. # index and retrieve list item at index .
  454. #
  455. # ------------------------------------------------------
  456. body iwidgets::Combobox::get {{index {}}} {
  457.     # no args means to get the current text in the entry field area
  458.     if {$index == {}} {
  459.     iwidgets::Entryfield::get
  460.     } else {
  461.     eval $itk_component(list) get $index
  462.     }
  463. }
  464.  
  465. # ------------------------------------------------------
  466. # PUBLIC METHOD: getcurselection
  467. #
  468. # Return currently selected item in the listbox. Shortcut
  469. # version of get curselection command combination.
  470. #
  471. # ------------------------------------------------------
  472. body iwidgets::Combobox::getcurselection {} {
  473.     return [$itk_component(list) getcurselection]
  474. }
  475.  
  476. # ------------------------------------------------------------------
  477. # PUBLIC METHOD: ivoke
  478. #
  479. # Pops up or down a dropdown combobox.
  480. # ------------------------------------------------------------------
  481. body iwidgets::Combobox::invoke {} {
  482.     if {$itk_option(-dropdown)} {
  483.     return [_toggleList]
  484.     }
  485.     return 
  486. }
  487.  
  488. # ------------------------------------------------------------
  489. # PUBLIC METHOD: insert comonent index string ?string ...?
  490. #
  491. # Insert an item into the listbox OR text into the entry area.
  492. # Valid component names are entry or list.
  493. #
  494. # ------------------------------------------------------------
  495. body iwidgets::Combobox::insert {component index args} {
  496.     set nargs [llength $args]
  497.  
  498.     if {$nargs == 0} {
  499.     error "no value given for parameter \"string\" in function\
  500.                \"Combobox::insert\""
  501.     } 
  502.  
  503.     switch -- $component {
  504.     entry {
  505.         if { $nargs > 1} {
  506.         error "called function \"Combobox::insert entry\"\
  507.                        with too many arguments"
  508.         } else {
  509.         if {$itk_option(-state) == "normal"} {
  510.             eval iwidgets::Entryfield::insert $index $args
  511.             [code $this _lookup ""]
  512.         }
  513.         }
  514.     }
  515.     list {
  516.         if {$itk_option(-state) == "normal"} {
  517.         eval $itk_component(list) insert $index $args
  518.         }
  519.     }
  520.     default {
  521.         error "bad Combobox component \"$component\": must\
  522.                    be entry or list."
  523.     }
  524.     }
  525. }
  526.  
  527. # ------------------------------------------------------
  528. # PUBLIC METHOD: justify direction
  529. #
  530. # Wrapper for justifying the listbox items in one of
  531. # 4 directions:     top, bottom, left, or right.
  532. #
  533. # ------------------------------------------------------
  534. body iwidgets::Combobox::justify {direction} {
  535.     return [$itk_component(list) justify $direction]
  536. }
  537.  
  538. # ------------------------------------------------------------------
  539. # PUBLIC METHOD: see index
  540. #
  541. # Adjusts the view such that the element given by index is visible.
  542. # ------------------------------------------------------------------
  543. body iwidgets::Combobox::see {index} {
  544.     return [$itk_component(list) see $index]
  545. }
  546.  
  547. # ------------------------------------------------------------------
  548. # PUBLIC METHOD: selection option first ?last?
  549. #
  550. # Adjusts the selection within the listbox and changes the contents
  551. # of the entry component to be the value of the selected list item.
  552. # ------------------------------------------------------------------
  553. body iwidgets::Combobox::selection {option first {last {}}} {
  554.     # thin wrap
  555.     if {$option == "set"} {
  556.     $itk_component(list) selection clear 0 end
  557.     $itk_component(list) selection set $first
  558.     set rtn ""
  559.     } else {
  560.     set rtn [eval $itk_component(list) selection $option $first $last]
  561.     }
  562.     set _currItem $first
  563.  
  564.     # combobox additions
  565.     set theText [getcurselection]
  566.     if {$theText != [$itk_component(entry) get]} {
  567.     clear entry
  568.     if {$theText != ""} {
  569.         insert entry 0 $theText
  570.     }
  571.     }
  572.     return $rtn
  573. }
  574.  
  575. # ------------------------------------------------------------------
  576. # PUBLIC METHOD: size 
  577. #
  578. # Returns a decimal string indicating the total number of elements 
  579. # in the listbox.
  580. # ------------------------------------------------------------------
  581. body iwidgets::Combobox::size {} {
  582.     return [$itk_component(list) size]
  583. }
  584.  
  585. # ------------------------------------------------------
  586. # PUBLIC METHOD: sort ?mode?
  587. #
  588. # Sort the current list in either "ascending" or "descending" order.
  589. #
  590. #    jss: how should i handle selected items?
  591. #
  592. # ------------------------------------------------------
  593. body iwidgets::Combobox::sort {{mode ascending}} {
  594.     $itk_component(list) sort $mode
  595.     #     return [$itk_component(list) sort $mode]
  596. }
  597.  
  598.  
  599. # ------------------------------------------------------------------
  600. # PUBLIC METHOD: xview ?arg arg ...?
  601. #
  602. # Change or query the vertical position of the text in the list box.
  603. # ------------------------------------------------------------------
  604. body iwidgets::Combobox::xview {args} {
  605.     return [eval $itk_component(list) xview $args]
  606. }
  607.  
  608. # ------------------------------------------------------------------
  609. # PUBLIC METHOD: yview ?arg arg ...?
  610. #
  611. # Change or query the horizontal position of the text in the list box.
  612. # ------------------------------------------------------------------
  613. body iwidgets::Combobox::yview {args} {
  614.     return [eval $itk_component(list) yview $args]
  615. }
  616.  
  617. # ------------------------------------------------------
  618. # PROTECTED METHOD: _addToList
  619. #
  620. # Add the current item in the entry to the listbox.
  621. #
  622. # ------------------------------------------------------
  623. body iwidgets::Combobox::_addToList {} {
  624.     set input [get]
  625.     if {$input != ""} {
  626.     if {$itk_option(-unique)} {
  627.         # if item is already in list, select it and exit
  628.         set item [lsearch -exact [$itk_component(list) get 0 end] $input]
  629.         if {$item != -1} {
  630.         selection clear 0 end
  631.         if {$item != {}} {
  632.             selection set $item $item
  633.             set _currItem $item
  634.         }
  635.         return
  636.         }
  637.     }
  638.     # add the item to end of list
  639.     selection clear 0 end
  640.     insert list end $input
  641.     selection set end end
  642.     }
  643. }
  644.  
  645. # ------------------------------------------------------
  646. # PROTECTED METHOD:      _createComponents
  647. #
  648. # Create deferred combobox components and add bindings.
  649. #
  650. # ------------------------------------------------------
  651. body iwidgets::Combobox::_createComponents {} {
  652.     if {$itk_option(-dropdown)} {
  653.     # --- build a dropdown combobox ---
  654.  
  655.     # make the arrow childsite be on the right hand side
  656.     configure -childsitepos e -command [code $this _addToList]
  657.     
  658.     # arrow button to popup the list
  659.     itk_component add arrowBtn {
  660.         button $itk_interior.arrowBtn -borderwidth 2 \
  661.         -width 15 -height 15 -image downarrow \
  662.         -command [code $this _toggleList] -state $itk_option(-state)
  663.     } {
  664.         keep -background -borderwidth -cursor  -state \
  665.         -highlightcolor -highlightthickness
  666.         rename -relief -arrowrelief arrowRelief Relief
  667.         rename -highlightbackground -background background Background
  668.     }
  669.     
  670.     # popup list container
  671.     itk_component add popup {
  672.         toplevel $itk_interior.popup
  673.     } {
  674.         keep -background -cursor
  675.     }
  676.     wm withdraw $itk_interior.popup
  677.     
  678.     # the listbox
  679.     itk_component add list {
  680.         iwidgets::Scrolledlistbox $itk_interior.popup.list -exportselection no \
  681.         -vscrollmode dynamic -hscrollmode dynamic -selectmode browse
  682.     } {
  683.         keep -background -borderwidth -cursor -foreground \
  684.         -highlightcolor -highlightthickness \
  685.         -hscrollmode -selectbackground \
  686.         -selectborderwidth -selectforeground -textbackground \
  687.         -textfont -vscrollmode
  688.         rename -height -listheight listHeight Height
  689.         rename -cursor -popupcursor popupCursor Cursor
  690.     }
  691.     # mode specific bindings
  692.     _dropdownBindings
  693.  
  694.     # Ugly hack to avoid tk buglet revealed in _dropdownBtnRelease where 
  695.     # relief is used but not set in scrollbar.tcl. 
  696.     global tkPriv
  697.     set tkPriv(relief) raise
  698.  
  699.     } else {
  700.     # --- build a simple combobox ---
  701.     configure -childsitepos s
  702.     itk_component add list {
  703.         iwidgets::Scrolledlistbox $itk_interior.list -exportselection no \
  704.         -vscrollmode dynamic -hscrollmode dynamic 
  705.     } {
  706.         keep -background -borderwidth -cursor -foreground \
  707.         -highlightcolor -highlightthickness \
  708.         -hscrollmode -selectbackground \
  709.         -selectborderwidth -selectforeground -textbackground \
  710.         -textfont -visibleitems -vscrollmode 
  711.         rename -height -listheight listHeight Height
  712.     }
  713.     # add mode specific bindings
  714.     _simpleBindings
  715.     }
  716.  
  717.     # popup cursor applies only to the list within the combobox
  718.     configure -popupcursor $itk_option(-popupcursor)
  719.  
  720.     # add mode independent bindings
  721.     _commonBindings
  722. }
  723.  
  724. # ------------------------------------------------------
  725. # PROTECTED METHOD: _deleteList first ?last?
  726. #
  727. # Delete an item or items from the listbox. Called via 
  728. # "delete list args".
  729. #
  730. # ------------------------------------------------------
  731. body iwidgets::Combobox::_deleteList {first {last {}}} {
  732.  
  733.     if {$last == {}} {
  734.     set last $first
  735.     }
  736.     $itk_component(list) delete $first $last
  737.  
  738.     # remove the item if it is no longer in the list
  739.     set text [$this get]
  740.     if {$text != ""} {
  741.     set index [lsearch -exact [$itk_component(list) get 0 end] $text ]
  742.     if {$index == -1} {
  743.         clear entry
  744.     }
  745.     }
  746.     return
  747. }
  748.  
  749. # ------------------------------------------------------
  750. # PROTECTED METHOD: _deleteText first ?last?
  751. #
  752. # Renamed Entryfield delete method. Called via "delete entry args".
  753. #
  754. # ------------------------------------------------------
  755. body iwidgets::Combobox::_deleteText {first {last {}}} {
  756.     $itk_component(entry) configure -state normal 
  757.     set rtrn [delete $first $last]
  758.     switch -- $itk_option(-editable) {
  759.     0 - false - no - off {
  760.         $itk_component(entry) configure -state disabled
  761.     }
  762.     }
  763.     return $rtrn
  764. }
  765.  
  766. # ------------------------------------------------------
  767. # PROTECTED METHOD:      _doLayout ?when?
  768. #
  769. # Call methods to create and pack the Combobox components.
  770. #
  771. # ------------------------------------------------------
  772. body iwidgets::Combobox::_doLayout {{when later}} {
  773.     _createComponents
  774.     _packComponents $when
  775. }
  776.  
  777.  
  778. # ------------------------------------------------------
  779. # PROTECTED METHOD:      _drawArrow 
  780. #
  781. # Draw the arrow button. Determines packing according to
  782. # -labelpos.
  783. #
  784. # ------------------------------------------------------
  785. body iwidgets::Combobox::_drawArrow {} {
  786.     set flip false
  787.     set relief ""
  788.     set fg [cget -foreground]
  789.     if {$_isPosted} {
  790.     set flip true
  791.     set relief "-relief sunken"
  792.     } else {
  793.     set relief "-relief $itk_option(-arrowrelief)"
  794.     }
  795.  
  796.     if {$flip} {
  797.     #     
  798.     #                draw up arrow
  799.     #
  800.     eval $itk_component(arrowBtn) configure -image uparrow $relief
  801.     } else {
  802.     #     
  803.     #                draw down arrow
  804.     #
  805.     eval $itk_component(arrowBtn) configure -image downarrow $relief
  806.     }
  807. }
  808.  
  809. # ------------------------------------------------------
  810. # PROTECTED METHOD: _dropdownBtnRelease window x y
  811. #
  812. # Event handler for button releases while a dropdown list
  813. # is posted.
  814. #
  815. # ------------------------------------------------------
  816. body iwidgets::Combobox::_dropdownBtnRelease {{window {}} {x 1} {y 1}} {
  817.  
  818.     # if it's a scrollbar then ignore the release
  819.     if {($window == [$itk_component(list) component vertsb]) ||
  820.     ($window == [$itk_component(list) component horizsb])} {
  821.     return
  822.     }
  823.  
  824.     # 1st release allows list to stay up unless we are in listbox
  825.     if {$_ignoreRelease} {
  826.     _ignoreNextBtnRelease false
  827.     return
  828.     }
  829.     
  830.     # should I use just the listbox or also include the scrollbars
  831.     if { ($x >= 0) && ($x < [winfo width [_slbListbox]])
  832.      && ($y >= 0) && ($y < [winfo height [_slbListbox]])} {
  833.     _stateSelect
  834.     }
  835.     
  836.     _unpostList
  837. }
  838.  
  839. # ------------------------------------------------------
  840. # PROTECTED METHOD: _ignoreNextBtnRelease ignore
  841. #
  842. # Set private variable _ignoreRelease. If this variable
  843. # is true then the next button release will not remove
  844. # a dropdown list.
  845. #
  846. # ------------------------------------------------------
  847. body iwidgets::Combobox::_ignoreNextBtnRelease {ignore} {
  848.     set _ignoreRelease $ignore
  849. }
  850.  
  851. # ------------------------------------------------------
  852. # PROTECTED METHOD:      _next
  853. #
  854. # Select the next item in the list.
  855. #
  856. # ------------------------------------------------------
  857. body iwidgets::Combobox::_next {} {
  858.     if {[size] <= 1} {
  859.     return
  860.     }
  861.     set i [curselection]
  862.     if {($i == {}) || ($i == [expr [size]-1]) } {
  863.     set i 0
  864.     } else {
  865.     incr i
  866.     }
  867.     selection clear 0 end
  868.     selection set $i $i
  869.     see $i
  870.     set _currItem $i
  871. }
  872.  
  873. # ------------------------------------------------------
  874. # PROTECTED METHOD:      _packComponents ?when?
  875. #
  876. # Pack the components of the combobox and add bindings.
  877. #
  878. # ------------------------------------------------------
  879. body iwidgets::Combobox::_packComponents {{when later}} {
  880.     if {$when == "later"} {
  881.     if {$_repacking == ""} {
  882.         set _repacking [after idle [code $this _packComponents now]]
  883.         return
  884.     }
  885.     } elseif {$when != "now"} {
  886.     error "bad option \"$when\": should be now or later"
  887.     }
  888.  
  889.     if {$itk_option(-dropdown)} {
  890.     grid configure $itk_component(list) -row 1 -column 0 -sticky news
  891.     _resizeArrow
  892.         grid config $itk_component(arrowBtn) -row 0 -column 1 -sticky nsew
  893.     } else {
  894.     # size and pack list hack
  895.     grid configure $itk_component(entry) -row 0 -column 0 -sticky ew
  896.     grid configure $itk_component(efchildsite) -row 1 -column 0 -sticky nsew
  897.     grid configure $itk_component(list) -row 0 -column 0 -sticky nsew
  898.  
  899.     grid rowconfigure $itk_component(efchildsite) 1 -weight 1
  900.     grid columnconfigure $itk_component(efchildsite) 0 -weight 1
  901.     }
  902.     set _repacking ""
  903. }
  904.  
  905. # ------------------------------------------------------
  906. # PROTECTED METHOD:      _positionList
  907. #
  908. # Determine the position (geometry) for the popped up list
  909. # and map it to the screen.
  910. #
  911. # ------------------------------------------------------
  912. body iwidgets::Combobox::_positionList {} {
  913.  
  914.     set x [winfo rootx $itk_component(entry) ]
  915.     set y [expr [winfo rooty $itk_component(entry) ] + \
  916.            [winfo height $itk_component(entry) ]]
  917.     set w [winfo width $itk_component(entry) ]
  918.     set h [winfo height [_slbListbox] ]
  919.     set sh [winfo screenheight .]
  920.  
  921.     if {([expr $y+$h] > $sh) && ($y > [expr $sh/2])} {
  922.     set y [expr [winfo rooty $itk_component(entry) ] - $h]
  923.     }
  924.     
  925.     $itk_component(list) configure -width $w
  926.     wm overrideredirect $itk_component(popup) 0
  927.     wm geometry $itk_component(popup) +$x+$y
  928.     wm overrideredirect $itk_component(popup) 1
  929. }
  930.  
  931. # ------------------------------------------------------
  932. # PROTECTED METHOD:      _postList
  933. #
  934. # Pop up the list in a dropdown style Combobox.
  935. #
  936. # ------------------------------------------------------
  937. body iwidgets::Combobox::_postList {} {
  938.     if {[$itk_component(list) size] == ""} {
  939.     return
  940.     }
  941.  
  942.     set _isPosted true
  943.     _positionList
  944.  
  945.     # map window and do a grab
  946.     wm deiconify $itk_component(popup)
  947.     _listShowing -wait
  948.     if {$itk_option(-grab) == "global"} {
  949.     grab -global $itk_component(popup) 
  950.     } else {
  951.     grab $itk_component(popup) 
  952.     }
  953.     raise $itk_component(popup)
  954.     focus $itk_component(popup)
  955.     _drawArrow
  956. }
  957.  
  958. # ------------------------------------------------------
  959. # PROTECTED METHOD:       _previous
  960. #
  961. # Select the previous item in the list. Wraps at front
  962. # and end of list. 
  963. #
  964. # ------------------------------------------------------
  965. body iwidgets::Combobox::_previous {} {
  966.     if {[size] <= 1} {
  967.     return
  968.     }
  969.     set i [curselection]
  970.     if {$i == "" || $i == 0} {
  971.     set i [expr [size] - 1]
  972.     } else {
  973.     incr i -1
  974.     }
  975.     selection clear 0 end
  976.     selection set $i $i
  977.     see $i
  978.     set _currItem $i
  979. }
  980.  
  981. # ------------------------------------------------------
  982. # PROTECTED METHOD:      _resizeArrow
  983. #
  984. # Recalculate the arrow button size and then redraw it.
  985. #
  986. # ------------------------------------------------------
  987. body iwidgets::Combobox::_resizeArrow {} {
  988.     set bw [expr [$itk_component(arrowBtn) cget -borderwidth]+ \
  989.         [$itk_component(arrowBtn) cget -highlightthickness]]
  990.     set newHeight [expr [winfo reqheight $itk_component(entry) ]-(2*$bw) - 2]
  991.     $itk_component(arrowBtn) configure -width $newHeight -height $newHeight
  992.     _drawArrow
  993. }
  994.  
  995. # ------------------------------------------------------
  996. # PROTECTED METHOD:      _selectCmd
  997. #
  998. # Called when list item is selected to insert new text 
  999. # in entry, and call user -command callback if defined.
  1000. #
  1001. # ------------------------------------------------------
  1002. body iwidgets::Combobox::_selectCmd {} {
  1003.     $itk_component(entry) configure -state normal
  1004.     
  1005.     set _currItem [$itk_component(list) curselection]
  1006.     set item [$itk_component(list) getcurselection]
  1007.     clear entry
  1008.     $itk_component(entry) insert 0 $item
  1009.     switch -- $itk_option(-editable) {
  1010.     0 - false - no - off {
  1011.         $itk_component(entry) configure -state disabled
  1012.     }
  1013.     }
  1014.  
  1015.     # execute user command
  1016.     if {$itk_option(-selectioncommand) != ""} {
  1017.     uplevel #0 $itk_option(-selectioncommand)
  1018.     }
  1019. }
  1020.  
  1021. # ------------------------------------------------------
  1022. # PROTECTED METHOD:     _toggleList
  1023. #
  1024. # Post or unpost the dropdown listbox (toggle).
  1025. #
  1026. # ------------------------------------------------------
  1027. body iwidgets::Combobox::_toggleList {} {
  1028.     if {[winfo ismapped $itk_component(popup)] } {
  1029.     _unpostList
  1030.     } else {
  1031.     _postList
  1032.     }
  1033. }
  1034.  
  1035. # ------------------------------------------------------
  1036. # PROTECTED METHOD:      _unpostList
  1037. #
  1038. # Unmap the listbox (pop it down).
  1039. #
  1040. # ------------------------------------------------------
  1041. body iwidgets::Combobox::_unpostList {} {
  1042.     # Determine if event occured in the scrolledlistbox and, if it did, 
  1043.     # don't unpost it. (A selection in the list unposts it correctly and 
  1044.     # in the scrollbar we don't want to unpost it.)
  1045.     set x [winfo x $itk_component(list)]
  1046.     set y [winfo y $itk_component(list)]
  1047.     set w [winfo width $itk_component(list)]
  1048.     set h [winfo height $itk_component(list)]
  1049.  
  1050.     wm withdraw $itk_component(popup)
  1051.     grab release $itk_component(popup)    
  1052.     
  1053.     set _isPosted false
  1054.     
  1055.     $itk_component(list) selection clear 0 end
  1056.     if {$_currItem != {}} {
  1057.     $itk_component(list) selection set $_currItem $_currItem
  1058.     $itk_component(list) activate $_currItem
  1059.     }
  1060.  
  1061.     switch -- $itk_option(-editable) {
  1062.     1 - true - yes - on {
  1063.         $itk_component(entry) configure -state normal
  1064.     }
  1065.     0 - false - no - off {
  1066.         $itk_component(entry) configure -state disabled
  1067.     }
  1068.     }
  1069.  
  1070.     _drawArrow
  1071. }
  1072.  
  1073. # ------------------------------------------------------
  1074. # PROTECTED METHOD:      _commonBindings
  1075. #
  1076. # Bindings that are used by both simple and dropdown
  1077. # style Comboboxes.
  1078. #
  1079. # ------------------------------------------------------
  1080. body iwidgets::Combobox::_commonBindings {} {
  1081.     bind $itk_component(entry) <KeyPress-BackSpace> [code $this _bs]
  1082.     bind $itk_component(entry) <KeyRelease> [code $this _lookup %K]
  1083.     bind $itk_component(entry) <Down>       [code $this _next]
  1084.     bind $itk_component(entry) <Up>         [code $this _previous]
  1085.     bind $itk_component(entry) <Control-n>  [code $this _next]
  1086.     bind $itk_component(entry) <Control-p>  [code $this _previous]
  1087.     bind [_slbListbox]         <Control-n>  [code $this _next]
  1088.     bind [_slbListbox]         <Control-p>  [code $this _previous]
  1089. }
  1090.  
  1091.  
  1092. # ------------------------------------------------------
  1093. # PROTECTED METHOD: _dropdownBindings
  1094. #
  1095. # Bindings used only by the dropdown type Combobox.
  1096. #
  1097. # ------------------------------------------------------
  1098. body iwidgets::Combobox::_dropdownBindings {} {
  1099.     bind $itk_component(popup)  <Escape> [code $this _unpostList]
  1100.     bind $itk_component(popup)  <space>  \
  1101.     "[code $this _stateSelect]; [code $this _unpostList]"
  1102.     bind $itk_component(popup)  <Return> \
  1103.     "[code $this _stateSelect]; [code $this _unpostList]"
  1104.     bind $itk_component(popup)  <ButtonRelease-1> \
  1105.         [code $this _dropdownBtnRelease %W %x %y]
  1106.  
  1107.     bind $itk_component(list)  <Map> \
  1108.     [code $this _listShowing 1]
  1109.     bind $itk_component(list)  <Unmap> \
  1110.         [code $this _listShowing 0]
  1111.  
  1112.     # once in the listbox, we drop on the next release (unless in scrollbar)
  1113.     bind [_slbListbox]   <Enter>   \
  1114.     [code $this _ignoreNextBtnRelease false]
  1115.  
  1116.     bind $itk_component(arrowBtn) <3>          [code $this _next]
  1117.     bind $itk_component(arrowBtn) <Shift-3>    [code $this _previous]
  1118.     bind $itk_component(arrowBtn) <Down>       [code $this _next]
  1119.     bind $itk_component(arrowBtn) <Up>         [code $this _previous]
  1120.     bind $itk_component(arrowBtn) <Control-n>  [code $this _next]
  1121.     bind $itk_component(arrowBtn) <Control-p>  [code $this _previous]
  1122.     bind $itk_component(arrowBtn) <Shift-Down> [code $this _toggleList]
  1123.     bind $itk_component(arrowBtn) <Shift-Up>   [code $this _toggleList]
  1124.     bind $itk_component(arrowBtn) <Return>     [code $this _toggleList]
  1125.     bind $itk_component(arrowBtn) <space>      [code $this _toggleList]
  1126.  
  1127.     bind $itk_component(entry)    <Configure>  [code $this _resizeArrow]
  1128.     bind $itk_component(entry)    <Shift-Down> [code $this _toggleList]
  1129.     bind $itk_component(entry)    <Shift-Up>   [code $this _toggleList]
  1130. }
  1131.  
  1132. # ------------------------------------------------------
  1133. # PROTECTED METHOD: _simpleBindings
  1134. #
  1135. # Bindings used only by the simple type Comboboxes.
  1136. #
  1137. # ------------------------------------------------------
  1138. body iwidgets::Combobox::_simpleBindings {} {
  1139.     bind [_slbListbox]         <ButtonRelease-1> [code $this _stateSelect]
  1140.     #               "[code $this _stateselect]; [code $this _selectCmd]"
  1141.  
  1142.  
  1143.     bind [_slbListbox]         <space>     [code $this _stateSelect]
  1144.     bind [_slbListbox]         <Return>    [code $this _stateSelect]
  1145.     bind $itk_component(entry) <Escape>     ""
  1146.     bind $itk_component(entry) <Shift-Down> ""
  1147.     bind $itk_component(entry) <Shift-Up>   ""
  1148.     bind $itk_component(entry) <Configure>  ""
  1149. }
  1150.  
  1151. # ------------------------------------------------------
  1152. # PROTECTED METHOD: _listShowing ?val?
  1153. #
  1154. # Used instead of "tkwait visibility" to make sure that
  1155. # the dropdown list is visible.     Whenever the list gets
  1156. # mapped or unmapped, this method is called to keep
  1157. # track of it.    When it is called with the value "-wait",
  1158. # it waits for the list to be mapped.
  1159. # ------------------------------------------------------
  1160. body iwidgets::Combobox::_listShowing {{val ""}} {
  1161.     if {$val == ""} {
  1162.     return $_listShowing($this)
  1163.     } elseif {$val == "-wait"} {
  1164.     while {!$_listShowing($this)} {
  1165.         tkwait variable [scope _listShowing($this)]
  1166.     }
  1167.     return
  1168.     }
  1169.     set _listShowing($this) $val
  1170. }
  1171.  
  1172. # ------------------------------------------------------
  1173. # PRIVATE METHOD:     _slbListbox
  1174. #
  1175. # Access the tk listbox window out of the scrolledlistbox.
  1176. #
  1177. # ------------------------------------------------------
  1178. body iwidgets::Combobox::_slbListbox {} {
  1179.     return [$itk_component(list) component listbox]
  1180. }
  1181.  
  1182. # ------------------------------------------------------
  1183. # PRIVATE METHOD:     _stateSelect
  1184. #
  1185. # only allows a B1 release in the listbox to have an effect if -state is
  1186. #    normal.
  1187. #
  1188. # ------------------------------------------------------
  1189. body iwidgets::Combobox::_stateSelect {} {
  1190.     switch --  $itk_option(-state) {
  1191.     normal {
  1192.         [code $this _selectCmd]
  1193.     }
  1194.     }
  1195. }
  1196.  
  1197. # ------------------------------------------------------
  1198. # PRIVATE METHOD:     _bs
  1199. #
  1200. # A part of the auto-completion code, this function sets a flag when the
  1201. #    Backspace key is hit and there is a selection in the entry field.
  1202. # Note that it's probably buggy to assume that a selection being present
  1203. #    means that that selection came from auto-completion.
  1204. #
  1205. # ------------------------------------------------------
  1206. body iwidgets::Combobox::_bs {} {
  1207.     #
  1208.     #        exit if completion is turned off
  1209.     #
  1210.     switch -- $itk_option(-completion) {
  1211.     0 - no - false - off {
  1212.         return
  1213.     }
  1214.     }
  1215.     #
  1216.     #        critical section flag.  it ain't perfect, but for most usage it'll
  1217.     #        keep us from being in this code "twice" at the same time
  1218.     #        (auto-repeated keystrokes are a pain!)
  1219.     #
  1220.     if {$_inbs} {
  1221.     return
  1222.     } else {
  1223.     set _inbs 1
  1224.     }
  1225.  
  1226.     #
  1227.     #        set the _doit flag if there is a selection set in the entry field
  1228.     #
  1229.     set _doit 0
  1230.     if [$itk_component(entry) selection present] {
  1231.     set _doit 1
  1232.     }
  1233.  
  1234.     #
  1235.     #        clear the semaphore and return
  1236.     #
  1237.     set _inbs 0
  1238. }
  1239.  
  1240. # ------------------------------------------------------
  1241. # PRIVATE METHOD:     _lookup
  1242. #
  1243. # handles auto-completion of text typed (or insert'd) into the entry field.
  1244. #
  1245. # ------------------------------------------------------
  1246. body iwidgets::Combobox::_lookup {key} {
  1247.     #
  1248.     #        exit if completion is turned off
  1249.     #
  1250.     switch -- $itk_option(-completion) {
  1251.     0 - no - false - off {
  1252.         return
  1253.     }
  1254.     }
  1255.  
  1256.     #
  1257.     #        critical section flag.  it ain't perfect, but for most usage it'll
  1258.     #        keep us from being in this code "twice" at the same time
  1259.     #        (auto-repeated keystrokes are a pain!)
  1260.     #
  1261.     if {$_inlookup} {
  1262.     return
  1263.     } else {
  1264.     set _inlookup 1
  1265.     }
  1266.  
  1267.     #
  1268.     #        if state of megawidget is disabled, or the entry is not editable,
  1269.     #        clear the semaphore and exit
  1270.     #
  1271.     if {$itk_option(-state) == "disabled" \
  1272.         || [lsearch {on 1 true yes} $itk_option(-editable)] == -1} {
  1273.     set _inlookup 0
  1274.     return
  1275.     }
  1276.  
  1277.     #
  1278.     #        okay, *now* we can get to work
  1279.     #        the _bs function is called on keyPRESS of BackSpace, and will set
  1280.     #        the _doit flag if there's a selection set in the entryfield.  If
  1281.     #        there is, we're assuming that it's generated by completion itself
  1282.     #        (this is probably a Bad Assumption), so we'll want to whack the
  1283.     #        selected text, as well as the character immediately preceding the
  1284.     #        insertion cursor.
  1285.     #
  1286.     if {$key == "BackSpace"} {
  1287.     if {$_doit} {
  1288.         set first [expr [$itk_component(entry) index insert] -1]
  1289.         $itk_component(entry) delete $first end
  1290.         $itk_component(entry) icursor $first
  1291.     }
  1292.     }
  1293.  
  1294.     #
  1295.     #        get the text left in the entry field, and its length.  if
  1296.     #        zero-length, clear the selection in the listbox, clear the
  1297.     #        semaphore, and boogie.
  1298.     #
  1299.     set text [get]
  1300.     set len [string length $text]
  1301.     if {$len == 0} {
  1302.     $itk_component(list) selection clear 0 end
  1303.     set _inlookup 0
  1304.     return
  1305.     }
  1306.  
  1307.     #
  1308.     #        okay, so we have to do a lookup.  find the first match in the
  1309.     #        listbox to the text we've got in the entry field (glob).
  1310.     #        if one exists, clear the current listbox selection, and set it to
  1311.     #        the one we just found, making that one visible in the listbox.
  1312.     #        then, pick off the text from the listbox entry that hadn't yet been
  1313.     #        entered into the entry field.  we need to tack that text onto the
  1314.     #        end of the entry field, select it, and then set the insertion cursor
  1315.     #        back to just before the point where we just added that text.
  1316.     #        if one didn't exist, then just clear the listbox selection
  1317.     #
  1318.     set item [lsearch [$itk_component(list) get 0 end] "$text*" ]
  1319.     if {$item != -1} {
  1320.     $itk_component(list) selection clear 0 end
  1321.     $itk_component(list) selection set $item $item
  1322.     see $item
  1323.     set remainder [string range [$itk_component(list) get $item] \
  1324.                $len end]
  1325.     $itk_component(entry) insert end $remainder
  1326.     $itk_component(entry) selection range $len end
  1327.     $itk_component(entry) icursor $len
  1328.     } else {
  1329.     $itk_component(list) selection clear 0 end
  1330.     }
  1331.     #
  1332.     #        clear the semaphore and return
  1333.     #
  1334.     set _inlookup 0
  1335.     return
  1336. }
  1337.