]> git.saurik.com Git - wxWidgets.git/commitdiff
Updated PyCrust contrib from Patrick O'Brian.
authorRobin Dunn <robin@alldunn.com>
Sat, 1 Dec 2001 02:25:39 +0000 (02:25 +0000)
committerRobin Dunn <robin@alldunn.com>
Sat, 1 Dec 2001 02:25:39 +0000 (02:25 +0000)
Added an enhanced wxEditor from Steve Howell and Adam Feuer.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@12782 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

28 files changed:
wxPython/CHANGES.txt
wxPython/MANIFEST.in
wxPython/demo/wxEditor.py
wxPython/distrib/make_installer.py
wxPython/samples/frogedit/FrogEdit.py [new file with mode: 0644]
wxPython/samples/frogedit/FrogEditor.py [new file with mode: 0644]
wxPython/samples/frogedit/StatusBar.py [new file with mode: 0644]
wxPython/wxPython/lib/PyCrust/PyCrust.py [deleted file]
wxPython/wxPython/lib/PyCrust/PyCrustApp.py [new file with mode: 0755]
wxPython/wxPython/lib/PyCrust/PyFilling.py [deleted file]
wxPython/wxPython/lib/PyCrust/PyFillingApp.py [new file with mode: 0755]
wxPython/wxPython/lib/PyCrust/PyShell.py [deleted file]
wxPython/wxPython/lib/PyCrust/PyShellApp.py [new file with mode: 0755]
wxPython/wxPython/lib/PyCrust/README.txt
wxPython/wxPython/lib/PyCrust/crust.py
wxPython/wxPython/lib/PyCrust/filling.py
wxPython/wxPython/lib/PyCrust/interpreter.py
wxPython/wxPython/lib/PyCrust/introspect.py
wxPython/wxPython/lib/PyCrust/pseudo.py
wxPython/wxPython/lib/PyCrust/shell.py
wxPython/wxPython/lib/PyCrust/version.py
wxPython/wxPython/lib/editor/README.txt
wxPython/wxPython/lib/editor/__init__.py
wxPython/wxPython/lib/editor/editor.py
wxPython/wxPython/lib/editor/images.py [new file with mode: 0644]
wxPython/wxPython/lib/editor/py_editor.py [deleted file]
wxPython/wxPython/lib/editor/selection.py [new file with mode: 0644]
wxPython/wxPython/lib/editor/tokenizer.py [deleted file]

index f504f9d0f0f413b90d90fa9ddc538e3f8af8db7e..87dffdbac093dd96c188af1afb65c18dde348872 100644 (file)
@@ -95,6 +95,8 @@ same document.
 
 Added wxEditableListBox gizmo.
 
+Added a greatly enhanced wxEditor from Steve Howell and Adam Feuer.
+
 
 
 
index fd87a7b4c0b95fe1e673aa7c5dab346733d4a716..60183f925ce1600578578aa0fa4f98e08fa833fe 100644 (file)
@@ -50,6 +50,7 @@ include samples/StyleEditor/*.txt
 include samples/StyleEditor/*.cfg
 include samples/pySketch/*.py
 include samples/pySketch/images/*.bmp
+include samples/frogedit/*.py
 
 
 include wxPython/lib/*.py
index a55dc9def240c6915b82d7ecae8ed222e6ea2cf9..756b46e3f736b8411182cbf2067cfeb31644ab79 100644 (file)
@@ -1,42 +1,63 @@
 
 from wxPython.wx         import *
-from wxPython.lib.editor import wxEditor, wxPyEditor
+from wxPython.lib.editor import wxEditor
 
 #----------------------------------------------------------------------
 
 def runTest(frame, nb, log):
     win = wxPanel(nb, -1)
     ed = wxEditor(win, -1, style=wxSUNKEN_BORDER)
-    pyed = wxPyEditor(win, -1, style=wxSUNKEN_BORDER)
     box = wxBoxSizer(wxVERTICAL)
     box.Add(ed, 1, wxALL|wxGROW, 5)
-    box.Add(pyed, 1, wxALL|wxGROW, 5)
     win.SetSizer(box)
     win.SetAutoLayout(true)
 
     ed.SetText(["",
                 "This is a simple text editor, the class name is",
                 "wxEditor.  Type a few lines and try it out.",
+                "",
+                "It uses Windows-style key commands that can be overriden by subclassing.",
+                "Mouse select works. Here are the key commands:",
+                "",
+                "Cursor movement:     Arrow keys or mouse",
+                "Beginning of line:   Home",
+                "End of line:         End",
+                "Beginning of buffer: Control-Home",
+                "End of the buffer:   Control-End",
+                "Select text:         Hold down Shift while moving the cursor",
+                "Copy:                Control-Insert, Control-C",
+                "Cut:                 Shift-Delete,   Control-X",
+                "Paste:               Shift-Insert,   Control-V",
                 ""])
 
-    pyed.SetText(["# This one is a derived class named wxPyEditor.",
-                  "# It adds syntax highlighting, folding (press",
-                  "# F12 on the \"def\" line below) and other stuff.",
-                  "import sys",
-                  "def hello():",
-                  "    print 'hello'",
-                  "    for x in sys.path:",
-                  "        print x",
-                  ""])
     return win
 
 #----------------------------------------------------------------------
 
 
+overview = """
+The wxEditor class implements a simple text editor using wxPython.  You
+can create a custom editor by subclassing wxEditor.  Even though much of
+the editor is implemented in Python, it runs surprisingly smoothly on  
+normal hardware with small files.
 
+How to use it
+-------------
+The demo code (demo/wxEditor.py) shows how to use wxEditor as a simple text
+box. Use the SetText() and GetText() methods to set or get text from
+the component; these both use a list of strings.
+
+The samples/FrogEdit directory has an example of a simple text editor
+application that uses the wxEditor component.
+
+Subclassing
+-----------
+To add or change functionality, you can subclass this
+component. One example of this might be to change the key
+Alt key commands. In that case you would (for example) override the
+SetAltFuncs() method.
 
 
-overview = """\
 """
 
 
index 8687e17cef03d4a8bbffb647967ffc8896b9c8a0..08e1aba4e29c29c7e2d78f7b228cdfe5bd23ac63 100644 (file)
@@ -151,6 +151,7 @@ Source: "samples\StyleEditor\*.cfg";           DestDir: "{app}\wxPython\samples\
 Source: "samples\pySketch\*.py";           DestDir: "{app}\wxPython\samples\pySketch"; Components: samples
 Source: "samples\pySketch\images\*.bmp";   DestDir: "{app}\wxPython\samples\pySketch\images"; Components: samples
 
+Source: "samples\frogedit\*.py";           DestDir: "{app}\wxPython\samples\frogedit"; Components: samples
 
 ;;------------------------------------------------------------
 
@@ -192,6 +193,8 @@ Type: files; Name: "{app}\wxPython\samples\stxview\*.pyc";
 Type: files; Name: "{app}\wxPython\samples\stxview\*.pyo";
 Type: files; Name: "{app}\wxPython\samples\stxview\StructuredText\*.pyc";
 Type: files; Name: "{app}\wxPython\samples\stxview\StructuredText\*.pyo";
+Type: files; Name: "{app}\wxPython\samples\frogedit\*.pyc";
+Type: files; Name: "{app}\wxPython\samples\frogedit\*.pyo";
 
 '''
 
diff --git a/wxPython/samples/frogedit/FrogEdit.py b/wxPython/samples/frogedit/FrogEdit.py
new file mode 100644 (file)
index 0000000..68f3e27
--- /dev/null
@@ -0,0 +1,366 @@
+#!/usr/local/bin/python
+
+# simple text editor
+#
+# Copyright 2001 Adam Feuer and Steve Howell
+#
+# License: Python
+
+import os, string, re
+import sys
+from wxPython.wx         import *
+from StatusBar           import *
+from FrogEditor          import FrogEditor
+
+TRUE  = 1
+FALSE = 0
+
+ABOUT_TEXT = """FrogEdit : Copyright 2001 Adam Feuer and Steve Howell
+wxEditor component : Copyright 1999 - 2001 Dirk Holtwic, Robin Dunn, Adam Feuer, Steve Howell
+
+FrogEdit was built using Python, wxPython, and wxWindows."""
+
+
+##---------------------------------------------------------------------
+
+def chomp(line):
+    line = string.split(line,'\n')[0]
+    return string.split(line,'\r')[0]
+
+##---------------------------------------------------------------------
+
+class OutlinerPanel(wxPanel):
+
+    def Close(self, event):
+        self.parent.Close()
+        wxPanel.Close(self)
+
+##----------------------------------------------------------------------
+    
+
+class FrogEditFrame(wxFrame):
+    def __init__(self, parent, ID, title, pos=wxDefaultPosition,
+                 size=wxDefaultSize, style=wxDEFAULT_FRAME_STYLE):
+
+        wxFrame.__init__(self, parent, ID, title, pos, size, style)
+
+        splitter = wxSplitterWindow(self, -1, style=wxNO_3D|wxSP_3D)
+        win = OutlinerPanel(splitter, -1, style=wxCLIP_CHILDREN)
+        win.parent = self
+        log = self.MakeLogWindow(splitter)
+        
+        self.MakeStatusbar()
+        self.MakeEditorWindow(win, log)
+        self.SetUpSplitter(splitter, win, log)
+        self.MakeMenus()
+        self.MakeMainWindow(win)
+        self.RegisterEventHandlers()
+        self.InitVariables()
+
+
+##------------- Init Misc
+
+    def RegisterEventHandlers(self):
+        EVT_CLOSE(self,self.OnCloseWindow)
+
+    def InitVariables(self):
+        self.fileName = None
+        self.edl.UnTouchBuffer()
+        
+    def MakeMenus(self):
+        self.MainMenu = wxMenuBar()
+        self.AddMenus(self.MainMenu)
+        self.SetMenuBar(self.MainMenu)
+
+##------------- Init Subwindows
+
+    def MakeEditorWindow(self, win, log):
+        self.edl = FrogEditor(win, -1, style=wxSUNKEN_BORDER, statusBar = self.sb)
+        self.edl.SetControlFuncs = self.SetControlFuncs
+        self.edl.SetAltFuncs = self.SetAltFuncs
+        self.edl.SetStatus(log)
+
+    def MakeStatusbar(self):
+        self.sb = CustomStatusBar(self)
+        self.SetStatusBar(self.sb)
+
+    def MakeLogWindow(self, container):
+        log = wxTextCtrl(container, -1,
+                         style = wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL)
+        wxLog_SetActiveTarget(wxLogTextCtrl(log))
+        wxLogMessage('window handle: %s' % self.GetHandle())
+        return log
+
+    def SetUpSplitter(self, splitter, win, log):
+        splitter.SplitHorizontally(win, log)
+        splitter.SetSashPosition(360, true)
+        splitter.SetMinimumPaneSize(40)
+
+    def MakeToolbar(self, win):
+        toolbarBox = wxBoxSizer(wxHORIZONTAL)
+        self.AddButtons(win, toolbarBox)
+        return toolbarBox
+
+    def MakeMainWindow(self, win):
+        mainBox = wxBoxSizer(wxVERTICAL)
+        mainBox.Add(self.MakeToolbar(win))
+        borderWidth = 5
+        mainBox.Add(self.edl, 1, wxALL|wxGROW, borderWidth)
+        win.SetSizer(mainBox)
+        win.SetAutoLayout(true)
+
+##-------------- Init Menus
+
+    # override this to add more menus
+    def AddMenus(self, menu):
+        self.AddFileMenu(menu)
+        self.AddEditMenu(menu)
+        self.AddHelpMenu(menu)
+
+    def AddMenuItem(self, menu, itemText, itemDescription, itemHandler):
+        menuId = wxNewId()
+        menu.Append(menuId, itemText, itemDescription)
+        EVT_MENU(self, menuId, itemHandler)
+        return menuId
+
+    def AddFileMenu(self, menu):
+        fileMenu = wxMenu()
+        self.AddMenuItem(fileMenu, '&New File\tCtrl-N', 'New File', self.OnNewFile)
+        self.AddMenuItem(fileMenu, '&Open File\tCtrl-O', 'Open File', self.OnOpenFile)
+        self.AddMenuItem(fileMenu, '&Save File\tCtrl-S', 'Save File', self.OnSaveFile)
+        self.AddMenuItem(fileMenu, 'Save File &As\tCtrl-A', 'Save File As',self.OnSaveFileAs)
+        self.AddMenuItem(fileMenu, 'E&xit\tAlt-X', 'Exit', self.OnFileExit)
+        menu.Append(fileMenu, 'File')
+
+    def AddEditMenu(self, menu):
+        editMenu = wxMenu()
+        self.AddMenuItem(editMenu, 'Cut\tCtrl-X', 'Cut', self.edl.OnCutSelection)
+        self.AddMenuItem(editMenu, '&Copy\tCtrl-C', 'Copy', self.edl.OnCopySelection)
+        self.AddMenuItem(editMenu, 'Paste\tCtrl-V', 'Paste', self.edl.OnPaste)
+        self.AddMenuItem(editMenu, 'Edit preferences', 'Edit Preferences', self.OnEditPreferences)
+        menu.Append(editMenu, 'Edit')
+
+    def AddHelpMenu(self, menu):
+        helpMenu = wxMenu()
+        self.AddMenuItem(helpMenu, 'About', 'About the program', self.OnHelpAbout)
+        menu.Append(helpMenu, 'Help')
+
+##---------------- Init Buttons
+
+
+    def NewButton(self, window, container, name, pos, size, handler):
+        buttonId = wxNewId()
+        if pos == None or size == None:
+            container.Add(wxButton(window, buttonId, name), 0, 0)
+        else:
+            container.Add(wxButton(window, buttonId, name, pos, size), 0, 0)
+        EVT_BUTTON(self, buttonId, handler)
+        return buttonId
+
+    # override this to make more buttons
+    def AddButtons(self, window, container):
+        buttonPos = None
+        buttonSize = None
+        self.NewButton(window, container, "New", buttonPos, buttonSize, self.OnNewFile)
+        self.NewButton(window, container, "Open", buttonPos, buttonSize, self.OnOpenFile)
+        self.NewButton(window, container, "Save", buttonPos, buttonSize, self.OnSaveFile)
+
+
+##-------------- Init Dialogs
+
+    def MessageDialog(self, text, title):
+        messageDialog = wxMessageDialog(self, text, title, wxOK | wxICON_INFORMATION)
+        messageDialog.ShowModal()
+        messageDialog.Destroy()
+    
+    def OkCancelDialog(self, text, title):
+        dialog = wxMessageDialog(self, text, title, wxOK | wxCANCEL | wxICON_INFORMATION)
+        result = dialog.ShowModal()
+        dialog.Destroy()
+        if result == wxID_OK:
+            return TRUE
+        else:
+            return FALSE
+
+    def SelectFileDialog(self, defaultDir=None, defaultFile=None, wildCard=None):
+        if defaultDir == None:
+            defaultDir = "."
+        if defaultFile == None:
+            defaultFile = ""
+        if wildCard == None:
+            wildCard = "*.*"
+        fileName = None
+        fileDialog = wxFileDialog(self, "Choose a file", defaultDir, defaultFile, wildCard, wxOPEN|wxMULTIPLE)
+        result = fileDialog.ShowModal() 
+        if result == wxID_OK:
+            fileName = fileDialog.GetPath()
+            wxLogMessage('You selected: %s\n' % fileName)
+        fileDialog.Destroy()       
+        return fileName
+
+    def OpenFileError(self, fileName):
+        wxLogMessage('Open file error.')
+        self.MessageDialog("Error opening file '%s'!" % fileName, "Error")
+
+
+    def SaveFileError(self, fileName):
+        wxLogMessage('Save file error.')
+        self.MessageDialog("Error saving file '%s'!" % fileName, "Error")
+
+##---------------- Utility functions
+
+
+    def SetControlFuncs(self, action):
+        "for overriding editor's keys"
+        FrogEditor.SetControlFuncs(self.edl, action)
+        action['a'] = self.OnSaveFileAs
+        action['o'] = self.OnOpenFile
+        action['n'] = self.OnNewFile
+        action['s'] = self.OnSaveFile
+
+    def SetAltFuncs(self, action):
+        FrogEditor.SetAltFuncs(self.edl, action)
+        action['x'] = self.OnFileExit 
+
+    def GetCurrentDir(self):
+        if self.fileName is not None:
+            return os.path.split(self.fileName)[0]
+        return "."
+            
+    def GetFileName(self):
+        if self.fileName is not None:
+            return os.path.split(self.fileName)[1]
+        return ""
+
+    def NewFile(self):
+        self.edl.SetText([""])
+        self.fileName = None
+        self.sb.setFileName("")
+
+    def SaveFile(self, fileName):
+        try:
+            contents = string.join(self.edl.GetText(), '\n')
+            f = open(fileName, 'w')
+            f.write(contents)
+            f.close()
+            self.edl.UnTouchBuffer()
+            self.sb.setFileName(fileName)
+            return TRUE
+        except:
+            return FALSE
+
+    def OpenFile(self, fileName):
+        try:
+            f = open(fileName, 'r')
+            contents = f.readlines()
+            f.close()
+            contents = [chomp(line) for line in contents]
+            if len(contents) == 0:
+                contents = [""]
+            self.edl.SetText(contents)
+            self.fileName = fileName
+            self.sb.setFileName(fileName)
+            return TRUE
+        except:
+            return FALSE
+        
+
+
+##---------------- Event handlers
+
+
+    def OnCloseWindow(self, event):
+        self.edl.OnCloseWindow(event)
+        self.Destroy()
+
+    def OnNewFile(self, event):
+        if self.edl.BufferWasTouched():
+            if not self.OkCancelDialog("New file - abandon changes?", "New File"):
+                return
+        self.NewFile()
+        self.edl.SetFocus()
+    
+    def OnOpenFile(self, event):
+        if self.edl.BufferWasTouched():
+            if not self.OkCancelDialog("Open file - abandon changes?", "Open File"):
+                return
+        fileName = self.SelectFileDialog(self.GetCurrentDir())
+        if fileName is not None:
+            if self.OpenFile(fileName) is FALSE:
+                self.OpenFileError(fileName)
+        self.edl.SetFocus()
+    
+    def OnSaveFile(self, event):
+        if self.fileName is None:
+            return self.OnSaveFileAs(event)
+        wxLogMessage("Saving %s..." % self.fileName)
+        if self.SaveFile(self.fileName) is not TRUE:
+            self.SaveFileError(self.fileName)
+        self.edl.SetFocus()
+    
+    def OnSaveFileAs(self, event):
+        fileName = self.SelectFileDialog(self.GetCurrentDir(),self.GetFileName())
+        if fileName is not None:
+            self.fileName = fileName
+            wxLogMessage("Saving %s..." % self.fileName)
+            if self.SaveFile(self.fileName) is not TRUE:
+                self.SaveFileError(self.fileName)
+        self.edl.SetFocus()
+    
+    def OnFileExit(self, event):        
+        if self.edl.BufferWasTouched():
+            if not self.OkCancelDialog("Exit program - abandon changes?", "Exit"):
+                return
+        self.OnCloseWindow(event)
+
+    def OnEditPreferences(self, event):
+        self.MessageDialog("Edit preferences is not implemented yet.", "Not implemented.")
+        pass
+    
+    def OnHelpAbout(self, event):
+        self.MessageDialog(ABOUT_TEXT, "About FrogEdit")
+        pass
+    
+    def Show(self, show):
+        wxFrame.Show(self, show)
+        self.edl.SetFocus()
+
+##------------- Startup stuff
+
+    def LoadInitialFile(self, fileName):
+        if fileName is not None:
+            if self.OpenFile(fileName) is FALSE:
+                self.OpenFileError(fileName)        
+
+
+
+
+##-------------- Application Launcher utility class
+
+class FrogEditLauncher:
+
+    def MakeAppFrame(self):
+        return FrogEditFrame(None, -1, "FrogEdit", size=(640, 480),
+                             style=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE)    
+    def GetArgvFilename(self):
+        if len(sys.argv) > 1:
+            return sys.argv[1]
+        else:
+            return None
+
+    def Main(self):
+        win = self.MakeAppFrame()
+        app = wxPySimpleApp()
+        win.Show(true)
+        win.LoadInitialFile(self.GetArgvFilename())
+        app.MainLoop()
+
+
+##-------------- Main program
+
+
+if __name__ == '__main__':
+
+    launcher = FrogEditLauncher()
+    launcher.Main()
+
diff --git a/wxPython/samples/frogedit/FrogEditor.py b/wxPython/samples/frogedit/FrogEditor.py
new file mode 100644 (file)
index 0000000..d94e83c
--- /dev/null
@@ -0,0 +1,92 @@
+#!/usr/local/bin/python
+
+# simple text editor
+#
+# Copyright 2001 Adam Feuer and Steve Howell
+#
+# License: Python
+
+import re
+from wxPython.wx            import *
+from wxPython.lib.editor    import wxEditor
+
+#---------------------------------------------------------------------
+
+class FrogEditor(wxEditor):
+    def __init__(self, parent, id,
+                 pos=wxDefaultPosition, size=wxDefaultSize, style=0, statusBar=None):
+        self.StatusBar = statusBar
+        wxEditor.__init__(self, parent, id, pos, size, style)
+        self.parent = parent
+
+    ##------------------------------------
+
+    def TouchBuffer(self):
+        wxEditor.TouchBuffer(self)
+        self.StatusBar.setDirty(1)
+
+    def UnTouchBuffer(self):
+        wxEditor.UnTouchBuffer(self)
+        self.StatusBar.setDirty(0)
+
+
+    #--------- utility function -------------
+
+    # override our base class method
+    def DrawCursor(self, dc = None):
+        wxEditor.DrawCursor(self,dc)
+        self.StatusBar.setRowCol(self.cy,self.cx)
+
+    def lastLine(self):
+        lastline = self.sy + self.sh - 1
+        return min(lastline, self.LinesInFile() - 1)
+
+    def rawLines(self):
+        return [l.text for l in self.text]
+
+    def save(self):
+        if self.page:
+            self.ds.store(self.page,self.rawLines())
+
+    def SetRawText(self, rawtext=""):
+        self.rawText= rawtext
+        self.SetText(self.RenderText())
+
+    def RenderText(self):
+        return(self.rawText)
+
+    #---------- logging -------------
+
+    def SetStatus(self, log):
+        self.log = log
+        self.status = []
+
+    def PrintSeparator(self, event):
+        self.Print("..........................")
+
+    def Print(self, data):
+        self.status.append(data)
+        if data[-1:] == '\n':
+            data = data[:-1]
+        wxLogMessage(data)
+
+    #--------- wxEditor keyboard overrides
+
+    def SetControlFuncs(self, action):
+        wxEditor.SetControlFuncs(self, action)
+        action['-'] = self.PrintSeparator
+
+    def SetAltFuncs(self, action):
+        wxEditor.SetAltFuncs(self, action)
+        action['x'] = self.Exit 
+
+    #----------- commands -----------
+
+    def OnCloseWindow(self, event):
+        # xxx - We don't fully understand how exit logic works.
+        # This event is actually called by our parent frame.
+        pass
+
+    def Exit(self,event):
+        self.parent.Close(None)
+
diff --git a/wxPython/samples/frogedit/StatusBar.py b/wxPython/samples/frogedit/StatusBar.py
new file mode 100644 (file)
index 0000000..d8c45d4
--- /dev/null
@@ -0,0 +1,22 @@
+from wxPython.wx import *
+
+import os.path
+
+class CustomStatusBar(wxStatusBar):
+    def __init__(self, parent):
+        wxStatusBar.__init__(self, parent, -1)
+        self.SetFieldsCount(3)
+
+    def setFileName(self, fn):
+        path, fileName = os.path.split(fn)
+        self.SetStatusText(fileName, 0)
+
+    def setRowCol(self, row, col):
+        self.SetStatusText("%d,%d" % (row,col), 1)
+
+    def setDirty(self, dirty):
+        if dirty:
+            self.SetStatusText("...", 2)
+        else:
+            self.SetStatusText(" ", 2)
+
diff --git a/wxPython/wxPython/lib/PyCrust/PyCrust.py b/wxPython/wxPython/lib/PyCrust/PyCrust.py
deleted file mode 100644 (file)
index 5c82403..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env python
-"""PyCrust is a python shell and namespace browser application."""
-
-__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
-__cvsid__ = "$Id$"
-__date__ = "July 1, 2001"
-__version__ = "$Revision$"[11:-2]
-
-from wxPython.wx import *
-from crust import CrustFrame
-
-
-class App(wxApp):
-    """PyCrust standalone application."""
-    
-    def OnInit(self):
-        locals = {'__app__': 'PyCrust Standalone Application'}
-        self.crustFrame = CrustFrame(locals=locals)
-        self.crustFrame.Show(true)
-        # Set focus to the shell editor.
-        #self.crustFrame.crust.shell.SetFocus()
-        self.SetTopWindow(self.crustFrame)
-        # Add the application object to the sys module's namespace.
-        # This allows a shell user to do:
-        # >>> import sys
-        # >>> sys.application.whatever
-        import sys
-        sys.application = self
-        return true
-
-
-def main():
-    application = App(0)
-    application.MainLoop()
-
-if __name__ == '__main__':
-    main()
-
diff --git a/wxPython/wxPython/lib/PyCrust/PyCrustApp.py b/wxPython/wxPython/lib/PyCrust/PyCrustApp.py
new file mode 100755 (executable)
index 0000000..135b86a
--- /dev/null
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+"""PyCrustApp is a python shell and namespace browser application."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__version__ = "$Revision$"[11:-2]
+
+from wxPython.wx import *
+from PyCrust.crust import CrustFrame
+
+
+class App(wxApp):
+    """PyCrust standalone application."""
+    
+    def OnInit(self):
+        locals = {'__app__': 'PyCrust Standalone Application'}
+        self.crustFrame = CrustFrame(locals=locals)
+        self.crustFrame.Show(true)
+        self.SetTopWindow(self.crustFrame)
+        # Add the application object to the sys module's namespace.
+        # This allows a shell user to do:
+        # >>> import sys
+        # >>> sys.application.whatever
+        import sys
+        sys.application = self
+        return true
+
+
+def main():
+    application = App(0)
+    application.MainLoop()
+
+if __name__ == '__main__':
+    main()
+
diff --git a/wxPython/wxPython/lib/PyCrust/PyFilling.py b/wxPython/wxPython/lib/PyCrust/PyFilling.py
deleted file mode 100644 (file)
index bb2c72b..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/usr/bin/env python
-"""PyFilling is a python namespace inspection application."""
-
-__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
-__cvsid__ = "$Id$"
-__date__ = "August 21, 2001"
-__version__ = "$Revision$"[11:-2]
-
-# We use this object to get more introspection when run standalone.
-application = None
-
-import filling
-
-# These are imported just to have something interesting to inspect.
-import crust
-import interpreter
-import introspect
-import pseudo
-import shell
-import sys
-from wxPython import wx
-
-
-def main():
-    """Create and run the application."""
-    global application
-    application = filling.App(0)
-    root = application.fillingFrame.filling.fillingTree.root
-    application.fillingFrame.filling.fillingTree.Expand(root)
-    application.MainLoop()
-
-
-if __name__ == '__main__':
-    main()
-
diff --git a/wxPython/wxPython/lib/PyCrust/PyFillingApp.py b/wxPython/wxPython/lib/PyCrust/PyFillingApp.py
new file mode 100755 (executable)
index 0000000..62cea73
--- /dev/null
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+"""PyFillingApp is a python namespace inspection application."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__version__ = "$Revision$"[11:-2]
+
+# We use this object to get more introspection when run standalone.
+application = None
+
+from PyCrust import filling
+
+# These are imported just to have something interesting to inspect.
+from PyCrust import crust
+from PyCrust import interpreter
+from PyCrust import introspect
+from PyCrust import pseudo
+from PyCrust import shell
+import sys
+from wxPython import wx
+
+
+def main():
+    """Create and run the application."""
+    global application
+    application = filling.App(0)
+    root = application.fillingFrame.filling.fillingTree.root
+    application.fillingFrame.filling.fillingTree.Expand(root)
+    application.MainLoop()
+
+
+if __name__ == '__main__':
+    main()
+
\ No newline at end of file
diff --git a/wxPython/wxPython/lib/PyCrust/PyShell.py b/wxPython/wxPython/lib/PyCrust/PyShell.py
deleted file mode 100644 (file)
index 0fea2d5..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python
-"""PyShell is a python shell application."""
-
-__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
-__cvsid__ = "$Id$"
-__date__ = "July 1, 2001"
-__version__ = "$Revision$"[11:-2]
-
-from wxPython.wx import *
-from shell import ShellFrame
-
-
-class App(wxApp):
-    """PyShell standalone application."""
-    
-    def OnInit(self):
-        locals = {'__app__': 'PyShell Standalone Application'}
-        self.shellFrame = ShellFrame(locals=locals)
-        self.shellFrame.Show(true)
-        self.SetTopWindow(self.shellFrame)
-        # Add the application object to the sys module's namespace.
-        # This allows a shell user to do:
-        # >>> import sys
-        # >>> sys.application.whatever
-        import sys
-        sys.application = self
-        return true
-
-
-def main():
-    application = App(0)
-    application.MainLoop()
-
-if __name__ == '__main__':
-    main()
-
diff --git a/wxPython/wxPython/lib/PyCrust/PyShellApp.py b/wxPython/wxPython/lib/PyCrust/PyShellApp.py
new file mode 100755 (executable)
index 0000000..9b3f945
--- /dev/null
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+"""PyShellApp is a python shell application."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__version__ = "$Revision$"[11:-2]
+
+from wxPython.wx import *
+from PyCrust.shell import ShellFrame
+
+
+class App(wxApp):
+    """PyShell standalone application."""
+    
+    def OnInit(self):
+        locals = {'__app__': 'PyShell Standalone Application'}
+        self.shellFrame = ShellFrame(locals=locals)
+        self.shellFrame.Show(true)
+        self.SetTopWindow(self.shellFrame)
+        # Add the application object to the sys module's namespace.
+        # This allows a shell user to do:
+        # >>> import sys
+        # >>> sys.application.whatever
+        import sys
+        sys.application = self
+        return true
+
+
+def main():
+    application = App(0)
+    application.MainLoop()
+
+if __name__ == '__main__':
+    main()
+
\ No newline at end of file
index df1431c41ec0f0bfafc4765d1b8e847af38a5628..828b99a46b4b105d3674f7bedea353730d8486d5 100644 (file)
@@ -1,6 +1,10 @@
 PyCrust - The Flakiest Python Shell
 Half-baked by Patrick K. O'Brien (pobrien@orbtech.com)
-======================================================
+
+==============================================================
+* Orbtech - "Your Source For Python Development Services"    *
+* Sample all our half-baked Python goods at www.orbtech.com. *
+==============================================================
 
 What is PyCrust?
 ----------------
@@ -20,7 +24,7 @@ shouldn't build a Python program without a PyCrust either.
 
 
 Where can I get the latest release of PyCrust?
-------------------------------------------------------------
+----------------------------------------------
 The latest PyCrust releases are available at:
 http://sourceforge.net/project/showfiles.php?group_id=31263
 
index ceb62dc6d7c1000a649fba5e3c728a25ff5c82c1..a97ac7fba7e5fdc0838ae1ebd7d19200cfe10070 100644 (file)
@@ -2,7 +2,6 @@
 
 __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
 __cvsid__ = "$Id$"
-__date__ = "July 1, 2001"
 __version__ = "$Revision$"[11:-2]
 
 from wxPython.wx import *
@@ -46,15 +45,20 @@ class CrustFrame(wxFrame, ShellMenu):
     revision = __version__
     
     def __init__(self, parent=None, id=-1, title='PyCrust', \
+                 pos=wxDefaultPosition, size=wxDefaultSize, \
+                 style=wxDEFAULT_FRAME_STYLE, \
                  rootObject=None, rootLabel=None, rootIsNamespace=1, \
                  locals=None, InterpClass=None, *args, **kwds):
         """Create a PyCrust CrustFrame instance."""
-        wxFrame.__init__(self, parent, id, title)
+        wxFrame.__init__(self, parent, id, title, pos, size, style)
         intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION
+        intro += '\nSponsored by Orbtech.com \96 Your Source For Python Development Services'
         self.CreateStatusBar()
         self.SetStatusText(intro)
         if wxPlatform == '__WXMSW__':
-            icon = wxIcon('PyCrust.ico', wxBITMAP_TYPE_ICO)
+            import os
+            filename = os.path.join(os.path.dirname(__file__), 'PyCrust.ico')
+            icon = wxIcon(filename, wxBITMAP_TYPE_ICO)
             self.SetIcon(icon)
         self.crust = Crust(parent=self, intro=intro, \
                            rootObject=rootObject, \
@@ -75,3 +79,4 @@ class CrustFrame(wxFrame, ShellMenu):
         self.createMenus()
 
 
+   
index f0f24eb952c1eaa6c722d1fa20583b3f45e8cfd7..c49708c8d89c742804c3dbf2e21a5fe3fac23de5 100644 (file)
@@ -3,7 +3,6 @@ the local namespace or any object."""
 
 __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
 __cvsid__ = "$Id$"
-__date__ = "August 21, 2001"
 __version__ = "$Revision$"[11:-2]
 
 from wxPython.wx import *
@@ -217,6 +216,7 @@ class FillingText(wxStyledTextCtrl):
         self.SetViewWhiteSpace(0)
         self.SetTabWidth(4)
         self.SetUseTabs(0)
+        self.SetReadOnly(1)
 
     def setStyles(self, faces):
         """Configure font size, typeface and color for lexer."""
@@ -248,6 +248,11 @@ class FillingText(wxStyledTextCtrl):
         self.StyleSetSpec(wxSTC_P_COMMENTBLOCK, "fore:#7F7F7F")
         self.StyleSetSpec(wxSTC_P_STRINGEOL, "fore:#000000,face:%(mono)s,back:#E0C0E0,eolfilled" % faces)
 
+    def SetText(self, *args, **kwds):
+        self.SetReadOnly(0)
+        wxStyledTextCtrl.SetText(self, *args, **kwds)
+        self.SetReadOnly(1)
+
 
 class Filling(wxSplitterWindow):
     """PyCrust Filling based on wxSplitterWindow."""
@@ -288,7 +293,9 @@ class FillingFrame(wxFrame):
         self.CreateStatusBar()
         self.SetStatusText(intro)
         if wxPlatform == '__WXMSW__':
-            icon = wxIcon('PyCrust.ico', wxBITMAP_TYPE_ICO)
+            import os
+            filename = os.path.join(os.path.dirname(__file__), 'PyCrust.ico')
+            icon = wxIcon(filename, wxBITMAP_TYPE_ICO)
             self.SetIcon(icon)
         self.filling = Filling(parent=self, rootObject=rootObject, \
                                rootLabel=rootLabel, \
@@ -308,3 +315,4 @@ class App(wxApp):
 
 
   
+   
\ No newline at end of file
index 1454495d4638609688385de9e6ad98402c7622cf..8274e35ed14b97165c4c1073ea9018940d5a0bea 100644 (file)
@@ -2,7 +2,6 @@
 
 __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
 __cvsid__ = "$Id$"
-__date__ = "July 1, 2001"
 __version__ = "$Revision$"[11:-2]
 
 import os
@@ -103,4 +102,4 @@ class InterpreterAlaCarte(Interpreter):
         sys.ps1 = ps1
         sys.ps2 = ps2
 
-  
\ No newline at end of file
+   
\ No newline at end of file
index 5c48cb8da00e12524d58222158e3fef7bae5345a..4139ec66c892465c8833a6840479751e2391abad 100644 (file)
@@ -3,7 +3,6 @@ like call tips and command auto completion."""
 
 __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
 __cvsid__ = "$Id$"
-__date__ = "August 8, 2001"
 __version__ = "$Revision$"[11:-2]
 
 import inspect
@@ -168,3 +167,4 @@ def getRoot(command, terminator=None):
     return root
 
      
\ No newline at end of file
index c709a8351ca40a507069bbac83738e901c9b9be0..d231dc26474c1eac18163d28fd32aae2a5c7c70f 100644 (file)
@@ -2,7 +2,6 @@
 
 __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
 __cvsid__ = "$Id$"
-__date__ = "July 1, 2001"
 __version__ = "$Revision$"[11:-2]
 
 class PseudoKeyword:
@@ -88,3 +87,4 @@ class PseudoFileErr(PseudoFile):
         return 1
         
         
\ No newline at end of file
index a071fb7ea14d89783b594aacad4ed74b0b7fba60..8fe9f1caa0c5a006aa36396d355db842ec89f1aa 100644 (file)
@@ -5,7 +5,6 @@ SourceForge project page at http://sourceforge.net/projects/pycrust/."""
 
 __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
 __cvsid__ = "$Id$"
-__date__ = "July 1, 2001"
 __version__ = "$Revision$"[11:-2]
 
 from wxPython.wx import *
@@ -326,6 +325,20 @@ class Shell(wxStyledTextCtrl):
         # If the auto-complete window is up let it do its thing.
         elif self.AutoCompActive():
             event.Skip()
+        # Cut to the clipboard.
+        elif event.ControlDown() and key in (ord('X'), ord('x')):
+            self.Cut()
+        # Copy to the clipboard.
+        elif event.ControlDown() and not event.ShiftDown() \
+        and key in (ord('C'), ord('c')):
+            self.Copy()
+        # Copy to the clipboard, including prompts.
+        elif event.ControlDown() and event.ShiftDown() \
+        and key in (ord('C'), ord('c')):
+            self.CopyWithPrompts()
+        # Paste from the clipboard.
+        elif event.ControlDown() and key in (ord('V'), ord('v')):
+            self.Paste()
         # Retrieve the previous command from the history buffer.
         elif (event.ControlDown() and key == WXK_UP) \
         or (event.AltDown() and key in (ord('P'), ord('p'))):
@@ -363,6 +376,9 @@ class Shell(wxStyledTextCtrl):
         # Don't toggle between insert mode and overwrite mode.
         elif key == WXK_INSERT:
             pass
+        # Protect the readonly portion of the shell.
+        elif not self.CanEdit():
+            pass
         else:
             event.Skip()
 
@@ -509,22 +525,26 @@ class Shell(wxStyledTextCtrl):
         The command may not necessarily be valid Python syntax."""
         if not text:
             text = self.GetCurLine()[0]
-        # XXX Need to extract real prompts here. Need to keep track of the
-        # prompt every time a command is issued.
+        # Strip the prompt off the front of text leaving just the command.
+        command = self.lstripPrompt(text)
+        if command == text:
+            command = ''  # Real commands have prompts.
+        if rstrip:
+            command = command.rstrip()
+        return command
+
+    def lstripPrompt(self, text):
+        """Return text without a leading prompt."""
         ps1 = str(sys.ps1)
         ps1size = len(ps1)
         ps2 = str(sys.ps2)
         ps2size = len(ps2)
-        # Strip the prompt off the front of text leaving just the command.
+        # Strip the prompt off the front of text.
         if text[:ps1size] == ps1:
-            command = text[ps1size:]
+            text = text[ps1size:]
         elif text[:ps2size] == ps2:
-            command = text[ps2size:]
-        else:
-            command = ''
-        if rstrip:
-            command = command.rstrip()
-        return command
+            text = text[ps2size:]
+        return text
     
     def push(self, command):
         """Send command to the interpreter for execution."""
@@ -738,6 +758,17 @@ class Shell(wxStyledTextCtrl):
         if self.CanCopy():
             command = self.GetSelectedText()
             command = command.replace(os.linesep + sys.ps2, os.linesep)
+            command = command.replace(os.linesep + sys.ps1, os.linesep)
+            command = self.lstripPrompt(text=command)
+            data = wxTextDataObject(command)
+            if wxTheClipboard.Open():
+                wxTheClipboard.SetData(data)
+                wxTheClipboard.Close()
+
+    def CopyWithPrompts(self):
+        """Copy selection, including prompts, and place it on the clipboard."""
+        if self.CanCopy():
+            command = self.GetSelectedText()
             data = wxTextDataObject(command)
             if wxTheClipboard.Open():
                 wxTheClipboard.SetData(data)
@@ -752,6 +783,7 @@ class Shell(wxStyledTextCtrl):
                     if wxTheClipboard.GetData(data):
                         command = data.GetText()
                         command = self.fixLineEndings(command)
+                        command = self.lstripPrompt(text=command)
                         command = command.replace(os.linesep + sys.ps2, '\n')
                         command = command.replace(os.linesep, '\n')
                         command = command.replace('\n', os.linesep + sys.ps2)
@@ -952,10 +984,13 @@ class ShellFrame(wxFrame, ShellMenu):
         """Create a PyCrust ShellFrame instance."""
         wxFrame.__init__(self, parent, id, title, pos, size, style)
         intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION
+        intro += '\nSponsored by Orbtech.com \96 Your Source For Python Development Services'
         self.CreateStatusBar()
         self.SetStatusText(intro)
         if wxPlatform == '__WXMSW__':
-            icon = wxIcon('PyCrust.ico', wxBITMAP_TYPE_ICO)
+            import os
+            filename = os.path.join(os.path.dirname(__file__), 'PyCrust.ico')
+            icon = wxIcon(filename, wxBITMAP_TYPE_ICO)
             self.SetIcon(icon)
         self.shell = Shell(parent=self, id=-1, introText=intro, \
                            locals=locals, InterpClass=InterpClass, \
@@ -966,3 +1001,4 @@ class ShellFrame(wxFrame, ShellMenu):
 
 
            
+    
index 177f1155bb3a911ecb68074c358f08e04ab8e89f..09d515a5cd384b7fe95f25bd6c9f04623fe0cbcb 100644 (file)
@@ -4,7 +4,7 @@ interpreter, each have a revision property based on the CVS Revision."""
 
 __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
 __cvsid__ = "$Id$"
-__date__ = "July 1, 2001"
 __version__ = "$Revision$"[11:-2]
 
 VERSION = '0.7'
\ No newline at end of file
index 6072b4360d5011428fa6314c0b90cbe081b3e6c5..6bf61637c77e4317075154c2c1d50c2290bd9f9f 100644 (file)
@@ -1,10 +1,77 @@
-PLEASE NOTE:  This is experimental code.  It needs an overhall in the
-              drawing and update code, and there is occasionally a
-              mysteriously disappearing line...
+wxEditor component
+------------------
 
-              I am working on a StyledTextEditor that will likely
-              render this editor obsolete...  But this one is at
-              least somewhat functional now while the other is still
-              vapor.
+The wxEditor class implements a simple text editor using wxPython.  You
+can create a custom editor by subclassing wxEditor.  Even though much of
+the editor is implemented in Python, it runs surprisingly smoothly on  
+normal hardware with small files.
 
-              - Robin
+
+Keys
+----
+Keys are similar to Windows-based editors:
+
+Tab:                 1 to 4 spaces (to next tab stop)
+Cursor movement:     Arrow keys
+Beginning of line:   Home
+End of line:         End
+Beginning of buffer: Control-Home
+End of the buffer:   Control-End 
+Select text:         Hold down Shift while moving the cursor
+Copy:                Shift-Insert,   Control-C
+Cut:                 Shift-Delete,   Control-X
+Paste:               Control-Insert, Control-V
+
+How to use it
+-------------
+The demo code (demo/wxEditor.py) shows how to use it as a simple text
+box. Use the SetText() and GetText() methods to set or get text from
+the component; these both return a list of strings.
+
+The samples/FrogEdit directory has an example of a simple text editor
+application that uses the wxEditor component.
+
+Subclassing
+-----------
+To add or change functionality, you can subclass this
+component. One example of this might be to change the key
+Alt key commands. In that case you would (for example) override the
+SetAltFuncs() method.
+
+History
+-------
+The original author of this component was Dirk Holtwic. It originally
+had limited support for syntax highlighting, but was not a usable text
+editor, as it didn't implement select (with keys or mouse), or any of
+the usual key sequences you'd expect in an editor. Robin Dunn did some
+refactoring work to make it more usable. Steve Howell and Adam Feuer
+did a lot of refactoring, and added some functionality, including
+keyboard and mouse select, properly working scrollbars, and
+overridable keys. Adam and Steve also removed support for
+syntax-highlighting while refactoring the code.
+
+To do
+-----
+Alt/Ctrl Arrow keys move by word
+Descriptive help text for keys
+Speed improvements
+Different fonts/colors
+
+
+Authors
+-------
+Steve Howell, Adam Feuer, Dirk Holtwic, Robin Dunn
+
+
+Contact
+-------
+You can find the latest code for wxEditor here:
+http://www.pobox.com/~adamf/software/
+
+We're not actively maintaining this code, but we can answer
+questions about it. You can email us at:
+
+Adam Feuer <adamf at pobox dot com>
+Steve Howell <showell at zipcon dot net>
+
+29 November 2001
index 30bd0310d0f329e73b27e0c4e75d85eb4d8da96c..c3b75eb2adfba63483d7ae320b5e208dd388ae4a 100644 (file)
@@ -15,4 +15,3 @@
 
 # import the main classes into the package namespace.
 from editor    import wxEditor
-from py_editor import wxPyEditor
index bfae39281720bb9b1bd4f2c173c926611c28d38d..e531bff7ff826f01c5b082b9aba483e851f5a8cf 100644 (file)
@@ -2,7 +2,18 @@
 # Name:        wxPython.lib.editor.wxEditor
 # Purpose:     An intelligent text editor with colorization capabilities.
 #
-# Author:      Dirk Holtwic, Robin Dunn
+# Original
+# Authors:      Dirk Holtwic, Robin Dunn
+#
+# New
+# Authors:      Adam Feuer, Steve Howell
+#
+# History:
+#   This code used to support a fairly complex subclass that did
+#   syntax coloring and outliner collapse mode.  Adam and Steve
+#   inherited the code, and added a lot of basic editor
+#   functionality that had not been there before, such as cut-and-paste.
+#   
 #
 # Created:     15-Dec-1999
 # RCS-ID:      $Id$
 # Licence:     wxWindows license
 #----------------------------------------------------------------------
 
-
-# PLEASE NOTE:  This is experimental code.  It needs an overhall in the
-#               drawing and update code, and there is occasionally a
-#               mysteriously disappearing line...
-#
-#               I am working on a StyledTextEditor that will likely
-#               render this editor obsolete...  But this one is at
-#               least somewhat functional now while the other is still
-#               vapor.
-#
-#               - Robin
-
+import os, time
 
 from wxPython.wx import *
 from string import *
-from keyword import *
-from regsub import *
-from tokenizer import *
 
-#---------------------------------------------------------------------------
+import selection
+import images
 
+#----------------------------
 
-class Line:
-    def __init__(self, text=""):
-        self.text       = text      # the string itself
-        self.syntax     = []        # the colors of the line
-        self.editable   = true      # edit?
-        self.visible    = 0         # will be incremented if not
-        self.indent     = 0         # not used yet
+def ForceBetween(min, val, max):                            
+    if val  > max:
+        return max
+    if val < min:
+        return min
+    return val
+
+#----------------------------
+
+class Scroller:
+    def __init__(self, parent):
+        self.parent = parent
+        self.ow = 0
+        self.oh = 0
+        self.ox = 0
+        self.oy = 0
+
+    def SetScrollbars(self, fw, fh, w, h, x, y):
+        if (self.ow != w or self.oh != h or self.ox != x or self.oy != y):
+            self.parent.SetScrollbars(fw, fh, w, h, x, y)
+            self.ow = w
+            self.oh = h
+            self.ox = x
+            self.oy = y
 
 #----------------------------------------------------------------------
 
@@ -46,229 +62,180 @@ class wxEditor(wxScrolledWindow):
 
     def __init__(self, parent, id,
                  pos=wxDefaultPosition, size=wxDefaultSize, style=0):
-    ###############################################################
-        """
-        Alles hat einen Anfang
-        """
 
         wxScrolledWindow.__init__(self, parent, id,
                                   pos, size,
                                   style|wxWANTS_CHARS)
 
-        # the syntax informations, if they don't exist,
-        # all syntax stuff will be ignored
+        self.InitCoords()
+        self.InitFonts()
+        self.SetColors()
+        self.MapEvents()
+        self.LoadImages()
+        self.InitDoubleBuffering()
+        self.InitScrolling()
+        self.SelectOff()
+        self.CopiedData = None
+        self.SetFocus()
+        self.SetText([""])
+        self.SpacesPerTab = 4
+
+##------------------ Init stuff
 
-        # cursor pos
+    def InitCoords(self):
         self.cx = 0
         self.cy = 0
-
-        # the lines that are visible
-        self.lines = []
-        self.line = 0
-        self.len = 0
-
-        self.ocy = 0
-
-        # border pos
-        #self.bx = 0
-        #self.by = 0
-
-        # screen
+        self.oldCx = 0
+        self.oldCy = 0
         self.sx = 0
         self.sy = 0
         self.sw = 0
         self.sh = 0
-        self.osx= 0
-        self.osy= 0
-
-        # font
-        dc = wxClientDC(self)
-
-        if wxPlatform == "__WXMSW__":
-            self.font = wxFont(10, wxMODERN, wxNORMAL, wxNORMAL)
-        else:
-            self.font = wxFont(12, wxMODERN, wxNORMAL, wxNORMAL, false)
-        dc.SetFont(self.font)
-
-        # font weight, height
-        self.fw = dc.GetCharWidth()
-        self.fh = dc.GetCharHeight()
-
-        #  back, for colour
-        self.bcol = wxNamedColour('white')
-        self.fcol = wxNamedColour('black')
-
-        self.cfcol = wxNamedColour('black')
-        self.cbcol = wxNamedColour('red')
-
-        # nicht edierbare zeile (hintergrund)
-        self.nedcol = wxNamedColour('grey')
-
-        self.SetBackgroundColour(self.bcol)
-        #dc.SetForegroundColour(self.fcol)
+        self.sco_x = 0
+        self.sco_y = 0
 
-        # events
-        EVT_LEFT_DOWN(self, self.OnMouseClick)
-        EVT_RIGHT_DOWN(self, self.OnMouseClick)
+    def MapEvents(self):
+        EVT_LEFT_DOWN(self, self.OnLeftDown)
+        EVT_LEFT_UP(self, self.OnLeftUp)
+        EVT_MOTION(self, self.OnMotion)
         EVT_SCROLLWIN(self, self.OnScroll)
         EVT_CHAR(self, self.OnChar)
         EVT_PAINT(self, self.OnPaint)
+        EVT_SIZE(self, self.OnSize)
+        EVT_WINDOW_DESTROY(self, self.OnDestroy)
 
-        self.o_cx = self.cx
-        self.o_cy = self.cy
-        self.o_sx = self.sx
-        self.o_sy = self.sy
-        self.o_line = self.line
-        self.sco_x = 0
-        self.sco_y = 0
-
-        self.tabsize = 4
+##------------------- Platform-specific stuff
 
-        self.update = true
-        self.in_scroll =FALSE
-        self.inUpdate = FALSE
-
-
-        bw,bh = self.GetSizeTuple()
-        # double buffering
-        self.mdc = wxMemoryDC()
-        self.mdc.SelectObject(wxEmptyBitmap(bw,bh))
-        # disable physical scrolling because invisible parts are not drawn
-        self.EnableScrolling(FALSE, FALSE)
-
-        # the ordinary text as it is
-        self.SetText()
+    def NiceFontForPlatform(self):
+        if wxPlatform == "__WXMSW__":
+            return wxFont(10, wxMODERN, wxNORMAL, wxNORMAL)
+        else:
+            return wxFont(12, wxMODERN, wxNORMAL, wxNORMAL, false)
+          
+    def UnixKeyHack(self, key):
+        # this will be obsolete when we get the new wxWindows patch
+        if key <= 26:
+            key += ord('a') - 1
+        return key
+
+##-------------------- UpdateView/Cursor code
+
+    def OnSize(self, event):
+        self.AdjustScrollbars()
         self.SetFocus()
 
+    def SetCharDimensions(self):
+        # TODO: We need a code review on this.  It appears that Linux
+        # improperly reports window dimensions when the scrollbar's there.
+        self.bw, self.bh = self.GetClientSizeTuple()
 
-#---------------------------------------------------------------------------
-
-    def CalcLines(self):
-    ###############################################################
-        self.lines = []
-        x =maxlen =0
-        for line in self.text:
-            if line.visible==0:
-                self.lines.append(x)
-            else:
-                if len(line.text) >maxlen:
-                    maxlen =len(line.text)
-            x = x + 1
-        self.len = len(self.lines)
-        self.max_linelength =maxlen
-
-
-    def SetFontTab(self, fonttab):
-    ###############################################################
-        """ Fonttabelle zum schnellen Zugriff """
-        self.ftab = fonttab
-
-
-    def SetText(self, text = [""]):
-    ###############################################################
-        """ Text mittels Liste setzen """
-        self.cx = 0
-        self.cy = 0
-        self.text = []
-
-        for t in text:
-            self.text.append(Line(t))
-
-        for l in range(0,len(text)-1):
-            #self.UpdateSyntax(l)
-            self.OnUpdateHighlight(l)
-
-        self.OnInit()
-
-        self.update = true
-        self.UpdateView(None, true)
-
-
-    # show new text
-    def GetText(self):
-    ###############################################################
-        """ Der gesamte Text als Liste """
-        text = []
-        for line in self.text:
-            text.append(line.text)
-        return text
-
+        if wxPlatform == "__WXMSW__":
+            self.sh = self.bh / self.fh
+            self.sw = (self.bw / self.fw) - 1
+        else:
+            self.sh = self.bh / self.fh
+            if self.LinesInFile() >= self.sh:
+                self.bw = self.bw - wxSystemSettings_GetSystemMetric(wxSYS_VSCROLL_X)
+                self.sw = (self.bw / self.fw) - 1
 
-    def IsEmpty(self):
-    ###############################################################
-        """see if at least one text line is not empty"""
-        for line in self.text:
-            if line.text: return 0
-        return 1
+            self.sw = (self.bw / self.fw) - 1
+            if self.CalcMaxLineLen() >= self.sw:
+                self.bh = self.bh - wxSystemSettings_GetSystemMetric(wxSYS_HSCROLL_Y)
+                self.sh = self.bh / self.fh
 
 
-    def IsLine(self, line):
-    ###############################################################
-        """ Schauen, ob alles im grünen Bereich ist """
-        return (line>=0) and (line<self.len)
+    def UpdateView(self, dc = None):
+        if not dc:
+            dc = wxClientDC(self)
+        self.SetCharDimensions()
+        self.KeepCursorOnScreen()
+        self.DrawSimpleCursor(0,0,dc, true)
+        self.Draw(dc)
+        
+    def OnPaint(self, event):
+        dc = wxPaintDC(self)
+        self.UpdateView(dc)
+        self.AdjustScrollbars()
 
+##-------------------- Drawing code
 
-    def IsEditable(self, line):
-    ###############################################################
-        return self.text[self.GetLine(line)].editable
+    def InitFonts(self):
+        dc = wxClientDC(self)
+        self.font = self.NiceFontForPlatform()
+        dc.SetFont(self.font)
+        self.fw = dc.GetCharWidth()
+        self.fh = dc.GetCharHeight()
 
+    def SetColors(self):
+        self.fgColor = wxNamedColour('black')
+        self.bgColor = wxNamedColour('white')
+        self.selectColor = wxColour(238, 220, 120)  # r, g, b = emacsOrange
 
-    def GetLine(self, line):
-    ###############################################################
-        return self.lines[line]
+    def InitDoubleBuffering(self):
+        bw,bh = self.GetClientSizeTuple()
+        self.mdc = wxMemoryDC()
+        self.mdc.SelectObject(wxEmptyBitmap(bw,bh))
 
+    def DrawEditText(self, t, x, y, dc):
+        dc.DrawText(t, x * self.fw, y * self.fh)
 
-    def GetTextLine(self, line):
-    ###############################################################
-        """ Text holen """
+    def DrawLine(self, line, dc):
         if self.IsLine(line):
-            return self.text[self.GetLine(line)].text
-        return ""
-
+            l   = line
+            t   = self.lines[l]
+            dc.SetTextForeground(self.fgColor)
+            fragments = selection.Selection(
+                self.SelectBegin, self.SelectEnd,
+                self.sx, self.sw, line, t)
+            x = 0
+            for (data, selected) in fragments:
+                if selected:
+                    dc.SetTextBackground(self.selectColor)
+                    if x == 0 and len(data) == 0 and len(fragments) == 1:
+                        data = ' '
+                else:
+                    dc.SetTextBackground(self.bgColor)
+                self.DrawEditText(data, x, line - self.sy, dc)
+                x += len(data)
 
-    def SetTextLine(self, line, text):
-    ###############################################################
-        """ Nur den Text Ã¤ndern """
-        if self.IsLine(line):
-            l = self.GetLine(line)
-            self.text[l].text = text
-            #self.UpdateSyntax(l)
-            self.OnUpdateHighlight(l)
-            self.update = true
+    def Draw(self, odc=None):
+        if not odc:
+            odc = wxClientDC(self)
 
+        dc = self.mdc
+        dc.SetFont(self.font)
+        dc.SelectObject(wxEmptyBitmap(self.bw,self.bh))
+        dc.SetBackgroundMode(wxSOLID)
+        dc.SetTextBackground(self.bgColor)
+        dc.SetTextForeground(self.fgColor)
+        dc.Clear()
+        for line in range(self.sy, self.sy + self.sh):
+            self.DrawLine(line, dc)
+        if len(self.lines) < self.sh + self.sy:
+            self.DrawEofMarker(dc)
+        odc.Blit(0,0,self.bw,self.bh,dc,0,0,wxCOPY)
+        self.DrawCursor(odc)
 
-#---------------------------------------------------------------------------
+##------------------ eofMarker stuff
 
-    def OnMouseClick(self, event):
-    ###############################################################
-        """
-        Wenn es Click gemacht hat => Cursor setzen
-        """
-        self.SetFocus()
+    def LoadImages(self):
+        self.eofMarker = images.GetBitmap(images.EofImageData)
 
-        self.cy = self.sy + (event.GetY() / self.fh)
-        if self.cy >= self.len: self.cy =max(self.len -1, 0)
-        linelen =len(self.text[self.GetLine(self.cy)].text)
-        self.cx = self.sx + (event.GetX() / self.fw)
-        # allow positioning right behind the last character
-        if self.cx > linelen: self.cx =linelen
-        if event.GetEventType() ==wxEVT_RIGHT_DOWN:
-            self.update = true
-            self.OnFold()
-        self.UpdateView()
+    def DrawEofMarker(self,dc):
+        x = 0
+        y = (len(self.lines) - self.sy) * self.fh
+        hasTransparency = 1
+        dc.DrawBitmap(self.eofMarker, x, y, hasTransparency)
 
+##------------------ cursor-related functions
 
     def DrawCursor(self, dc = None):
-    ###############################################################
-        """
-        Auch der Cursor muß ja irgendwie gezeichnet werden
-        """
         if not dc:
             dc = wxClientDC(self)
 
-        if (self.len)<self.cy: #-1 ?
-            self.cy = self.len-1
-        s = self.text[self.GetLine(self.cy)].text
+        if (self.LinesInFile())<self.cy: #-1 ?
+            self.cy = self.LinesInFile()-1
+        s = self.lines[self.cy]
 
         x = self.cx - self.sx
         y = self.cy - self.sy
@@ -276,10 +243,6 @@ class wxEditor(wxScrolledWindow):
 
 
     def DrawSimpleCursor(self, xp, yp, dc = None, old=false):
-    ###############################################################
-        """
-        Auch der Cursor muß ja irgendwie gezeichnet werden
-        """
         if not dc:
             dc = wxClientDC(self)
 
@@ -295,376 +258,666 @@ class wxEditor(wxScrolledWindow):
         self.sco_x = xp
         self.sco_y = yp
 
+##-------- Enforcing screen boundaries, cursor movement
+
+    def CalcMaxLineLen(self):
+        """get length of longest line on screen"""
+        maxlen = 0
+        for line in self.lines[self.sy:self.sy+self.sh]:
+            if len(line) >maxlen:
+                maxlen = len(line)
+        return maxlen
+
+    def KeepCursorOnScreen(self):
+        self.sy = ForceBetween(max(0, self.cy-self.sh), self.sy, self.cy)
+        self.sx = ForceBetween(max(0, self.cx-self.sw), self.sx, self.cx)
+        self.AdjustScrollbars()
+            
+    def HorizBoundaries(self):
+        self.SetCharDimensions()
+        maxLineLen = self.CalcMaxLineLen()
+        self.sx = ForceBetween(0, self.sx, max(self.sw, maxLineLen - self.sw + 1))
+        self.cx = ForceBetween(self.sx, self.cx, self.sx + self.sw - 1)
+
+    def VertBoundaries(self):
+        self.SetCharDimensions()
+        self.sy = ForceBetween(0, self.sy, max(self.sh, self.LinesInFile() - self.sh + 1))
+        self.cy = ForceBetween(self.sy, self.cy, self.sy + self.sh - 1)
+       
+    def cVert(self, num):
+        self.cy = self.cy + num
+        self.cy = ForceBetween(0, self.cy, self.LinesInFile() - 1)
+        self.sy = ForceBetween(self.cy - self.sh + 1, self.sy, self.cy) 
+        self.cx = min(self.cx, self.CurrentLineLength())
 
-    def OnScroll(self, event):
-        dir =event.GetOrientation()
-        evt =event.GetEventType()
-        if dir ==wxHORIZONTAL:
-            if evt ==wxEVT_SCROLLWIN_LINEUP:     self.sx =self.sx -1
-            elif evt ==wxEVT_SCROLLWIN_LINEDOWN: self.sx =self.sx +1
-            elif evt ==wxEVT_SCROLLWIN_PAGEUP:   self.sx =self.sx -self.sw
-            elif evt ==wxEVT_SCROLLWIN_PAGEDOWN: self.sx =self.sx +self.sw
-            elif evt ==wxEVT_SCROLLWIN_TOP:      self.sx =self.cx =0
-            elif evt ==wxEVT_SCROLLWIN_BOTTOM:
-                self.sx =self.max_linelength -self.sw
-                self.cx =self.max_linelength
-            else:
-                self.sx =event.GetPosition()
-
-            if self.sx >(self.max_linelength -self.sw +1):
-                self.sx =self.max_linelength -self.sw +1
-            if self.sx <0:   self.sx =0
-            if self.cx >(self.sx +self.sw -1): self.cx =self.sx +self.sw -1
-            if self.cx <self.sx: self.cx =self.sx
-
-        else:
-            if evt ==wxEVT_SCROLLWIN_LINEUP:     self.sy =self.sy -1
-            elif evt ==wxEVT_SCROLLWIN_LINEDOWN: self.sy =self.sy +1
-            elif evt ==wxEVT_SCROLLWIN_PAGEUP:   self.sy =self.sy -self.sh
-            elif evt ==wxEVT_SCROLLWIN_PAGEDOWN: self.sy =self.sy +self.sh
-            elif evt ==wxEVT_SCROLLWIN_TOP:      self.sy =self.cy =0
-            elif evt ==wxEVT_SCROLLWIN_BOTTOM:
-                self.sy =self.len -self.sh
-                self.cy =self.len
-            else:
-                self.sy =event.GetPosition()
-
-            if self.sy >(self.len -self.sh +1):
-                self.sy =self.len -self.sh +1
-            if self.sy <0: self.sy =0
-            if self.cy >(self.sy +self.sh -1): self.cy =self.sy +self.sh -1
-            if self.cy <self.sy: self.cy =self.sy
-
-        self.UpdateView()
-
-
-    def AdjustScrollbars(self):
-        # there appears to be endless recursion:
-        # SetScrollbars issue EvtPaint which calls UpdateView
-        # which calls AdjustScrollbars
-        if not self.in_scroll:
-            self.in_scroll =TRUE
-            self.SetScrollbars(self.fw, self.fh, self.max_linelength +1,
-                               # it seem to be a bug in scrollbars:
-                               # the scrollbar is hidden
-                               # even if current position >0
-                               max(self.len +1, self.sy +self.sh),
-                               self.sx, self.sy)
-            self.osx, self.osy = self.sx, self.sy
-            self.in_scroll =FALSE
-
-
-    # adapts the output to what it should be
-    def UpdateView(self, dc = None, doup=false):
-    ###############################################################
-        """
-        Diese Routine wird immer dann aufgerufen, wenn
-        sich etwas verändert hat
-        """
-        if self.inUpdate:
-            return
-        self.inUpdate = true
-
-        self.CalcLines()
+    def cHoriz(self, num):
+        self.cx = self.cx + num
+        self.cx = ForceBetween(0, self.cx, self.CurrentLineLength())
+        self.sx = ForceBetween(self.cx - self.sw + 1, self.sx, self.cx)
 
-        if not dc:
-            dc = wxClientDC(self)
+    def AboveScreen(self, row):
+        return row < self.sy
 
-        self.bw,self.bh = self.GetSizeTuple()
-        self.sw = self.bw / self.fw
-        self.sh = self.bh / self.fh
+    def BelowScreen(self, row):
+        return row >= self.sy + self.sh
 
-        if self.cy<self.sy:
-            self.sy = self.cy
-        elif self.cy>(self.sy+self.sh-1):
-            self.sy = self.cy-self.sh+1
+    def LeftOfScreen(self, col):
+        return col < self.sx
 
-        if self.cx<self.sx:
-            self.sx = self.cx
-        elif self.cx>(self.sx+self.sw-1):
-            self.sx = self.cx-self.sw+1
+    def RightOfScreen(self, col):
+        return col >= self.sx + self.sw
 
-        # left line? change syntax!
-        if self.ocy!=self.cy:
-            self.OnUpdateSyntax(self.ocy)
-        self.ocy = self.cy
+##----------------- data structure helper functions
 
-        # alles beim alten
-        if self.osx != self.sx or self.osy != self.sy:
-            self.AdjustScrollbars()
+    def GetText(self):
+        return self.lines
+
+    def SetText(self, lines):
+        self.InitCoords()
+        self.lines = lines
+        self.UnTouchBuffer()
+        self.SelectOff()
+        self.AdjustScrollbars()
+        self.UpdateView(None)
+
+    def IsLine(self, lineNum):
+        return (0<=lineNum) and (lineNum<self.LinesInFile())
+
+    def GetTextLine(self, lineNum):
+        if self.IsLine(lineNum):
+            return self.lines[lineNum]
+        return ""
 
-        self.DrawSimpleCursor(0,0,dc, true)
-        # [als] i don't really understand how the following condition works
-        #if self.update or doup:
-        self.Draw(dc)
-        #    self.update = false
-        #else:
-        #    self.DrawCursor(dc)
+    def SetTextLine(self, lineNum, text):
+        if self.IsLine(lineNum):
+            self.lines[lineNum] = text
 
-        self.o_cx = self.cx
-        self.o_cy = self.cy
-        self.o_sx = self.sx
-        self.o_sy = self.sy
-        self.o_line = self.line
-        self.inUpdate = false
+    def CurrentLineLength(self):
+        return len(self.lines[self.cy])
 
+    def LinesInFile(self):
+        return len(self.lines)
 
+    def UnTouchBuffer(self):
+        self.bufferTouched = FALSE
 
+    def BufferWasTouched(self):
+        return self.bufferTouched
 
-    def DrawEditText(self, t, x, y, dc = None):
-    ###############################################################
-        """ Einfache Hilfsroutine um Text zu schreiben
-        """
-        if not dc:
-            dc = wxClientDC(self)
-        dc.SetFont(self.font)
-        dc.DrawText(t, x * self.fw, y * self.fh)
+    def TouchBuffer(self):
+        self.bufferTouched = TRUE
+        
 
+##-------------------------- Mouse scroll timing functions
 
-    def DrawLine(self, line, dc=None):
-    ###############################################################
-        """
-        Hier wird einfach die Ansicht der ganzen Seite
-        wiederhergestellt.
-        !!! Kann modifiziert werden !!!
-        """
+    def InitScrolling(self):
+        # we don't rely on the windows system to scroll for us; we just
+        # redraw the screen manually every time
+        self.EnableScrolling(FALSE, FALSE)
+        self.nextScrollTime = 0
+        self.SCROLLDELAY = 0.050 # seconds
+        self.scrollTimer = wxTimer(self)
+        self.scroller = Scroller(self)
+
+    def CanScroll(self):
+       if time.time() >  self.nextScrollTime:
+           self.nextScrollTime = time.time() + self.SCROLLDELAY
+           return true
+       else:
+           return false
+
+    def SetScrollTimer(self):
+        oneShot = true
+        self.scrollTimer.Start(1000*self.SCROLLDELAY/2, oneShot)
+        EVT_TIMER(self, -1, self.OnTimer)
+
+    def OnTimer(self, event):
+        screenX, screenY = wxGetMousePosition()
+        x, y = self.ScreenToClientXY(screenX, screenY)
+        self.MouseToRow(y)
+        self.MouseToCol(x)
+        self.SelectUpdate()
+
+##-------------------------- Mouse off screen functions
+
+    def HandleAboveScreen(self, row):
+        self.SetScrollTimer()
+        if self.CanScroll():
+            row = self.sy - 1
+            row = max(0, row)
+            self.cy = row
+
+    def HandleBelowScreen(self, row):
+        self.SetScrollTimer()
+        if self.CanScroll():
+            row = self.sy + self.sh
+            row  = min(row, self.LinesInFile() - 1)
+            self.cy = row
+        
+    def HandleLeftOfScreen(self, col):
+        self.SetScrollTimer()
+        if self.CanScroll():
+            col = self.sx - 1
+            col = max(0,col)
+            self.cx = col
+
+    def HandleRightOfScreen(self, col):
+        self.SetScrollTimer()
+        if self.CanScroll():
+            col = self.sx + self.sw
+            col = min(col, self.CurrentLineLength())
+            self.cx = col
+        
+##------------------------ mousing functions
+
+    def MouseToRow(self, mouseY):
+        row  = self.sy + (mouseY/ self.fh)
+        if self.AboveScreen(row):
+            self.HandleAboveScreen(row)
+        elif self.BelowScreen(row):
+            self.HandleBelowScreen(row)
+        else:
+            self.cy  = min(row, self.LinesInFile() - 1)
+
+    def MouseToCol(self, mouseX):
+        col = self.sx + (mouseX / self.fw)
+        if self.LeftOfScreen(col):
+            self.HandleLeftOfScreen(col)
+        elif self.RightOfScreen(col):
+            self.HandleRightOfScreen(col)
+        else:
+            self.cx = min(col, self.CurrentLineLength())
+
+    def MouseToCursor(self, event):
+        self.MouseToRow(event.GetY())
+        self.MouseToCol(event.GetX())            
+
+    def OnMotion(self, event):
+        if event.LeftIsDown():
+            self.Selecting = true
+            self.MouseToCursor(event)
+            self.SelectUpdate()
+            
+    def OnLeftDown(self, event):
+        self.MouseToCursor(event)
+        self.SelectBegin = (self.cy, self.cx)
+        self.SelectEnd = None
+        self.UpdateView()
+        self.CaptureMouse()
 
-        if not dc:
-            dc = wxClientDC(self)
+    def OnLeftUp(self, event):
+        if self.SelectEnd is None:
+            self.OnClick()
+        else:
+            self.Selecting = false
+            self.SelectNotify(false, self.SelectBegin, self.SelectEnd)
+
+        self.ReleaseMouse()
+        self.scrollTimer.Stop()
+            
+
+#------------------------- Scrolling
+
+    def HorizScroll(self, event, eventType):
+        maxLineLen = self.CalcMaxLineLen()
+
+        if eventType == wxEVT_SCROLLWIN_LINEUP:
+            self.sx -= 1
+        elif eventType == wxEVT_SCROLLWIN_LINEDOWN:
+            self.sx += 1
+        elif eventType == wxEVT_SCROLLWIN_PAGEUP:
+            self.sx -= self.sw
+        elif eventType == wxEVT_SCROLLWIN_PAGEDOWN:
+            self.sx += self.sw
+        elif eventType == wxEVT_SCROLLWIN_TOP:
+            self.sx = self.cx = 0
+        elif eventType == wxEVT_SCROLLWIN_BOTTOM:
+            self.sx = maxLineLen - self.sw
+            self.cx = maxLineLen
+        else:
+            self.sx = event.GetPosition()
+
+        self.HorizBoundaries()
+
+    def VertScroll(self, event, eventType):
+        if   eventType == wxEVT_SCROLLWIN_LINEUP:
+            self.sy -= 1
+        elif eventType == wxEVT_SCROLLWIN_LINEDOWN:
+            self.sy += 1
+        elif eventType == wxEVT_SCROLLWIN_PAGEUP:
+            self.sy -= self.sh
+        elif eventType == wxEVT_SCROLLWIN_PAGEDOWN:
+            self.sy += self.sh
+        elif eventType == wxEVT_SCROLLWIN_TOP:
+            self.sy = self.cy = 0
+        elif eventType == wxEVT_SCROLLWIN_BOTTOM:
+            self.sy = self.LinesInFile() - self.sh
+            self.cy = self.LinesInFile()
+        else:
+            self.sy = event.GetPosition()
+            
+        self.VertBoundaries()
 
-        dc.SetBackgroundMode(wxSOLID)
-        dc.SetTextBackground(self.bcol)
-        dc.SetTextForeground(self.fcol)
-        #dc.Clear()
+    def OnScroll(self, event):
+        dir = event.GetOrientation()
+        eventType = event.GetEventType()
+        if dir == wxHORIZONTAL:
+            self.HorizScroll(event, eventType)
+        else:
+            self.VertScroll(event, eventType)
+        self.UpdateView()
 
-        # delimiter
-        ll = self.sx
-        lr = self.sx + self.sw
-        y = line - self.sy
 
-        # text + syntax
-        if self.IsLine(line):
-            l   = self.GetLine(line)
-            t   = self.text[l].text
-            syn = self.text[l].syntax
+    def AdjustScrollbars(self):
+        for i in range(2):
+            self.SetCharDimensions()
+            self.scroller.SetScrollbars(
+                self.fw, self.fh,
+                self.CalcMaxLineLen()+3, max(self.LinesInFile()+1, self.sh),
+                self.sx, self.sy) 
+
+#------------ backspace, delete, return
+
+    def BreakLine(self, event):
+        if self.IsLine(self.cy):
+            t = self.lines[self.cy]
+            self.lines = self.lines[:self.cy] + [t[:self.cx],t[self.cx:]] + self.lines[self.cy+1:]
+            self.cVert(1)
+            self.cx = 0
+            self.TouchBuffer()
 
-            if not self.text[l].editable:
-                dc.SetTextBackground(self.nedcol)
+    def InsertChar(self,char):
+        if self.IsLine(self.cy):
+            t = self.lines[self.cy]
+            t = t[:self.cx] + char + t[self.cx:]
+            self.SetTextLine(self.cy, t)
+            self.cHoriz(1)
+            self.TouchBuffer()
+
+    def JoinLines(self):
+        t1 = self.lines[self.cy]
+        t2 = self.lines[self.cy+1]
+        self.cx = len(t1)
+        self.lines = self.lines[:self.cy] + [t1 + t2] + self.lines[self.cy+2:]
+        self.TouchBuffer()
+        
+
+    def DeleteChar(self,x,y,oldtext):
+        newtext = oldtext[:x] + oldtext[x+1:]
+        self.SetTextLine(y, newtext)        
+        self.TouchBuffer()
+
+
+    def BackSpace(self, event):
+        t = self.GetTextLine(self.cy)
+        if self.cx>0:
+            self.DeleteChar(self.cx-1,self.cy,t)
+            self.cHoriz(-1)
+            self.TouchBuffer()
+        elif self.cx == 0:
+            if self.cy > 0:
+                self.cy -= 1
+                self.JoinLines()
+                self.TouchBuffer()
             else:
-                dc.SetTextBackground(self.bcol)
+                wxBell()
+            
+    def Delete(self, event):
+        t = self.GetTextLine(self.cy)
+        if self.cx<len(t):
+            self.DeleteChar(self.cx,self.cy,t)
+            self.TouchBuffer()
+        else:
+            if self.cy < len(self.lines) - 1:
+                self.JoinLines()
+                self.TouchBuffer()
 
-            dc.SetTextForeground(self.fcol)
+    def Escape(self, event):
+        self.SelectOff()
 
-            pos = ll
-            for h in syn:
-                xp, col = h
-                if xp>=ll:
-                    self.DrawEditText(t[pos:xp], (pos-ll), y, dc)
-                    pos = xp
-                dc.SetTextForeground(self.ftab[col])
-            self.DrawEditText(t[pos:], (pos-ll), y, dc)
+    def TabKey(self, event):
+        numSpaces = self.SpacesPerTab - (self.cx % self.SpacesPerTab)
+        self.SingleLineInsert(' ' * numSpaces)       
 
+##----------- selection routines
 
-    def Draw(self, odc=None):
-    ###############################################################
-        """
-        Hier wird einfach die Ansicht der ganzen Seite
-        wiederhergestellt.
-        !!! Kann modifiziert werden !!!
-        """
+    def SelectUpdate(self):
+        self.SelectEnd = (self.cy, self.cx)
+        self.SelectNotify(self.Selecting, self.SelectBegin, self.SelectEnd)
+        self.UpdateView()
 
-        if not odc:
-            odc = wxClientDC(self)
+    def NormalizedSelect(self):
+        (begin, end) = (self.SelectBegin, self.SelectEnd)
+        (bRow, bCol) = begin
+        (eRow, eCol) = end
+        if (bRow < eRow):
+            return (begin, end)
+        elif (eRow < bRow):
+            return (end, begin)
+        else:
+            if (bCol < eCol):
+                return (begin, end)
+            else:
+                return (end, begin)
+                
+    def FindSelection(self):
+        if self.SelectEnd is None or self.SelectBegin is None:
+            wxBell()
+            return None
+        (begin, end) =  self.NormalizedSelect()
+        (bRow, bCol) = begin
+        (eRow, eCol) = end
+        return (bRow, bCol, eRow, eCol)
+
+    def SelectOff(self):
+        self.SelectBegin = None
+        self.SelectEnd = None
+        self.Selecting = false
+        self.SelectNotify(false,None,None)
+
+    def CopySelection(self, event):
+        selection = self.FindSelection()
+        if selection is None:
+            return
+        (bRow, bCol, eRow, eCol) = selection
+        
+        if bRow == eRow:
+            self.SingleLineCopy(bRow, bCol, eCol)
+        else:
+            self.MultipleLineCopy(bRow, bCol, eRow, eCol)
+        
+    def OnCopySelection(self, event):
+        self.CopySelection(event)
+        self.SelectOff()
+
+    def CopyData(self, data):
+        self.CopiedData = data
+
+    def SingleLineCopy(self, Row, bCol, eCol):
+        Line = self.GetTextLine(Row)
+        self.CopyData([Line[bCol:eCol]])
+            
+    def MultipleLineCopy(self, bRow, bCol, eRow, eCol):
+        bLine = self.GetTextLine(bRow)[bCol:]
+        eLine = self.GetTextLine(eRow)[:eCol]
+        self.CopyData([bLine] + [l for l in self.lines[bRow + 1:eRow]] + [eLine])
+
+    def OnDeleteSelection(self, event):
+        selection = self.FindSelection()
+        if selection is None:
+            return
+        (bRow, bCol, eRow, eCol) = selection
+        
+        if bRow == eRow:
+            self.SingleLineDelete(bRow, bCol, eCol)
+        else:
+            self.MultipleLineDelete(bRow, bCol, eRow, eCol)
 
-        dc = self.mdc
-        dc.SelectObject(wxEmptyBitmap(self.bw,self.bh))
-        dc.SetBackgroundMode(wxSOLID)
-        dc.SetTextBackground(self.bcol)
-        dc.SetTextForeground(self.fcol)
-        dc.Clear()
-        for line in range(self.sy, self.sy + self.sh): self.DrawLine(line, dc)
-        odc.Blit(0,0,self.bw,self.bh,dc,0,0,wxCOPY)
-        self.DrawCursor(odc)
+        self.TouchBuffer()
 
+        self.cy = bRow
+        self.cx = bCol
+        self.SelectOff()
+        self.UpdateView()
 
-    def cVert(self, num):
-    ###############################################################
-        """ Vertikale Cursorverschiebung
-        """
-        cy = self.cy + num
-        if cy <0: cy =0
-        elif cy >(self.len -1): cy =self.len -1
-        # scroll when edge hit
-        if cy >(self.sy +self.sh -1): self.sy =cy -self.sh +1
-        elif cy <self.sy: self.sy =cy
-        self.cy =cy
-        # disallow positioning behind the end of the line
-        linelen =len(self.text[self.GetLine(cy)].text)
-        if self.cx >linelen: self.cx =linelen
 
+    def SingleLineDelete(self, Row, bCol, eCol):
+        ModLine = self.GetTextLine(Row)
+        ModLine = ModLine[:bCol] + ModLine[eCol:]
+        self.SetTextLine(Row,ModLine)
 
-    def cHoriz(self, num):
-    ###############################################################
-        """ Horizontale Cursorverschiebung
-        """
-        cx = self.cx + num
-        linelen =len(self.text[self.GetLine(self.cy)].text)
-        if cx <0: cx =0
-        elif cx >linelen: cx =linelen
-        # scroll when edge hit
-        if cx >(self.sx +self.sw -2): self.sx =cx -self.sw +2
-        elif cx <self.sx: self.sx =cx
-        self.cx =cx
-
-
-    def InsertText(self, text):
-    ###############################################################
-        """
-        Simple Routine um Text - auch Ã¼ber mehrere
-        Zeilen - einzufügen
-        """
-
-        if self.IsEditable(self.cy):
-            tis = split(text, "\n")
-
-            t = self.GetTextLine(self.cy)
-
-            if len(tis)==1:
-                t = t[:self.cx] + text + t[self.cx:]
-                self.SetTextLine(self.cy, t)
-                self.cHoriz(len(text))
-            else:
-                rest = t[self.cx:]
-                t = t[:self.cx] + tis[0]
-                self.SetTextLine(self.cy, t)
-                for i in range(1,len(tis)):
-                    self.text.insert(self.GetLine(self.cy)+1, Line())
-                    self.lines.insert(self.cy+1,self.GetLine(self.cy)+1)
-                    self.cVert(+1)
-                    self.SetTextLine(self.cy, tis[i])
-                t = self.GetTextLine(self.cy)
-                self.cx = len(t)
-                t = t + rest
-                self.SetTextLine(self.cy, t)
-            self.update = true
-            #self.UpdateView()
-
-#-----------------------------------------------------------------------------------------
-
-    def RemoveLine(self, line):
-        pass
+    def MultipleLineDelete(self, bRow, bCol, eRow, eCol):
+        bLine = self.GetTextLine(bRow)
+        eLine = self.GetTextLine(eRow)
+        ModLine = bLine[:bCol] + eLine[eCol:]
+        self.lines[bRow:eRow + 1] = [ModLine]
 
+    def OnPaste(self, event):
+        if self.CopiedData is None:
+            wxBell()
+            return
+        elif len(self.CopiedData) == 0:
+            wxBell()
+            return
+        elif len(self.CopiedData) == 1:
+            self.SingleLineInsert(self.CopiedData[0])
+        else:
+            self.MultipleLinePaste()
+
+    def SingleLineInsert(self, newText): 
+        ModLine = self.GetTextLine(self.cy)
+        ModLine = ModLine[:self.cx] + newText + ModLine[self.cx:]
+        self.SetTextLine(self.cy, ModLine)
+        self.cHoriz(len(newText))
+        self.TouchBuffer()
+        self.UpdateView()
 
-    def OnChar(self, event):
-    ###############################################################
-        """
-        Wenn eine Taste gedrückt wird,
-        kann an dieser Stelle die Auswertung stattfinden
-        """
+    def MultipleLinePaste(self):
+        FirstLine = LastLine = self.GetTextLine(self.cy)
+        FirstLine = FirstLine[:self.cx] + self.CopiedData[0]
+        LastLine = self.CopiedData[-1] + LastLine[self.cx:]
 
-        # get code
-        key = event.KeyCode()
+        NewSlice = [FirstLine]
+        NewSlice += [l for l in self.CopiedData[1:-1]]
+        NewSlice += [LastLine]
+        self.lines[self.cy:self.cy + 1] = NewSlice
 
-#        if event.ControlDown:
-#            if chr(key)=="k":
-#                print "weg"
+        self.cy = self.cy + len(self.CopiedData)-1
+        self.cx = len(self.CopiedData[-1])
+        self.TouchBuffer()
+        self.UpdateView()
 
+    def OnCutSelection(self,event):
+        self.CopySelection(event)
+        self.OnDeleteSelection(event)
+        
+#-------------- Keyboard movement implementations
 
-        # movements
-        if key==WXK_DOWN:
-            self.cVert(+1)
-        elif key==WXK_UP:
-            self.cVert(-1)
-        elif key==WXK_LEFT:
-            self.cHoriz(-1)
-        elif key==WXK_RIGHT:
-            self.cHoriz(+1)
+    def MoveDown(self, event):
+        self.cVert(+1)
 
-        elif key==WXK_NEXT:
-            self.cVert(self.sh)
-        elif key==WXK_PRIOR:
-            self.cVert(-self.sh)
+    def MoveUp(self, event):
+        self.cVert(-1)
 
-        elif key==WXK_HOME:
-            self.cx = 0
-        elif key==WXK_END:
-            self.cx = len(self.GetTextLine(self.cy))
-
-        elif key==WXK_BACK:
-            t = self.GetTextLine(self.cy)
-            if self.cx>0:
-                t = t[:self.cx-1] + t[self.cx:]
-                self.SetTextLine(self.cy, t)
-                self.cHoriz(-1)
-
-        elif key==WXK_DELETE:
-            t = self.GetTextLine(self.cy)
-            if self.cx<len(t):
-                t = t[:self.cx] + t[self.cx+1:]
-            self.SetTextLine(self.cy, t)
+    def MoveLeft(self, event):
+        if self.cx == 0:
+            if self.cy == 0:
+                wxBell()
+            else:
+                self.cVert(-1)
+                self.cx = self.CurrentLineLength()
+        else:
+            self.cx -= 1
 
-        elif key==WXK_RETURN:
-            self.InsertText("\n")
+    def MoveRight(self, event):
+        linelen = self.CurrentLineLength()
+        if self.cx == linelen:
+            if self.cy == len(self.lines) - 1:
+                wxBell()
+            else:
+                self.cx = 0
+                self.cVert(1)
+        else:
+            self.cx += 1
+           
 
-        elif key==WXK_TAB:
-            self.OnTabulator(event)
+    def MovePageDown(self, event):
+        self.cVert(self.sh)
 
-        # clipboard (buggy)
-        elif key==WXK_F10:
-            if wxTheClipboard.Open():
-                data = wxTheClipboard.GetData()
-                wxTheClipboard.Close()
-                print data
+    def MovePageUp(self, event):
+        self.cVert(-self.sh)
 
-        # folding (buggy)
-        elif key==WXK_F12:
-            self.update = true
-            self.OnFold()
+    def MoveHome(self, event):
+        self.cx = 0
 
-        # regular ascii
-        elif (key>31) and (key<256):
-            self.InsertText(chr(key))
+    def MoveEnd(self, event):
+        self.cx = self.CurrentLineLength()
 
-        self.UpdateView()
-        return 0
+    def MoveStartOfFile(self, event):
+        self.cy = 0
+        self.cx = 0
 
+    def MoveEndOfFile(self, event):
+        self.cy = len(self.lines) - 1
+        self.cx = self.CurrentLineLength()
 
-    def OnPaint(self, event):
-        dc = wxPaintDC(self)
-        self.bw,self.bh = self.GetSizeTuple()
-        self.UpdateView(dc, true)
+#-------------- Key handler mapping tables
 
+    def SetMoveSpecialFuncs(self, action):
+        action[WXK_DOWN]  = self.MoveDown
+        action[WXK_UP]    = self.MoveUp
+        action[WXK_LEFT]  = self.MoveLeft
+        action[WXK_RIGHT] = self.MoveRight
+        action[WXK_NEXT]  = self.MovePageDown
+        action[WXK_PRIOR] = self.MovePageUp
+        action[WXK_HOME]  = self.MoveHome
+        action[WXK_END]   = self.MoveEnd
 
-#-----------------------------------------------------------------------------------------
+    def SetMoveSpecialControlFuncs(self, action):
+        action[WXK_HOME] = self.MoveStartOfFile
+        action[WXK_END]  = self.MoveEndOfFile
 
-    def GetIndent(self, line):
-        p = 0
-        for c in line:
-            if c==" ": p = p + 1
-            elif c=="\t": p =(p /self.tabsize +1) *self.tabsize
-            else: break
-        return p
+    def SetAltFuncs(self, action):
+        # subclass implements
+        pass
 
+    def SetControlFuncs(self, action):
+        action['c'] = self.OnCopySelection
+        action['d'] = self.OnDeleteSelection
+        action['v'] = self.OnPaste
+        action['x'] = self.OnCutSelection
+
+    def SetSpecialControlFuncs(self, action):
+        action[WXK_INSERT] = self.OnCopySelection
+
+    def SetShiftFuncs(self, action):
+        action[WXK_DELETE] = self.OnCutSelection
+        action[WXK_INSERT] = self.OnPaste
+
+    def SetSpecialFuncs(self, action):
+        action[WXK_BACK]   = self.BackSpace
+        action[WXK_DELETE] = self.Delete
+        action[WXK_RETURN] = self.BreakLine
+        action[WXK_ESCAPE] = self.Escape
+        action[WXK_TAB]    = self.TabKey
+
+##-------------- Logic for key handlers
+
+
+    def Move(self, keySettingFunction, key, event):
+        action = {}
+        keySettingFunction(action)
+
+        if not action.has_key(key):
+            return false
+       
+        if event.ShiftDown():
+            if not self.Selecting:
+                self.Selecting = true
+                self.SelectBegin = (self.cy, self.cx)
+            action[key](event)
+            self.SelectEnd = (self.cy, self.cx)
+        else:
+            action[key](event)
+            if self.Selecting:
+                self.Selecting = false
+                
+        self.SelectNotify(self.Selecting, self.SelectBegin, self.SelectEnd)
+        self.UpdateView()
+        return true
+
+    def MoveSpecialKey(self, event, key):
+        return self.Move(self.SetMoveSpecialFuncs, key, event)
+
+    def MoveSpecialControlKey(self, event, key):
+        if not event.ControlDown():
+            return false
+        return self.Move(self.SetMoveSpecialControlFuncs, key, event)
+
+    def Dispatch(self, keySettingFunction, key, event):
+        action = {}
+        keySettingFunction(action)
+        if action.has_key(key):
+            action[key](event)
+            self.UpdateView()
+            return true
+        return false
+
+    def ModifierKey(self, key, event, modifierKeyDown, MappingFunc):
+        if not modifierKeyDown:
+            return false
+
+        key = self.UnixKeyHack(key)
+        try:
+            key = chr(key)
+        except:
+            return false
+        if not self.Dispatch(MappingFunc, key, event):
+            wxBell()
+        return true
+
+    def ControlKey(self, event, key):
+        return self.ModifierKey(key, event, event.ControlDown(), self.SetControlFuncs)
+
+    def AltKey(self, event, key):
+        return self.ModifierKey(key, event, event.AltDown(), self.SetAltFuncs)
+    
+    def SpecialControlKey(self, event, key):
+        if not event.ControlDown():
+            return false
+        if not self.Dispatch(self.SetSpecialControlFuncs, key, event):
+            wxBell()
+        return true
+
+    def ShiftKey(self, event, key):
+        if not event.ShiftDown():
+            return false
+        return self.Dispatch(self.SetShiftFuncs, key, event)
+
+    def NormalChar(self, event, key):
+        self.SelectOff()
 
-    def Goto(self, pos):
-        self.cVert(pos-self.cy-1)
+        # regular ascii
+        if not self.Dispatch(self.SetSpecialFuncs, key, event):
+            if (key>31) and (key<256):
+                self.InsertChar(chr(key))
+            else:
+                wxBell()
+                return
         self.UpdateView()
+        self.AdjustScrollbars()
 
-# --------------------------------------------------------
+    def OnChar(self, event):
+        key = event.KeyCode()
+        filters = [self.AltKey,
+                   self.MoveSpecialControlKey,
+                   self.ControlKey,
+                   self.SpecialControlKey,
+                   self.MoveSpecialKey,
+                   self.ShiftKey,
+                   self.NormalChar]
+        for filter in filters:
+            if filter(event,key):
+                break
+        return 0
 
-    # to be overloaded
-    def OnUpdateHighlight(self, line = -1):
-        pass
+#----------------------- Eliminate memory leaks
 
-    def OnUpdateSyntax(self, line = -1):
-        pass
+    def OnDestroy(self, event):
+        self.mdc = None
+        self.odc = None
+        self.bgColor = None
+        self.fgColor = None
+        self.font = None
+        self.selectColor = None
+        self.scrollTimer = None
+        self.eofMarker = None
 
-    def OnTabulator(self, event):
-        pass
+#--------------------  Abstract methods for subclasses
 
-    def OnInit(self):
+    def OnClick(self):
         pass
-
-    def OnFold(self):
+        
+    def SelectNotify(self, Selecting, SelectionBegin, SelectionEnd):
         pass
 
diff --git a/wxPython/wxPython/lib/editor/images.py b/wxPython/wxPython/lib/editor/images.py
new file mode 100644 (file)
index 0000000..fa2f09f
--- /dev/null
@@ -0,0 +1,20 @@
+
+# images converted with wxPython's img2py.py tool
+
+from wxPython.wx import wxBitmapFromXPMData, wxImageFromBitmap
+import cPickle, zlib
+
+##----------- Common Functions
+
+def GetBitmap(ImageData):
+    return wxBitmapFromXPMData(ImageData)
+
+def GetImage(ImageData):
+    return wxImageFromBitmap(GetBitmap(ImageData))
+
+##----------- Image Data 
+
+EofImageData = cPickle.loads(zlib.decompress(
+'x\xda\xd3\xc8)0\xe4\nV7W0W0R0T\xe7J\x0cV\xd7SHVp\xcaIL\xce\x06\xf3\x14\x80<\
+\xbf\xfc\xbcT(GA\x0f\x88\xa1l===\x18[\x0f\x04 l=\x08\xc0\x10GQ\x0f7G\x0f\x00\
+\xec\xa2\x19\x96' ))
diff --git a/wxPython/wxPython/lib/editor/py_editor.py b/wxPython/wxPython/lib/editor/py_editor.py
deleted file mode 100644 (file)
index 883370d..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-# (C)opyright by Dirk Holtwick, 1999
-# ----------------------------------
-# holtwick@spirito.de
-# http://www.spirito.de/pyde
-
-from editor import *
-from string import *
-from keyword import *
-from tokenizer import *
-
-"""
-This module will be loaded by the main
-window. It implements some methods that
-are typical for Python sources.
-"""
-
-class wxPyEditor(wxEditor):
-
-    # ------------------------------------------------------------------
-
-    def __init__(self, parent, id,
-                 pos=wxDefaultPosition, size=wxDefaultSize, style=0):
-        wxEditor.__init__(self, parent, id, pos, size, style)
-        self.SetFontTab([
-            wxNamedColour('black'),
-            wxNamedColour('blue'),
-            wxNamedColour('red'),
-            wxNamedColour('darkgreen'),
-            wxNamedColour('brown')
-            ])
-
-    # ------------------------------------------------------------------
-
-    def OnUpdateHighlight(self, line = -1):
-        if line>=0:
-            t   = self.text[line].text
-            syn = []
-
-            toks = Tokenizer(t).tokens()
-            for type, string, begin, end in toks:
-                if type == "KEY":
-                    syn.append((begin,  1))
-                    syn.append((end,    0))
-                elif type == "COMMENT":
-                    syn.append((begin,  2))
-                elif type == "STRING":
-                    syn.append((begin,  3))
-                    syn.append((end,    0))
-                elif type == "NUMBER":
-                    syn.append((begin,  4))
-                    syn.append((end,    0))
-                elif type == "NAME":
-                    if string=="self":
-                        syn.append((begin,  4))
-                        syn.append((end,    0))
-                else:
-                    pass
-            self.text[line].syntax = syn
-
-    # ------------------------------------------------------------------
-
-    def OnUpdateSyntax(self, line = -1):
-        if line>=0:
-            """
-            tx, syn, m = self.text[line]
-            pre = 0
-            for i in range(0,len(tx)):
-                if tx[i] != " ":
-                    pre = i
-                    break
-            t = tx[pre:]
-
-            t = Tokenizer(t).line()
-
-            t = tx[:pre] + t
-            self.text[line] = t, syn, m
-            """
-            self.OnUpdateHighlight(line)
-
-    # ------------------------------------------------------------------
-
-    def OnTabulator(self, event):
-        add = +1
-        if event.ShiftDown():
-            add = -1
-        t = self.GetTextLine(self.cy)
-        if strip(t):
-            indent = self.GetIndent(t)
-#           print indent
-            t = t[indent:]
-            tabs = indent / self.tabsize
-#            for i in range(0,tabs+add):
-            t = (" " * 4 * (tabs+add)) + t
-            self.SetTextLine(self.cy, t)
-        elif add>0:
-            self.InsertText("    ")
-
-    # ------------------------------------------------------------------
-
-    def FindQuote(self, lineno, quote_type='"""', direction=1):
-        """find line containing the matching quote"""
-        l =lineno +direction
-        while (l < len(self.text)-1) and (l >= 0):
-            if find(self.text[l].text, quote_type) >=0: return l
-            l =l +direction
-        return None
-
-    def FindNextLine(self, lineno, direction=1):
-        """get the next line of code (skipping comment lines and empty lines)"""
-        l =lineno +direction
-        while (l < len(self.text)-1) and (l >= 0):
-            str =lstrip(self.text[l].text)
-            if (len(str) >0) and (str[0] !="#"): return l
-            l =l +direction
-        return None
-
-    def Fold(self):
-        l       = self.GetLine(self.cy)
-        line    = self.text[l]
-        t       = line.text
-
-        # fold ...
-        if line.editable:
-
-            # 3*quotes
-            qpos =find(t, '"""')
-            if qpos >=0: qtype ='"""'
-            else:
-                qpos =find(t, "'''")
-                if qpos >=0: qtype ="'''"
-
-            if (qpos >=0) and (find(t[qpos+3:], qtype) <0):
-                closing_quote =self.FindQuote(l, qtype)
-                if closing_quote !=None:
-                    line.editable = not line.editable
-                    l =l +1
-                    while l <= closing_quote:
-                       self.text[l].visible =self.text[l].visible +1
-                       l =l +1
-
-            else:  # try normal fold on leading whitespace
-                lim = self.GetIndent(t)
-                lnext =self.FindNextLine(l)
-                if (lnext !=None) \
-                and (self.GetIndent(self.text[lnext].text) >lim):
-                    line.editable =FALSE
-                    lstart =l +1
-                    l =self.FindNextLine(l)
-                    while (l !=None) \
-                    and (self.GetIndent(self.text[l].text) >lim):
-                        l =self.FindNextLine(l)
-                    if l ==None:
-                        # fold till the end
-                        l =len(self.text)
-                    for line in self.text[lstart:l]:
-                        line.visible =line.visible +1
-
-        # ... or unfold
-        else:
-            lim = line.visible + 1
-            line.editable = not line.editable
-
-            l = l + 1
-            line = self.text[l]
-            while (l < (len(self.text) -1)) and (line.visible>=lim):
-                line.visible = line.visible - 1
-                l = l + 1
-                line = self.text[l]
-
-    def FoldAll(self):
-        self.CalcLines()
-        self.cx = 0
-        self.cy = len(self.lines) - 1
-        prev_indent =0
-        # following loop is exited in two cases:
-        # when self.cy becomes 0 (topmost level is not folded by FoldAll)
-        # or when FindNextLine() returns None (all remaining lines till
-        #               the beginning of the text are empty or comments)
-        while self.cy:
-            t = self.GetTextLine(self.cy)
-            # indent-based folding
-            indent =self.GetIndent(t)
-            if indent <prev_indent:
-                self.Fold()
-            prev_indent =indent
-            # triple-quote folding
-            qpos =find(t, '"""')
-            if qpos >=0: qtype ='"""'
-            else:
-                qpos =find(t, "'''")
-                if qpos >=0: qtype ="'''"
-            if (qpos >=0) and (find(t[qpos+3:], qtype) <0):
-                closing_quote =self.FindQuote(self.cy, qtype, -1)
-                if closing_quote !=None:
-                    # XXX potential bug: unmatched triple quotes
-                    self.cy =closing_quote
-                    self.Fold()
-            self.cy =self.FindNextLine(self.cy, -1)
-        if self.cy ==None: self.cy =0
-
-    # ------------------------------------------------------------------
-
-    def OnFold(self):
-        self.Fold()
-
-    # ------------------------------------------------------------------
-
-    def OnInit(self):
-        #self.FoldAll()
-        pass
-
diff --git a/wxPython/wxPython/lib/editor/selection.py b/wxPython/wxPython/lib/editor/selection.py
new file mode 100644 (file)
index 0000000..d57982e
--- /dev/null
@@ -0,0 +1,42 @@
+TRUE  = 1
+FALSE = 0
+
+def RestOfLine(sx, width, data, bool):
+    if len(data) == 0 and sx == 0:
+        return [('', bool)]
+    if sx >= len(data):
+        return []
+    return [(data[sx:sx+width], bool)]
+
+def Selection(SelectBegin,SelectEnd, sx, width, line, data):
+    if SelectEnd is None or SelectBegin is None:
+        return RestOfLine(sx, width, data, FALSE)
+    (bRow, bCol) = SelectBegin
+    (eRow, eCol) = SelectEnd
+    if (eRow < bRow):
+        (bRow, bCol) = SelectEnd
+        (eRow, eCol) = SelectBegin
+    if (line < bRow or eRow < line):
+        return RestOfLine(sx, width, data, FALSE)
+    if (bRow < line and line < eRow):
+        return RestOfLine(sx, width, data, TRUE)
+    if (bRow == eRow) and (eCol < bCol):
+        (bCol, eCol) = (eCol, bCol)
+    # selection either starts or ends on this line
+    end = min(sx+width, len(data))
+    if (bRow < line):
+        bCol = 0
+    if (line < eRow):
+        eCol = end
+    pieces = []
+    if (sx < bCol):
+        if bCol <= end:
+            pieces += [(data[sx:bCol], FALSE)]
+        else:
+            return [(data[sx:end], FALSE)]
+    pieces += [(data[max(bCol,sx):min(eCol,end)], TRUE)]
+    if (eCol < end):
+        pieces += [(data[eCol:end], FALSE)]
+    return pieces
+
+
diff --git a/wxPython/wxPython/lib/editor/tokenizer.py b/wxPython/wxPython/lib/editor/tokenizer.py
deleted file mode 100644 (file)
index 1d8e18a..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-from tokenize import *
-from keyword import *
-from string import *
-
-class Tokenizer:
-    """
-    Simple class to create a list of token-tuples like:
-
-       (type, string, first, last)
-
-    Example:
-    t = Tokenizer('def hallo(du): # juchee')
-    print t.tokens()
-    """
-
-    def __init__(self, text):
-       self.text = text
-       self.toks = []
-       try:
-           tokenize(self.readline, self.get)
-       except TokenError:
-           pass
-
-    def tokens(self):
-       return self.toks
-
-    def get(self, type, string, begin, end, l):
-       #print begin,end
-       h1, b = begin
-       h2, e = end
-       tname = tok_name[type]
-       if iskeyword(string):
-           tname = "KEY"
-       self.toks.append( (tname, string, b, e) )
-
-    def readline(self):
-       t = self.text
-       self.text = ""
-       return t
-
-    def line(self):
-       pre = ""
-       out = ""
-       for type, string, begin, end in self.toks:
-           if (pre in ["NAME","KEY"]) and (not string in [".",",","("]):
-               out = out + " "
-
-           if type in ["NAME","KEY"]:
-               out = out + string
-           elif type=="OP":
-               if string in [",",":"]:
-                   out = out + string + " "
-               else:
-                           out = out + string
-           else:
-               out = out + string
-           pre = type
-       return out
-
-