]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/samples/ide/activegrid/tool/FindService.py
Added the ActiveGrid IDE as a sample application
[wxWidgets.git] / wxPython / samples / ide / activegrid / tool / FindService.py
diff --git a/wxPython/samples/ide/activegrid/tool/FindService.py b/wxPython/samples/ide/activegrid/tool/FindService.py
new file mode 100644 (file)
index 0000000..da5235b
--- /dev/null
@@ -0,0 +1,521 @@
+#----------------------------------------------------------------------------
+# Name:         FindService.py
+# Purpose:      Find Service for pydocview
+#
+# Author:       Peter Yared, Morgan Hua
+#
+# Created:      8/15/03
+# CVS-ID:       $Id$
+# Copyright:    (c) 2003-2005 ActiveGrid, Inc.
+# License:      wxWindows License
+#----------------------------------------------------------------------------
+
+import wx
+import wx.lib.docview
+import wx.lib.pydocview
+import re
+_ = wx.GetTranslation
+
+
+#----------------------------------------------------------------------------
+# Constants
+#----------------------------------------------------------------------------
+FIND_MATCHPATTERN = "FindMatchPattern"
+FIND_MATCHREPLACE = "FindMatchReplace"
+FIND_MATCHCASE = "FindMatchCase"
+FIND_MATCHWHOLEWORD = "FindMatchWholeWordOnly"
+FIND_MATCHREGEXPR = "FindMatchRegularExpr"
+FIND_MATCHWRAP = "FindMatchWrap"
+FIND_MATCHUPDOWN = "FindMatchUpDown"
+
+FIND_SYNTAXERROR = -2
+
+SPACE = 10
+HALF_SPACE = 5
+
+
+#----------------------------------------------------------------------------
+# Classes
+#----------------------------------------------------------------------------
+
+class FindService(wx.lib.pydocview.DocService):
+
+    #----------------------------------------------------------------------------
+    # Constants
+    #----------------------------------------------------------------------------
+    FIND_ID = wx.NewId()            # for bringing up Find dialog box
+    FINDONE_ID = wx.NewId()         # for doing Find
+    FIND_PREVIOUS_ID = wx.NewId()   # for doing Find Next
+    FIND_NEXT_ID = wx.NewId()       # for doing Find Prev
+    REPLACE_ID = wx.NewId()         # for bringing up Replace dialog box
+    REPLACEONE_ID = wx.NewId()      # for doing a Replace
+    REPLACEALL_ID = wx.NewId()      # for doing Replace All
+    GOTO_LINE_ID = wx.NewId()       # for bringing up Goto dialog box
+
+    # Extending bitmasks: wx.FR_WHOLEWORD, wx.FR_MATCHCASE, and wx.FR_DOWN
+    FR_REGEXP = max([wx.FR_WHOLEWORD, wx.FR_MATCHCASE, wx.FR_DOWN]) << 1
+    FR_WRAP = FR_REGEXP << 1
+
+
+    def __init__(self):
+        self._replaceDialog = None
+        self._findDialog = None
+        self._findReplaceData = wx.FindReplaceData()
+        self._findReplaceData.SetFlags(wx.FR_DOWN)
+
+
+    def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None):
+        """ Install Find Service Menu Items """
+        editMenu = menuBar.GetMenu(menuBar.FindMenu(_("&Edit")))
+        editMenu.AppendSeparator()
+        editMenu.Append(FindService.FIND_ID, _("&Find...\tCtrl+F"), _("Finds the specified text"))
+        wx.EVT_MENU(frame, FindService.FIND_ID, frame.ProcessEvent)
+        wx.EVT_UPDATE_UI(frame, FindService.FIND_ID, frame.ProcessUpdateUIEvent)
+        editMenu.Append(FindService.FIND_PREVIOUS_ID, _("Find &Previous\tShift+F3"), _("Finds the specified text"))
+        wx.EVT_MENU(frame, FindService.FIND_PREVIOUS_ID, frame.ProcessEvent)
+        wx.EVT_UPDATE_UI(frame, FindService.FIND_PREVIOUS_ID, frame.ProcessUpdateUIEvent)
+        editMenu.Append(FindService.FIND_NEXT_ID, _("Find &Next\tF3"), _("Finds the specified text"))
+        wx.EVT_MENU(frame, FindService.FIND_NEXT_ID, frame.ProcessEvent)
+        wx.EVT_UPDATE_UI(frame, FindService.FIND_NEXT_ID, frame.ProcessUpdateUIEvent)
+        editMenu.Append(FindService.REPLACE_ID, _("R&eplace...\tCtrl+H"), _("Replaces specific text with different text"))
+        wx.EVT_MENU(frame, FindService.REPLACE_ID, frame.ProcessEvent)
+        wx.EVT_UPDATE_UI(frame, FindService.REPLACE_ID, frame.ProcessUpdateUIEvent)
+        editMenu.Append(FindService.GOTO_LINE_ID, _("&Go to Line...\tCtrl+G"), _("Goes to a certain line in the file"))
+        wx.EVT_MENU(frame, FindService.GOTO_LINE_ID, frame.ProcessEvent)
+        wx.EVT_UPDATE_UI(frame, FindService.GOTO_LINE_ID, frame.ProcessUpdateUIEvent)
+
+        # wxBug: wxToolBar::GetToolPos doesn't exist, need it to find cut tool and then insert find in front of it.
+        toolBar.InsertTool(6, FindService.FIND_ID, getFindBitmap(), shortHelpString = _("Find"), longHelpString = _("Finds the specified text"))
+        toolBar.InsertSeparator(6)
+        toolBar.Realize()
+
+        frame.Bind(wx.EVT_FIND, frame.ProcessEvent)
+        frame.Bind(wx.EVT_FIND_NEXT, frame.ProcessEvent)
+        frame.Bind(wx.EVT_FIND_REPLACE, frame.ProcessEvent)
+        frame.Bind(wx.EVT_FIND_REPLACE_ALL, frame.ProcessEvent)
+
+
+    def ProcessUpdateUIEvent(self, event):
+        id = event.GetId()
+        if id == FindService.FIND_ID:
+            event.Enable(False)
+            return True
+        elif id == FindService.FIND_PREVIOUS_ID:
+            event.Enable(False)
+            return True
+        elif id == FindService.FIND_NEXT_ID:
+            event.Enable(False)
+            return True
+        elif id == FindService.REPLACE_ID:
+            event.Enable(False)
+            return True
+        elif id == FindService.GOTO_LINE_ID:
+            event.Enable(False)
+            return True
+        else:
+            return False
+
+
+    def ShowFindReplaceDialog(self, findString="", replace = False):
+        """ Display find/replace dialog box.
+        
+            Parameters: findString is the default value shown in the find/replace dialog input field.
+            If replace is True, the replace dialog box is shown, otherwise only the find dialog box is shown. 
+        """
+        if replace:
+            if self._findDialog != None:
+                # No reason to have both find and replace dialogs up at the same time
+                self._findDialog.DoClose()
+                self._findDialog = None
+
+            self._replaceDialog = FindReplaceDialog(self.GetDocumentManager().FindSuitableParent(), -1, _("Replace"), size=(320,200), findString=findString)
+            self._replaceDialog.Show(True)
+        else:
+            if self._replaceDialog != None:
+                # No reason to have both find and replace dialogs up at the same time
+                self._replaceDialog.DoClose()
+                self._replaceDialog = None
+
+            self._findDialog = FindDialog(self.GetDocumentManager().FindSuitableParent(), -1, _("Find"), size=(320,200), findString=findString)
+            self._findDialog.Show(True)
+
+
+
+    def OnFindClose(self, event):
+        """ Cleanup handles when find/replace dialog is closed """
+        if self._findDialog != None:
+            self._findDialog = None
+        elif self._replaceDialog != None:
+            self._replaceDialog = None
+
+
+    def GetCurrentDialog(self):
+        """ return handle to either the find or replace dialog """
+        if self._findDialog != None:
+            return self._findDialog
+        return self._replaceDialog
+
+
+    def GetLineNumber(self, parent):
+        """ Display Goto Line Number dialog box """
+        line = -1
+        dialog = wx.TextEntryDialog(parent, _("Enter line number to go to:"), _("Go to Line"))
+        if dialog.ShowModal() == wx.ID_OK:
+            try:
+                line = int(dialog.GetValue())
+                if line > 65535:
+                    line = 65535
+            except:
+                pass
+        dialog.Destroy()
+        # This one is ugly:  wx.GetNumberFromUser("", _("Enter line number to go to:"), _("Go to Line"), 1, min = 1, max = 65535, parent = parent)
+        return line
+
+
+    def DoFind(self, findString, replaceString, text, startLoc, endLoc, down, matchCase, wholeWord, regExpr = False, replace = False, replaceAll = False, wrap = False):
+        """ Do the actual work of the find/replace.
+        
+            Returns the tuple (count, start, end, newText).
+            count = number of string replacements
+            start = start position of found string
+            end = end position of found string
+            newText = new replaced text 
+        """
+        flags = 0
+        if regExpr:
+            pattern = findString
+        else:
+            pattern = re.escape(findString)  # Treat the strings as a literal string
+        if not matchCase:
+            flags = re.IGNORECASE
+        if wholeWord:
+            pattern = r"\b%s\b" % pattern
+            
+        try:
+            reg = re.compile(pattern, flags)
+        except:
+            # syntax error of some sort
+            import sys
+            msgTitle = wx.GetApp().GetAppName()
+            if not msgTitle:
+                msgTitle = _("Regular Expression Search")
+            wx.MessageBox(_("Invalid regular expression \"%s\". %s") % (pattern, sys.exc_value),
+                          msgTitle,
+                          wx.OK | wx.ICON_EXCLAMATION,
+                          self.GetView())
+            return FIND_SYNTAXERROR, None, None, None
+
+        if replaceAll:
+            newText, count = reg.subn(replaceString, text)
+            if count == 0:
+                return -1, None, None, None
+            else:
+                return count, None, None, newText
+
+        start = -1
+        if down:
+            match = reg.search(text, endLoc)
+            if match == None:
+                if wrap:  # try again, but this time from top of file
+                    match = reg.search(text, 0)
+                    if match == None:
+                        return -1, None, None, None
+                else:
+                    return -1, None, None, None
+            start = match.start()
+            end = match.end()
+        else:
+            match = reg.search(text)
+            if match == None:
+                return -1, None, None, None
+            found = None
+            i, j = match.span()
+            while i < startLoc and j <= startLoc:
+                found = match
+                if i == j:
+                    j = j + 1
+                match = reg.search(text, j)
+                if match == None:
+                    break
+                i, j = match.span()
+            if found == None:
+                if wrap:  # try again, but this time from bottom of file
+                    match = reg.search(text, startLoc)
+                    if match == None:
+                        return -1, None, None, None
+                    found = None
+                    i, j = match.span()
+                    end = len(text)
+                    while i < end and j <= end:
+                        found = match
+                        if i == j:
+                            j = j + 1
+                        match = reg.search(text, j)
+                        if match == None:
+                            break
+                        i, j = match.span()
+                    if found == None:
+                        return -1, None, None, None
+                else:
+                    return -1, None, None, None
+            start = found.start()
+            end = found.end()
+
+        if replace and start != -1:
+            newText, count = reg.subn(replaceString, text, 1)
+            return count, start, end, newText
+
+        return 0, start, end, None
+
+
+    def SaveFindConfig(self, findString, wholeWord, matchCase, regExpr = None, wrap = None, upDown = None, replaceString = None):
+        """ Save find/replace patterns and search flags to registry.
+        
+            findString = search pattern
+            wholeWord = match whole word only
+            matchCase = match case
+            regExpr = use regular expressions in search pattern
+            wrap = return to top/bottom of file on search
+            upDown = search up or down from current cursor position
+            replaceString = replace string
+        """
+        config = wx.ConfigBase_Get()
+
+        config.Write(FIND_MATCHPATTERN, findString)
+        config.WriteInt(FIND_MATCHCASE, matchCase)
+        config.WriteInt(FIND_MATCHWHOLEWORD, wholeWord)
+        if replaceString != None:
+            config.Write(FIND_MATCHREPLACE, replaceString)
+        if regExpr != None:
+            config.WriteInt(FIND_MATCHREGEXPR, regExpr)
+        if wrap != None:
+            config.WriteInt(FIND_MATCHWRAP, wrap)
+        if upDown != None:
+            config.WriteInt(FIND_MATCHUPDOWN, upDown)
+
+
+    def GetFindString(self):
+        """ Load the search pattern from registry """
+        return wx.ConfigBase_Get().Read(FIND_MATCHPATTERN, "")
+
+
+    def GetReplaceString(self):
+        """ Load the replace pattern from registry """
+        return wx.ConfigBase_Get().Read(FIND_MATCHREPLACE, "")
+
+
+    def GetFlags(self):
+        """ Load search parameters from registry """
+        config = wx.ConfigBase_Get()
+
+        flags = 0
+        if config.ReadInt(FIND_MATCHWHOLEWORD, False):
+            flags = flags | wx.FR_WHOLEWORD
+        if config.ReadInt(FIND_MATCHCASE, False):
+            flags = flags | wx.FR_MATCHCASE
+        if config.ReadInt(FIND_MATCHUPDOWN, False):
+            flags = flags | wx.FR_DOWN
+        if config.ReadInt(FIND_MATCHREGEXPR, False):
+            flags = flags | FindService.FR_REGEXP
+        if config.ReadInt(FIND_MATCHWRAP, False):
+            flags = flags | FindService.FR_WRAP
+        return flags
+
+
+class FindDialog(wx.Dialog):
+    """ Find Dialog with regular expression matching and wrap to top/bottom of file. """
+
+    def __init__(self, parent, id, title, size, findString=None):
+        wx.Dialog.__init__(self, parent, id, title, size=size)
+
+        config = wx.ConfigBase_Get()
+        borderSizer = wx.BoxSizer(wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(SPACE, SPACE)
+
+        lineSizer = wx.BoxSizer(wx.HORIZONTAL)
+        lineSizer.Add(wx.StaticText(self, -1, _("Find what:")), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, SPACE)
+        if not findString:
+            findString = config.Read(FIND_MATCHPATTERN, "")
+        self._findCtrl = wx.TextCtrl(self, -1, findString, size=(200,-1))
+        lineSizer.Add(self._findCtrl, 0)
+        gridSizer.Add(lineSizer, pos=(0,0), span=(1,2))
+        choiceSizer = wx.BoxSizer(wx.VERTICAL)
+        self._wholeWordCtrl = wx.CheckBox(self, -1, _("Match whole word only"))
+        self._wholeWordCtrl.SetValue(config.ReadInt(FIND_MATCHWHOLEWORD, False))
+        self._matchCaseCtrl = wx.CheckBox(self, -1, _("Match case"))
+        self._matchCaseCtrl.SetValue(config.ReadInt(FIND_MATCHCASE, False))
+        self._regExprCtrl = wx.CheckBox(self, -1, _("Regular expression"))
+        self._regExprCtrl.SetValue(config.ReadInt(FIND_MATCHREGEXPR, False))
+        self._wrapCtrl = wx.CheckBox(self, -1, _("Wrap"))
+        self._wrapCtrl.SetValue(config.ReadInt(FIND_MATCHWRAP, False))
+        choiceSizer.Add(self._wholeWordCtrl, 0, wx.BOTTOM, SPACE)
+        choiceSizer.Add(self._matchCaseCtrl, 0, wx.BOTTOM, SPACE)
+        choiceSizer.Add(self._regExprCtrl, 0, wx.BOTTOM, SPACE)
+        choiceSizer.Add(self._wrapCtrl, 0)
+        gridSizer.Add(choiceSizer, pos=(1,0), span=(2,1))
+
+        self._radioBox = wx.RadioBox(self, -1, _("Direction"), choices = ["Up", "Down"])
+        self._radioBox.SetSelection(config.ReadInt(FIND_MATCHUPDOWN, 1))
+        gridSizer.Add(self._radioBox, pos=(1,1), span=(2,1))
+
+        buttonSizer = wx.BoxSizer(wx.VERTICAL)
+        findBtn = wx.Button(self, FindService.FINDONE_ID, _("Find Next"))
+        findBtn.SetDefault()
+        wx.EVT_BUTTON(self, FindService.FINDONE_ID, self.OnActionEvent)
+        cancelBtn = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
+        wx.EVT_BUTTON(self, wx.ID_CANCEL, self.OnClose)
+        buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE)
+        buttonSizer.Add(cancelBtn, 0)
+        gridSizer.Add(buttonSizer, pos=(0,2), span=(3,1))
+
+        borderSizer.Add(gridSizer, 0, wx.ALL, SPACE)
+
+        self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+        self.SetSizer(borderSizer)
+        self.Fit()
+        self._findCtrl.SetFocus()
+
+    def SaveConfig(self):
+        """ Save find patterns and search flags to registry. """
+        findService = wx.GetApp().GetService(FindService)
+        if findService:
+            findService.SaveFindConfig(self._findCtrl.GetValue(),
+                                       self._wholeWordCtrl.IsChecked(),
+                                       self._matchCaseCtrl.IsChecked(),
+                                       self._regExprCtrl.IsChecked(),
+                                       self._wrapCtrl.IsChecked(),
+                                       self._radioBox.GetSelection(),
+                                       )
+
+
+    def DoClose(self):
+        self.SaveConfig()
+        self.Destroy()
+
+
+    def OnClose(self, event):
+        findService = wx.GetApp().GetService(FindService)
+        if findService:
+            findService.OnFindClose(event)
+        self.DoClose()
+
+
+    def OnActionEvent(self, event):
+        self.SaveConfig()
+
+        if wx.GetApp().GetDocumentManager().GetFlags() & wx.lib.docview.DOC_MDI:
+            if wx.GetApp().GetTopWindow().ProcessEvent(event):
+                return True
+        else:
+            view = wx.GetApp().GetDocumentManager().GetLastActiveView()
+            if view and view.ProcessEvent(event):
+                return True
+        return False
+
+
+class FindReplaceDialog(FindDialog):
+    """ Find/Replace Dialog with regular expression matching and wrap to top/bottom of file. """
+
+    def __init__(self, parent, id, title, size, findString=None):
+        wx.Dialog.__init__(self, parent, id, title, size=size)
+
+        config = wx.ConfigBase_Get()
+        borderSizer = wx.BoxSizer(wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(SPACE, SPACE)
+
+        gridSizer2 = wx.GridBagSizer(SPACE, SPACE)
+        gridSizer2.Add(wx.StaticText(self, -1, _("Find what:")), flag=wx.ALIGN_CENTER_VERTICAL, pos=(0,0))
+        if not findString:
+            findString = config.Read(FIND_MATCHPATTERN, "")
+        self._findCtrl = wx.TextCtrl(self, -1, findString, size=(200,-1))
+        gridSizer2.Add(self._findCtrl, pos=(0,1))
+        gridSizer2.Add(wx.StaticText(self, -1, _("Replace with:")), flag=wx.ALIGN_CENTER_VERTICAL, pos=(1,0))
+        self._replaceCtrl = wx.TextCtrl(self, -1, config.Read(FIND_MATCHREPLACE, ""), size=(200,-1))
+        gridSizer2.Add(self._replaceCtrl, pos=(1,1))
+        gridSizer.Add(gridSizer2, pos=(0,0), span=(1,2))
+        choiceSizer = wx.BoxSizer(wx.VERTICAL)
+        self._wholeWordCtrl = wx.CheckBox(self, -1, _("Match whole word only"))
+        self._wholeWordCtrl.SetValue(config.ReadInt(FIND_MATCHWHOLEWORD, False))
+        self._matchCaseCtrl = wx.CheckBox(self, -1, _("Match case"))
+        self._matchCaseCtrl.SetValue(config.ReadInt(FIND_MATCHCASE, False))
+        self._regExprCtrl = wx.CheckBox(self, -1, _("Regular expression"))
+        self._regExprCtrl.SetValue(config.ReadInt(FIND_MATCHREGEXPR, False))
+        self._wrapCtrl = wx.CheckBox(self, -1, _("Wrap"))
+        self._wrapCtrl.SetValue(config.ReadInt(FIND_MATCHWRAP, False))
+        choiceSizer.Add(self._wholeWordCtrl, 0, wx.BOTTOM, SPACE)
+        choiceSizer.Add(self._matchCaseCtrl, 0, wx.BOTTOM, SPACE)
+        choiceSizer.Add(self._regExprCtrl, 0, wx.BOTTOM, SPACE)
+        choiceSizer.Add(self._wrapCtrl, 0)
+        gridSizer.Add(choiceSizer, pos=(1,0), span=(2,1))
+
+        self._radioBox = wx.RadioBox(self, -1, _("Direction"), choices = ["Up", "Down"])
+        self._radioBox.SetSelection(config.ReadInt(FIND_MATCHUPDOWN, 1))
+        gridSizer.Add(self._radioBox, pos=(1,1), span=(2,1))
+
+        buttonSizer = wx.BoxSizer(wx.VERTICAL)
+        findBtn = wx.Button(self, FindService.FINDONE_ID, _("Find Next"))
+        findBtn.SetDefault()
+        wx.EVT_BUTTON(self, FindService.FINDONE_ID, self.OnActionEvent)
+        cancelBtn = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
+        wx.EVT_BUTTON(self, wx.ID_CANCEL, self.OnClose)
+        replaceBtn = wx.Button(self, FindService.REPLACEONE_ID, _("Replace"))
+        wx.EVT_BUTTON(self, FindService.REPLACEONE_ID, self.OnActionEvent)
+        replaceAllBtn = wx.Button(self, FindService.REPLACEALL_ID, _("Replace All"))
+        wx.EVT_BUTTON(self, FindService.REPLACEALL_ID, self.OnActionEvent)
+        buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE)
+        buttonSizer.Add(replaceBtn, 0, wx.BOTTOM, HALF_SPACE)
+        buttonSizer.Add(replaceAllBtn, 0, wx.BOTTOM, HALF_SPACE)
+        buttonSizer.Add(cancelBtn, 0)
+        gridSizer.Add(buttonSizer, pos=(0,2), span=(3,1))
+
+        borderSizer.Add(gridSizer, 0, wx.ALL, SPACE)
+
+        self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+        self.SetSizer(borderSizer)
+        self.Fit()
+        self._findCtrl.SetFocus()
+        
+
+    def SaveConfig(self):
+        """ Save find/replace patterns and search flags to registry. """
+        findService = wx.GetApp().GetService(FindService)
+        if findService:
+            findService.SaveFindConfig(self._findCtrl.GetValue(),
+                                       self._wholeWordCtrl.IsChecked(),
+                                       self._matchCaseCtrl.IsChecked(),
+                                       self._regExprCtrl.IsChecked(),
+                                       self._wrapCtrl.IsChecked(),
+                                       self._radioBox.GetSelection(),
+                                       self._replaceCtrl.GetValue()
+                                       )
+
+
+#----------------------------------------------------------------------------
+# Menu Bitmaps - generated by encode_bitmaps.py
+#----------------------------------------------------------------------------
+from wx import ImageFromStream, BitmapFromImage
+import cStringIO
+
+
+def getFindData():
+    return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
+\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x00\x81IDAT8\x8d\xa5S\xc1\x16\xc0\x10\x0ckk\xff\xff\xc7d\x87\xad^U\r\
+\x93S\xe5U$\n\xb3$:\xc1e\x17(\x19Z\xb3$\x9e\xf1DD\xe2\x15\x01x\xea\x93\xef\
+\x04\x989\xea\x1b\xf2U\xc0\xda\xb4\xeb\x11\x1f:\xd8\xb5\xff8\x93\xd4\xa9\xae\
+@/S\xaaUwJ3\x85\xc0\x81\xee\xeb.q\x17C\x81\xd5XU \x1a\x93\xc6\x18\x8d\x90\
+\xe8}\x89\x00\x9a&\x9b_k\x94\x0c\xdf\xd78\xf8\x0b\x99Y\xb4\x08c\x9e\xfe\xc6\
+\xe3\x087\xf9\xd0D\x180\xf1#\x8e\x00\x00\x00\x00IEND\xaeB`\x82' 
+
+
+def getFindBitmap():
+    return BitmapFromImage(getFindImage())
+
+
+def getFindImage():
+    stream = cStringIO.StringIO(getFindData())
+    return ImageFromStream(stream)
+