some support for syntax coloring, disabled for now
diff --git a/Mac/Tools/IDE/PyEdit.py b/Mac/Tools/IDE/PyEdit.py
index 7740dfe..8d163ed 100644
--- a/Mac/Tools/IDE/PyEdit.py
+++ b/Mac/Tools/IDE/PyEdit.py
@@ -96,7 +96,7 @@
 		W.Window.__init__(self, bounds, self.title, minsize = (330, 120), tabbable = 0)
 		self.setupwidgets(text)
 		if change > 0:
-			self.editgroup.editor.changed = 1
+			self.editgroup.editor.textchanged()
 		
 		if self.settings.has_key("selection"):
 			selstart, selend = self.settings["selection"]
@@ -247,12 +247,12 @@
 	def domenu_toggle_run_as_main(self):
 		self.run_as_main = not self.run_as_main
 		self.run_with_interpreter = 0
-		self.editgroup.editor.selchanged = 1
+		self.editgroup.editor.selectionchanged()
 	
 	def domenu_toggle_run_with_interpreter(self):
 		self.run_with_interpreter = not self.run_with_interpreter
 		self.run_as_main = 0
-		self.editgroup.editor.selchanged = 1
+		self.editgroup.editor.selectionchanged()
 	
 	def showbreakpoints(self, onoff):
 		self.editgroup.editor.showbreakpoints(onoff)
@@ -314,7 +314,7 @@
 	def domenu_options(self, *args):
 		rv = SaveOptions(self._creator)
 		if rv:
-			self.editgroup.editor.selchanged = 1 # ouch...
+			self.editgroup.editor.selectionchanged() # ouch...
 			self._creator = rv
 	
 	def clicklinefield(self):
@@ -633,6 +633,8 @@
 				dir, dirname = os.path.split(dir)
 				modname = dirname + '.' + modname
 			subname = _filename_as_modname(self.title)
+			if subname is None:
+				return self.globals, file, None
 			if modname:
 				if subname == "__init__":
 					# strip trailing period
@@ -949,8 +951,8 @@
 			self.hide()
 			import EasyDialogs
 			from Carbon import Res
-			editor.changed = 1
-			editor.selchanged = 1
+			editor.textchanged()
+			editor.selectionchanged()
 			editor.ted.WEUseText(Res.Resource(Text))
 			editor.ted.WECalText()
 			editor.SetPort()
@@ -1147,6 +1149,9 @@
 		raise W.AlertError, detail
 	except (KeyboardInterrupt, BdbQuit):
 		pass
+	except SystemExit, arg:
+		if arg.code:
+			sys.stderr.write("Script exited with status code: %s\n" % repr(arg.code))
 	except:
 		if haveThreading:
 			import continuation
@@ -1268,7 +1273,7 @@
 		tabsettings = prefs.pyedit.tabsettings
 		windowsize = prefs.pyedit.windowsize
 	except:
-		fontsettings = prefs.pyedit.fontsettings = ("Python-Sans", 0, 9, (0, 0, 0))
+		fontsettings = prefs.pyedit.fontsettings = ("Geneva", 0, 10, (0, 0, 0))
 		tabsettings = prefs.pyedit.tabsettings = (8, 1)
 		windowsize = prefs.pyedit.windowsize = (500, 250)
 		sys.exc_traceback = None
diff --git a/Mac/Tools/IDE/Wtext.py b/Mac/Tools/IDE/Wtext.py
index 68ba592..0d9203d 100644
--- a/Mac/Tools/IDE/Wtext.py
+++ b/Mac/Tools/IDE/Wtext.py
@@ -1,23 +1,14 @@
-from Carbon import Qd
-from Carbon import TE
-from Carbon import Fm
+from Carbon import Evt, Events, Fm, Fonts
+from Carbon import Qd, Res, Scrap
+from Carbon import TE, TextEdit, Win
 import waste
 import WASTEconst
-from Carbon import Res
-from Carbon import Evt
-from Carbon import Events
-from Carbon import Scrap
-import string
-
-from Carbon import Win
 import Wbase
 import Wkeys
 import Wcontrols
 import PyFontify
-from types import *
-from Carbon import Fonts
-from Carbon import TextEdit
-
+import string
+from types import TupleType, StringType
 
 
 class TextBox(Wbase.Widget):
@@ -105,6 +96,7 @@
 		self.temptext = text
 		self.ted = None
 		self.selection = None
+		self.oldselection = None
 		self._callback = callback
 		self.changed = 0
 		self.selchanged = 0
@@ -155,6 +147,13 @@
 		self.temptext = None
 		Wbase.SelectableWidget.close(self)
 	
+	def textchanged(self, all=0):
+		self.changed = 1
+	
+	def selectionchanged(self):
+		self.selchanged = 1
+		self.oldselection = self.getselection()
+	
 	def gettabsettings(self):
 		return self.tabsettings
 	
@@ -208,7 +207,7 @@
 		viewrect = self.ted.WEGetViewRect()
 		Qd.EraseRect(viewrect)
 		self.ted.WEUpdate(self._parentwindow.wid.GetWindowPort().visRgn)
-		self.selchanged = 1
+		self.selectionchanged()
 		self.updatescrollbars()
 	
 	def adjust(self, oldbounds):
@@ -235,7 +234,7 @@
 	
 	def selectall(self):
 		self.ted.WESetSelection(0, self.ted.WEGetTextLength())
-		self.selchanged = 1
+		self.selectionchanged()
 		self.updatescrollbars()
 	
 	def selectline(self, lineno, charoffset = 0):
@@ -246,7 +245,7 @@
 		# Let's fool Waste by initially selecting one char less:
 		self.ted.WESetSelection(newselstart + charoffset, newselend-1)
 		self.ted.WESetSelection(newselstart + charoffset, newselend)
-		self.selchanged = 1
+		self.selectionchanged()
 		self.updatescrollbars()
 	
 	def getselection(self):
@@ -256,7 +255,7 @@
 			return self.selection
 	
 	def setselection(self, selstart, selend):
-		self.selchanged = 1
+		self.selectionchanged()
 		if self.ted:
 			self.ted.WESetSelection(selstart, selend)
 			self.ted.WESelView()
@@ -284,12 +283,12 @@
 		if oldselstart <> newselstart or  oldselend <> newselend:
 			self.ted.WESetSelection(newselstart, newselend)
 			self.updatescrollbars()
-		self.selchanged = 1
+		self.selectionchanged()
 	
 	def insert(self, text):
 		self.ted.WEInsert(text, None, None)
-		self.changed = 1
-		self.selchanged = 1
+		self.textchanged()
+		self.selectionchanged()
 	
 	# text
 	def set(self, text):
@@ -306,8 +305,8 @@
 			Qd.RectRgn(rgn, viewrect)
 			Qd.EraseRect(viewrect)
 			self.draw(rgn)
-			#self.GetWindow().InvalWindowRect(self.ted.WEGetViewRect())
 			self.updatescrollbars()
+			self.textchanged(1)
 	
 	def get(self):
 		if not self._parent:
@@ -321,9 +320,9 @@
 		if self._enabled and not modifiers & Events.cmdKey or char in Wkeys.arrowkeys:
 			self.ted.WEKey(ord(char), modifiers)
 			if char not in Wkeys.navigationkeys:
-				self.changed = 1
+				self.textchanged()
 			if char not in Wkeys.scrollkeys:
-				self.selchanged = 1
+				self.selectionchanged()
 			self.updatescrollbars()
 			if self._callback:
 				Wbase.CallbackCall(self._callback, 0, char, modifiers)
@@ -332,7 +331,7 @@
 		if not self._enabled:
 			return
 		self.ted.WEClick(point, modifiers, Evt.TickCount())
-		self.selchanged = 1
+		self.selectionchanged()
 		self.updatescrollbars()
 		return 1
 	
@@ -411,8 +410,8 @@
 		self.ted.WECut()
 		self.updatescrollbars()
 		self.selview()
-		self.changed = 1
-		self.selchanged = 1
+		self.textchanged()
+		self.selectionchanged()
 		if self._callback:
 			Wbase.CallbackCall(self._callback, 0, "", None)
 	
@@ -422,8 +421,8 @@
 		self.selview()
 		self.ted.WEPaste()
 		self.updatescrollbars()
-		self.changed = 1
-		self.selchanged = 1
+		self.textchanged()
+		self.selectionchanged()
 		if self._callback:
 			Wbase.CallbackCall(self._callback, 0, "", None)
 	
@@ -431,8 +430,8 @@
 		self.ted.WEDelete()
 		self.selview()
 		self.updatescrollbars()
-		self.changed = 1
-		self.selchanged = 1
+		self.textchanged()
+		self.selectionchanged()
 		if self._callback:
 			Wbase.CallbackCall(self._callback, 0, "", None)
 	
@@ -442,8 +441,8 @@
 			return
 		self.ted.WEUndo()
 		self.updatescrollbars()
-		self.changed = 1
-		self.selchanged = 1
+		self.textchanged()
+		self.selectionchanged()
 		if self._callback:
 			Wbase.CallbackCall(self._callback, 0, "", None)
 	
@@ -610,6 +609,8 @@
 import re
 commentPat = re.compile("[ \t]*(#)")
 indentPat = re.compile("[ \t]*")
+kStringColor = (0, 0x7fff, 0)
+kCommentColor = (0, 0, 0xb000)
 
 
 class PyEditor(TextEditor):
@@ -627,10 +628,111 @@
 		self.bind("cmd]", self.domenu_shiftright)
 		self.bind("cmdshift[", self.domenu_uncomment)
 		self.bind("cmdshift]", self.domenu_comment)
+		self.bind("cmdshiftd", self.alldirty)
 		self.file = file	# only for debugger reference
 		self._debugger = debugger
 		if debugger:
 			debugger.register_editor(self, self.file)
+		self._dirty = (0, None)
+		self.do_fontify = 0
+	
+	#def open(self):
+	#	TextEditor.open(self)
+	#	if self.do_fontify:
+	#		self.fontify()
+	#	self._dirty = (None, None)
+	
+	def _getflags(self):
+		flags = (WASTEconst.weDoDrawOffscreen | WASTEconst.weDoUseTempMem |
+				WASTEconst.weDoAutoScroll | WASTEconst.weDoOutlineHilite)
+		if self.readonly:
+			flags = flags | WASTEconst.weDoReadOnly
+		else:
+			flags = flags | WASTEconst.weDoUndo
+		return flags
+	
+	def textchanged(self, all=0):
+		self.changed = 1
+		if all:
+			self._dirty = (0, None)
+			return
+		oldsel = self.oldselection
+		sel = self.getselection()
+		if not sel:
+			# XXX what to do?
+			return
+		selstart, selend = sel
+		selstart, selend = min(selstart, selend), max(selstart, selend)
+		if oldsel:
+			oldselstart, oldselend = min(oldsel), max(oldsel)
+			selstart, selend = min(selstart, oldselstart), max(selend, oldselend)
+		startline = self.offsettoline(selstart)
+		endline = self.offsettoline(selend)
+		selstart, _ = self.ted.WEGetLineRange(startline)
+		_, selend = self.ted.WEGetLineRange(endline)
+		if selstart > 0:
+			selstart = selstart - 1
+		self._dirty = (selstart, selend)
+	
+	def idle(self):
+		self.SetPort()
+		self.ted.WEIdle()
+		if not self.do_fontify:
+			return
+		start, end = self._dirty
+		if start is None:
+			return
+		textLength = self.ted.WEGetTextLength()
+		if end is None:
+			end = textLength
+		if start >= end:
+			self._dirty = (None, None)
+		else:
+			self.fontify(start, end)
+			self._dirty = (None, None)
+	
+	def alldirty(self, *args):
+		self._dirty = (0, None)
+	
+	def fontify(self, start=0, end=None):
+		#W.SetCursor('watch')
+		if self.readonly:
+			self.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 0)
+		self.ted.WEFeatureFlag(WASTEconst.weFOutlineHilite, 0)
+		self.ted.WEDeactivate()
+		self.ted.WEFeatureFlag(WASTEconst.weFAutoScroll, 0)
+		self.ted.WEFeatureFlag(WASTEconst.weFUndo, 0)
+		pytext = self.get().replace("\r", "\n")
+		if end is None:
+			end = len(pytext)
+		else:
+			end = min(end, len(pytext))
+		selstart, selend = self.ted.WEGetSelection()
+		self.ted.WESetSelection(start, end)
+		self.ted.WESetStyle(WASTEconst.weDoFace | WASTEconst.weDoColor, 
+				(0, 0, 12, (0, 0, 0)))
+		
+		tags = PyFontify.fontify(pytext, start, end)
+		styles = {
+			'string': (WASTEconst.weDoColor, (0, 0, 0, kStringColor)),
+			'keyword': (WASTEconst.weDoFace, (0, 1, 0, (0, 0, 0))),
+			'comment': (WASTEconst.weDoFace | WASTEconst.weDoColor, (0, 0, 0, kCommentColor)),
+			'identifier': (WASTEconst.weDoColor, (0, 0, 0, (0xbfff, 0, 0)))
+		}
+		setselection = self.ted.WESetSelection
+		setstyle = self.ted.WESetStyle
+		for tag, start, end, sublist in tags:
+			setselection(start, end)
+			mode, style = styles[tag]
+			setstyle(mode, style)
+		self.ted.WESetSelection(selstart, selend)
+		self.SetPort()
+		self.ted.WEFeatureFlag(WASTEconst.weFAutoScroll, 1)
+		self.ted.WEFeatureFlag(WASTEconst.weFUndo, 1)
+		self.ted.WEActivate()
+		self.ted.WEFeatureFlag(WASTEconst.weFOutlineHilite, 1)
+		if self.readonly:
+			self.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 1)
 	
 	def domenu_shiftleft(self):
 		self.expandselection()
@@ -786,8 +888,8 @@
 		else:
 			self.ted.WEKey(ord(char), modifiers)
 		if char not in Wkeys.navigationkeys:
-			self.changed = 1
-		self.selchanged = 1
+			self.textchanged()
+		self.selectionchanged()
 		self.updatescrollbars()
 	
 	def balanceparens(self, char):