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 / finddialog.itk < prev    next >
Text File  |  1999-02-24  |  16KB  |  489 lines

  1. #
  2. # Finddialog
  3. # ----------------------------------------------------------------------
  4. # This class implements a dialog for searching text.  It prompts the
  5. # user for a search string and the method of searching which includes
  6. # case sensitive, regular expressions, backwards, and all.
  7. #
  8. # ----------------------------------------------------------------------
  9. #  AUTHOR: Mark L. Ulferts              EMAIL: mulferts@austin.dsccc.com
  10. #
  11. #  @(#) RCS: $Id: finddialog.itk,v 1.1 1998/07/27 18:53:08 stanton Exp $
  12. # ----------------------------------------------------------------------
  13. #            Copyright (c) 1996 DSC Technologies Corporation
  14. # ======================================================================
  15. # Permission to use, copy, modify, distribute and license this software 
  16. # and its documentation for any purpose, and without fee or written 
  17. # agreement with DSC, is hereby granted, provided that the above copyright 
  18. # notice appears in all copies and that both the copyright notice and 
  19. # warranty disclaimer below appear in supporting documentation, and that 
  20. # the names of DSC Technologies Corporation or DSC Communications 
  21. # Corporation not be used in advertising or publicity pertaining to the 
  22. # software without specific, written prior permission.
  23. # DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
  24. # ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-
  25. # INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE
  26. # AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, 
  27. # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL 
  28. # DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 
  29. # ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
  30. # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
  31. # ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
  32. # SOFTWARE.
  33. # ======================================================================
  34.  
  35. #
  36. # Usual options.
  37. #
  38. itk::usual Finddialog {
  39.     keep -background -cursor -foreground -selectcolor
  40. }
  41.  
  42. # ------------------------------------------------------------------
  43. #                          IPRFINDDIALOG
  44. # ------------------------------------------------------------------
  45. class ::iwidgets::Finddialog {
  46.     inherit iwidgets::Dialogshell
  47.  
  48.     constructor {args} {}
  49.  
  50.     itk_option define -selectcolor selectColor Background {} 
  51.     itk_option define -clearcommand clearCommand Command {}
  52.     itk_option define -matchcommand matchCommand Command {}
  53.     itk_option define -patternbackground patternBackground Background \#707070
  54.     itk_option define -patternforeground patternForeground Foreground White
  55.     itk_option define -searchbackground searchBackground Background \#c4c4c4
  56.     itk_option define -searchforeground searchForeground Foreground Black
  57.     itk_option define -textwidget textWidget TextWidget {}
  58.  
  59.     public {
  60.     method clear {}
  61.     method find {}
  62.     }
  63.  
  64.     protected {
  65.     method _get {setting}
  66.     method _textExists {}
  67.  
  68.     common _optionValues       ;# Current settings of check buttons.
  69.     common _searchPoint        ;# Starting location for searches
  70.     common _matchLen           ;# Matching pattern string length
  71.     }
  72. }
  73.  
  74. #
  75. # Provide a lowercased access method for the ::finddialog class.
  76. proc ::iwidgets::finddialog {pathName args} {
  77.     uplevel ::iwidgets::Finddialog $pathName $args
  78. }
  79.  
  80. #
  81. # Use option database to override default resources of base classes.
  82. #
  83. option add *Finddialog.title "Find" widgetDefault
  84.  
  85. # ------------------------------------------------------------------
  86. #                            CONSTRUCTOR
  87. # ------------------------------------------------------------------
  88. body ::iwidgets::Finddialog::constructor {args} {
  89.     #
  90.     # Add the find pattern entryfield.
  91.     #
  92.     itk_component add pattern {
  93.     iwidgets::Entryfield $itk_interior.pattern -labeltext "Find:"
  94.     } 
  95.     bind [$itk_component(pattern) component entry] \
  96.         <Return> "[code $this invoke]; break"
  97.     
  98.     #
  99.     # Add the find all checkbutton.
  100.     #
  101.     itk_component add all {
  102.     checkbutton $itk_interior.all \
  103.         -variable [scope _optionValues($this-all)] \
  104.         -text "All"
  105.     }
  106.  
  107.     #
  108.     # Add the case consideration checkbutton.
  109.     #
  110.     itk_component add case {
  111.     checkbutton $itk_interior.case \
  112.         -variable [scope _optionValues($this-case)] \
  113.         -text "Consider Case"
  114.     }
  115.  
  116.     #
  117.     # Add the regular expression checkbutton.
  118.     #
  119.     itk_component add regexp {
  120.     checkbutton $itk_interior.regexp \
  121.         -variable [scope _optionValues($this-regexp)] \
  122.         -text "Use Regular Expression"
  123.     }
  124.  
  125.     #
  126.     # Add the find backwards checkbutton.
  127.     #
  128.     itk_component add backwards {
  129.     checkbutton $itk_interior.backwards \
  130.         -variable [scope _optionValues($this-backwards)] \
  131.         -text "Find Backwards"
  132.     }
  133.  
  134.     #
  135.     # Add the find, clear, and close buttons, making find be the default.
  136.     #
  137.     add Find -text Find -command [code $this find]
  138.     add Clear -text Clear -command [code $this clear]
  139.     add Close -text Close -command [code $this deactivate 0]
  140.  
  141.     default Find
  142.  
  143.     #
  144.     # Use the grid to layout the components.
  145.     #
  146.     grid $itk_component(pattern) -row 0 -column 0 \
  147.     -padx 10 -pady 10 -columnspan 4 -sticky ew
  148.     grid $itk_component(all) -row 1 -column 0
  149.     grid $itk_component(case) -row 1 -column 1
  150.     grid $itk_component(regexp) -row 1 -column 2
  151.     grid $itk_component(backwards) -row 1 -column 3
  152.  
  153.     grid columnconfigure $itk_interior 0 -weight 1
  154.     grid columnconfigure $itk_interior 1 -weight 1
  155.     grid columnconfigure $itk_interior 2 -weight 1
  156.     grid columnconfigure $itk_interior 3 -weight 1
  157.  
  158.     #
  159.     # Initialize all the configuration options.
  160.     #
  161.     eval itk_initialize $args
  162. }
  163.  
  164. # ------------------------------------------------------------------
  165. #                             OPTIONS
  166. # ------------------------------------------------------------------
  167.  
  168. # ------------------------------------------------------------------
  169. # OPTION: -clearcommand
  170. #
  171. # Specifies a command to be invoked following a clear operation. 
  172. # The command is meant to be a means of notification that the
  173. # clear has taken place and allow other actions to take place such
  174. # as disabling a find again menu.
  175. # ------------------------------------------------------------------
  176. configbody iwidgets::Finddialog::clearcommand {}
  177.  
  178. # ------------------------------------------------------------------
  179. # OPTION: -matchcommand
  180. #
  181. # Specifies a command to be invoked following a find operation. 
  182. # The command is called with a match point as an argument.  Should
  183. # a match not be found the match point is {}.
  184. # ------------------------------------------------------------------
  185. configbody iwidgets::Finddialog::matchcommand {}
  186.  
  187. # ------------------------------------------------------------------
  188. # OPTION: -patternbackground
  189. #
  190. # Specifies the background color of the text matching the search
  191. # pattern.  It may have any of the forms accepted by Tk_GetColor.
  192. # ------------------------------------------------------------------
  193. configbody iwidgets::Finddialog::patternbackground {}
  194.  
  195. # ------------------------------------------------------------------
  196. # OPTION: -patternforeground
  197. #
  198. # Specifies the foreground color of the pattern matching a search
  199. # operation.  It may have any of the forms accepted by Tk_GetColor.
  200. # ------------------------------------------------------------------
  201. configbody iwidgets::Finddialog::patternforeground {}
  202.  
  203. # ------------------------------------------------------------------
  204. # OPTION: -searchforeground
  205. #
  206. # Specifies the foreground color of the line containing the matching
  207. # pattern from a search operation.  It may have any of the forms 
  208. # accepted by Tk_GetColor.
  209. # ------------------------------------------------------------------
  210. configbody iwidgets::Finddialog::searchforeground {}
  211.  
  212. # ------------------------------------------------------------------
  213. # OPTION: -searchbackground
  214. #
  215. # Specifies the background color of the line containing the matching
  216. # pattern from a search operation.  It may have any of the forms 
  217. # accepted by Tk_GetColor.
  218. # ------------------------------------------------------------------
  219. configbody iwidgets::Finddialog::searchbackground {}
  220.  
  221. # ------------------------------------------------------------------
  222. # OPTION: -textwidget
  223. #
  224. # Specifies the scrolledtext or text widget to be searched.
  225. # ------------------------------------------------------------------
  226. configbody iwidgets::Finddialog::textwidget {
  227.     if {$itk_option(-textwidget) != {}} {
  228.     set _searchPoint($itk_option(-textwidget)) 1.0
  229.     }
  230. }
  231.  
  232. # ------------------------------------------------------------------
  233. #                            METHODS
  234. # ------------------------------------------------------------------
  235.  
  236. # ------------------------------------------------------------------
  237. # PUBLIC METHOD: clear 
  238. #
  239. # Clear the pattern entryfield and the indicators.  
  240. # ------------------------------------------------------------------
  241. body ::iwidgets::Finddialog::clear {} {
  242.     $itk_component(pattern) clear
  243.  
  244.     if {[_textExists]} {
  245.     set _searchPoint($itk_option(-textwidget)) 1.0
  246.  
  247.     $itk_option(-textwidget) tag remove search-line 1.0 end
  248.     $itk_option(-textwidget) tag remove search-pattern 1.0 end
  249.     }
  250.  
  251.     if {$itk_option(-clearcommand) != {}} {
  252.     $itk_option(-clearcommand)
  253.     }
  254. }
  255.  
  256. # ------------------------------------------------------------------
  257. # PUBLIC METHOD: find
  258. #
  259. # Search for a specific text string in the text widget given by
  260. # the -textwidget option.  Should this option not be set to an
  261. # existing widget, then a quick exit is made. 
  262. # ------------------------------------------------------------------
  263. body ::iwidgets::Finddialog::find {} {
  264.     if {! [_textExists]} {
  265.     return
  266.     }
  267.  
  268.     #
  269.     # Clear any existing indicators in the text widget.
  270.     #
  271.     $itk_option(-textwidget) tag remove search-line 1.0 end
  272.     $itk_option(-textwidget) tag remove search-pattern 1.0 end
  273.  
  274.     #
  275.     # Make sure the search pattern isn't just blank.  If so, skip this.
  276.     #
  277.     set pattern [_get pattern]
  278.  
  279.     if {[string trim $pattern] == ""} {
  280.     return
  281.     }
  282.  
  283.     #
  284.     # After clearing out any old highlight indicators from a previous
  285.     # search, we'll be building our search command piece-meal based on 
  286.     # the current settings of the checkbuttons in the find dialog.  The
  287.     # first we'll add is a variable to catch the count of the length
  288.     # of the string matching the pattern.
  289.     #
  290.     set precmd "$itk_option(-textwidget) search \
  291.         -count [list [scope _matchLen($this)]]"
  292.  
  293.     if {! [_get case]} {
  294.     append precmd " -nocase"
  295.     }
  296.  
  297.     if {[_get regexp]} {
  298.     append precmd " -regexp"
  299.     } else {
  300.     append precmd " -exact"
  301.     }
  302.  
  303.     #
  304.     # If we are going to find all matches, then the start point for
  305.     # the search will be the beginning of the text; otherwise, we'll
  306.     # use the last known starting point +/- a character depending on
  307.     # the direction.
  308.     #
  309.     if {[_get all]} {
  310.     set _searchPoint($itk_option(-textwidget)) 1.0
  311.     } else {
  312.     if {[_get backwards]} {
  313.         append precmd " -backwards"
  314.     } else {
  315.         append precmd " -forwards"
  316.     }
  317.     }
  318.  
  319.     #
  320.     # Get the pattern to be matched and add it to the search command.
  321.     # Since it may contain embedded spaces, we'll wrap it in a list.
  322.     #
  323.     append precmd " [list $pattern]"    
  324.  
  325.     #
  326.     # If the search is for all matches, then we'll be performing the 
  327.     # search until no more matches are found; otherwise, we'll break
  328.     # out of the loop after one search.
  329.     #
  330.     while {1} {
  331.     if {[_get all]} {
  332.         set postcmd " $_searchPoint($itk_option(-textwidget)) end"
  333.  
  334.     } else {
  335.         set postcmd " $_searchPoint($itk_option(-textwidget))"
  336.     }
  337.  
  338.     #
  339.     # Create the final search command out of the pre and post parts
  340.     # and evaluate it which returns the location of the matching string.
  341.     #
  342.     set cmd {}
  343.     append cmd $precmd $postcmd
  344.  
  345.     if {[catch {eval $cmd} matchPoint] != 0} {
  346.         set _searchPoint($itk_option(-textwidget)) 1.0
  347.         return {}
  348.     }
  349.  
  350.     #
  351.     # If a match exists, then we'll make this spot be the new starting
  352.     # position.  Then we'll tag the line and the pattern in the line.
  353.     # The foreground and background settings will lite these positions
  354.     # in the text widget up.
  355.     #
  356.     if {$matchPoint != {}} {
  357.         set _searchPoint($itk_option(-textwidget)) $matchPoint 
  358.  
  359.         $itk_option(-textwidget) tag add search-line \
  360.           "$_searchPoint($itk_option(-textwidget)) linestart" \
  361.         "$_searchPoint($itk_option(-textwidget))" 
  362.         $itk_option(-textwidget) tag add search-line \
  363.           "$_searchPoint($itk_option(-textwidget)) + \
  364.                $_matchLen($this) chars" \
  365.           "$_searchPoint($itk_option(-textwidget)) lineend"
  366.         $itk_option(-textwidget) tag add search-pattern \
  367.            $_searchPoint($itk_option(-textwidget)) \
  368.         "$_searchPoint($itk_option(-textwidget)) + \
  369.                  $_matchLen($this) chars"
  370.     }
  371.  
  372.     #
  373.     # Set the search point for the next time through to be one
  374.     # character more or less from the current search point based
  375.     # on the direction.
  376.     #
  377.     if {[_get all] || ! [_get backwards]} {
  378.         set _searchPoint($itk_option(-textwidget)) \
  379.         [$itk_option(-textwidget) index \
  380.              "$_searchPoint($itk_option(-textwidget)) + 1c"]
  381.     } else {
  382.         set _searchPoint($itk_option(-textwidget)) \
  383.         [$itk_option(-textwidget) index \
  384.              "$_searchPoint($itk_option(-textwidget)) - 1c"]
  385.     }
  386.  
  387.     #
  388.     # If this isn't a find all operation or we didn't get a match, exit.
  389.     #
  390.     if {(! [_get all]) || ($matchPoint == {})} {
  391.         break
  392.     }
  393.     }
  394.  
  395.     #
  396.     # Configure the colors for the search-line and search-pattern.
  397.     #
  398.     $itk_option(-textwidget) tag configure search-line \
  399.         -foreground $itk_option(-searchforeground)
  400.     $itk_option(-textwidget) tag configure search-line \
  401.         -background $itk_option(-searchbackground)
  402.     $itk_option(-textwidget) tag configure search-pattern \
  403.         -background $itk_option(-patternbackground)
  404.     $itk_option(-textwidget) tag configure search-pattern \
  405.         -foreground $itk_option(-patternforeground)
  406.  
  407.     #
  408.     # Adjust the view to be the last matched position.
  409.     #
  410.     if {$matchPoint != {}} {
  411.     $itk_option(-textwidget) see $matchPoint
  412.     }
  413.  
  414.     #
  415.     # There may be multiple matches of the pattern on a single line,
  416.     # so we'll set the tag priorities such that the pattern tag is higher.
  417.     #
  418.     $itk_option(-textwidget) tag raise search-pattern search-line
  419.  
  420.     #
  421.     # If a match command is defined, then call it with the match point.
  422.     #
  423.     if {$itk_option(-matchcommand) != {}} {
  424.     $itk_option(-matchcommand) $matchPoint
  425.     }
  426.  
  427.     #
  428.     # Return the match point to the caller so they know if we found 
  429.     # anything and if so where
  430.     #
  431.     return $matchPoint
  432. }
  433.  
  434. # ------------------------------------------------------------------
  435. # PROTECTED METHOD: _get setting
  436. #
  437. # Get the current value for the pattern, case, regexp, or backwards.
  438. # ------------------------------------------------------------------
  439. body ::iwidgets::Finddialog::_get {setting} {
  440.     switch $setting {
  441.     pattern {
  442.         return [$itk_component(pattern) get]
  443.     }
  444.     case {
  445.         return $_optionValues($this-case)
  446.     }
  447.     regexp {
  448.         return $_optionValues($this-regexp)
  449.     }
  450.     backwards {
  451.         return $_optionValues($this-backwards)
  452.     }
  453.     all {
  454.         return $_optionValues($this-all)
  455.     }
  456.     default {
  457.         error "bad get setting: \"$setting\", should be pattern,\
  458.             case, regexp, backwards, or all"
  459.     }
  460.     }
  461. }
  462.  
  463. # ------------------------------------------------------------------
  464. # PROTECTED METHOD: _textExists
  465. #
  466. # Check the validity of the text widget option.  Does it exist and
  467. # is it of the class Text or Scrolledtext.
  468. # ------------------------------------------------------------------
  469. body ::iwidgets::Finddialog::_textExists {} {
  470.     if {$itk_option(-textwidget) == {}} {
  471.     return 0
  472.     }
  473.  
  474.     if {! [winfo exists $itk_option(-textwidget)]} {
  475.     error "bad finddialog text widget value: \"$itk_option(-textwidget)\",\
  476.                the widget doesn't exist"
  477.     }
  478.  
  479.     if {([winfo class $itk_option(-textwidget)] != "Text") &&
  480.     ([itcl::find objects -isa iwidgets::Scrolledtext *::$itk_option(-textwidget)] == "")} {
  481.     error "bad finddialog text widget value: \"$itk_option(-textwidget)\",\
  482.                must be of the class Text or based on Scrolledtext"
  483.     }
  484.  
  485.     return 1
  486. }
  487.