Whitespace normalization, via reindent.py.
diff --git a/Mac/Tools/IDE/BuildIDE.py b/Mac/Tools/IDE/BuildIDE.py
index 7e65869..914028c 100644
--- a/Mac/Tools/IDE/BuildIDE.py
+++ b/Mac/Tools/IDE/BuildIDE.py
@@ -1,4 +1,4 @@
-"""Build a "big" applet for the IDE, and put it in the Python home 
+"""Build a "big" applet for the IDE, and put it in the Python home
 directory. It will contain all IDE-specific modules as PYC resources,
 which reduces the startup time (especially on slower machines)."""
 
@@ -25,17 +25,16 @@
 files = os.listdir(ide_home)
 
 # skip this script and the main program
-files = filter(lambda x: x[-3:] == '.py' and 
-		x not in ("BuildIDE.py", "PythonIDE.py"), files)
+files = filter(lambda x: x[-3:] == '.py' and
+                x not in ("BuildIDE.py", "PythonIDE.py"), files)
 
 # add the modules as PYC resources
 for name in files:
-	print "adding", name
-	fullpath = os.path.join(ide_home, name)
-	id, name = py_resource.frompyfile(fullpath, name[:-3], preload=1,
-		ispackage=0)
+    print "adding", name
+    fullpath = os.path.join(ide_home, name)
+    id, name = py_resource.frompyfile(fullpath, name[:-3], preload=1,
+            ispackage=0)
 
 # add W resources
 wresref = Res.FSpOpenResFile(os.path.join(ide_home, "Widgets.rsrc"), 1)
 buildtools.copyres(wresref, targetref, [], 0)
-
diff --git a/Mac/Tools/IDE/FontSettings.py b/Mac/Tools/IDE/FontSettings.py
index af2bd80..d713438 100644
--- a/Mac/Tools/IDE/FontSettings.py
+++ b/Mac/Tools/IDE/FontSettings.py
@@ -1,9 +1,9 @@
-"""usage: 
-newsettings = FontDialog(('Chicago', 0, 12, (0, 0, 0)))	# font name or id, style flags, size, color (color is ignored)
+"""usage:
+newsettings = FontDialog(('Chicago', 0, 12, (0, 0, 0))) # font name or id, style flags, size, color (color is ignored)
 if newsettings:
-	fontsettings, tabsettings = newsettings
-	font, style, size, color = fontsettings	# 'font' is always the font name, not the id number
-	# do something
+        fontsettings, tabsettings = newsettings
+        font, style, size, color = fontsettings # 'font' is always the font name, not the id number
+        # do something
 """
 
 import W
@@ -15,209 +15,209 @@
 import sys
 import MacOS
 if hasattr(MacOS, "SysBeep"):
-	SysBeep = MacOS.SysBeep
+    SysBeep = MacOS.SysBeep
 else:
-	def SysBeep(*args):
-		pass
+    def SysBeep(*args):
+        pass
 
 _stylenames = ["Plain", "Bold", "Italic", "Underline", "Outline", "Shadow", "Condensed", "Extended"]
 
 
 class _FontDialog:
-	
-	#def __del__(self):
-	#	print "doei!"
-	
-	def __init__(self, fontsettings, tabsettings):
-		leftmargin = 60
-		leftmargin2 = leftmargin - 16
-		self.w = W.ModalDialog((440, 180), 'Font settings')
-		self.w.fonttitle = W.TextBox((10, 12, leftmargin2, 14), "Font:", TextEdit.teJustRight)
-		self.w.pop = W.FontMenu((leftmargin, 10, 16, 16), self.setfont)
-		self.w.fontname = W.TextBox((leftmargin + 20, 12, 150, 14))
-		self.w.sizetitle = W.TextBox((10, 38, leftmargin2, 14), "Size:", TextEdit.teJustRight)
-		self.w.sizeedit = W.EditText((leftmargin, 35, 40, 20), "", self.checksize)
-		styletop = 64
-		self.w.styletitle = W.TextBox((10, styletop + 2, leftmargin2, 14), "Style:", TextEdit.teJustRight)
-		for i in range(len(_stylenames)):
-			top = styletop + (i % 4) * 20
-			left = leftmargin + 80 * (i > 3) - 2
-			if i:
-				self.w[i] = W.CheckBox((left, top, 76, 16), _stylenames[i], self.dostyle)
-			else:
-				self.w[i] = W.CheckBox((left, top, 70, 16), _stylenames[i], self.doplain)
-		
-		if tabsettings:
-			self.lasttab, self.tabmode = tabsettings
-			self.w.tabsizetitle = W.TextBox((10, -26, leftmargin2, 14), "Tabsize:", TextEdit.teJustRight)
-			self.w.tabsizeedit = W.EditText((leftmargin, -29, 40, 20), "", self.checktab)
-			self.w.tabsizeedit.set(repr(self.lasttab))
-			radiobuttons = []
-			self.w.tabsizechars = W.RadioButton((leftmargin + 48, -26, 55, 14), "Spaces", 
-					radiobuttons, self.toggletabmode)
-			self.w.tabsizepixels = W.RadioButton((leftmargin + 110, -26, 55, 14), "Pixels", 
-					radiobuttons, self.toggletabmode)
-			if self.tabmode:
-				self.w.tabsizechars.set(1)
-			else:
-				self.w.tabsizepixels.set(1)
-		else:
-			self.tabmode = None
-		
-		self.w.cancelbutton = W.Button((-180, -26, 80, 16), "Cancel", self.cancel)
-		self.w.donebutton = W.Button((-90, -26, 80, 16), "Done", self.done)
-		
-		sampletext = "Sample text."
-		self.w.sample = W.EditText((230, 10, -10, 130), sampletext, 
-				fontsettings = fontsettings, tabsettings = tabsettings)
-		
-		self.w.setdefaultbutton(self.w.donebutton)
-		self.w.bind('cmd.', self.w.cancelbutton.push)
-		self.w.bind('cmdw', self.w.donebutton.push)
-		self.lastsize = fontsettings[2]
-		self._rv = None
-		self.set(fontsettings)
-		self.w.open()
-	
-	def toggletabmode(self, onoff):
-		if self.w.tabsizechars.get():
-			tabmode = 1
-		else:
-			tabmode = 0
-		if self.tabmode <> tabmode:
-			port = self.w.wid.GetWindowPort()
-			(font, style, size, color), (tabsize, dummy) = self.get()
-			savesettings = W.GetPortFontSettings(port)
-			W.SetPortFontSettings(port, (font, style, size))
-			spacewidth = Qd.StringWidth(' ')
-			W.SetPortFontSettings(port, savesettings)
-			if tabmode:
-				# convert pixels to spaces
-				self.lasttab = int(round(float(tabsize) / spacewidth))
-			else:
-				# convert spaces to pixels
-				self.lasttab = spacewidth * tabsize
-			self.w.tabsizeedit.set(repr(self.lasttab))
-			self.tabmode = tabmode
-			self.doit()
-	
-	def set(self, fontsettings):
-		font, style, size, color = fontsettings
-		if type(font) <> types.StringType:
-			from Carbon import Res
-			res = Res.GetResource('FOND', font)
-			font = res.GetResInfo()[2]
-		self.w.fontname.set(font)
-		self.w.sizeedit.set(str(size))
-		if style:
-			for i in range(1, len(_stylenames)):
-				self.w[i].set(style & 0x01)
-				style = style >> 1
-		else:
-			self.w[0].set(1)
-	
-	def get(self):
-		font = self.w.fontname.get()
-		style = 0
-		if not self.w[0].get():
-			flag = 0x01
-			for i in range(1, len(_stylenames)):
-				if self.w[i].get():
-					style = style | flag
-				flag = flag << 1
-		size = self.lastsize
-		if self.tabmode is None:
-			return (font, style, size, (0, 0, 0)), (32, 0)
-		else:
-			return (font, style, size, (0, 0, 0)), (self.lasttab, self.tabmode)
-	
-	def doit(self):
-		if self.w[0].get():
-			style = 0
-		else:
-			style = 0
-			for i in range(1, len(_stylenames)):
-				if self.w[i].get():
-					style = style | 2 ** (i - 1)
-		#self.w.sample.set(repr(style))
-		fontsettings, tabsettings = self.get()
-		self.w.sample.setfontsettings(fontsettings)
-		self.w.sample.settabsettings(tabsettings)
-	
-	def checktab(self):
-		tabsize = self.w.tabsizeedit.get()
-		if not tabsize:
-			return
-		try:
-			tabsize = string.atoi(tabsize)
-		except (ValueError, OverflowError):
-			good = 0
-			sys.exc_traceback = None
-		else:
-			good = 1 <= tabsize <= 500
-		if good:
-			if self.lasttab <> tabsize:
-				self.lasttab = tabsize
-				self.doit()
-		else:
-			SysBeep(0)
-			self.w.tabsizeedit.set(repr(self.lasttab))
-			self.w.tabsizeedit.selectall()
-	
-	def checksize(self):
-		size = self.w.sizeedit.get()
-		if not size:
-			return
-		try:
-			size = string.atoi(size)
-		except (ValueError, OverflowError):
-			good = 0
-			sys.exc_traceback = None
-		else:
-			good = 1 <= size <= 500
-		if good:
-			if self.lastsize <> size:
-				self.lastsize = size
-				self.doit()
-		else:
-			SysBeep(0)
-			self.w.sizeedit.set(repr(self.lastsize))
-			self.w.sizeedit.selectall()
-	
-	def doplain(self):
-		for i in range(1, len(_stylenames)):
-			self.w[i].set(0)
-		self.w[0].set(1)
-		self.doit()
-	
-	def dostyle(self):
-		for i in range(1, len(_stylenames)):
-			if self.w[i].get():
-				self.w[0].set(0)
-				break
-		else:
-			self.w[0].set(1)
-		self.doit()
-	
-	def close(self):
-		self.w.close()
-		del self.w
-	
-	def cancel(self):
-		self.close()
-	
-	def done(self):
-		self._rv = self.get()
-		self.close()
-	
-	def setfont(self, fontname):
-		self.w.fontname.set(fontname)
-		self.doit()
-	
+
+    #def __del__(self):
+    #       print "doei!"
+
+    def __init__(self, fontsettings, tabsettings):
+        leftmargin = 60
+        leftmargin2 = leftmargin - 16
+        self.w = W.ModalDialog((440, 180), 'Font settings')
+        self.w.fonttitle = W.TextBox((10, 12, leftmargin2, 14), "Font:", TextEdit.teJustRight)
+        self.w.pop = W.FontMenu((leftmargin, 10, 16, 16), self.setfont)
+        self.w.fontname = W.TextBox((leftmargin + 20, 12, 150, 14))
+        self.w.sizetitle = W.TextBox((10, 38, leftmargin2, 14), "Size:", TextEdit.teJustRight)
+        self.w.sizeedit = W.EditText((leftmargin, 35, 40, 20), "", self.checksize)
+        styletop = 64
+        self.w.styletitle = W.TextBox((10, styletop + 2, leftmargin2, 14), "Style:", TextEdit.teJustRight)
+        for i in range(len(_stylenames)):
+            top = styletop + (i % 4) * 20
+            left = leftmargin + 80 * (i > 3) - 2
+            if i:
+                self.w[i] = W.CheckBox((left, top, 76, 16), _stylenames[i], self.dostyle)
+            else:
+                self.w[i] = W.CheckBox((left, top, 70, 16), _stylenames[i], self.doplain)
+
+        if tabsettings:
+            self.lasttab, self.tabmode = tabsettings
+            self.w.tabsizetitle = W.TextBox((10, -26, leftmargin2, 14), "Tabsize:", TextEdit.teJustRight)
+            self.w.tabsizeedit = W.EditText((leftmargin, -29, 40, 20), "", self.checktab)
+            self.w.tabsizeedit.set(repr(self.lasttab))
+            radiobuttons = []
+            self.w.tabsizechars = W.RadioButton((leftmargin + 48, -26, 55, 14), "Spaces",
+                            radiobuttons, self.toggletabmode)
+            self.w.tabsizepixels = W.RadioButton((leftmargin + 110, -26, 55, 14), "Pixels",
+                            radiobuttons, self.toggletabmode)
+            if self.tabmode:
+                self.w.tabsizechars.set(1)
+            else:
+                self.w.tabsizepixels.set(1)
+        else:
+            self.tabmode = None
+
+        self.w.cancelbutton = W.Button((-180, -26, 80, 16), "Cancel", self.cancel)
+        self.w.donebutton = W.Button((-90, -26, 80, 16), "Done", self.done)
+
+        sampletext = "Sample text."
+        self.w.sample = W.EditText((230, 10, -10, 130), sampletext,
+                        fontsettings = fontsettings, tabsettings = tabsettings)
+
+        self.w.setdefaultbutton(self.w.donebutton)
+        self.w.bind('cmd.', self.w.cancelbutton.push)
+        self.w.bind('cmdw', self.w.donebutton.push)
+        self.lastsize = fontsettings[2]
+        self._rv = None
+        self.set(fontsettings)
+        self.w.open()
+
+    def toggletabmode(self, onoff):
+        if self.w.tabsizechars.get():
+            tabmode = 1
+        else:
+            tabmode = 0
+        if self.tabmode <> tabmode:
+            port = self.w.wid.GetWindowPort()
+            (font, style, size, color), (tabsize, dummy) = self.get()
+            savesettings = W.GetPortFontSettings(port)
+            W.SetPortFontSettings(port, (font, style, size))
+            spacewidth = Qd.StringWidth(' ')
+            W.SetPortFontSettings(port, savesettings)
+            if tabmode:
+                # convert pixels to spaces
+                self.lasttab = int(round(float(tabsize) / spacewidth))
+            else:
+                # convert spaces to pixels
+                self.lasttab = spacewidth * tabsize
+            self.w.tabsizeedit.set(repr(self.lasttab))
+            self.tabmode = tabmode
+            self.doit()
+
+    def set(self, fontsettings):
+        font, style, size, color = fontsettings
+        if type(font) <> types.StringType:
+            from Carbon import Res
+            res = Res.GetResource('FOND', font)
+            font = res.GetResInfo()[2]
+        self.w.fontname.set(font)
+        self.w.sizeedit.set(str(size))
+        if style:
+            for i in range(1, len(_stylenames)):
+                self.w[i].set(style & 0x01)
+                style = style >> 1
+        else:
+            self.w[0].set(1)
+
+    def get(self):
+        font = self.w.fontname.get()
+        style = 0
+        if not self.w[0].get():
+            flag = 0x01
+            for i in range(1, len(_stylenames)):
+                if self.w[i].get():
+                    style = style | flag
+                flag = flag << 1
+        size = self.lastsize
+        if self.tabmode is None:
+            return (font, style, size, (0, 0, 0)), (32, 0)
+        else:
+            return (font, style, size, (0, 0, 0)), (self.lasttab, self.tabmode)
+
+    def doit(self):
+        if self.w[0].get():
+            style = 0
+        else:
+            style = 0
+            for i in range(1, len(_stylenames)):
+                if self.w[i].get():
+                    style = style | 2 ** (i - 1)
+        #self.w.sample.set(repr(style))
+        fontsettings, tabsettings = self.get()
+        self.w.sample.setfontsettings(fontsettings)
+        self.w.sample.settabsettings(tabsettings)
+
+    def checktab(self):
+        tabsize = self.w.tabsizeedit.get()
+        if not tabsize:
+            return
+        try:
+            tabsize = string.atoi(tabsize)
+        except (ValueError, OverflowError):
+            good = 0
+            sys.exc_traceback = None
+        else:
+            good = 1 <= tabsize <= 500
+        if good:
+            if self.lasttab <> tabsize:
+                self.lasttab = tabsize
+                self.doit()
+        else:
+            SysBeep(0)
+            self.w.tabsizeedit.set(repr(self.lasttab))
+            self.w.tabsizeedit.selectall()
+
+    def checksize(self):
+        size = self.w.sizeedit.get()
+        if not size:
+            return
+        try:
+            size = string.atoi(size)
+        except (ValueError, OverflowError):
+            good = 0
+            sys.exc_traceback = None
+        else:
+            good = 1 <= size <= 500
+        if good:
+            if self.lastsize <> size:
+                self.lastsize = size
+                self.doit()
+        else:
+            SysBeep(0)
+            self.w.sizeedit.set(repr(self.lastsize))
+            self.w.sizeedit.selectall()
+
+    def doplain(self):
+        for i in range(1, len(_stylenames)):
+            self.w[i].set(0)
+        self.w[0].set(1)
+        self.doit()
+
+    def dostyle(self):
+        for i in range(1, len(_stylenames)):
+            if self.w[i].get():
+                self.w[0].set(0)
+                break
+        else:
+            self.w[0].set(1)
+        self.doit()
+
+    def close(self):
+        self.w.close()
+        del self.w
+
+    def cancel(self):
+        self.close()
+
+    def done(self):
+        self._rv = self.get()
+        self.close()
+
+    def setfont(self, fontname):
+        self.w.fontname.set(fontname)
+        self.doit()
+
 
 def FontDialog(fontsettings, tabsettings = (32, 0)):
-	fd = _FontDialog(fontsettings, tabsettings)
-	return fd._rv
+    fd = _FontDialog(fontsettings, tabsettings)
+    return fd._rv
 
 def test():
-	print FontDialog(('Zapata-Light', 0, 25, (0, 0, 0)))
+    print FontDialog(('Zapata-Light', 0, 25, (0, 0, 0)))
diff --git a/Mac/Tools/IDE/MacPrefs.py b/Mac/Tools/IDE/MacPrefs.py
index 25dda4f..3cf9153 100644
--- a/Mac/Tools/IDE/MacPrefs.py
+++ b/Mac/Tools/IDE/MacPrefs.py
@@ -4,105 +4,105 @@
 from Carbon import Folders
 
 class PrefObject:
-	
-	def __init__(self, dict = None):
-		if dict == None:
-			self._prefsdict = {}
-		else:
-			self._prefsdict = dict
-	
-	def __len__(self):
-		return len(self._prefsdict)
-	
-	def __delattr__(self, attr):
-		if self._prefsdict.has_key(attr):
-			del self._prefsdict[attr]
-		else:
-			raise AttributeError, 'delete non-existing instance attribute'
-	
-	def __getattr__(self, attr):
-		if attr == '__members__':
-			keys = self._prefsdict.keys()
-			keys.sort()
-			return keys
-		try:
-			return self._prefsdict[attr]
-		except KeyError:
-			raise AttributeError, attr
-	
-	def __setattr__(self, attr, value):
-		if attr[0] <> '_':
-			self._prefsdict[attr] = value
-		else:
-			self.__dict__[attr] = value
-	
-	def getprefsdict(self):
-		return self._prefsdict
+
+    def __init__(self, dict = None):
+        if dict == None:
+            self._prefsdict = {}
+        else:
+            self._prefsdict = dict
+
+    def __len__(self):
+        return len(self._prefsdict)
+
+    def __delattr__(self, attr):
+        if self._prefsdict.has_key(attr):
+            del self._prefsdict[attr]
+        else:
+            raise AttributeError, 'delete non-existing instance attribute'
+
+    def __getattr__(self, attr):
+        if attr == '__members__':
+            keys = self._prefsdict.keys()
+            keys.sort()
+            return keys
+        try:
+            return self._prefsdict[attr]
+        except KeyError:
+            raise AttributeError, attr
+
+    def __setattr__(self, attr, value):
+        if attr[0] <> '_':
+            self._prefsdict[attr] = value
+        else:
+            self.__dict__[attr] = value
+
+    def getprefsdict(self):
+        return self._prefsdict
 
 
 class PrefFile(PrefObject):
-	
-	def __init__(self, path, creator = 'Pyth'):
-		# Find the preferences folder and our prefs file, create if needed.
-		self.__path = path
-		self.__creator = creator
-		self._prefsdict = {}
-		try:
-			prefdict = marshal.load(open(self.__path, 'rb'))
-		except (IOError, ValueError):
-			# file not found, or currupt marshal data
-			pass
-		else:
-			for key, value in prefdict.items():
-				if type(value) == types.DictType:
-					self._prefsdict[key] = PrefObject(value)
-				else:
-					self._prefsdict[key] = value
-	
-	def save(self):
-		prefdict = {}
-		for key, value in self._prefsdict.items():
-			if type(value) == types.InstanceType:
-				prefdict[key] = value.getprefsdict()
-				if not prefdict[key]:
-					del prefdict[key]
-			else:
-				prefdict[key] = value
-		marshal.dump(prefdict, open(self.__path, 'wb'))
-		try:
-			MacOS.SetCreatorAndType(self.__path, self.__creator, 'pref')
-		except:
-			pass
-	
-	def __getattr__(self, attr):
-		if attr == '__members__':
-			keys = self._prefsdict.keys()
-			keys.sort()
-			return keys
-		try:
-			return self._prefsdict[attr]
-		except KeyError:
-			if attr[0] <> '_':
-				self._prefsdict[attr] = PrefObject()
-				return self._prefsdict[attr]
-			else:
-				raise AttributeError, attr
+
+    def __init__(self, path, creator = 'Pyth'):
+        # Find the preferences folder and our prefs file, create if needed.
+        self.__path = path
+        self.__creator = creator
+        self._prefsdict = {}
+        try:
+            prefdict = marshal.load(open(self.__path, 'rb'))
+        except (IOError, ValueError):
+            # file not found, or currupt marshal data
+            pass
+        else:
+            for key, value in prefdict.items():
+                if type(value) == types.DictType:
+                    self._prefsdict[key] = PrefObject(value)
+                else:
+                    self._prefsdict[key] = value
+
+    def save(self):
+        prefdict = {}
+        for key, value in self._prefsdict.items():
+            if type(value) == types.InstanceType:
+                prefdict[key] = value.getprefsdict()
+                if not prefdict[key]:
+                    del prefdict[key]
+            else:
+                prefdict[key] = value
+        marshal.dump(prefdict, open(self.__path, 'wb'))
+        try:
+            MacOS.SetCreatorAndType(self.__path, self.__creator, 'pref')
+        except:
+            pass
+
+    def __getattr__(self, attr):
+        if attr == '__members__':
+            keys = self._prefsdict.keys()
+            keys.sort()
+            return keys
+        try:
+            return self._prefsdict[attr]
+        except KeyError:
+            if attr[0] <> '_':
+                self._prefsdict[attr] = PrefObject()
+                return self._prefsdict[attr]
+            else:
+                raise AttributeError, attr
 
 
 _prefscache = {}
 
 def GetPrefs(prefname, creator = 'Pyth'):
-	import macostools, os
-	if _prefscache.has_key(prefname):
-		return _prefscache[prefname]
-	# Find the preferences folder and our prefs file, create if needed.
-	fsr = Folder.FSFindFolder(Folders.kOnSystemDisk, 'pref', 1)
-	prefsfolder = fsr.as_pathname()
-	path = os.path.join(prefsfolder, prefname)
-	head, tail = os.path.split(path)
-	# make sure the folder(s) exist
-	macostools.mkdirs(head)
-	
-	preffile = PrefFile(path, creator)
-	_prefscache[prefname] = preffile
-	return preffile
+    import macostools, os
+    if _prefscache.has_key(prefname):
+        return _prefscache[prefname]
+    # Find the preferences folder and our prefs file, create if needed.
+    fsr = Folder.FSFindFolder(Folders.kOnSystemDisk, 'pref', 1)
+    prefsfolder = fsr.as_pathname()
+    path = os.path.join(prefsfolder, prefname)
+    head, tail = os.path.split(path)
+    # make sure the folder(s) exist
+    macostools.mkdirs(head)
+
+    preffile = PrefFile(path, creator)
+    _prefscache[prefname] = preffile
+    return preffile
diff --git a/Mac/Tools/IDE/ModuleBrowser.py b/Mac/Tools/IDE/ModuleBrowser.py
index 0e8850f..9fe1064 100644
--- a/Mac/Tools/IDE/ModuleBrowser.py
+++ b/Mac/Tools/IDE/ModuleBrowser.py
@@ -6,172 +6,172 @@
 __author__ = "jvr"
 
 class _modulebrowser:
-	
-	def __init__(self):
-		self.editmodules = []
-		self.modules = []
-		self.window = W.Window((210, 1000), "Module Browser", minsize = (210, 160), maxsize = (340, 20000))
-		
-		self.window.openbutton = W.Button((10, 8, 90, 16), "Open", self.openbuttonhit)
-		self.window.browsebutton = W.Button((110, 8, 90, 16), "Browse\xc9", self.browsebuttonhit)
-		self.window.reloadbutton = W.Button((10, 32, 90, 16), "Reload", self.reloadbuttonhit)
-		self.window.openotherbutton = W.Button((110, 32, 90, 16), "Open other\xc9", self.openother)
-		
-		self.window.openbutton.enable(0)
-		self.window.reloadbutton.enable(0)
-		self.window.browsebutton.enable(0)
-		self.window.setdefaultbutton(self.window.browsebutton)
-		
-		self.window.bind("cmdr", self.window.reloadbutton.push)
-		self.window.bind("cmdb", self.window.browsebutton.push)
-	
-		self.window.bind("<activate>", self.activate)
-		self.window.bind("<close>", self.close)
-		
-		self.window.list = W.List((-1, 56, 1, -14), [], self.listhit)
-		
-		self.window.open()
-		self.checkbuttons()
-	
-	def close(self):
-		global _browser
-		_browser = None
-	
-	def activate(self, onoff):
-		if onoff:
-			self.makelist()
-		
-	def listhit(self, isdbl):
-		self.checkbuttons()
-		if isdbl:
-			if self.window._defaultbutton:
-				self.window._defaultbutton.push()
-	
-	def checkbuttons(self):
-		sel = self.window.list.getselection()
-		if sel:
-			for i in sel:
-				if self.editmodules[i]:
-					self.window.openbutton.enable(1)
-					self.window.reloadbutton.enable(1)
-					self.window.setdefaultbutton(self.window.openbutton)
-					break
-			else:
-				self.window.openbutton.enable(0)
-				self.window.reloadbutton.enable(0)
-				self.window.setdefaultbutton(self.window.browsebutton)
-			self.window.browsebutton.enable(1)
-		else:
-			#self.window.setdefaultbutton(self.window.browsebutton)
-			self.window.openbutton.enable(0)
-			self.window.reloadbutton.enable(0)
-			self.window.browsebutton.enable(0)
-	
-	def openbuttonhit(self):
-		import imp
-		sel = self.window.list.getselection()
-		W.SetCursor("watch")
-		for i in sel:
-			modname = self.window.list[i]
-			try:
-				self.openscript(sys.modules[modname].__file__, modname)
-			except IOError:
-				try:
-					file, path, description = imp.find_module(modname)
-				except ImportError:
-					W.SetCursor("arrow")
-					W.Message("Can't find file for module '%s'." 
-							% modname)
-				else:
-					self.openscript(path, modname)					
-	
-	def openscript(self, path, modname):
-		import os
-		if path[-3:] == '.py':
-			W.getapplication().openscript(path, modname=modname)
-		elif path[-4:] in ['.pyc', '.pyo']:
-			W.getapplication().openscript(path[:-1], modname=modname)
-		else:
-			W.Message("Can't edit '%s'; it might be a shared library or a .pyc file." 
-					% modname)
-	
-	def openother(self):
-		import imp
-		import EasyDialogs
-		
-		modname = EasyDialogs.AskString("Open module:")
-		if modname:
-			try:
-				file, path, description = imp.find_module(modname)
-			except ImportError:
-				if modname in sys.builtin_module_names:
-					alerttext = "'%s' is a builtin module, which you can't edit." % modname
-				else:
-					alerttext = "No module named '%s'." % modname
-				raise W.AlertError, alerttext
-			self.openscript(path, modname)
-	
-	def reloadbuttonhit(self):
-		sel = self.window.list.getselection()
-		W.SetCursor("watch")
-		for i in sel:
-			mname = self.window.list[i]
-			m = sys.modules[mname]
-			# Set the __name__ attribute of the module to its real name.
-			# reload() complains if it's __main__, which is true
-			# when it recently has been run as a script with "Run as __main__" 
-			# enabled.
-			m.__name__ = mname
-			reload(m)
-	
-	def browsebuttonhit(self):
-		sel = self.window.list.getselection()
-		if not sel:
-			return
-		import PyBrowser
-		for i in sel:
-			PyBrowser.Browser(sys.modules[self.window.list[i]])
-	
-	def makelist(self):
-		editmodules, modules = getmoduleslist()
-		if modules == self.modules:
-			return
-		self.editmodules, self.modules = editmodules, modules
-		self.window.list.setdrawingmode(0)
-		sel = self.window.list.getselectedobjects()
-		self.window.list.set(self.modules)
-		self.window.list.setselectedobjects(sel)
-		self.window.list.setdrawingmode(1)
+
+    def __init__(self):
+        self.editmodules = []
+        self.modules = []
+        self.window = W.Window((210, 1000), "Module Browser", minsize = (210, 160), maxsize = (340, 20000))
+
+        self.window.openbutton = W.Button((10, 8, 90, 16), "Open", self.openbuttonhit)
+        self.window.browsebutton = W.Button((110, 8, 90, 16), "Browse\xc9", self.browsebuttonhit)
+        self.window.reloadbutton = W.Button((10, 32, 90, 16), "Reload", self.reloadbuttonhit)
+        self.window.openotherbutton = W.Button((110, 32, 90, 16), "Open other\xc9", self.openother)
+
+        self.window.openbutton.enable(0)
+        self.window.reloadbutton.enable(0)
+        self.window.browsebutton.enable(0)
+        self.window.setdefaultbutton(self.window.browsebutton)
+
+        self.window.bind("cmdr", self.window.reloadbutton.push)
+        self.window.bind("cmdb", self.window.browsebutton.push)
+
+        self.window.bind("<activate>", self.activate)
+        self.window.bind("<close>", self.close)
+
+        self.window.list = W.List((-1, 56, 1, -14), [], self.listhit)
+
+        self.window.open()
+        self.checkbuttons()
+
+    def close(self):
+        global _browser
+        _browser = None
+
+    def activate(self, onoff):
+        if onoff:
+            self.makelist()
+
+    def listhit(self, isdbl):
+        self.checkbuttons()
+        if isdbl:
+            if self.window._defaultbutton:
+                self.window._defaultbutton.push()
+
+    def checkbuttons(self):
+        sel = self.window.list.getselection()
+        if sel:
+            for i in sel:
+                if self.editmodules[i]:
+                    self.window.openbutton.enable(1)
+                    self.window.reloadbutton.enable(1)
+                    self.window.setdefaultbutton(self.window.openbutton)
+                    break
+            else:
+                self.window.openbutton.enable(0)
+                self.window.reloadbutton.enable(0)
+                self.window.setdefaultbutton(self.window.browsebutton)
+            self.window.browsebutton.enable(1)
+        else:
+            #self.window.setdefaultbutton(self.window.browsebutton)
+            self.window.openbutton.enable(0)
+            self.window.reloadbutton.enable(0)
+            self.window.browsebutton.enable(0)
+
+    def openbuttonhit(self):
+        import imp
+        sel = self.window.list.getselection()
+        W.SetCursor("watch")
+        for i in sel:
+            modname = self.window.list[i]
+            try:
+                self.openscript(sys.modules[modname].__file__, modname)
+            except IOError:
+                try:
+                    file, path, description = imp.find_module(modname)
+                except ImportError:
+                    W.SetCursor("arrow")
+                    W.Message("Can't find file for module '%s'."
+                                    % modname)
+                else:
+                    self.openscript(path, modname)
+
+    def openscript(self, path, modname):
+        import os
+        if path[-3:] == '.py':
+            W.getapplication().openscript(path, modname=modname)
+        elif path[-4:] in ['.pyc', '.pyo']:
+            W.getapplication().openscript(path[:-1], modname=modname)
+        else:
+            W.Message("Can't edit '%s'; it might be a shared library or a .pyc file."
+                            % modname)
+
+    def openother(self):
+        import imp
+        import EasyDialogs
+
+        modname = EasyDialogs.AskString("Open module:")
+        if modname:
+            try:
+                file, path, description = imp.find_module(modname)
+            except ImportError:
+                if modname in sys.builtin_module_names:
+                    alerttext = "'%s' is a builtin module, which you can't edit." % modname
+                else:
+                    alerttext = "No module named '%s'." % modname
+                raise W.AlertError, alerttext
+            self.openscript(path, modname)
+
+    def reloadbuttonhit(self):
+        sel = self.window.list.getselection()
+        W.SetCursor("watch")
+        for i in sel:
+            mname = self.window.list[i]
+            m = sys.modules[mname]
+            # Set the __name__ attribute of the module to its real name.
+            # reload() complains if it's __main__, which is true
+            # when it recently has been run as a script with "Run as __main__"
+            # enabled.
+            m.__name__ = mname
+            reload(m)
+
+    def browsebuttonhit(self):
+        sel = self.window.list.getselection()
+        if not sel:
+            return
+        import PyBrowser
+        for i in sel:
+            PyBrowser.Browser(sys.modules[self.window.list[i]])
+
+    def makelist(self):
+        editmodules, modules = getmoduleslist()
+        if modules == self.modules:
+            return
+        self.editmodules, self.modules = editmodules, modules
+        self.window.list.setdrawingmode(0)
+        sel = self.window.list.getselectedobjects()
+        self.window.list.set(self.modules)
+        self.window.list.setselectedobjects(sel)
+        self.window.list.setdrawingmode(1)
 
 
 def getmoduleslist():
-	import PyBrowser	# for caselesssort function
-	moduleitems = sys.modules.items()
-	moduleitems = filter(lambda (name, module): module is not None, moduleitems)
-	modules = map(lambda (name, module): name, moduleitems)
-	modules = PyBrowser.caselesssort(modules)
-	editmodules = []
-	sysmodules = sys.modules
-	modulesappend = editmodules.append
-	for m in modules:
-		module = sysmodules[m]
-		try:
-			if sysmodules[m].__file__[-3:] == '.py' or \
-					sysmodules[m].__file__[-4:] in ['.pyc', '.pyo']:
-				modulesappend(1)
-			else:
-				modulesappend(0)
-		except AttributeError:
-			modulesappend(0)
-	return editmodules, modules
-	
-	
+    import PyBrowser        # for caselesssort function
+    moduleitems = sys.modules.items()
+    moduleitems = filter(lambda (name, module): module is not None, moduleitems)
+    modules = map(lambda (name, module): name, moduleitems)
+    modules = PyBrowser.caselesssort(modules)
+    editmodules = []
+    sysmodules = sys.modules
+    modulesappend = editmodules.append
+    for m in modules:
+        module = sysmodules[m]
+        try:
+            if sysmodules[m].__file__[-3:] == '.py' or \
+                            sysmodules[m].__file__[-4:] in ['.pyc', '.pyo']:
+                modulesappend(1)
+            else:
+                modulesappend(0)
+        except AttributeError:
+            modulesappend(0)
+    return editmodules, modules
+
+
 
 _browser = None
 
 def ModuleBrowser():
-	global _browser
-	if _browser is not None:
-		_browser.window.select()
-	else:
-		_browser = _modulebrowser()
+    global _browser
+    if _browser is not None:
+        _browser.window.select()
+    else:
+        _browser = _modulebrowser()
diff --git a/Mac/Tools/IDE/PackageManager.py b/Mac/Tools/IDE/PackageManager.py
index ee6355b..0041a17 100755
--- a/Mac/Tools/IDE/PackageManager.py
+++ b/Mac/Tools/IDE/PackageManager.py
@@ -1,37 +1,37 @@
 # Prelude to allow running this as a main program
 def _init():
-	import macresource
-	import sys, os
-	macresource.need('DITL', 468, "PythonIDE.rsrc")
-	widgetrespathsegs = [sys.exec_prefix, "Mac", "Tools", "IDE", "Widgets.rsrc"]
-	widgetresfile = os.path.join(*widgetrespathsegs)
-	if not os.path.exists(widgetresfile):
-		widgetrespathsegs = [os.pardir, "Tools", "IDE", "Widgets.rsrc"]
-		widgetresfile = os.path.join(*widgetrespathsegs)
-	refno = macresource.need('CURS', 468, widgetresfile)
-	if os.environ.has_key('PYTHONIDEPATH'):
-		# For development set this environment variable
-		ide_path = os.environ['PYTHONIDEPATH']
-	elif refno:
-		# We're not a fullblown application
-		idepathsegs = [sys.exec_prefix, "Mac", "Tools", "IDE"]
-		ide_path = os.path.join(*idepathsegs)
-		if not os.path.exists(ide_path):
-			idepathsegs = [os.pardir, "Tools", "IDE"]
-			for p in sys.path:
-				ide_path = os.path.join(*([p]+idepathsegs))
-				if os.path.exists(ide_path):
-					break
-		
-	else:
-		# We are a fully frozen application
-		ide_path = sys.argv[0]
-	if ide_path not in sys.path:
-		sys.path.insert(0, ide_path)
-		
+    import macresource
+    import sys, os
+    macresource.need('DITL', 468, "PythonIDE.rsrc")
+    widgetrespathsegs = [sys.exec_prefix, "Mac", "Tools", "IDE", "Widgets.rsrc"]
+    widgetresfile = os.path.join(*widgetrespathsegs)
+    if not os.path.exists(widgetresfile):
+        widgetrespathsegs = [os.pardir, "Tools", "IDE", "Widgets.rsrc"]
+        widgetresfile = os.path.join(*widgetrespathsegs)
+    refno = macresource.need('CURS', 468, widgetresfile)
+    if os.environ.has_key('PYTHONIDEPATH'):
+        # For development set this environment variable
+        ide_path = os.environ['PYTHONIDEPATH']
+    elif refno:
+        # We're not a fullblown application
+        idepathsegs = [sys.exec_prefix, "Mac", "Tools", "IDE"]
+        ide_path = os.path.join(*idepathsegs)
+        if not os.path.exists(ide_path):
+            idepathsegs = [os.pardir, "Tools", "IDE"]
+            for p in sys.path:
+                ide_path = os.path.join(*([p]+idepathsegs))
+                if os.path.exists(ide_path):
+                    break
+
+    else:
+        # We are a fully frozen application
+        ide_path = sys.argv[0]
+    if ide_path not in sys.path:
+        sys.path.insert(0, ide_path)
+
 if __name__ == '__main__':
-	_init()
-	
+    _init()
+
 import W
 import Wapplication
 from Carbon import Evt
@@ -48,424 +48,424 @@
 PACKMAN_HOMEPAGE="http://www.python.org/packman"
 
 ELIPSES = '...'
-		
+
 USER_INSTALL_DIR = os.path.join(os.environ.get('HOME', ''),
-								'Library',
-								'Python',
-								sys.version[:3],
-								'site-packages')
-								
+                                                                'Library',
+                                                                'Python',
+                                                                sys.version[:3],
+                                                                'site-packages')
+
 class PackageManagerMain(Wapplication.Application):
-	
-	def __init__(self):
-		self.preffilepath = os.path.join("Python", "Package Install Manager Prefs")
-		Wapplication.Application.__init__(self, 'Pimp')
-		from Carbon import AE
-		from Carbon import AppleEvents
-		self.defaulturl = ""
-		
-		AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEOpenApplication, 
-				self.ignoreevent)
-		AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEReopenApplication, 
-				self.ignoreevent)
-		AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEPrintDocuments, 
-				self.ignoreevent)
-		AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEQuitApplication, 
-				self.quitevent)
-		if 1:
-			import PyConsole
-			# With -D option (OSX command line only) keep stderr, for debugging the IDE
-			# itself.
-			debug_stderr = None
-			if len(sys.argv) >= 2 and sys.argv[1] == '-D':
-				debug_stderr = sys.stderr
-				del sys.argv[1]
-			PyConsole.installoutput()
-			if debug_stderr:
-				sys.stderr = debug_stderr
-		self.domenu_openstandard()
-		self.mainloop()
-		
-	def makeusermenus(self):
-		m = Wapplication.Menu(self.menubar, "File")
-		newitem = FrameWork.MenuItem(m, "Open Standard Database", "N", 'openstandard')
-		newexpitem = FrameWork.MenuItem(m, "Open Experimental Database", None, 'openexperimental')
-		newexpitem.enable(pimp.PIMP_VERSION >= "0.4")
-		openitem = FrameWork.MenuItem(m, "Open"+ELIPSES, "O", 'open')
-		openURLitem = FrameWork.MenuItem(m, "Open URL"+ELIPSES, "D", 'openURL')
-		FrameWork.Separator(m)
-		moreinfoitem = FrameWork.MenuItem(m, "More Databases", None, 'opendatabasepage')
-		FrameWork.Separator(m)
-		closeitem = FrameWork.MenuItem(m, "Close", "W", 'close')
-##		saveitem = FrameWork.MenuItem(m, "Save", "S", 'save')
-##		saveasitem = FrameWork.MenuItem(m, "Save as"+ELIPSES, None, 'save_as')
-##		FrameWork.Separator(m)
-		
-		m = Wapplication.Menu(self.menubar, "Edit")
-		undoitem = FrameWork.MenuItem(m, "Undo", 'Z', "undo")
-		FrameWork.Separator(m)
-		cutitem = FrameWork.MenuItem(m, "Cut", 'X', "cut")
-		copyitem = FrameWork.MenuItem(m, "Copy", "C", "copy")
-		pasteitem = FrameWork.MenuItem(m, "Paste", "V", "paste")
-		FrameWork.MenuItem(m, "Clear", None,  "clear")
-		FrameWork.Separator(m)
-		selallitem = FrameWork.MenuItem(m, "Select all", "A", "selectall")
-		
-		m = Wapplication.Menu(self.menubar, "Package")
-		runitem = FrameWork.MenuItem(m, "Install", "I", 'install')
-		homepageitem = FrameWork.MenuItem(m, "Visit Homepage", None, 'homepage')
-		
-		self.openwindowsmenu = Wapplication.Menu(self.menubar, 'Windows')
-		self.makeopenwindowsmenu()
-		self.makehelpmenu()
-		self._menustocheck = [closeitem, 
-				undoitem, cutitem, copyitem, pasteitem, 
-				selallitem,
-				runitem, homepageitem]
-			
-	def makehelpmenu(self):
-		python_app = os.path.join(sys.prefix, 'Resources/Python.app')
-		help_source = os.path.join(python_app, 'Contents/Resources/English.lproj/Documentation')
-		hashelp = os.path.isdir(help_source)
 
-		self.helpmenu = m = self.gethelpmenu()
-		helpitem1 = FrameWork.MenuItem(m, "PackageManager Help", None, self.domenu_packmanhelp)
-		helpitem1.enable(hashelp)
-		helpitem2 = FrameWork.MenuItem(m, "MacPython Help", None, self.domenu_pythonhelp)
-		helpitem2.enable(hashelp)
+    def __init__(self):
+        self.preffilepath = os.path.join("Python", "Package Install Manager Prefs")
+        Wapplication.Application.__init__(self, 'Pimp')
+        from Carbon import AE
+        from Carbon import AppleEvents
+        self.defaulturl = ""
 
-	def quitevent(self, theAppleEvent, theReply):
-		self._quit()
-		
-	def ignoreevent(self, theAppleEvent, theReply):
-		pass
-	
-	def opendocsevent(self, theAppleEvent, theReply):
-		W.SetCursor('watch')
-		import aetools
-		parameters, args = aetools.unpackevent(theAppleEvent)
-		docs = parameters['----']
-		if type(docs) <> type([]):
-			docs = [docs]
-		for doc in docs:
-			fsr, a = doc.FSResolveAlias(None)
-			path = fsr.as_pathname()
-			path = urllib.pathname2url(path)
-			self.opendoc(path)
-	
-	def opendoc(self, url):
-		if url:
-			self.defaulturl = url
-		PackageBrowser(url)
-	
-	def getabouttext(self):
-		return "About Package Manager"+ELIPSES
-	
-	def do_about(self, id, item, window, event):
-		EasyDialogs.Message("Package Install Manager for Python\nPackMan engine (pimp) version: %s" %
-			pimp.PIMP_VERSION)
-	
-	def domenu_openstandard(self, *args):
-		if pimp.PIMP_VERSION >= "0.4":
-			url = pimp.getDefaultDatabase()
-		else:
-			# 0.3 compatibility
-			url = None
-		self.opendoc(url)
-		
-	def domenu_openexperimental(self, *args):
-		database = pimp.getDefaultDatabase(experimental=True)
-		self.opendoc(database)
-		
-	def domenu_open(self, *args):
-		filename = EasyDialogs.AskFileForOpen(typeList=("TEXT",))
-		if filename:
-			filename = urllib.pathname2url(filename)
-			self.opendoc(filename)
-			
-	def domenu_openURL(self, *args):
-		ok = EasyDialogs.AskYesNoCancel(
-			"Warning: by opening a non-standard database "
-			"you are trusting the maintainer of it "
-			"to run arbitrary code on your machine.",
-			yes="OK", no="")
-		if ok <= 0: return
-		url = EasyDialogs.AskString("URL of database to open:", 
-			default=self.defaulturl, ok="Open")
-		if url:
-			self.opendoc(url)
-	
-	def domenu_opendatabasepage(self):
-		import ic
-			
-		icr = ic.IC()
-		icr.launchurl(PACKMAN_HOMEPAGE)
-	def makeopenwindowsmenu(self):
-		for i in range(len(self.openwindowsmenu.items)):
-			self.openwindowsmenu.menu.DeleteMenuItem(1)
-			self.openwindowsmenu.items = []
-		windows = []
-		self._openwindows = {}
-		for window in self._windows.keys():
-			title = window.GetWTitle()
-			if not title:
-				title = "<no title>"
-			windows.append((title, window))
-		windows.sort()
-		for title, window in windows:
-			shortcut = None
-			item = FrameWork.MenuItem(self.openwindowsmenu, title, shortcut, callback = self.domenu_openwindows)
-			self._openwindows[item.item] = window
-		self._openwindowscheckmark = 0
-		self.checkopenwindowsmenu()
-		
-	def domenu_openwindows(self, id, item, window, event):
-		w = self._openwindows[item]
-		w.ShowWindow()
-		w.SelectWindow()
-	
-	def domenu_quit(self):
-		self._quit()
-	
-	def domenu_save(self, *args):
-		print "Save"
-	
-	def domenu_pythonhelp(self, *args):
-		from Carbon import AH
-		AH.AHGotoPage("MacPython Help", None, None)
-		
-	def domenu_packmanhelp(self, *args):
-		from Carbon import AH
-		AH.AHGotoPage("MacPython Help", "packman.html", None)
-		
-	def _quit(self):
-##		import PyConsole, PyEdit
-		for window in self._windows.values():
-			try:
-				rv = window.close() # ignore any errors while quitting
-			except:
-				rv = 0	 # (otherwise, we can get stuck!)
-			if rv and rv > 0:
-				return
-##		try:
-##			PyConsole.console.writeprefs()
-##			PyConsole.output.writeprefs()
-##			PyEdit.searchengine.writeprefs()
-##		except:
-##			# Write to __stderr__ so the msg end up in Console.app and has
-##			# at least _some_ chance of getting read...
-##			# But: this is a workaround for way more serious problems with
-##			# the Python 2.2 Jaguar addon.
-##			sys.__stderr__.write("*** PythonIDE: Can't write preferences ***\n")
-		self.quitting = 1
-		
+        AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEOpenApplication,
+                        self.ignoreevent)
+        AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEReopenApplication,
+                        self.ignoreevent)
+        AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEPrintDocuments,
+                        self.ignoreevent)
+        AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEQuitApplication,
+                        self.quitevent)
+        if 1:
+            import PyConsole
+            # With -D option (OSX command line only) keep stderr, for debugging the IDE
+            # itself.
+            debug_stderr = None
+            if len(sys.argv) >= 2 and sys.argv[1] == '-D':
+                debug_stderr = sys.stderr
+                del sys.argv[1]
+            PyConsole.installoutput()
+            if debug_stderr:
+                sys.stderr = debug_stderr
+        self.domenu_openstandard()
+        self.mainloop()
+
+    def makeusermenus(self):
+        m = Wapplication.Menu(self.menubar, "File")
+        newitem = FrameWork.MenuItem(m, "Open Standard Database", "N", 'openstandard')
+        newexpitem = FrameWork.MenuItem(m, "Open Experimental Database", None, 'openexperimental')
+        newexpitem.enable(pimp.PIMP_VERSION >= "0.4")
+        openitem = FrameWork.MenuItem(m, "Open"+ELIPSES, "O", 'open')
+        openURLitem = FrameWork.MenuItem(m, "Open URL"+ELIPSES, "D", 'openURL')
+        FrameWork.Separator(m)
+        moreinfoitem = FrameWork.MenuItem(m, "More Databases", None, 'opendatabasepage')
+        FrameWork.Separator(m)
+        closeitem = FrameWork.MenuItem(m, "Close", "W", 'close')
+##              saveitem = FrameWork.MenuItem(m, "Save", "S", 'save')
+##              saveasitem = FrameWork.MenuItem(m, "Save as"+ELIPSES, None, 'save_as')
+##              FrameWork.Separator(m)
+
+        m = Wapplication.Menu(self.menubar, "Edit")
+        undoitem = FrameWork.MenuItem(m, "Undo", 'Z', "undo")
+        FrameWork.Separator(m)
+        cutitem = FrameWork.MenuItem(m, "Cut", 'X', "cut")
+        copyitem = FrameWork.MenuItem(m, "Copy", "C", "copy")
+        pasteitem = FrameWork.MenuItem(m, "Paste", "V", "paste")
+        FrameWork.MenuItem(m, "Clear", None,  "clear")
+        FrameWork.Separator(m)
+        selallitem = FrameWork.MenuItem(m, "Select all", "A", "selectall")
+
+        m = Wapplication.Menu(self.menubar, "Package")
+        runitem = FrameWork.MenuItem(m, "Install", "I", 'install')
+        homepageitem = FrameWork.MenuItem(m, "Visit Homepage", None, 'homepage')
+
+        self.openwindowsmenu = Wapplication.Menu(self.menubar, 'Windows')
+        self.makeopenwindowsmenu()
+        self.makehelpmenu()
+        self._menustocheck = [closeitem,
+                        undoitem, cutitem, copyitem, pasteitem,
+                        selallitem,
+                        runitem, homepageitem]
+
+    def makehelpmenu(self):
+        python_app = os.path.join(sys.prefix, 'Resources/Python.app')
+        help_source = os.path.join(python_app, 'Contents/Resources/English.lproj/Documentation')
+        hashelp = os.path.isdir(help_source)
+
+        self.helpmenu = m = self.gethelpmenu()
+        helpitem1 = FrameWork.MenuItem(m, "PackageManager Help", None, self.domenu_packmanhelp)
+        helpitem1.enable(hashelp)
+        helpitem2 = FrameWork.MenuItem(m, "MacPython Help", None, self.domenu_pythonhelp)
+        helpitem2.enable(hashelp)
+
+    def quitevent(self, theAppleEvent, theReply):
+        self._quit()
+
+    def ignoreevent(self, theAppleEvent, theReply):
+        pass
+
+    def opendocsevent(self, theAppleEvent, theReply):
+        W.SetCursor('watch')
+        import aetools
+        parameters, args = aetools.unpackevent(theAppleEvent)
+        docs = parameters['----']
+        if type(docs) <> type([]):
+            docs = [docs]
+        for doc in docs:
+            fsr, a = doc.FSResolveAlias(None)
+            path = fsr.as_pathname()
+            path = urllib.pathname2url(path)
+            self.opendoc(path)
+
+    def opendoc(self, url):
+        if url:
+            self.defaulturl = url
+        PackageBrowser(url)
+
+    def getabouttext(self):
+        return "About Package Manager"+ELIPSES
+
+    def do_about(self, id, item, window, event):
+        EasyDialogs.Message("Package Install Manager for Python\nPackMan engine (pimp) version: %s" %
+                pimp.PIMP_VERSION)
+
+    def domenu_openstandard(self, *args):
+        if pimp.PIMP_VERSION >= "0.4":
+            url = pimp.getDefaultDatabase()
+        else:
+            # 0.3 compatibility
+            url = None
+        self.opendoc(url)
+
+    def domenu_openexperimental(self, *args):
+        database = pimp.getDefaultDatabase(experimental=True)
+        self.opendoc(database)
+
+    def domenu_open(self, *args):
+        filename = EasyDialogs.AskFileForOpen(typeList=("TEXT",))
+        if filename:
+            filename = urllib.pathname2url(filename)
+            self.opendoc(filename)
+
+    def domenu_openURL(self, *args):
+        ok = EasyDialogs.AskYesNoCancel(
+                "Warning: by opening a non-standard database "
+                "you are trusting the maintainer of it "
+                "to run arbitrary code on your machine.",
+                yes="OK", no="")
+        if ok <= 0: return
+        url = EasyDialogs.AskString("URL of database to open:",
+                default=self.defaulturl, ok="Open")
+        if url:
+            self.opendoc(url)
+
+    def domenu_opendatabasepage(self):
+        import ic
+
+        icr = ic.IC()
+        icr.launchurl(PACKMAN_HOMEPAGE)
+    def makeopenwindowsmenu(self):
+        for i in range(len(self.openwindowsmenu.items)):
+            self.openwindowsmenu.menu.DeleteMenuItem(1)
+            self.openwindowsmenu.items = []
+        windows = []
+        self._openwindows = {}
+        for window in self._windows.keys():
+            title = window.GetWTitle()
+            if not title:
+                title = "<no title>"
+            windows.append((title, window))
+        windows.sort()
+        for title, window in windows:
+            shortcut = None
+            item = FrameWork.MenuItem(self.openwindowsmenu, title, shortcut, callback = self.domenu_openwindows)
+            self._openwindows[item.item] = window
+        self._openwindowscheckmark = 0
+        self.checkopenwindowsmenu()
+
+    def domenu_openwindows(self, id, item, window, event):
+        w = self._openwindows[item]
+        w.ShowWindow()
+        w.SelectWindow()
+
+    def domenu_quit(self):
+        self._quit()
+
+    def domenu_save(self, *args):
+        print "Save"
+
+    def domenu_pythonhelp(self, *args):
+        from Carbon import AH
+        AH.AHGotoPage("MacPython Help", None, None)
+
+    def domenu_packmanhelp(self, *args):
+        from Carbon import AH
+        AH.AHGotoPage("MacPython Help", "packman.html", None)
+
+    def _quit(self):
+##              import PyConsole, PyEdit
+        for window in self._windows.values():
+            try:
+                rv = window.close() # ignore any errors while quitting
+            except:
+                rv = 0   # (otherwise, we can get stuck!)
+            if rv and rv > 0:
+                return
+##              try:
+##                      PyConsole.console.writeprefs()
+##                      PyConsole.output.writeprefs()
+##                      PyEdit.searchengine.writeprefs()
+##              except:
+##                      # Write to __stderr__ so the msg end up in Console.app and has
+##                      # at least _some_ chance of getting read...
+##                      # But: this is a workaround for way more serious problems with
+##                      # the Python 2.2 Jaguar addon.
+##                      sys.__stderr__.write("*** PythonIDE: Can't write preferences ***\n")
+        self.quitting = 1
+
 class PimpInterface:
 
-	def setuppimp(self, url):
-		self.pimpprefs = pimp.PimpPreferences()
-		self.pimpdb = pimp.PimpDatabase(self.pimpprefs)
-		if not url:
-			url = self.pimpprefs.pimpDatabase
-		try:
-			self.pimpdb.appendURL(url)
-		except IOError, arg:
-			rv = "Cannot open %s: %s\n" % (url, arg)
-			rv += "\nSee MacPython Package Manager help page."
-			return rv
-		except:
-			rv = "Unspecified error while parsing database: %s\n" % url
-			rv += "Usually, this means the database is not correctly formatted.\n"
-			rv += "\nSee MacPython Package Manager help page."
-			return rv
-		# Check whether we can write the installation directory.
-		# If not, set to the per-user directory, possibly
-		# creating it, if needed.
-		installDir = self.pimpprefs.installDir
-		if not os.access(installDir, os.R_OK|os.W_OK|os.X_OK):
-			rv = self.setuserinstall(1)
-			if rv: return rv
-		return self.pimpprefs.check()
-		
-	def closepimp(self):
-		self.pimpdb.close()
-		self.pimpprefs = None
-		self.pimpdb = None
-		self.packages = []
+    def setuppimp(self, url):
+        self.pimpprefs = pimp.PimpPreferences()
+        self.pimpdb = pimp.PimpDatabase(self.pimpprefs)
+        if not url:
+            url = self.pimpprefs.pimpDatabase
+        try:
+            self.pimpdb.appendURL(url)
+        except IOError, arg:
+            rv = "Cannot open %s: %s\n" % (url, arg)
+            rv += "\nSee MacPython Package Manager help page."
+            return rv
+        except:
+            rv = "Unspecified error while parsing database: %s\n" % url
+            rv += "Usually, this means the database is not correctly formatted.\n"
+            rv += "\nSee MacPython Package Manager help page."
+            return rv
+        # Check whether we can write the installation directory.
+        # If not, set to the per-user directory, possibly
+        # creating it, if needed.
+        installDir = self.pimpprefs.installDir
+        if not os.access(installDir, os.R_OK|os.W_OK|os.X_OK):
+            rv = self.setuserinstall(1)
+            if rv: return rv
+        return self.pimpprefs.check()
 
-	def setuserinstall(self, onoff):
-		rv = ""
-		if onoff:
-			if not os.path.exists(USER_INSTALL_DIR):
-				try:
-					os.makedirs(USER_INSTALL_DIR)
-				except OSError, arg:
-					rv = rv + arg + "\n"
-			if not USER_INSTALL_DIR in sys.path:
-				import site
-				reload(site)
-			self.pimpprefs.setInstallDir(USER_INSTALL_DIR)
-		else:
-			self.pimpprefs.setInstallDir(None)
-		rv = rv + self.pimpprefs.check()
-		return rv
-		
-	def getuserinstall(self):
-		return self.pimpprefs.installDir == USER_INSTALL_DIR
-			
-	def getbrowserdata(self, show_hidden=1):
-		packages = self.pimpdb.list()
-		if show_hidden:
-			self.packages = packages
-		else:
-			self.packages = []
-			for pkg in packages:
-				name = pkg.fullname()
-				if name[0] == '(' and name[-1] == ')' and not show_hidden:
-					continue
-				self.packages.append(pkg)			
-		rv = []
-		for pkg in self.packages:
-			name = pkg.fullname()
-			status, _ = pkg.installed()
-			description = pkg.description()
-			description_line1 = description.split('\n')[0]
-			rv.append((status, name, description_line1))
-		return rv
-		
-	def getstatus(self, number):
-		pkg = self.packages[number]
-		return pkg.installed()
-		
-	def installpackage(self, sel, output, recursive, force):
-		pkg = self.packages[sel]
-		pimpinstaller = pimp.PimpInstaller(self.pimpdb)
-		list, messages = pimpinstaller.prepareInstall(pkg, force, recursive)
-		if messages:
-			return messages
-		messages = pimpinstaller.install(list, output)
-		return messages
-			
+    def closepimp(self):
+        self.pimpdb.close()
+        self.pimpprefs = None
+        self.pimpdb = None
+        self.packages = []
+
+    def setuserinstall(self, onoff):
+        rv = ""
+        if onoff:
+            if not os.path.exists(USER_INSTALL_DIR):
+                try:
+                    os.makedirs(USER_INSTALL_DIR)
+                except OSError, arg:
+                    rv = rv + arg + "\n"
+            if not USER_INSTALL_DIR in sys.path:
+                import site
+                reload(site)
+            self.pimpprefs.setInstallDir(USER_INSTALL_DIR)
+        else:
+            self.pimpprefs.setInstallDir(None)
+        rv = rv + self.pimpprefs.check()
+        return rv
+
+    def getuserinstall(self):
+        return self.pimpprefs.installDir == USER_INSTALL_DIR
+
+    def getbrowserdata(self, show_hidden=1):
+        packages = self.pimpdb.list()
+        if show_hidden:
+            self.packages = packages
+        else:
+            self.packages = []
+            for pkg in packages:
+                name = pkg.fullname()
+                if name[0] == '(' and name[-1] == ')' and not show_hidden:
+                    continue
+                self.packages.append(pkg)
+        rv = []
+        for pkg in self.packages:
+            name = pkg.fullname()
+            status, _ = pkg.installed()
+            description = pkg.description()
+            description_line1 = description.split('\n')[0]
+            rv.append((status, name, description_line1))
+        return rv
+
+    def getstatus(self, number):
+        pkg = self.packages[number]
+        return pkg.installed()
+
+    def installpackage(self, sel, output, recursive, force):
+        pkg = self.packages[sel]
+        pimpinstaller = pimp.PimpInstaller(self.pimpdb)
+        list, messages = pimpinstaller.prepareInstall(pkg, force, recursive)
+        if messages:
+            return messages
+        messages = pimpinstaller.install(list, output)
+        return messages
+
 class PackageBrowser(PimpInterface):
-	
-	def __init__(self, url = None):
-		self.ic = None
-		messages = self.setuppimp(url)
-		self.setupwidgets()
-		self.updatestatus()
-		self.showmessages(messages)
-		
-	def close(self):
-		self.closepimp()
-	
-	def setupwidgets(self):
-		DESCRIPTION_HEIGHT = 140
-		INSTALL_POS = -30
-		STATUS_POS = INSTALL_POS - (70 + DESCRIPTION_HEIGHT)
-		self.w = W.Window((580, 600), "Python Install Manager", minsize = (400, 400), tabbable = 0)
-		self.w.titlebar = W.TextBox((4, 8, 60, 18), 'Packages:')
-		self.w.hidden_button = W.CheckBox((-100, 4, 0, 18), 'Show Hidden', self.updatestatus)
-		data = self.getbrowserdata()
-		self.w.packagebrowser = W.MultiList((4, 24, 0, STATUS_POS-2), data, self.listhit, cols=3)
-		
-		self.w.installed_l = W.TextBox((4, STATUS_POS, 70, 12), 'Installed:')
-		self.w.installed = W.TextBox((74, STATUS_POS, 0, 12), '')
-		self.w.message_l = W.TextBox((4, STATUS_POS+20, 70, 12), 'Status:')
-		self.w.message = W.TextBox((74, STATUS_POS+20, 0, 12), '')
-		self.w.homepage_button = W.Button((4, STATUS_POS+40, 96, 18), 'View homepage', self.do_homepage)
-		self.w.description_l = W.TextBox((4, STATUS_POS+70, 70, 12), 'Description:')
-		self.w.description = W.EditText((74, STATUS_POS+70, 0, DESCRIPTION_HEIGHT-4))
-		
-		self.w.divline = W.HorizontalLine((0, INSTALL_POS-4, 0, 0))
-		self.w.verbose_button = W.CheckBox((84, INSTALL_POS+4, 60, 18), 'Verbose')
-		self.w.recursive_button = W.CheckBox((146, INSTALL_POS+4, 120, 18), 'Install dependencies', self.updatestatus)
-		self.w.recursive_button.set(1)
-		self.w.force_button = W.CheckBox((268, INSTALL_POS+4, 70, 18), 'Overwrite', self.updatestatus)
-		self.w.user_button = W.CheckBox((340, INSTALL_POS+4, 140, 18), 'For Current User Only', self.do_user)
-		self.w.install_button = W.Button((4, INSTALL_POS+4, 56, 18), 'Install:', self.do_install)
-		self.w.open()
-		self.w.description.enable(0)
-		
-	def updatestatus(self):
-		topcell = self.w.packagebrowser.gettopcell()
-		sel = self.w.packagebrowser.getselection()
-		data = self.getbrowserdata(self.w.hidden_button.get())
-		self.w.packagebrowser.setitems(data)
-		self.w.user_button.set(self.getuserinstall())
-		if len(sel) != 1:
-			self.w.installed.set('')
-			self.w.message.set('')
-			self.w.install_button.enable(0)
-			self.w.homepage_button.enable(0)
-			self.w.description.set('')
-			self.w.verbose_button.enable(0)
-			self.w.recursive_button.enable(0)
-			self.w.force_button.enable(0)
-			self.w.user_button.enable(0)
-		else:
-			sel = sel[0]
-			if sel >= len(self.packages):
-				sel = 0
-			self.w.packagebrowser.setselection([sel])
-			installed, message = self.getstatus(sel)
-			self.w.installed.set(installed)
-			self.w.message.set(message)
-			self.w.install_button.enable(installed != "yes" or self.w.force_button.get())
-			self.w.homepage_button.enable(not not self.packages[sel].homepage())
-			description = self.packages[sel].description()
-			description = description.splitlines()
-			description = '\r'.join(description)
-			self.w.description.set(description)
-			self.w.verbose_button.enable(1)
-			self.w.recursive_button.enable(1)
-			self.w.force_button.enable(1)
-			self.w.user_button.enable(1)
-		self.w.packagebrowser.settopcell(topcell)
-		
-	def listhit(self, *args, **kwargs):
-		self.updatestatus()
-		
-	def do_install(self):
-		sel = self.w.packagebrowser.getselection()[0]
-		if self.w.verbose_button.get():
-			output = sys.stdout
-		else:
-			output = None
-		recursive = self.w.recursive_button.get()
-		force = self.w.force_button.get()
-		messages = self.installpackage(sel, output, recursive, force)
-		
-		# Re-read .pth files
-		import site
-		reload(site)
-		
-		self.updatestatus()
-		self.showmessages(messages)
-		
-	def showmessages(self, messages):
-		if messages:
-			# To be on the safe side we always show the hidden packages,
-			# they may be referred to in the error messages.
-			if not self.w.hidden_button.get():
-				self.w.hidden_button.set(1)
-				self.updatestatus()
-			if type(messages) == list:
-				messages = '\n'.join(messages)
-			if self.w.verbose_button.get():
-				sys.stdout.write(messages + '\n')
-			EasyDialogs.Message(messages)
-		
-	def do_homepage(self):
-		sel = self.w.packagebrowser.getselection()[0]
-		if not self.ic:
-			import ic
-			
-			self.ic = ic.IC()
-		self.ic.launchurl(self.packages[sel].homepage())
-		
-	def do_user(self):
-		messages = self.setuserinstall(self.w.user_button.get())
-		self.updatestatus()
-		self.showmessages(messages)
-		
+
+    def __init__(self, url = None):
+        self.ic = None
+        messages = self.setuppimp(url)
+        self.setupwidgets()
+        self.updatestatus()
+        self.showmessages(messages)
+
+    def close(self):
+        self.closepimp()
+
+    def setupwidgets(self):
+        DESCRIPTION_HEIGHT = 140
+        INSTALL_POS = -30
+        STATUS_POS = INSTALL_POS - (70 + DESCRIPTION_HEIGHT)
+        self.w = W.Window((580, 600), "Python Install Manager", minsize = (400, 400), tabbable = 0)
+        self.w.titlebar = W.TextBox((4, 8, 60, 18), 'Packages:')
+        self.w.hidden_button = W.CheckBox((-100, 4, 0, 18), 'Show Hidden', self.updatestatus)
+        data = self.getbrowserdata()
+        self.w.packagebrowser = W.MultiList((4, 24, 0, STATUS_POS-2), data, self.listhit, cols=3)
+
+        self.w.installed_l = W.TextBox((4, STATUS_POS, 70, 12), 'Installed:')
+        self.w.installed = W.TextBox((74, STATUS_POS, 0, 12), '')
+        self.w.message_l = W.TextBox((4, STATUS_POS+20, 70, 12), 'Status:')
+        self.w.message = W.TextBox((74, STATUS_POS+20, 0, 12), '')
+        self.w.homepage_button = W.Button((4, STATUS_POS+40, 96, 18), 'View homepage', self.do_homepage)
+        self.w.description_l = W.TextBox((4, STATUS_POS+70, 70, 12), 'Description:')
+        self.w.description = W.EditText((74, STATUS_POS+70, 0, DESCRIPTION_HEIGHT-4))
+
+        self.w.divline = W.HorizontalLine((0, INSTALL_POS-4, 0, 0))
+        self.w.verbose_button = W.CheckBox((84, INSTALL_POS+4, 60, 18), 'Verbose')
+        self.w.recursive_button = W.CheckBox((146, INSTALL_POS+4, 120, 18), 'Install dependencies', self.updatestatus)
+        self.w.recursive_button.set(1)
+        self.w.force_button = W.CheckBox((268, INSTALL_POS+4, 70, 18), 'Overwrite', self.updatestatus)
+        self.w.user_button = W.CheckBox((340, INSTALL_POS+4, 140, 18), 'For Current User Only', self.do_user)
+        self.w.install_button = W.Button((4, INSTALL_POS+4, 56, 18), 'Install:', self.do_install)
+        self.w.open()
+        self.w.description.enable(0)
+
+    def updatestatus(self):
+        topcell = self.w.packagebrowser.gettopcell()
+        sel = self.w.packagebrowser.getselection()
+        data = self.getbrowserdata(self.w.hidden_button.get())
+        self.w.packagebrowser.setitems(data)
+        self.w.user_button.set(self.getuserinstall())
+        if len(sel) != 1:
+            self.w.installed.set('')
+            self.w.message.set('')
+            self.w.install_button.enable(0)
+            self.w.homepage_button.enable(0)
+            self.w.description.set('')
+            self.w.verbose_button.enable(0)
+            self.w.recursive_button.enable(0)
+            self.w.force_button.enable(0)
+            self.w.user_button.enable(0)
+        else:
+            sel = sel[0]
+            if sel >= len(self.packages):
+                sel = 0
+            self.w.packagebrowser.setselection([sel])
+            installed, message = self.getstatus(sel)
+            self.w.installed.set(installed)
+            self.w.message.set(message)
+            self.w.install_button.enable(installed != "yes" or self.w.force_button.get())
+            self.w.homepage_button.enable(not not self.packages[sel].homepage())
+            description = self.packages[sel].description()
+            description = description.splitlines()
+            description = '\r'.join(description)
+            self.w.description.set(description)
+            self.w.verbose_button.enable(1)
+            self.w.recursive_button.enable(1)
+            self.w.force_button.enable(1)
+            self.w.user_button.enable(1)
+        self.w.packagebrowser.settopcell(topcell)
+
+    def listhit(self, *args, **kwargs):
+        self.updatestatus()
+
+    def do_install(self):
+        sel = self.w.packagebrowser.getselection()[0]
+        if self.w.verbose_button.get():
+            output = sys.stdout
+        else:
+            output = None
+        recursive = self.w.recursive_button.get()
+        force = self.w.force_button.get()
+        messages = self.installpackage(sel, output, recursive, force)
+
+        # Re-read .pth files
+        import site
+        reload(site)
+
+        self.updatestatus()
+        self.showmessages(messages)
+
+    def showmessages(self, messages):
+        if messages:
+            # To be on the safe side we always show the hidden packages,
+            # they may be referred to in the error messages.
+            if not self.w.hidden_button.get():
+                self.w.hidden_button.set(1)
+                self.updatestatus()
+            if type(messages) == list:
+                messages = '\n'.join(messages)
+            if self.w.verbose_button.get():
+                sys.stdout.write(messages + '\n')
+            EasyDialogs.Message(messages)
+
+    def do_homepage(self):
+        sel = self.w.packagebrowser.getselection()[0]
+        if not self.ic:
+            import ic
+
+            self.ic = ic.IC()
+        self.ic.launchurl(self.packages[sel].homepage())
+
+    def do_user(self):
+        messages = self.setuserinstall(self.w.user_button.get())
+        self.updatestatus()
+        self.showmessages(messages)
+
 if __name__ == '__main__':
-	PackageManagerMain()
+    PackageManagerMain()
diff --git a/Mac/Tools/IDE/ProfileBrowser.py b/Mac/Tools/IDE/ProfileBrowser.py
index a19641c..a2dafdd 100644
--- a/Mac/Tools/IDE/ProfileBrowser.py
+++ b/Mac/Tools/IDE/ProfileBrowser.py
@@ -9,84 +9,84 @@
 
 # increase precision
 def f8(x):
-	return string.rjust(fpformat.fix(x, 4), 8)
+    return string.rjust(fpformat.fix(x, 4), 8)
 pstats.f8 = f8
 
 # hacking around a hack
 if sys.version[:3] > '1.4':
-	timer = Evt.TickCount
+    timer = Evt.TickCount
 else:
-	def timer(TickCount = Evt.TickCount):
-		return TickCount() / 60.0
+    def timer(TickCount = Evt.TickCount):
+        return TickCount() / 60.0
 
 class ProfileBrowser:
-	
-	def __init__(self, stats = None):
-		self.sortkeys = ('calls',)
-		self.setupwidgets()
-		self.setstats(stats)
-	
-	def setupwidgets(self): 
-		self.w = W.Window((580, 400), "Profile Statistics", minsize = (200, 100), tabbable = 0)
-		self.w.divline = W.HorizontalLine((0, 20, 0, 0))
-		self.w.titlebar = W.TextBox((4, 4, 40, 12), 'Sort by:')
-		self.buttons = []
-		x = 54
-		width1 = 50
-		width2 = 75
-		for name in ["calls", "time", "cumulative", "stdname", "file", "line", "name"]:
-			if len(name) > 6:
-				width = width2
-			else:
-				width = width1
-			self.w["button_" + name] = W.RadioButton((x, 4, width, 12), name, self.buttons, self.setsort)
-			x += width + 10
-		self.w.button_calls.set(1)
-		self.w.text = W.TextEditor((0, 21, -15, -15), inset = (6, 5), 
-				readonly = 1, wrap = 0, fontsettings = ('Monaco', 0, 9, (0, 0, 0)))
-		self.w._bary = W.Scrollbar((-15, 20, 16, -14), self.w.text.vscroll, max = 32767)
-		self.w._barx = W.Scrollbar((-1, -15, -14, 16), self.w.text.hscroll, max = 32767)
-		self.w.open()
-	
-	def setstats(self, stats):
-		self.stats = stats
-		self.stats.strip_dirs()
-		self.displaystats()
-	
-	def setsort(self):
-		# Grmpf. The callback doesn't give us the button:-(
-		for b in self.buttons:
-			if b.get():
-				if b._title == self.sortkeys[0]:
-					return
-				self.sortkeys = (b._title,) + self.sortkeys[:3]
-				break
-		self.displaystats()
-	
-	def displaystats(self):
-		W.SetCursor('watch')
-		apply(self.stats.sort_stats, self.sortkeys)
-		saveout = sys.stdout
-		try:
-			s = sys.stdout = StringIO.StringIO()
-			self.stats.print_stats()
-		finally:
-			sys.stdout = saveout
-		text = string.join(string.split(s.getvalue(), '\n'), '\r')
-		self.w.text.set(text)
+
+    def __init__(self, stats = None):
+        self.sortkeys = ('calls',)
+        self.setupwidgets()
+        self.setstats(stats)
+
+    def setupwidgets(self):
+        self.w = W.Window((580, 400), "Profile Statistics", minsize = (200, 100), tabbable = 0)
+        self.w.divline = W.HorizontalLine((0, 20, 0, 0))
+        self.w.titlebar = W.TextBox((4, 4, 40, 12), 'Sort by:')
+        self.buttons = []
+        x = 54
+        width1 = 50
+        width2 = 75
+        for name in ["calls", "time", "cumulative", "stdname", "file", "line", "name"]:
+            if len(name) > 6:
+                width = width2
+            else:
+                width = width1
+            self.w["button_" + name] = W.RadioButton((x, 4, width, 12), name, self.buttons, self.setsort)
+            x += width + 10
+        self.w.button_calls.set(1)
+        self.w.text = W.TextEditor((0, 21, -15, -15), inset = (6, 5),
+                        readonly = 1, wrap = 0, fontsettings = ('Monaco', 0, 9, (0, 0, 0)))
+        self.w._bary = W.Scrollbar((-15, 20, 16, -14), self.w.text.vscroll, max = 32767)
+        self.w._barx = W.Scrollbar((-1, -15, -14, 16), self.w.text.hscroll, max = 32767)
+        self.w.open()
+
+    def setstats(self, stats):
+        self.stats = stats
+        self.stats.strip_dirs()
+        self.displaystats()
+
+    def setsort(self):
+        # Grmpf. The callback doesn't give us the button:-(
+        for b in self.buttons:
+            if b.get():
+                if b._title == self.sortkeys[0]:
+                    return
+                self.sortkeys = (b._title,) + self.sortkeys[:3]
+                break
+        self.displaystats()
+
+    def displaystats(self):
+        W.SetCursor('watch')
+        apply(self.stats.sort_stats, self.sortkeys)
+        saveout = sys.stdout
+        try:
+            s = sys.stdout = StringIO.StringIO()
+            self.stats.print_stats()
+        finally:
+            sys.stdout = saveout
+        text = string.join(string.split(s.getvalue(), '\n'), '\r')
+        self.w.text.set(text)
 
 
 def main():
-	import pstats
-	args = sys.argv[1:]
-	for i in args:
-		stats = pstats.Stats(i)
-		browser = ProfileBrowser(stats)
-	else:
-		filename = EasyDialogs.AskFileForOpen(message='Profiler data')
-		if not filename: sys.exit(0)
-		stats = pstats.Stats(filename)
-		browser = ProfileBrowser(stats)
+    import pstats
+    args = sys.argv[1:]
+    for i in args:
+        stats = pstats.Stats(i)
+        browser = ProfileBrowser(stats)
+    else:
+        filename = EasyDialogs.AskFileForOpen(message='Profiler data')
+        if not filename: sys.exit(0)
+        stats = pstats.Stats(filename)
+        browser = ProfileBrowser(stats)
 
 if __name__ == '__main__':
-	main()
+    main()
diff --git a/Mac/Tools/IDE/PyBrowser.py b/Mac/Tools/IDE/PyBrowser.py
index 397347e..0ad3a9a 100644
--- a/Mac/Tools/IDE/PyBrowser.py
+++ b/Mac/Tools/IDE/PyBrowser.py
@@ -18,600 +18,599 @@
 
 has_ctlcharsRE = re.compile(r'[\000-\037\177-\377]')
 def ctlcharsREsearch(str):
-	if has_ctlcharsRE.search(str) is None:
-		return -1
-	return 1
-	
-def double_repr(key, value, truncvalue = 0, 
-			type = type, StringType = types.StringType,
-			has_ctlchars = ctlcharsREsearch, _repr = repr, str = str):
-	if type(key) == StringType and has_ctlchars(key) < 0:
-		key = str(key)
-	else:
-		key = _repr(key)
-	if key == '__builtins__':
-		value = "<" + type(value).__name__ + " '__builtin__'>"
-	elif key == '__return__':
-		# bleh, when returning from a class codeblock we get infinite recursion in repr. 
-		# Use safe repr instead.
-		import repr
-		value = repr.repr(value)
-	else:
-		try:
-			value = _repr(value)
-			'' + value	# test to see if it is a string, in case a __repr__ method is buggy
-		except:
-			value = '\xa5\xa5\xa5 exception in repr()'
-	if truncvalue:
-		return key + '\t' + value[:255]
-	return key + '\t' + value
+    if has_ctlcharsRE.search(str) is None:
+        return -1
+    return 1
+
+def double_repr(key, value, truncvalue = 0,
+                        type = type, StringType = types.StringType,
+                        has_ctlchars = ctlcharsREsearch, _repr = repr, str = str):
+    if type(key) == StringType and has_ctlchars(key) < 0:
+        key = str(key)
+    else:
+        key = _repr(key)
+    if key == '__builtins__':
+        value = "<" + type(value).__name__ + " '__builtin__'>"
+    elif key == '__return__':
+        # bleh, when returning from a class codeblock we get infinite recursion in repr.
+        # Use safe repr instead.
+        import repr
+        value = repr.repr(value)
+    else:
+        try:
+            value = _repr(value)
+            '' + value      # test to see if it is a string, in case a __repr__ method is buggy
+        except:
+            value = '\xa5\xa5\xa5 exception in repr()'
+    if truncvalue:
+        return key + '\t' + value[:255]
+    return key + '\t' + value
 
 
 def truncString(s, maxwid):
-	if maxwid < 1:
-		return 1, ""
-	strlen = len(s)
-	strwid = Qd.TextWidth(s, 0, strlen);
-	if strwid <= maxwid:
-		return 0, s
-	
-	Qd.TextFace(QuickDraw.condense)
-	strwid = Qd.TextWidth(s, 0, strlen)
-	ellipsis = Qd.StringWidth('\xc9')
-	
-	if strwid <= maxwid:
-		Qd.TextFace(0)
-		return 1, s
-	if strwid < 1:
-		Qd.TextFace(0)
-		return 1, ""
-	
-	mid = int(strlen * maxwid / strwid)
-	while 1:
-		if mid <= 0:
-			mid = 0
-			break
-		strwid = Qd.TextWidth(s, 0, mid) + ellipsis
-		strwid2 = Qd.TextWidth(s, 0, mid + 1) + ellipsis
-		if strwid <= maxwid and maxwid <= strwid2:
-			if maxwid == strwid2:
-				mid += 1
-			break
-		if strwid > maxwid:
-			mid -= 1
-			if mid <= 0:
-				mid = 0
-				break
-		elif strwid2 < maxwid:
-			mid += 1
-	Qd.TextFace(0)
-	return 1, s[:mid] + '\xc9'
+    if maxwid < 1:
+        return 1, ""
+    strlen = len(s)
+    strwid = Qd.TextWidth(s, 0, strlen);
+    if strwid <= maxwid:
+        return 0, s
+
+    Qd.TextFace(QuickDraw.condense)
+    strwid = Qd.TextWidth(s, 0, strlen)
+    ellipsis = Qd.StringWidth('\xc9')
+
+    if strwid <= maxwid:
+        Qd.TextFace(0)
+        return 1, s
+    if strwid < 1:
+        Qd.TextFace(0)
+        return 1, ""
+
+    mid = int(strlen * maxwid / strwid)
+    while 1:
+        if mid <= 0:
+            mid = 0
+            break
+        strwid = Qd.TextWidth(s, 0, mid) + ellipsis
+        strwid2 = Qd.TextWidth(s, 0, mid + 1) + ellipsis
+        if strwid <= maxwid and maxwid <= strwid2:
+            if maxwid == strwid2:
+                mid += 1
+            break
+        if strwid > maxwid:
+            mid -= 1
+            if mid <= 0:
+                mid = 0
+                break
+        elif strwid2 < maxwid:
+            mid += 1
+    Qd.TextFace(0)
+    return 1, s[:mid] + '\xc9'
 
 
 def drawTextCell(text, cellRect, ascent, theList):
-	l, t, r, b = cellRect
-	cellwidth = r - l
-	Qd.MoveTo(int(l + 2), int(t + ascent))
-	condense, text = truncString(text, cellwidth - 3)
-	if condense:
-		Qd.TextFace(QuickDraw.condense)
-	Qd.DrawText(text, 0, len(text))
-	Qd.TextFace(0)
+    l, t, r, b = cellRect
+    cellwidth = r - l
+    Qd.MoveTo(int(l + 2), int(t + ascent))
+    condense, text = truncString(text, cellwidth - 3)
+    if condense:
+        Qd.TextFace(QuickDraw.condense)
+    Qd.DrawText(text, 0, len(text))
+    Qd.TextFace(0)
 
 
 PICTWIDTH = 16
 
 
 class BrowserWidget(W.CustomList):
-	
-	def __init__(self, possize, object = None, col = 100, closechildren = 0):
-		W.List.__init__(self, possize, callback = self.listhit)
-		self.object = (None,)
-		self.indent = 16
-		self.lastmaxindent = 0
-		self.closechildren = closechildren
-		self.children = []
-		self.mincol = 64
-		self.setcolumn(col)
-		self.bind('return', self.openselection)
-		self.bind('enter', self.openselection)
-		if object is not None:
-			self.set(object)
-	
-	def set(self, object):
-		if self.object[0] is not object:
-			self.object = object,
-			self[:] = self.unpack(object, 0)
-		elif self._parentwindow is not None and self._parentwindow.wid:
-			self.update()
-	
-	def unpack(self, object, indent):
-		return unpack_object(object, indent)
-	
-	def update(self):
-		# for now...
-		W.SetCursor('watch')
-		self.setdrawingmode(0)
-		sel = self.getselectedobjects()
-		fold = self.getunfoldedobjects()
-		topcell = self.gettopcell()
-		self[:] = self.unpack(self.object[0], 0)
-		self.unfoldobjects(fold)
-		self.setselectedobjects(sel)
-		self.settopcell(topcell)
-		self.setdrawingmode(1)
-	
-	def setcolumn(self, col):
-		self.col = col
-		self.colstr = struct.pack('h', col)
-		if self._list:
-			sel = self.getselection()
-			self.setitems(self.items)
-			self.setselection(sel)
-	
-	def key(self, char, event):
-		if char in (Wkeys.leftarrowkey, Wkeys.rightarrowkey):
-			sel = self.getselection()
-			sel.reverse()
-			self.setdrawingmode(0)
-			for index in sel:
-				self.fold(index, char == Wkeys.rightarrowkey)
-			self.setdrawingmode(1)
-		else:
-			W.List.key(self, char, event)
-	
-	def rollover(self, (x, y), onoff):
-		if onoff:
-			if self.incolumn((x, y)):
-				W.SetCursor('hmover')
-			else:
-				W.SetCursor('arrow')
-	
-	def inarrow(self, (x, y)):
-		cl, ct, cr, cb = self._list.LRect((0, 0))
-		l, t, r, b = self._bounds
-		if (x - cl) < 16:
-			cellheight = cb - ct
-			index = (y - ct) / cellheight
-			if index < len(self.items):
-				return 1, index
-		return None, None
-	
-	def incolumn(self, (x, y)):
-		l, t, r, b = self._list.LRect((0, 0))
-		abscol = l + self.col
-		return abs(abscol - x) < 3
-	
-	def trackcolumn(self, (x, y)):
-		from Carbon import Qd, QuickDraw, Evt
-		self.SetPort()
-		l, t, r, b = self._bounds
-		bounds = l, t, r, b = l + 1, t + 1, r - 16, b - 1
-		abscol = l + self.col
-		mincol = l + self.mincol
-		maxcol = r - 10
-		diff = abscol - x
-		Qd.PenPat('\000\377\000\377\000\377\000\377')
-		Qd.PenMode(QuickDraw.srcXor)
-		rect = abscol - 1, t, abscol, b
-		Qd.PaintRect(rect)
-		lastpoint = (x, y)
-		newcol = -1
-		#W.SetCursor('fist')
-		while Evt.Button():
-			Evt.WaitNextEvent(0, 1, None)  # needed for OSX
-			(x, y) = Evt.GetMouse()
-			if (x, y) <> lastpoint:
-				newcol = x + diff
-				newcol = max(newcol, mincol)
-				newcol = min(newcol, maxcol)
-				Qd.PaintRect(rect)
-				rect = newcol - 1, t, newcol, b
-				Qd.PaintRect(rect)
-				lastpoint = (x, y)
-		Qd.PaintRect(rect)
-		Qd.PenPat(Qd.GetQDGlobalsBlack())
-		Qd.PenNormal()
-		if newcol > 0 and newcol <> abscol:
-			self.setcolumn(newcol - l)
-	
-	def click(self, point, modifiers):
-		if point == (-1, -1):	# gross.
-			W.List.click(self, point ,modifiers)
-			return
-		hit, index = self.inarrow(point)
-		if hit:
-			(key, value, arrow, indent) = self.items[index]
-			self.fold(index, arrow == 1)
-		elif self.incolumn(point):
-			self.trackcolumn(point)
-		else:
-			W.List.click(self, point, modifiers)
-	
-	# for W.List.key
-	def findmatch(self, tag):
-		lower = string.lower
-		items = self.items
-		taglen = len(tag)
-		match = '\377' * 100
-		match_i = -1
-		for i in range(len(items)):
-			item = lower(str(items[i][0]))
-			if tag <= item < match:
-				match = item
-				match_i = i
-		if match_i >= 0:
-			return match_i
-		else:
-			return len(items) - 1
-	
-	def close(self):
-		if self.closechildren:
-			for window in self.children:
-				window.close()
-		self.children = []
-		W.List.close(self)
-	
-	def fold(self, index, onoff):
-		(key, value, arrow, indent) = self.items[index]
-		if arrow == 0 or (onoff and arrow == 2) or (not onoff and arrow == 1):
-			return
-		W.SetCursor('watch')
-		topcell = self.gettopcell()
-		if onoff:
-			self[index] = (key, value, 4, indent)
-			self.setdrawingmode(0)
-			self[index+1:index+1] = self.unpack(value, indent + 1)
-			self[index] = (key, value, 2, indent)
-		else:
-			self[index] = (key, value, 3, indent)
-			self.setdrawingmode(0)
-			count = 0
-			for i in range(index + 1, len(self.items)):
-				(dummy, dummy, dummy, subindent) = self.items[i]
-				if subindent <= indent:
-					break
-				count = count + 1
-			self[index+1:index+1+count] = []
-			self[index] = (key, value, 1, indent)
-		maxindent = self.getmaxindent()
-		if maxindent <> self.lastmaxindent:
-			newabsindent = self.col + (maxindent - self.lastmaxindent) * self.indent
-			if newabsindent >= self.mincol:
-				self.setcolumn(newabsindent)
-			self.lastmaxindent = maxindent
-		self.settopcell(topcell)
-		self.setdrawingmode(1)
-	
-	def unfoldobjects(self, objects):
-		for obj in objects:
-			try:
-				index = self.items.index(obj)
-			except ValueError:
-				pass
-			else:
-				self.fold(index, 1)
-	
-	def getunfoldedobjects(self):
-		curindent = 0
-		objects = []
-		for index in range(len(self.items)):
-			(key, value, arrow, indent) = self.items[index]
-			if indent > curindent:
-				(k, v, a, i) = self.items[index - 1]
-				objects.append((k, v, 1, i))
-				curindent = indent
-			elif indent < curindent:
-				curindent = indent
-		return objects
-	
-	def listhit(self, isdbl):
-		if isdbl:
-			self.openselection()
-	
-	def openselection(self):
-		import os
-		sel = self.getselection()
-		for index in sel:
-			(key, value, arrow, indent) = self[index]
-			if arrow:
-				self.children.append(Browser(value))
-			elif type(value) == types.StringType and '\0' not in value:
-				editor = self._parentwindow.parent.getscript(value)
-				if editor:
-					editor.select()
-					return
-				elif os.path.exists(value) and os.path.isfile(value):
-					if MacOS.GetCreatorAndType(value)[1] in ('TEXT', '\0\0\0\0'):
-						W.getapplication().openscript(value)
-	
-	def itemrepr(self, (key, value, arrow, indent), str = str, double_repr = double_repr, 
-			arrows = arrows, pack = struct.pack):
-		arrow = arrows[arrow]
-		return arrow + pack('h', self.indent * indent) + self.colstr + \
-				double_repr(key, value, 1)
-	
-	def getmaxindent(self, max = max):
-		maxindent = 0
-		for item in self.items:
-			maxindent = max(maxindent, item[3])
-		return maxindent
-	
-	def domenu_copy(self, *args):
-		sel = self.getselectedobjects()
-		selitems = []
-		for key, value, dummy, dummy in sel:
-			selitems.append(double_repr(key, value))
-		text = string.join(selitems, '\r')
-		if text:
-			from Carbon import Scrap
-			if hasattr(Scrap, 'PutScrap'):
-				Scrap.ZeroScrap()
-				Scrap.PutScrap('TEXT', text)
-			else:
-				Scrap.ClearCurrentScrap()
-				sc = Scrap.GetCurrentScrap()
-				sc.PutScrapFlavor('TEXT', 0, text)
 
-	def listDefDraw(self, selected, cellRect, theCell, 
-			dataOffset, dataLen, theList):
-		self.myDrawCell(0, selected, cellRect, theCell, 
-			dataOffset, dataLen, theList)
-	
-	def listDefHighlight(self, selected, cellRect, theCell, 
-			dataOffset, dataLen, theList):
-		self.myDrawCell(1, selected, cellRect, theCell, 
-			dataOffset, dataLen, theList)
-	
-	def myDrawCell(self, onlyHilite, selected, cellRect, theCell, 
-			dataOffset, dataLen, theList):
-		savedPort = Qd.GetPort()
-		Qd.SetPort(theList.GetListPort())
-		savedClip = Qd.NewRgn()
-		Qd.GetClip(savedClip)
-		Qd.ClipRect(cellRect)
-		savedPenState = Qd.GetPenState()
-		Qd.PenNormal()
-		
-		l, t, r, b = cellRect
-		
-		if not onlyHilite:
-			Qd.EraseRect(cellRect)
-			
-			ascent, descent, leading, size, hm = Fm.FontMetrics()
-			linefeed = ascent + descent + leading
-			
-			if dataLen >= 6:
-				data = theList.LGetCell(dataLen, theCell)
-				iconId, indent, tab = struct.unpack("hhh", data[:6])
-				try:
-					key, value = data[6:].split("\t", 1)
-				except ValueError:
-					# bogus data, at least don't crash.
-					indent = 0
-					tab = 0
-					iconId = 0
-					key = ""
-					value = data[6:]
-				
-				if iconId:
-					try:
-						theIcon = Icn.GetCIcon(iconId)
-					except Icn.Error:
-						pass
-					else:
-						rect = (0, 0, 16, 16)
-						rect = Qd.OffsetRect(rect, l, t)
-						rect = Qd.OffsetRect(rect, 0, (theList.cellSize[1] - (rect[3] - rect[1])) / 2)
-						Icn.PlotCIcon(rect, theIcon)
-				
-				if len(key) >= 0:
-					cl, ct, cr, cb = cellRect
-					vl, vt, vr, vb = self._viewbounds
-					cl = vl + PICTWIDTH + indent
-					cr = vl + tab
-					if cr > vr:
-						cr = vr
-					if cl < cr:
-						drawTextCell(key, (cl, ct, cr, cb), ascent, theList)
-					cl = vl + tab
-					cr = vr
-					if cl < cr:
-						drawTextCell(value, (cl, ct, cr, cb), ascent, theList)
-			#elif dataLen != 0:
-			#	drawTextCell("???", 3, cellRect, ascent, theList)
-			else:
-				return  # we have bogus data
-			
-			# draw nice dotted line
-			l, t, r, b = cellRect
-			l = self._viewbounds[0] + tab
-			r = l + 1;
-			if not (theList.cellSize[1] & 0x01) or (t & 0x01):
-				myPat = "\xff\x00\xff\x00\xff\x00\xff\x00"
-			else:
-				myPat = "\x00\xff\x00\xff\x00\xff\x00\xff"
-			Qd.PenPat(myPat)
-			Qd.PenMode(QuickDraw.srcCopy)
-			Qd.PaintRect((l, t, r, b))
-			Qd.PenNormal()
-		
-		if selected or onlyHilite:
-			l, t, r, b = cellRect
-			l = self._viewbounds[0] + PICTWIDTH
-			r = self._viewbounds[2]
-			Qd.PenMode(hilitetransfermode)
-			Qd.PaintRect((l, t, r, b))
-		
-		# restore graphics environment
-		Qd.SetPort(savedPort)
-		Qd.SetClip(savedClip)
-		Qd.DisposeRgn(savedClip)
-		Qd.SetPenState(savedPenState)
+    def __init__(self, possize, object = None, col = 100, closechildren = 0):
+        W.List.__init__(self, possize, callback = self.listhit)
+        self.object = (None,)
+        self.indent = 16
+        self.lastmaxindent = 0
+        self.closechildren = closechildren
+        self.children = []
+        self.mincol = 64
+        self.setcolumn(col)
+        self.bind('return', self.openselection)
+        self.bind('enter', self.openselection)
+        if object is not None:
+            self.set(object)
+
+    def set(self, object):
+        if self.object[0] is not object:
+            self.object = object,
+            self[:] = self.unpack(object, 0)
+        elif self._parentwindow is not None and self._parentwindow.wid:
+            self.update()
+
+    def unpack(self, object, indent):
+        return unpack_object(object, indent)
+
+    def update(self):
+        # for now...
+        W.SetCursor('watch')
+        self.setdrawingmode(0)
+        sel = self.getselectedobjects()
+        fold = self.getunfoldedobjects()
+        topcell = self.gettopcell()
+        self[:] = self.unpack(self.object[0], 0)
+        self.unfoldobjects(fold)
+        self.setselectedobjects(sel)
+        self.settopcell(topcell)
+        self.setdrawingmode(1)
+
+    def setcolumn(self, col):
+        self.col = col
+        self.colstr = struct.pack('h', col)
+        if self._list:
+            sel = self.getselection()
+            self.setitems(self.items)
+            self.setselection(sel)
+
+    def key(self, char, event):
+        if char in (Wkeys.leftarrowkey, Wkeys.rightarrowkey):
+            sel = self.getselection()
+            sel.reverse()
+            self.setdrawingmode(0)
+            for index in sel:
+                self.fold(index, char == Wkeys.rightarrowkey)
+            self.setdrawingmode(1)
+        else:
+            W.List.key(self, char, event)
+
+    def rollover(self, (x, y), onoff):
+        if onoff:
+            if self.incolumn((x, y)):
+                W.SetCursor('hmover')
+            else:
+                W.SetCursor('arrow')
+
+    def inarrow(self, (x, y)):
+        cl, ct, cr, cb = self._list.LRect((0, 0))
+        l, t, r, b = self._bounds
+        if (x - cl) < 16:
+            cellheight = cb - ct
+            index = (y - ct) / cellheight
+            if index < len(self.items):
+                return 1, index
+        return None, None
+
+    def incolumn(self, (x, y)):
+        l, t, r, b = self._list.LRect((0, 0))
+        abscol = l + self.col
+        return abs(abscol - x) < 3
+
+    def trackcolumn(self, (x, y)):
+        from Carbon import Qd, QuickDraw, Evt
+        self.SetPort()
+        l, t, r, b = self._bounds
+        bounds = l, t, r, b = l + 1, t + 1, r - 16, b - 1
+        abscol = l + self.col
+        mincol = l + self.mincol
+        maxcol = r - 10
+        diff = abscol - x
+        Qd.PenPat('\000\377\000\377\000\377\000\377')
+        Qd.PenMode(QuickDraw.srcXor)
+        rect = abscol - 1, t, abscol, b
+        Qd.PaintRect(rect)
+        lastpoint = (x, y)
+        newcol = -1
+        #W.SetCursor('fist')
+        while Evt.Button():
+            Evt.WaitNextEvent(0, 1, None)  # needed for OSX
+            (x, y) = Evt.GetMouse()
+            if (x, y) <> lastpoint:
+                newcol = x + diff
+                newcol = max(newcol, mincol)
+                newcol = min(newcol, maxcol)
+                Qd.PaintRect(rect)
+                rect = newcol - 1, t, newcol, b
+                Qd.PaintRect(rect)
+                lastpoint = (x, y)
+        Qd.PaintRect(rect)
+        Qd.PenPat(Qd.GetQDGlobalsBlack())
+        Qd.PenNormal()
+        if newcol > 0 and newcol <> abscol:
+            self.setcolumn(newcol - l)
+
+    def click(self, point, modifiers):
+        if point == (-1, -1):   # gross.
+            W.List.click(self, point ,modifiers)
+            return
+        hit, index = self.inarrow(point)
+        if hit:
+            (key, value, arrow, indent) = self.items[index]
+            self.fold(index, arrow == 1)
+        elif self.incolumn(point):
+            self.trackcolumn(point)
+        else:
+            W.List.click(self, point, modifiers)
+
+    # for W.List.key
+    def findmatch(self, tag):
+        lower = string.lower
+        items = self.items
+        taglen = len(tag)
+        match = '\377' * 100
+        match_i = -1
+        for i in range(len(items)):
+            item = lower(str(items[i][0]))
+            if tag <= item < match:
+                match = item
+                match_i = i
+        if match_i >= 0:
+            return match_i
+        else:
+            return len(items) - 1
+
+    def close(self):
+        if self.closechildren:
+            for window in self.children:
+                window.close()
+        self.children = []
+        W.List.close(self)
+
+    def fold(self, index, onoff):
+        (key, value, arrow, indent) = self.items[index]
+        if arrow == 0 or (onoff and arrow == 2) or (not onoff and arrow == 1):
+            return
+        W.SetCursor('watch')
+        topcell = self.gettopcell()
+        if onoff:
+            self[index] = (key, value, 4, indent)
+            self.setdrawingmode(0)
+            self[index+1:index+1] = self.unpack(value, indent + 1)
+            self[index] = (key, value, 2, indent)
+        else:
+            self[index] = (key, value, 3, indent)
+            self.setdrawingmode(0)
+            count = 0
+            for i in range(index + 1, len(self.items)):
+                (dummy, dummy, dummy, subindent) = self.items[i]
+                if subindent <= indent:
+                    break
+                count = count + 1
+            self[index+1:index+1+count] = []
+            self[index] = (key, value, 1, indent)
+        maxindent = self.getmaxindent()
+        if maxindent <> self.lastmaxindent:
+            newabsindent = self.col + (maxindent - self.lastmaxindent) * self.indent
+            if newabsindent >= self.mincol:
+                self.setcolumn(newabsindent)
+            self.lastmaxindent = maxindent
+        self.settopcell(topcell)
+        self.setdrawingmode(1)
+
+    def unfoldobjects(self, objects):
+        for obj in objects:
+            try:
+                index = self.items.index(obj)
+            except ValueError:
+                pass
+            else:
+                self.fold(index, 1)
+
+    def getunfoldedobjects(self):
+        curindent = 0
+        objects = []
+        for index in range(len(self.items)):
+            (key, value, arrow, indent) = self.items[index]
+            if indent > curindent:
+                (k, v, a, i) = self.items[index - 1]
+                objects.append((k, v, 1, i))
+                curindent = indent
+            elif indent < curindent:
+                curindent = indent
+        return objects
+
+    def listhit(self, isdbl):
+        if isdbl:
+            self.openselection()
+
+    def openselection(self):
+        import os
+        sel = self.getselection()
+        for index in sel:
+            (key, value, arrow, indent) = self[index]
+            if arrow:
+                self.children.append(Browser(value))
+            elif type(value) == types.StringType and '\0' not in value:
+                editor = self._parentwindow.parent.getscript(value)
+                if editor:
+                    editor.select()
+                    return
+                elif os.path.exists(value) and os.path.isfile(value):
+                    if MacOS.GetCreatorAndType(value)[1] in ('TEXT', '\0\0\0\0'):
+                        W.getapplication().openscript(value)
+
+    def itemrepr(self, (key, value, arrow, indent), str = str, double_repr = double_repr,
+                    arrows = arrows, pack = struct.pack):
+        arrow = arrows[arrow]
+        return arrow + pack('h', self.indent * indent) + self.colstr + \
+                        double_repr(key, value, 1)
+
+    def getmaxindent(self, max = max):
+        maxindent = 0
+        for item in self.items:
+            maxindent = max(maxindent, item[3])
+        return maxindent
+
+    def domenu_copy(self, *args):
+        sel = self.getselectedobjects()
+        selitems = []
+        for key, value, dummy, dummy in sel:
+            selitems.append(double_repr(key, value))
+        text = string.join(selitems, '\r')
+        if text:
+            from Carbon import Scrap
+            if hasattr(Scrap, 'PutScrap'):
+                Scrap.ZeroScrap()
+                Scrap.PutScrap('TEXT', text)
+            else:
+                Scrap.ClearCurrentScrap()
+                sc = Scrap.GetCurrentScrap()
+                sc.PutScrapFlavor('TEXT', 0, text)
+
+    def listDefDraw(self, selected, cellRect, theCell,
+                    dataOffset, dataLen, theList):
+        self.myDrawCell(0, selected, cellRect, theCell,
+                dataOffset, dataLen, theList)
+
+    def listDefHighlight(self, selected, cellRect, theCell,
+                    dataOffset, dataLen, theList):
+        self.myDrawCell(1, selected, cellRect, theCell,
+                dataOffset, dataLen, theList)
+
+    def myDrawCell(self, onlyHilite, selected, cellRect, theCell,
+                    dataOffset, dataLen, theList):
+        savedPort = Qd.GetPort()
+        Qd.SetPort(theList.GetListPort())
+        savedClip = Qd.NewRgn()
+        Qd.GetClip(savedClip)
+        Qd.ClipRect(cellRect)
+        savedPenState = Qd.GetPenState()
+        Qd.PenNormal()
+
+        l, t, r, b = cellRect
+
+        if not onlyHilite:
+            Qd.EraseRect(cellRect)
+
+            ascent, descent, leading, size, hm = Fm.FontMetrics()
+            linefeed = ascent + descent + leading
+
+            if dataLen >= 6:
+                data = theList.LGetCell(dataLen, theCell)
+                iconId, indent, tab = struct.unpack("hhh", data[:6])
+                try:
+                    key, value = data[6:].split("\t", 1)
+                except ValueError:
+                    # bogus data, at least don't crash.
+                    indent = 0
+                    tab = 0
+                    iconId = 0
+                    key = ""
+                    value = data[6:]
+
+                if iconId:
+                    try:
+                        theIcon = Icn.GetCIcon(iconId)
+                    except Icn.Error:
+                        pass
+                    else:
+                        rect = (0, 0, 16, 16)
+                        rect = Qd.OffsetRect(rect, l, t)
+                        rect = Qd.OffsetRect(rect, 0, (theList.cellSize[1] - (rect[3] - rect[1])) / 2)
+                        Icn.PlotCIcon(rect, theIcon)
+
+                if len(key) >= 0:
+                    cl, ct, cr, cb = cellRect
+                    vl, vt, vr, vb = self._viewbounds
+                    cl = vl + PICTWIDTH + indent
+                    cr = vl + tab
+                    if cr > vr:
+                        cr = vr
+                    if cl < cr:
+                        drawTextCell(key, (cl, ct, cr, cb), ascent, theList)
+                    cl = vl + tab
+                    cr = vr
+                    if cl < cr:
+                        drawTextCell(value, (cl, ct, cr, cb), ascent, theList)
+            #elif dataLen != 0:
+            #       drawTextCell("???", 3, cellRect, ascent, theList)
+            else:
+                return  # we have bogus data
+
+            # draw nice dotted line
+            l, t, r, b = cellRect
+            l = self._viewbounds[0] + tab
+            r = l + 1;
+            if not (theList.cellSize[1] & 0x01) or (t & 0x01):
+                myPat = "\xff\x00\xff\x00\xff\x00\xff\x00"
+            else:
+                myPat = "\x00\xff\x00\xff\x00\xff\x00\xff"
+            Qd.PenPat(myPat)
+            Qd.PenMode(QuickDraw.srcCopy)
+            Qd.PaintRect((l, t, r, b))
+            Qd.PenNormal()
+
+        if selected or onlyHilite:
+            l, t, r, b = cellRect
+            l = self._viewbounds[0] + PICTWIDTH
+            r = self._viewbounds[2]
+            Qd.PenMode(hilitetransfermode)
+            Qd.PaintRect((l, t, r, b))
+
+        # restore graphics environment
+        Qd.SetPort(savedPort)
+        Qd.SetClip(savedClip)
+        Qd.DisposeRgn(savedClip)
+        Qd.SetPenState(savedPenState)
 
 
 
 class Browser:
-	
-	def __init__(self, object = None, title = None, closechildren = 0):
-		if hasattr(object, '__name__'):
-			name = object.__name__
-		else:
-			name = ''
-		if title is None:
-			title = 'Object browser'
-			if name:
-				title = title + ': ' + name
-		self.w = w = W.Window((300, 400), title, minsize = (100, 100))
-		w.info = W.TextBox((18, 8, -70, 15))
-		w.updatebutton = W.BevelButton((-64, 4, 50, 16), 'Update', self.update)
-		w.browser = BrowserWidget((-1, 24, 1, -14), None)
-		w.bind('cmdu', w.updatebutton.push)
-		w.open()
-		self.set(object, name)
-	
-	def close(self):
-		if self.w.wid:
-			self.w.close()
-	
-	def set(self, object, name = ''):
-		W.SetCursor('watch')
-		tp = type(object).__name__
-		try:
-			length = len(object)
-		except:
-			length = -1
-		if not name and hasattr(object, '__name__'):
-			name = object.__name__
-		if name:
-			info = name + ': ' + tp
-		else:
-			info = tp
-		if length >= 0:
-			if length == 1:
-				info = info + ' (%d element)' % length
-			else:
-				info = info + ' (%d elements)' % length
-		self.w.info.set(info)
-		self.w.browser.set(object)
-	
-	def update(self):
-		self.w.browser.update()
+
+    def __init__(self, object = None, title = None, closechildren = 0):
+        if hasattr(object, '__name__'):
+            name = object.__name__
+        else:
+            name = ''
+        if title is None:
+            title = 'Object browser'
+            if name:
+                title = title + ': ' + name
+        self.w = w = W.Window((300, 400), title, minsize = (100, 100))
+        w.info = W.TextBox((18, 8, -70, 15))
+        w.updatebutton = W.BevelButton((-64, 4, 50, 16), 'Update', self.update)
+        w.browser = BrowserWidget((-1, 24, 1, -14), None)
+        w.bind('cmdu', w.updatebutton.push)
+        w.open()
+        self.set(object, name)
+
+    def close(self):
+        if self.w.wid:
+            self.w.close()
+
+    def set(self, object, name = ''):
+        W.SetCursor('watch')
+        tp = type(object).__name__
+        try:
+            length = len(object)
+        except:
+            length = -1
+        if not name and hasattr(object, '__name__'):
+            name = object.__name__
+        if name:
+            info = name + ': ' + tp
+        else:
+            info = tp
+        if length >= 0:
+            if length == 1:
+                info = info + ' (%d element)' % length
+            else:
+                info = info + ' (%d elements)' % length
+        self.w.info.set(info)
+        self.w.browser.set(object)
+
+    def update(self):
+        self.w.browser.update()
 
 
 SIMPLE_TYPES = (
-	type(None),
-	int,
-	long,
-	float,
-	complex,
-	str,
-	unicode,
+        type(None),
+        int,
+        long,
+        float,
+        complex,
+        str,
+        unicode,
 )
 
 def get_ivars(obj):
-	"""Return a list the names of all (potential) instance variables."""
-	# __mro__ recipe from Guido
-	slots = {}
-	# old-style C objects
-	if hasattr(obj, "__members__"):
-		for name in obj.__members__:
-			slots[name] = None
-	if hasattr(obj, "__methods__"):
-		for name in obj.__methods__:
-			slots[name] = None
-	# generic type
-	if hasattr(obj, "__dict__"):
-		slots.update(obj.__dict__)
-	cls = type(obj)
-	if hasattr(cls, "__mro__"):
-		# new-style class, use descriptors
-		for base in cls.__mro__:
-			for name, value in base.__dict__.items():
-				# XXX using callable() is a heuristic which isn't 100%
-				# foolproof.
-				if hasattr(value, "__get__") and not callable(value):
-					slots[name] = None
-	if "__dict__" in slots:
-		del slots["__dict__"]
-	slots = slots.keys()
-	slots.sort()
-	return slots
+    """Return a list the names of all (potential) instance variables."""
+    # __mro__ recipe from Guido
+    slots = {}
+    # old-style C objects
+    if hasattr(obj, "__members__"):
+        for name in obj.__members__:
+            slots[name] = None
+    if hasattr(obj, "__methods__"):
+        for name in obj.__methods__:
+            slots[name] = None
+    # generic type
+    if hasattr(obj, "__dict__"):
+        slots.update(obj.__dict__)
+    cls = type(obj)
+    if hasattr(cls, "__mro__"):
+        # new-style class, use descriptors
+        for base in cls.__mro__:
+            for name, value in base.__dict__.items():
+                # XXX using callable() is a heuristic which isn't 100%
+                # foolproof.
+                if hasattr(value, "__get__") and not callable(value):
+                    slots[name] = None
+    if "__dict__" in slots:
+        del slots["__dict__"]
+    slots = slots.keys()
+    slots.sort()
+    return slots
 
 def unpack_object(object, indent = 0):
-	tp = type(object)
-	if isinstance(object, SIMPLE_TYPES) and object is not None:
-		raise TypeError, "can't browse simple type: %s" % tp.__name__
-	elif isinstance(object, dict):
-		return unpack_dict(object, indent)
-	elif isinstance(object, (tuple, list)):
-		return unpack_sequence(object, indent)
-	elif isinstance(object, types.ModuleType):
-		return unpack_dict(object.__dict__, indent)
-	else:
-		return unpack_other(object, indent)
+    tp = type(object)
+    if isinstance(object, SIMPLE_TYPES) and object is not None:
+        raise TypeError, "can't browse simple type: %s" % tp.__name__
+    elif isinstance(object, dict):
+        return unpack_dict(object, indent)
+    elif isinstance(object, (tuple, list)):
+        return unpack_sequence(object, indent)
+    elif isinstance(object, types.ModuleType):
+        return unpack_dict(object.__dict__, indent)
+    else:
+        return unpack_other(object, indent)
 
 def unpack_sequence(seq, indent = 0):
-	return [(i, v, not isinstance(v, SIMPLE_TYPES), indent)
-	         for i, v in enumerate(seq)]
+    return [(i, v, not isinstance(v, SIMPLE_TYPES), indent)
+             for i, v in enumerate(seq)]
 
 def unpack_dict(dict, indent = 0):
-	items = dict.items()
-	return pack_items(items, indent)
+    items = dict.items()
+    return pack_items(items, indent)
 
 def unpack_instance(inst, indent = 0):
-	if hasattr(inst, '__pybrowse_unpack__'):
-		return unpack_object(inst.__pybrowse_unpack__(), indent)
-	else:
-		items = [('__class__', inst.__class__)] + inst.__dict__.items()
-		return pack_items(items, indent)
+    if hasattr(inst, '__pybrowse_unpack__'):
+        return unpack_object(inst.__pybrowse_unpack__(), indent)
+    else:
+        items = [('__class__', inst.__class__)] + inst.__dict__.items()
+        return pack_items(items, indent)
 
 def unpack_class(clss, indent = 0):
-	items = [('__bases__', clss.__bases__), ('__name__', clss.__name__)] + clss.__dict__.items()
-	return pack_items(items, indent)
+    items = [('__bases__', clss.__bases__), ('__name__', clss.__name__)] + clss.__dict__.items()
+    return pack_items(items, indent)
 
 def unpack_other(object, indent = 0):
-	attrs = get_ivars(object)
-	items = []
-	for attr in attrs:
-		try:
-			value = getattr(object, attr)
-		except:
-			pass
-		else:
-			items.append((attr, value))
-	return pack_items(items, indent)
+    attrs = get_ivars(object)
+    items = []
+    for attr in attrs:
+        try:
+            value = getattr(object, attr)
+        except:
+            pass
+        else:
+            items.append((attr, value))
+    return pack_items(items, indent)
 
 def pack_items(items, indent = 0):
-	items = [(k, v, not isinstance(v, SIMPLE_TYPES), indent)
-	         for k, v in items]
-	return tuple_caselesssort(items)
+    items = [(k, v, not isinstance(v, SIMPLE_TYPES), indent)
+             for k, v in items]
+    return tuple_caselesssort(items)
 
 def caselesssort(alist):
-	"""Return a sorted copy of a list. If there are only strings in the list, 
-	it will not consider case"""
-	
-	try:
-		# turn ['FOO',  'aaBc', 'ABcD'] into [('foo', 'FOO'), ('aabc', 'aaBc'), ('abcd', 'ABcD')], if possible
-		tupledlist = map(lambda item, lower = string.lower: (lower(item), item), alist)
-	except TypeError:
-		# at least one element in alist is not a string, proceed the normal way...
-		alist = alist[:]
-		alist.sort()
-		return alist
-	else:
-		tupledlist.sort()
-		# turn [('aabc', 'aaBc'), ('abcd', 'ABcD'), ('foo', 'FOO')] into ['aaBc', 'ABcD', 'FOO']
-		return map(lambda x: x[1], tupledlist)
+    """Return a sorted copy of a list. If there are only strings in the list,
+    it will not consider case"""
+
+    try:
+        # turn ['FOO',  'aaBc', 'ABcD'] into [('foo', 'FOO'), ('aabc', 'aaBc'), ('abcd', 'ABcD')], if possible
+        tupledlist = map(lambda item, lower = string.lower: (lower(item), item), alist)
+    except TypeError:
+        # at least one element in alist is not a string, proceed the normal way...
+        alist = alist[:]
+        alist.sort()
+        return alist
+    else:
+        tupledlist.sort()
+        # turn [('aabc', 'aaBc'), ('abcd', 'ABcD'), ('foo', 'FOO')] into ['aaBc', 'ABcD', 'FOO']
+        return map(lambda x: x[1], tupledlist)
 
 def tuple_caselesssort(items):
-	try:
-		tupledlist = map(lambda tuple, lower = string.lower: (lower(tuple[0]), tuple), items)
-	except (AttributeError, TypeError):
-		items = items[:]
-		items.sort()
-		return items
-	else:
-		tupledlist.sort()
-		return map(lambda (low, tuple): tuple, tupledlist)
-
+    try:
+        tupledlist = map(lambda tuple, lower = string.lower: (lower(tuple[0]), tuple), items)
+    except (AttributeError, TypeError):
+        items = items[:]
+        items.sort()
+        return items
+    else:
+        tupledlist.sort()
+        return map(lambda (low, tuple): tuple, tupledlist)
diff --git a/Mac/Tools/IDE/PyConsole.py b/Mac/Tools/IDE/PyConsole.py
index 6f398d1..b8d6489 100644
--- a/Mac/Tools/IDE/PyConsole.py
+++ b/Mac/Tools/IDE/PyConsole.py
@@ -14,424 +14,424 @@
 import PyInteractive
 
 if not hasattr(sys, 'ps1'):
-	sys.ps1 = '>>> '
+    sys.ps1 = '>>> '
 if not hasattr(sys, 'ps2'):
-	sys.ps2 = '... '
+    sys.ps2 = '... '
 
-def inspect(foo):			# JJS 1/25/99
-	"Launch the browser on the given object.  This is a general built-in function."
-	import PyBrowser
-	PyBrowser.Browser(foo)
+def inspect(foo):                       # JJS 1/25/99
+    "Launch the browser on the given object.  This is a general built-in function."
+    import PyBrowser
+    PyBrowser.Browser(foo)
 
 class ConsoleTextWidget(W.EditText):
-	
-	def __init__(self, *args, **kwargs):
-		apply(W.EditText.__init__, (self,) + args, kwargs)
-		self._inputstart = 0
-		self._buf = ''
-		self.pyinteractive = PyInteractive.PyInteractive()
-	
-		import __main__
-		self._namespace = __main__.__dict__
-		self._namespace['inspect'] = inspect			# JJS 1/25/99
-	
-	def insert(self, text):
-		self.checkselection()
-		self.ted.WEInsert(text, None, None)
-		self.changed = 1
-		self.selchanged = 1
-	
-	def set_namespace(self, dict):
-		if type(dict) <> DictionaryType:
-			raise TypeError, "The namespace needs to be a dictionary"
-		if 'inspect' not in dict.keys(): dict['inspect'] = inspect			# JJS 1/25/99
-		self._namespace = dict
-	
-	def open(self):
-		import __main__
-		W.EditText.open(self)
-		self.write('Python %s\n' % sys.version)
-		self.write('Type "copyright", "credits" or "license" for more information.\n')
-		self.write('MacPython IDE %s\n' % __main__.__version__)
-		self.write(sys.ps1)
-		self.flush()
-	
-	def key(self, char, event):
-		(what, message, when, where, modifiers) = event
-		if self._enabled and not modifiers & Events.cmdKey or char in Wkeys.arrowkeys:
-			if char not in Wkeys.navigationkeys:
-				self.checkselection()
-			if char == Wkeys.enterkey:
-				char = Wkeys.returnkey
-			selstart, selend = self.getselection()
-			if char == Wkeys.backspacekey:
-				if selstart <= (self._inputstart - (selstart <> selend)):
-					return
-			self.ted.WEKey(ord(char), modifiers)
-			if char not in Wkeys.navigationkeys:
-				self.changed = 1
-			if char not in Wkeys.scrollkeys:
-				self.selchanged = 1
-			self.updatescrollbars()
-			if char == Wkeys.returnkey:
-				text = self.get()[self._inputstart:selstart]
-				text = string.join(string.split(text, "\r"), "\n")
-				if hasattr(MacOS, 'EnableAppswitch'):
-					saveyield = MacOS.EnableAppswitch(0)
-				self._scriptDone = False
-				if sys.platform == "darwin":
-					# see identical construct in PyEdit.py
-					from threading import Thread
-					t = Thread(target=self._userCancelledMonitor,
-							name="UserCancelledMonitor")
-					t.start()
-				try:
-					self.pyinteractive.executeline(text, self, self._namespace)
-				finally:
-					self._scriptDone = True
-				if hasattr(MacOS, 'EnableAppswitch'):
-					MacOS.EnableAppswitch(saveyield)
-				selstart, selend = self.getselection()
-				self._inputstart = selstart
-	
-	def _userCancelledMonitor(self):
-		# XXX duplicate code from PyEdit.py
-		import time, os
-		from signal import SIGINT
-		from Carbon import Evt
-		while not self._scriptDone:
-			if Evt.CheckEventQueueForUserCancel():
-				# Send a SIGINT signal to ourselves.
-				# This gets delivered to the main thread,
-				# cancelling the running script.
-				os.kill(os.getpid(), SIGINT)
-				break
-			time.sleep(0.25)
-	
-	def domenu_save_as(self, *args):
-		filename = EasyDialogs.AskFileForSave(message='Save console text as:', 
-			savedFileName='console.txt')
-		if not filename:
-			return
-		f = open(filename, 'wb')
-		f.write(self.get())
-		f.close()
-		MacOS.SetCreatorAndType(filename, W._signature, 'TEXT')
-	
-	def write(self, text):
-		self._buf = self._buf + text
-		if '\n' in self._buf:
-			self.flush()
-	
-	def flush(self):
-		stuff = string.split(self._buf, '\n')
-		stuff = string.join(stuff, '\r')
-		self.setselection_at_end()
-		try:
-			self.ted.WEInsert(stuff, None, None)
-		finally:
-			self._buf = ""
-		selstart, selend = self.getselection()
-		self._inputstart = selstart
-		self.ted.WEClearUndo()
-		self.updatescrollbars()
-		if self._parentwindow.wid.GetWindowPort().QDIsPortBuffered():
-			self._parentwindow.wid.GetWindowPort().QDFlushPortBuffer(None)
-	
-	def selection_ok(self):
-		selstart, selend = self.getselection()
-		return not (selstart < self._inputstart or selend < self._inputstart)
-	
-	def checkselection(self):
-		if not self.selection_ok():
-			self.setselection_at_end()
-	
-	def setselection_at_end(self):
-		end = self.ted.WEGetTextLength()
-		self.setselection(end, end)
-		self.updatescrollbars()
-		
-	def domenu_cut(self, *args):
-		if not self.selection_ok():
-			return
-		W.EditText.domenu_cut(self)
-	
-	def domenu_paste(self, *args):
-		if not self.selection_ok():
-			self.setselection_at_end()
-		W.EditText.domenu_paste(self)
-	
-	def domenu_clear(self, *args):
-		if not self.selection_ok():
-			return
-		W.EditText.domenu_clear(self)
+
+    def __init__(self, *args, **kwargs):
+        apply(W.EditText.__init__, (self,) + args, kwargs)
+        self._inputstart = 0
+        self._buf = ''
+        self.pyinteractive = PyInteractive.PyInteractive()
+
+        import __main__
+        self._namespace = __main__.__dict__
+        self._namespace['inspect'] = inspect                    # JJS 1/25/99
+
+    def insert(self, text):
+        self.checkselection()
+        self.ted.WEInsert(text, None, None)
+        self.changed = 1
+        self.selchanged = 1
+
+    def set_namespace(self, dict):
+        if type(dict) <> DictionaryType:
+            raise TypeError, "The namespace needs to be a dictionary"
+        if 'inspect' not in dict.keys(): dict['inspect'] = inspect                      # JJS 1/25/99
+        self._namespace = dict
+
+    def open(self):
+        import __main__
+        W.EditText.open(self)
+        self.write('Python %s\n' % sys.version)
+        self.write('Type "copyright", "credits" or "license" for more information.\n')
+        self.write('MacPython IDE %s\n' % __main__.__version__)
+        self.write(sys.ps1)
+        self.flush()
+
+    def key(self, char, event):
+        (what, message, when, where, modifiers) = event
+        if self._enabled and not modifiers & Events.cmdKey or char in Wkeys.arrowkeys:
+            if char not in Wkeys.navigationkeys:
+                self.checkselection()
+            if char == Wkeys.enterkey:
+                char = Wkeys.returnkey
+            selstart, selend = self.getselection()
+            if char == Wkeys.backspacekey:
+                if selstart <= (self._inputstart - (selstart <> selend)):
+                    return
+            self.ted.WEKey(ord(char), modifiers)
+            if char not in Wkeys.navigationkeys:
+                self.changed = 1
+            if char not in Wkeys.scrollkeys:
+                self.selchanged = 1
+            self.updatescrollbars()
+            if char == Wkeys.returnkey:
+                text = self.get()[self._inputstart:selstart]
+                text = string.join(string.split(text, "\r"), "\n")
+                if hasattr(MacOS, 'EnableAppswitch'):
+                    saveyield = MacOS.EnableAppswitch(0)
+                self._scriptDone = False
+                if sys.platform == "darwin":
+                    # see identical construct in PyEdit.py
+                    from threading import Thread
+                    t = Thread(target=self._userCancelledMonitor,
+                                    name="UserCancelledMonitor")
+                    t.start()
+                try:
+                    self.pyinteractive.executeline(text, self, self._namespace)
+                finally:
+                    self._scriptDone = True
+                if hasattr(MacOS, 'EnableAppswitch'):
+                    MacOS.EnableAppswitch(saveyield)
+                selstart, selend = self.getselection()
+                self._inputstart = selstart
+
+    def _userCancelledMonitor(self):
+        # XXX duplicate code from PyEdit.py
+        import time, os
+        from signal import SIGINT
+        from Carbon import Evt
+        while not self._scriptDone:
+            if Evt.CheckEventQueueForUserCancel():
+                # Send a SIGINT signal to ourselves.
+                # This gets delivered to the main thread,
+                # cancelling the running script.
+                os.kill(os.getpid(), SIGINT)
+                break
+            time.sleep(0.25)
+
+    def domenu_save_as(self, *args):
+        filename = EasyDialogs.AskFileForSave(message='Save console text as:',
+                savedFileName='console.txt')
+        if not filename:
+            return
+        f = open(filename, 'wb')
+        f.write(self.get())
+        f.close()
+        MacOS.SetCreatorAndType(filename, W._signature, 'TEXT')
+
+    def write(self, text):
+        self._buf = self._buf + text
+        if '\n' in self._buf:
+            self.flush()
+
+    def flush(self):
+        stuff = string.split(self._buf, '\n')
+        stuff = string.join(stuff, '\r')
+        self.setselection_at_end()
+        try:
+            self.ted.WEInsert(stuff, None, None)
+        finally:
+            self._buf = ""
+        selstart, selend = self.getselection()
+        self._inputstart = selstart
+        self.ted.WEClearUndo()
+        self.updatescrollbars()
+        if self._parentwindow.wid.GetWindowPort().QDIsPortBuffered():
+            self._parentwindow.wid.GetWindowPort().QDFlushPortBuffer(None)
+
+    def selection_ok(self):
+        selstart, selend = self.getselection()
+        return not (selstart < self._inputstart or selend < self._inputstart)
+
+    def checkselection(self):
+        if not self.selection_ok():
+            self.setselection_at_end()
+
+    def setselection_at_end(self):
+        end = self.ted.WEGetTextLength()
+        self.setselection(end, end)
+        self.updatescrollbars()
+
+    def domenu_cut(self, *args):
+        if not self.selection_ok():
+            return
+        W.EditText.domenu_cut(self)
+
+    def domenu_paste(self, *args):
+        if not self.selection_ok():
+            self.setselection_at_end()
+        W.EditText.domenu_paste(self)
+
+    def domenu_clear(self, *args):
+        if not self.selection_ok():
+            return
+        W.EditText.domenu_clear(self)
 
 
 class PyConsole(W.Window):
-	
-	def __init__(self, bounds, show = 1, fontsettings = ("Monaco", 0, 9, (0, 0, 0)), 
-			tabsettings = (32, 0), unclosable = 0):
-		W.Window.__init__(self,
-					bounds, 
-					"Python Interactive", 
-					minsize = (200, 100), 
-					tabbable = 0, 
-					show = show)
-		
-		self._unclosable = unclosable
-		consoletext = ConsoleTextWidget((-1, -1, -14, 1), inset = (6, 5), 
-				fontsettings = fontsettings, tabsettings = tabsettings)
-		self._bary = W.Scrollbar((-15, 14, 16, -14), consoletext.vscroll, max = 32767)
-		self.consoletext = consoletext
-		self.namespacemenu = W.PopupMenu((-15, -1, 16, 16), [], self.consoletext.set_namespace)
-		self.namespacemenu.bind('<click>', self.makenamespacemenu)
-		self.open()
-	
-	def makenamespacemenu(self, *args):
-		W.SetCursor('watch')
-		namespacelist = self.getnamespacelist()
-		self.namespacemenu.set([("Clear window", self.clearbuffer), ("Font settings\xc9", self.dofontsettings), 
-				["Namespace"] + namespacelist, ("Browse namespace\xc9", self.browsenamespace)])
-		currentname = self.consoletext._namespace["__name__"]
-		for i in range(len(namespacelist)):
-			if namespacelist[i][0] == currentname:
-				break
-		else:
-			return
-		# XXX this functionality should be generally available in Wmenus
-		submenuid = self.namespacemenu.menu.menu.GetItemMark(3)
-		menu = self.namespacemenu.menu.bar.menus[submenuid]
-		menu.menu.CheckMenuItem(i + 1, 1)
-	
-	def browsenamespace(self):
-		import PyBrowser, W
-		W.SetCursor('watch')
-		PyBrowser.Browser(self.consoletext._namespace, self.consoletext._namespace["__name__"])
-	
-	def clearbuffer(self):
-		from Carbon import Res
-		self.consoletext.ted.WEUseText(Res.Resource(''))
-		self.consoletext.write(sys.ps1)
-		self.consoletext.flush()
-	
-	def getnamespacelist(self):
-		import os
-		import __main__
-		editors = filter(lambda x: x.__class__.__name__ == "Editor", self.parent._windows.values())
-		
-		namespaces = [ ("__main__",__main__.__dict__) ]
-		for ed in editors:
-			modname = os.path.splitext(ed.title)[0]
-			if sys.modules.has_key(modname):
-				module = sys.modules[modname] 
-				namespaces.append((modname, module.__dict__))
-			else:
-				if ed.title[-3:] == '.py':
-					modname = ed.title[:-3]
-				else:
-					modname = ed.title
-				ed.globals["__name__"] = modname
-				namespaces.append((modname, ed.globals))
-		return namespaces
-	
-	def dofontsettings(self):
-		import FontSettings
-		settings = FontSettings.FontDialog(self.consoletext.getfontsettings(),
-				self.consoletext.gettabsettings())
-		if settings:
-			fontsettings, tabsettings = settings
-			self.consoletext.setfontsettings(fontsettings)
-			self.consoletext.settabsettings(tabsettings)
-	
-	def show(self, onoff = 1):
-		W.Window.show(self, onoff)
-		if onoff:
-			self.select()
-	
-	def close(self):
-		if self._unclosable:
-			self.show(0)
-			return -1
-		W.Window.close(self)
-	
-	def writeprefs(self):
-		prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
-		prefs.console.show = self.isvisible()
-		prefs.console.windowbounds = self.getbounds()
-		prefs.console.fontsettings = self.consoletext.getfontsettings()
-		prefs.console.tabsettings = self.consoletext.gettabsettings()
-		prefs.save()
 
-	def getselectedtext(self):
-		return self.consoletext.getselectedtext()
-	
+    def __init__(self, bounds, show = 1, fontsettings = ("Monaco", 0, 9, (0, 0, 0)),
+                    tabsettings = (32, 0), unclosable = 0):
+        W.Window.__init__(self,
+                                bounds,
+                                "Python Interactive",
+                                minsize = (200, 100),
+                                tabbable = 0,
+                                show = show)
+
+        self._unclosable = unclosable
+        consoletext = ConsoleTextWidget((-1, -1, -14, 1), inset = (6, 5),
+                        fontsettings = fontsettings, tabsettings = tabsettings)
+        self._bary = W.Scrollbar((-15, 14, 16, -14), consoletext.vscroll, max = 32767)
+        self.consoletext = consoletext
+        self.namespacemenu = W.PopupMenu((-15, -1, 16, 16), [], self.consoletext.set_namespace)
+        self.namespacemenu.bind('<click>', self.makenamespacemenu)
+        self.open()
+
+    def makenamespacemenu(self, *args):
+        W.SetCursor('watch')
+        namespacelist = self.getnamespacelist()
+        self.namespacemenu.set([("Clear window", self.clearbuffer), ("Font settings\xc9", self.dofontsettings),
+                        ["Namespace"] + namespacelist, ("Browse namespace\xc9", self.browsenamespace)])
+        currentname = self.consoletext._namespace["__name__"]
+        for i in range(len(namespacelist)):
+            if namespacelist[i][0] == currentname:
+                break
+        else:
+            return
+        # XXX this functionality should be generally available in Wmenus
+        submenuid = self.namespacemenu.menu.menu.GetItemMark(3)
+        menu = self.namespacemenu.menu.bar.menus[submenuid]
+        menu.menu.CheckMenuItem(i + 1, 1)
+
+    def browsenamespace(self):
+        import PyBrowser, W
+        W.SetCursor('watch')
+        PyBrowser.Browser(self.consoletext._namespace, self.consoletext._namespace["__name__"])
+
+    def clearbuffer(self):
+        from Carbon import Res
+        self.consoletext.ted.WEUseText(Res.Resource(''))
+        self.consoletext.write(sys.ps1)
+        self.consoletext.flush()
+
+    def getnamespacelist(self):
+        import os
+        import __main__
+        editors = filter(lambda x: x.__class__.__name__ == "Editor", self.parent._windows.values())
+
+        namespaces = [ ("__main__",__main__.__dict__) ]
+        for ed in editors:
+            modname = os.path.splitext(ed.title)[0]
+            if sys.modules.has_key(modname):
+                module = sys.modules[modname]
+                namespaces.append((modname, module.__dict__))
+            else:
+                if ed.title[-3:] == '.py':
+                    modname = ed.title[:-3]
+                else:
+                    modname = ed.title
+                ed.globals["__name__"] = modname
+                namespaces.append((modname, ed.globals))
+        return namespaces
+
+    def dofontsettings(self):
+        import FontSettings
+        settings = FontSettings.FontDialog(self.consoletext.getfontsettings(),
+                        self.consoletext.gettabsettings())
+        if settings:
+            fontsettings, tabsettings = settings
+            self.consoletext.setfontsettings(fontsettings)
+            self.consoletext.settabsettings(tabsettings)
+
+    def show(self, onoff = 1):
+        W.Window.show(self, onoff)
+        if onoff:
+            self.select()
+
+    def close(self):
+        if self._unclosable:
+            self.show(0)
+            return -1
+        W.Window.close(self)
+
+    def writeprefs(self):
+        prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
+        prefs.console.show = self.isvisible()
+        prefs.console.windowbounds = self.getbounds()
+        prefs.console.fontsettings = self.consoletext.getfontsettings()
+        prefs.console.tabsettings = self.consoletext.gettabsettings()
+        prefs.save()
+
+    def getselectedtext(self):
+        return self.consoletext.getselectedtext()
+
 class OutputTextWidget(W.EditText):
-	
-	def domenu_save_as(self, *args):
-		title = self._parentwindow.gettitle()
-		filename = EasyDialogs.AskFileForSave(message='Save %s text as:' % title, 
-			savedFileName=title + '.txt')
-		if not filename:
-			return
-		f = open(filename, 'wb')
-		f.write(self.get())
-		f.close()
-		MacOS.SetCreatorAndType(filename, W._signature, 'TEXT')
-	
-	def domenu_cut(self, *args):
-		self.domenu_copy(*args)
-	
-	def domenu_clear(self, *args):
-		self.set('')
+
+    def domenu_save_as(self, *args):
+        title = self._parentwindow.gettitle()
+        filename = EasyDialogs.AskFileForSave(message='Save %s text as:' % title,
+                savedFileName=title + '.txt')
+        if not filename:
+            return
+        f = open(filename, 'wb')
+        f.write(self.get())
+        f.close()
+        MacOS.SetCreatorAndType(filename, W._signature, 'TEXT')
+
+    def domenu_cut(self, *args):
+        self.domenu_copy(*args)
+
+    def domenu_clear(self, *args):
+        self.set('')
 
 
 class PyOutput:
-	
-	def __init__(self, bounds, show = 1, fontsettings = ("Monaco", 0, 9, (0, 0, 0)), tabsettings = (32, 0)):
-		self.bounds = bounds
-		self.fontsettings = fontsettings
-		self.tabsettings = tabsettings
-		self.w = None
-		self.closed = 1
-		self._buf = ''
-		# should be able to set this
-		self.savestdout, self.savestderr = sys.stdout, sys.stderr
-		sys.stderr = sys.stdout = self
-		if show:
-			self.show()
-	
-	def setupwidgets(self):
-		self.w = W.Window(self.bounds, "Output", 
-				minsize = (200, 100), 
-				tabbable = 0)
-		self.w.outputtext = OutputTextWidget((-1, -1, -14, 1), inset = (6, 5), 
-				fontsettings = self.fontsettings, tabsettings = self.tabsettings, readonly = 1)
-		menuitems = [("Clear window", self.clearbuffer), ("Font settings\xc9", self.dofontsettings)]
-		self.w.popupmenu = W.PopupMenu((-15, -1, 16, 16), menuitems)
-		
-		self.w._bary = W.Scrollbar((-15, 14, 16, -14), self.w.outputtext.vscroll, max = 32767)
-		self.w.bind("<close>", self.close)
-		self.w.bind("<activate>", self.activate)
-	
-	def write(self, text):
-		if hasattr(MacOS, 'EnableAppswitch'):
-			oldyield = MacOS.EnableAppswitch(-1)
-		try:
-			self._buf = self._buf + text
-			if '\n' in self._buf:
-				self.flush()
-		finally:
-			if hasattr(MacOS, 'EnableAppswitch'):
-				MacOS.EnableAppswitch(oldyield)
-	
-	def flush(self):
-		self.show()
-		stuff = string.split(self._buf, '\n')
-		stuff = string.join(stuff, '\r')
-		end = self.w.outputtext.ted.WEGetTextLength()
-		self.w.outputtext.setselection(end, end)
-		self.w.outputtext.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 0)
-		try:
-			self.w.outputtext.ted.WEInsert(stuff, None, None)
-		finally:
-			self._buf = ""
-		self.w.outputtext.updatescrollbars()
-		self.w.outputtext.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 1)
-		if self.w.wid.GetWindowPort().QDIsPortBuffered():
-			self.w.wid.GetWindowPort().QDFlushPortBuffer(None)
-	
-	def show(self):
-		if self.closed:
-			if not self.w:
-				self.setupwidgets()
-				self.w.open()
-				self.w.outputtext.updatescrollbars()
-				self.closed = 0
-			else:
-				self.w.show(1)
-				self.closed = 0
-				self.w.select()
-	
-	def writeprefs(self):
-		if self.w is not None:
-			prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
-			prefs.output.show = self.w.isvisible()
-			prefs.output.windowbounds = self.w.getbounds()
-			prefs.output.fontsettings = self.w.outputtext.getfontsettings()
-			prefs.output.tabsettings = self.w.outputtext.gettabsettings()
-			prefs.save()
-	
-	def dofontsettings(self):
-		import FontSettings
-		settings = FontSettings.FontDialog(self.w.outputtext.getfontsettings(),
-				self.w.outputtext.gettabsettings())
-		if settings:
-			fontsettings, tabsettings = settings
-			self.w.outputtext.setfontsettings(fontsettings)
-			self.w.outputtext.settabsettings(tabsettings)
-	
-	def clearbuffer(self):
-		from Carbon import Res
-		self.w.outputtext.set('')
-	
-	def activate(self, onoff):
-		if onoff:
-			self.closed = 0
-	
-	def close(self):
-		self.w.show(0)
-		self.closed = 1
-		return -1
+
+    def __init__(self, bounds, show = 1, fontsettings = ("Monaco", 0, 9, (0, 0, 0)), tabsettings = (32, 0)):
+        self.bounds = bounds
+        self.fontsettings = fontsettings
+        self.tabsettings = tabsettings
+        self.w = None
+        self.closed = 1
+        self._buf = ''
+        # should be able to set this
+        self.savestdout, self.savestderr = sys.stdout, sys.stderr
+        sys.stderr = sys.stdout = self
+        if show:
+            self.show()
+
+    def setupwidgets(self):
+        self.w = W.Window(self.bounds, "Output",
+                        minsize = (200, 100),
+                        tabbable = 0)
+        self.w.outputtext = OutputTextWidget((-1, -1, -14, 1), inset = (6, 5),
+                        fontsettings = self.fontsettings, tabsettings = self.tabsettings, readonly = 1)
+        menuitems = [("Clear window", self.clearbuffer), ("Font settings\xc9", self.dofontsettings)]
+        self.w.popupmenu = W.PopupMenu((-15, -1, 16, 16), menuitems)
+
+        self.w._bary = W.Scrollbar((-15, 14, 16, -14), self.w.outputtext.vscroll, max = 32767)
+        self.w.bind("<close>", self.close)
+        self.w.bind("<activate>", self.activate)
+
+    def write(self, text):
+        if hasattr(MacOS, 'EnableAppswitch'):
+            oldyield = MacOS.EnableAppswitch(-1)
+        try:
+            self._buf = self._buf + text
+            if '\n' in self._buf:
+                self.flush()
+        finally:
+            if hasattr(MacOS, 'EnableAppswitch'):
+                MacOS.EnableAppswitch(oldyield)
+
+    def flush(self):
+        self.show()
+        stuff = string.split(self._buf, '\n')
+        stuff = string.join(stuff, '\r')
+        end = self.w.outputtext.ted.WEGetTextLength()
+        self.w.outputtext.setselection(end, end)
+        self.w.outputtext.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 0)
+        try:
+            self.w.outputtext.ted.WEInsert(stuff, None, None)
+        finally:
+            self._buf = ""
+        self.w.outputtext.updatescrollbars()
+        self.w.outputtext.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 1)
+        if self.w.wid.GetWindowPort().QDIsPortBuffered():
+            self.w.wid.GetWindowPort().QDFlushPortBuffer(None)
+
+    def show(self):
+        if self.closed:
+            if not self.w:
+                self.setupwidgets()
+                self.w.open()
+                self.w.outputtext.updatescrollbars()
+                self.closed = 0
+            else:
+                self.w.show(1)
+                self.closed = 0
+                self.w.select()
+
+    def writeprefs(self):
+        if self.w is not None:
+            prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
+            prefs.output.show = self.w.isvisible()
+            prefs.output.windowbounds = self.w.getbounds()
+            prefs.output.fontsettings = self.w.outputtext.getfontsettings()
+            prefs.output.tabsettings = self.w.outputtext.gettabsettings()
+            prefs.save()
+
+    def dofontsettings(self):
+        import FontSettings
+        settings = FontSettings.FontDialog(self.w.outputtext.getfontsettings(),
+                        self.w.outputtext.gettabsettings())
+        if settings:
+            fontsettings, tabsettings = settings
+            self.w.outputtext.setfontsettings(fontsettings)
+            self.w.outputtext.settabsettings(tabsettings)
+
+    def clearbuffer(self):
+        from Carbon import Res
+        self.w.outputtext.set('')
+
+    def activate(self, onoff):
+        if onoff:
+            self.closed = 0
+
+    def close(self):
+        self.w.show(0)
+        self.closed = 1
+        return -1
 
 
 class SimpleStdin:
-	
-	def readline(self):
-		import EasyDialogs
-		# A trick to make the input dialog box a bit more palatable
-		if hasattr(sys.stdout, '_buf'):
-			prompt = sys.stdout._buf
-		else:
-			prompt = ""
-		if not prompt:
-			prompt = "Stdin input:"
-		sys.stdout.flush()
-		rv = EasyDialogs.AskString(prompt)
-		if rv is None:
-			return ""
-		rv = rv + "\n"  # readline should include line terminator
-		sys.stdout.write(rv)  # echo user's reply
-		return rv
+
+    def readline(self):
+        import EasyDialogs
+        # A trick to make the input dialog box a bit more palatable
+        if hasattr(sys.stdout, '_buf'):
+            prompt = sys.stdout._buf
+        else:
+            prompt = ""
+        if not prompt:
+            prompt = "Stdin input:"
+        sys.stdout.flush()
+        rv = EasyDialogs.AskString(prompt)
+        if rv is None:
+            return ""
+        rv = rv + "\n"  # readline should include line terminator
+        sys.stdout.write(rv)  # echo user's reply
+        return rv
 
 
 def installconsole(defaultshow = 1):
-	global console
-	prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
-	if not prefs.console or not hasattr(prefs.console, 'show'):
-		prefs.console.show = defaultshow
-	if not hasattr(prefs.console, "windowbounds"):
-		prefs.console.windowbounds = (450, 250)
-	if not hasattr(prefs.console, "fontsettings"):
-		prefs.console.fontsettings = ("Monaco", 0, 9, (0, 0, 0))
-	if not hasattr(prefs.console, "tabsettings"):
-		prefs.console.tabsettings = (32, 0)
-	console = PyConsole(prefs.console.windowbounds, prefs.console.show, 
-			prefs.console.fontsettings, prefs.console.tabsettings, 1)
+    global console
+    prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
+    if not prefs.console or not hasattr(prefs.console, 'show'):
+        prefs.console.show = defaultshow
+    if not hasattr(prefs.console, "windowbounds"):
+        prefs.console.windowbounds = (450, 250)
+    if not hasattr(prefs.console, "fontsettings"):
+        prefs.console.fontsettings = ("Monaco", 0, 9, (0, 0, 0))
+    if not hasattr(prefs.console, "tabsettings"):
+        prefs.console.tabsettings = (32, 0)
+    console = PyConsole(prefs.console.windowbounds, prefs.console.show,
+                    prefs.console.fontsettings, prefs.console.tabsettings, 1)
 
 def installoutput(defaultshow = 0, OutPutWindow = PyOutput):
-	global output
-	
-	# quick 'n' dirty std in emulation
-	sys.stdin = SimpleStdin()
-	
-	prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
-	if not prefs.output or not hasattr(prefs.output, 'show'):
-		prefs.output.show = defaultshow
-	if not hasattr(prefs.output, "windowbounds"):
-		prefs.output.windowbounds = (450, 250)
-	if not hasattr(prefs.output, "fontsettings"):
-		prefs.output.fontsettings = ("Monaco", 0, 9, (0, 0, 0))
-	if not hasattr(prefs.output, "tabsettings"):
-		prefs.output.tabsettings = (32, 0)
-	output = OutPutWindow(prefs.output.windowbounds, prefs.output.show, 
-			prefs.output.fontsettings, prefs.output.tabsettings)
+    global output
+
+    # quick 'n' dirty std in emulation
+    sys.stdin = SimpleStdin()
+
+    prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
+    if not prefs.output or not hasattr(prefs.output, 'show'):
+        prefs.output.show = defaultshow
+    if not hasattr(prefs.output, "windowbounds"):
+        prefs.output.windowbounds = (450, 250)
+    if not hasattr(prefs.output, "fontsettings"):
+        prefs.output.fontsettings = ("Monaco", 0, 9, (0, 0, 0))
+    if not hasattr(prefs.output, "tabsettings"):
+        prefs.output.tabsettings = (32, 0)
+    output = OutPutWindow(prefs.output.windowbounds, prefs.output.show,
+                    prefs.output.fontsettings, prefs.output.tabsettings)
diff --git a/Mac/Tools/IDE/PyDebugger.py b/Mac/Tools/IDE/PyDebugger.py
index 51ba753..5ee92d5 100644
--- a/Mac/Tools/IDE/PyDebugger.py
+++ b/Mac/Tools/IDE/PyDebugger.py
@@ -13,882 +13,882 @@
 _filenames = {}
 
 SIMPLE_TYPES = (
-	types.NoneType,
-	types.IntType,
-	types.LongType,
-	types.FloatType,
-	types.ComplexType,
-	types.StringType
+        types.NoneType,
+        types.IntType,
+        types.LongType,
+        types.FloatType,
+        types.ComplexType,
+        types.StringType
 )
 
 
 class Debugger(bdb.Bdb):
-	
-	def __init__(self, title = 'Debugger'):
-		bdb.Bdb.__init__(self)
-		self.closed = 1
-		self.title = title
-		self.breaksviewer = None
-		self.reset()
-		self.tracing = 0
-		self.tracingmonitortime = Evt.TickCount()
-		self.editors = {}
-		
-		prefs = W.getapplication().getprefs()
-		if prefs.debugger:
-			for file, breaks in prefs.debugger.breaks.items():
-				for b in breaks:
-					self.set_break(file, b)
-			self.bounds, self.horpanes, self.verpanes = prefs.debugger.windowsettings
-			self.tracemagic = prefs.debugger.tracemagic
-		else:
-			self.breaks = {}
-			self.horpanes = (0.4, 0.6)
-			self.verpanes = (0.3, 0.35, 0.35)
-			self.bounds = (600, 400)
-			self.tracemagic = 0
-		self.laststacksel = None
-	
-	def canonic(self, filename):
-		# override: the provided canonic() method breaks our
-		# file-less Untitled windows
-		return filename
-	
-	def reset(self):
-		self.currentframe = None
-		self.file = None
-		self.laststack = None
-		self.reason = 'Not running'
-		self.continuewithoutdebugger = 0
-		bdb.Bdb.reset(self)
-		self.forget()
-	
-	def start(self, bottomframe = None, running = 0):
-		W.getapplication().DebuggerQuit = bdb.BdbQuit
-		from Carbon import Menu
-		Menu.HiliteMenu(0)
-		if self.closed:
-			self.setupwidgets(self.title)
-			self.closed = 0
-		if not self.w.parent.debugger_quitting:
-			self.w.select()
-			raise W.AlertError, 'There is another debugger session busy.'
-		self.reset()
-		self.botframe = bottomframe
-		if running:
-			self.set_continue()
-			self.reason = 'Running\xc9'
-			self.setstate('running')
-		else:
-			self.set_step()
-			self.reason = 'stopped'
-			self.setstate('stopped')
-		sys.settrace(self.trace_dispatch)
-	
-	def stop(self):
-		self.set_quit()
-		if self.w.parent:
-			self.exit_mainloop()
-			self.resetwidgets()
-	
-	def set_continue_without_debugger(self):
-		sys.settrace(None)
-		self.set_quit()
-		self.clear_tracefuncs()
-		self.continuewithoutdebugger = 1
-		if hasattr(self, "w") and self.w.parent:
-			self.exit_mainloop()
-			self.resetwidgets()
-	
-	def clear_tracefuncs(self):
-		try:
-			raise 'spam'
-		except:
-			pass
-		frame = sys.exc_traceback.tb_frame
-		while frame is not None:
-			del frame.f_trace
-			frame = frame.f_back
-	
-	def postmortem(self, exc_type, exc_value, traceback):
-		if self.closed:
-			self.setupwidgets(self.title)
-			self.closed = 0
-		if not self.w.parent.debugger_quitting:
-			raise W.AlertError, 'There is another debugger session busy.'
-		self.reset()
-		if traceback:
-			self.botframe = traceback.tb_frame
-			while traceback.tb_next <> None:
-				traceback = traceback.tb_next
-			frame = traceback.tb_frame
-		else:
-			self.botframe = None
-			frame = None
-		self.w.panes.bottom.buttons.killbutton.enable(1)
-		self.reason = '(dead) ' + self.formatexception(exc_type, exc_value)
-		self.w.select()
-		self.setup(frame, traceback)
-		self.setstate('dead')
-		self.showstack(self.curindex)
-		self.showframe(self.curindex)
-	
-	def setupwidgets(self, title):
-		self.w = w = W.Window(self.bounds, title, minsize = (500, 300))
-		
-		w.panes = W.HorizontalPanes((8, 4, -8, -8), self.horpanes)
-		
-		w.panes.browserpanes = browserpanes = W.VerticalPanes(None, self.verpanes)
-		
-		browserpanes.stacklist = W.Group(None)
-		browserpanes.stacklist.title = W.TextBox((4, 0, 0, 12), 'Stack')
-		browserpanes.stacklist.stack = W.List((0, 16, 0, 0), callback = self.do_stack, flags = Lists.lOnlyOne)
-		
-		browserpanes.locals = W.Group(None)
-		browserpanes.locals.title = W.TextBox((4, 0, 0, 12), 'Local variables')
-		browserpanes.locals.browser = PyBrowser.BrowserWidget((0, 16, 0, 0))
-		
-		browserpanes.globals = W.Group(None)
-		browserpanes.globals.title = W.TextBox((4, 0, 0, 12), 'Global variables')
-		browserpanes.globals.browser = PyBrowser.BrowserWidget((0, 16, 0, 0))
-		
-		w.panes.bottom = bottom = W.Group(None)
-		bottom.src = src = W.Group((0, 64, 0, 0))
-		source = SourceViewer((1, 1, -15, -15), readonly = 1, debugger = self)
-		src.optionsmenu = W.PopupMenu((-16, 0, 16, 16), [])
-		src.optionsmenu.bind('<click>', self.makeoptionsmenu)
-		
-		src._barx = W.Scrollbar((0, -16, -15, 16), source.hscroll, max = 32767)
-		src._bary = W.Scrollbar((-16, 15, 16, -15), source.vscroll, max = 32767)
-		src.source = source
-		src.frame = W.Frame((0, 0, -15, -15))
-		
-		bottom.tracingmonitor = TracingMonitor((0, 23, 6, 6))
-		bottom.state = W.TextBox((12, 24, 0, 16), self.reason)
-		
-		bottom.srctitle = W.TextBox((12, 44, 0, 16))
-		bottom.buttons = buttons = W.Group((12, 0, 0, 20))
-		
-		buttons.runbutton = W.Button((0, 0, 50, 16), "Run", self.do_run)
-		buttons.stopbutton = W.Button((58, 0, 50, 16), "Stop", self.do_stop)
-		buttons.killbutton = W.Button((116, 0, 50, 16), "Kill", self.do_kill)
-		buttons.line = W.VerticalLine((173, 0, 0, 0))
-		buttons.stepbutton = W.Button((181, 0, 60, 16), "Step", self.do_step)
-		buttons.stepinbutton = W.Button((249, 0, 60, 16), "Step in", self.do_stepin)
-		buttons.stepoutbutton = W.Button((317, 0, 60, 16), "Step out", self.do_stepout)
-		
-		w.bind('cmdr', buttons.runbutton.push)
-		w.bind('cmd.', buttons.stopbutton.push)
-		w.bind('cmdk', buttons.killbutton.push)
-		w.bind('cmds', buttons.stepbutton.push)
-		w.bind('cmdt', buttons.stepinbutton.push)
-		w.bind('cmdu', buttons.stepoutbutton.push)
-		
-		w.bind('<close>', self.close)
-		
-		w.open()
-		w.xxx___select(w.panes.bottom.src.source)
-	
-	def makeoptionsmenu(self):
-		options = [('Clear breakpoints', self.w.panes.bottom.src.source.clearbreakpoints), 
-				('Clear all breakpoints', self.clear_all_breaks),
-				('Edit breakpoints\xc9', self.edit_breaks), '-',
-				(self.tracemagic and 
-					'Disable __magic__ tracing' or 'Enable __magic__ tracing', self.togglemagic)]
-		self.w.panes.bottom.src.optionsmenu.set(options)
-	
-	def edit_breaks(self):
-		if self.breaksviewer:
-			self.breaksviewer.select()
-		else:
-			self.breaksviewer = BreakpointsViewer(self)
-	
-	def togglemagic(self):
-		self.tracemagic = not self.tracemagic
-	
-	def setstate(self, state):
-		self.w.panes.bottom.tracingmonitor.reset()
-		self.w.panes.bottom.state.set(self.reason)
-		buttons = self.w.panes.bottom.buttons
-		if state == 'stopped':
-			buttons.runbutton.enable(1)
-			buttons.stopbutton.enable(0)
-			buttons.killbutton.enable(1)
-			buttons.stepbutton.enable(1)
-			buttons.stepinbutton.enable(1)
-			buttons.stepoutbutton.enable(1)
-		elif state == 'running':
-			buttons.runbutton.enable(0)
-			buttons.stopbutton.enable(1)
-			buttons.killbutton.enable(1)
-			buttons.stepbutton.enable(0)
-			buttons.stepinbutton.enable(0)
-			buttons.stepoutbutton.enable(0)
-		elif state == 'idle':
-			buttons.runbutton.enable(0)
-			buttons.stopbutton.enable(0)
-			buttons.killbutton.enable(0)
-			buttons.stepbutton.enable(0)
-			buttons.stepinbutton.enable(0)
-			buttons.stepoutbutton.enable(0)
-		elif state == 'dead':
-			buttons.runbutton.enable(0)
-			buttons.stopbutton.enable(0)
-			buttons.killbutton.enable(1)
-			buttons.stepbutton.enable(0)
-			buttons.stepinbutton.enable(0)
-			buttons.stepoutbutton.enable(0)
-		else:
-			print 'unknown state:', state
-	
-	def resetwidgets(self):
-		self.reason = ''
-		self.w.panes.bottom.srctitle.set('')
-		self.w.panes.bottom.src.source.set('')
-		self.w.panes.browserpanes.stacklist.stack.set([])
-		self.w.panes.browserpanes.locals.browser.set({})
-		self.w.panes.browserpanes.globals.browser.set({})
-		self.setstate('idle')
-	
-	# W callbacks
-	
-	def close(self):
-		self.set_quit()
-		self.exit_mainloop()
-		self.closed = 1
-		
-		self.unregister_editor(self.w.panes.bottom.src.source, 
-				self.w.panes.bottom.src.source.file)
-		self.horpanes = self.w.panes.getpanesizes()
-		self.verpanes = self.w.panes.browserpanes.getpanesizes()
-		self.bounds = self.w.getbounds()
-		prefs = W.getapplication().getprefs()
-		prefs.debugger.breaks = self.breaks
-		prefs.debugger.windowsettings = self.bounds, self.horpanes, self.verpanes
-		prefs.debugger.tracemagic = self.tracemagic
-		prefs.save()
-	
-	# stack list callback
-	
-	def do_stack(self, isdbl):
-		sel = self.w.panes.browserpanes.stacklist.stack.getselection()
-		if isdbl:
-			if sel:
-				frame, lineno = self.stack[sel[0] + 1]
-				filename = frame.f_code.co_filename
-				editor = self.w._parentwindow.parent.openscript(filename, lineno)
-				if self.breaks.has_key(filename):
-					editor.showbreakpoints(1)
-		else:
-			if sel and sel <> self.laststacksel:
-				self.showframe(sel[0] + 1)
-			self.laststacksel = sel
-	
-	def geteditor(self, filename):
-		if filename[:1] == '<' and filename[-1:] == '>':
-			editor = W.getapplication().getscript(filename[1:-1])
-		else:
-			editor = W.getapplication().getscript(filename)
-		return editor
-	
-	# button callbacks
-	
-	def do_run(self):
-		self.running()
-		self.set_continue()
-		self.exit_mainloop()
-	
-	def do_stop(self):
-		self.set_step()
-	
-	def do_kill(self):
-		self.set_quit()
-		self.exit_mainloop()
-		self.resetwidgets()
-	
-	def do_step(self):
-		self.running()
-		self.set_next(self.curframe)
-		self.exit_mainloop()
-	
-	def do_stepin(self):
-		self.running()
-		self.set_step()
-		self.exit_mainloop()
-	
-	def do_stepout(self):
-		self.running()
-		self.set_return(self.curframe)
-		self.exit_mainloop()
-	
-	def running(self):
-		W.SetCursor('watch')
-		self.reason = 'Running\xc9'
-		self.setstate('running')
-		#self.w.panes.bottom.src.source.set('')
-		#self.w.panes.browserpanes.stacklist.stack.set([])
-		#self.w.panes.browserpanes.locals.browser.set({})
-		#self.w.panes.browserpanes.globals.browser.set({})
-	
-	def exit_mainloop(self):
-		self.w.parent.debugger_quitting = 1
-	
-	#
-	
-	def showframe(self, stackindex):
-		(frame, lineno) = self.stack[stackindex]
-		W.SetCursor('watch')
-		filename = frame.f_code.co_filename
-		if filename <> self.file:
-			editor = self.geteditor(filename)
-			if editor:
-				self.w.panes.bottom.src.source.set(editor.get(), filename)
-			else:
-				try:
-					f = open(filename, 'rU')
-					data = f.read()
-					f.close()
-				except IOError:
-					if filename[-3:] == '.py':
-						import imp
-						modname = os.path.basename(filename)[:-3]
-						try:
-							f, filename, (suff, mode, dummy) = imp.find_module(modname)
-						except ImportError:
-							self.w.panes.bottom.src.source.set("can't find file")
-						else:
-							if f:
-								f.close()
-							if f and suff == '.py':
-								f = open(filename, 'rU')
-								data = f.read()
-								f.close()
-								self.w.panes.bottom.src.source.set(data, filename)
-							else:
-								self.w.panes.bottom.src.source.set("can't find file")
-					else:
-						self.w.panes.bottom.src.source.set("can't find file")
-				else:
-					data = data.replace('\n', '\r')
-					self.w.panes.bottom.src.source.set(data, filename)
-			self.file = filename
-		self.w.panes.bottom.srctitle.set('Source: ' + filename + ((lineno > 0) and (' (line %d)' % lineno) or ' '))
-		self.goto_line(lineno)
-		self.lineno = lineno
-		self.showvars((frame, lineno))
-	
-	def showvars(self, (frame, lineno)):
-		if frame.f_locals is not frame.f_globals:
-			locals = frame.f_locals
-		else:
-			locals = {'Same as Globals':''}
-		filteredlocals = {}
-		for key, value in locals.items():
-			# empty key is magic for Python 1.4; '.' is magic for 1.5...
-			if not key or key[0] <> '.':
-				filteredlocals[key] = value
-		self.w.panes.browserpanes.locals.browser.set(filteredlocals)
-		self.w.panes.browserpanes.globals.browser.set(frame.f_globals)
-	
-	def showstack(self, stackindex):
-		stack = []
-		for frame, lineno in self.stack[1:]:
-			filename = frame.f_code.co_filename
-			try:
-				filename = _filenames[filename]
-			except KeyError:
-				if filename[:1] + filename[-1:] <> '<>':
-					filename = os.path.basename(filename)
-				_filenames[frame.f_code.co_filename] = filename
-			funcname = frame.f_code.co_name
-			if funcname == '?':
-				funcname = '<toplevel>'
-			stack.append(filename + ': ' + funcname)
-		if stack <> self.laststack:
-			self.w.panes.browserpanes.stacklist.stack.set(stack)
-			self.laststack = stack
-		sel = [stackindex - 1]
-		self.w.panes.browserpanes.stacklist.stack.setselection(sel)
-		self.laststacksel = sel
-	
-	def goto_line(self, lineno):
-		if lineno > 0:
-			self.w.panes.bottom.src.source.selectline(lineno - 1)
-		else:
-			self.w.panes.bottom.src.source.setselection(0, 0)
-	
-	# bdb entry points
-	
-#	def user_call(self, frame, argument_list):
-#		self.reason = 'Calling'
-#		self.interaction(frame, None)
-	
-	def user_line(self, frame):
-		# This function is called when we stop or break at this line
-		self.reason = 'Stopped'
-		self.interaction(frame, None)
-	
-	def user_return(self, frame, return_value):
-		# This function is called when a return trap is set here
-		fname = frame.f_code.co_name
-		if fname <> '?':
-			self.reason = 'Returning from %s()' % frame.f_code.co_name
-			frame.f_locals['__return__'] = return_value
-		elif frame.f_back is self.botframe:
-			self.reason = 'Done'
-		else:
-			self.reason = 'Returning'
-		self.interaction(frame, None, 1)
-	
-	def user_exception(self, frame, (exc_type, exc_value, exc_traceback)):
-		# This function is called when we stop or break at this line
-		self.reason = self.formatexception(exc_type, exc_value)
-		self.interaction(frame, exc_traceback)
-	
-	def formatexception(self, exc_type, exc_value):
-		if exc_type == SyntaxError:
-			try:
-				value, (filename, lineno, charno, line) = exc_value
-			except:
-				pass
-			else:
-				return str(exc_type) + ': ' + str(value)
-		if type(exc_type) == types.ClassType:
-			nice = exc_type.__name__
-		else:
-			nice = str(exc_type)
-		value = str(exc_value)
-		if exc_value and value:
-			nice = nice + ": " + value
-		return nice
-	
-	def forget(self):
-		self.stack = []
-		self.curindex = 0
-		self.curframe = None
-	
-	def setup(self, f, t, isreturning = 0):
-		self.forget()
-		self.stack, self.curindex = self.get_stack(f, t)
-		self.curframe = self.stack[self.curindex - isreturning][0]
-	
-	def interaction(self, frame, traceback, isreturning = 0):
-		saveport = Qd.GetPort()
-		self.w.select()
-		try:
-			self.setup(frame, traceback, isreturning)
-			self.setstate('stopped')
-			stackindex = self.curindex
-			if isreturning:
-				if frame.f_back is not self.botframe:
-					stackindex = stackindex - 1
-			self.showstack(stackindex)
-			self.showframe(stackindex)
-			self.w.parent.debugger_mainloop()
-			self.forget()
-		finally:
-			Qd.SetPort(saveport)
-	
-	# bdb customization
-	
-	def trace_dispatch(self, frame, event, arg, TickCount = Evt.TickCount):
-		if TickCount() - self.tracingmonitortime > 15:
-			self.tracingmonitortime = TickCount()
-			self.w.panes.bottom.tracingmonitor.toggle()
-		try:
-			try:
-				if hasattr(MacOS, 'EnableAppswitch'):
-					MacOS.EnableAppswitch(0)
-				if self.quitting:
-					# returning None is not enough, a former BdbQuit exception
-					# might have been eaten by the print statement
-					raise bdb.BdbQuit
-				if event == 'line':
-					return self.dispatch_line(frame)
-				if event == 'call':
-					return self.dispatch_call(frame, arg)
-				if event == 'return':
-					return self.dispatch_return(frame, arg)
-				if event == 'exception':
-					return self.dispatch_exception(frame, arg)
-				print 'bdb.Bdb.dispatch: unknown debugging event:', repr(event)
-				return self.trace_dispatch
-			finally:
-				if hasattr(MacOS, 'EnableAppswitch'):
-					MacOS.EnableAppswitch(-1)
-		except KeyboardInterrupt:
-			self.set_step()
-			return self.trace_dispatch
-		except bdb.BdbQuit:
-			if self.continuewithoutdebugger:
-				self.clear_tracefuncs()
-				return
-			else:
-				raise bdb.BdbQuit
-		except:
-			print 'XXX Exception during debugger interaction.', \
-					self.formatexception(sys.exc_type, sys.exc_value)
-			import traceback
-			traceback.print_exc()
-			return self.trace_dispatch
-	
-	def dispatch_call(self, frame, arg):
-		if not self.tracemagic and \
-				frame.f_code.co_name[:2] == '__' == frame.f_code.co_name[-2:] and \
-				frame.f_code.co_name <> '__init__':
-			return
-		if self.botframe is None:
-			# First call of dispatch since reset()
-			self.botframe = frame.f_back	# xxx !!! added f_back
-			return self.trace_dispatch
-		if not (self.stop_here(frame) or self.break_anywhere(frame)):
-			# No need to trace this function
-			return # None
-		self.user_call(frame, arg)
-		if self.quitting:
-			raise bdb.BdbQuit
-		return self.trace_dispatch
-	
-	def set_continue(self):
-		# Don't stop except at breakpoints or when finished
-		self.stopframe = self.botframe
-		self.returnframe = None
-		self.quitting = 0
-		# unlike in bdb/pdb, there's a chance that breakpoints change 
-		# *while* a program (this program ;-) is running. It's actually quite likely.
-		# So we don't delete frame.f_trace until the bottom frame if there are no breakpoints.
-	
-	def set_break(self, filename, lineno):
-		if not self.breaks.has_key(filename):
-			self.breaks[filename] = []
-		list = self.breaks[filename]
-		if lineno in list:
-			return 'There is already a breakpoint there!'
-		list.append(lineno)
-		list.sort()	# I want to keep them neatly sorted; easier for drawing
-		if hasattr(bdb, "Breakpoint"):
-			# 1.5.2b1 specific
-			bp = bdb.Breakpoint(filename, lineno, 0, None)
-		self.update_breaks(filename)
-	
-	def clear_break(self, filename, lineno):
-		bdb.Bdb.clear_break(self, filename, lineno)
-		self.update_breaks(filename)
-	
-	def clear_all_file_breaks(self, filename):
-		bdb.Bdb.clear_all_file_breaks(self, filename)
-		self.update_breaks(filename)
-	
-	def clear_all_breaks(self):
-		bdb.Bdb.clear_all_breaks(self)
-		for editors in self.editors.values():
-			for editor in editors:
-				editor.drawbreakpoints()
-	
-	# special
-	
-	def toggle_break(self, filename, lineno):
-		if self.get_break(filename, lineno):
-			self.clear_break(filename, lineno)
-		else:
-			self.set_break(filename, lineno)
-	
-	def clear_breaks_above(self, filename, above):
-		if not self.breaks.has_key(filename):
-			return 'There are no breakpoints in that file!'
-		for lineno in self.breaks[filename][:]:
-			if lineno > above:
-				self.breaks[filename].remove(lineno)
-		if not self.breaks[filename]:
-			del self.breaks[filename]
-	
-	# editor stuff
-	
-	def update_breaks(self, filename):
-		if self.breaksviewer:
-			self.breaksviewer.update()
-		if self.editors.has_key(filename):
-			for editor in self.editors[filename]:
-				if editor._debugger:	# XXX
-					editor.drawbreakpoints()
-				else:
-					print 'xxx dead editor!'
-	
-	def update_allbreaks(self):
-		if self.breaksviewer:
-			self.breaksviewer.update()
-		for filename in self.breaks.keys():
-			if self.editors.has_key(filename):
-				for editor in self.editors[filename]:
-					if editor._debugger:	# XXX
-						editor.drawbreakpoints()
-					else:
-						print 'xxx dead editor!'
-	
-	def register_editor(self, editor, filename):
-		if not filename:
-			return
-		if not self.editors.has_key(filename):
-			self.editors[filename] = [editor]
-		elif editor not in self.editors[filename]:
-			self.editors[filename].append(editor)
-	
-	def unregister_editor(self, editor, filename):
-		if not filename:
-			return
-		try:
-			self.editors[filename].remove(editor)
-			if not self.editors[filename]:
-				del self.editors[filename]
-				# if this was an untitled window, clear the breaks.
-				if filename[:1] == '<' and filename[-1:] == '>' and \
-						self.breaks.has_key(filename):
-					self.clear_all_file_breaks(filename)
-		except (KeyError, ValueError):
-			pass
-		
+
+    def __init__(self, title = 'Debugger'):
+        bdb.Bdb.__init__(self)
+        self.closed = 1
+        self.title = title
+        self.breaksviewer = None
+        self.reset()
+        self.tracing = 0
+        self.tracingmonitortime = Evt.TickCount()
+        self.editors = {}
+
+        prefs = W.getapplication().getprefs()
+        if prefs.debugger:
+            for file, breaks in prefs.debugger.breaks.items():
+                for b in breaks:
+                    self.set_break(file, b)
+            self.bounds, self.horpanes, self.verpanes = prefs.debugger.windowsettings
+            self.tracemagic = prefs.debugger.tracemagic
+        else:
+            self.breaks = {}
+            self.horpanes = (0.4, 0.6)
+            self.verpanes = (0.3, 0.35, 0.35)
+            self.bounds = (600, 400)
+            self.tracemagic = 0
+        self.laststacksel = None
+
+    def canonic(self, filename):
+        # override: the provided canonic() method breaks our
+        # file-less Untitled windows
+        return filename
+
+    def reset(self):
+        self.currentframe = None
+        self.file = None
+        self.laststack = None
+        self.reason = 'Not running'
+        self.continuewithoutdebugger = 0
+        bdb.Bdb.reset(self)
+        self.forget()
+
+    def start(self, bottomframe = None, running = 0):
+        W.getapplication().DebuggerQuit = bdb.BdbQuit
+        from Carbon import Menu
+        Menu.HiliteMenu(0)
+        if self.closed:
+            self.setupwidgets(self.title)
+            self.closed = 0
+        if not self.w.parent.debugger_quitting:
+            self.w.select()
+            raise W.AlertError, 'There is another debugger session busy.'
+        self.reset()
+        self.botframe = bottomframe
+        if running:
+            self.set_continue()
+            self.reason = 'Running\xc9'
+            self.setstate('running')
+        else:
+            self.set_step()
+            self.reason = 'stopped'
+            self.setstate('stopped')
+        sys.settrace(self.trace_dispatch)
+
+    def stop(self):
+        self.set_quit()
+        if self.w.parent:
+            self.exit_mainloop()
+            self.resetwidgets()
+
+    def set_continue_without_debugger(self):
+        sys.settrace(None)
+        self.set_quit()
+        self.clear_tracefuncs()
+        self.continuewithoutdebugger = 1
+        if hasattr(self, "w") and self.w.parent:
+            self.exit_mainloop()
+            self.resetwidgets()
+
+    def clear_tracefuncs(self):
+        try:
+            raise 'spam'
+        except:
+            pass
+        frame = sys.exc_traceback.tb_frame
+        while frame is not None:
+            del frame.f_trace
+            frame = frame.f_back
+
+    def postmortem(self, exc_type, exc_value, traceback):
+        if self.closed:
+            self.setupwidgets(self.title)
+            self.closed = 0
+        if not self.w.parent.debugger_quitting:
+            raise W.AlertError, 'There is another debugger session busy.'
+        self.reset()
+        if traceback:
+            self.botframe = traceback.tb_frame
+            while traceback.tb_next <> None:
+                traceback = traceback.tb_next
+            frame = traceback.tb_frame
+        else:
+            self.botframe = None
+            frame = None
+        self.w.panes.bottom.buttons.killbutton.enable(1)
+        self.reason = '(dead) ' + self.formatexception(exc_type, exc_value)
+        self.w.select()
+        self.setup(frame, traceback)
+        self.setstate('dead')
+        self.showstack(self.curindex)
+        self.showframe(self.curindex)
+
+    def setupwidgets(self, title):
+        self.w = w = W.Window(self.bounds, title, minsize = (500, 300))
+
+        w.panes = W.HorizontalPanes((8, 4, -8, -8), self.horpanes)
+
+        w.panes.browserpanes = browserpanes = W.VerticalPanes(None, self.verpanes)
+
+        browserpanes.stacklist = W.Group(None)
+        browserpanes.stacklist.title = W.TextBox((4, 0, 0, 12), 'Stack')
+        browserpanes.stacklist.stack = W.List((0, 16, 0, 0), callback = self.do_stack, flags = Lists.lOnlyOne)
+
+        browserpanes.locals = W.Group(None)
+        browserpanes.locals.title = W.TextBox((4, 0, 0, 12), 'Local variables')
+        browserpanes.locals.browser = PyBrowser.BrowserWidget((0, 16, 0, 0))
+
+        browserpanes.globals = W.Group(None)
+        browserpanes.globals.title = W.TextBox((4, 0, 0, 12), 'Global variables')
+        browserpanes.globals.browser = PyBrowser.BrowserWidget((0, 16, 0, 0))
+
+        w.panes.bottom = bottom = W.Group(None)
+        bottom.src = src = W.Group((0, 64, 0, 0))
+        source = SourceViewer((1, 1, -15, -15), readonly = 1, debugger = self)
+        src.optionsmenu = W.PopupMenu((-16, 0, 16, 16), [])
+        src.optionsmenu.bind('<click>', self.makeoptionsmenu)
+
+        src._barx = W.Scrollbar((0, -16, -15, 16), source.hscroll, max = 32767)
+        src._bary = W.Scrollbar((-16, 15, 16, -15), source.vscroll, max = 32767)
+        src.source = source
+        src.frame = W.Frame((0, 0, -15, -15))
+
+        bottom.tracingmonitor = TracingMonitor((0, 23, 6, 6))
+        bottom.state = W.TextBox((12, 24, 0, 16), self.reason)
+
+        bottom.srctitle = W.TextBox((12, 44, 0, 16))
+        bottom.buttons = buttons = W.Group((12, 0, 0, 20))
+
+        buttons.runbutton = W.Button((0, 0, 50, 16), "Run", self.do_run)
+        buttons.stopbutton = W.Button((58, 0, 50, 16), "Stop", self.do_stop)
+        buttons.killbutton = W.Button((116, 0, 50, 16), "Kill", self.do_kill)
+        buttons.line = W.VerticalLine((173, 0, 0, 0))
+        buttons.stepbutton = W.Button((181, 0, 60, 16), "Step", self.do_step)
+        buttons.stepinbutton = W.Button((249, 0, 60, 16), "Step in", self.do_stepin)
+        buttons.stepoutbutton = W.Button((317, 0, 60, 16), "Step out", self.do_stepout)
+
+        w.bind('cmdr', buttons.runbutton.push)
+        w.bind('cmd.', buttons.stopbutton.push)
+        w.bind('cmdk', buttons.killbutton.push)
+        w.bind('cmds', buttons.stepbutton.push)
+        w.bind('cmdt', buttons.stepinbutton.push)
+        w.bind('cmdu', buttons.stepoutbutton.push)
+
+        w.bind('<close>', self.close)
+
+        w.open()
+        w.xxx___select(w.panes.bottom.src.source)
+
+    def makeoptionsmenu(self):
+        options = [('Clear breakpoints', self.w.panes.bottom.src.source.clearbreakpoints),
+                        ('Clear all breakpoints', self.clear_all_breaks),
+                        ('Edit breakpoints\xc9', self.edit_breaks), '-',
+                        (self.tracemagic and
+                                'Disable __magic__ tracing' or 'Enable __magic__ tracing', self.togglemagic)]
+        self.w.panes.bottom.src.optionsmenu.set(options)
+
+    def edit_breaks(self):
+        if self.breaksviewer:
+            self.breaksviewer.select()
+        else:
+            self.breaksviewer = BreakpointsViewer(self)
+
+    def togglemagic(self):
+        self.tracemagic = not self.tracemagic
+
+    def setstate(self, state):
+        self.w.panes.bottom.tracingmonitor.reset()
+        self.w.panes.bottom.state.set(self.reason)
+        buttons = self.w.panes.bottom.buttons
+        if state == 'stopped':
+            buttons.runbutton.enable(1)
+            buttons.stopbutton.enable(0)
+            buttons.killbutton.enable(1)
+            buttons.stepbutton.enable(1)
+            buttons.stepinbutton.enable(1)
+            buttons.stepoutbutton.enable(1)
+        elif state == 'running':
+            buttons.runbutton.enable(0)
+            buttons.stopbutton.enable(1)
+            buttons.killbutton.enable(1)
+            buttons.stepbutton.enable(0)
+            buttons.stepinbutton.enable(0)
+            buttons.stepoutbutton.enable(0)
+        elif state == 'idle':
+            buttons.runbutton.enable(0)
+            buttons.stopbutton.enable(0)
+            buttons.killbutton.enable(0)
+            buttons.stepbutton.enable(0)
+            buttons.stepinbutton.enable(0)
+            buttons.stepoutbutton.enable(0)
+        elif state == 'dead':
+            buttons.runbutton.enable(0)
+            buttons.stopbutton.enable(0)
+            buttons.killbutton.enable(1)
+            buttons.stepbutton.enable(0)
+            buttons.stepinbutton.enable(0)
+            buttons.stepoutbutton.enable(0)
+        else:
+            print 'unknown state:', state
+
+    def resetwidgets(self):
+        self.reason = ''
+        self.w.panes.bottom.srctitle.set('')
+        self.w.panes.bottom.src.source.set('')
+        self.w.panes.browserpanes.stacklist.stack.set([])
+        self.w.panes.browserpanes.locals.browser.set({})
+        self.w.panes.browserpanes.globals.browser.set({})
+        self.setstate('idle')
+
+    # W callbacks
+
+    def close(self):
+        self.set_quit()
+        self.exit_mainloop()
+        self.closed = 1
+
+        self.unregister_editor(self.w.panes.bottom.src.source,
+                        self.w.panes.bottom.src.source.file)
+        self.horpanes = self.w.panes.getpanesizes()
+        self.verpanes = self.w.panes.browserpanes.getpanesizes()
+        self.bounds = self.w.getbounds()
+        prefs = W.getapplication().getprefs()
+        prefs.debugger.breaks = self.breaks
+        prefs.debugger.windowsettings = self.bounds, self.horpanes, self.verpanes
+        prefs.debugger.tracemagic = self.tracemagic
+        prefs.save()
+
+    # stack list callback
+
+    def do_stack(self, isdbl):
+        sel = self.w.panes.browserpanes.stacklist.stack.getselection()
+        if isdbl:
+            if sel:
+                frame, lineno = self.stack[sel[0] + 1]
+                filename = frame.f_code.co_filename
+                editor = self.w._parentwindow.parent.openscript(filename, lineno)
+                if self.breaks.has_key(filename):
+                    editor.showbreakpoints(1)
+        else:
+            if sel and sel <> self.laststacksel:
+                self.showframe(sel[0] + 1)
+            self.laststacksel = sel
+
+    def geteditor(self, filename):
+        if filename[:1] == '<' and filename[-1:] == '>':
+            editor = W.getapplication().getscript(filename[1:-1])
+        else:
+            editor = W.getapplication().getscript(filename)
+        return editor
+
+    # button callbacks
+
+    def do_run(self):
+        self.running()
+        self.set_continue()
+        self.exit_mainloop()
+
+    def do_stop(self):
+        self.set_step()
+
+    def do_kill(self):
+        self.set_quit()
+        self.exit_mainloop()
+        self.resetwidgets()
+
+    def do_step(self):
+        self.running()
+        self.set_next(self.curframe)
+        self.exit_mainloop()
+
+    def do_stepin(self):
+        self.running()
+        self.set_step()
+        self.exit_mainloop()
+
+    def do_stepout(self):
+        self.running()
+        self.set_return(self.curframe)
+        self.exit_mainloop()
+
+    def running(self):
+        W.SetCursor('watch')
+        self.reason = 'Running\xc9'
+        self.setstate('running')
+        #self.w.panes.bottom.src.source.set('')
+        #self.w.panes.browserpanes.stacklist.stack.set([])
+        #self.w.panes.browserpanes.locals.browser.set({})
+        #self.w.panes.browserpanes.globals.browser.set({})
+
+    def exit_mainloop(self):
+        self.w.parent.debugger_quitting = 1
+
+    #
+
+    def showframe(self, stackindex):
+        (frame, lineno) = self.stack[stackindex]
+        W.SetCursor('watch')
+        filename = frame.f_code.co_filename
+        if filename <> self.file:
+            editor = self.geteditor(filename)
+            if editor:
+                self.w.panes.bottom.src.source.set(editor.get(), filename)
+            else:
+                try:
+                    f = open(filename, 'rU')
+                    data = f.read()
+                    f.close()
+                except IOError:
+                    if filename[-3:] == '.py':
+                        import imp
+                        modname = os.path.basename(filename)[:-3]
+                        try:
+                            f, filename, (suff, mode, dummy) = imp.find_module(modname)
+                        except ImportError:
+                            self.w.panes.bottom.src.source.set("can't find file")
+                        else:
+                            if f:
+                                f.close()
+                            if f and suff == '.py':
+                                f = open(filename, 'rU')
+                                data = f.read()
+                                f.close()
+                                self.w.panes.bottom.src.source.set(data, filename)
+                            else:
+                                self.w.panes.bottom.src.source.set("can't find file")
+                    else:
+                        self.w.panes.bottom.src.source.set("can't find file")
+                else:
+                    data = data.replace('\n', '\r')
+                    self.w.panes.bottom.src.source.set(data, filename)
+            self.file = filename
+        self.w.panes.bottom.srctitle.set('Source: ' + filename + ((lineno > 0) and (' (line %d)' % lineno) or ' '))
+        self.goto_line(lineno)
+        self.lineno = lineno
+        self.showvars((frame, lineno))
+
+    def showvars(self, (frame, lineno)):
+        if frame.f_locals is not frame.f_globals:
+            locals = frame.f_locals
+        else:
+            locals = {'Same as Globals':''}
+        filteredlocals = {}
+        for key, value in locals.items():
+            # empty key is magic for Python 1.4; '.' is magic for 1.5...
+            if not key or key[0] <> '.':
+                filteredlocals[key] = value
+        self.w.panes.browserpanes.locals.browser.set(filteredlocals)
+        self.w.panes.browserpanes.globals.browser.set(frame.f_globals)
+
+    def showstack(self, stackindex):
+        stack = []
+        for frame, lineno in self.stack[1:]:
+            filename = frame.f_code.co_filename
+            try:
+                filename = _filenames[filename]
+            except KeyError:
+                if filename[:1] + filename[-1:] <> '<>':
+                    filename = os.path.basename(filename)
+                _filenames[frame.f_code.co_filename] = filename
+            funcname = frame.f_code.co_name
+            if funcname == '?':
+                funcname = '<toplevel>'
+            stack.append(filename + ': ' + funcname)
+        if stack <> self.laststack:
+            self.w.panes.browserpanes.stacklist.stack.set(stack)
+            self.laststack = stack
+        sel = [stackindex - 1]
+        self.w.panes.browserpanes.stacklist.stack.setselection(sel)
+        self.laststacksel = sel
+
+    def goto_line(self, lineno):
+        if lineno > 0:
+            self.w.panes.bottom.src.source.selectline(lineno - 1)
+        else:
+            self.w.panes.bottom.src.source.setselection(0, 0)
+
+    # bdb entry points
+
+#       def user_call(self, frame, argument_list):
+#               self.reason = 'Calling'
+#               self.interaction(frame, None)
+
+    def user_line(self, frame):
+        # This function is called when we stop or break at this line
+        self.reason = 'Stopped'
+        self.interaction(frame, None)
+
+    def user_return(self, frame, return_value):
+        # This function is called when a return trap is set here
+        fname = frame.f_code.co_name
+        if fname <> '?':
+            self.reason = 'Returning from %s()' % frame.f_code.co_name
+            frame.f_locals['__return__'] = return_value
+        elif frame.f_back is self.botframe:
+            self.reason = 'Done'
+        else:
+            self.reason = 'Returning'
+        self.interaction(frame, None, 1)
+
+    def user_exception(self, frame, (exc_type, exc_value, exc_traceback)):
+        # This function is called when we stop or break at this line
+        self.reason = self.formatexception(exc_type, exc_value)
+        self.interaction(frame, exc_traceback)
+
+    def formatexception(self, exc_type, exc_value):
+        if exc_type == SyntaxError:
+            try:
+                value, (filename, lineno, charno, line) = exc_value
+            except:
+                pass
+            else:
+                return str(exc_type) + ': ' + str(value)
+        if type(exc_type) == types.ClassType:
+            nice = exc_type.__name__
+        else:
+            nice = str(exc_type)
+        value = str(exc_value)
+        if exc_value and value:
+            nice = nice + ": " + value
+        return nice
+
+    def forget(self):
+        self.stack = []
+        self.curindex = 0
+        self.curframe = None
+
+    def setup(self, f, t, isreturning = 0):
+        self.forget()
+        self.stack, self.curindex = self.get_stack(f, t)
+        self.curframe = self.stack[self.curindex - isreturning][0]
+
+    def interaction(self, frame, traceback, isreturning = 0):
+        saveport = Qd.GetPort()
+        self.w.select()
+        try:
+            self.setup(frame, traceback, isreturning)
+            self.setstate('stopped')
+            stackindex = self.curindex
+            if isreturning:
+                if frame.f_back is not self.botframe:
+                    stackindex = stackindex - 1
+            self.showstack(stackindex)
+            self.showframe(stackindex)
+            self.w.parent.debugger_mainloop()
+            self.forget()
+        finally:
+            Qd.SetPort(saveport)
+
+    # bdb customization
+
+    def trace_dispatch(self, frame, event, arg, TickCount = Evt.TickCount):
+        if TickCount() - self.tracingmonitortime > 15:
+            self.tracingmonitortime = TickCount()
+            self.w.panes.bottom.tracingmonitor.toggle()
+        try:
+            try:
+                if hasattr(MacOS, 'EnableAppswitch'):
+                    MacOS.EnableAppswitch(0)
+                if self.quitting:
+                    # returning None is not enough, a former BdbQuit exception
+                    # might have been eaten by the print statement
+                    raise bdb.BdbQuit
+                if event == 'line':
+                    return self.dispatch_line(frame)
+                if event == 'call':
+                    return self.dispatch_call(frame, arg)
+                if event == 'return':
+                    return self.dispatch_return(frame, arg)
+                if event == 'exception':
+                    return self.dispatch_exception(frame, arg)
+                print 'bdb.Bdb.dispatch: unknown debugging event:', repr(event)
+                return self.trace_dispatch
+            finally:
+                if hasattr(MacOS, 'EnableAppswitch'):
+                    MacOS.EnableAppswitch(-1)
+        except KeyboardInterrupt:
+            self.set_step()
+            return self.trace_dispatch
+        except bdb.BdbQuit:
+            if self.continuewithoutdebugger:
+                self.clear_tracefuncs()
+                return
+            else:
+                raise bdb.BdbQuit
+        except:
+            print 'XXX Exception during debugger interaction.', \
+                            self.formatexception(sys.exc_type, sys.exc_value)
+            import traceback
+            traceback.print_exc()
+            return self.trace_dispatch
+
+    def dispatch_call(self, frame, arg):
+        if not self.tracemagic and \
+                        frame.f_code.co_name[:2] == '__' == frame.f_code.co_name[-2:] and \
+                        frame.f_code.co_name <> '__init__':
+            return
+        if self.botframe is None:
+            # First call of dispatch since reset()
+            self.botframe = frame.f_back    # xxx !!! added f_back
+            return self.trace_dispatch
+        if not (self.stop_here(frame) or self.break_anywhere(frame)):
+            # No need to trace this function
+            return # None
+        self.user_call(frame, arg)
+        if self.quitting:
+            raise bdb.BdbQuit
+        return self.trace_dispatch
+
+    def set_continue(self):
+        # Don't stop except at breakpoints or when finished
+        self.stopframe = self.botframe
+        self.returnframe = None
+        self.quitting = 0
+        # unlike in bdb/pdb, there's a chance that breakpoints change
+        # *while* a program (this program ;-) is running. It's actually quite likely.
+        # So we don't delete frame.f_trace until the bottom frame if there are no breakpoints.
+
+    def set_break(self, filename, lineno):
+        if not self.breaks.has_key(filename):
+            self.breaks[filename] = []
+        list = self.breaks[filename]
+        if lineno in list:
+            return 'There is already a breakpoint there!'
+        list.append(lineno)
+        list.sort()     # I want to keep them neatly sorted; easier for drawing
+        if hasattr(bdb, "Breakpoint"):
+            # 1.5.2b1 specific
+            bp = bdb.Breakpoint(filename, lineno, 0, None)
+        self.update_breaks(filename)
+
+    def clear_break(self, filename, lineno):
+        bdb.Bdb.clear_break(self, filename, lineno)
+        self.update_breaks(filename)
+
+    def clear_all_file_breaks(self, filename):
+        bdb.Bdb.clear_all_file_breaks(self, filename)
+        self.update_breaks(filename)
+
+    def clear_all_breaks(self):
+        bdb.Bdb.clear_all_breaks(self)
+        for editors in self.editors.values():
+            for editor in editors:
+                editor.drawbreakpoints()
+
+    # special
+
+    def toggle_break(self, filename, lineno):
+        if self.get_break(filename, lineno):
+            self.clear_break(filename, lineno)
+        else:
+            self.set_break(filename, lineno)
+
+    def clear_breaks_above(self, filename, above):
+        if not self.breaks.has_key(filename):
+            return 'There are no breakpoints in that file!'
+        for lineno in self.breaks[filename][:]:
+            if lineno > above:
+                self.breaks[filename].remove(lineno)
+        if not self.breaks[filename]:
+            del self.breaks[filename]
+
+    # editor stuff
+
+    def update_breaks(self, filename):
+        if self.breaksviewer:
+            self.breaksviewer.update()
+        if self.editors.has_key(filename):
+            for editor in self.editors[filename]:
+                if editor._debugger:    # XXX
+                    editor.drawbreakpoints()
+                else:
+                    print 'xxx dead editor!'
+
+    def update_allbreaks(self):
+        if self.breaksviewer:
+            self.breaksviewer.update()
+        for filename in self.breaks.keys():
+            if self.editors.has_key(filename):
+                for editor in self.editors[filename]:
+                    if editor._debugger:    # XXX
+                        editor.drawbreakpoints()
+                    else:
+                        print 'xxx dead editor!'
+
+    def register_editor(self, editor, filename):
+        if not filename:
+            return
+        if not self.editors.has_key(filename):
+            self.editors[filename] = [editor]
+        elif editor not in self.editors[filename]:
+            self.editors[filename].append(editor)
+
+    def unregister_editor(self, editor, filename):
+        if not filename:
+            return
+        try:
+            self.editors[filename].remove(editor)
+            if not self.editors[filename]:
+                del self.editors[filename]
+                # if this was an untitled window, clear the breaks.
+                if filename[:1] == '<' and filename[-1:] == '>' and \
+                                self.breaks.has_key(filename):
+                    self.clear_all_file_breaks(filename)
+        except (KeyError, ValueError):
+            pass
+
 
 class SourceViewer(W.PyEditor):
-	
-	def __init__(self, *args, **kwargs):
-		apply(W.PyEditor.__init__, (self,) + args, kwargs)
-		self.bind('<click>', self.clickintercept)
-	
-	def clickintercept(self, point, modifiers):
-		if self._parentwindow._currentwidget <> self and not self.pt_in_breaks(point):
-			self._parentwindow.xxx___select(self)
-			return 1
-	
-	def _getviewrect(self):
-		l, t, r, b = self._bounds
-		if self._debugger:
-			return (l + 12, t + 2, r - 1, b - 2)
-		else:
-			return (l + 5, t + 2, r - 1, b - 2)
-	
-	def select(self, onoff, isclick = 0):
-		if W.SelectableWidget.select(self, onoff):
-			return
-		self.SetPort()
-		#if onoff:
-		#	self.ted.WEActivate()
-		#else:
-		#	self.ted.WEDeactivate()
-		self.drawselframe(onoff)
-	
-	def drawselframe(self, onoff):
-		pass
+
+    def __init__(self, *args, **kwargs):
+        apply(W.PyEditor.__init__, (self,) + args, kwargs)
+        self.bind('<click>', self.clickintercept)
+
+    def clickintercept(self, point, modifiers):
+        if self._parentwindow._currentwidget <> self and not self.pt_in_breaks(point):
+            self._parentwindow.xxx___select(self)
+            return 1
+
+    def _getviewrect(self):
+        l, t, r, b = self._bounds
+        if self._debugger:
+            return (l + 12, t + 2, r - 1, b - 2)
+        else:
+            return (l + 5, t + 2, r - 1, b - 2)
+
+    def select(self, onoff, isclick = 0):
+        if W.SelectableWidget.select(self, onoff):
+            return
+        self.SetPort()
+        #if onoff:
+        #       self.ted.WEActivate()
+        #else:
+        #       self.ted.WEDeactivate()
+        self.drawselframe(onoff)
+
+    def drawselframe(self, onoff):
+        pass
 
 
 class BreakpointsViewer:
-	
-	def __init__(self, debugger):
-		self.debugger = debugger
-		self.w = W.Window((300, 250), 'Breakpoints', minsize = (200, 200))
-		self.w.panes = W.HorizontalPanes((8, 8, -8, -32), (0.3, 0.7))
-		self.w.panes.files = W.List(None, callback = self.filehit)		#, flags = Lists.lOnlyOne)
-		self.w.panes.gr = W.Group(None)
-		self.w.panes.gr.breaks = W.List((0, 0, -130, 0), callback = self.linehit)	#, flags = Lists.lOnlyOne)
-		self.w.panes.gr.openbutton = W.Button((-80, 4, 0, 16), 'View\xc9', self.openbuttonhit)
-		self.w.panes.gr.deletebutton = W.Button((-80, 28, 0, 16), 'Delete', self.deletebuttonhit)
-		
-		self.w.bind('<close>', self.close)
-		self.w.bind('backspace', self.w.panes.gr.deletebutton.push)
-		
-		self.setup()
-		self.w.open()
-		self.w.panes.gr.openbutton.enable(0)
-		self.w.panes.gr.deletebutton.enable(0)
-		self.curfile = None
-	
-	def deletebuttonhit(self):
-		if self.w._currentwidget == self.w.panes.files:
-			self.del_filename()
-		else:
-			self.del_number()
-		self.checkbuttons()
-	
-	def del_number(self):
-		if self.curfile is None:
-			return
-		sel = self.w.panes.gr.breaks.getselectedobjects()
-		for lineno in sel:
-			self.debugger.clear_break(self.curfile, lineno)
-	
-	def del_filename(self):
-		sel = self.w.panes.files.getselectedobjects()
-		for filename in sel:
-			self.debugger.clear_all_file_breaks(filename)
-		self.debugger.update_allbreaks()
-	
-	def setup(self):
-		files = self.debugger.breaks.keys()
-		files.sort()
-		self.w.panes.files.set(files)
-	
-	def close(self):
-		self.debugger.breaksviewer = None
-		self.debugger = None
-	
-	def update(self):
-		sel = self.w.panes.files.getselectedobjects()
-		self.setup()
-		self.w.panes.files.setselectedobjects(sel)
-		sel = self.w.panes.files.getselection()
-		if len(sel) == 0 and self.curfile:
-			self.w.panes.files.setselectedobjects([self.curfile])
-		self.filehit(0)
-	
-	def select(self):
-		self.w.select()
-	
-	def selectfile(self, file):
-		self.w.panes.files.setselectedobjects([file])
-		self.filehit(0)			
-	
-	def openbuttonhit(self):
-		self.filehit(1)
-	
-	def filehit(self, isdbl):
-		sel = self.w.panes.files.getselectedobjects()
-		if isdbl:
-			for filename in sel:
-				lineno = None
-				if filename == self.curfile:
-					linesel = self.w.panes.gr.breaks.getselectedobjects()
-					if linesel:
-						lineno = linesel[-1]
-					elif self.w.panes.gr.breaks:
-						lineno = self.w.panes.gr.breaks[0]
-				editor = self.w._parentwindow.parent.openscript(filename, lineno)
-				editor.showbreakpoints(1)
-			return
-		if len(sel) == 1:
-			file = sel[0]
-			filebreaks = self.debugger.breaks[file][:]
-			if self.curfile == file:
-				linesel = self.w.panes.gr.breaks.getselectedobjects()
-			self.w.panes.gr.breaks.set(filebreaks)
-			if self.curfile == file:
-				self.w.panes.gr.breaks.setselectedobjects(linesel)
-			self.curfile = file
-		else:
-			if len(sel) <> 0:
-				self.curfile = None
-			self.w.panes.gr.breaks.set([])
-		self.checkbuttons()
-	
-	def linehit(self, isdbl):
-		if isdbl:
-			files = self.w.panes.files.getselectedobjects()
-			if len(files) <> 1:
-				return
-			filename = files[0]
-			linenos = self.w.panes.gr.breaks.getselectedobjects()
-			if not linenos:
-				return
-			lineno = linenos[-1]
-			editor = self.w._parentwindow.parent.openscript(filename, lineno)
-			editor.showbreakpoints(1)
-		self.checkbuttons()
-	
-	def checkbuttons(self):
-		if self.w.panes.files.getselection():
-			self.w.panes.gr.openbutton.enable(1)
-			self.w._parentwindow.setdefaultbutton(self.w.panes.gr.openbutton)
-			if self.w._currentwidget == self.w.panes.files:
-				if self.w.panes.files.getselection():
-					self.w.panes.gr.deletebutton.enable(1)
-				else:
-					self.w.panes.gr.deletebutton.enable(0)
-			else:
-				if self.w.panes.gr.breaks.getselection():
-					self.w.panes.gr.deletebutton.enable(1)
-				else:
-					self.w.panes.gr.deletebutton.enable(0)
-		else:
-			self.w.panes.gr.openbutton.enable(0)
-			self.w.panes.gr.deletebutton.enable(0)
+
+    def __init__(self, debugger):
+        self.debugger = debugger
+        self.w = W.Window((300, 250), 'Breakpoints', minsize = (200, 200))
+        self.w.panes = W.HorizontalPanes((8, 8, -8, -32), (0.3, 0.7))
+        self.w.panes.files = W.List(None, callback = self.filehit)              #, flags = Lists.lOnlyOne)
+        self.w.panes.gr = W.Group(None)
+        self.w.panes.gr.breaks = W.List((0, 0, -130, 0), callback = self.linehit)       #, flags = Lists.lOnlyOne)
+        self.w.panes.gr.openbutton = W.Button((-80, 4, 0, 16), 'View\xc9', self.openbuttonhit)
+        self.w.panes.gr.deletebutton = W.Button((-80, 28, 0, 16), 'Delete', self.deletebuttonhit)
+
+        self.w.bind('<close>', self.close)
+        self.w.bind('backspace', self.w.panes.gr.deletebutton.push)
+
+        self.setup()
+        self.w.open()
+        self.w.panes.gr.openbutton.enable(0)
+        self.w.panes.gr.deletebutton.enable(0)
+        self.curfile = None
+
+    def deletebuttonhit(self):
+        if self.w._currentwidget == self.w.panes.files:
+            self.del_filename()
+        else:
+            self.del_number()
+        self.checkbuttons()
+
+    def del_number(self):
+        if self.curfile is None:
+            return
+        sel = self.w.panes.gr.breaks.getselectedobjects()
+        for lineno in sel:
+            self.debugger.clear_break(self.curfile, lineno)
+
+    def del_filename(self):
+        sel = self.w.panes.files.getselectedobjects()
+        for filename in sel:
+            self.debugger.clear_all_file_breaks(filename)
+        self.debugger.update_allbreaks()
+
+    def setup(self):
+        files = self.debugger.breaks.keys()
+        files.sort()
+        self.w.panes.files.set(files)
+
+    def close(self):
+        self.debugger.breaksviewer = None
+        self.debugger = None
+
+    def update(self):
+        sel = self.w.panes.files.getselectedobjects()
+        self.setup()
+        self.w.panes.files.setselectedobjects(sel)
+        sel = self.w.panes.files.getselection()
+        if len(sel) == 0 and self.curfile:
+            self.w.panes.files.setselectedobjects([self.curfile])
+        self.filehit(0)
+
+    def select(self):
+        self.w.select()
+
+    def selectfile(self, file):
+        self.w.panes.files.setselectedobjects([file])
+        self.filehit(0)
+
+    def openbuttonhit(self):
+        self.filehit(1)
+
+    def filehit(self, isdbl):
+        sel = self.w.panes.files.getselectedobjects()
+        if isdbl:
+            for filename in sel:
+                lineno = None
+                if filename == self.curfile:
+                    linesel = self.w.panes.gr.breaks.getselectedobjects()
+                    if linesel:
+                        lineno = linesel[-1]
+                    elif self.w.panes.gr.breaks:
+                        lineno = self.w.panes.gr.breaks[0]
+                editor = self.w._parentwindow.parent.openscript(filename, lineno)
+                editor.showbreakpoints(1)
+            return
+        if len(sel) == 1:
+            file = sel[0]
+            filebreaks = self.debugger.breaks[file][:]
+            if self.curfile == file:
+                linesel = self.w.panes.gr.breaks.getselectedobjects()
+            self.w.panes.gr.breaks.set(filebreaks)
+            if self.curfile == file:
+                self.w.panes.gr.breaks.setselectedobjects(linesel)
+            self.curfile = file
+        else:
+            if len(sel) <> 0:
+                self.curfile = None
+            self.w.panes.gr.breaks.set([])
+        self.checkbuttons()
+
+    def linehit(self, isdbl):
+        if isdbl:
+            files = self.w.panes.files.getselectedobjects()
+            if len(files) <> 1:
+                return
+            filename = files[0]
+            linenos = self.w.panes.gr.breaks.getselectedobjects()
+            if not linenos:
+                return
+            lineno = linenos[-1]
+            editor = self.w._parentwindow.parent.openscript(filename, lineno)
+            editor.showbreakpoints(1)
+        self.checkbuttons()
+
+    def checkbuttons(self):
+        if self.w.panes.files.getselection():
+            self.w.panes.gr.openbutton.enable(1)
+            self.w._parentwindow.setdefaultbutton(self.w.panes.gr.openbutton)
+            if self.w._currentwidget == self.w.panes.files:
+                if self.w.panes.files.getselection():
+                    self.w.panes.gr.deletebutton.enable(1)
+                else:
+                    self.w.panes.gr.deletebutton.enable(0)
+            else:
+                if self.w.panes.gr.breaks.getselection():
+                    self.w.panes.gr.deletebutton.enable(1)
+                else:
+                    self.w.panes.gr.deletebutton.enable(0)
+        else:
+            self.w.panes.gr.openbutton.enable(0)
+            self.w.panes.gr.deletebutton.enable(0)
 
 
 class TracingMonitor(W.Widget):
-	
-	def __init__(self, *args, **kwargs):
-		apply(W.Widget.__init__, (self,) + args, kwargs)
-		self.state = 0
-	
-	def toggle(self):
-		if hasattr(self, "_parentwindow") and self._parentwindow is not None:
-			self.state = self.state % 2 + 1
-			port = Qd.GetPort()
-			self.SetPort()
-			self.draw()
-			Qd.SetPort(port)
-	
-	def reset(self):
-		if self._parentwindow:
-			self.state = 0
-			port = Qd.GetPort()
-			self.SetPort()
-			self.draw()
-			Qd.SetPort(port)
-	
-	def draw(self, visRgn = None):
-		if self.state == 2:
-			Qd.PaintOval(self._bounds)
-		else:
-			Qd.EraseOval(self._bounds)
+
+    def __init__(self, *args, **kwargs):
+        apply(W.Widget.__init__, (self,) + args, kwargs)
+        self.state = 0
+
+    def toggle(self):
+        if hasattr(self, "_parentwindow") and self._parentwindow is not None:
+            self.state = self.state % 2 + 1
+            port = Qd.GetPort()
+            self.SetPort()
+            self.draw()
+            Qd.SetPort(port)
+
+    def reset(self):
+        if self._parentwindow:
+            self.state = 0
+            port = Qd.GetPort()
+            self.SetPort()
+            self.draw()
+            Qd.SetPort(port)
+
+    def draw(self, visRgn = None):
+        if self.state == 2:
+            Qd.PaintOval(self._bounds)
+        else:
+            Qd.EraseOval(self._bounds)
 
 
 # convenience funcs
 
 def postmortem(exc_type, exc_value, tb):
-	d = getdebugger()
-	d.postmortem(exc_type, exc_value, tb)
+    d = getdebugger()
+    d.postmortem(exc_type, exc_value, tb)
 
 def start(bottomframe = None):
-	d = getdebugger()
-	d.start(bottomframe)
+    d = getdebugger()
+    d.start(bottomframe)
 
 def startfromhere():
-	d = getdebugger()
-	try:
-		raise 'spam'
-	except:
-		frame = sys.exc_traceback.tb_frame.f_back
-	d.start(frame)
+    d = getdebugger()
+    try:
+        raise 'spam'
+    except:
+        frame = sys.exc_traceback.tb_frame.f_back
+    d.start(frame)
 
 def startfrombottom():
-	d = getdebugger()
-	d.start(_getbottomframe(), 1)
+    d = getdebugger()
+    d.start(_getbottomframe(), 1)
 
 def stop():
-	d = getdebugger()
-	d.stop()
+    d = getdebugger()
+    d.stop()
 
 def cont():
-	sys.settrace(None)
-	d = getdebugger()
-	d.set_continue_without_debugger()
+    sys.settrace(None)
+    d = getdebugger()
+    d.set_continue_without_debugger()
 
 def _getbottomframe():
-	try:
-		raise 'spam'
-	except:
-		pass
-	frame = sys.exc_traceback.tb_frame
-	while 1:
-		if frame.f_code.co_name == 'mainloop' or frame.f_back is None:
-			break
-		frame = frame.f_back
-	return frame
+    try:
+        raise 'spam'
+    except:
+        pass
+    frame = sys.exc_traceback.tb_frame
+    while 1:
+        if frame.f_code.co_name == 'mainloop' or frame.f_back is None:
+            break
+        frame = frame.f_back
+    return frame
 
 _debugger = None
 
 def getdebugger():
-	if not __debug__:
-		raise W.AlertError, "Can't debug in \"Optimize bytecode\" mode.\r(see \"Default startup options\" in EditPythonPreferences)"
-	global _debugger
-	if _debugger is None:
-		_debugger = Debugger()
-	return _debugger
+    if not __debug__:
+        raise W.AlertError, "Can't debug in \"Optimize bytecode\" mode.\r(see \"Default startup options\" in EditPythonPreferences)"
+    global _debugger
+    if _debugger is None:
+        _debugger = Debugger()
+    return _debugger
diff --git a/Mac/Tools/IDE/PyDocSearch.py b/Mac/Tools/IDE/PyDocSearch.py
index 1abd4cd..ec666b6 100644
--- a/Mac/Tools/IDE/PyDocSearch.py
+++ b/Mac/Tools/IDE/PyDocSearch.py
@@ -13,244 +13,244 @@
 _titlepat = re.compile('<title>\([^<]*\)</title>')
 
 def sucktitle(path):
-	f = open(path)
-	text = f.read(1024) # assume the title is in the first 1024 bytes
-	f.close()
-	lowertext = text.lower()
-	matcher = _titlepat.search(lowertext)
-	if matcher:
-		return matcher.group(1)
-	return path
+    f = open(path)
+    text = f.read(1024) # assume the title is in the first 1024 bytes
+    f.close()
+    lowertext = text.lower()
+    matcher = _titlepat.search(lowertext)
+    if matcher:
+        return matcher.group(1)
+    return path
 
 def verifydocpath(docpath):
-	try:
-		tut = os.path.join(docpath, "tut")
-		lib = os.path.join(docpath, "lib")
-		ref = os.path.join(docpath, "ref")
-		for path in [tut, lib, ref]:
-			if not os.path.exists(path):
-				return 0
-	except:
-		return 0
-	return 1
+    try:
+        tut = os.path.join(docpath, "tut")
+        lib = os.path.join(docpath, "lib")
+        ref = os.path.join(docpath, "ref")
+        for path in [tut, lib, ref]:
+            if not os.path.exists(path):
+                return 0
+    except:
+        return 0
+    return 1
 
 
 _resultscounter = 1
 
 class Results:
-	
-	def __init__(self, hits):
-		global _resultscounter
-		hits = map(lambda (path, hits): (sucktitle(path), path, hits), hits)
-		hits.sort()
-		self.hits = hits
-		nicehits = map(
-				lambda (title, path, hits):
-				title + '\r' + string.join(
-				map(lambda (c, p): "%s (%d)" % (p, c), hits), ', '), hits)
-		nicehits.sort()
-		self.w = W.Window((440, 300), "Search results %d" % _resultscounter, minsize = (200, 100))
-		self.w.results = W.TwoLineList((-1, -1, 1, -14), nicehits, self.listhit)
-		self.w.open()
-		self.w.bind('return', self.listhit)
-		self.w.bind('enter', self.listhit)
-		_resultscounter = _resultscounter + 1
-	
-	def listhit(self, isdbl = 1):
-		if isdbl:
-			for i in self.w.results.getselection():
-				path = self.hits[i][1]
-				url = "file://" + "/".join(path.split(":"))
-				webbrowser.open(url)
+
+    def __init__(self, hits):
+        global _resultscounter
+        hits = map(lambda (path, hits): (sucktitle(path), path, hits), hits)
+        hits.sort()
+        self.hits = hits
+        nicehits = map(
+                        lambda (title, path, hits):
+                        title + '\r' + string.join(
+                        map(lambda (c, p): "%s (%d)" % (p, c), hits), ', '), hits)
+        nicehits.sort()
+        self.w = W.Window((440, 300), "Search results %d" % _resultscounter, minsize = (200, 100))
+        self.w.results = W.TwoLineList((-1, -1, 1, -14), nicehits, self.listhit)
+        self.w.open()
+        self.w.bind('return', self.listhit)
+        self.w.bind('enter', self.listhit)
+        _resultscounter = _resultscounter + 1
+
+    def listhit(self, isdbl = 1):
+        if isdbl:
+            for i in self.w.results.getselection():
+                path = self.hits[i][1]
+                url = "file://" + "/".join(path.split(":"))
+                webbrowser.open(url)
 
 
 class Status:
-	
-	def __init__(self):
-		self.w = W.Dialog((440, 64), "Searching\xc9")
-		self.w.searching = W.TextBox((4, 4, -4, 16), "")
-		self.w.hits = W.TextBox((4, 24, -4, 16), "Hits: 0")
-		self.w.canceltip = W.TextBox((4, 44, -4, 16), "Type cmd-period (.) to cancel.")
-		self.w.open()
-	
-	def set(self, path, hits):
-		self.w.searching.set(path)
-		self.w.hits.set('Hits: %r' % (hits,))
-		app.breathe()
-	
-	def close(self):
-		self.w.close()
+
+    def __init__(self):
+        self.w = W.Dialog((440, 64), "Searching\xc9")
+        self.w.searching = W.TextBox((4, 4, -4, 16), "")
+        self.w.hits = W.TextBox((4, 24, -4, 16), "Hits: 0")
+        self.w.canceltip = W.TextBox((4, 44, -4, 16), "Type cmd-period (.) to cancel.")
+        self.w.open()
+
+    def set(self, path, hits):
+        self.w.searching.set(path)
+        self.w.hits.set('Hits: %r' % (hits,))
+        app.breathe()
+
+    def close(self):
+        self.w.close()
 
 
 def match(text, patterns, all):
-	hits = []
-	hitsappend = hits.append
-	stringcount = string.count
-	for pat in patterns:
-		c = stringcount(text, pat)
-		if c > 0:
-			hitsappend((c, pat))
-		elif all:
-			hits[:] = []
-			break
-	hits.sort()
-	hits.reverse()
-	return hits
+    hits = []
+    hitsappend = hits.append
+    stringcount = string.count
+    for pat in patterns:
+        c = stringcount(text, pat)
+        if c > 0:
+            hitsappend((c, pat))
+        elif all:
+            hits[:] = []
+            break
+    hits.sort()
+    hits.reverse()
+    return hits
 
 
 def dosearch(docpath, searchstring, settings):
-	(docpath, kind, case, word, tut, lib, ref, ext, api) = settings
-	books = [(tut, 'tut'), (lib, 'lib'), (ref, 'ref'), (ext, 'ext'), (api, 'api')]
-	if not case:
-		searchstring = string.lower(searchstring)
-	
-	if kind == 1:
-		patterns = string.split(searchstring)
-		all = 1
-	elif kind == 2:
-		patterns = string.split(searchstring)
-		all = 0
-	else:
-		patterns = [searchstring]
-		all = 0 # not relevant
-	
-	ospathjoin = os.path.join
-	stringlower = string.lower
-	status = Status()
-	statusset = status.set
-	_match = match
-	_open = open
-	hits = {}
-	try:
-		if hasattr(MacOS, 'EnableAppswitch'):
-			MacOS.EnableAppswitch(0)
-		try:
-			for do, name in books:
-				if not do:
-					continue
-				bookpath = ospathjoin(docpath, name)
-				if not os.path.exists(bookpath):
-					continue
-				files = os.listdir(bookpath)
-				for file in files:
-					fullpath = ospathjoin(bookpath, file)
-					if fullpath[-5:] <> '.html':
-						continue
-					statusset(fullpath, len(hits))
-					f = _open(fullpath)
-					text = f.read()
-					if not case:
-						text = stringlower(text)
-					f.close()
-					filehits = _match(text, patterns, all)
-					if filehits:
-						hits[fullpath] = filehits
-		finally:
-			if hasattr(MacOS, 'EnableAppswitch'):
-				MacOS.EnableAppswitch(-1)
-			status.close()
-	except KeyboardInterrupt:
-		pass
-	hits = hits.items()
-	hits.sort()
-	return hits
+    (docpath, kind, case, word, tut, lib, ref, ext, api) = settings
+    books = [(tut, 'tut'), (lib, 'lib'), (ref, 'ref'), (ext, 'ext'), (api, 'api')]
+    if not case:
+        searchstring = string.lower(searchstring)
+
+    if kind == 1:
+        patterns = string.split(searchstring)
+        all = 1
+    elif kind == 2:
+        patterns = string.split(searchstring)
+        all = 0
+    else:
+        patterns = [searchstring]
+        all = 0 # not relevant
+
+    ospathjoin = os.path.join
+    stringlower = string.lower
+    status = Status()
+    statusset = status.set
+    _match = match
+    _open = open
+    hits = {}
+    try:
+        if hasattr(MacOS, 'EnableAppswitch'):
+            MacOS.EnableAppswitch(0)
+        try:
+            for do, name in books:
+                if not do:
+                    continue
+                bookpath = ospathjoin(docpath, name)
+                if not os.path.exists(bookpath):
+                    continue
+                files = os.listdir(bookpath)
+                for file in files:
+                    fullpath = ospathjoin(bookpath, file)
+                    if fullpath[-5:] <> '.html':
+                        continue
+                    statusset(fullpath, len(hits))
+                    f = _open(fullpath)
+                    text = f.read()
+                    if not case:
+                        text = stringlower(text)
+                    f.close()
+                    filehits = _match(text, patterns, all)
+                    if filehits:
+                        hits[fullpath] = filehits
+        finally:
+            if hasattr(MacOS, 'EnableAppswitch'):
+                MacOS.EnableAppswitch(-1)
+            status.close()
+    except KeyboardInterrupt:
+        pass
+    hits = hits.items()
+    hits.sort()
+    return hits
 
 
 class PyDocSearch:
-	
-	def __init__(self):
-		prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
-		try:
-			(docpath, kind, case, word, tut, lib, ref, ext, api) = prefs.docsearchengine
-		except:
-			(docpath, kind, case, word, tut, lib, ref, ext, api) = prefs.docsearchengine = \
-				("", 0, 0, 0, 1, 1, 0, 0, 0)
-		
-		if docpath and not verifydocpath(docpath):
-			docpath = ""
-		
-		self.w = W.Window((400, 200), "Search the Python Documentation")
-		self.w.searchtext = W.EditText((10, 10, -100, 20), callback = self.checkbuttons)
-		self.w.searchbutton = W.Button((-90, 12, 80, 16), "Search", self.search)
-		buttons = []
-		
-		gutter = 10
-		width = 130
-		bookstart = width + 2 * gutter
-		self.w.phraseradio = W.RadioButton((10, 38, width, 16), "As a phrase", buttons)
-		self.w.allwordsradio = W.RadioButton((10, 58, width, 16), "All words", buttons)
-		self.w.anywordsradio = W.RadioButton((10, 78, width, 16), "Any word", buttons)
-		self.w.casesens = W.CheckBox((10, 98, width, 16), "Case sensitive")
-		self.w.wholewords = W.CheckBox((10, 118, width, 16), "Whole words")
-		self.w.tutorial = W.CheckBox((bookstart, 38, -10, 16), "Tutorial")
-		self.w.library = W.CheckBox((bookstart, 58, -10, 16), "Library reference")
-		self.w.langueref = W.CheckBox((bookstart, 78, -10, 16), "Lanuage reference manual")
-		self.w.extending = W.CheckBox((bookstart, 98, -10, 16), "Extending & embedding")
-		self.w.api = W.CheckBox((bookstart, 118, -10, 16), "C/C++ API")
-		
-		self.w.setdocfolderbutton = W.Button((10, -30, 100, 16), "Set doc folder", self.setdocpath)
-		
-		if docpath:
-			self.w.setdefaultbutton(self.w.searchbutton)
-		else:
-			self.w.setdefaultbutton(self.w.setdocfolderbutton)
-		
-		self.docpath = docpath
-		if not docpath:
-			docpath = "(please select the Python html documentation folder)"
-		self.w.docfolder = W.TextBox((120, -28, -10, 16), docpath)
-		
-		[self.w.phraseradio, self.w.allwordsradio, self.w.anywordsradio][kind].set(1)
-		
-		self.w.casesens.set(case)
-		self.w.wholewords.set(word)
-		self.w.tutorial.set(tut)
-		self.w.library.set(lib)
-		self.w.langueref.set(ref)
-		self.w.extending.set(ext)
-		self.w.api.set(api)
-		
-		self.w.open()
-		self.w.wholewords.enable(0)
-		self.w.bind('<close>', self.close)
-		self.w.searchbutton.enable(0)
-	
-	def search(self):
-		hits = dosearch(self.docpath, self.w.searchtext.get(), self.getsettings())
-		if hits:
-			Results(hits)
-		elif hasattr(MacOS, 'SysBeep'):
-			MacOS.SysBeep(0)
-	
-	def setdocpath(self):
-		docpath = EasyDialogs.AskFolder()
-		if docpath:
-			if not verifydocpath(docpath):
-				W.Message("This does not seem to be a Python documentation folder...")
-			else:
-				self.docpath = docpath
-				self.w.docfolder.set(docpath)
-				self.w.setdefaultbutton(self.w.searchbutton)
-	
-	def close(self):
-		prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
-		prefs.docsearchengine = self.getsettings()
-	
-	def getsettings(self):
-		radiobuttons = [self.w.phraseradio, self.w.allwordsradio, self.w.anywordsradio]
-		for i in range(3):
-			if radiobuttons[i].get():
-				kind = i
-				break
-		docpath = self.docpath
-		case = self.w.casesens.get()
-		word = self.w.wholewords.get()
-		tut = self.w.tutorial.get()
-		lib = self.w.library.get()
-		ref = self.w.langueref.get()
-		ext = self.w.extending.get()
-		api = self.w.api.get()
-		return (docpath, kind, case, word, tut, lib, ref, ext, api)
-	
-	def checkbuttons(self):
-		self.w.searchbutton.enable(not not self.w.searchtext.get())
+
+    def __init__(self):
+        prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
+        try:
+            (docpath, kind, case, word, tut, lib, ref, ext, api) = prefs.docsearchengine
+        except:
+            (docpath, kind, case, word, tut, lib, ref, ext, api) = prefs.docsearchengine = \
+                    ("", 0, 0, 0, 1, 1, 0, 0, 0)
+
+        if docpath and not verifydocpath(docpath):
+            docpath = ""
+
+        self.w = W.Window((400, 200), "Search the Python Documentation")
+        self.w.searchtext = W.EditText((10, 10, -100, 20), callback = self.checkbuttons)
+        self.w.searchbutton = W.Button((-90, 12, 80, 16), "Search", self.search)
+        buttons = []
+
+        gutter = 10
+        width = 130
+        bookstart = width + 2 * gutter
+        self.w.phraseradio = W.RadioButton((10, 38, width, 16), "As a phrase", buttons)
+        self.w.allwordsradio = W.RadioButton((10, 58, width, 16), "All words", buttons)
+        self.w.anywordsradio = W.RadioButton((10, 78, width, 16), "Any word", buttons)
+        self.w.casesens = W.CheckBox((10, 98, width, 16), "Case sensitive")
+        self.w.wholewords = W.CheckBox((10, 118, width, 16), "Whole words")
+        self.w.tutorial = W.CheckBox((bookstart, 38, -10, 16), "Tutorial")
+        self.w.library = W.CheckBox((bookstart, 58, -10, 16), "Library reference")
+        self.w.langueref = W.CheckBox((bookstart, 78, -10, 16), "Lanuage reference manual")
+        self.w.extending = W.CheckBox((bookstart, 98, -10, 16), "Extending & embedding")
+        self.w.api = W.CheckBox((bookstart, 118, -10, 16), "C/C++ API")
+
+        self.w.setdocfolderbutton = W.Button((10, -30, 100, 16), "Set doc folder", self.setdocpath)
+
+        if docpath:
+            self.w.setdefaultbutton(self.w.searchbutton)
+        else:
+            self.w.setdefaultbutton(self.w.setdocfolderbutton)
+
+        self.docpath = docpath
+        if not docpath:
+            docpath = "(please select the Python html documentation folder)"
+        self.w.docfolder = W.TextBox((120, -28, -10, 16), docpath)
+
+        [self.w.phraseradio, self.w.allwordsradio, self.w.anywordsradio][kind].set(1)
+
+        self.w.casesens.set(case)
+        self.w.wholewords.set(word)
+        self.w.tutorial.set(tut)
+        self.w.library.set(lib)
+        self.w.langueref.set(ref)
+        self.w.extending.set(ext)
+        self.w.api.set(api)
+
+        self.w.open()
+        self.w.wholewords.enable(0)
+        self.w.bind('<close>', self.close)
+        self.w.searchbutton.enable(0)
+
+    def search(self):
+        hits = dosearch(self.docpath, self.w.searchtext.get(), self.getsettings())
+        if hits:
+            Results(hits)
+        elif hasattr(MacOS, 'SysBeep'):
+            MacOS.SysBeep(0)
+
+    def setdocpath(self):
+        docpath = EasyDialogs.AskFolder()
+        if docpath:
+            if not verifydocpath(docpath):
+                W.Message("This does not seem to be a Python documentation folder...")
+            else:
+                self.docpath = docpath
+                self.w.docfolder.set(docpath)
+                self.w.setdefaultbutton(self.w.searchbutton)
+
+    def close(self):
+        prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
+        prefs.docsearchengine = self.getsettings()
+
+    def getsettings(self):
+        radiobuttons = [self.w.phraseradio, self.w.allwordsradio, self.w.anywordsradio]
+        for i in range(3):
+            if radiobuttons[i].get():
+                kind = i
+                break
+        docpath = self.docpath
+        case = self.w.casesens.get()
+        word = self.w.wholewords.get()
+        tut = self.w.tutorial.get()
+        lib = self.w.library.get()
+        ref = self.w.langueref.get()
+        ext = self.w.extending.get()
+        api = self.w.api.get()
+        return (docpath, kind, case, word, tut, lib, ref, ext, api)
+
+    def checkbuttons(self):
+        self.w.searchbutton.enable(not not self.w.searchtext.get())
diff --git a/Mac/Tools/IDE/PyEdit.py b/Mac/Tools/IDE/PyEdit.py
index ce228ff..88c72ac 100644
--- a/Mac/Tools/IDE/PyEdit.py
+++ b/Mac/Tools/IDE/PyEdit.py
@@ -21,9 +21,9 @@
 smAllScripts = -3
 
 if hasattr(Win, "FrontNonFloatingWindow"):
-	MyFrontWindow = Win.FrontNonFloatingWindow
+    MyFrontWindow = Win.FrontNonFloatingWindow
 else:
-	MyFrontWindow = Win.FrontWindow
+    MyFrontWindow = Win.FrontWindow
 
 
 _scriptuntitledcounter = 1
@@ -35,1328 +35,1328 @@
 
 
 class Editor(W.Window):
-	
-	def __init__(self, path = "", title = ""):
-		defaultfontsettings, defaulttabsettings, defaultwindowsize = geteditorprefs()
-		global _scriptuntitledcounter
-		if not path:
-			if title:
-				self.title = title
-			else:
-				self.title = "Untitled Script %r" % (_scriptuntitledcounter,)
-				_scriptuntitledcounter = _scriptuntitledcounter + 1
-			text = ""
-			self._creator = W._signature
-			self._eoln = os.linesep
-		elif os.path.exists(path):
-			path = resolvealiases(path)
-			dir, name = os.path.split(path)
-			self.title = name
-			f = open(path, "rb")
-			text = f.read()
-			f.close()
-			self._creator, filetype = MacOS.GetCreatorAndType(path)
-			self.addrecentfile(path)
-			if '\n' in text:
-				if string.find(text, '\r\n') >= 0:
-					self._eoln = '\r\n'
-				else:
-					self._eoln = '\n'
-				text = string.replace(text, self._eoln, '\r')
-			else:
-				self._eoln = '\r'
-		else:
-			raise IOError, "file '%s' does not exist" % path
-		self.path = path
-		
-		self.settings = {}
-		if self.path:
-			self.readwindowsettings()
-		if self.settings.has_key("windowbounds"):
-			bounds = self.settings["windowbounds"]
-		else:
-			bounds = defaultwindowsize
-		if self.settings.has_key("fontsettings"):
-			self.fontsettings = self.settings["fontsettings"]
-		else:
-			self.fontsettings = defaultfontsettings
-		if self.settings.has_key("tabsize"):
-			try:
-				self.tabsettings = (tabsize, tabmode) = self.settings["tabsize"]
-			except:
-				self.tabsettings = defaulttabsettings
-		else:
-			self.tabsettings = defaulttabsettings
-		
-		W.Window.__init__(self, bounds, self.title, minsize = (330, 120), tabbable = 0)
-		self.setupwidgets(text)
-		
-		if self.settings.has_key("selection"):
-			selstart, selend = self.settings["selection"]
-			self.setselection(selstart, selend)
-		self.open()
-		self.setinfotext()
-		self.globals = {}
-		self._buf = ""  # for write method
-		self.debugging = 0
-		self.profiling = 0
-		self.run_as_main = self.settings.get("run_as_main", 0)
-		self.run_with_interpreter = self.settings.get("run_with_interpreter", 0)
-		self.run_with_cl_interpreter = self.settings.get("run_with_cl_interpreter", 0)
-	
-	def readwindowsettings(self):
-		try:
-			resref = Res.FSpOpenResFile(self.path, 1)
-		except Res.Error:
-			return
-		try:
-			Res.UseResFile(resref)
-			data = Res.Get1Resource('PyWS', 128)
-			self.settings = marshal.loads(data.data)
-		except:
-			pass
-		Res.CloseResFile(resref)
-		
-	def writewindowsettings(self):
-		try:
-			resref = Res.FSpOpenResFile(self.path, 3)
-		except Res.Error:
-			Res.FSpCreateResFile(self.path, self._creator, 'TEXT', smAllScripts)
-			resref = Res.FSpOpenResFile(self.path, 3)
-		try:
-			data = Res.Resource(marshal.dumps(self.settings))
-			Res.UseResFile(resref)
-			try:
-				temp = Res.Get1Resource('PyWS', 128)
-				temp.RemoveResource()
-			except Res.Error:
-				pass
-			data.AddResource('PyWS', 128, "window settings")
-		finally:
-			Res.UpdateResFile(resref)
-			Res.CloseResFile(resref)
-	
-	def getsettings(self):
-		self.settings = {}
-		self.settings["windowbounds"] = self.getbounds()
-		self.settings["selection"] = self.getselection()
-		self.settings["fontsettings"] = self.editgroup.editor.getfontsettings()
-		self.settings["tabsize"] = self.editgroup.editor.gettabsettings()
-		self.settings["run_as_main"] = self.run_as_main
-		self.settings["run_with_interpreter"] = self.run_with_interpreter
-		self.settings["run_with_cl_interpreter"] = self.run_with_cl_interpreter
-	
-	def get(self):
-		return self.editgroup.editor.get()
-	
-	def getselection(self):
-		return self.editgroup.editor.ted.WEGetSelection()
-	
-	def setselection(self, selstart, selend):
-		self.editgroup.editor.setselection(selstart, selend)
-		
-	def getselectedtext(self):
-		return self.editgroup.editor.getselectedtext()
-	
-	def getfilename(self):
-		if self.path:
-			return self.path
-		return '<%s>' % self.title
-	
-	def setupwidgets(self, text):
-		topbarheight = 24
-		popfieldwidth = 80
-		self.lastlineno = None
-		
-		# make an editor
-		self.editgroup = W.Group((0, topbarheight + 1, 0, 0))
-		editor = W.PyEditor((0, 0, -15,-15), text, 
-				fontsettings = self.fontsettings, 
-				tabsettings = self.tabsettings,
-				file = self.getfilename())
-		
-		# make the widgets
-		self.popfield = ClassFinder((popfieldwidth - 17, -15, 16, 16), [], self.popselectline)
-		self.linefield = W.EditText((-1, -15, popfieldwidth - 15, 16), inset = (6, 1))
-		self.editgroup._barx = W.Scrollbar((popfieldwidth - 2, -15, -14, 16), editor.hscroll, max = 32767)
-		self.editgroup._bary = W.Scrollbar((-15, 14, 16, -14), editor.vscroll, max = 32767)
-		self.editgroup.editor = editor	# add editor *after* scrollbars
-		
-		self.editgroup.optionsmenu = W.PopupMenu((-15, -1, 16, 16), [])
-		self.editgroup.optionsmenu.bind('<click>', self.makeoptionsmenu)
-		
-		self.bevelbox = W.BevelBox((0, 0, 0, topbarheight))
-		self.hline = W.HorizontalLine((0, topbarheight, 0, 0))
-		self.infotext = W.TextBox((175, 6, -4, 14), backgroundcolor = (0xe000, 0xe000, 0xe000))
-		self.runbutton = W.BevelButton((6, 4, 80, 16), runButtonLabels[0], self.run)
-		self.runselbutton = W.BevelButton((90, 4, 80, 16), runSelButtonLabels[0], self.runselection)
-		
-		# bind some keys
-		editor.bind("cmdr", self.runbutton.push)
-		editor.bind("enter", self.runselbutton.push)
-		editor.bind("cmdj", self.domenu_gotoline)
-		editor.bind("cmdd", self.domenu_toggledebugger)
-		editor.bind("<idle>", self.updateselection)
-		
-		editor.bind("cmde", searchengine.setfindstring)
-		editor.bind("cmdf", searchengine.show)
-		editor.bind("cmdg", searchengine.findnext)
-		editor.bind("cmdshiftr", searchengine.replace)
-		editor.bind("cmdt", searchengine.replacefind)
-		
-		self.linefield.bind("return", self.dolinefield)
-		self.linefield.bind("enter", self.dolinefield)
-		self.linefield.bind("tab", self.dolinefield)
-		
-		# intercept clicks
-		editor.bind("<click>", self.clickeditor)
-		self.linefield.bind("<click>", self.clicklinefield)
-	
-	def makeoptionsmenu(self):
-		menuitems = [('Font settings\xc9', self.domenu_fontsettings), 
-				("Save options\xc9", self.domenu_options),
-				'-',
-				('\0' + chr(self.run_as_main) + 'Run as __main__', self.domenu_toggle_run_as_main), 
-				#('\0' + chr(self.run_with_interpreter) + 'Run with Interpreter', self.domenu_dtoggle_run_with_interpreter), 
-				('\0' + chr(self.run_with_cl_interpreter) + 'Run with commandline Python', self.domenu_toggle_run_with_cl_interpreter), 
-				'-',
-				('Modularize', self.domenu_modularize),
-				('Browse namespace\xc9', self.domenu_browsenamespace), 
-				'-']
-		if self.profiling:
-			menuitems = menuitems + [('Disable profiler', self.domenu_toggleprofiler)]
-		else:
-			menuitems = menuitems + [('Enable profiler', self.domenu_toggleprofiler)]
-		if self.editgroup.editor._debugger:
-			menuitems = menuitems + [('Disable debugger', self.domenu_toggledebugger),
-				('Clear breakpoints', self.domenu_clearbreakpoints),
-				('Edit breakpoints\xc9', self.domenu_editbreakpoints)]
-		else:
-			menuitems = menuitems + [('Enable debugger', self.domenu_toggledebugger)]
-		self.editgroup.optionsmenu.set(menuitems)
-	
-	def domenu_toggle_run_as_main(self):
-		self.run_as_main = not self.run_as_main
-		self.run_with_interpreter = 0
-		self.run_with_cl_interpreter = 0
-		self.editgroup.editor.selectionchanged()
-	
-	def XXdomenu_toggle_run_with_interpreter(self):
-		self.run_with_interpreter = not self.run_with_interpreter
-		self.run_as_main = 0
-		self.run_with_cl_interpreter = 0
-		self.editgroup.editor.selectionchanged()
-	
-	def domenu_toggle_run_with_cl_interpreter(self):
-		self.run_with_cl_interpreter = not self.run_with_cl_interpreter
-		self.run_as_main = 0
-		self.run_with_interpreter = 0
-		self.editgroup.editor.selectionchanged()
-	
-	def showbreakpoints(self, onoff):
-		self.editgroup.editor.showbreakpoints(onoff)
-		self.debugging = onoff
-	
-	def domenu_clearbreakpoints(self, *args):
-		self.editgroup.editor.clearbreakpoints()
-	
-	def domenu_editbreakpoints(self, *args):
-		self.editgroup.editor.editbreakpoints()
-	
-	def domenu_toggledebugger(self, *args):
-		if not self.debugging:
-			W.SetCursor('watch')
-		self.debugging = not self.debugging
-		self.editgroup.editor.togglebreakpoints()
-		
-	def domenu_toggleprofiler(self, *args):
-		self.profiling = not self.profiling
-	
-	def domenu_browsenamespace(self, *args):
-		import PyBrowser, W
-		W.SetCursor('watch')
-		globals, file, modname = self.getenvironment()
-		if not modname:
-			modname = self.title
-		PyBrowser.Browser(globals, "Object browser: " + modname)
-	
-	def domenu_modularize(self, *args):
-		modname = _filename_as_modname(self.title)
-		if not modname:
-			raise W.AlertError, "Can't modularize \"%s\"" % self.title
-		run_as_main = self.run_as_main
-		self.run_as_main = 0
-		self.run()
-		self.run_as_main = run_as_main
-		if self.path:
-			file = self.path
-		else:
-			file = self.title
-		
-		if self.globals and not sys.modules.has_key(modname):
-			module = imp.new_module(modname)
-			for attr in self.globals.keys():
-				setattr(module,attr,self.globals[attr])
-			sys.modules[modname] = module
-			self.globals = {}
-	
-	def domenu_fontsettings(self, *args):
-		import FontSettings
-		fontsettings = self.editgroup.editor.getfontsettings()
-		tabsettings = self.editgroup.editor.gettabsettings()
-		settings = FontSettings.FontDialog(fontsettings, tabsettings)
-		if settings:
-			fontsettings, tabsettings = settings
-			self.editgroup.editor.setfontsettings(fontsettings)
-			self.editgroup.editor.settabsettings(tabsettings)
-	
-	def domenu_options(self, *args):
-		rv = SaveOptions(self._creator, self._eoln)
-		if rv:
-			self.editgroup.editor.selectionchanged() # ouch...
-			self._creator, self._eoln = rv
-	
-	def clicklinefield(self):
-		if self._currentwidget <> self.linefield:
-			self.linefield.select(1)
-			self.linefield.selectall()
-			return 1
-	
-	def clickeditor(self):
-		if self._currentwidget <> self.editgroup.editor:
-			self.dolinefield()
-			return 1
-	
-	def updateselection(self, force = 0):
-		sel = min(self.editgroup.editor.getselection())
-		lineno = self.editgroup.editor.offsettoline(sel)
-		if lineno <> self.lastlineno or force:
-			self.lastlineno = lineno
-			self.linefield.set(str(lineno + 1))
-			self.linefield.selview()
-	
-	def dolinefield(self):
-		try:
-			lineno = string.atoi(self.linefield.get()) - 1
-			if lineno <> self.lastlineno:
-				self.editgroup.editor.selectline(lineno)
-				self.updateselection(1)
-		except:
-			self.updateselection(1)
-		self.editgroup.editor.select(1)
-	
-	def setinfotext(self):
-		if not hasattr(self, 'infotext'):
-			return
-		if self.path:
-			self.infotext.set(self.path)
-		else:
-			self.infotext.set("")
-	
-	def close(self):
-		if self.editgroup.editor.changed:
-			Qd.InitCursor()
-			save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?' % self.title,
-					default=1, no="Don\xd5t save")
-			if save > 0:
-				if self.domenu_save():
-					return 1
-			elif save < 0:
-				return 1
-		self.globals = None
-		W.Window.close(self)
-	
-	def domenu_close(self, *args):
-		return self.close()
-	
-	def domenu_save(self, *args):
-		if not self.path:
-			# Will call us recursively
-			return self.domenu_save_as()
-		data = self.editgroup.editor.get()
-		if self._eoln != '\r':
-			data = string.replace(data, '\r', self._eoln)
-		fp = open(self.path, 'wb')  # open file in binary mode, data has '\r' line-endings
-		fp.write(data)
-		fp.close()
-		MacOS.SetCreatorAndType(self.path, self._creator, 'TEXT')
-		self.getsettings()
-		self.writewindowsettings()
-		self.editgroup.editor.changed = 0
-		self.editgroup.editor.selchanged = 0
-		import linecache
-		if linecache.cache.has_key(self.path):
-			del linecache.cache[self.path]
-		import macostools
-		macostools.touched(self.path)
-		self.addrecentfile(self.path)
-	
-	def can_save(self, menuitem):
-		return self.editgroup.editor.changed or self.editgroup.editor.selchanged
-	
-	def domenu_save_as(self, *args):
-		path = EasyDialogs.AskFileForSave(message='Save as:', savedFileName=self.title)
-		if not path: 
-			return 1
-		self.showbreakpoints(0)
-		self.path = path
-		self.setinfotext()
-		self.title = os.path.split(self.path)[-1]
-		self.wid.SetWTitle(self.title)
-		self.domenu_save()
-		self.editgroup.editor.setfile(self.getfilename())
-		app = W.getapplication()
-		app.makeopenwindowsmenu()
-		if hasattr(app, 'makescriptsmenu'):
-			app = W.getapplication()
-			fsr, changed = app.scriptsfolder.FSResolveAlias(None)
-			path = fsr.as_pathname()
-			if path == self.path[:len(path)]:
-				W.getapplication().makescriptsmenu()
-	
-	def domenu_save_as_applet(self, *args):
-		import buildtools
-		
-		buildtools.DEBUG = 0	# ouch.
-		
-		if self.title[-3:] == ".py":
-			destname = self.title[:-3]
-		else:
-			destname = self.title + ".applet"
-		destname = EasyDialogs.AskFileForSave(message='Save as Applet:', 
-			savedFileName=destname)
-		if not destname: 
-			return 1
-		W.SetCursor("watch")
-		if self.path:
-			filename = self.path
-			if filename[-3:] == ".py":
-				rsrcname = filename[:-3] + '.rsrc'
-			else:
-				rsrcname = filename + '.rsrc'
-		else:
-			filename = self.title
-			rsrcname = ""
-		
-		pytext = self.editgroup.editor.get()
-		pytext = string.split(pytext, '\r')
-		pytext = string.join(pytext, '\n') + '\n'
-		try:
-			code = compile(pytext, filename, "exec")
-		except (SyntaxError, EOFError):
-			raise buildtools.BuildError, "Syntax error in script %r" % (filename,)
-			
-		import tempfile
-		tmpdir = tempfile.mkdtemp()
-		
-		if filename[-3:] != ".py":
-			filename = filename + ".py"
-		filename = os.path.join(tmpdir, os.path.split(filename)[1])
-		fp = open(filename, "w")
-		fp.write(pytext)
-		fp.close()
-		
-		# Try removing the output file
-		try:
-			os.remove(destname)
-		except os.error:
-			pass
-		template = buildtools.findtemplate()
-		buildtools.process(template, filename, destname, 1, rsrcname=rsrcname, progress=None)
-		try:
-			os.remove(filename)
-			os.rmdir(tmpdir)
-		except os.error:
-			pass
-	
-	def domenu_gotoline(self, *args):
-		self.linefield.selectall()
-		self.linefield.select(1)
-		self.linefield.selectall()
-	
-	def domenu_selectline(self, *args):
-		self.editgroup.editor.expandselection()
-	
-	def domenu_find(self, *args):
-		searchengine.show()
-	
-	def domenu_entersearchstring(self, *args):
-		searchengine.setfindstring()
-	
-	def domenu_replace(self, *args):
-		searchengine.replace()
-	
-	def domenu_findnext(self, *args):
-		searchengine.findnext()
-	
-	def domenu_replacefind(self, *args):
-		searchengine.replacefind()
-	
-	def domenu_run(self, *args):
-		self.runbutton.push()
-	
-	def domenu_runselection(self, *args):
-		self.runselbutton.push()
-	
-	def run(self):
-		self._run()
-	
-	def _run(self):
-		if self.run_with_interpreter:
-			if self.editgroup.editor.changed:
-				Qd.InitCursor()
-				save = EasyDialogs.AskYesNoCancel('Save "%s" before running?' % self.title, 1)
-				if save > 0:
-					if self.domenu_save():
-						return
-				elif save < 0:
-					return
-			if not self.path:
-				raise W.AlertError, "Can't run unsaved file"
-			self._run_with_interpreter()
-		elif self.run_with_cl_interpreter:
-			if self.editgroup.editor.changed:
-				Qd.InitCursor()
-				save = EasyDialogs.AskYesNoCancel('Save "%s" before running?' % self.title, 1)
-				if save > 0:
-					if self.domenu_save():
-						return
-				elif save < 0:
-					return
-			if not self.path:
-				raise W.AlertError, "Can't run unsaved file"
-			self._run_with_cl_interpreter()
-		else:
-			pytext = self.editgroup.editor.get()
-			globals, file, modname = self.getenvironment()
-			self.execstring(pytext, globals, globals, file, modname)
-	
-	def _run_with_interpreter(self):
-		interp_path = os.path.join(sys.exec_prefix, "PythonInterpreter")
-		if not os.path.exists(interp_path):
-			raise W.AlertError, "Can't find interpreter"
-		import findertools
-		XXX
 
-	def _run_with_cl_interpreter(self):
-		import Terminal
-		interp_path = os.path.join(sys.exec_prefix, 
-			"Resources", "Python.app", "Contents", "MacOS", "Python")
-		if not os.path.exists(interp_path):
-			interp_path = os.path.join(sys.exec_prefix, "bin", "python")
-		file_path = self.path
-		if not os.path.exists(interp_path):
-			# This "can happen" if we are running IDE under MacPython-OS9.
-			raise W.AlertError, "Can't find command-line Python"
-		cmd = '"%s" "%s" ; exit' % (interp_path, file_path)
-		t = Terminal.Terminal()
-		t.do_script(cmd)
-	
-	def runselection(self):
-		self._runselection()
-	
-	def _runselection(self):
-		if self.run_with_interpreter or self.run_with_cl_interpreter:
-			raise W.AlertError, "Can't run selection with Interpreter"
-		globals, file, modname = self.getenvironment()
-		locals = globals
-		# select whole lines
-		self.editgroup.editor.expandselection()
-		
-		# get lineno of first selected line
-		selstart, selend = self.editgroup.editor.getselection()
-		selstart, selend = min(selstart, selend), max(selstart, selend)
-		selfirstline = self.editgroup.editor.offsettoline(selstart)
-		alltext = self.editgroup.editor.get()
-		pytext = alltext[selstart:selend]
-		lines = string.split(pytext, '\r')
-		indent = getminindent(lines)
-		if indent == 1:
-			classname = ''
-			alllines = string.split(alltext, '\r')
-			for i in range(selfirstline - 1, -1, -1):
-				line = alllines[i]
-				if line[:6] == 'class ':
-					classname = string.split(string.strip(line[6:]))[0]
-					classend = identifieRE_match(classname)
-					if classend < 1:
-						raise W.AlertError, "Can't find a class."
-					classname = classname[:classend]
-					break
-				elif line and line[0] not in '\t#':
-					raise W.AlertError, "Can't find a class."
-			else:
-				raise W.AlertError, "Can't find a class."
-			if globals.has_key(classname):
-				klass = globals[classname]
-			else:
-				raise W.AlertError, "Can't find class \"%s\"." % classname
-			# add class def
-			pytext = ("class %s:\n" % classname) + pytext
-			selfirstline = selfirstline - 1
-		elif indent > 0:
-			raise W.AlertError, "Can't run indented code."
-		
-		# add "newlines" to fool compile/exec: 
-		# now a traceback will give the right line number
-		pytext = selfirstline * '\r' + pytext
-		self.execstring(pytext, globals, locals, file, modname)
-		if indent == 1 and globals[classname] is not klass:
-			# update the class in place
-			klass.__dict__.update(globals[classname].__dict__)
-			globals[classname] = klass
-	
-	def execstring(self, pytext, globals, locals, file, modname):
-		tracebackwindow.hide()
-		# update windows
-		W.getapplication().refreshwindows()
-		if self.run_as_main:
-			modname = "__main__"
-		if self.path:
-			dir = os.path.dirname(self.path)
-			savedir = os.getcwd()
-			os.chdir(dir)
-			sys.path.insert(0, dir)
-		self._scriptDone = False
-		if sys.platform == "darwin":
-			# On MacOSX, MacPython doesn't poll for command-period
-			# (cancel), so to enable the user to cancel a running
-			# script, we have to spawn a thread which does the
-			# polling. It will send a SIGINT to the main thread
-			# (in which the script is running) when the user types
-			# command-period.
-			from threading import Thread
-			t = Thread(target=self._userCancelledMonitor,
-					name="UserCancelledMonitor")
-			t.start()
-		try:
-			execstring(pytext, globals, locals, file, self.debugging, 
-					modname, self.profiling)
-		finally:
-			self._scriptDone = True
-			if self.path:
-				os.chdir(savedir)
-				del sys.path[0]
-	
-	def _userCancelledMonitor(self):
-		import time
-		from signal import SIGINT
-		while not self._scriptDone:
-			if Evt.CheckEventQueueForUserCancel():
-				# Send a SIGINT signal to ourselves.
-				# This gets delivered to the main thread,
-				# cancelling the running script.
-				os.kill(os.getpid(), SIGINT)
-				break
-			time.sleep(0.25)
-	
-	def getenvironment(self):
-		if self.path:
-			file = self.path
-			dir = os.path.dirname(file)
-			# check if we're part of a package
-			modname = ""
-			while os.path.exists(os.path.join(dir, "__init__.py")):
-				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
-					modname = modname[:-1]
-				else:
-					modname = modname + subname
-			else:
-				modname = subname
-			if sys.modules.has_key(modname):
-				globals = sys.modules[modname].__dict__
-				self.globals = {}
-			else:
-				globals = self.globals
-				modname = subname
-		else:
-			file = '<%s>' % self.title
-			globals = self.globals
-			modname = file
-		return globals, file, modname
-	
-	def write(self, stuff):
-		"""for use as stdout"""
-		self._buf = self._buf + stuff
-		if '\n' in self._buf:
-			self.flush()
-	
-	def flush(self):
-		stuff = string.split(self._buf, '\n')
-		stuff = string.join(stuff, '\r')
-		end = self.editgroup.editor.ted.WEGetTextLength()
-		self.editgroup.editor.ted.WESetSelection(end, end)
-		self.editgroup.editor.ted.WEInsert(stuff, None, None)
-		self.editgroup.editor.updatescrollbars()
-		self._buf = ""
-		# ? optional:
-		#self.wid.SelectWindow()
-	
-	def getclasslist(self):
-		from string import find, strip
-		methodRE = re.compile(r"\r[ \t]+def ")
-		findMethod = methodRE.search
-		editor = self.editgroup.editor
-		text = editor.get()
-		list = []
-		append = list.append
-		functag = "func"
-		classtag = "class"
-		methodtag = "method"
-		pos = -1
-		if text[:4] == 'def ':
-			append((pos + 4, functag))
-			pos = 4
-		while 1:
-			pos = find(text, '\rdef ', pos + 1)
-			if pos < 0:
-				break
-			append((pos + 5, functag))
-		pos = -1
-		if text[:6] == 'class ':
-			append((pos + 6, classtag))
-			pos = 6
-		while 1:
-			pos = find(text, '\rclass ', pos + 1)
-			if pos < 0:
-				break
-			append((pos + 7, classtag))
-		pos = 0
-		while 1:
-			m = findMethod(text, pos + 1)
-			if m is None:
-				break
-			pos = m.regs[0][0]
-			#pos = find(text, '\r\tdef ', pos + 1)
-			append((m.regs[0][1], methodtag))
-		list.sort()
-		classlist = []
-		methodlistappend = None
-		offsetToLine = editor.ted.WEOffsetToLine
-		getLineRange = editor.ted.WEGetLineRange
-		append = classlist.append
-		for pos, tag in list:
-			lineno = offsetToLine(pos)
-			lineStart, lineEnd = getLineRange(lineno)
-			line = strip(text[pos:lineEnd])
-			line = line[:identifieRE_match(line)]
-			if tag is functag:
-				append(("def " + line, lineno + 1))
-				methodlistappend = None
-			elif tag is classtag:
-				append(["class " + line])
-				methodlistappend = classlist[-1].append
-			elif methodlistappend and tag is methodtag:
-				methodlistappend(("def " + line, lineno + 1))
-		return classlist
-	
-	def popselectline(self, lineno):
-		self.editgroup.editor.selectline(lineno - 1)
-	
-	def selectline(self, lineno, charoffset = 0):
-		self.editgroup.editor.selectline(lineno - 1, charoffset)
-		
-	def addrecentfile(self, filename):
-		app = W.getapplication()
-		app.addrecentfile(filename)
+    def __init__(self, path = "", title = ""):
+        defaultfontsettings, defaulttabsettings, defaultwindowsize = geteditorprefs()
+        global _scriptuntitledcounter
+        if not path:
+            if title:
+                self.title = title
+            else:
+                self.title = "Untitled Script %r" % (_scriptuntitledcounter,)
+                _scriptuntitledcounter = _scriptuntitledcounter + 1
+            text = ""
+            self._creator = W._signature
+            self._eoln = os.linesep
+        elif os.path.exists(path):
+            path = resolvealiases(path)
+            dir, name = os.path.split(path)
+            self.title = name
+            f = open(path, "rb")
+            text = f.read()
+            f.close()
+            self._creator, filetype = MacOS.GetCreatorAndType(path)
+            self.addrecentfile(path)
+            if '\n' in text:
+                if string.find(text, '\r\n') >= 0:
+                    self._eoln = '\r\n'
+                else:
+                    self._eoln = '\n'
+                text = string.replace(text, self._eoln, '\r')
+            else:
+                self._eoln = '\r'
+        else:
+            raise IOError, "file '%s' does not exist" % path
+        self.path = path
+
+        self.settings = {}
+        if self.path:
+            self.readwindowsettings()
+        if self.settings.has_key("windowbounds"):
+            bounds = self.settings["windowbounds"]
+        else:
+            bounds = defaultwindowsize
+        if self.settings.has_key("fontsettings"):
+            self.fontsettings = self.settings["fontsettings"]
+        else:
+            self.fontsettings = defaultfontsettings
+        if self.settings.has_key("tabsize"):
+            try:
+                self.tabsettings = (tabsize, tabmode) = self.settings["tabsize"]
+            except:
+                self.tabsettings = defaulttabsettings
+        else:
+            self.tabsettings = defaulttabsettings
+
+        W.Window.__init__(self, bounds, self.title, minsize = (330, 120), tabbable = 0)
+        self.setupwidgets(text)
+
+        if self.settings.has_key("selection"):
+            selstart, selend = self.settings["selection"]
+            self.setselection(selstart, selend)
+        self.open()
+        self.setinfotext()
+        self.globals = {}
+        self._buf = ""  # for write method
+        self.debugging = 0
+        self.profiling = 0
+        self.run_as_main = self.settings.get("run_as_main", 0)
+        self.run_with_interpreter = self.settings.get("run_with_interpreter", 0)
+        self.run_with_cl_interpreter = self.settings.get("run_with_cl_interpreter", 0)
+
+    def readwindowsettings(self):
+        try:
+            resref = Res.FSpOpenResFile(self.path, 1)
+        except Res.Error:
+            return
+        try:
+            Res.UseResFile(resref)
+            data = Res.Get1Resource('PyWS', 128)
+            self.settings = marshal.loads(data.data)
+        except:
+            pass
+        Res.CloseResFile(resref)
+
+    def writewindowsettings(self):
+        try:
+            resref = Res.FSpOpenResFile(self.path, 3)
+        except Res.Error:
+            Res.FSpCreateResFile(self.path, self._creator, 'TEXT', smAllScripts)
+            resref = Res.FSpOpenResFile(self.path, 3)
+        try:
+            data = Res.Resource(marshal.dumps(self.settings))
+            Res.UseResFile(resref)
+            try:
+                temp = Res.Get1Resource('PyWS', 128)
+                temp.RemoveResource()
+            except Res.Error:
+                pass
+            data.AddResource('PyWS', 128, "window settings")
+        finally:
+            Res.UpdateResFile(resref)
+            Res.CloseResFile(resref)
+
+    def getsettings(self):
+        self.settings = {}
+        self.settings["windowbounds"] = self.getbounds()
+        self.settings["selection"] = self.getselection()
+        self.settings["fontsettings"] = self.editgroup.editor.getfontsettings()
+        self.settings["tabsize"] = self.editgroup.editor.gettabsettings()
+        self.settings["run_as_main"] = self.run_as_main
+        self.settings["run_with_interpreter"] = self.run_with_interpreter
+        self.settings["run_with_cl_interpreter"] = self.run_with_cl_interpreter
+
+    def get(self):
+        return self.editgroup.editor.get()
+
+    def getselection(self):
+        return self.editgroup.editor.ted.WEGetSelection()
+
+    def setselection(self, selstart, selend):
+        self.editgroup.editor.setselection(selstart, selend)
+
+    def getselectedtext(self):
+        return self.editgroup.editor.getselectedtext()
+
+    def getfilename(self):
+        if self.path:
+            return self.path
+        return '<%s>' % self.title
+
+    def setupwidgets(self, text):
+        topbarheight = 24
+        popfieldwidth = 80
+        self.lastlineno = None
+
+        # make an editor
+        self.editgroup = W.Group((0, topbarheight + 1, 0, 0))
+        editor = W.PyEditor((0, 0, -15,-15), text,
+                        fontsettings = self.fontsettings,
+                        tabsettings = self.tabsettings,
+                        file = self.getfilename())
+
+        # make the widgets
+        self.popfield = ClassFinder((popfieldwidth - 17, -15, 16, 16), [], self.popselectline)
+        self.linefield = W.EditText((-1, -15, popfieldwidth - 15, 16), inset = (6, 1))
+        self.editgroup._barx = W.Scrollbar((popfieldwidth - 2, -15, -14, 16), editor.hscroll, max = 32767)
+        self.editgroup._bary = W.Scrollbar((-15, 14, 16, -14), editor.vscroll, max = 32767)
+        self.editgroup.editor = editor  # add editor *after* scrollbars
+
+        self.editgroup.optionsmenu = W.PopupMenu((-15, -1, 16, 16), [])
+        self.editgroup.optionsmenu.bind('<click>', self.makeoptionsmenu)
+
+        self.bevelbox = W.BevelBox((0, 0, 0, topbarheight))
+        self.hline = W.HorizontalLine((0, topbarheight, 0, 0))
+        self.infotext = W.TextBox((175, 6, -4, 14), backgroundcolor = (0xe000, 0xe000, 0xe000))
+        self.runbutton = W.BevelButton((6, 4, 80, 16), runButtonLabels[0], self.run)
+        self.runselbutton = W.BevelButton((90, 4, 80, 16), runSelButtonLabels[0], self.runselection)
+
+        # bind some keys
+        editor.bind("cmdr", self.runbutton.push)
+        editor.bind("enter", self.runselbutton.push)
+        editor.bind("cmdj", self.domenu_gotoline)
+        editor.bind("cmdd", self.domenu_toggledebugger)
+        editor.bind("<idle>", self.updateselection)
+
+        editor.bind("cmde", searchengine.setfindstring)
+        editor.bind("cmdf", searchengine.show)
+        editor.bind("cmdg", searchengine.findnext)
+        editor.bind("cmdshiftr", searchengine.replace)
+        editor.bind("cmdt", searchengine.replacefind)
+
+        self.linefield.bind("return", self.dolinefield)
+        self.linefield.bind("enter", self.dolinefield)
+        self.linefield.bind("tab", self.dolinefield)
+
+        # intercept clicks
+        editor.bind("<click>", self.clickeditor)
+        self.linefield.bind("<click>", self.clicklinefield)
+
+    def makeoptionsmenu(self):
+        menuitems = [('Font settings\xc9', self.domenu_fontsettings),
+                        ("Save options\xc9", self.domenu_options),
+                        '-',
+                        ('\0' + chr(self.run_as_main) + 'Run as __main__', self.domenu_toggle_run_as_main),
+                        #('\0' + chr(self.run_with_interpreter) + 'Run with Interpreter', self.domenu_dtoggle_run_with_interpreter),
+                        ('\0' + chr(self.run_with_cl_interpreter) + 'Run with commandline Python', self.domenu_toggle_run_with_cl_interpreter),
+                        '-',
+                        ('Modularize', self.domenu_modularize),
+                        ('Browse namespace\xc9', self.domenu_browsenamespace),
+                        '-']
+        if self.profiling:
+            menuitems = menuitems + [('Disable profiler', self.domenu_toggleprofiler)]
+        else:
+            menuitems = menuitems + [('Enable profiler', self.domenu_toggleprofiler)]
+        if self.editgroup.editor._debugger:
+            menuitems = menuitems + [('Disable debugger', self.domenu_toggledebugger),
+                    ('Clear breakpoints', self.domenu_clearbreakpoints),
+                    ('Edit breakpoints\xc9', self.domenu_editbreakpoints)]
+        else:
+            menuitems = menuitems + [('Enable debugger', self.domenu_toggledebugger)]
+        self.editgroup.optionsmenu.set(menuitems)
+
+    def domenu_toggle_run_as_main(self):
+        self.run_as_main = not self.run_as_main
+        self.run_with_interpreter = 0
+        self.run_with_cl_interpreter = 0
+        self.editgroup.editor.selectionchanged()
+
+    def XXdomenu_toggle_run_with_interpreter(self):
+        self.run_with_interpreter = not self.run_with_interpreter
+        self.run_as_main = 0
+        self.run_with_cl_interpreter = 0
+        self.editgroup.editor.selectionchanged()
+
+    def domenu_toggle_run_with_cl_interpreter(self):
+        self.run_with_cl_interpreter = not self.run_with_cl_interpreter
+        self.run_as_main = 0
+        self.run_with_interpreter = 0
+        self.editgroup.editor.selectionchanged()
+
+    def showbreakpoints(self, onoff):
+        self.editgroup.editor.showbreakpoints(onoff)
+        self.debugging = onoff
+
+    def domenu_clearbreakpoints(self, *args):
+        self.editgroup.editor.clearbreakpoints()
+
+    def domenu_editbreakpoints(self, *args):
+        self.editgroup.editor.editbreakpoints()
+
+    def domenu_toggledebugger(self, *args):
+        if not self.debugging:
+            W.SetCursor('watch')
+        self.debugging = not self.debugging
+        self.editgroup.editor.togglebreakpoints()
+
+    def domenu_toggleprofiler(self, *args):
+        self.profiling = not self.profiling
+
+    def domenu_browsenamespace(self, *args):
+        import PyBrowser, W
+        W.SetCursor('watch')
+        globals, file, modname = self.getenvironment()
+        if not modname:
+            modname = self.title
+        PyBrowser.Browser(globals, "Object browser: " + modname)
+
+    def domenu_modularize(self, *args):
+        modname = _filename_as_modname(self.title)
+        if not modname:
+            raise W.AlertError, "Can't modularize \"%s\"" % self.title
+        run_as_main = self.run_as_main
+        self.run_as_main = 0
+        self.run()
+        self.run_as_main = run_as_main
+        if self.path:
+            file = self.path
+        else:
+            file = self.title
+
+        if self.globals and not sys.modules.has_key(modname):
+            module = imp.new_module(modname)
+            for attr in self.globals.keys():
+                setattr(module,attr,self.globals[attr])
+            sys.modules[modname] = module
+            self.globals = {}
+
+    def domenu_fontsettings(self, *args):
+        import FontSettings
+        fontsettings = self.editgroup.editor.getfontsettings()
+        tabsettings = self.editgroup.editor.gettabsettings()
+        settings = FontSettings.FontDialog(fontsettings, tabsettings)
+        if settings:
+            fontsettings, tabsettings = settings
+            self.editgroup.editor.setfontsettings(fontsettings)
+            self.editgroup.editor.settabsettings(tabsettings)
+
+    def domenu_options(self, *args):
+        rv = SaveOptions(self._creator, self._eoln)
+        if rv:
+            self.editgroup.editor.selectionchanged() # ouch...
+            self._creator, self._eoln = rv
+
+    def clicklinefield(self):
+        if self._currentwidget <> self.linefield:
+            self.linefield.select(1)
+            self.linefield.selectall()
+            return 1
+
+    def clickeditor(self):
+        if self._currentwidget <> self.editgroup.editor:
+            self.dolinefield()
+            return 1
+
+    def updateselection(self, force = 0):
+        sel = min(self.editgroup.editor.getselection())
+        lineno = self.editgroup.editor.offsettoline(sel)
+        if lineno <> self.lastlineno or force:
+            self.lastlineno = lineno
+            self.linefield.set(str(lineno + 1))
+            self.linefield.selview()
+
+    def dolinefield(self):
+        try:
+            lineno = string.atoi(self.linefield.get()) - 1
+            if lineno <> self.lastlineno:
+                self.editgroup.editor.selectline(lineno)
+                self.updateselection(1)
+        except:
+            self.updateselection(1)
+        self.editgroup.editor.select(1)
+
+    def setinfotext(self):
+        if not hasattr(self, 'infotext'):
+            return
+        if self.path:
+            self.infotext.set(self.path)
+        else:
+            self.infotext.set("")
+
+    def close(self):
+        if self.editgroup.editor.changed:
+            Qd.InitCursor()
+            save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?' % self.title,
+                            default=1, no="Don\xd5t save")
+            if save > 0:
+                if self.domenu_save():
+                    return 1
+            elif save < 0:
+                return 1
+        self.globals = None
+        W.Window.close(self)
+
+    def domenu_close(self, *args):
+        return self.close()
+
+    def domenu_save(self, *args):
+        if not self.path:
+            # Will call us recursively
+            return self.domenu_save_as()
+        data = self.editgroup.editor.get()
+        if self._eoln != '\r':
+            data = string.replace(data, '\r', self._eoln)
+        fp = open(self.path, 'wb')  # open file in binary mode, data has '\r' line-endings
+        fp.write(data)
+        fp.close()
+        MacOS.SetCreatorAndType(self.path, self._creator, 'TEXT')
+        self.getsettings()
+        self.writewindowsettings()
+        self.editgroup.editor.changed = 0
+        self.editgroup.editor.selchanged = 0
+        import linecache
+        if linecache.cache.has_key(self.path):
+            del linecache.cache[self.path]
+        import macostools
+        macostools.touched(self.path)
+        self.addrecentfile(self.path)
+
+    def can_save(self, menuitem):
+        return self.editgroup.editor.changed or self.editgroup.editor.selchanged
+
+    def domenu_save_as(self, *args):
+        path = EasyDialogs.AskFileForSave(message='Save as:', savedFileName=self.title)
+        if not path:
+            return 1
+        self.showbreakpoints(0)
+        self.path = path
+        self.setinfotext()
+        self.title = os.path.split(self.path)[-1]
+        self.wid.SetWTitle(self.title)
+        self.domenu_save()
+        self.editgroup.editor.setfile(self.getfilename())
+        app = W.getapplication()
+        app.makeopenwindowsmenu()
+        if hasattr(app, 'makescriptsmenu'):
+            app = W.getapplication()
+            fsr, changed = app.scriptsfolder.FSResolveAlias(None)
+            path = fsr.as_pathname()
+            if path == self.path[:len(path)]:
+                W.getapplication().makescriptsmenu()
+
+    def domenu_save_as_applet(self, *args):
+        import buildtools
+
+        buildtools.DEBUG = 0    # ouch.
+
+        if self.title[-3:] == ".py":
+            destname = self.title[:-3]
+        else:
+            destname = self.title + ".applet"
+        destname = EasyDialogs.AskFileForSave(message='Save as Applet:',
+                savedFileName=destname)
+        if not destname:
+            return 1
+        W.SetCursor("watch")
+        if self.path:
+            filename = self.path
+            if filename[-3:] == ".py":
+                rsrcname = filename[:-3] + '.rsrc'
+            else:
+                rsrcname = filename + '.rsrc'
+        else:
+            filename = self.title
+            rsrcname = ""
+
+        pytext = self.editgroup.editor.get()
+        pytext = string.split(pytext, '\r')
+        pytext = string.join(pytext, '\n') + '\n'
+        try:
+            code = compile(pytext, filename, "exec")
+        except (SyntaxError, EOFError):
+            raise buildtools.BuildError, "Syntax error in script %r" % (filename,)
+
+        import tempfile
+        tmpdir = tempfile.mkdtemp()
+
+        if filename[-3:] != ".py":
+            filename = filename + ".py"
+        filename = os.path.join(tmpdir, os.path.split(filename)[1])
+        fp = open(filename, "w")
+        fp.write(pytext)
+        fp.close()
+
+        # Try removing the output file
+        try:
+            os.remove(destname)
+        except os.error:
+            pass
+        template = buildtools.findtemplate()
+        buildtools.process(template, filename, destname, 1, rsrcname=rsrcname, progress=None)
+        try:
+            os.remove(filename)
+            os.rmdir(tmpdir)
+        except os.error:
+            pass
+
+    def domenu_gotoline(self, *args):
+        self.linefield.selectall()
+        self.linefield.select(1)
+        self.linefield.selectall()
+
+    def domenu_selectline(self, *args):
+        self.editgroup.editor.expandselection()
+
+    def domenu_find(self, *args):
+        searchengine.show()
+
+    def domenu_entersearchstring(self, *args):
+        searchengine.setfindstring()
+
+    def domenu_replace(self, *args):
+        searchengine.replace()
+
+    def domenu_findnext(self, *args):
+        searchengine.findnext()
+
+    def domenu_replacefind(self, *args):
+        searchengine.replacefind()
+
+    def domenu_run(self, *args):
+        self.runbutton.push()
+
+    def domenu_runselection(self, *args):
+        self.runselbutton.push()
+
+    def run(self):
+        self._run()
+
+    def _run(self):
+        if self.run_with_interpreter:
+            if self.editgroup.editor.changed:
+                Qd.InitCursor()
+                save = EasyDialogs.AskYesNoCancel('Save "%s" before running?' % self.title, 1)
+                if save > 0:
+                    if self.domenu_save():
+                        return
+                elif save < 0:
+                    return
+            if not self.path:
+                raise W.AlertError, "Can't run unsaved file"
+            self._run_with_interpreter()
+        elif self.run_with_cl_interpreter:
+            if self.editgroup.editor.changed:
+                Qd.InitCursor()
+                save = EasyDialogs.AskYesNoCancel('Save "%s" before running?' % self.title, 1)
+                if save > 0:
+                    if self.domenu_save():
+                        return
+                elif save < 0:
+                    return
+            if not self.path:
+                raise W.AlertError, "Can't run unsaved file"
+            self._run_with_cl_interpreter()
+        else:
+            pytext = self.editgroup.editor.get()
+            globals, file, modname = self.getenvironment()
+            self.execstring(pytext, globals, globals, file, modname)
+
+    def _run_with_interpreter(self):
+        interp_path = os.path.join(sys.exec_prefix, "PythonInterpreter")
+        if not os.path.exists(interp_path):
+            raise W.AlertError, "Can't find interpreter"
+        import findertools
+        XXX
+
+    def _run_with_cl_interpreter(self):
+        import Terminal
+        interp_path = os.path.join(sys.exec_prefix,
+                "Resources", "Python.app", "Contents", "MacOS", "Python")
+        if not os.path.exists(interp_path):
+            interp_path = os.path.join(sys.exec_prefix, "bin", "python")
+        file_path = self.path
+        if not os.path.exists(interp_path):
+            # This "can happen" if we are running IDE under MacPython-OS9.
+            raise W.AlertError, "Can't find command-line Python"
+        cmd = '"%s" "%s" ; exit' % (interp_path, file_path)
+        t = Terminal.Terminal()
+        t.do_script(cmd)
+
+    def runselection(self):
+        self._runselection()
+
+    def _runselection(self):
+        if self.run_with_interpreter or self.run_with_cl_interpreter:
+            raise W.AlertError, "Can't run selection with Interpreter"
+        globals, file, modname = self.getenvironment()
+        locals = globals
+        # select whole lines
+        self.editgroup.editor.expandselection()
+
+        # get lineno of first selected line
+        selstart, selend = self.editgroup.editor.getselection()
+        selstart, selend = min(selstart, selend), max(selstart, selend)
+        selfirstline = self.editgroup.editor.offsettoline(selstart)
+        alltext = self.editgroup.editor.get()
+        pytext = alltext[selstart:selend]
+        lines = string.split(pytext, '\r')
+        indent = getminindent(lines)
+        if indent == 1:
+            classname = ''
+            alllines = string.split(alltext, '\r')
+            for i in range(selfirstline - 1, -1, -1):
+                line = alllines[i]
+                if line[:6] == 'class ':
+                    classname = string.split(string.strip(line[6:]))[0]
+                    classend = identifieRE_match(classname)
+                    if classend < 1:
+                        raise W.AlertError, "Can't find a class."
+                    classname = classname[:classend]
+                    break
+                elif line and line[0] not in '\t#':
+                    raise W.AlertError, "Can't find a class."
+            else:
+                raise W.AlertError, "Can't find a class."
+            if globals.has_key(classname):
+                klass = globals[classname]
+            else:
+                raise W.AlertError, "Can't find class \"%s\"." % classname
+            # add class def
+            pytext = ("class %s:\n" % classname) + pytext
+            selfirstline = selfirstline - 1
+        elif indent > 0:
+            raise W.AlertError, "Can't run indented code."
+
+        # add "newlines" to fool compile/exec:
+        # now a traceback will give the right line number
+        pytext = selfirstline * '\r' + pytext
+        self.execstring(pytext, globals, locals, file, modname)
+        if indent == 1 and globals[classname] is not klass:
+            # update the class in place
+            klass.__dict__.update(globals[classname].__dict__)
+            globals[classname] = klass
+
+    def execstring(self, pytext, globals, locals, file, modname):
+        tracebackwindow.hide()
+        # update windows
+        W.getapplication().refreshwindows()
+        if self.run_as_main:
+            modname = "__main__"
+        if self.path:
+            dir = os.path.dirname(self.path)
+            savedir = os.getcwd()
+            os.chdir(dir)
+            sys.path.insert(0, dir)
+        self._scriptDone = False
+        if sys.platform == "darwin":
+            # On MacOSX, MacPython doesn't poll for command-period
+            # (cancel), so to enable the user to cancel a running
+            # script, we have to spawn a thread which does the
+            # polling. It will send a SIGINT to the main thread
+            # (in which the script is running) when the user types
+            # command-period.
+            from threading import Thread
+            t = Thread(target=self._userCancelledMonitor,
+                            name="UserCancelledMonitor")
+            t.start()
+        try:
+            execstring(pytext, globals, locals, file, self.debugging,
+                            modname, self.profiling)
+        finally:
+            self._scriptDone = True
+            if self.path:
+                os.chdir(savedir)
+                del sys.path[0]
+
+    def _userCancelledMonitor(self):
+        import time
+        from signal import SIGINT
+        while not self._scriptDone:
+            if Evt.CheckEventQueueForUserCancel():
+                # Send a SIGINT signal to ourselves.
+                # This gets delivered to the main thread,
+                # cancelling the running script.
+                os.kill(os.getpid(), SIGINT)
+                break
+            time.sleep(0.25)
+
+    def getenvironment(self):
+        if self.path:
+            file = self.path
+            dir = os.path.dirname(file)
+            # check if we're part of a package
+            modname = ""
+            while os.path.exists(os.path.join(dir, "__init__.py")):
+                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
+                    modname = modname[:-1]
+                else:
+                    modname = modname + subname
+            else:
+                modname = subname
+            if sys.modules.has_key(modname):
+                globals = sys.modules[modname].__dict__
+                self.globals = {}
+            else:
+                globals = self.globals
+                modname = subname
+        else:
+            file = '<%s>' % self.title
+            globals = self.globals
+            modname = file
+        return globals, file, modname
+
+    def write(self, stuff):
+        """for use as stdout"""
+        self._buf = self._buf + stuff
+        if '\n' in self._buf:
+            self.flush()
+
+    def flush(self):
+        stuff = string.split(self._buf, '\n')
+        stuff = string.join(stuff, '\r')
+        end = self.editgroup.editor.ted.WEGetTextLength()
+        self.editgroup.editor.ted.WESetSelection(end, end)
+        self.editgroup.editor.ted.WEInsert(stuff, None, None)
+        self.editgroup.editor.updatescrollbars()
+        self._buf = ""
+        # ? optional:
+        #self.wid.SelectWindow()
+
+    def getclasslist(self):
+        from string import find, strip
+        methodRE = re.compile(r"\r[ \t]+def ")
+        findMethod = methodRE.search
+        editor = self.editgroup.editor
+        text = editor.get()
+        list = []
+        append = list.append
+        functag = "func"
+        classtag = "class"
+        methodtag = "method"
+        pos = -1
+        if text[:4] == 'def ':
+            append((pos + 4, functag))
+            pos = 4
+        while 1:
+            pos = find(text, '\rdef ', pos + 1)
+            if pos < 0:
+                break
+            append((pos + 5, functag))
+        pos = -1
+        if text[:6] == 'class ':
+            append((pos + 6, classtag))
+            pos = 6
+        while 1:
+            pos = find(text, '\rclass ', pos + 1)
+            if pos < 0:
+                break
+            append((pos + 7, classtag))
+        pos = 0
+        while 1:
+            m = findMethod(text, pos + 1)
+            if m is None:
+                break
+            pos = m.regs[0][0]
+            #pos = find(text, '\r\tdef ', pos + 1)
+            append((m.regs[0][1], methodtag))
+        list.sort()
+        classlist = []
+        methodlistappend = None
+        offsetToLine = editor.ted.WEOffsetToLine
+        getLineRange = editor.ted.WEGetLineRange
+        append = classlist.append
+        for pos, tag in list:
+            lineno = offsetToLine(pos)
+            lineStart, lineEnd = getLineRange(lineno)
+            line = strip(text[pos:lineEnd])
+            line = line[:identifieRE_match(line)]
+            if tag is functag:
+                append(("def " + line, lineno + 1))
+                methodlistappend = None
+            elif tag is classtag:
+                append(["class " + line])
+                methodlistappend = classlist[-1].append
+            elif methodlistappend and tag is methodtag:
+                methodlistappend(("def " + line, lineno + 1))
+        return classlist
+
+    def popselectline(self, lineno):
+        self.editgroup.editor.selectline(lineno - 1)
+
+    def selectline(self, lineno, charoffset = 0):
+        self.editgroup.editor.selectline(lineno - 1, charoffset)
+
+    def addrecentfile(self, filename):
+        app = W.getapplication()
+        app.addrecentfile(filename)
 
 class _saveoptions:
-	
-	def __init__(self, creator, eoln):
-		self.rv = None
-		self.eoln = eoln
-		self.w = w = W.ModalDialog((260, 160), 'Save options')
-		radiobuttons = []
-		w.label = W.TextBox((8, 8, 80, 18), "File creator:")
-		w.ide_radio = W.RadioButton((8, 22, 160, 18), "PythonIDE", radiobuttons, self.ide_hit)
-		w.interp_radio = W.RadioButton((8, 42, 160, 18), "MacPython-OS9 Interpreter", radiobuttons, self.interp_hit)
-		w.interpx_radio = W.RadioButton((8, 62, 160, 18), "PythonLauncher", radiobuttons, self.interpx_hit)
-		w.other_radio = W.RadioButton((8, 82, 50, 18), "Other:", radiobuttons)
-		w.other_creator = W.EditText((62, 82, 40, 20), creator, self.otherselect)
-		w.none_radio = W.RadioButton((8, 102, 160, 18), "None", radiobuttons, self.none_hit)
-		w.cancelbutton = W.Button((-180, -30, 80, 16), "Cancel", self.cancelbuttonhit)
-		w.okbutton = W.Button((-90, -30, 80, 16), "Done", self.okbuttonhit)
-		w.setdefaultbutton(w.okbutton)
-		if creator == 'Pyth':
-			w.interp_radio.set(1)
-		elif creator == W._signature:
-			w.ide_radio.set(1)
-		elif creator == 'PytX':
-			w.interpx_radio.set(1)
-		elif creator == '\0\0\0\0':
-			w.none_radio.set(1)
-		else:
-			w.other_radio.set(1)
-			
-		w.eolnlabel = W.TextBox((168, 8, 80, 18), "Newline style:")
-		radiobuttons = []
-		w.unix_radio = W.RadioButton((168, 22, 80, 18), "Unix", radiobuttons, self.unix_hit)
-		w.mac_radio = W.RadioButton((168, 42, 80, 18), "Macintosh", radiobuttons, self.mac_hit)
-		w.win_radio = W.RadioButton((168, 62, 80, 18), "Windows", radiobuttons, self.win_hit)
-		if self.eoln == '\n':
-			w.unix_radio.set(1)
-		elif self.eoln == '\r\n':
-			w.win_radio.set(1)
-		else:
-			w.mac_radio.set(1)
-		
-		w.bind("cmd.", w.cancelbutton.push)
-		w.open()
-	
-	def ide_hit(self):
-		self.w.other_creator.set(W._signature)
-	
-	def interp_hit(self):
-		self.w.other_creator.set("Pyth")
-	
-	def interpx_hit(self):
-		self.w.other_creator.set("PytX")
-	
-	def none_hit(self):
-		self.w.other_creator.set("\0\0\0\0")
-	
-	def otherselect(self, *args):
-		sel_from, sel_to = self.w.other_creator.getselection()
-		creator = self.w.other_creator.get()[:4]
-		creator = creator + " " * (4 - len(creator))
-		self.w.other_creator.set(creator)
-		self.w.other_creator.setselection(sel_from, sel_to)
-		self.w.other_radio.set(1)
-	
-	def mac_hit(self):
-		self.eoln = '\r'
-		
-	def unix_hit(self):
-		self.eoln = '\n'
-		
-	def win_hit(self):
-		self.eoln = '\r\n'
-		
-	def cancelbuttonhit(self):
-		self.w.close()
-	
-	def okbuttonhit(self):
-		self.rv = (self.w.other_creator.get()[:4], self.eoln)
-		self.w.close()
+
+    def __init__(self, creator, eoln):
+        self.rv = None
+        self.eoln = eoln
+        self.w = w = W.ModalDialog((260, 160), 'Save options')
+        radiobuttons = []
+        w.label = W.TextBox((8, 8, 80, 18), "File creator:")
+        w.ide_radio = W.RadioButton((8, 22, 160, 18), "PythonIDE", radiobuttons, self.ide_hit)
+        w.interp_radio = W.RadioButton((8, 42, 160, 18), "MacPython-OS9 Interpreter", radiobuttons, self.interp_hit)
+        w.interpx_radio = W.RadioButton((8, 62, 160, 18), "PythonLauncher", radiobuttons, self.interpx_hit)
+        w.other_radio = W.RadioButton((8, 82, 50, 18), "Other:", radiobuttons)
+        w.other_creator = W.EditText((62, 82, 40, 20), creator, self.otherselect)
+        w.none_radio = W.RadioButton((8, 102, 160, 18), "None", radiobuttons, self.none_hit)
+        w.cancelbutton = W.Button((-180, -30, 80, 16), "Cancel", self.cancelbuttonhit)
+        w.okbutton = W.Button((-90, -30, 80, 16), "Done", self.okbuttonhit)
+        w.setdefaultbutton(w.okbutton)
+        if creator == 'Pyth':
+            w.interp_radio.set(1)
+        elif creator == W._signature:
+            w.ide_radio.set(1)
+        elif creator == 'PytX':
+            w.interpx_radio.set(1)
+        elif creator == '\0\0\0\0':
+            w.none_radio.set(1)
+        else:
+            w.other_radio.set(1)
+
+        w.eolnlabel = W.TextBox((168, 8, 80, 18), "Newline style:")
+        radiobuttons = []
+        w.unix_radio = W.RadioButton((168, 22, 80, 18), "Unix", radiobuttons, self.unix_hit)
+        w.mac_radio = W.RadioButton((168, 42, 80, 18), "Macintosh", radiobuttons, self.mac_hit)
+        w.win_radio = W.RadioButton((168, 62, 80, 18), "Windows", radiobuttons, self.win_hit)
+        if self.eoln == '\n':
+            w.unix_radio.set(1)
+        elif self.eoln == '\r\n':
+            w.win_radio.set(1)
+        else:
+            w.mac_radio.set(1)
+
+        w.bind("cmd.", w.cancelbutton.push)
+        w.open()
+
+    def ide_hit(self):
+        self.w.other_creator.set(W._signature)
+
+    def interp_hit(self):
+        self.w.other_creator.set("Pyth")
+
+    def interpx_hit(self):
+        self.w.other_creator.set("PytX")
+
+    def none_hit(self):
+        self.w.other_creator.set("\0\0\0\0")
+
+    def otherselect(self, *args):
+        sel_from, sel_to = self.w.other_creator.getselection()
+        creator = self.w.other_creator.get()[:4]
+        creator = creator + " " * (4 - len(creator))
+        self.w.other_creator.set(creator)
+        self.w.other_creator.setselection(sel_from, sel_to)
+        self.w.other_radio.set(1)
+
+    def mac_hit(self):
+        self.eoln = '\r'
+
+    def unix_hit(self):
+        self.eoln = '\n'
+
+    def win_hit(self):
+        self.eoln = '\r\n'
+
+    def cancelbuttonhit(self):
+        self.w.close()
+
+    def okbuttonhit(self):
+        self.rv = (self.w.other_creator.get()[:4], self.eoln)
+        self.w.close()
 
 
 def SaveOptions(creator, eoln):
-	s = _saveoptions(creator, eoln)
-	return s.rv
+    s = _saveoptions(creator, eoln)
+    return s.rv
 
 
-def _escape(where, what) : 
-	return string.join(string.split(where, what), '\\' + what)
+def _escape(where, what) :
+    return string.join(string.split(where, what), '\\' + what)
 
 def _makewholewordpattern(word):
-	# first, escape special regex chars
-	for esc in "\\[]()|.*^+$?":
-		word = _escape(word, esc)
-	notwordcharspat = '[^' + _wordchars + ']'
-	pattern = '(' + word + ')'
-	if word[0] in _wordchars:
-		pattern = notwordcharspat + pattern
-	if word[-1] in _wordchars:
-		pattern = pattern + notwordcharspat
-	return re.compile(pattern)
+    # first, escape special regex chars
+    for esc in "\\[]()|.*^+$?":
+        word = _escape(word, esc)
+    notwordcharspat = '[^' + _wordchars + ']'
+    pattern = '(' + word + ')'
+    if word[0] in _wordchars:
+        pattern = notwordcharspat + pattern
+    if word[-1] in _wordchars:
+        pattern = pattern + notwordcharspat
+    return re.compile(pattern)
 
 
 class SearchEngine:
-	
-	def __init__(self):
-		self.visible = 0
-		self.w = None
-		self.parms = {  "find": "",
-					"replace": "",
-					"wrap": 1,
-					"casesens": 1,
-					"wholeword": 1
-				}
-		import MacPrefs
-		prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
-		if prefs.searchengine:
-			self.parms["casesens"] = prefs.searchengine.casesens
-			self.parms["wrap"] = prefs.searchengine.wrap
-			self.parms["wholeword"] = prefs.searchengine.wholeword
-	
-	def show(self):
-		self.visible = 1
-		if self.w:
-			self.w.wid.ShowWindow()
-			self.w.wid.SelectWindow()
-			self.w.find.edit.select(1)
-			self.w.find.edit.selectall()
-			return
-		self.w = W.Dialog((420, 150), "Find")
-		
-		self.w.find = TitledEditText((10, 4, 300, 36), "Search for:")
-		self.w.replace = TitledEditText((10, 100, 300, 36), "Replace with:")
-		
-		self.w.boxes = W.Group((10, 50, 300, 40))
-		self.w.boxes.casesens = W.CheckBox((0, 0, 100, 16), "Case sensitive")
-		self.w.boxes.wholeword = W.CheckBox((0, 20, 100, 16), "Whole word")
-		self.w.boxes.wrap = W.CheckBox((110, 0, 100, 16), "Wrap around")
-		
-		self.buttons = [	("Find",		"cmdf",	 self.find), 
-					("Replace",	     "cmdr",	 self.replace), 
-					("Replace all",	 None,   self.replaceall), 
-					("Don't find",  "cmdd",	 self.dont), 
-					("Cancel",	      "cmd.",	 self.cancel)
-				]
-		for i in range(len(self.buttons)):
-			bounds = -90, 22 + i * 24, 80, 16
-			title, shortcut, callback = self.buttons[i]
-			self.w[title] = W.Button(bounds, title, callback)
-			if shortcut:
-				self.w.bind(shortcut, self.w[title].push)
-		self.w.setdefaultbutton(self.w["Don't find"])
-		self.w.find.edit.bind("<key>", self.key)
-		self.w.bind("<activate>", self.activate)
-		self.w.bind("<close>", self.close)
-		self.w.open()
-		self.setparms()
-		self.w.find.edit.select(1)
-		self.w.find.edit.selectall()
-		self.checkbuttons()
-	
-	def close(self):
-		self.hide()
-		return -1
-	
-	def key(self, char, modifiers):
-		self.w.find.edit.key(char, modifiers)
-		self.checkbuttons()
-		return 1
-	
-	def activate(self, onoff):
-		if onoff:
-			self.checkbuttons()
-	
-	def checkbuttons(self):
-		editor = findeditor(self)
-		if editor:
-			if self.w.find.get():
-				for title, cmd, call in self.buttons[:-2]:
-					self.w[title].enable(1)
-				self.w.setdefaultbutton(self.w["Find"])
-			else:
-				for title, cmd, call in self.buttons[:-2]:
-					self.w[title].enable(0)
-				self.w.setdefaultbutton(self.w["Don't find"])
-		else:
-			for title, cmd, call in self.buttons[:-2]:
-				self.w[title].enable(0)
-			self.w.setdefaultbutton(self.w["Don't find"])
-	
-	def find(self):
-		self.getparmsfromwindow()
-		if self.findnext():
-			self.hide()
-	
-	def replace(self):
-		editor = findeditor(self)
-		if not editor:
-			return
-		if self.visible:
-			self.getparmsfromwindow()
-		text = editor.getselectedtext()
-		find = self.parms["find"]
-		if not self.parms["casesens"]:
-			find = string.lower(find)
-			text = string.lower(text)
-		if text == find:
-			self.hide()
-			editor.insert(self.parms["replace"])
-	
-	def replaceall(self):
-		editor = findeditor(self)
-		if not editor:
-			return
-		if self.visible:
-			self.getparmsfromwindow()
-		W.SetCursor("watch")
-		find = self.parms["find"]
-		if not find:
-			return
-		findlen = len(find)
-		replace = self.parms["replace"]
-		replacelen = len(replace)
-		Text = editor.get()
-		if not self.parms["casesens"]:
-			find = string.lower(find)
-			text = string.lower(Text)
-		else:
-			text = Text
-		newtext = ""
-		pos = 0
-		counter = 0
-		while 1:
-			if self.parms["wholeword"]:
-				wholewordRE = _makewholewordpattern(find)
-				match = wholewordRE.search(text, pos)
-				if match:
-					pos = match.start(1)
-				else:
-					pos = -1
-			else:
-				pos = string.find(text, find, pos)
-			if pos < 0:
-				break
-			counter = counter + 1
-			text = text[:pos] + replace + text[pos + findlen:]
-			Text = Text[:pos] + replace + Text[pos + findlen:]
-			pos = pos + replacelen
-		W.SetCursor("arrow")
-		if counter:
-			self.hide()
-			from Carbon import Res
-			editor.textchanged()
-			editor.selectionchanged()
-			editor.set(Text)
-			EasyDialogs.Message("Replaced %d occurrences" % counter)
-	
-	def dont(self):
-		self.getparmsfromwindow()
-		self.hide()
-	
-	def replacefind(self):
-		self.replace()
-		self.findnext()
-	
-	def setfindstring(self):
-		editor = findeditor(self)
-		if not editor:
-			return
-		find = editor.getselectedtext()
-		if not find:
-			return
-		self.parms["find"] = find
-		if self.w:
-			self.w.find.edit.set(self.parms["find"])
-			self.w.find.edit.selectall()
-	
-	def findnext(self):
-		editor = findeditor(self)
-		if not editor:
-			return
-		find = self.parms["find"]
-		if not find:
-			return
-		text = editor.get()
-		if not self.parms["casesens"]:
-			find = string.lower(find)
-			text = string.lower(text)
-		selstart, selend = editor.getselection()
-		selstart, selend = min(selstart, selend), max(selstart, selend)
-		if self.parms["wholeword"]:
-			wholewordRE = _makewholewordpattern(find)
-			match = wholewordRE.search(text, selend)
-			if match:
-				pos = match.start(1)
-			else:
-				pos = -1
-		else:
-			pos = string.find(text, find, selend)
-		if pos >= 0:
-			editor.setselection(pos, pos + len(find))
-			return 1
-		elif self.parms["wrap"]:
-			if self.parms["wholeword"]:
-				match = wholewordRE.search(text, 0)
-				if match:
-					pos = match.start(1)
-				else:
-					pos = -1
-			else:
-				pos = string.find(text, find)
-			if selstart > pos >= 0:
-				editor.setselection(pos, pos + len(find))
-				return 1
-	
-	def setparms(self):
-		for key, value in self.parms.items():
-			try:
-				self.w[key].set(value)
-			except KeyError:
-				self.w.boxes[key].set(value)
-	
-	def getparmsfromwindow(self):
-		if not self.w:
-			return
-		for key, value in self.parms.items():
-			try:
-				value = self.w[key].get()
-			except KeyError:
-				value = self.w.boxes[key].get()
-			self.parms[key] = value
-	
-	def cancel(self):
-		self.hide()
-		self.setparms()
-	
-	def hide(self):
-		if self.w:
-			self.w.wid.HideWindow()
-			self.visible = 0
-	
-	def writeprefs(self):
-		import MacPrefs
-		self.getparmsfromwindow()
-		prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
-		prefs.searchengine.casesens = self.parms["casesens"]
-		prefs.searchengine.wrap = self.parms["wrap"]
-		prefs.searchengine.wholeword = self.parms["wholeword"]
-		prefs.save()
-	
+
+    def __init__(self):
+        self.visible = 0
+        self.w = None
+        self.parms = {  "find": "",
+                                "replace": "",
+                                "wrap": 1,
+                                "casesens": 1,
+                                "wholeword": 1
+                        }
+        import MacPrefs
+        prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
+        if prefs.searchengine:
+            self.parms["casesens"] = prefs.searchengine.casesens
+            self.parms["wrap"] = prefs.searchengine.wrap
+            self.parms["wholeword"] = prefs.searchengine.wholeword
+
+    def show(self):
+        self.visible = 1
+        if self.w:
+            self.w.wid.ShowWindow()
+            self.w.wid.SelectWindow()
+            self.w.find.edit.select(1)
+            self.w.find.edit.selectall()
+            return
+        self.w = W.Dialog((420, 150), "Find")
+
+        self.w.find = TitledEditText((10, 4, 300, 36), "Search for:")
+        self.w.replace = TitledEditText((10, 100, 300, 36), "Replace with:")
+
+        self.w.boxes = W.Group((10, 50, 300, 40))
+        self.w.boxes.casesens = W.CheckBox((0, 0, 100, 16), "Case sensitive")
+        self.w.boxes.wholeword = W.CheckBox((0, 20, 100, 16), "Whole word")
+        self.w.boxes.wrap = W.CheckBox((110, 0, 100, 16), "Wrap around")
+
+        self.buttons = [        ("Find",                "cmdf",  self.find),
+                                ("Replace",          "cmdr",     self.replace),
+                                ("Replace all",  None,   self.replaceall),
+                                ("Don't find",  "cmdd",  self.dont),
+                                ("Cancel",            "cmd.",    self.cancel)
+                        ]
+        for i in range(len(self.buttons)):
+            bounds = -90, 22 + i * 24, 80, 16
+            title, shortcut, callback = self.buttons[i]
+            self.w[title] = W.Button(bounds, title, callback)
+            if shortcut:
+                self.w.bind(shortcut, self.w[title].push)
+        self.w.setdefaultbutton(self.w["Don't find"])
+        self.w.find.edit.bind("<key>", self.key)
+        self.w.bind("<activate>", self.activate)
+        self.w.bind("<close>", self.close)
+        self.w.open()
+        self.setparms()
+        self.w.find.edit.select(1)
+        self.w.find.edit.selectall()
+        self.checkbuttons()
+
+    def close(self):
+        self.hide()
+        return -1
+
+    def key(self, char, modifiers):
+        self.w.find.edit.key(char, modifiers)
+        self.checkbuttons()
+        return 1
+
+    def activate(self, onoff):
+        if onoff:
+            self.checkbuttons()
+
+    def checkbuttons(self):
+        editor = findeditor(self)
+        if editor:
+            if self.w.find.get():
+                for title, cmd, call in self.buttons[:-2]:
+                    self.w[title].enable(1)
+                self.w.setdefaultbutton(self.w["Find"])
+            else:
+                for title, cmd, call in self.buttons[:-2]:
+                    self.w[title].enable(0)
+                self.w.setdefaultbutton(self.w["Don't find"])
+        else:
+            for title, cmd, call in self.buttons[:-2]:
+                self.w[title].enable(0)
+            self.w.setdefaultbutton(self.w["Don't find"])
+
+    def find(self):
+        self.getparmsfromwindow()
+        if self.findnext():
+            self.hide()
+
+    def replace(self):
+        editor = findeditor(self)
+        if not editor:
+            return
+        if self.visible:
+            self.getparmsfromwindow()
+        text = editor.getselectedtext()
+        find = self.parms["find"]
+        if not self.parms["casesens"]:
+            find = string.lower(find)
+            text = string.lower(text)
+        if text == find:
+            self.hide()
+            editor.insert(self.parms["replace"])
+
+    def replaceall(self):
+        editor = findeditor(self)
+        if not editor:
+            return
+        if self.visible:
+            self.getparmsfromwindow()
+        W.SetCursor("watch")
+        find = self.parms["find"]
+        if not find:
+            return
+        findlen = len(find)
+        replace = self.parms["replace"]
+        replacelen = len(replace)
+        Text = editor.get()
+        if not self.parms["casesens"]:
+            find = string.lower(find)
+            text = string.lower(Text)
+        else:
+            text = Text
+        newtext = ""
+        pos = 0
+        counter = 0
+        while 1:
+            if self.parms["wholeword"]:
+                wholewordRE = _makewholewordpattern(find)
+                match = wholewordRE.search(text, pos)
+                if match:
+                    pos = match.start(1)
+                else:
+                    pos = -1
+            else:
+                pos = string.find(text, find, pos)
+            if pos < 0:
+                break
+            counter = counter + 1
+            text = text[:pos] + replace + text[pos + findlen:]
+            Text = Text[:pos] + replace + Text[pos + findlen:]
+            pos = pos + replacelen
+        W.SetCursor("arrow")
+        if counter:
+            self.hide()
+            from Carbon import Res
+            editor.textchanged()
+            editor.selectionchanged()
+            editor.set(Text)
+            EasyDialogs.Message("Replaced %d occurrences" % counter)
+
+    def dont(self):
+        self.getparmsfromwindow()
+        self.hide()
+
+    def replacefind(self):
+        self.replace()
+        self.findnext()
+
+    def setfindstring(self):
+        editor = findeditor(self)
+        if not editor:
+            return
+        find = editor.getselectedtext()
+        if not find:
+            return
+        self.parms["find"] = find
+        if self.w:
+            self.w.find.edit.set(self.parms["find"])
+            self.w.find.edit.selectall()
+
+    def findnext(self):
+        editor = findeditor(self)
+        if not editor:
+            return
+        find = self.parms["find"]
+        if not find:
+            return
+        text = editor.get()
+        if not self.parms["casesens"]:
+            find = string.lower(find)
+            text = string.lower(text)
+        selstart, selend = editor.getselection()
+        selstart, selend = min(selstart, selend), max(selstart, selend)
+        if self.parms["wholeword"]:
+            wholewordRE = _makewholewordpattern(find)
+            match = wholewordRE.search(text, selend)
+            if match:
+                pos = match.start(1)
+            else:
+                pos = -1
+        else:
+            pos = string.find(text, find, selend)
+        if pos >= 0:
+            editor.setselection(pos, pos + len(find))
+            return 1
+        elif self.parms["wrap"]:
+            if self.parms["wholeword"]:
+                match = wholewordRE.search(text, 0)
+                if match:
+                    pos = match.start(1)
+                else:
+                    pos = -1
+            else:
+                pos = string.find(text, find)
+            if selstart > pos >= 0:
+                editor.setselection(pos, pos + len(find))
+                return 1
+
+    def setparms(self):
+        for key, value in self.parms.items():
+            try:
+                self.w[key].set(value)
+            except KeyError:
+                self.w.boxes[key].set(value)
+
+    def getparmsfromwindow(self):
+        if not self.w:
+            return
+        for key, value in self.parms.items():
+            try:
+                value = self.w[key].get()
+            except KeyError:
+                value = self.w.boxes[key].get()
+            self.parms[key] = value
+
+    def cancel(self):
+        self.hide()
+        self.setparms()
+
+    def hide(self):
+        if self.w:
+            self.w.wid.HideWindow()
+            self.visible = 0
+
+    def writeprefs(self):
+        import MacPrefs
+        self.getparmsfromwindow()
+        prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
+        prefs.searchengine.casesens = self.parms["casesens"]
+        prefs.searchengine.wrap = self.parms["wrap"]
+        prefs.searchengine.wholeword = self.parms["wholeword"]
+        prefs.save()
+
 
 class TitledEditText(W.Group):
-	
-	def __init__(self, possize, title, text = ""):
-		W.Group.__init__(self, possize)
-		self.title = W.TextBox((0, 0, 0, 16), title)
-		self.edit = W.EditText((0, 16, 0, 0), text)
-	
-	def set(self, value):
-		self.edit.set(value)
-	
-	def get(self):
-		return self.edit.get()
+
+    def __init__(self, possize, title, text = ""):
+        W.Group.__init__(self, possize)
+        self.title = W.TextBox((0, 0, 0, 16), title)
+        self.edit = W.EditText((0, 16, 0, 0), text)
+
+    def set(self, value):
+        self.edit.set(value)
+
+    def get(self):
+        return self.edit.get()
 
 
 class ClassFinder(W.PopupWidget):
-	
-	def click(self, point, modifiers):
-		W.SetCursor("watch")
-		self.set(self._parentwindow.getclasslist())
-		W.PopupWidget.click(self, point, modifiers)
+
+    def click(self, point, modifiers):
+        W.SetCursor("watch")
+        self.set(self._parentwindow.getclasslist())
+        W.PopupWidget.click(self, point, modifiers)
 
 
 def getminindent(lines):
-	indent = -1
-	for line in lines:
-		stripped = string.strip(line)
-		if not stripped or stripped[0] == '#':
-			continue
-		if indent < 0 or line[:indent] <> indent * '\t':
-			indent = 0
-			for c in line:
-				if c <> '\t':
-					break
-				indent = indent + 1
-	return indent
+    indent = -1
+    for line in lines:
+        stripped = string.strip(line)
+        if not stripped or stripped[0] == '#':
+            continue
+        if indent < 0 or line[:indent] <> indent * '\t':
+            indent = 0
+            for c in line:
+                if c <> '\t':
+                    break
+                indent = indent + 1
+    return indent
 
 
 def getoptionkey():
-	return not not ord(Evt.GetKeys()[7]) & 0x04
+    return not not ord(Evt.GetKeys()[7]) & 0x04
 
 
-def execstring(pytext, globals, locals, filename="<string>", debugging=0, 
-			modname="__main__", profiling=0):
-	if debugging:
-		import PyDebugger, bdb
-		BdbQuit = bdb.BdbQuit
-	else:
-		BdbQuit = 'BdbQuitDummyException'
-	pytext = string.split(pytext, '\r')
-	pytext = string.join(pytext, '\n') + '\n'
-	W.SetCursor("watch")
-	globals['__name__'] = modname
-	globals['__file__'] = filename
-	sys.argv = [filename]
-	try:
-		code = compile(pytext, filename, "exec")
-	except:
-		# XXXX BAAAADDD.... We let tracebackwindow decide to treat SyntaxError 
-		# special. That's wrong because THIS case is special (could be literal 
-		# overflow!) and SyntaxError could mean we need a traceback (syntax error 
-		# in imported module!!!
-		tracebackwindow.traceback(1, filename)
-		return
-	try:
-		if debugging:
-			PyDebugger.startfromhere()
-		else:
-			if hasattr(MacOS, 'EnableAppswitch'):
-				MacOS.EnableAppswitch(0)
-		try:
-			if profiling:
-				import profile, ProfileBrowser
-				p = profile.Profile()
-				p.set_cmd(filename)
-				try:
-					p.runctx(code, globals, locals)
-				finally:
-					import pstats
-					
-					stats = pstats.Stats(p)
-					ProfileBrowser.ProfileBrowser(stats)
-			else:
-				exec code in globals, locals
-		finally:
-			if hasattr(MacOS, 'EnableAppswitch'):
-				MacOS.EnableAppswitch(-1)
-	except W.AlertError, detail:
-		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 debugging:
-			sys.settrace(None)
-			PyDebugger.postmortem(sys.exc_type, sys.exc_value, sys.exc_traceback)
-			return
-		else:
-			tracebackwindow.traceback(1, filename)
-	if debugging:
-		sys.settrace(None)
-		PyDebugger.stop()
+def execstring(pytext, globals, locals, filename="<string>", debugging=0,
+                        modname="__main__", profiling=0):
+    if debugging:
+        import PyDebugger, bdb
+        BdbQuit = bdb.BdbQuit
+    else:
+        BdbQuit = 'BdbQuitDummyException'
+    pytext = string.split(pytext, '\r')
+    pytext = string.join(pytext, '\n') + '\n'
+    W.SetCursor("watch")
+    globals['__name__'] = modname
+    globals['__file__'] = filename
+    sys.argv = [filename]
+    try:
+        code = compile(pytext, filename, "exec")
+    except:
+        # XXXX BAAAADDD.... We let tracebackwindow decide to treat SyntaxError
+        # special. That's wrong because THIS case is special (could be literal
+        # overflow!) and SyntaxError could mean we need a traceback (syntax error
+        # in imported module!!!
+        tracebackwindow.traceback(1, filename)
+        return
+    try:
+        if debugging:
+            PyDebugger.startfromhere()
+        else:
+            if hasattr(MacOS, 'EnableAppswitch'):
+                MacOS.EnableAppswitch(0)
+        try:
+            if profiling:
+                import profile, ProfileBrowser
+                p = profile.Profile()
+                p.set_cmd(filename)
+                try:
+                    p.runctx(code, globals, locals)
+                finally:
+                    import pstats
+
+                    stats = pstats.Stats(p)
+                    ProfileBrowser.ProfileBrowser(stats)
+            else:
+                exec code in globals, locals
+        finally:
+            if hasattr(MacOS, 'EnableAppswitch'):
+                MacOS.EnableAppswitch(-1)
+    except W.AlertError, detail:
+        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 debugging:
+            sys.settrace(None)
+            PyDebugger.postmortem(sys.exc_type, sys.exc_value, sys.exc_traceback)
+            return
+        else:
+            tracebackwindow.traceback(1, filename)
+    if debugging:
+        sys.settrace(None)
+        PyDebugger.stop()
 
 
 _identifieRE = re.compile(r"[A-Za-z_][A-Za-z_0-9]*")
 
 def identifieRE_match(str):
-	match = _identifieRE.match(str)
-	if not match:
-		return -1
-	return match.end()
+    match = _identifieRE.match(str)
+    if not match:
+        return -1
+    return match.end()
 
 def _filename_as_modname(fname):
-	if fname[-3:] == '.py':
-		modname = fname[:-3]
-		match = _identifieRE.match(modname)
-		if match and match.start() == 0 and match.end() == len(modname):
-			return string.join(string.split(modname, '.'), '_')
+    if fname[-3:] == '.py':
+        modname = fname[:-3]
+        match = _identifieRE.match(modname)
+        if match and match.start() == 0 and match.end() == len(modname):
+            return string.join(string.split(modname, '.'), '_')
 
 def findeditor(topwindow, fromtop = 0):
-	wid = MyFrontWindow()
-	if not fromtop:
-		if topwindow.w and wid == topwindow.w.wid:
-			wid = topwindow.w.wid.GetNextWindow()
-	if not wid:
-		return
-	app = W.getapplication()
-	if app._windows.has_key(wid): # KeyError otherwise can happen in RoboFog :-(
-		window = W.getapplication()._windows[wid]
-	else:
-		return
-	if not isinstance(window, Editor):
-		return
-	return window.editgroup.editor
+    wid = MyFrontWindow()
+    if not fromtop:
+        if topwindow.w and wid == topwindow.w.wid:
+            wid = topwindow.w.wid.GetNextWindow()
+    if not wid:
+        return
+    app = W.getapplication()
+    if app._windows.has_key(wid): # KeyError otherwise can happen in RoboFog :-(
+        window = W.getapplication()._windows[wid]
+    else:
+        return
+    if not isinstance(window, Editor):
+        return
+    return window.editgroup.editor
 
 
 class _EditorDefaultSettings:
-	
-	def __init__(self):
-		self.template = "%s, %d point"
-		self.fontsettings, self.tabsettings, self.windowsize = geteditorprefs()
-		self.w = W.Dialog((328, 120), "Editor default settings")
-		self.w.setfontbutton = W.Button((8, 8, 80, 16), "Set font\xc9", self.dofont)
-		self.w.fonttext = W.TextBox((98, 10, -8, 14), self.template % (self.fontsettings[0], self.fontsettings[2]))
-		
-		self.w.picksizebutton = W.Button((8, 50, 80, 16), "Front window", self.picksize)
-		self.w.xsizelabel = W.TextBox((98, 32, 40, 14), "Width:")
-		self.w.ysizelabel = W.TextBox((148, 32, 40, 14), "Height:")
-		self.w.xsize = W.EditText((98, 48, 40, 20), repr(self.windowsize[0]))
-		self.w.ysize = W.EditText((148, 48, 40, 20), repr(self.windowsize[1]))
-		
-		self.w.cancelbutton = W.Button((-180, -26, 80, 16), "Cancel", self.cancel)
-		self.w.okbutton = W.Button((-90, -26, 80, 16), "Done", self.ok)
-		self.w.setdefaultbutton(self.w.okbutton)
-		self.w.bind('cmd.', self.w.cancelbutton.push)
-		self.w.open()
-	
-	def picksize(self):
-		app = W.getapplication()
-		editor = findeditor(self)
-		if editor is not None:
-			width, height = editor._parentwindow._bounds[2:]
-			self.w.xsize.set(repr(width))
-			self.w.ysize.set(repr(height))
-		else:
-			raise W.AlertError, "No edit window found"
-	
-	def dofont(self):
-		import FontSettings
-		settings = FontSettings.FontDialog(self.fontsettings, self.tabsettings)
-		if settings:
-			self.fontsettings, self.tabsettings = settings
-			sys.exc_traceback = None
-			self.w.fonttext.set(self.template % (self.fontsettings[0], self.fontsettings[2]))
-	
-	def close(self):
-		self.w.close()
-		del self.w
-	
-	def cancel(self):
-		self.close()
-	
-	def ok(self):
-		try:
-			width = string.atoi(self.w.xsize.get())
-		except:
-			self.w.xsize.select(1)
-			self.w.xsize.selectall()
-			raise W.AlertError, "Bad number for window width"
-		try:
-			height = string.atoi(self.w.ysize.get())
-		except:
-			self.w.ysize.select(1)
-			self.w.ysize.selectall()
-			raise W.AlertError, "Bad number for window height"
-		self.windowsize = width, height
-		seteditorprefs(self.fontsettings, self.tabsettings, self.windowsize)
-		self.close()
+
+    def __init__(self):
+        self.template = "%s, %d point"
+        self.fontsettings, self.tabsettings, self.windowsize = geteditorprefs()
+        self.w = W.Dialog((328, 120), "Editor default settings")
+        self.w.setfontbutton = W.Button((8, 8, 80, 16), "Set font\xc9", self.dofont)
+        self.w.fonttext = W.TextBox((98, 10, -8, 14), self.template % (self.fontsettings[0], self.fontsettings[2]))
+
+        self.w.picksizebutton = W.Button((8, 50, 80, 16), "Front window", self.picksize)
+        self.w.xsizelabel = W.TextBox((98, 32, 40, 14), "Width:")
+        self.w.ysizelabel = W.TextBox((148, 32, 40, 14), "Height:")
+        self.w.xsize = W.EditText((98, 48, 40, 20), repr(self.windowsize[0]))
+        self.w.ysize = W.EditText((148, 48, 40, 20), repr(self.windowsize[1]))
+
+        self.w.cancelbutton = W.Button((-180, -26, 80, 16), "Cancel", self.cancel)
+        self.w.okbutton = W.Button((-90, -26, 80, 16), "Done", self.ok)
+        self.w.setdefaultbutton(self.w.okbutton)
+        self.w.bind('cmd.', self.w.cancelbutton.push)
+        self.w.open()
+
+    def picksize(self):
+        app = W.getapplication()
+        editor = findeditor(self)
+        if editor is not None:
+            width, height = editor._parentwindow._bounds[2:]
+            self.w.xsize.set(repr(width))
+            self.w.ysize.set(repr(height))
+        else:
+            raise W.AlertError, "No edit window found"
+
+    def dofont(self):
+        import FontSettings
+        settings = FontSettings.FontDialog(self.fontsettings, self.tabsettings)
+        if settings:
+            self.fontsettings, self.tabsettings = settings
+            sys.exc_traceback = None
+            self.w.fonttext.set(self.template % (self.fontsettings[0], self.fontsettings[2]))
+
+    def close(self):
+        self.w.close()
+        del self.w
+
+    def cancel(self):
+        self.close()
+
+    def ok(self):
+        try:
+            width = string.atoi(self.w.xsize.get())
+        except:
+            self.w.xsize.select(1)
+            self.w.xsize.selectall()
+            raise W.AlertError, "Bad number for window width"
+        try:
+            height = string.atoi(self.w.ysize.get())
+        except:
+            self.w.ysize.select(1)
+            self.w.ysize.selectall()
+            raise W.AlertError, "Bad number for window height"
+        self.windowsize = width, height
+        seteditorprefs(self.fontsettings, self.tabsettings, self.windowsize)
+        self.close()
 
 def geteditorprefs():
-	import MacPrefs
-	prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
-	try:
-		fontsettings = prefs.pyedit.fontsettings
-		tabsettings = prefs.pyedit.tabsettings
-		windowsize = prefs.pyedit.windowsize
-	except:
-		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
-	return fontsettings, tabsettings, windowsize
+    import MacPrefs
+    prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
+    try:
+        fontsettings = prefs.pyedit.fontsettings
+        tabsettings = prefs.pyedit.tabsettings
+        windowsize = prefs.pyedit.windowsize
+    except:
+        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
+    return fontsettings, tabsettings, windowsize
 
 def seteditorprefs(fontsettings, tabsettings, windowsize):
-	import MacPrefs
-	prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
-	prefs.pyedit.fontsettings = fontsettings
-	prefs.pyedit.tabsettings = tabsettings
-	prefs.pyedit.windowsize = windowsize
-	prefs.save()
+    import MacPrefs
+    prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
+    prefs.pyedit.fontsettings = fontsettings
+    prefs.pyedit.tabsettings = tabsettings
+    prefs.pyedit.windowsize = windowsize
+    prefs.save()
 
 _defaultSettingsEditor = None
 
 def EditorDefaultSettings():
-	global _defaultSettingsEditor
-	if _defaultSettingsEditor is None or not hasattr(_defaultSettingsEditor, "w"):
-		_defaultSettingsEditor = _EditorDefaultSettings()
-	else:
-		_defaultSettingsEditor.w.select()
+    global _defaultSettingsEditor
+    if _defaultSettingsEditor is None or not hasattr(_defaultSettingsEditor, "w"):
+        _defaultSettingsEditor = _EditorDefaultSettings()
+    else:
+        _defaultSettingsEditor.w.select()
 
 def resolvealiases(path):
-	try:
-		fsr, d1, d2 = File.FSResolveAliasFile(path, 1)
-		path = fsr.as_pathname()
-		return path
-	except (File.Error, ValueError), (error, str):
-		if error <> -120:
-			raise
-		dir, file = os.path.split(path)
-		return os.path.join(resolvealiases(dir), file)
+    try:
+        fsr, d1, d2 = File.FSResolveAliasFile(path, 1)
+        path = fsr.as_pathname()
+        return path
+    except (File.Error, ValueError), (error, str):
+        if error <> -120:
+            raise
+        dir, file = os.path.split(path)
+        return os.path.join(resolvealiases(dir), file)
 
 searchengine = SearchEngine()
 tracebackwindow = Wtraceback.TraceBack()
diff --git a/Mac/Tools/IDE/PyFontify.py b/Mac/Tools/IDE/PyFontify.py
index eb37ad3..41f1942 100644
--- a/Mac/Tools/IDE/PyFontify.py
+++ b/Mac/Tools/IDE/PyFontify.py
@@ -1,29 +1,29 @@
 """Module to analyze Python source code; for syntax coloring tools.
 
 Interface:
-	tags = fontify(pytext, searchfrom, searchto)
+        tags = fontify(pytext, searchfrom, searchto)
 
 The 'pytext' argument is a string containing Python source code.
-The (optional) arguments 'searchfrom' and 'searchto' may contain a slice in pytext. 
+The (optional) arguments 'searchfrom' and 'searchto' may contain a slice in pytext.
 The returned value is a list of tuples, formatted like this:
-	[('keyword', 0, 6, None), ('keyword', 11, 17, None), ('comment', 23, 53, None), etc. ]
+        [('keyword', 0, 6, None), ('keyword', 11, 17, None), ('comment', 23, 53, None), etc. ]
 The tuple contents are always like this:
-	(tag, startindex, endindex, sublist)
+        (tag, startindex, endindex, sublist)
 tag is one of 'keyword', 'string', 'comment' or 'identifier'
-sublist is not used, hence always None. 
+sublist is not used, hence always None.
 """
 
 # Based on FontText.py by Mitchell S. Chapman,
 # which was modified by Zachary Roadhouse,
 # then un-Tk'd by Just van Rossum.
 # Many thanks for regular expression debugging & authoring are due to:
-#	Tim (the-incredib-ly y'rs) Peters and Cristian Tismer
+#       Tim (the-incredib-ly y'rs) Peters and Cristian Tismer
 # So, who owns the copyright? ;-) How about this:
-# Copyright 1996-2001: 
-#	Mitchell S. Chapman,
-#	Zachary Roadhouse,
-#	Tim Peters,
-#	Just van Rossum
+# Copyright 1996-2001:
+#       Mitchell S. Chapman,
+#       Zachary Roadhouse,
+#       Tim Peters,
+#       Just van Rossum
 
 __version__ = "0.4"
 
@@ -33,18 +33,18 @@
 # First a little helper, since I don't like to repeat things. (Tismer speaking)
 import string
 def replace(where, what, with):
-	return string.join(string.split(where, what), with)
+    return string.join(string.split(where, what), with)
 
 # This list of keywords is taken from ref/node13.html of the
 # Python 1.3 HTML documentation. ("access" is intentionally omitted.)
 keywordsList = [
-	"assert", "exec",
-	"del", "from", "lambda", "return",
-	"and", "elif", "global", "not", "try",
-	"break", "else", "if", "or", "while",
-	"class", "except", "import", "pass",
-	"continue", "finally", "in", "print",
-	"def", "for", "is", "raise", "yield"]
+        "assert", "exec",
+        "del", "from", "lambda", "return",
+        "and", "elif", "global", "not", "try",
+        "break", "else", "if", "or", "while",
+        "class", "except", "import", "pass",
+        "continue", "finally", "in", "print",
+        "def", "for", "is", "raise", "yield"]
 
 # Build up a regular expression which will match anything
 # interesting, including multi-line triple-quoted strings.
@@ -55,24 +55,24 @@
 
 # Way to go, Tim!
 pat = r"""
-	qqq
-	[^\\q]*
-	(
-		(	\\[\000-\377]
-		|	q
-			(	\\[\000-\377]
-			|	[^\q]
-			|	q
-				(	\\[\000-\377]
-				|	[^\\q]
-				)
-			)
-		)
-		[^\\q]*
-	)*
-	qqq
+        qqq
+        [^\\q]*
+        (
+                (       \\[\000-\377]
+                |       q
+                        (       \\[\000-\377]
+                        |       [^\q]
+                        |       q
+                                (       \\[\000-\377]
+                                |       [^\\q]
+                                )
+                        )
+                )
+                [^\\q]*
+        )*
+        qqq
 """
-pat = string.join(string.split(pat), '')	# get rid of whitespace
+pat = string.join(string.split(pat), '')        # get rid of whitespace
 tripleQuotePat = replace(pat, "q", "'") + "|" + replace(pat, 'q', '"')
 
 # Build up a regular expression which matches all and only
@@ -87,69 +87,69 @@
 matchPat = commentPat + "|" + keyPat + "|" + tripleQuotePat + "|" + quotePat
 matchRE = re.compile(matchPat)
 
-idKeyPat = "[ \t]*[A-Za-z_][A-Za-z_0-9.]*"	# Ident w. leading whitespace.
+idKeyPat = "[ \t]*[A-Za-z_][A-Za-z_0-9.]*"      # Ident w. leading whitespace.
 idRE = re.compile(idKeyPat)
 
 
 def fontify(pytext, searchfrom = 0, searchto = None):
-	if searchto is None:
-		searchto = len(pytext)
-	# Cache a few attributes for quicker reference.
-	search = matchRE.search
-	idSearch = idRE.search
-	
-	tags = []
-	tags_append = tags.append
-	commentTag = 'comment'
-	stringTag = 'string'
-	keywordTag = 'keyword'
-	identifierTag = 'identifier'
-	
-	start = 0
-	end = searchfrom
-	while 1:
-		m = search(pytext, end)
-		if m is None:
-			break	# EXIT LOOP
-		start = m.start()
-		if start >= searchto:
-			break	# EXIT LOOP
-		match = m.group(0)
-		end = start + len(match)
-		c = match[0]
-		if c not in "#'\"":
-			# Must have matched a keyword.
-			if start <> searchfrom:
-				# there's still a redundant char before and after it, strip!
-				match = match[1:-1]
-				start = start + 1
-			else:
-				# this is the first keyword in the text.
-				# Only a space at the end.
-				match = match[:-1]
-			end = end - 1
-			tags_append((keywordTag, start, end, None))
-			# If this was a defining keyword, look ahead to the
-			# following identifier.
-			if match in ["def", "class"]:
-				m = idSearch(pytext, end)
-				if m is not None:
-					start = m.start()
-					if start == end:
-						match = m.group(0)
-						end = start + len(match)
-						tags_append((identifierTag, start, end, None))
-		elif c == "#":
-			tags_append((commentTag, start, end, None))
-		else:
-			tags_append((stringTag, start, end, None))
-	return tags
+    if searchto is None:
+        searchto = len(pytext)
+    # Cache a few attributes for quicker reference.
+    search = matchRE.search
+    idSearch = idRE.search
+
+    tags = []
+    tags_append = tags.append
+    commentTag = 'comment'
+    stringTag = 'string'
+    keywordTag = 'keyword'
+    identifierTag = 'identifier'
+
+    start = 0
+    end = searchfrom
+    while 1:
+        m = search(pytext, end)
+        if m is None:
+            break   # EXIT LOOP
+        start = m.start()
+        if start >= searchto:
+            break   # EXIT LOOP
+        match = m.group(0)
+        end = start + len(match)
+        c = match[0]
+        if c not in "#'\"":
+            # Must have matched a keyword.
+            if start <> searchfrom:
+                # there's still a redundant char before and after it, strip!
+                match = match[1:-1]
+                start = start + 1
+            else:
+                # this is the first keyword in the text.
+                # Only a space at the end.
+                match = match[:-1]
+            end = end - 1
+            tags_append((keywordTag, start, end, None))
+            # If this was a defining keyword, look ahead to the
+            # following identifier.
+            if match in ["def", "class"]:
+                m = idSearch(pytext, end)
+                if m is not None:
+                    start = m.start()
+                    if start == end:
+                        match = m.group(0)
+                        end = start + len(match)
+                        tags_append((identifierTag, start, end, None))
+        elif c == "#":
+            tags_append((commentTag, start, end, None))
+        else:
+            tags_append((stringTag, start, end, None))
+    return tags
 
 
 def test(path):
-	f = open(path)
-	text = f.read()
-	f.close()
-	tags = fontify(text)
-	for tag, start, end, sublist in tags:
-		print tag, repr(text[start:end])
+    f = open(path)
+    text = f.read()
+    f.close()
+    tags = fontify(text)
+    for tag, start, end, sublist in tags:
+        print tag, repr(text[start:end])
diff --git a/Mac/Tools/IDE/PyInteractive.py b/Mac/Tools/IDE/PyInteractive.py
index 3ad02c5..987eec5 100644
--- a/Mac/Tools/IDE/PyInteractive.py
+++ b/Mac/Tools/IDE/PyInteractive.py
@@ -4,114 +4,114 @@
 
 
 try:
-	sys.ps1
+    sys.ps1
 except AttributeError:
-	sys.ps1 = ">>> "
+    sys.ps1 = ">>> "
 try:
-	sys.ps2
+    sys.ps2
 except AttributeError:
-	sys.ps2 = "... "
+    sys.ps2 = "... "
 
 
 def print_exc(limit=None, file=None):
-	if not file:
-		file = sys.stderr
-	# we're going to skip the outermost traceback object, we don't
-	# want people to see the line which excecuted their code.
-	tb = sys.exc_traceback
-	if tb:
-		tb = tb.tb_next
-	try:
-		sys.last_type = sys.exc_type
-		sys.last_value = sys.exc_value
-		sys.last_traceback = tb
-		traceback.print_exception(sys.last_type, sys.last_value, 
-					sys.last_traceback, limit, file)
-	except:
-		print '--- hola! ---'
-		traceback.print_exception(sys.exc_type, sys.exc_value, 
-					sys.exc_traceback, limit, file)
+    if not file:
+        file = sys.stderr
+    # we're going to skip the outermost traceback object, we don't
+    # want people to see the line which excecuted their code.
+    tb = sys.exc_traceback
+    if tb:
+        tb = tb.tb_next
+    try:
+        sys.last_type = sys.exc_type
+        sys.last_value = sys.exc_value
+        sys.last_traceback = tb
+        traceback.print_exception(sys.last_type, sys.last_value,
+                                sys.last_traceback, limit, file)
+    except:
+        print '--- hola! ---'
+        traceback.print_exception(sys.exc_type, sys.exc_value,
+                                sys.exc_traceback, limit, file)
 
 
 class PyInteractive:
-	
-	def __init__(self):
-		import codeop
-		self._pybuf = ""
-		self._compile = codeop.Compile()
-	
-	def executeline(self, stuff, out = None, env = None):
-		if env is None:
-			import __main__
-			env = __main__.__dict__
-		if out:
-			saveerr, saveout = sys.stderr, sys.stdout
-			sys.stderr = sys.stdout = out
-		try:
-			if self._pybuf:
-				self._pybuf = self._pybuf + '\n' + stuff
-			else:
-				self._pybuf = stuff
-			
-			# Compile three times: as is, with \n, and with \n\n appended.
-			# If it compiles as is, it's complete.  If it compiles with
-			# one \n appended, we expect more.  If it doesn't compile
-			# either way, we compare the error we get when compiling with
-			# \n or \n\n appended.  If the errors are the same, the code
-			# is broken.  But if the errors are different, we expect more.
-			# Not intuitive; not even guaranteed to hold in future
-			# releases; but this matches the compiler's behavior in Python
-			# 1.4 and 1.5.
-			err = err1 = err2 = None
-			code = code1 = code2 = None
-			
-			# quickly get out of here when the line is 'empty' or is a comment
-			stripped = string.strip(self._pybuf)
-			if not stripped or stripped[0] == '#':
-				self._pybuf = ''
-				sys.stdout.write(sys.ps1)
-				sys.stdout.flush()
-				return
-			
-			try:
-				code = self._compile(self._pybuf, "<input>", "single")
-			except SyntaxError, err:
-				pass
-			except:
-				# OverflowError. More?
-				print_exc()
-				self._pybuf = ""
-				sys.stdout.write(sys.ps1)
-				sys.stdout.flush()
-				return
-			
-			try:
-				code1 = self._compile(self._pybuf + "\n", "<input>", "single")
-			except SyntaxError, err1:
-				pass
-			
-			try:
-				code2 = self._compile(self._pybuf + "\n\n", "<input>", "single")
-			except SyntaxError, err2:
-				pass
-			
-			if code:
-				try:
-					exec code in env
-				except:
-					print_exc()
-				self._pybuf = ""
-			elif code1:
-				pass
-			elif err1 == err2 or (not stuff and self._pybuf):
-				print_exc()
-				self._pybuf = ""
-			if self._pybuf:
-				sys.stdout.write(sys.ps2)
-				sys.stdout.flush()
-			else:
-				sys.stdout.write(sys.ps1)
-				sys.stdout.flush()
-		finally:
-			if out:
-				sys.stderr, sys.stdout = saveerr, saveout
+
+    def __init__(self):
+        import codeop
+        self._pybuf = ""
+        self._compile = codeop.Compile()
+
+    def executeline(self, stuff, out = None, env = None):
+        if env is None:
+            import __main__
+            env = __main__.__dict__
+        if out:
+            saveerr, saveout = sys.stderr, sys.stdout
+            sys.stderr = sys.stdout = out
+        try:
+            if self._pybuf:
+                self._pybuf = self._pybuf + '\n' + stuff
+            else:
+                self._pybuf = stuff
+
+            # Compile three times: as is, with \n, and with \n\n appended.
+            # If it compiles as is, it's complete.  If it compiles with
+            # one \n appended, we expect more.  If it doesn't compile
+            # either way, we compare the error we get when compiling with
+            # \n or \n\n appended.  If the errors are the same, the code
+            # is broken.  But if the errors are different, we expect more.
+            # Not intuitive; not even guaranteed to hold in future
+            # releases; but this matches the compiler's behavior in Python
+            # 1.4 and 1.5.
+            err = err1 = err2 = None
+            code = code1 = code2 = None
+
+            # quickly get out of here when the line is 'empty' or is a comment
+            stripped = string.strip(self._pybuf)
+            if not stripped or stripped[0] == '#':
+                self._pybuf = ''
+                sys.stdout.write(sys.ps1)
+                sys.stdout.flush()
+                return
+
+            try:
+                code = self._compile(self._pybuf, "<input>", "single")
+            except SyntaxError, err:
+                pass
+            except:
+                # OverflowError. More?
+                print_exc()
+                self._pybuf = ""
+                sys.stdout.write(sys.ps1)
+                sys.stdout.flush()
+                return
+
+            try:
+                code1 = self._compile(self._pybuf + "\n", "<input>", "single")
+            except SyntaxError, err1:
+                pass
+
+            try:
+                code2 = self._compile(self._pybuf + "\n\n", "<input>", "single")
+            except SyntaxError, err2:
+                pass
+
+            if code:
+                try:
+                    exec code in env
+                except:
+                    print_exc()
+                self._pybuf = ""
+            elif code1:
+                pass
+            elif err1 == err2 or (not stuff and self._pybuf):
+                print_exc()
+                self._pybuf = ""
+            if self._pybuf:
+                sys.stdout.write(sys.ps2)
+                sys.stdout.flush()
+            else:
+                sys.stdout.write(sys.ps1)
+                sys.stdout.flush()
+        finally:
+            if out:
+                sys.stderr, sys.stdout = saveerr, saveout
diff --git a/Mac/Tools/IDE/PythonIDE.py b/Mac/Tools/IDE/PythonIDE.py
index 1ea7711..b8f54a9 100644
--- a/Mac/Tools/IDE/PythonIDE.py
+++ b/Mac/Tools/IDE/PythonIDE.py
@@ -1,6 +1,6 @@
 # copyright 1996-2001 Just van Rossum, Letterror. just@letterror.com
 
-# keep this (__main__) as clean as possible, since we are using 
+# keep this (__main__) as clean as possible, since we are using
 # it like the "normal" interpreter.
 
 __version__ = '1.0.2'
@@ -8,48 +8,48 @@
 import os
 
 def init():
-	import MacOS
-	if hasattr(MacOS, 'EnableAppswitch'):
-		MacOS.EnableAppswitch(-1)
-	
-	try:
-		import autoGIL
-	except ImportError:
-		pass
-	else:
-		autoGIL.installAutoGIL()
-	
-	from Carbon import Qd, QuickDraw
-	Qd.SetCursor(Qd.GetCursor(QuickDraw.watchCursor).data)
-	
-	import macresource
-	import sys, os
-	macresource.need('DITL', 468, "PythonIDE.rsrc")
-	widgetrespathsegs = [sys.exec_prefix, "Mac", "Tools", "IDE", "Widgets.rsrc"]
-	widgetresfile = os.path.join(*widgetrespathsegs)
-	if not os.path.exists(widgetresfile):
-		widgetrespathsegs = [os.pardir, "Tools", "IDE", "Widgets.rsrc"]
-		widgetresfile = os.path.join(*widgetrespathsegs)
-	refno = macresource.need('CURS', 468, widgetresfile)
-	if os.environ.has_key('PYTHONIDEPATH'):
-		# For development set this environment variable
-		ide_path = os.environ['PYTHONIDEPATH']
-	elif refno:
-		# We're not a fullblown application
-		idepathsegs = [sys.exec_prefix, "Mac", "Tools", "IDE"]
-		ide_path = os.path.join(*idepathsegs)
-		if not os.path.exists(ide_path):
-			idepathsegs = [os.pardir, "Tools", "IDE"]
-			for p in sys.path:
-				ide_path = os.path.join(*([p]+idepathsegs))
-				if os.path.exists(ide_path):
-					break
-		
-	else:
-		# We are a fully frozen application
-		ide_path = sys.argv[0]
-	if ide_path not in sys.path:
-		sys.path.insert(1, ide_path)
+    import MacOS
+    if hasattr(MacOS, 'EnableAppswitch'):
+        MacOS.EnableAppswitch(-1)
+
+    try:
+        import autoGIL
+    except ImportError:
+        pass
+    else:
+        autoGIL.installAutoGIL()
+
+    from Carbon import Qd, QuickDraw
+    Qd.SetCursor(Qd.GetCursor(QuickDraw.watchCursor).data)
+
+    import macresource
+    import sys, os
+    macresource.need('DITL', 468, "PythonIDE.rsrc")
+    widgetrespathsegs = [sys.exec_prefix, "Mac", "Tools", "IDE", "Widgets.rsrc"]
+    widgetresfile = os.path.join(*widgetrespathsegs)
+    if not os.path.exists(widgetresfile):
+        widgetrespathsegs = [os.pardir, "Tools", "IDE", "Widgets.rsrc"]
+        widgetresfile = os.path.join(*widgetrespathsegs)
+    refno = macresource.need('CURS', 468, widgetresfile)
+    if os.environ.has_key('PYTHONIDEPATH'):
+        # For development set this environment variable
+        ide_path = os.environ['PYTHONIDEPATH']
+    elif refno:
+        # We're not a fullblown application
+        idepathsegs = [sys.exec_prefix, "Mac", "Tools", "IDE"]
+        ide_path = os.path.join(*idepathsegs)
+        if not os.path.exists(ide_path):
+            idepathsegs = [os.pardir, "Tools", "IDE"]
+            for p in sys.path:
+                ide_path = os.path.join(*([p]+idepathsegs))
+                if os.path.exists(ide_path):
+                    break
+
+    else:
+        # We are a fully frozen application
+        ide_path = sys.argv[0]
+    if ide_path not in sys.path:
+        sys.path.insert(1, ide_path)
 
 
 init()
diff --git a/Mac/Tools/IDE/PythonIDEMain.py b/Mac/Tools/IDE/PythonIDEMain.py
index 111a0b0..4dbe92a 100644
--- a/Mac/Tools/IDE/PythonIDEMain.py
+++ b/Mac/Tools/IDE/PythonIDEMain.py
@@ -13,476 +13,476 @@
 from Carbon import Files
 
 if MacOS.runtimemodel == 'macho':
-	ELLIPSIS = '...'
+    ELLIPSIS = '...'
 else:
-	ELLIPSIS = '\xc9'
+    ELLIPSIS = '\xc9'
 
 def runningOnOSX():
-	from gestalt import gestalt
-	gestaltMenuMgrAquaLayoutBit = 1  # menus have the Aqua 1.0 layout
-	gestaltMenuMgrAquaLayoutMask = (1L << gestaltMenuMgrAquaLayoutBit)
-	value = gestalt("menu") & gestaltMenuMgrAquaLayoutMask
-	return not not value
+    from gestalt import gestalt
+    gestaltMenuMgrAquaLayoutBit = 1  # menus have the Aqua 1.0 layout
+    gestaltMenuMgrAquaLayoutMask = (1L << gestaltMenuMgrAquaLayoutBit)
+    value = gestalt("menu") & gestaltMenuMgrAquaLayoutMask
+    return not not value
 
 def getmodtime(file):
-	file = File.FSRef(file)
-	catinfo, d1, d2, d3 = file.FSGetCatalogInfo(Files.kFSCatInfoContentMod)
-	return catinfo.contentModDate
+    file = File.FSRef(file)
+    catinfo, d1, d2, d3 = file.FSGetCatalogInfo(Files.kFSCatInfoContentMod)
+    return catinfo.contentModDate
 
 class PythonIDE(Wapplication.Application):
-	
-	def __init__(self):
-		if sys.platform == "darwin":
-			if len(sys.argv) > 1 and sys.argv[1].startswith("-psn"):
-				home = os.getenv("HOME")
-				if home:
-					os.chdir(home)
-		self.preffilepath = os.path.join("Python", "PythonIDE preferences")
-		Wapplication.Application.__init__(self, 'Pide')
-		from Carbon import AE
-		from Carbon import AppleEvents
-		
-		AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEOpenApplication, 
-				self.ignoreevent)
-		AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEReopenApplication, 
-				self.ignoreevent)
-		AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEPrintDocuments, 
-				self.ignoreevent)
-		AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEOpenDocuments, 
-				self.opendocsevent)
-		AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEQuitApplication, 
-				self.quitevent)
-		import PyConsole, PyEdit
-		Splash.wait()
-		# With -D option (OSX command line only) keep stderr, for debugging the IDE
-		# itself.
-		debug_stderr = None
-		if len(sys.argv) >= 2 and sys.argv[1] == '-D':
-			debug_stderr = sys.stderr
-			del sys.argv[1]
-		PyConsole.installoutput()
-		PyConsole.installconsole()
-		if debug_stderr:
-			sys.stderr = debug_stderr
-		for path in sys.argv[1:]:
-			if path.startswith("-p"):
-				# process number added by the OS
-				continue
-			self.opendoc(path)
-		self.mainloop()
-	
-	def makeusermenus(self):
-		m = Wapplication.Menu(self.menubar, "File")
-		newitem = FrameWork.MenuItem(m, "New", "N", 'new')
-		openitem = FrameWork.MenuItem(m, "Open"+ELLIPSIS, "O", 'open')
-		openbynameitem = FrameWork.MenuItem(m, "Open File by Name"+ELLIPSIS, "D", 'openbyname')
-		self.openrecentmenu = FrameWork.SubMenu(m, "Open Recent")
-		self.makeopenrecentmenu()
-		FrameWork.Separator(m)
-		closeitem = FrameWork.MenuItem(m, "Close", "W", 'close')
-		saveitem = FrameWork.MenuItem(m, "Save", "S", 'save')
-		saveasitem = FrameWork.MenuItem(m, "Save as"+ELLIPSIS, None, 'save_as')
-		FrameWork.Separator(m)
-		saveasappletitem = FrameWork.MenuItem(m, "Save as Applet"+ELLIPSIS, None, 'save_as_applet')
-		FrameWork.Separator(m)
-		instmgritem = FrameWork.MenuItem(m, "Package Manager", None, 'openpackagemanager')
-		gensuiteitem = FrameWork.MenuItem(m, "Generate OSA Suite...", None, 'gensuite')
-		if not runningOnOSX():
-			# On OSX there's a special "magic" quit menu, so we shouldn't add
-			# it to the File menu.
-			FrameWork.Separator(m)
-			quititem = FrameWork.MenuItem(m, "Quit", "Q", 'quit')
-		
-		m = Wapplication.Menu(self.menubar, "Edit")
-		undoitem = FrameWork.MenuItem(m, "Undo", 'Z', "undo")
-		FrameWork.Separator(m)
-		cutitem = FrameWork.MenuItem(m, "Cut", 'X', "cut")
-		copyitem = FrameWork.MenuItem(m, "Copy", "C", "copy")
-		pasteitem = FrameWork.MenuItem(m, "Paste", "V", "paste")
-		FrameWork.MenuItem(m, "Clear", None,  "clear")
-		FrameWork.Separator(m)
-		selallitem = FrameWork.MenuItem(m, "Select all", "A", "selectall")
-		sellineitem = FrameWork.MenuItem(m, "Select line", "L", "selectline")
-		FrameWork.Separator(m)
-		finditem = FrameWork.MenuItem(m, "Find"+ELLIPSIS, "F", "find")
-		findagainitem = FrameWork.MenuItem(m, "Find again", 'G', "findnext")
-		enterselitem = FrameWork.MenuItem(m, "Enter search string", "E", "entersearchstring")
-		replaceitem = FrameWork.MenuItem(m, "Replace", None, "replace")
-		replacefinditem = FrameWork.MenuItem(m, "Replace & find again", 'T', "replacefind")
-		FrameWork.Separator(m)
-		shiftleftitem = FrameWork.MenuItem(m, "Shift left", "[", "shiftleft")
-		shiftrightitem = FrameWork.MenuItem(m, "Shift right", "]", "shiftright")
-		
-		m = Wapplication.Menu(self.menubar, "Python")
-		runitem = FrameWork.MenuItem(m, "Run window", "R", 'run')
-		runselitem = FrameWork.MenuItem(m, "Run selection", None, 'runselection')
-		FrameWork.Separator(m)
-		moditem = FrameWork.MenuItem(m, "Module browser"+ELLIPSIS, "M", self.domenu_modulebrowser)
-		FrameWork.Separator(m)
-		mm = FrameWork.SubMenu(m, "Preferences")
-		FrameWork.MenuItem(mm, "Set Scripts folder"+ELLIPSIS, None, self.do_setscriptsfolder)
-		FrameWork.MenuItem(mm, "Editor default settings"+ELLIPSIS, None, self.do_editorprefs)
-		FrameWork.MenuItem(mm, "Set default window font"+ELLIPSIS, None, self.do_setwindowfont)
-		
-		self.openwindowsmenu = Wapplication.Menu(self.menubar, 'Windows')
-		self.makeopenwindowsmenu()
-		self._menustocheck = [closeitem, saveitem, saveasitem, saveasappletitem,
-				undoitem, cutitem, copyitem, pasteitem, 
-				selallitem, sellineitem, 
-				finditem, findagainitem, enterselitem, replaceitem, replacefinditem,
-				shiftleftitem, shiftrightitem, 
-				runitem, runselitem]
-		
-		prefs = self.getprefs()
-		try:
-			fsr, d = File.Alias(rawdata=prefs.scriptsfolder).FSResolveAlias(None)
-			self.scriptsfolder = fsr.FSNewAliasMinimal()
-		except:
-			path = os.path.join(os.getcwd(), "Mac", "IDE scripts")
-			if not os.path.exists(path):
-				if sys.platform == "darwin":
-					path = os.path.join(os.getenv("HOME"), "Library", "Python", "IDE-Scripts")
-				else:
-					path = os.path.join(os.getcwd(), "Scripts")
-				if not os.path.exists(path):
-					os.makedirs(path)
-					f = open(os.path.join(path, "Place your scripts here"+ELLIPSIS), "w")
-					f.close()
-			fsr = File.FSRef(path)
-			self.scriptsfolder = fsr.FSNewAliasMinimal()
-			self.scriptsfoldermodtime = getmodtime(fsr)
-		else:
-			self.scriptsfoldermodtime = getmodtime(fsr)
-		prefs.scriptsfolder = self.scriptsfolder.data
-		self._scripts = {}
-		self.scriptsmenu = None
-		self.makescriptsmenu()
-		self.makehelpmenu()
-	
-	def quitevent(self, theAppleEvent, theReply):
-		self._quit()
-	
-	def suspendresume(self, onoff):
-		if onoff:
-			fsr, changed = self.scriptsfolder.FSResolveAlias(None)
-			modtime = getmodtime(fsr)
-			if self.scriptsfoldermodtime <> modtime or changed:
-				self.scriptsfoldermodtime = modtime
-				W.SetCursor('watch')
-				self.makescriptsmenu()
-	
-	def ignoreevent(self, theAppleEvent, theReply):
-		pass
-	
-	def opendocsevent(self, theAppleEvent, theReply):
-		W.SetCursor('watch')
-		import aetools
-		parameters, args = aetools.unpackevent(theAppleEvent)
-		docs = parameters['----']
-		if type(docs) <> type([]):
-			docs = [docs]
-		for doc in docs:
-			fsr, a = doc.FSResolveAlias(None)
-			path = fsr.as_pathname()
-			self.opendoc(path)
-	
-	def opendoc(self, path):
-		fcreator, ftype = MacOS.GetCreatorAndType(path)
-		if ftype == 'TEXT':
-			self.openscript(path)
-		elif ftype == '\0\0\0\0' and path[-3:] == '.py':
-			self.openscript(path)
-		else:
-			W.Message("Can't open file of type '%s'." % ftype)
-	
-	def getabouttext(self):
-		return "About Python IDE"+ELLIPSIS
-	
-	def do_about(self, id, item, window, event):
-		Splash.about()
-	
-	def do_setscriptsfolder(self, *args):
-		fsr = EasyDialogs.AskFolder(message="Select Scripts Folder",
-			wanted=File.FSRef)
-		if fsr:
-			prefs = self.getprefs()
-			alis = fsr.FSNewAliasMinimal()
-			prefs.scriptsfolder = alis.data
-			self.scriptsfolder = alis
-			self.makescriptsmenu()
-			prefs.save()
-	
-	def domenu_modulebrowser(self, *args):
-		W.SetCursor('watch')
-		import ModuleBrowser
-		ModuleBrowser.ModuleBrowser()
-	
-	def domenu_open(self, *args):
-		filename = EasyDialogs.AskFileForOpen(typeList=("TEXT",))
-		if filename:
-			self.openscript(filename)
-	
-	def domenu_openbyname(self, *args):
-		# Open a file by name. If the clipboard contains a filename
-		# use that as the default.
-		from Carbon import Scrap
-		try:
-			sc = Scrap.GetCurrentScrap()
-			dft = sc.GetScrapFlavorData("TEXT")
-		except Scrap.Error:
-			dft = ""
-		else:
-			if not os.path.exists(dft):
-				dft = ""
-		filename = EasyDialogs.AskString("Open File Named:", default=dft, ok="Open")
-		if filename:
-			self.openscript(filename)
-	
-	def domenu_new(self, *args):
-		W.SetCursor('watch')
-		import PyEdit
-		return PyEdit.Editor()
-	
-	def makescriptsmenu(self):
-		W.SetCursor('watch')
-		if self._scripts:
-			for id, item in self._scripts.keys():
-				if self.menubar.menus.has_key(id):
-					m = self.menubar.menus[id]
-					m.delete()
-			self._scripts = {}
-		if self.scriptsmenu:
-			if hasattr(self.scriptsmenu, 'id') and self.menubar.menus.has_key(self.scriptsmenu.id):
-				self.scriptsmenu.delete()
-		self.scriptsmenu = FrameWork.Menu(self.menubar, "Scripts")
-		#FrameWork.MenuItem(self.scriptsmenu, "New script", None, self.domenu_new)
-		#self.scriptsmenu.addseparator()
-		fsr, d1 = self.scriptsfolder.FSResolveAlias(None)
-		self.scriptswalk(fsr.as_pathname(), self.scriptsmenu)
-	
-	def makeopenwindowsmenu(self):
-		for i in range(len(self.openwindowsmenu.items)):
-			self.openwindowsmenu.menu.DeleteMenuItem(1)
-			self.openwindowsmenu.items = []
-		windows = []
-		self._openwindows = {}
-		for window in self._windows.keys():
-			title = window.GetWTitle()
-			if not title:
-				title = "<no title>"
-			windows.append((title, window))
-		windows.sort()
-		for title, window in windows:
-			if title == "Python Interactive":	# ugly but useful hack by Joe Strout
-				shortcut = '0'
-			else: 
-				shortcut = None
-			item = FrameWork.MenuItem(self.openwindowsmenu, title, shortcut, callback = self.domenu_openwindows)
-			self._openwindows[item.item] = window
-		self._openwindowscheckmark = 0
-		self.checkopenwindowsmenu()
-		
-	def makeopenrecentmenu(self):
-		for i in range(len(self.openrecentmenu.items)):
-			self.openrecentmenu.menu.DeleteMenuItem(1)
-			self.openrecentmenu.items = []
-		prefs = self.getprefs()
-		filelist = prefs.recentfiles
-		if not filelist:
-			self.openrecentmenu.enable(0)
-			return
-		self.openrecentmenu.enable(1)
-		for filename in filelist:
-			item = FrameWork.MenuItem(self.openrecentmenu, filename, None, callback = self.domenu_openrecent)
-		
-	def addrecentfile(self, file):
-		prefs = self.getprefs()
-		filelist = prefs.recentfiles
-		if not filelist:
-			filelist = []
-		
-		if file in filelist:
-			if file == filelist[0]:
-				return
-			filelist.remove(file)
-		filelist.insert(0, file)
-		filelist = filelist[:10]
-		prefs.recentfiles = filelist
-		prefs.save()
-		self.makeopenrecentmenu()
-		
-	def domenu_openwindows(self, id, item, window, event):
-		w = self._openwindows[item]
-		w.ShowWindow()
-		w.SelectWindow()
-	
-	def domenu_openrecent(self, id, item, window, event):
-		prefs = self.getprefs()
-		filelist = prefs.recentfiles
-		if not filelist:
-			filelist = []
-		item = item - 1
-		filename = filelist[item]
-		self.openscript(filename)
-	
-	def domenu_quit(self):
-		self._quit()
-	
-	def domenu_save(self, *args):
-		print "Save"
-	
-	def _quit(self):
-		import PyConsole, PyEdit
-		for window in self._windows.values():
-			try:
-				rv = window.close() # ignore any errors while quitting
-			except:
-				rv = 0   # (otherwise, we can get stuck!)
-			if rv and rv > 0:
-				return
-		try:
-			PyConsole.console.writeprefs()
-			PyConsole.output.writeprefs()
-			PyEdit.searchengine.writeprefs()
-		except:
-			# Write to __stderr__ so the msg end up in Console.app and has
-			# at least _some_ chance of getting read...
-			# But: this is a workaround for way more serious problems with
-			# the Python 2.2 Jaguar addon.
-			sys.__stderr__.write("*** PythonIDE: Can't write preferences ***\n")
-		self.quitting = 1
-		
-	def domenu_openpackagemanager(self):
-		import PackageManager
-		PackageManager.PackageBrowser()
-		
-	def domenu_gensuite(self):
-		import gensuitemodule
-		gensuitemodule.main_interactive()
-		
-	def makehelpmenu(self):
-		hashelp, hasdocs = self.installdocumentation()
-		self.helpmenu = m = self.gethelpmenu()
-		helpitem = FrameWork.MenuItem(m, "MacPython Help", None, self.domenu_localhelp)
-		helpitem.enable(hashelp)
-		docitem = FrameWork.MenuItem(m, "Python Documentation", None, self.domenu_localdocs)
-		docitem.enable(hasdocs)
-		finditem = FrameWork.MenuItem(m, "Lookup in Python Documentation", None, 'lookuppython')
-		finditem.enable(hasdocs)
-		if runningOnOSX():
-			FrameWork.Separator(m)
-			doc2item = FrameWork.MenuItem(m, "Apple Developer Documentation", None, self.domenu_appledocs)
-			find2item = FrameWork.MenuItem(m, "Lookup in Carbon Documentation", None, 'lookupcarbon')
-		FrameWork.Separator(m)
-		webitem = FrameWork.MenuItem(m, "Python Documentation on the Web", None, self.domenu_webdocs)
-		web2item = FrameWork.MenuItem(m, "Python on the Web", None, self.domenu_webpython)
-		web3item = FrameWork.MenuItem(m, "MacPython on the Web", None, self.domenu_webmacpython)
-		
-	def domenu_localdocs(self, *args):
-		from Carbon import AH
-		AH.AHGotoPage("Python Documentation", None, None)
-		
-	def domenu_localhelp(self, *args):
-		from Carbon import AH
-		AH.AHGotoPage("MacPython Help", None, None)
-		
-	def domenu_appledocs(self, *args):
-		from Carbon import AH, AppleHelp
-		try:
-			AH.AHGotoMainTOC(AppleHelp.kAHTOCTypeDeveloper)
-		except AH.Error, arg:
-			if arg[0] == -50:
-				W.Message("Developer documentation not installed")
-			else:
-				W.Message("AppleHelp Error: %r" % (arg,))
-		
-	def domenu_lookuppython(self, *args):
-		from Carbon import AH
-		searchstring = self._getsearchstring()
-		if not searchstring:
-			return
-		try:
-			AH.AHSearch("Python Documentation", searchstring)
-		except AH.Error, arg:
-			W.Message("AppleHelp Error: %r" % (arg,))
-			
-	def domenu_lookupcarbon(self, *args):
-		from Carbon import AH
-		searchstring = self._getsearchstring()
-		if not searchstring:
-			return
-		try:
-			AH.AHSearch("Carbon", searchstring)
-		except AH.Error, arg:
-			W.Message("AppleHelp Error: %r" % (arg,))
-			
-	def _getsearchstring(self):
-		# First we get the frontmost window
-		front = self.getfrontwindow()
-		if front and hasattr(front, 'getselectedtext'):
-			text = front.getselectedtext()
-			if text:
-				return text
-		# This is a cop-out. We should have disabled the menus
-		# if there is no selection, but the can_ methods only seem
-		# to work for Windows. Or not for the Help menu, maybe?
-		text = EasyDialogs.AskString("Search documentation for", ok="Search")
-		return text
-		
-	def domenu_webdocs(self, *args):
-		import webbrowser
-		major, minor, micro, state, nano = sys.version_info
-		if state in ('alpha', 'beta'):
-			docversion = 'dev/doc/devel'
-		elif micro == 0:
-			docversion = 'doc/%d.%d' % (major, minor)
-		else:
-			docversion = 'doc/%d.%d.%d' % (major, minor, micro)
-		webbrowser.open("http://www.python.org/%s" % docversion)
-		
-	def domenu_webpython(self, *args):
-		import webbrowser
-		webbrowser.open("http://www.python.org/")
-		
-	def domenu_webmacpython(self, *args):
-		import webbrowser
-		webbrowser.open("http://www.cwi.nl/~jack/macpython.html")
-		
-	def installdocumentation(self):
-		# This is rather much of a hack. Someone has to tell the Help Viewer
-		# about the Python documentation, so why not us. The documentation
-		# is located in the framework, but there's a symlink in Python.app.
-		# And as AHRegisterHelpBook wants a bundle (with the right bits in
-		# the plist file) we refer it to Python.app
-		#
-		# To make matters worse we have to look in two places: first in the IDE
-		# itself, then in the Python application inside the framework.
-		has_help = False
-		has_doc = False
-		ide_path_components = sys.argv[0].split("/")
-		if ide_path_components[-3:] == ["Contents", "Resources", "PythonIDE.py"]:
-			ide_app = "/".join(ide_path_components[:-3])
-			help_source = os.path.join(ide_app, 'Contents/Resources/English.lproj/Documentation')
-			doc_source = os.path.join(ide_app, 'Contents/Resources/English.lproj/PythonDocumentation')
-			has_help = os.path.isdir(help_source)
-			has_doc = os.path.isdir(doc_source)
-			if has_help or has_doc:
-				try:
-					from Carbon import AH
-					AH.AHRegisterHelpBook(ide_app)
-				except (ImportError, MacOS.Error), arg:
-					pass # W.Message("Cannot register Python Documentation: %s" % str(arg))
-		python_app = os.path.join(sys.prefix, 'Resources/Python.app')
-		if not has_help:
-			help_source = os.path.join(python_app, 'Contents/Resources/English.lproj/Documentation')
-			has_help = os.path.isdir(help_source)
-		if not has_doc:
-			doc_source = os.path.join(python_app, 'Contents/Resources/English.lproj/PythonDocumentation')
-			has_doc = os.path.isdir(doc_source)
-		if has_help or has_doc:
-			try:
-				from Carbon import AH
-				AH.AHRegisterHelpBook(python_app)
-			except (ImportError, MacOS.Error), arg:
-				pass # W.Message("Cannot register Python Documentation: %s" % str(arg))
-		return has_help, has_doc
+
+    def __init__(self):
+        if sys.platform == "darwin":
+            if len(sys.argv) > 1 and sys.argv[1].startswith("-psn"):
+                home = os.getenv("HOME")
+                if home:
+                    os.chdir(home)
+        self.preffilepath = os.path.join("Python", "PythonIDE preferences")
+        Wapplication.Application.__init__(self, 'Pide')
+        from Carbon import AE
+        from Carbon import AppleEvents
+
+        AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEOpenApplication,
+                        self.ignoreevent)
+        AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEReopenApplication,
+                        self.ignoreevent)
+        AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEPrintDocuments,
+                        self.ignoreevent)
+        AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEOpenDocuments,
+                        self.opendocsevent)
+        AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEQuitApplication,
+                        self.quitevent)
+        import PyConsole, PyEdit
+        Splash.wait()
+        # With -D option (OSX command line only) keep stderr, for debugging the IDE
+        # itself.
+        debug_stderr = None
+        if len(sys.argv) >= 2 and sys.argv[1] == '-D':
+            debug_stderr = sys.stderr
+            del sys.argv[1]
+        PyConsole.installoutput()
+        PyConsole.installconsole()
+        if debug_stderr:
+            sys.stderr = debug_stderr
+        for path in sys.argv[1:]:
+            if path.startswith("-p"):
+                # process number added by the OS
+                continue
+            self.opendoc(path)
+        self.mainloop()
+
+    def makeusermenus(self):
+        m = Wapplication.Menu(self.menubar, "File")
+        newitem = FrameWork.MenuItem(m, "New", "N", 'new')
+        openitem = FrameWork.MenuItem(m, "Open"+ELLIPSIS, "O", 'open')
+        openbynameitem = FrameWork.MenuItem(m, "Open File by Name"+ELLIPSIS, "D", 'openbyname')
+        self.openrecentmenu = FrameWork.SubMenu(m, "Open Recent")
+        self.makeopenrecentmenu()
+        FrameWork.Separator(m)
+        closeitem = FrameWork.MenuItem(m, "Close", "W", 'close')
+        saveitem = FrameWork.MenuItem(m, "Save", "S", 'save')
+        saveasitem = FrameWork.MenuItem(m, "Save as"+ELLIPSIS, None, 'save_as')
+        FrameWork.Separator(m)
+        saveasappletitem = FrameWork.MenuItem(m, "Save as Applet"+ELLIPSIS, None, 'save_as_applet')
+        FrameWork.Separator(m)
+        instmgritem = FrameWork.MenuItem(m, "Package Manager", None, 'openpackagemanager')
+        gensuiteitem = FrameWork.MenuItem(m, "Generate OSA Suite...", None, 'gensuite')
+        if not runningOnOSX():
+            # On OSX there's a special "magic" quit menu, so we shouldn't add
+            # it to the File menu.
+            FrameWork.Separator(m)
+            quititem = FrameWork.MenuItem(m, "Quit", "Q", 'quit')
+
+        m = Wapplication.Menu(self.menubar, "Edit")
+        undoitem = FrameWork.MenuItem(m, "Undo", 'Z', "undo")
+        FrameWork.Separator(m)
+        cutitem = FrameWork.MenuItem(m, "Cut", 'X', "cut")
+        copyitem = FrameWork.MenuItem(m, "Copy", "C", "copy")
+        pasteitem = FrameWork.MenuItem(m, "Paste", "V", "paste")
+        FrameWork.MenuItem(m, "Clear", None,  "clear")
+        FrameWork.Separator(m)
+        selallitem = FrameWork.MenuItem(m, "Select all", "A", "selectall")
+        sellineitem = FrameWork.MenuItem(m, "Select line", "L", "selectline")
+        FrameWork.Separator(m)
+        finditem = FrameWork.MenuItem(m, "Find"+ELLIPSIS, "F", "find")
+        findagainitem = FrameWork.MenuItem(m, "Find again", 'G', "findnext")
+        enterselitem = FrameWork.MenuItem(m, "Enter search string", "E", "entersearchstring")
+        replaceitem = FrameWork.MenuItem(m, "Replace", None, "replace")
+        replacefinditem = FrameWork.MenuItem(m, "Replace & find again", 'T', "replacefind")
+        FrameWork.Separator(m)
+        shiftleftitem = FrameWork.MenuItem(m, "Shift left", "[", "shiftleft")
+        shiftrightitem = FrameWork.MenuItem(m, "Shift right", "]", "shiftright")
+
+        m = Wapplication.Menu(self.menubar, "Python")
+        runitem = FrameWork.MenuItem(m, "Run window", "R", 'run')
+        runselitem = FrameWork.MenuItem(m, "Run selection", None, 'runselection')
+        FrameWork.Separator(m)
+        moditem = FrameWork.MenuItem(m, "Module browser"+ELLIPSIS, "M", self.domenu_modulebrowser)
+        FrameWork.Separator(m)
+        mm = FrameWork.SubMenu(m, "Preferences")
+        FrameWork.MenuItem(mm, "Set Scripts folder"+ELLIPSIS, None, self.do_setscriptsfolder)
+        FrameWork.MenuItem(mm, "Editor default settings"+ELLIPSIS, None, self.do_editorprefs)
+        FrameWork.MenuItem(mm, "Set default window font"+ELLIPSIS, None, self.do_setwindowfont)
+
+        self.openwindowsmenu = Wapplication.Menu(self.menubar, 'Windows')
+        self.makeopenwindowsmenu()
+        self._menustocheck = [closeitem, saveitem, saveasitem, saveasappletitem,
+                        undoitem, cutitem, copyitem, pasteitem,
+                        selallitem, sellineitem,
+                        finditem, findagainitem, enterselitem, replaceitem, replacefinditem,
+                        shiftleftitem, shiftrightitem,
+                        runitem, runselitem]
+
+        prefs = self.getprefs()
+        try:
+            fsr, d = File.Alias(rawdata=prefs.scriptsfolder).FSResolveAlias(None)
+            self.scriptsfolder = fsr.FSNewAliasMinimal()
+        except:
+            path = os.path.join(os.getcwd(), "Mac", "IDE scripts")
+            if not os.path.exists(path):
+                if sys.platform == "darwin":
+                    path = os.path.join(os.getenv("HOME"), "Library", "Python", "IDE-Scripts")
+                else:
+                    path = os.path.join(os.getcwd(), "Scripts")
+                if not os.path.exists(path):
+                    os.makedirs(path)
+                    f = open(os.path.join(path, "Place your scripts here"+ELLIPSIS), "w")
+                    f.close()
+            fsr = File.FSRef(path)
+            self.scriptsfolder = fsr.FSNewAliasMinimal()
+            self.scriptsfoldermodtime = getmodtime(fsr)
+        else:
+            self.scriptsfoldermodtime = getmodtime(fsr)
+        prefs.scriptsfolder = self.scriptsfolder.data
+        self._scripts = {}
+        self.scriptsmenu = None
+        self.makescriptsmenu()
+        self.makehelpmenu()
+
+    def quitevent(self, theAppleEvent, theReply):
+        self._quit()
+
+    def suspendresume(self, onoff):
+        if onoff:
+            fsr, changed = self.scriptsfolder.FSResolveAlias(None)
+            modtime = getmodtime(fsr)
+            if self.scriptsfoldermodtime <> modtime or changed:
+                self.scriptsfoldermodtime = modtime
+                W.SetCursor('watch')
+                self.makescriptsmenu()
+
+    def ignoreevent(self, theAppleEvent, theReply):
+        pass
+
+    def opendocsevent(self, theAppleEvent, theReply):
+        W.SetCursor('watch')
+        import aetools
+        parameters, args = aetools.unpackevent(theAppleEvent)
+        docs = parameters['----']
+        if type(docs) <> type([]):
+            docs = [docs]
+        for doc in docs:
+            fsr, a = doc.FSResolveAlias(None)
+            path = fsr.as_pathname()
+            self.opendoc(path)
+
+    def opendoc(self, path):
+        fcreator, ftype = MacOS.GetCreatorAndType(path)
+        if ftype == 'TEXT':
+            self.openscript(path)
+        elif ftype == '\0\0\0\0' and path[-3:] == '.py':
+            self.openscript(path)
+        else:
+            W.Message("Can't open file of type '%s'." % ftype)
+
+    def getabouttext(self):
+        return "About Python IDE"+ELLIPSIS
+
+    def do_about(self, id, item, window, event):
+        Splash.about()
+
+    def do_setscriptsfolder(self, *args):
+        fsr = EasyDialogs.AskFolder(message="Select Scripts Folder",
+                wanted=File.FSRef)
+        if fsr:
+            prefs = self.getprefs()
+            alis = fsr.FSNewAliasMinimal()
+            prefs.scriptsfolder = alis.data
+            self.scriptsfolder = alis
+            self.makescriptsmenu()
+            prefs.save()
+
+    def domenu_modulebrowser(self, *args):
+        W.SetCursor('watch')
+        import ModuleBrowser
+        ModuleBrowser.ModuleBrowser()
+
+    def domenu_open(self, *args):
+        filename = EasyDialogs.AskFileForOpen(typeList=("TEXT",))
+        if filename:
+            self.openscript(filename)
+
+    def domenu_openbyname(self, *args):
+        # Open a file by name. If the clipboard contains a filename
+        # use that as the default.
+        from Carbon import Scrap
+        try:
+            sc = Scrap.GetCurrentScrap()
+            dft = sc.GetScrapFlavorData("TEXT")
+        except Scrap.Error:
+            dft = ""
+        else:
+            if not os.path.exists(dft):
+                dft = ""
+        filename = EasyDialogs.AskString("Open File Named:", default=dft, ok="Open")
+        if filename:
+            self.openscript(filename)
+
+    def domenu_new(self, *args):
+        W.SetCursor('watch')
+        import PyEdit
+        return PyEdit.Editor()
+
+    def makescriptsmenu(self):
+        W.SetCursor('watch')
+        if self._scripts:
+            for id, item in self._scripts.keys():
+                if self.menubar.menus.has_key(id):
+                    m = self.menubar.menus[id]
+                    m.delete()
+            self._scripts = {}
+        if self.scriptsmenu:
+            if hasattr(self.scriptsmenu, 'id') and self.menubar.menus.has_key(self.scriptsmenu.id):
+                self.scriptsmenu.delete()
+        self.scriptsmenu = FrameWork.Menu(self.menubar, "Scripts")
+        #FrameWork.MenuItem(self.scriptsmenu, "New script", None, self.domenu_new)
+        #self.scriptsmenu.addseparator()
+        fsr, d1 = self.scriptsfolder.FSResolveAlias(None)
+        self.scriptswalk(fsr.as_pathname(), self.scriptsmenu)
+
+    def makeopenwindowsmenu(self):
+        for i in range(len(self.openwindowsmenu.items)):
+            self.openwindowsmenu.menu.DeleteMenuItem(1)
+            self.openwindowsmenu.items = []
+        windows = []
+        self._openwindows = {}
+        for window in self._windows.keys():
+            title = window.GetWTitle()
+            if not title:
+                title = "<no title>"
+            windows.append((title, window))
+        windows.sort()
+        for title, window in windows:
+            if title == "Python Interactive":       # ugly but useful hack by Joe Strout
+                shortcut = '0'
+            else:
+                shortcut = None
+            item = FrameWork.MenuItem(self.openwindowsmenu, title, shortcut, callback = self.domenu_openwindows)
+            self._openwindows[item.item] = window
+        self._openwindowscheckmark = 0
+        self.checkopenwindowsmenu()
+
+    def makeopenrecentmenu(self):
+        for i in range(len(self.openrecentmenu.items)):
+            self.openrecentmenu.menu.DeleteMenuItem(1)
+            self.openrecentmenu.items = []
+        prefs = self.getprefs()
+        filelist = prefs.recentfiles
+        if not filelist:
+            self.openrecentmenu.enable(0)
+            return
+        self.openrecentmenu.enable(1)
+        for filename in filelist:
+            item = FrameWork.MenuItem(self.openrecentmenu, filename, None, callback = self.domenu_openrecent)
+
+    def addrecentfile(self, file):
+        prefs = self.getprefs()
+        filelist = prefs.recentfiles
+        if not filelist:
+            filelist = []
+
+        if file in filelist:
+            if file == filelist[0]:
+                return
+            filelist.remove(file)
+        filelist.insert(0, file)
+        filelist = filelist[:10]
+        prefs.recentfiles = filelist
+        prefs.save()
+        self.makeopenrecentmenu()
+
+    def domenu_openwindows(self, id, item, window, event):
+        w = self._openwindows[item]
+        w.ShowWindow()
+        w.SelectWindow()
+
+    def domenu_openrecent(self, id, item, window, event):
+        prefs = self.getprefs()
+        filelist = prefs.recentfiles
+        if not filelist:
+            filelist = []
+        item = item - 1
+        filename = filelist[item]
+        self.openscript(filename)
+
+    def domenu_quit(self):
+        self._quit()
+
+    def domenu_save(self, *args):
+        print "Save"
+
+    def _quit(self):
+        import PyConsole, PyEdit
+        for window in self._windows.values():
+            try:
+                rv = window.close() # ignore any errors while quitting
+            except:
+                rv = 0   # (otherwise, we can get stuck!)
+            if rv and rv > 0:
+                return
+        try:
+            PyConsole.console.writeprefs()
+            PyConsole.output.writeprefs()
+            PyEdit.searchengine.writeprefs()
+        except:
+            # Write to __stderr__ so the msg end up in Console.app and has
+            # at least _some_ chance of getting read...
+            # But: this is a workaround for way more serious problems with
+            # the Python 2.2 Jaguar addon.
+            sys.__stderr__.write("*** PythonIDE: Can't write preferences ***\n")
+        self.quitting = 1
+
+    def domenu_openpackagemanager(self):
+        import PackageManager
+        PackageManager.PackageBrowser()
+
+    def domenu_gensuite(self):
+        import gensuitemodule
+        gensuitemodule.main_interactive()
+
+    def makehelpmenu(self):
+        hashelp, hasdocs = self.installdocumentation()
+        self.helpmenu = m = self.gethelpmenu()
+        helpitem = FrameWork.MenuItem(m, "MacPython Help", None, self.domenu_localhelp)
+        helpitem.enable(hashelp)
+        docitem = FrameWork.MenuItem(m, "Python Documentation", None, self.domenu_localdocs)
+        docitem.enable(hasdocs)
+        finditem = FrameWork.MenuItem(m, "Lookup in Python Documentation", None, 'lookuppython')
+        finditem.enable(hasdocs)
+        if runningOnOSX():
+            FrameWork.Separator(m)
+            doc2item = FrameWork.MenuItem(m, "Apple Developer Documentation", None, self.domenu_appledocs)
+            find2item = FrameWork.MenuItem(m, "Lookup in Carbon Documentation", None, 'lookupcarbon')
+        FrameWork.Separator(m)
+        webitem = FrameWork.MenuItem(m, "Python Documentation on the Web", None, self.domenu_webdocs)
+        web2item = FrameWork.MenuItem(m, "Python on the Web", None, self.domenu_webpython)
+        web3item = FrameWork.MenuItem(m, "MacPython on the Web", None, self.domenu_webmacpython)
+
+    def domenu_localdocs(self, *args):
+        from Carbon import AH
+        AH.AHGotoPage("Python Documentation", None, None)
+
+    def domenu_localhelp(self, *args):
+        from Carbon import AH
+        AH.AHGotoPage("MacPython Help", None, None)
+
+    def domenu_appledocs(self, *args):
+        from Carbon import AH, AppleHelp
+        try:
+            AH.AHGotoMainTOC(AppleHelp.kAHTOCTypeDeveloper)
+        except AH.Error, arg:
+            if arg[0] == -50:
+                W.Message("Developer documentation not installed")
+            else:
+                W.Message("AppleHelp Error: %r" % (arg,))
+
+    def domenu_lookuppython(self, *args):
+        from Carbon import AH
+        searchstring = self._getsearchstring()
+        if not searchstring:
+            return
+        try:
+            AH.AHSearch("Python Documentation", searchstring)
+        except AH.Error, arg:
+            W.Message("AppleHelp Error: %r" % (arg,))
+
+    def domenu_lookupcarbon(self, *args):
+        from Carbon import AH
+        searchstring = self._getsearchstring()
+        if not searchstring:
+            return
+        try:
+            AH.AHSearch("Carbon", searchstring)
+        except AH.Error, arg:
+            W.Message("AppleHelp Error: %r" % (arg,))
+
+    def _getsearchstring(self):
+        # First we get the frontmost window
+        front = self.getfrontwindow()
+        if front and hasattr(front, 'getselectedtext'):
+            text = front.getselectedtext()
+            if text:
+                return text
+        # This is a cop-out. We should have disabled the menus
+        # if there is no selection, but the can_ methods only seem
+        # to work for Windows. Or not for the Help menu, maybe?
+        text = EasyDialogs.AskString("Search documentation for", ok="Search")
+        return text
+
+    def domenu_webdocs(self, *args):
+        import webbrowser
+        major, minor, micro, state, nano = sys.version_info
+        if state in ('alpha', 'beta'):
+            docversion = 'dev/doc/devel'
+        elif micro == 0:
+            docversion = 'doc/%d.%d' % (major, minor)
+        else:
+            docversion = 'doc/%d.%d.%d' % (major, minor, micro)
+        webbrowser.open("http://www.python.org/%s" % docversion)
+
+    def domenu_webpython(self, *args):
+        import webbrowser
+        webbrowser.open("http://www.python.org/")
+
+    def domenu_webmacpython(self, *args):
+        import webbrowser
+        webbrowser.open("http://www.cwi.nl/~jack/macpython.html")
+
+    def installdocumentation(self):
+        # This is rather much of a hack. Someone has to tell the Help Viewer
+        # about the Python documentation, so why not us. The documentation
+        # is located in the framework, but there's a symlink in Python.app.
+        # And as AHRegisterHelpBook wants a bundle (with the right bits in
+        # the plist file) we refer it to Python.app
+        #
+        # To make matters worse we have to look in two places: first in the IDE
+        # itself, then in the Python application inside the framework.
+        has_help = False
+        has_doc = False
+        ide_path_components = sys.argv[0].split("/")
+        if ide_path_components[-3:] == ["Contents", "Resources", "PythonIDE.py"]:
+            ide_app = "/".join(ide_path_components[:-3])
+            help_source = os.path.join(ide_app, 'Contents/Resources/English.lproj/Documentation')
+            doc_source = os.path.join(ide_app, 'Contents/Resources/English.lproj/PythonDocumentation')
+            has_help = os.path.isdir(help_source)
+            has_doc = os.path.isdir(doc_source)
+            if has_help or has_doc:
+                try:
+                    from Carbon import AH
+                    AH.AHRegisterHelpBook(ide_app)
+                except (ImportError, MacOS.Error), arg:
+                    pass # W.Message("Cannot register Python Documentation: %s" % str(arg))
+        python_app = os.path.join(sys.prefix, 'Resources/Python.app')
+        if not has_help:
+            help_source = os.path.join(python_app, 'Contents/Resources/English.lproj/Documentation')
+            has_help = os.path.isdir(help_source)
+        if not has_doc:
+            doc_source = os.path.join(python_app, 'Contents/Resources/English.lproj/PythonDocumentation')
+            has_doc = os.path.isdir(doc_source)
+        if has_help or has_doc:
+            try:
+                from Carbon import AH
+                AH.AHRegisterHelpBook(python_app)
+            except (ImportError, MacOS.Error), arg:
+                pass # W.Message("Cannot register Python Documentation: %s" % str(arg))
+        return has_help, has_doc
diff --git a/Mac/Tools/IDE/Splash.py b/Mac/Tools/IDE/Splash.py
index 86009d2..ab36fa4 100644
--- a/Mac/Tools/IDE/Splash.py
+++ b/Mac/Tools/IDE/Splash.py
@@ -25,88 +25,88 @@
 %s
 See: <http://www.python.org/> for information and documentation."""
 
-flauwekul = [	"Goodday, Bruce.", 
-			"What's new?",
-			"Nudge, nudge, say no more!", 
-			"No, no sir, it's not dead. It's resting.",
-			"Albatros!",
-			"It's . . .",
-			"Is your name not Bruce, then?",
-			"""But Mr F.G. Superman has a secret identity . . . 
-when trouble strikes at any time . . . 
-at any place . . . he is ready to become . . . 
+flauwekul = [   "Goodday, Bruce.",
+                        "What's new?",
+                        "Nudge, nudge, say no more!",
+                        "No, no sir, it's not dead. It's resting.",
+                        "Albatros!",
+                        "It's . . .",
+                        "Is your name not Bruce, then?",
+                        """But Mr F.G. Superman has a secret identity . . .
+when trouble strikes at any time . . .
+at any place . . . he is ready to become . . .
 Bicycle Repair Man!"""
-			]
+                        ]
 
 def skipdoublereturns(text):
-	return string.replace(text, '\n\n', '\n')
+    return string.replace(text, '\n\n', '\n')
 
 def nl2return(text):
-	return string.replace(text, '\n', '\r')
+    return string.replace(text, '\n', '\r')
 
 def UpdateSplash(drawdialog = 0, what = 0):
-	if drawdialog:
-		splash.DrawDialog()
-	drawtext(what)
-	splash.GetDialogWindow().ValidWindowRect(splash.GetDialogPort().GetPortBounds())
-	splash.GetDialogWindow().GetWindowPort().QDFlushPortBuffer(None)
+    if drawdialog:
+        splash.DrawDialog()
+    drawtext(what)
+    splash.GetDialogWindow().ValidWindowRect(splash.GetDialogPort().GetPortBounds())
+    splash.GetDialogWindow().GetWindowPort().QDFlushPortBuffer(None)
 
 def drawtext(what = 0):
-	Qd.SetPort(splash)
-	fontID = Fm.GetFNum("Python-Sans")
-	if not fontID:
-		fontID = geneva
-	Qd.TextFont(fontID)
-	Qd.TextSize(9)
-	rect = (10, 115, _about_width - 10, _about_height - 30)
-	if not what:
-		import __main__
-		abouttxt = nl2return(abouttext1 % (
-				__main__.__version__, sys.version, skipdoublereturns(sys.copyright)))
-	else:
-		import random
-		abouttxt = nl2return(random.choice(flauwekul))
-	TE.TETextBox(abouttxt, rect, teJustCenter)
+    Qd.SetPort(splash)
+    fontID = Fm.GetFNum("Python-Sans")
+    if not fontID:
+        fontID = geneva
+    Qd.TextFont(fontID)
+    Qd.TextSize(9)
+    rect = (10, 115, _about_width - 10, _about_height - 30)
+    if not what:
+        import __main__
+        abouttxt = nl2return(abouttext1 % (
+                        __main__.__version__, sys.version, skipdoublereturns(sys.copyright)))
+    else:
+        import random
+        abouttxt = nl2return(random.choice(flauwekul))
+    TE.TETextBox(abouttxt, rect, teJustCenter)
 
 UpdateSplash(1)
 
 def wait():
-	from Carbon import Evt
-	from Carbon import Events
-	global splash
-	try:
-		splash
-	except NameError:
-		return
-	Qd.InitCursor()
-	time = Evt.TickCount()
-	whattext = 0
-	drawtext(whattext)
-	while _keepsplashscreenopen:
-		ok, event = Evt.EventAvail(Events.highLevelEventMask)
-		if ok:
-			# got apple event, back to mainloop
-			break
-		ok, event = Evt.EventAvail(Events.mDownMask | Events.keyDownMask | Events.updateMask)
-		if ok:
-			ok, event = Evt.WaitNextEvent(Events.mDownMask | Events.keyDownMask | Events.updateMask, 30)
-			if ok:
-				(what, message, when, where, modifiers) = event
-				if what == Events.updateEvt:
-					if Win.WhichWindow(message) == splash:
-						UpdateSplash(1, whattext)
-				else:
-					break
-		if Evt.TickCount() - time > 360:
-			whattext = not whattext
-			drawtext(whattext)
-			time = Evt.TickCount()
-	del splash
+    from Carbon import Evt
+    from Carbon import Events
+    global splash
+    try:
+        splash
+    except NameError:
+        return
+    Qd.InitCursor()
+    time = Evt.TickCount()
+    whattext = 0
+    drawtext(whattext)
+    while _keepsplashscreenopen:
+        ok, event = Evt.EventAvail(Events.highLevelEventMask)
+        if ok:
+            # got apple event, back to mainloop
+            break
+        ok, event = Evt.EventAvail(Events.mDownMask | Events.keyDownMask | Events.updateMask)
+        if ok:
+            ok, event = Evt.WaitNextEvent(Events.mDownMask | Events.keyDownMask | Events.updateMask, 30)
+            if ok:
+                (what, message, when, where, modifiers) = event
+                if what == Events.updateEvt:
+                    if Win.WhichWindow(message) == splash:
+                        UpdateSplash(1, whattext)
+                else:
+                    break
+        if Evt.TickCount() - time > 360:
+            whattext = not whattext
+            drawtext(whattext)
+            time = Evt.TickCount()
+    del splash
 
 
 def about():
-	global splash, splashresfile, _keepsplashscreenopen
-	_keepsplashscreenopen = 1
-	splash = Dlg.GetNewDialog(468, -1)
-	splash.DrawDialog()
-	wait()
+    global splash, splashresfile, _keepsplashscreenopen
+    _keepsplashscreenopen = 1
+    splash = Dlg.GetNewDialog(468, -1)
+    splash.DrawDialog()
+    wait()
diff --git a/Mac/Tools/IDE/W.py b/Mac/Tools/IDE/W.py
index 397b211..3ddeb76 100644
--- a/Mac/Tools/IDE/W.py
+++ b/Mac/Tools/IDE/W.py
@@ -15,27 +15,26 @@
 AlertError = 'AlertError'
 
 def setapplication(app, sig):
-	global _application, _signature
-	_application = app
-	_signature = sig
+    global _application, _signature
+    _application = app
+    _signature = sig
 
 def getapplication():
-	if _application is None:
-		raise WidgetsError, 'W not properly initialized: unknown Application'
-	return _application
+    if _application is None:
+        raise WidgetsError, 'W not properly initialized: unknown Application'
+    return _application
 
 def getdefaultfont():
-	prefs = getapplication().getprefs()
-	if not prefs.defaultfont:
-		prefs.defaultfont = ("Geneva", 0, 10, (0, 0, 0))
-	return prefs.defaultfont
+    prefs = getapplication().getprefs()
+    if not prefs.defaultfont:
+        prefs.defaultfont = ("Geneva", 0, 10, (0, 0, 0))
+    return prefs.defaultfont
 
 def Message(text):
-	import EasyDialogs, string
-	from Carbon import Qd
-	Qd.InitCursor()
-	text = string.replace(text, "\n", "\r")
-	if not text:
-		text = '<Alert text not specified>'
-	EasyDialogs.Message(text)
-
+    import EasyDialogs, string
+    from Carbon import Qd
+    Qd.InitCursor()
+    text = string.replace(text, "\n", "\r")
+    if not text:
+        text = '<Alert text not specified>'
+    EasyDialogs.Message(text)
diff --git a/Mac/Tools/IDE/Wapplication.py b/Mac/Tools/IDE/Wapplication.py
index 553391e..4cfc77b 100644
--- a/Mac/Tools/IDE/Wapplication.py
+++ b/Mac/Tools/IDE/Wapplication.py
@@ -11,472 +11,471 @@
 from Carbon import File
 
 if hasattr(Win, "FrontNonFloatingWindow"):
-	MyFrontWindow = Win.FrontNonFloatingWindow
+    MyFrontWindow = Win.FrontNonFloatingWindow
 else:
-	MyFrontWindow = Win.FrontWindow
+    MyFrontWindow = Win.FrontWindow
 
 
 KILLUNKNOWNWINDOWS = 0  # Set to 0 for debugging.
 
 class Application(FrameWork.Application):
-	
-	def __init__(self, signature='Pyth'):
-		# Open our resource file, if it is not open yet
-		macresource.need('CURS', 468, "Widgets.rsrc")
-		import W
-		W.setapplication(self, signature)
-		FrameWork.Application.__init__(self)
-		self._suspended = 0
-		self.quitting = 0
-		self.debugger_quitting = 1
-		self.DebuggerQuit = 'DebuggerQuitDummyException'
-		self._idlefuncs = []
-		# map certain F key codes to equivalent command-letter combos (JJS)
-		self.fkeymaps = {122:"z", 120:"x", 99:"c", 118:"v"}
-	
-	def mainloop(self, mask=FrameWork.everyEvent, wait=None):
-		import W
-		self.quitting = 0
-		if hasattr(MacOS, 'EnableAppswitch'):
-			saveyield = MacOS.EnableAppswitch(-1)
-		try:
-			while not self.quitting:
-				try:
-					self.do1event(mask, wait)
-				except W.AlertError, detail:
-					if hasattr(MacOS, 'EnableAppswitch'):
-						MacOS.EnableAppswitch(-1)
-					W.Message(detail)
-				except self.DebuggerQuit:
-					if hasattr(MacOS, 'EnableAppswitch'):
-						MacOS.EnableAppswitch(-1)
-				except:
-					if hasattr(MacOS, 'EnableAppswitch'):
-						MacOS.EnableAppswitch(-1)
-					import PyEdit
-					PyEdit.tracebackwindow.traceback()
-		finally:
-			if hasattr(MacOS, 'EnableAppswitch'):
-				MacOS.EnableAppswitch(1)
-	
-	def debugger_mainloop(self, mask=FrameWork.everyEvent, wait=None):
-		import W
-		self.debugger_quitting = 0
-		if hasattr(MacOS, 'EnableAppswitch'):
-			saveyield = MacOS.EnableAppswitch(-1)
-		try:
-			while not self.quitting and not self.debugger_quitting:
-				try:
-					self.do1event(mask, wait)
-				except W.AlertError, detail:
-					W.Message(detail)
-				except:
-					import PyEdit
-					PyEdit.tracebackwindow.traceback()
-		finally:
-			if hasattr(MacOS, 'EnableAppswitch'):
-				MacOS.EnableAppswitch(saveyield)
-	
-	def breathe(self, wait=1):
-		import W
-		ok, event = Evt.WaitNextEvent(FrameWork.updateMask | 
-				FrameWork.mDownMask | FrameWork.osMask |
-				FrameWork.activMask, 
-				wait)
-		if ok:
-			(what, message, when, where, modifiers) = event
-			#print FrameWork.eventname[what]
-			if FrameWork.eventname[what] == 'mouseDown':
-				partcode, wid = Win.FindWindow(where)
-				if FrameWork.partname[partcode] <> 'inDesk':
-					return
-			else:
-				W.SetCursor('watch')
-			self.dispatch(event)
-	
-	def refreshwindows(self, wait=1):
-		import W
-		while 1:
-			ok, event = Evt.WaitNextEvent(FrameWork.updateMask, wait)
-			if not ok:
-				break
-			self.dispatch(event)
-	
-	def addidlefunc(self, func):
-		self._idlefuncs.append(func)
-	
-	def removeidlefunc(self, func):
-		self._idlefuncs.remove(func)
-	
-	def idle(self, event):
-		if not self._suspended:
-			if not self.do_frontWindowMethod("idle", event):
-				Qd.InitCursor()
-		if self._idlefuncs:
-			for func in self._idlefuncs:
-				try:
-					func()
-				except:
-					import sys
-					sys.stderr.write("exception in idle function %r; killed:\n" % (func,))
-					traceback.print_exc()
-					self._idlefuncs.remove(func)
-					break
-	
-	def do_frontWindowMethod(self, attr, *args):
-		wid = MyFrontWindow()
-		if wid and self._windows.has_key(wid):
-			window = self._windows[wid]
-			if hasattr(window, attr):
-				handler = getattr(window, attr)
-				apply(handler, args)
-				return 1
-				
-	def getfrontwindow(self):
-		wid = MyFrontWindow()
-		if wid and self._windows.has_key(wid):
-			return self._windows[wid]
-		return None
-	
-	def appendwindow(self, wid, window):
-		self._windows[wid] = window
-		self.makeopenwindowsmenu()
-		
-	def removewindow(self, wid):
-		del self._windows[wid]
-		self.makeopenwindowsmenu()
-	
-	def makeopenwindowsmenu(self):
-		# dummy; could be the full version from PythonIDEMain.py
-		self._openwindows = {}
-		self._openwindowscheckmark = 0
-		if not hasattr(self, "_menustocheck"):
-			self._menustocheck = []
-	
-	def do_key(self, event):
-		(what, message, when, where, modifiers) = event
-		ch = chr(message & FrameWork.charCodeMask)
-		rest = message & ~FrameWork.charCodeMask
-		keycode = (message & FrameWork.keyCodeMask) >> 8
-		if keycode in self.fkeymaps.keys():		# JJS
-			ch = self.fkeymaps[keycode]
-			modifiers = modifiers | FrameWork.cmdKey
-		wid = MyFrontWindow()
-		if modifiers & FrameWork.cmdKey and not modifiers & FrameWork.shiftKey:
-			if wid and self._windows.has_key(wid):
-				self.checkmenus(self._windows[wid])
-			else:
-				self.checkmenus(None)
-			event = (what, ord(ch) | rest, when, where, modifiers)
-			result = MenuToolbox.MenuKey(ord(ch))
-			id = (result>>16) & 0xffff	# Hi word
-			item = result & 0xffff		# Lo word
-			if id:
-				self.do_rawmenu(id, item, None, event)
-				return	# here! we had a menukey! 
-			#else:
-			#	print "XXX Command-%r" % ch
-		# See whether the front window wants it
-		if wid and self._windows.has_key(wid):
-			window = self._windows[wid]
-			try:
-				do_char = window.do_char
-			except AttributeError:
-				do_char = self.do_char
-			do_char(ch, event)
-		# else it wasn't for us, sigh...
-	
-	def do_inMenuBar(self, partcode, window, event):
-		Qd.InitCursor()
-		(what, message, when, where, modifiers) = event
-		self.checkopenwindowsmenu()
-		wid = MyFrontWindow()
-		if wid and self._windows.has_key(wid):
-			self.checkmenus(self._windows[wid])
-		else:
-			self.checkmenus(None)
-		result = MenuToolbox.MenuSelect(where)
-		id = (result>>16) & 0xffff	# Hi word
-		if id >= 0x8000:
-			id = -0x10000 + id
-		item = result & 0xffff		# Lo word
-		self.do_rawmenu(id, item, window, event)
-	
-	def do_updateEvt(self, event):
-		(what, message, when, where, modifiers) = event
-		wid = Win.WhichWindow(message)
-		if wid and self._windows.has_key(wid):
-			window = self._windows[wid]
-			window.do_rawupdate(wid, event)
-		else:
-			if KILLUNKNOWNWINDOWS and wid:
-				wid.HideWindow()
-				import sys
-				sys.stderr.write("XXX killed unknown (crashed?) Python window.\n")
-			else:
-				if hasattr(MacOS, 'HandleEvent'):
-					MacOS.HandleEvent(event)
-				else:
-					print 'Unexpected updateEvent:', event
-	
-	def suspendresume(self, onoff):
-		pass
-	
-	def do_suspendresume(self, event):
-		self._suspended = not event[1] & 1
-		FrameWork.Application.do_suspendresume(self, event)
-	
-	def checkopenwindowsmenu(self):
-		if self._openwindowscheckmark:
-			self.openwindowsmenu.menu.CheckMenuItem(self._openwindowscheckmark, 0)
-		window = MyFrontWindow()
-		if window:
-			for item, wid in self._openwindows.items():
-				if wid == window:
-					#self.pythonwindowsmenuitem.check(1)
-					self.openwindowsmenu.menu.CheckMenuItem(item, 1)
-					self._openwindowscheckmark = item
-					break
-		else:
-			self._openwindowscheckmark = 0
-		#if self._openwindows:
-		#	self.pythonwindowsmenuitem.enable(1)
-		#else:
-		#	self.pythonwindowsmenuitem.enable(0)
-	
-	def checkmenus(self, window):
-		for item in self._menustocheck:
-			callback = item.menu.items[item.item-1][2]
-			if type(callback) <> StringType:
-				item.enable(1)
-			elif hasattr(window, "domenu_" + callback):
-				if hasattr(window, "can_" + callback):
-					canhandler = getattr(window, "can_" + callback)
-					if canhandler(item):
-						item.enable(1)
-					else:
-						item.enable(0)
-				else:
-					item.enable(1)
-			else:
-				item.enable(0)
-	
-	def enablemenubar(self, onoff):
-		for m in self.menubar.menus.values():
-			if onoff:
-				m.menu.EnableMenuItem(0)
-			elif m.menu.GetMenuItemText(3) <> 'Cut': # ew...
-				m.menu.DisableMenuItem(0)
-		MenuToolbox.DrawMenuBar()
-	
-	def makemenubar(self):
-		self.menubar = MenuBar(self)
-		FrameWork.AppleMenu(self.menubar, self.getabouttext(), self.do_about)
-		self.makeusermenus()
-	
-	def scriptswalk(self, top, menu, done=None):
-		if menu.id > 200:
-			import W
-			W.Message("Scripts folder not completely traversed: running out of menus")
-			return False
-		if done is None:
-			done = {}
-		if done.has_key(top):
-			return True
-		done[top] = 1
-		import os, string
-		try:
-			names = os.listdir(top)
-		except os.error:
-			FrameWork.MenuItem(menu, '(Scripts Folder not found)', None, None)
-			return True
-		savedir = os.getcwd()
-		os.chdir(top)
-		for name in names:
-			if name == "CVS":
-				continue
-			try:
-				fsr, isdir, isalias = File.FSResolveAliasFile(name, 1)
-			except:
-				# maybe a broken alias
-				continue
-			path = fsr.as_pathname()
-			if done.has_key(path):
-				continue
-			name = string.strip(name)
-			if os.name == "posix":
-				name = unicode(name, "utf-8")
-			if name[-3:] == '---':
-				menu.addseparator()
-			elif isdir:
-				submenu = FrameWork.SubMenu(menu, name)
-				if not self.scriptswalk(path, submenu, done):
-					return False
-			else:
-				creator, type = MacOS.GetCreatorAndType(path)
-				if type == 'TEXT':
-					if name[-3:] == '.py':
-						name = name[:-3]
-					item = FrameWork.MenuItem(menu, name, None, self.domenu_script)
-					self._scripts[(menu.id, item.item)] = path
-			done[path] = 1
-		os.chdir(savedir)
-		return True
-	
-	def domenu_script(self, id, item, window, event):
-		(what, message, when, where, modifiers) = event
-		path = self._scripts[(id, item)]
-		import os
-		if not os.path.exists(path):
-			self.makescriptsmenu()
-			import W
-			raise W.AlertError, "File not found."
-		if ord(Evt.GetKeys()[7]) & 4:
-			self.openscript(path)
-		else:
-			import W, MacOS, sys
-			W.SetCursor("watch")
-			sys.argv = [path]
-			#cwd = os.getcwd()
-			#os.chdir(os.path.dirname(path) + ':')
-			try:
-				# xxx if there is a script window for this file,
-				# exec in that window's namespace.
-				# xxx what to do when it's not saved???
-				# promt to save?
-				if hasattr(MacOS, 'EnableAppswitch'):
-					MacOS.EnableAppswitch(0)
-				execfile(path, {'__name__': '__main__', '__file__': path})
-			except W.AlertError, detail:
-				if hasattr(MacOS, 'EnableAppswitch'):
-					MacOS.EnableAppswitch(-1)
-				raise W.AlertError, detail
-			except KeyboardInterrupt:
-				if hasattr(MacOS, 'EnableAppswitch'):
-					MacOS.EnableAppswitch(-1)
-			except:
-				if hasattr(MacOS, 'EnableAppswitch'):
-					MacOS.EnableAppswitch(-1)
-				import PyEdit
-				PyEdit.tracebackwindow.traceback(1)
-			else:
-				if hasattr(MacOS, 'EnableAppswitch'):
-					MacOS.EnableAppswitch(-1)
-			#os.chdir(cwd)
-	
-	def openscript(self, filename, lineno=None, charoffset=0, modname=""):
-		import os, PyEdit, W
-		editor = self.getscript(filename)
-		if editor:
-			editor.select()
-		elif os.path.exists(filename):
-			editor = PyEdit.Editor(filename)
-		elif filename[-3:] == '.py' or filename[-4:] == '.pyc':
-			import imp
-			if not modname:
-				if filename[-1] == 'c':
-					modname = os.path.basename(filename)[:-4]
-				else:
-					modname = os.path.basename(filename)[:-3]
-			try:
-				# XXX This does not work correctly with packages!
-				# XXX The docs say we should do it manually, pack, then sub, then sub2 etc. 
-				# XXX It says we should use imp.load_module(), but that *reloads* a package,
-				# XXX and that's the last thing we want here.
-				f, filename, (suff, mode, dummy) = imp.find_module(modname)
-			except ImportError:
-				raise W.AlertError, "Can't find file for \"%s\"" % modname
-			else:
-				if not f:
-					raise W.AlertError, "Can't find file for \"%s\"" % modname
-				f.close()
-			if suff == '.py':
-				self.openscript(filename, lineno, charoffset)
-				return
-			else:
-				raise W.AlertError, "Can't find file for \"%s\"" % modname
-		else:
-			raise W.AlertError, "Can't find file \"%s\"" % filename
-		if lineno is not None:
-			editor.selectline(lineno, charoffset)
-		return editor
-	
-	def getscript(self, filename):
-		if filename[:1] == '<' and filename[-1:] == '>':
-			filename = filename[1:-1]
-		import string
-		lowpath = string.lower(filename)
-		for wid, window in self._windows.items():
-			if hasattr(window, "path") and type(window.path) == StringType and \
-					lowpath == string.lower(window.path):
-				return window
-			elif hasattr(window, "path") and filename == wid.GetWTitle():
-				return window
-	
-	def getprefs(self):
-		import MacPrefs
-		return MacPrefs.GetPrefs(self.preffilepath)
-	
-	def do_editorprefs(self, *args):
-		import PyEdit
-		PyEdit.EditorDefaultSettings()
-	
-	def do_setwindowfont(self, *args):
-		import FontSettings, W
-		prefs = self.getprefs()
-		settings = FontSettings.FontDialog(prefs.defaultfont)
-		if settings:
-			prefs.defaultfont, tabsettings = settings
-			raise W.AlertError, "Note that changes will only affect new windows!"
+
+    def __init__(self, signature='Pyth'):
+        # Open our resource file, if it is not open yet
+        macresource.need('CURS', 468, "Widgets.rsrc")
+        import W
+        W.setapplication(self, signature)
+        FrameWork.Application.__init__(self)
+        self._suspended = 0
+        self.quitting = 0
+        self.debugger_quitting = 1
+        self.DebuggerQuit = 'DebuggerQuitDummyException'
+        self._idlefuncs = []
+        # map certain F key codes to equivalent command-letter combos (JJS)
+        self.fkeymaps = {122:"z", 120:"x", 99:"c", 118:"v"}
+
+    def mainloop(self, mask=FrameWork.everyEvent, wait=None):
+        import W
+        self.quitting = 0
+        if hasattr(MacOS, 'EnableAppswitch'):
+            saveyield = MacOS.EnableAppswitch(-1)
+        try:
+            while not self.quitting:
+                try:
+                    self.do1event(mask, wait)
+                except W.AlertError, detail:
+                    if hasattr(MacOS, 'EnableAppswitch'):
+                        MacOS.EnableAppswitch(-1)
+                    W.Message(detail)
+                except self.DebuggerQuit:
+                    if hasattr(MacOS, 'EnableAppswitch'):
+                        MacOS.EnableAppswitch(-1)
+                except:
+                    if hasattr(MacOS, 'EnableAppswitch'):
+                        MacOS.EnableAppswitch(-1)
+                    import PyEdit
+                    PyEdit.tracebackwindow.traceback()
+        finally:
+            if hasattr(MacOS, 'EnableAppswitch'):
+                MacOS.EnableAppswitch(1)
+
+    def debugger_mainloop(self, mask=FrameWork.everyEvent, wait=None):
+        import W
+        self.debugger_quitting = 0
+        if hasattr(MacOS, 'EnableAppswitch'):
+            saveyield = MacOS.EnableAppswitch(-1)
+        try:
+            while not self.quitting and not self.debugger_quitting:
+                try:
+                    self.do1event(mask, wait)
+                except W.AlertError, detail:
+                    W.Message(detail)
+                except:
+                    import PyEdit
+                    PyEdit.tracebackwindow.traceback()
+        finally:
+            if hasattr(MacOS, 'EnableAppswitch'):
+                MacOS.EnableAppswitch(saveyield)
+
+    def breathe(self, wait=1):
+        import W
+        ok, event = Evt.WaitNextEvent(FrameWork.updateMask |
+                        FrameWork.mDownMask | FrameWork.osMask |
+                        FrameWork.activMask,
+                        wait)
+        if ok:
+            (what, message, when, where, modifiers) = event
+            #print FrameWork.eventname[what]
+            if FrameWork.eventname[what] == 'mouseDown':
+                partcode, wid = Win.FindWindow(where)
+                if FrameWork.partname[partcode] <> 'inDesk':
+                    return
+            else:
+                W.SetCursor('watch')
+            self.dispatch(event)
+
+    def refreshwindows(self, wait=1):
+        import W
+        while 1:
+            ok, event = Evt.WaitNextEvent(FrameWork.updateMask, wait)
+            if not ok:
+                break
+            self.dispatch(event)
+
+    def addidlefunc(self, func):
+        self._idlefuncs.append(func)
+
+    def removeidlefunc(self, func):
+        self._idlefuncs.remove(func)
+
+    def idle(self, event):
+        if not self._suspended:
+            if not self.do_frontWindowMethod("idle", event):
+                Qd.InitCursor()
+        if self._idlefuncs:
+            for func in self._idlefuncs:
+                try:
+                    func()
+                except:
+                    import sys
+                    sys.stderr.write("exception in idle function %r; killed:\n" % (func,))
+                    traceback.print_exc()
+                    self._idlefuncs.remove(func)
+                    break
+
+    def do_frontWindowMethod(self, attr, *args):
+        wid = MyFrontWindow()
+        if wid and self._windows.has_key(wid):
+            window = self._windows[wid]
+            if hasattr(window, attr):
+                handler = getattr(window, attr)
+                apply(handler, args)
+                return 1
+
+    def getfrontwindow(self):
+        wid = MyFrontWindow()
+        if wid and self._windows.has_key(wid):
+            return self._windows[wid]
+        return None
+
+    def appendwindow(self, wid, window):
+        self._windows[wid] = window
+        self.makeopenwindowsmenu()
+
+    def removewindow(self, wid):
+        del self._windows[wid]
+        self.makeopenwindowsmenu()
+
+    def makeopenwindowsmenu(self):
+        # dummy; could be the full version from PythonIDEMain.py
+        self._openwindows = {}
+        self._openwindowscheckmark = 0
+        if not hasattr(self, "_menustocheck"):
+            self._menustocheck = []
+
+    def do_key(self, event):
+        (what, message, when, where, modifiers) = event
+        ch = chr(message & FrameWork.charCodeMask)
+        rest = message & ~FrameWork.charCodeMask
+        keycode = (message & FrameWork.keyCodeMask) >> 8
+        if keycode in self.fkeymaps.keys():             # JJS
+            ch = self.fkeymaps[keycode]
+            modifiers = modifiers | FrameWork.cmdKey
+        wid = MyFrontWindow()
+        if modifiers & FrameWork.cmdKey and not modifiers & FrameWork.shiftKey:
+            if wid and self._windows.has_key(wid):
+                self.checkmenus(self._windows[wid])
+            else:
+                self.checkmenus(None)
+            event = (what, ord(ch) | rest, when, where, modifiers)
+            result = MenuToolbox.MenuKey(ord(ch))
+            id = (result>>16) & 0xffff      # Hi word
+            item = result & 0xffff          # Lo word
+            if id:
+                self.do_rawmenu(id, item, None, event)
+                return  # here! we had a menukey!
+            #else:
+            #       print "XXX Command-%r" % ch
+        # See whether the front window wants it
+        if wid and self._windows.has_key(wid):
+            window = self._windows[wid]
+            try:
+                do_char = window.do_char
+            except AttributeError:
+                do_char = self.do_char
+            do_char(ch, event)
+        # else it wasn't for us, sigh...
+
+    def do_inMenuBar(self, partcode, window, event):
+        Qd.InitCursor()
+        (what, message, when, where, modifiers) = event
+        self.checkopenwindowsmenu()
+        wid = MyFrontWindow()
+        if wid and self._windows.has_key(wid):
+            self.checkmenus(self._windows[wid])
+        else:
+            self.checkmenus(None)
+        result = MenuToolbox.MenuSelect(where)
+        id = (result>>16) & 0xffff      # Hi word
+        if id >= 0x8000:
+            id = -0x10000 + id
+        item = result & 0xffff          # Lo word
+        self.do_rawmenu(id, item, window, event)
+
+    def do_updateEvt(self, event):
+        (what, message, when, where, modifiers) = event
+        wid = Win.WhichWindow(message)
+        if wid and self._windows.has_key(wid):
+            window = self._windows[wid]
+            window.do_rawupdate(wid, event)
+        else:
+            if KILLUNKNOWNWINDOWS and wid:
+                wid.HideWindow()
+                import sys
+                sys.stderr.write("XXX killed unknown (crashed?) Python window.\n")
+            else:
+                if hasattr(MacOS, 'HandleEvent'):
+                    MacOS.HandleEvent(event)
+                else:
+                    print 'Unexpected updateEvent:', event
+
+    def suspendresume(self, onoff):
+        pass
+
+    def do_suspendresume(self, event):
+        self._suspended = not event[1] & 1
+        FrameWork.Application.do_suspendresume(self, event)
+
+    def checkopenwindowsmenu(self):
+        if self._openwindowscheckmark:
+            self.openwindowsmenu.menu.CheckMenuItem(self._openwindowscheckmark, 0)
+        window = MyFrontWindow()
+        if window:
+            for item, wid in self._openwindows.items():
+                if wid == window:
+                    #self.pythonwindowsmenuitem.check(1)
+                    self.openwindowsmenu.menu.CheckMenuItem(item, 1)
+                    self._openwindowscheckmark = item
+                    break
+        else:
+            self._openwindowscheckmark = 0
+        #if self._openwindows:
+        #       self.pythonwindowsmenuitem.enable(1)
+        #else:
+        #       self.pythonwindowsmenuitem.enable(0)
+
+    def checkmenus(self, window):
+        for item in self._menustocheck:
+            callback = item.menu.items[item.item-1][2]
+            if type(callback) <> StringType:
+                item.enable(1)
+            elif hasattr(window, "domenu_" + callback):
+                if hasattr(window, "can_" + callback):
+                    canhandler = getattr(window, "can_" + callback)
+                    if canhandler(item):
+                        item.enable(1)
+                    else:
+                        item.enable(0)
+                else:
+                    item.enable(1)
+            else:
+                item.enable(0)
+
+    def enablemenubar(self, onoff):
+        for m in self.menubar.menus.values():
+            if onoff:
+                m.menu.EnableMenuItem(0)
+            elif m.menu.GetMenuItemText(3) <> 'Cut': # ew...
+                m.menu.DisableMenuItem(0)
+        MenuToolbox.DrawMenuBar()
+
+    def makemenubar(self):
+        self.menubar = MenuBar(self)
+        FrameWork.AppleMenu(self.menubar, self.getabouttext(), self.do_about)
+        self.makeusermenus()
+
+    def scriptswalk(self, top, menu, done=None):
+        if menu.id > 200:
+            import W
+            W.Message("Scripts folder not completely traversed: running out of menus")
+            return False
+        if done is None:
+            done = {}
+        if done.has_key(top):
+            return True
+        done[top] = 1
+        import os, string
+        try:
+            names = os.listdir(top)
+        except os.error:
+            FrameWork.MenuItem(menu, '(Scripts Folder not found)', None, None)
+            return True
+        savedir = os.getcwd()
+        os.chdir(top)
+        for name in names:
+            if name == "CVS":
+                continue
+            try:
+                fsr, isdir, isalias = File.FSResolveAliasFile(name, 1)
+            except:
+                # maybe a broken alias
+                continue
+            path = fsr.as_pathname()
+            if done.has_key(path):
+                continue
+            name = string.strip(name)
+            if os.name == "posix":
+                name = unicode(name, "utf-8")
+            if name[-3:] == '---':
+                menu.addseparator()
+            elif isdir:
+                submenu = FrameWork.SubMenu(menu, name)
+                if not self.scriptswalk(path, submenu, done):
+                    return False
+            else:
+                creator, type = MacOS.GetCreatorAndType(path)
+                if type == 'TEXT':
+                    if name[-3:] == '.py':
+                        name = name[:-3]
+                    item = FrameWork.MenuItem(menu, name, None, self.domenu_script)
+                    self._scripts[(menu.id, item.item)] = path
+            done[path] = 1
+        os.chdir(savedir)
+        return True
+
+    def domenu_script(self, id, item, window, event):
+        (what, message, when, where, modifiers) = event
+        path = self._scripts[(id, item)]
+        import os
+        if not os.path.exists(path):
+            self.makescriptsmenu()
+            import W
+            raise W.AlertError, "File not found."
+        if ord(Evt.GetKeys()[7]) & 4:
+            self.openscript(path)
+        else:
+            import W, MacOS, sys
+            W.SetCursor("watch")
+            sys.argv = [path]
+            #cwd = os.getcwd()
+            #os.chdir(os.path.dirname(path) + ':')
+            try:
+                # xxx if there is a script window for this file,
+                # exec in that window's namespace.
+                # xxx what to do when it's not saved???
+                # promt to save?
+                if hasattr(MacOS, 'EnableAppswitch'):
+                    MacOS.EnableAppswitch(0)
+                execfile(path, {'__name__': '__main__', '__file__': path})
+            except W.AlertError, detail:
+                if hasattr(MacOS, 'EnableAppswitch'):
+                    MacOS.EnableAppswitch(-1)
+                raise W.AlertError, detail
+            except KeyboardInterrupt:
+                if hasattr(MacOS, 'EnableAppswitch'):
+                    MacOS.EnableAppswitch(-1)
+            except:
+                if hasattr(MacOS, 'EnableAppswitch'):
+                    MacOS.EnableAppswitch(-1)
+                import PyEdit
+                PyEdit.tracebackwindow.traceback(1)
+            else:
+                if hasattr(MacOS, 'EnableAppswitch'):
+                    MacOS.EnableAppswitch(-1)
+            #os.chdir(cwd)
+
+    def openscript(self, filename, lineno=None, charoffset=0, modname=""):
+        import os, PyEdit, W
+        editor = self.getscript(filename)
+        if editor:
+            editor.select()
+        elif os.path.exists(filename):
+            editor = PyEdit.Editor(filename)
+        elif filename[-3:] == '.py' or filename[-4:] == '.pyc':
+            import imp
+            if not modname:
+                if filename[-1] == 'c':
+                    modname = os.path.basename(filename)[:-4]
+                else:
+                    modname = os.path.basename(filename)[:-3]
+            try:
+                # XXX This does not work correctly with packages!
+                # XXX The docs say we should do it manually, pack, then sub, then sub2 etc.
+                # XXX It says we should use imp.load_module(), but that *reloads* a package,
+                # XXX and that's the last thing we want here.
+                f, filename, (suff, mode, dummy) = imp.find_module(modname)
+            except ImportError:
+                raise W.AlertError, "Can't find file for \"%s\"" % modname
+            else:
+                if not f:
+                    raise W.AlertError, "Can't find file for \"%s\"" % modname
+                f.close()
+            if suff == '.py':
+                self.openscript(filename, lineno, charoffset)
+                return
+            else:
+                raise W.AlertError, "Can't find file for \"%s\"" % modname
+        else:
+            raise W.AlertError, "Can't find file \"%s\"" % filename
+        if lineno is not None:
+            editor.selectline(lineno, charoffset)
+        return editor
+
+    def getscript(self, filename):
+        if filename[:1] == '<' and filename[-1:] == '>':
+            filename = filename[1:-1]
+        import string
+        lowpath = string.lower(filename)
+        for wid, window in self._windows.items():
+            if hasattr(window, "path") and type(window.path) == StringType and \
+                            lowpath == string.lower(window.path):
+                return window
+            elif hasattr(window, "path") and filename == wid.GetWTitle():
+                return window
+
+    def getprefs(self):
+        import MacPrefs
+        return MacPrefs.GetPrefs(self.preffilepath)
+
+    def do_editorprefs(self, *args):
+        import PyEdit
+        PyEdit.EditorDefaultSettings()
+
+    def do_setwindowfont(self, *args):
+        import FontSettings, W
+        prefs = self.getprefs()
+        settings = FontSettings.FontDialog(prefs.defaultfont)
+        if settings:
+            prefs.defaultfont, tabsettings = settings
+            raise W.AlertError, "Note that changes will only affect new windows!"
 
 
 
 class MenuBar(FrameWork.MenuBar):
-	
-	possibleIDs = range(10, 256)
-	
-	def getnextid(self):
-		id = self.possibleIDs[0]
-		del self.possibleIDs[0]
-		return id
-	
-	def __init__(self, parent = None):
-		self.bar = MenuToolbox.GetMenuBar()
-		MenuToolbox.ClearMenuBar()
-		self.menus = {}
-		self.parent = parent
-	
-	def dispatch(self, id, item, window, event):
-		if self.menus.has_key(id):
-			self.menus[id].dispatch(id, item, window, event)
-	
-	def delmenu(self, id):
-		MenuToolbox.DeleteMenu(id)
-		if id in self.possibleIDs:
-			print "XXX duplicate menu ID!", id
-		self.possibleIDs.append(id)
-	
+
+    possibleIDs = range(10, 256)
+
+    def getnextid(self):
+        id = self.possibleIDs[0]
+        del self.possibleIDs[0]
+        return id
+
+    def __init__(self, parent = None):
+        self.bar = MenuToolbox.GetMenuBar()
+        MenuToolbox.ClearMenuBar()
+        self.menus = {}
+        self.parent = parent
+
+    def dispatch(self, id, item, window, event):
+        if self.menus.has_key(id):
+            self.menus[id].dispatch(id, item, window, event)
+
+    def delmenu(self, id):
+        MenuToolbox.DeleteMenu(id)
+        if id in self.possibleIDs:
+            print "XXX duplicate menu ID!", id
+        self.possibleIDs.append(id)
+
 
 class Menu(FrameWork.Menu):
-	
-	def dispatch(self, id, item, window, event):
-		title, shortcut, callback, kind = self.items[item-1]
-		if type(callback) == StringType:
-			callback = self._getmenuhandler(callback)
-		if callback:
-			import W
-			W.CallbackCall(callback, 0, id, item, window, event)
-	
-	def _getmenuhandler(self, callback):
-		menuhandler = None
-		wid = MyFrontWindow()
-		if wid and self.bar.parent._windows.has_key(wid):
-			window = self.bar.parent._windows[wid]
-			if hasattr(window, "domenu_" + callback):
-				menuhandler = getattr(window, "domenu_" + callback)
-			elif hasattr(self.bar.parent, "domenu_" + callback):
-				menuhandler = getattr(self.bar.parent, "domenu_" + callback)
-		elif hasattr(self.bar.parent, "domenu_" + callback):
-			menuhandler = getattr(self.bar.parent, "domenu_" + callback)
-		return menuhandler
 
+    def dispatch(self, id, item, window, event):
+        title, shortcut, callback, kind = self.items[item-1]
+        if type(callback) == StringType:
+            callback = self._getmenuhandler(callback)
+        if callback:
+            import W
+            W.CallbackCall(callback, 0, id, item, window, event)
+
+    def _getmenuhandler(self, callback):
+        menuhandler = None
+        wid = MyFrontWindow()
+        if wid and self.bar.parent._windows.has_key(wid):
+            window = self.bar.parent._windows[wid]
+            if hasattr(window, "domenu_" + callback):
+                menuhandler = getattr(window, "domenu_" + callback)
+            elif hasattr(self.bar.parent, "domenu_" + callback):
+                menuhandler = getattr(self.bar.parent, "domenu_" + callback)
+        elif hasattr(self.bar.parent, "domenu_" + callback):
+            menuhandler = getattr(self.bar.parent, "domenu_" + callback)
+        return menuhandler
diff --git a/Mac/Tools/IDE/Wbase.py b/Mac/Tools/IDE/Wbase.py
index a5d556b..4eef120 100644
--- a/Mac/Tools/IDE/Wbase.py
+++ b/Mac/Tools/IDE/Wbase.py
@@ -9,790 +9,790 @@
 
 
 def _intRect((l, t, r, b)):
-	return (int(l), int(t), int(r), int(b))
+    return (int(l), int(t), int(r), int(b))
 
 
 class Widget:
-	
-	"""Base class for all widgets."""
-	
-	_selectable = 0
-	
-	def __init__(self, possize):
-		self._widgets = []
-		self._widgetsdict = {}
-		self._possize = possize
-		self._bounds = None
-		self._visible = 1
-		self._enabled = 0
-		self._selected = 0
-		self._activated = 0
-		self._callback = None
-		self._parent = None
-		self._parentwindow = None
-		self._bindings = {}
-		self._backcolor = None
-	
-	def show(self, onoff):
-		self._visible = onoff
-		for w in self._widgets:
-			w.show(onoff)
-		if self._parentwindow is not None and self._parentwindow.wid is not None:
-			self.SetPort()
-			if onoff:
-				self.draw()
-			else:
-				Qd.EraseRect(self._bounds)
-	
-	def draw(self, visRgn = None):
-		if self._visible:
-			# draw your stuff here
-			pass
-	
-	def getpossize(self):
-		return self._possize
-	
-	def getbounds(self):
-		return self._bounds
-	
-	def move(self, x, y = None):
-		"""absolute move"""
-		if y == None:
-			x, y = x
-		if type(self._possize) <> TupleType:
-			raise WidgetsError, "can't move widget with bounds function"
-		l, t, r, b = self._possize
-		self.resize(x, y, r, b)
-	
-	def rmove(self, x, y = None):
-		"""relative move"""
-		if y == None:
-			x, y = x
-		if type(self._possize) <> TupleType:
-			raise WidgetsError, "can't move widget with bounds function"
-		l, t, r, b = self._possize
-		self.resize(l + x, t + y, r, b)
-		
-	def resize(self, *args):
-		if len(args) == 1:
-			if type(args[0]) == FunctionType or type(args[0]) == MethodType:
-				self._possize = args[0]
-			else:
-				apply(self.resize, args[0])
-		elif len(args) == 2:
-			self._possize = (0, 0) + args
-		elif len(args) == 4:
-			self._possize = args
-		else:
-			raise TypeError, "wrong number of arguments"
-		self._calcbounds()
-	
-	def open(self):
-		self._calcbounds()
-	
-	def close(self):
-		del self._callback
-		del self._possize
-		del self._bindings
-		del self._parent
-		del self._parentwindow
-	
-	def bind(self, key, callback):
-		"""bind a key or an 'event' to a callback"""
-		if callback:
-			self._bindings[key] = callback
-		elif self._bindings.has_key(key):
-			del self._bindings[key]
-	
-	def adjust(self, oldbounds):
-		self.SetPort()
-		self.GetWindow().InvalWindowRect(oldbounds)
-		self.GetWindow().InvalWindowRect(self._bounds)
-	
-	def _calcbounds(self):
-		# calculate absolute bounds relative to the window origin from our
-		# abstract _possize attribute, which is either a 4-tuple or a callable object
-		oldbounds = self._bounds
-		pl, pt, pr, pb = self._parent._bounds
-		if callable(self._possize):
-			# _possize is callable, let it figure it out by itself: it should return 
-			# the bounds relative to our parent widget.
-			width = pr - pl
-			height = pb - pt
-			self._bounds = Qd.OffsetRect(_intRect(self._possize(width, height)), pl, pt)
-		else:
-			# _possize must be a 4-tuple. This is where the algorithm by Peter Kriens and
-			# Petr van Blokland kicks in. (*** Parts of this algorithm are applied for 
-			# patents by Ericsson, Sweden ***)
-			l, t, r, b = self._possize
-			# depending on the values of l(eft), t(op), r(right) and b(ottom), 
-			# they mean different things:
-			if l < -1:
-				# l is less than -1, this mean it measures from the *right* of it's parent
-				l = pr + l
-			else:
-				# l is -1 or greater, this mean it measures from the *left* of it's parent
-				l = pl + l
-			if t < -1:
-				# t is less than -1, this mean it measures from the *bottom* of it's parent
-				t = pb + t
-			else:
-				# t is -1 or greater, this mean it measures from the *top* of it's parent
-				t = pt + t
-			if r > 1:
-				# r is greater than 1, this means r is the *width* of the widget
-				r = l + r
-			else:
-				# r is less than 1, this means it measures from the *right* of it's parent
-				r = pr + r
-			if b > 1:
-				# b is greater than 1, this means b is the *height* of the widget
-				b = t + b
-			else:
-				# b is less than 1, this means it measures from the *bottom* of it's parent
-				b = pb + b
-			self._bounds = (l, t, r, b)
-		if oldbounds and oldbounds <> self._bounds:
-			self.adjust(oldbounds)
-		for w in self._widgets:
-			w._calcbounds()
-	
-	def test(self, point):
-		if Qd.PtInRect(point, self._bounds):
-			return 1
-	
-	def click(self, point, modifiers):
-		pass
-	
-	def findwidget(self, point, onlyenabled = 1):
-		if self.test(point):
-			for w in self._widgets:
-				widget = w.findwidget(point)
-				if widget is not None:
-					return widget
-			if self._enabled or not onlyenabled:
-				return self
-	
-	def forall(self, methodname, *args):
-		for w in self._widgets:
-			rv = apply(w.forall, (methodname,) + args)
-			if rv: 
-				return rv
-		if self._bindings.has_key("<" + methodname + ">"):
-			callback = self._bindings["<" + methodname + ">"]
-			rv = apply(callback, args)
-			if rv: 
-				return rv
-		if hasattr(self, methodname):
-			method = getattr(self, methodname)
-			return apply(method, args)
-	
-	def forall_butself(self, methodname, *args):
-		for w in self._widgets:
-			rv = apply(w.forall, (methodname,) + args)
-			if rv: 
-				return rv
-	
-	def forall_frombottom(self, methodname, *args):
-		if self._bindings.has_key("<" + methodname + ">"):
-			callback = self._bindings["<" + methodname + ">"]
-			rv = apply(callback, args)
-			if rv: 
-				return rv
-		if hasattr(self, methodname):
-			method = getattr(self, methodname)
-			rv = apply(method, args)
-			if rv: 
-				return rv
-		for w in self._widgets:
-			rv = apply(w.forall_frombottom, (methodname,) + args)
-			if rv: 
-				return rv
-	
-	def _addwidget(self, key, widget):
-		if widget in self._widgets:
-			raise ValueError, "duplicate widget"
-		if self._widgetsdict.has_key(key):
-			self._removewidget(key)
-		self._widgets.append(widget)
-		self._widgetsdict[key] = widget
-		widget._parent = self
-		self._setparentwindow(widget)
-		if self._parentwindow and self._parentwindow.wid:
-			widget.forall_frombottom("open")
-			self.GetWindow().InvalWindowRect(widget._bounds)
-	
-	def _setparentwindow(self, widget):
-		widget._parentwindow = self._parentwindow
-		for w in widget._widgets:
-			self._setparentwindow(w)
-	
-	def _removewidget(self, key):
-		if not self._widgetsdict.has_key(key):
-			raise KeyError, "no widget with key %r" % (key,)
-		widget = self._widgetsdict[key]
-		for k in widget._widgetsdict.keys():
-			widget._removewidget(k)
-		if self._parentwindow._currentwidget == widget:
-			widget.select(0)
-			self._parentwindow._currentwidget = None
-		self.SetPort()
-		self.GetWindow().InvalWindowRect(widget._bounds)
-		widget.close()
-		del self._widgetsdict[key]
-		self._widgets.remove(widget)
-	
-	def __setattr__(self, attr, value):
-		if type(value) == InstanceType and isinstance(value, Widget) and	\
-				attr not in ("_currentwidget", "_lastrollover", 
-				"_parent", "_parentwindow", "_defaultbutton"):
-			if hasattr(self, attr):
-				raise ValueError, "Can't replace existing attribute: " + attr
-			self._addwidget(attr, value)
-		self.__dict__[attr] = value
-	
-	def __delattr__(self, attr):
-		if attr == "_widgetsdict":
-			raise AttributeError, "cannot delete attribute _widgetsdict"
-		if self._widgetsdict.has_key(attr):
-			self._removewidget(attr)
-			if self.__dict__.has_key(attr):
-				del self.__dict__[attr]
-		elif self.__dict__.has_key(attr):
-			del self.__dict__[attr]
-		else:
-			raise AttributeError, attr
-	
-	def __setitem__(self, key, value):
-		self._addwidget(key, value)
-	
-	def __getitem__(self, key):
-		if not self._widgetsdict.has_key(key):
-			raise KeyError, key
-		return self._widgetsdict[key]
-	
-	def __delitem__(self, key):
-		self._removewidget(key)
-	
-	def SetPort(self):
-		self._parentwindow.SetPort()
-		
 
-	def GetWindow(self):
-		return self._parentwindow.GetWindow()
-		
-	def __del__(self):
-		if DEBUG:
-			print "%s instance deleted" % self.__class__.__name__
-	
-	def _drawbounds(self):
-		Qd.FrameRect(self._bounds)
+    """Base class for all widgets."""
+
+    _selectable = 0
+
+    def __init__(self, possize):
+        self._widgets = []
+        self._widgetsdict = {}
+        self._possize = possize
+        self._bounds = None
+        self._visible = 1
+        self._enabled = 0
+        self._selected = 0
+        self._activated = 0
+        self._callback = None
+        self._parent = None
+        self._parentwindow = None
+        self._bindings = {}
+        self._backcolor = None
+
+    def show(self, onoff):
+        self._visible = onoff
+        for w in self._widgets:
+            w.show(onoff)
+        if self._parentwindow is not None and self._parentwindow.wid is not None:
+            self.SetPort()
+            if onoff:
+                self.draw()
+            else:
+                Qd.EraseRect(self._bounds)
+
+    def draw(self, visRgn = None):
+        if self._visible:
+            # draw your stuff here
+            pass
+
+    def getpossize(self):
+        return self._possize
+
+    def getbounds(self):
+        return self._bounds
+
+    def move(self, x, y = None):
+        """absolute move"""
+        if y == None:
+            x, y = x
+        if type(self._possize) <> TupleType:
+            raise WidgetsError, "can't move widget with bounds function"
+        l, t, r, b = self._possize
+        self.resize(x, y, r, b)
+
+    def rmove(self, x, y = None):
+        """relative move"""
+        if y == None:
+            x, y = x
+        if type(self._possize) <> TupleType:
+            raise WidgetsError, "can't move widget with bounds function"
+        l, t, r, b = self._possize
+        self.resize(l + x, t + y, r, b)
+
+    def resize(self, *args):
+        if len(args) == 1:
+            if type(args[0]) == FunctionType or type(args[0]) == MethodType:
+                self._possize = args[0]
+            else:
+                apply(self.resize, args[0])
+        elif len(args) == 2:
+            self._possize = (0, 0) + args
+        elif len(args) == 4:
+            self._possize = args
+        else:
+            raise TypeError, "wrong number of arguments"
+        self._calcbounds()
+
+    def open(self):
+        self._calcbounds()
+
+    def close(self):
+        del self._callback
+        del self._possize
+        del self._bindings
+        del self._parent
+        del self._parentwindow
+
+    def bind(self, key, callback):
+        """bind a key or an 'event' to a callback"""
+        if callback:
+            self._bindings[key] = callback
+        elif self._bindings.has_key(key):
+            del self._bindings[key]
+
+    def adjust(self, oldbounds):
+        self.SetPort()
+        self.GetWindow().InvalWindowRect(oldbounds)
+        self.GetWindow().InvalWindowRect(self._bounds)
+
+    def _calcbounds(self):
+        # calculate absolute bounds relative to the window origin from our
+        # abstract _possize attribute, which is either a 4-tuple or a callable object
+        oldbounds = self._bounds
+        pl, pt, pr, pb = self._parent._bounds
+        if callable(self._possize):
+            # _possize is callable, let it figure it out by itself: it should return
+            # the bounds relative to our parent widget.
+            width = pr - pl
+            height = pb - pt
+            self._bounds = Qd.OffsetRect(_intRect(self._possize(width, height)), pl, pt)
+        else:
+            # _possize must be a 4-tuple. This is where the algorithm by Peter Kriens and
+            # Petr van Blokland kicks in. (*** Parts of this algorithm are applied for
+            # patents by Ericsson, Sweden ***)
+            l, t, r, b = self._possize
+            # depending on the values of l(eft), t(op), r(right) and b(ottom),
+            # they mean different things:
+            if l < -1:
+                # l is less than -1, this mean it measures from the *right* of it's parent
+                l = pr + l
+            else:
+                # l is -1 or greater, this mean it measures from the *left* of it's parent
+                l = pl + l
+            if t < -1:
+                # t is less than -1, this mean it measures from the *bottom* of it's parent
+                t = pb + t
+            else:
+                # t is -1 or greater, this mean it measures from the *top* of it's parent
+                t = pt + t
+            if r > 1:
+                # r is greater than 1, this means r is the *width* of the widget
+                r = l + r
+            else:
+                # r is less than 1, this means it measures from the *right* of it's parent
+                r = pr + r
+            if b > 1:
+                # b is greater than 1, this means b is the *height* of the widget
+                b = t + b
+            else:
+                # b is less than 1, this means it measures from the *bottom* of it's parent
+                b = pb + b
+            self._bounds = (l, t, r, b)
+        if oldbounds and oldbounds <> self._bounds:
+            self.adjust(oldbounds)
+        for w in self._widgets:
+            w._calcbounds()
+
+    def test(self, point):
+        if Qd.PtInRect(point, self._bounds):
+            return 1
+
+    def click(self, point, modifiers):
+        pass
+
+    def findwidget(self, point, onlyenabled = 1):
+        if self.test(point):
+            for w in self._widgets:
+                widget = w.findwidget(point)
+                if widget is not None:
+                    return widget
+            if self._enabled or not onlyenabled:
+                return self
+
+    def forall(self, methodname, *args):
+        for w in self._widgets:
+            rv = apply(w.forall, (methodname,) + args)
+            if rv:
+                return rv
+        if self._bindings.has_key("<" + methodname + ">"):
+            callback = self._bindings["<" + methodname + ">"]
+            rv = apply(callback, args)
+            if rv:
+                return rv
+        if hasattr(self, methodname):
+            method = getattr(self, methodname)
+            return apply(method, args)
+
+    def forall_butself(self, methodname, *args):
+        for w in self._widgets:
+            rv = apply(w.forall, (methodname,) + args)
+            if rv:
+                return rv
+
+    def forall_frombottom(self, methodname, *args):
+        if self._bindings.has_key("<" + methodname + ">"):
+            callback = self._bindings["<" + methodname + ">"]
+            rv = apply(callback, args)
+            if rv:
+                return rv
+        if hasattr(self, methodname):
+            method = getattr(self, methodname)
+            rv = apply(method, args)
+            if rv:
+                return rv
+        for w in self._widgets:
+            rv = apply(w.forall_frombottom, (methodname,) + args)
+            if rv:
+                return rv
+
+    def _addwidget(self, key, widget):
+        if widget in self._widgets:
+            raise ValueError, "duplicate widget"
+        if self._widgetsdict.has_key(key):
+            self._removewidget(key)
+        self._widgets.append(widget)
+        self._widgetsdict[key] = widget
+        widget._parent = self
+        self._setparentwindow(widget)
+        if self._parentwindow and self._parentwindow.wid:
+            widget.forall_frombottom("open")
+            self.GetWindow().InvalWindowRect(widget._bounds)
+
+    def _setparentwindow(self, widget):
+        widget._parentwindow = self._parentwindow
+        for w in widget._widgets:
+            self._setparentwindow(w)
+
+    def _removewidget(self, key):
+        if not self._widgetsdict.has_key(key):
+            raise KeyError, "no widget with key %r" % (key,)
+        widget = self._widgetsdict[key]
+        for k in widget._widgetsdict.keys():
+            widget._removewidget(k)
+        if self._parentwindow._currentwidget == widget:
+            widget.select(0)
+            self._parentwindow._currentwidget = None
+        self.SetPort()
+        self.GetWindow().InvalWindowRect(widget._bounds)
+        widget.close()
+        del self._widgetsdict[key]
+        self._widgets.remove(widget)
+
+    def __setattr__(self, attr, value):
+        if type(value) == InstanceType and isinstance(value, Widget) and        \
+                        attr not in ("_currentwidget", "_lastrollover",
+                        "_parent", "_parentwindow", "_defaultbutton"):
+            if hasattr(self, attr):
+                raise ValueError, "Can't replace existing attribute: " + attr
+            self._addwidget(attr, value)
+        self.__dict__[attr] = value
+
+    def __delattr__(self, attr):
+        if attr == "_widgetsdict":
+            raise AttributeError, "cannot delete attribute _widgetsdict"
+        if self._widgetsdict.has_key(attr):
+            self._removewidget(attr)
+            if self.__dict__.has_key(attr):
+                del self.__dict__[attr]
+        elif self.__dict__.has_key(attr):
+            del self.__dict__[attr]
+        else:
+            raise AttributeError, attr
+
+    def __setitem__(self, key, value):
+        self._addwidget(key, value)
+
+    def __getitem__(self, key):
+        if not self._widgetsdict.has_key(key):
+            raise KeyError, key
+        return self._widgetsdict[key]
+
+    def __delitem__(self, key):
+        self._removewidget(key)
+
+    def SetPort(self):
+        self._parentwindow.SetPort()
+
+
+    def GetWindow(self):
+        return self._parentwindow.GetWindow()
+
+    def __del__(self):
+        if DEBUG:
+            print "%s instance deleted" % self.__class__.__name__
+
+    def _drawbounds(self):
+        Qd.FrameRect(self._bounds)
 
 
 class ClickableWidget(Widget):
-	
-	"""Base class for clickable widgets. (note: self._enabled must be true to receive click events.)"""
-	
-	def click(self, point, modifiers):
-		pass
-	
-	def enable(self, onoff):
-		self._enabled = onoff
-		self.SetPort()
-		self.draw()
-	
-	def callback(self):
-		if self._callback:
-			return CallbackCall(self._callback, 1)
-	
+
+    """Base class for clickable widgets. (note: self._enabled must be true to receive click events.)"""
+
+    def click(self, point, modifiers):
+        pass
+
+    def enable(self, onoff):
+        self._enabled = onoff
+        self.SetPort()
+        self.draw()
+
+    def callback(self):
+        if self._callback:
+            return CallbackCall(self._callback, 1)
+
 
 class SelectableWidget(ClickableWidget):
 
-	"""Base class for selectable widgets."""
-	
-	_selectable = 1
-	
-	def select(self, onoff, isclick = 0):
-		if onoff == self._selected:
-			return 1
-		if self._bindings.has_key("<select>"):
-			callback = self._bindings["<select>"]
-			if callback(onoff):
-				return 1
-		self._selected = onoff
-		if onoff:
-			if self._parentwindow._currentwidget is not None:
-				self._parentwindow._currentwidget.select(0)
-			self._parentwindow._currentwidget = self
-		else:
-			self._parentwindow._currentwidget = None
-	
-	def key(self, char, event):
-		pass
-	
-	def drawselframe(self, onoff):
-		if not self._parentwindow._hasselframes:
-			return
-		App.DrawThemeFocusRect(self._bounds, onoff)
-	
-	def adjust(self, oldbounds):
-		self.SetPort()
-		if self._selected:
-			self.GetWindow().InvalWindowRect(Qd.InsetRect(oldbounds, -3, -3))
-			self.GetWindow().InvalWindowRect(Qd.InsetRect(self._bounds, -3, -3))
-		else:
-			self.GetWindow().InvalWindowRect(oldbounds)
-			self.GetWindow().InvalWindowRect(self._bounds)
+    """Base class for selectable widgets."""
+
+    _selectable = 1
+
+    def select(self, onoff, isclick = 0):
+        if onoff == self._selected:
+            return 1
+        if self._bindings.has_key("<select>"):
+            callback = self._bindings["<select>"]
+            if callback(onoff):
+                return 1
+        self._selected = onoff
+        if onoff:
+            if self._parentwindow._currentwidget is not None:
+                self._parentwindow._currentwidget.select(0)
+            self._parentwindow._currentwidget = self
+        else:
+            self._parentwindow._currentwidget = None
+
+    def key(self, char, event):
+        pass
+
+    def drawselframe(self, onoff):
+        if not self._parentwindow._hasselframes:
+            return
+        App.DrawThemeFocusRect(self._bounds, onoff)
+
+    def adjust(self, oldbounds):
+        self.SetPort()
+        if self._selected:
+            self.GetWindow().InvalWindowRect(Qd.InsetRect(oldbounds, -3, -3))
+            self.GetWindow().InvalWindowRect(Qd.InsetRect(self._bounds, -3, -3))
+        else:
+            self.GetWindow().InvalWindowRect(oldbounds)
+            self.GetWindow().InvalWindowRect(self._bounds)
 
 
 class _Line(Widget):
-	
-	def __init__(self, possize, thickness = 1):
-		Widget.__init__(self, possize)
-		self._thickness = thickness
-	
-	def open(self):
-		self._calcbounds()
-		self.SetPort()
-		self.draw()
-	
-	def draw(self, visRgn = None):
-		if self._visible:
-			Qd.PaintRect(self._bounds)
-	
-	def _drawbounds(self):
-		pass
+
+    def __init__(self, possize, thickness = 1):
+        Widget.__init__(self, possize)
+        self._thickness = thickness
+
+    def open(self):
+        self._calcbounds()
+        self.SetPort()
+        self.draw()
+
+    def draw(self, visRgn = None):
+        if self._visible:
+            Qd.PaintRect(self._bounds)
+
+    def _drawbounds(self):
+        pass
 
 class HorizontalLine(_Line):
-	
-	def _calcbounds(self):
-		Widget._calcbounds(self)
-		l, t, r, b = self._bounds
-		self._bounds = l, t, r, t + self._thickness
+
+    def _calcbounds(self):
+        Widget._calcbounds(self)
+        l, t, r, b = self._bounds
+        self._bounds = l, t, r, t + self._thickness
 
 class VerticalLine(_Line):
-	
-	def _calcbounds(self):
-		Widget._calcbounds(self)
-		l, t, r, b = self._bounds
-		self._bounds = l, t, l + self._thickness, b
+
+    def _calcbounds(self):
+        Widget._calcbounds(self)
+        l, t, r, b = self._bounds
+        self._bounds = l, t, l + self._thickness, b
 
 
 class Frame(Widget):
-	
-	def __init__(self, possize, pattern = Qd.GetQDGlobalsBlack(), color = (0, 0, 0)):
-		Widget.__init__(self, possize)
-		self._framepattern = pattern
-		self._framecolor = color
-	
-	def setcolor(self, color):
-		self._framecolor = color
-		self.SetPort()
-		self.draw()
-	
-	def setpattern(self, pattern):
-		self._framepattern = pattern
-		self.SetPort()
-		self.draw()
-		
-	def draw(self, visRgn = None):
-		if self._visible:
-			penstate = Qd.GetPenState()
-			Qd.PenPat(self._framepattern)
-			Qd.RGBForeColor(self._framecolor)
-			Qd.FrameRect(self._bounds)
-			Qd.RGBForeColor((0, 0, 0))
-			Qd.SetPenState(penstate)
+
+    def __init__(self, possize, pattern = Qd.GetQDGlobalsBlack(), color = (0, 0, 0)):
+        Widget.__init__(self, possize)
+        self._framepattern = pattern
+        self._framecolor = color
+
+    def setcolor(self, color):
+        self._framecolor = color
+        self.SetPort()
+        self.draw()
+
+    def setpattern(self, pattern):
+        self._framepattern = pattern
+        self.SetPort()
+        self.draw()
+
+    def draw(self, visRgn = None):
+        if self._visible:
+            penstate = Qd.GetPenState()
+            Qd.PenPat(self._framepattern)
+            Qd.RGBForeColor(self._framecolor)
+            Qd.FrameRect(self._bounds)
+            Qd.RGBForeColor((0, 0, 0))
+            Qd.SetPenState(penstate)
 
 def _darkencolor((r, g, b)):
-	return int(0.75 * r), int(0.75 * g), int(0.75 * b)
+    return int(0.75 * r), int(0.75 * g), int(0.75 * b)
 
 class BevelBox(Widget):
-	
-	"""'Platinum' beveled rectangle."""
-	
-	def __init__(self, possize, color = (0xe000, 0xe000, 0xe000)):
-		Widget.__init__(self, possize)
-		self._color = color
-		self._darkercolor = _darkencolor(color)
-	
-	def setcolor(self, color):
-		self._color = color
-		self.SetPort()
-		self.draw()
-	
-	def draw(self, visRgn = None):
-		if self._visible:
-			l, t, r, b = Qd.InsetRect(self._bounds, 1, 1)
-			Qd.RGBForeColor(self._color)
-			Qd.PaintRect((l, t, r, b))
-			Qd.RGBForeColor(self._darkercolor)
-			Qd.MoveTo(l, b)
-			Qd.LineTo(r, b)
-			Qd.LineTo(r, t)
-			Qd.RGBForeColor((0, 0, 0))
+
+    """'Platinum' beveled rectangle."""
+
+    def __init__(self, possize, color = (0xe000, 0xe000, 0xe000)):
+        Widget.__init__(self, possize)
+        self._color = color
+        self._darkercolor = _darkencolor(color)
+
+    def setcolor(self, color):
+        self._color = color
+        self.SetPort()
+        self.draw()
+
+    def draw(self, visRgn = None):
+        if self._visible:
+            l, t, r, b = Qd.InsetRect(self._bounds, 1, 1)
+            Qd.RGBForeColor(self._color)
+            Qd.PaintRect((l, t, r, b))
+            Qd.RGBForeColor(self._darkercolor)
+            Qd.MoveTo(l, b)
+            Qd.LineTo(r, b)
+            Qd.LineTo(r, t)
+            Qd.RGBForeColor((0, 0, 0))
 
 
 class Group(Widget):
-	
-	"""A container for subwidgets"""
+
+    """A container for subwidgets"""
 
 
 class HorizontalPanes(Widget):
-	
-	"""Panes, a.k.a. frames. Works a bit like a group. Devides the widget area into "panes",
-	which can be resized by the user by clicking and dragging between the subwidgets."""
-	
-	_direction = 1
-	
-	def __init__(self, possize, panesizes = None, gutter = 8):
-		"""panesizes should be a tuple of numbers. The length of the tuple is the number of panes, 
-		the items in the tuple are the relative sizes of these panes; these numbers should add up 
-		to 1 (the total size of all panes)."""
-		Widget.__init__(self, possize)
-		self._panesizes = panesizes
-		self._gutter = gutter
-		self._enabled = 1
-		self.setuppanes()
-	
-	#def open(self):
-	#	self.installbounds()
-	#	ClickableWidget.open(self)
-	
-	def _calcbounds(self):
-		# hmmm. It should not neccesary be override _calcbounds :-(
-		self.installbounds()
-		Widget._calcbounds(self)
-	
-	def setuppanes(self):
-		panesizes = self._panesizes
-		total = 0
-		if panesizes is not None:
-			#if len(self._widgets) <> len(panesizes):
-			#	raise TypeError, 'number of widgets does not match number of panes'
-			for panesize in panesizes:
-				if not 0 < panesize < 1:
-					raise TypeError, 'pane sizes must be between 0 and 1, not including.'
-				total = total + panesize
-			if round(total, 4) <> 1.0:
-				raise TypeError, 'pane sizes must add up to 1'
-		else:
-			# XXX does not work!
-			step = 1.0 / len(self._widgets)
-			panesizes = []
-			for i in range(len(self._widgets)):
-				panesizes.append(step)
-		current = 0
-		self._panesizes = []
-		self._gutters = []
-		for panesize in panesizes:
-			if current:
-				self._gutters.append(current)
-			self._panesizes.append((current, current + panesize))
-			current = current + panesize
-		self.makepanebounds()
-	
-	def getpanesizes(self):
-		return map(lambda (fr, to): to-fr,  self._panesizes)
-	
-	boundstemplate = "lambda width, height: (0, height * %s + %d, width, height * %s + %d)"
-	
-	def makepanebounds(self):
-		halfgutter = self._gutter / 2
-		self._panebounds = []
-		for i in range(len(self._panesizes)):
-			panestart, paneend = self._panesizes[i]
-			boundsstring = self.boundstemplate % (repr(panestart), panestart and halfgutter, 
-							repr(paneend), (paneend <> 1.0) and -halfgutter)
-			self._panebounds.append(eval(boundsstring))
-	
-	def installbounds(self):
-		#self.setuppanes()
-		for i in range(len(self._widgets)):
-			w = self._widgets[i]
-			w._possize = self._panebounds[i]
-			#if hasattr(w, "setuppanes"):
-			#	w.setuppanes()
-			if hasattr(w, "installbounds"):
-				w.installbounds()
-	
-	def rollover(self, point, onoff):
-		if onoff:
-			orgmouse = point[self._direction]
-			halfgutter = self._gutter / 2
-			l, t, r, b = self._bounds
-			if self._direction:
-				begin, end = t, b
-			else:
-				begin, end = l, r
-			
-			i = self.findgutter(orgmouse, begin, end)
-			if i is None:
-				SetCursor("arrow")
-			else:
-				SetCursor(self._direction and 'vmover' or 'hmover')
-	
-	def findgutter(self, orgmouse, begin, end):
-		tolerance = max(4, self._gutter) / 2
-		for i in range(len(self._gutters)):
-			pos = begin + (end - begin) * self._gutters[i]
-			if abs(orgmouse - pos) <= tolerance:
-				break
-		else:
-			return
-		return i
-	
-	def click(self, point, modifiers):
-		# what a mess...
-		orgmouse = point[self._direction]
-		halfgutter = self._gutter / 2
-		l, t, r, b = self._bounds
-		if self._direction:
-			begin, end = t, b
-		else:
-			begin, end = l, r
-		
-		i = self.findgutter(orgmouse, begin, end)
-		if i is None:
-			return
-		
-		pos = orgpos = begin + (end - begin) * self._gutters[i]	# init pos too, for fast click on border, bug done by Petr
-		
-		minpos = self._panesizes[i][0]
-		maxpos = self._panesizes[i+1][1]
-		minpos = begin + (end - begin) * minpos + 64
-		maxpos = begin + (end - begin) * maxpos - 64
-		if minpos > orgpos and maxpos < orgpos:
-			return
-		
-		#SetCursor("fist")
-		self.SetPort()
-		if self._direction:
-			rect = l, orgpos - 1, r, orgpos
-		else:
-			rect = orgpos - 1, t, orgpos, b
-		
-		# track mouse --- XXX  move to separate method?
-		Qd.PenMode(QuickDraw.srcXor)
-		Qd.PenPat(Qd.GetQDGlobalsGray())
-		Qd.PaintRect(_intRect(rect))
-		lastpos = None
-		while Evt.Button():
-			pos = orgpos - orgmouse + Evt.GetMouse()[self._direction]
-			pos = max(pos, minpos)
-			pos = min(pos, maxpos)
-			if pos == lastpos:
-				continue
-			Qd.PenPat(Qd.GetQDGlobalsGray())
-			Qd.PaintRect(_intRect(rect))
-			if self._direction:
-				rect = l, pos - 1, r, pos
-			else:
-				rect = pos - 1, t, pos, b
-			Qd.PenPat(Qd.GetQDGlobalsGray())
-			Qd.PaintRect(_intRect(rect))
-			lastpos = pos
-			self._parentwindow.wid.GetWindowPort().QDFlushPortBuffer(None)
-			Evt.WaitNextEvent(0, 3)
-		Qd.PaintRect(_intRect(rect))
-		Qd.PenNormal()
-		SetCursor("watch")
-		
-		newpos = (pos - begin) / float(end - begin)
-		self._gutters[i] = newpos
-		self._panesizes[i] = self._panesizes[i][0], newpos
-		self._panesizes[i+1] = newpos, self._panesizes[i+1][1]
-		self.makepanebounds()
-		self.installbounds()
-		self._calcbounds()
+
+    """Panes, a.k.a. frames. Works a bit like a group. Devides the widget area into "panes",
+    which can be resized by the user by clicking and dragging between the subwidgets."""
+
+    _direction = 1
+
+    def __init__(self, possize, panesizes = None, gutter = 8):
+        """panesizes should be a tuple of numbers. The length of the tuple is the number of panes,
+        the items in the tuple are the relative sizes of these panes; these numbers should add up
+        to 1 (the total size of all panes)."""
+        Widget.__init__(self, possize)
+        self._panesizes = panesizes
+        self._gutter = gutter
+        self._enabled = 1
+        self.setuppanes()
+
+    #def open(self):
+    #       self.installbounds()
+    #       ClickableWidget.open(self)
+
+    def _calcbounds(self):
+        # hmmm. It should not neccesary be override _calcbounds :-(
+        self.installbounds()
+        Widget._calcbounds(self)
+
+    def setuppanes(self):
+        panesizes = self._panesizes
+        total = 0
+        if panesizes is not None:
+            #if len(self._widgets) <> len(panesizes):
+            #       raise TypeError, 'number of widgets does not match number of panes'
+            for panesize in panesizes:
+                if not 0 < panesize < 1:
+                    raise TypeError, 'pane sizes must be between 0 and 1, not including.'
+                total = total + panesize
+            if round(total, 4) <> 1.0:
+                raise TypeError, 'pane sizes must add up to 1'
+        else:
+            # XXX does not work!
+            step = 1.0 / len(self._widgets)
+            panesizes = []
+            for i in range(len(self._widgets)):
+                panesizes.append(step)
+        current = 0
+        self._panesizes = []
+        self._gutters = []
+        for panesize in panesizes:
+            if current:
+                self._gutters.append(current)
+            self._panesizes.append((current, current + panesize))
+            current = current + panesize
+        self.makepanebounds()
+
+    def getpanesizes(self):
+        return map(lambda (fr, to): to-fr,  self._panesizes)
+
+    boundstemplate = "lambda width, height: (0, height * %s + %d, width, height * %s + %d)"
+
+    def makepanebounds(self):
+        halfgutter = self._gutter / 2
+        self._panebounds = []
+        for i in range(len(self._panesizes)):
+            panestart, paneend = self._panesizes[i]
+            boundsstring = self.boundstemplate % (repr(panestart), panestart and halfgutter,
+                                            repr(paneend), (paneend <> 1.0) and -halfgutter)
+            self._panebounds.append(eval(boundsstring))
+
+    def installbounds(self):
+        #self.setuppanes()
+        for i in range(len(self._widgets)):
+            w = self._widgets[i]
+            w._possize = self._panebounds[i]
+            #if hasattr(w, "setuppanes"):
+            #       w.setuppanes()
+            if hasattr(w, "installbounds"):
+                w.installbounds()
+
+    def rollover(self, point, onoff):
+        if onoff:
+            orgmouse = point[self._direction]
+            halfgutter = self._gutter / 2
+            l, t, r, b = self._bounds
+            if self._direction:
+                begin, end = t, b
+            else:
+                begin, end = l, r
+
+            i = self.findgutter(orgmouse, begin, end)
+            if i is None:
+                SetCursor("arrow")
+            else:
+                SetCursor(self._direction and 'vmover' or 'hmover')
+
+    def findgutter(self, orgmouse, begin, end):
+        tolerance = max(4, self._gutter) / 2
+        for i in range(len(self._gutters)):
+            pos = begin + (end - begin) * self._gutters[i]
+            if abs(orgmouse - pos) <= tolerance:
+                break
+        else:
+            return
+        return i
+
+    def click(self, point, modifiers):
+        # what a mess...
+        orgmouse = point[self._direction]
+        halfgutter = self._gutter / 2
+        l, t, r, b = self._bounds
+        if self._direction:
+            begin, end = t, b
+        else:
+            begin, end = l, r
+
+        i = self.findgutter(orgmouse, begin, end)
+        if i is None:
+            return
+
+        pos = orgpos = begin + (end - begin) * self._gutters[i] # init pos too, for fast click on border, bug done by Petr
+
+        minpos = self._panesizes[i][0]
+        maxpos = self._panesizes[i+1][1]
+        minpos = begin + (end - begin) * minpos + 64
+        maxpos = begin + (end - begin) * maxpos - 64
+        if minpos > orgpos and maxpos < orgpos:
+            return
+
+        #SetCursor("fist")
+        self.SetPort()
+        if self._direction:
+            rect = l, orgpos - 1, r, orgpos
+        else:
+            rect = orgpos - 1, t, orgpos, b
+
+        # track mouse --- XXX  move to separate method?
+        Qd.PenMode(QuickDraw.srcXor)
+        Qd.PenPat(Qd.GetQDGlobalsGray())
+        Qd.PaintRect(_intRect(rect))
+        lastpos = None
+        while Evt.Button():
+            pos = orgpos - orgmouse + Evt.GetMouse()[self._direction]
+            pos = max(pos, minpos)
+            pos = min(pos, maxpos)
+            if pos == lastpos:
+                continue
+            Qd.PenPat(Qd.GetQDGlobalsGray())
+            Qd.PaintRect(_intRect(rect))
+            if self._direction:
+                rect = l, pos - 1, r, pos
+            else:
+                rect = pos - 1, t, pos, b
+            Qd.PenPat(Qd.GetQDGlobalsGray())
+            Qd.PaintRect(_intRect(rect))
+            lastpos = pos
+            self._parentwindow.wid.GetWindowPort().QDFlushPortBuffer(None)
+            Evt.WaitNextEvent(0, 3)
+        Qd.PaintRect(_intRect(rect))
+        Qd.PenNormal()
+        SetCursor("watch")
+
+        newpos = (pos - begin) / float(end - begin)
+        self._gutters[i] = newpos
+        self._panesizes[i] = self._panesizes[i][0], newpos
+        self._panesizes[i+1] = newpos, self._panesizes[i+1][1]
+        self.makepanebounds()
+        self.installbounds()
+        self._calcbounds()
 
 
 class VerticalPanes(HorizontalPanes):
-	"""see HorizontalPanes"""
-	_direction = 0
-	boundstemplate = "lambda width, height: (width * %s + %d, 0, width * %s + %d, height)"
+    """see HorizontalPanes"""
+    _direction = 0
+    boundstemplate = "lambda width, height: (width * %s + %d, 0, width * %s + %d, height)"
 
 
 class ColorPicker(ClickableWidget):
-	
-	"""Color picker widget. Allows the user to choose a color."""
-	
-	def __init__(self, possize, color = (0, 0, 0), callback = None):
-		ClickableWidget.__init__(self, possize)
-		self._color = color
-		self._callback = callback
-		self._enabled = 1
-	
-	def click(self, point, modifiers):
-		if not self._enabled:
-			return
-		import ColorPicker
-		newcolor, ok = ColorPicker.GetColor("", self._color)
-		if ok:
-			self._color = newcolor
-			self.SetPort()
-			self.draw()
-			if self._callback:
-				return CallbackCall(self._callback, 0, self._color)
-	
-	def set(self, color):
-		self._color = color
-		self.SetPort()
-		self.draw()
-	
-	def get(self):
-		return self._color
-	
-	def draw(self, visRgn=None):
-		if self._visible:
-			if not visRgn:
-				visRgn = self._parentwindow.wid.GetWindowPort().visRgn
-			Qd.PenPat(Qd.GetQDGlobalsGray())
-			rect = self._bounds
-			Qd.FrameRect(rect)
-			rect = Qd.InsetRect(rect, 3, 3)
-			Qd.PenNormal()
-			Qd.RGBForeColor(self._color)
-			Qd.PaintRect(rect)
-			Qd.RGBForeColor((0, 0, 0))
-			
+
+    """Color picker widget. Allows the user to choose a color."""
+
+    def __init__(self, possize, color = (0, 0, 0), callback = None):
+        ClickableWidget.__init__(self, possize)
+        self._color = color
+        self._callback = callback
+        self._enabled = 1
+
+    def click(self, point, modifiers):
+        if not self._enabled:
+            return
+        import ColorPicker
+        newcolor, ok = ColorPicker.GetColor("", self._color)
+        if ok:
+            self._color = newcolor
+            self.SetPort()
+            self.draw()
+            if self._callback:
+                return CallbackCall(self._callback, 0, self._color)
+
+    def set(self, color):
+        self._color = color
+        self.SetPort()
+        self.draw()
+
+    def get(self):
+        return self._color
+
+    def draw(self, visRgn=None):
+        if self._visible:
+            if not visRgn:
+                visRgn = self._parentwindow.wid.GetWindowPort().visRgn
+            Qd.PenPat(Qd.GetQDGlobalsGray())
+            rect = self._bounds
+            Qd.FrameRect(rect)
+            rect = Qd.InsetRect(rect, 3, 3)
+            Qd.PenNormal()
+            Qd.RGBForeColor(self._color)
+            Qd.PaintRect(rect)
+            Qd.RGBForeColor((0, 0, 0))
+
 
 # misc utils
 
 def CallbackCall(callback, mustfit, *args):
-	"""internal helper routine for W"""
-	# XXX this function should die.
-	if type(callback) == FunctionType:
-		func = callback
-		maxargs = func.func_code.co_argcount
-	elif type(callback) == MethodType:
-		func = callback.im_func
-		maxargs = func.func_code.co_argcount - 1
-	else:
-		if callable(callback):
-			return apply(callback, args)
-		else:
-			raise TypeError, "uncallable callback object"
-	
-	if func.func_defaults:
-		minargs = maxargs - len(func.func_defaults)
-	else:
-		minargs = maxargs
-	if minargs <= len(args) <= maxargs:
-		return apply(callback, args)
-	elif not mustfit and minargs == 0:
-		return callback()
-	else:
-		if mustfit:
-			raise TypeError, "callback accepts wrong number of arguments: %r" % len(args)
-		else:
-			raise TypeError, "callback accepts wrong number of arguments: 0 or %r" % len(args)
+    """internal helper routine for W"""
+    # XXX this function should die.
+    if type(callback) == FunctionType:
+        func = callback
+        maxargs = func.func_code.co_argcount
+    elif type(callback) == MethodType:
+        func = callback.im_func
+        maxargs = func.func_code.co_argcount - 1
+    else:
+        if callable(callback):
+            return apply(callback, args)
+        else:
+            raise TypeError, "uncallable callback object"
+
+    if func.func_defaults:
+        minargs = maxargs - len(func.func_defaults)
+    else:
+        minargs = maxargs
+    if minargs <= len(args) <= maxargs:
+        return apply(callback, args)
+    elif not mustfit and minargs == 0:
+        return callback()
+    else:
+        if mustfit:
+            raise TypeError, "callback accepts wrong number of arguments: %r" % len(args)
+        else:
+            raise TypeError, "callback accepts wrong number of arguments: 0 or %r" % len(args)
 
 
 def HasBaseClass(obj, class_):
-	try:
-		raise obj
-	except class_:
-		return 1
-	except:
-		pass
-	return 0
+    try:
+        raise obj
+    except class_:
+        return 1
+    except:
+        pass
+    return 0
 
 
 #
 # To remove the dependence of Widgets.rsrc we hardcode the cursor
 # data below.
 #_cursors = {
-#	"watch"	: Qd.GetCursor(QuickDraw.watchCursor).data,
-#	"arrow"	: Qd.GetQDGlobalsArrow(),
-#	"iBeam"	: Qd.GetCursor(QuickDraw.iBeamCursor).data,
-#	"cross"	: Qd.GetCursor(QuickDraw.crossCursor).data,
-#	"plus"		: Qd.GetCursor(QuickDraw.plusCursor).data,
-#	"hand"	: Qd.GetCursor(468).data,
-#	"fist"		: Qd.GetCursor(469).data,
-#	"hmover"	: Qd.GetCursor(470).data,
-#	"vmover"	: Qd.GetCursor(471).data,
-#	"zoomin"	: Qd.GetCursor(472).data,
-#	"zoomout"	: Qd.GetCursor(473).data,
-#	"zoom"	: Qd.GetCursor(474).data,
+#       "watch" : Qd.GetCursor(QuickDraw.watchCursor).data,
+#       "arrow" : Qd.GetQDGlobalsArrow(),
+#       "iBeam" : Qd.GetCursor(QuickDraw.iBeamCursor).data,
+#       "cross" : Qd.GetCursor(QuickDraw.crossCursor).data,
+#       "plus"          : Qd.GetCursor(QuickDraw.plusCursor).data,
+#       "hand"  : Qd.GetCursor(468).data,
+#       "fist"          : Qd.GetCursor(469).data,
+#       "hmover"        : Qd.GetCursor(470).data,
+#       "vmover"        : Qd.GetCursor(471).data,
+#       "zoomin"        : Qd.GetCursor(472).data,
+#       "zoomout"       : Qd.GetCursor(473).data,
+#       "zoom"  : Qd.GetCursor(474).data,
 #}
 
 _cursors = {
-	'arrow':
-	'\x00\x00\x40\x00\x60\x00\x70\x00\x78\x00\x7c\x00\x7e\x00\x7f\x00'
-	'\x7f\x80\x7c\x00\x6c\x00\x46\x00\x06\x00\x03\x00\x03\x00\x00\x00'
-	'\xc0\x00\xe0\x00\xf0\x00\xf8\x00\xfc\x00\xfe\x00\xff\x00\xff\x80'
-	'\xff\xc0\xff\xe0\xfe\x00\xef\x00\xcf\x00\x87\x80\x07\x80\x03\x80'
-	'\x00\x01\x00\x01',
-	'cross':
-	'\x04\x00\x04\x00\x04\x00\x04\x00\x04\x00\xff\xe0\x04\x00\x04\x00'
-	'\x04\x00\x04\x00\x04\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00'
-	'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
-	'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
-	'\x00\x05\x00\x05',
-	'fist':
-	'\x00\x00\x00\x00\x0d\x80\x12\x70\x12\x4c\x12\x4a\x28\x0a\x28\x02'
-	'\x48\x02\x40\x02\x20\x02\x20\x04\x10\x04\x08\x08\x04\x08\x04\x08'
-	'\x00\x00\x00\x00\x0d\x80\x1f\xf0\x1f\xfc\x1f\xfe\x3f\xfe\x3f\xfe'
-	'\x7f\xfe\x7f\xfe\x3f\xfe\x3f\xfc\x1f\xfc\x0f\xf8\x07\xf8\x07\xf8'
-	'\x00\x09\x00\x08',
-	'hand':
-	'\x01\x80\x1a\x70\x26\x48\x26\x4a\x12\x4d\x12\x49\x68\x09\x98\x01'
-	'\x88\x02\x40\x02\x20\x02\x20\x04\x10\x04\x08\x08\x04\x08\x04\x08'
-	'\x01\x80\x1b\xf0\x3f\xf8\x3f\xfa\x1f\xff\x1f\xff\x6f\xff\xff\xff'
-	'\xff\xfe\x7f\xfe\x3f\xfe\x3f\xfc\x1f\xfc\x0f\xf8\x07\xf8\x07\xf8'
-	'\x00\x09\x00\x08',
-	'hmover':
-	'\x00\x00\x01\x80\x01\x80\x01\x80\x01\x80\x11\x88\x31\x8c\x7f\xfe'
-	'\x31\x8c\x11\x88\x01\x80\x01\x80\x01\x80\x01\x80\x00\x00\x00\x00'
-	'\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x1b\xd8\x3b\xdc\x7f\xfe\xff\xff'
-	'\x7f\xfe\x3b\xdc\x1b\xd8\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x00\x00'
-	'\x00\x07\x00\x07',
-	'iBeam':
-	'\x0c\x60\x02\x80\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00'
-	'\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x02\x80\x0c\x60'
-	'\x0c\x60\x02\x80\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00'
-	'\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x02\x80\x0c\x60'
-	'\x00\x04\x00\x07',
-	'plus':
-	'\x00\x00\x07\xc0\x04\x60\x04\x60\x04\x60\x7c\x7c\x43\x86\x42\x86'
-	'\x43\x86\x7c\x7e\x3c\x7e\x04\x60\x04\x60\x07\xe0\x03\xe0\x00\x00'
-	'\x0f\xc0\x0f\xe0\x0f\xf0\x0f\xf0\xff\xff\xff\xfe\xfc\x7f\xfc\x7f'
-	'\xfc\x7f\xff\xff\x7f\xff\x7f\xff\x0f\xf0\x0f\xf0\x07\xf0\x03\xe0'
-	'\x00\x08\x00\x08',
-	'vmover':
-	'\x00\x00\x01\x00\x03\x80\x07\xc0\x01\x00\x01\x00\x01\x00\x7f\xfc'
-	'\x7f\xfc\x01\x00\x01\x00\x01\x00\x07\xc0\x03\x80\x01\x00\x00\x00'
-	'\x01\x00\x03\x80\x07\xc0\x0f\xe0\x0f\xe0\x03\x80\xff\xfe\xff\xfe'
-	'\xff\xfe\xff\xfe\x03\x80\x0f\xe0\x0f\xe0\x07\xc0\x03\x80\x01\x00'
-	'\x00\x07\x00\x07',
-	'watch':
-	'\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x40\x80\x84\x40\x84\x40\x84\x60'
-	'\x9c\x60\x80\x40\x80\x40\x40\x80\x3f\x00\x3f\x00\x3f\x00\x3f\x00'
-	'\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x7f\x80\xff\xc0\xff\xc0\xff\xc0'
-	'\xff\xc0\xff\xc0\xff\xc0\x7f\x80\x3f\x00\x3f\x00\x3f\x00\x3f\x00'
-	'\x00\x08\x00\x08',
-	'zoom':
-	'\x0f\x00\x30\xc0\x40\x20\x40\x20\x80\x10\x80\x10\x80\x10\x80\x10'
-	'\x40\x20\x40\x20\x30\xf0\x0f\x38\x00\x1c\x00\x0e\x00\x07\x00\x02'
-	'\x0f\x00\x3f\xc0\x7f\xe0\x7f\xe0\xff\xf0\xff\xf0\xff\xf0\xff\xf0'
-	'\x7f\xe0\x7f\xe0\x3f\xf0\x0f\x38\x00\x1c\x00\x0e\x00\x07\x00\x02'
-	'\x00\x06\x00\x06',
-	'zoomin':
-	'\x0f\x00\x30\xc0\x40\x20\x46\x20\x86\x10\x9f\x90\x9f\x90\x86\x10'
-	'\x46\x20\x40\x20\x30\xf0\x0f\x38\x00\x1c\x00\x0e\x00\x07\x00\x02'
-	'\x0f\x00\x3f\xc0\x7f\xe0\x7f\xe0\xff\xf0\xff\xf0\xff\xf0\xff\xf0'
-	'\x7f\xe0\x7f\xe0\x3f\xf0\x0f\x38\x00\x1c\x00\x0e\x00\x07\x00\x02'
-	'\x00\x06\x00\x06',
-	'zoomout':
-	'\x0f\x00\x30\xc0\x40\x20\x40\x20\x80\x10\x9f\x90\x9f\x90\x80\x10'
-	'\x40\x20\x40\x20\x30\xf0\x0f\x38\x00\x1c\x00\x0e\x00\x07\x00\x02'
-	'\x0f\x00\x3f\xc0\x7f\xe0\x7f\xe0\xff\xf0\xff\xf0\xff\xf0\xff\xf0'
-	'\x7f\xe0\x7f\xe0\x3f\xf0\x0f\x38\x00\x1c\x00\x0e\x00\x07\x00\x02'
-	'\x00\x06\x00\x06',
+        'arrow':
+        '\x00\x00\x40\x00\x60\x00\x70\x00\x78\x00\x7c\x00\x7e\x00\x7f\x00'
+        '\x7f\x80\x7c\x00\x6c\x00\x46\x00\x06\x00\x03\x00\x03\x00\x00\x00'
+        '\xc0\x00\xe0\x00\xf0\x00\xf8\x00\xfc\x00\xfe\x00\xff\x00\xff\x80'
+        '\xff\xc0\xff\xe0\xfe\x00\xef\x00\xcf\x00\x87\x80\x07\x80\x03\x80'
+        '\x00\x01\x00\x01',
+        'cross':
+        '\x04\x00\x04\x00\x04\x00\x04\x00\x04\x00\xff\xe0\x04\x00\x04\x00'
+        '\x04\x00\x04\x00\x04\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+        '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+        '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+        '\x00\x05\x00\x05',
+        'fist':
+        '\x00\x00\x00\x00\x0d\x80\x12\x70\x12\x4c\x12\x4a\x28\x0a\x28\x02'
+        '\x48\x02\x40\x02\x20\x02\x20\x04\x10\x04\x08\x08\x04\x08\x04\x08'
+        '\x00\x00\x00\x00\x0d\x80\x1f\xf0\x1f\xfc\x1f\xfe\x3f\xfe\x3f\xfe'
+        '\x7f\xfe\x7f\xfe\x3f\xfe\x3f\xfc\x1f\xfc\x0f\xf8\x07\xf8\x07\xf8'
+        '\x00\x09\x00\x08',
+        'hand':
+        '\x01\x80\x1a\x70\x26\x48\x26\x4a\x12\x4d\x12\x49\x68\x09\x98\x01'
+        '\x88\x02\x40\x02\x20\x02\x20\x04\x10\x04\x08\x08\x04\x08\x04\x08'
+        '\x01\x80\x1b\xf0\x3f\xf8\x3f\xfa\x1f\xff\x1f\xff\x6f\xff\xff\xff'
+        '\xff\xfe\x7f\xfe\x3f\xfe\x3f\xfc\x1f\xfc\x0f\xf8\x07\xf8\x07\xf8'
+        '\x00\x09\x00\x08',
+        'hmover':
+        '\x00\x00\x01\x80\x01\x80\x01\x80\x01\x80\x11\x88\x31\x8c\x7f\xfe'
+        '\x31\x8c\x11\x88\x01\x80\x01\x80\x01\x80\x01\x80\x00\x00\x00\x00'
+        '\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x1b\xd8\x3b\xdc\x7f\xfe\xff\xff'
+        '\x7f\xfe\x3b\xdc\x1b\xd8\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x00\x00'
+        '\x00\x07\x00\x07',
+        'iBeam':
+        '\x0c\x60\x02\x80\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00'
+        '\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x02\x80\x0c\x60'
+        '\x0c\x60\x02\x80\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00'
+        '\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x02\x80\x0c\x60'
+        '\x00\x04\x00\x07',
+        'plus':
+        '\x00\x00\x07\xc0\x04\x60\x04\x60\x04\x60\x7c\x7c\x43\x86\x42\x86'
+        '\x43\x86\x7c\x7e\x3c\x7e\x04\x60\x04\x60\x07\xe0\x03\xe0\x00\x00'
+        '\x0f\xc0\x0f\xe0\x0f\xf0\x0f\xf0\xff\xff\xff\xfe\xfc\x7f\xfc\x7f'
+        '\xfc\x7f\xff\xff\x7f\xff\x7f\xff\x0f\xf0\x0f\xf0\x07\xf0\x03\xe0'
+        '\x00\x08\x00\x08',
+        'vmover':
+        '\x00\x00\x01\x00\x03\x80\x07\xc0\x01\x00\x01\x00\x01\x00\x7f\xfc'
+        '\x7f\xfc\x01\x00\x01\x00\x01\x00\x07\xc0\x03\x80\x01\x00\x00\x00'
+        '\x01\x00\x03\x80\x07\xc0\x0f\xe0\x0f\xe0\x03\x80\xff\xfe\xff\xfe'
+        '\xff\xfe\xff\xfe\x03\x80\x0f\xe0\x0f\xe0\x07\xc0\x03\x80\x01\x00'
+        '\x00\x07\x00\x07',
+        'watch':
+        '\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x40\x80\x84\x40\x84\x40\x84\x60'
+        '\x9c\x60\x80\x40\x80\x40\x40\x80\x3f\x00\x3f\x00\x3f\x00\x3f\x00'
+        '\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x7f\x80\xff\xc0\xff\xc0\xff\xc0'
+        '\xff\xc0\xff\xc0\xff\xc0\x7f\x80\x3f\x00\x3f\x00\x3f\x00\x3f\x00'
+        '\x00\x08\x00\x08',
+        'zoom':
+        '\x0f\x00\x30\xc0\x40\x20\x40\x20\x80\x10\x80\x10\x80\x10\x80\x10'
+        '\x40\x20\x40\x20\x30\xf0\x0f\x38\x00\x1c\x00\x0e\x00\x07\x00\x02'
+        '\x0f\x00\x3f\xc0\x7f\xe0\x7f\xe0\xff\xf0\xff\xf0\xff\xf0\xff\xf0'
+        '\x7f\xe0\x7f\xe0\x3f\xf0\x0f\x38\x00\x1c\x00\x0e\x00\x07\x00\x02'
+        '\x00\x06\x00\x06',
+        'zoomin':
+        '\x0f\x00\x30\xc0\x40\x20\x46\x20\x86\x10\x9f\x90\x9f\x90\x86\x10'
+        '\x46\x20\x40\x20\x30\xf0\x0f\x38\x00\x1c\x00\x0e\x00\x07\x00\x02'
+        '\x0f\x00\x3f\xc0\x7f\xe0\x7f\xe0\xff\xf0\xff\xf0\xff\xf0\xff\xf0'
+        '\x7f\xe0\x7f\xe0\x3f\xf0\x0f\x38\x00\x1c\x00\x0e\x00\x07\x00\x02'
+        '\x00\x06\x00\x06',
+        'zoomout':
+        '\x0f\x00\x30\xc0\x40\x20\x40\x20\x80\x10\x9f\x90\x9f\x90\x80\x10'
+        '\x40\x20\x40\x20\x30\xf0\x0f\x38\x00\x1c\x00\x0e\x00\x07\x00\x02'
+        '\x0f\x00\x3f\xc0\x7f\xe0\x7f\xe0\xff\xf0\xff\xf0\xff\xf0\xff\xf0'
+        '\x7f\xe0\x7f\xe0\x3f\xf0\x0f\x38\x00\x1c\x00\x0e\x00\x07\x00\x02'
+        '\x00\x06\x00\x06',
 }
 
 def SetCursor(what):
-	"""Set the cursorshape to any of these: 'arrow', 'cross', 'fist', 'hand', 'hmover', 'iBeam', 
-	'plus', 'vmover', 'watch', 'zoom', 'zoomin', 'zoomout'."""
-	Qd.SetCursor(_cursors[what])
+    """Set the cursorshape to any of these: 'arrow', 'cross', 'fist', 'hand', 'hmover', 'iBeam',
+    'plus', 'vmover', 'watch', 'zoom', 'zoomin', 'zoomout'."""
+    Qd.SetCursor(_cursors[what])
diff --git a/Mac/Tools/IDE/Wcontrols.py b/Mac/Tools/IDE/Wcontrols.py
index 58fc31b..00b06ac 100644
--- a/Mac/Tools/IDE/Wcontrols.py
+++ b/Mac/Tools/IDE/Wcontrols.py
@@ -4,430 +4,429 @@
 
 
 class ControlWidget(Wbase.ClickableWidget):
-	
-	"""Baseclass for all native controls."""
-	
-	def __init__(self, possize, title = "Control", procID = 0, callback = None, value = 0, min = 0, max = 1, viewsize = 0):
-		Wbase.ClickableWidget.__init__(self, possize)
-		self._control = None
-		self._title = title
-		self._callback = callback
-		self._procID = procID
-		self._value = value
-		self._min = min
-		self._max = max
-		self._enabled = 1
-		self._viewsize = viewsize
-	
-	def open(self):
-		self._calcbounds()
-		
-		# NewControl doesn't accept 32-bit value, min, or max, so for consistency
-		# with the new 32-bit set/get methods, out-of-range values are initially
-		# set as zero, followed by a 32-bit set of the actual value.
-		# Values not representable in 16 bits will fail on MacOS 8.1, however
-		# the vast majority of control usage should still be compatible.
-		_value, _min, _max = self._value, self._min, self._max
-		if -32768 <= _value <= 32767:
-			bigvalue = None
-		else:
-			bigvalue = _value
-			_value = 0
-		if -32768 <= _min <= 32767:
-			bigmin = None
-		else:
-			bigmin = _min
-			_min = 0
-		if -32768 <= _max <= 32767:
-			bigmax = None
-		else:
-			bigmax = _max
-			_max = 0
-		self._control = Ctl.NewControl(self._parentwindow.wid, 
-						self._bounds, 
-						self._title, 
-						1, 
-						_value, 
-						_min, 
-						_max, 
-						self._procID, 
-						0)
-		if bigvalue:
-			self._control.SetControl32BitValue(bigvalue)
-		if bigmin:
-			self._control.SetControl32BitMinimum(bigmin)
-		if bigmax:
-			self._control.SetControl32BitMaximum(bigmax)
-		if self._viewsize:
-			try:
-				self._control.SetControlViewSize(self._viewsize)
-				# Not available in MacOS 8.1, but that's OK since it only affects
-				# proportional scrollbars which weren't available in 8.1 either.
-			except NotImplementedError:
-				pass
-		self.enable(self._enabled)
-	
-	def adjust(self, oldbounds):
-		self.SetPort()
-		self._control.HideControl()
-		self._control.MoveControl(self._bounds[0], self._bounds[1])
-		self._control.SizeControl(self._bounds[2] - self._bounds[0], self._bounds[3] - self._bounds[1])
-		if self._visible:
-			Qd.EraseRect(self._bounds)
-			self._control.ShowControl()
-			self.GetWindow().ValidWindowRect(self._bounds)
-	
-	def close(self):
-		self._control.HideControl()
-		self._control = None
-		Wbase.ClickableWidget.close(self)
-	
-	def enable(self, onoff):
-		if self._control and self._enabled <> onoff:
-			self._control.HiliteControl((not onoff) and 255)
-			self._enabled = onoff
-	
-	def show(self, onoff):
-		self._visible = onoff
-		for w in self._widgets:
-			w.show(onoff)
-		if onoff:
-			self._control.ShowControl()
-		else:
-			self._control.HideControl()
-	
-	def activate(self, onoff):
-		self._activated = onoff
-		if self._enabled:
-			if onoff:
-				self._control.ActivateControl()
-			else:
-				self._control.DeactivateControl()
-	
-	def draw(self, visRgn = None):
-		if self._visible:
-			self._control.Draw1Control()
-	
-	def test(self, point):
-		if Qd.PtInRect(point, self._bounds) and self._enabled:
-			return 1
-		#ctltype, control = Ctl.FindControl(point, self._parentwindow.wid)
-		#if self._enabled and control == self._control:
-		#	return 1
-	
-	def click(self, point, modifiers):
-		if not self._enabled:
-			return
-		part = self._control.TrackControl(point)
-		if part:
-			if self._callback:
-				Wbase.CallbackCall(self._callback, 0)
-	
-	def settitle(self, title):
-		if self._control:
-			self._control.SetControlTitle(title)
-		self._title = title
-	
-	def gettitle(self):
-		return self._title
-	
-	def set(self, value):
-		if self._control:
-			if -32768 <= value <= 32767:
-				# No 32-bit control support in MacOS 8.1, so use
-				# the 16-bit interface when possible.
-				self._control.SetControlValue(value)
-			else:
-				self._control.SetControl32BitValue(value)
-		else:
-			self._value = value
-	
-	def get(self):
-		if self._control:
-			try:
-				return self._control.GetControl32BitValue()
-				# No 32-bit control support in MacOS 8.1, so fall
-				# back to the 16-bit interface when needed.
-			except NotImplementedError:
-				return self._control.GetControlValue()
-		else:
-			return self._value
+
+    """Baseclass for all native controls."""
+
+    def __init__(self, possize, title = "Control", procID = 0, callback = None, value = 0, min = 0, max = 1, viewsize = 0):
+        Wbase.ClickableWidget.__init__(self, possize)
+        self._control = None
+        self._title = title
+        self._callback = callback
+        self._procID = procID
+        self._value = value
+        self._min = min
+        self._max = max
+        self._enabled = 1
+        self._viewsize = viewsize
+
+    def open(self):
+        self._calcbounds()
+
+        # NewControl doesn't accept 32-bit value, min, or max, so for consistency
+        # with the new 32-bit set/get methods, out-of-range values are initially
+        # set as zero, followed by a 32-bit set of the actual value.
+        # Values not representable in 16 bits will fail on MacOS 8.1, however
+        # the vast majority of control usage should still be compatible.
+        _value, _min, _max = self._value, self._min, self._max
+        if -32768 <= _value <= 32767:
+            bigvalue = None
+        else:
+            bigvalue = _value
+            _value = 0
+        if -32768 <= _min <= 32767:
+            bigmin = None
+        else:
+            bigmin = _min
+            _min = 0
+        if -32768 <= _max <= 32767:
+            bigmax = None
+        else:
+            bigmax = _max
+            _max = 0
+        self._control = Ctl.NewControl(self._parentwindow.wid,
+                                        self._bounds,
+                                        self._title,
+                                        1,
+                                        _value,
+                                        _min,
+                                        _max,
+                                        self._procID,
+                                        0)
+        if bigvalue:
+            self._control.SetControl32BitValue(bigvalue)
+        if bigmin:
+            self._control.SetControl32BitMinimum(bigmin)
+        if bigmax:
+            self._control.SetControl32BitMaximum(bigmax)
+        if self._viewsize:
+            try:
+                self._control.SetControlViewSize(self._viewsize)
+                # Not available in MacOS 8.1, but that's OK since it only affects
+                # proportional scrollbars which weren't available in 8.1 either.
+            except NotImplementedError:
+                pass
+        self.enable(self._enabled)
+
+    def adjust(self, oldbounds):
+        self.SetPort()
+        self._control.HideControl()
+        self._control.MoveControl(self._bounds[0], self._bounds[1])
+        self._control.SizeControl(self._bounds[2] - self._bounds[0], self._bounds[3] - self._bounds[1])
+        if self._visible:
+            Qd.EraseRect(self._bounds)
+            self._control.ShowControl()
+            self.GetWindow().ValidWindowRect(self._bounds)
+
+    def close(self):
+        self._control.HideControl()
+        self._control = None
+        Wbase.ClickableWidget.close(self)
+
+    def enable(self, onoff):
+        if self._control and self._enabled <> onoff:
+            self._control.HiliteControl((not onoff) and 255)
+            self._enabled = onoff
+
+    def show(self, onoff):
+        self._visible = onoff
+        for w in self._widgets:
+            w.show(onoff)
+        if onoff:
+            self._control.ShowControl()
+        else:
+            self._control.HideControl()
+
+    def activate(self, onoff):
+        self._activated = onoff
+        if self._enabled:
+            if onoff:
+                self._control.ActivateControl()
+            else:
+                self._control.DeactivateControl()
+
+    def draw(self, visRgn = None):
+        if self._visible:
+            self._control.Draw1Control()
+
+    def test(self, point):
+        if Qd.PtInRect(point, self._bounds) and self._enabled:
+            return 1
+        #ctltype, control = Ctl.FindControl(point, self._parentwindow.wid)
+        #if self._enabled and control == self._control:
+        #       return 1
+
+    def click(self, point, modifiers):
+        if not self._enabled:
+            return
+        part = self._control.TrackControl(point)
+        if part:
+            if self._callback:
+                Wbase.CallbackCall(self._callback, 0)
+
+    def settitle(self, title):
+        if self._control:
+            self._control.SetControlTitle(title)
+        self._title = title
+
+    def gettitle(self):
+        return self._title
+
+    def set(self, value):
+        if self._control:
+            if -32768 <= value <= 32767:
+                # No 32-bit control support in MacOS 8.1, so use
+                # the 16-bit interface when possible.
+                self._control.SetControlValue(value)
+            else:
+                self._control.SetControl32BitValue(value)
+        else:
+            self._value = value
+
+    def get(self):
+        if self._control:
+            try:
+                return self._control.GetControl32BitValue()
+                # No 32-bit control support in MacOS 8.1, so fall
+                # back to the 16-bit interface when needed.
+            except NotImplementedError:
+                return self._control.GetControlValue()
+        else:
+            return self._value
 
 
 class Button(ControlWidget):
-	
-	"""Standard push button."""
-	
-	procID = Controls.pushButProc | Controls.useWFont
-	
-	def __init__(self, possize, title = "Button", callback = None):
-		ControlWidget.__init__(self, possize, title, self.procID, callback, 0, 0, 1)
-		self._isdefault = 0
-	
-	def push(self):
-		if not self._enabled:
-			return
-		# emulate the pushing of the button
-		import time
-		self._control.HiliteControl(Controls.kControlButtonPart)
-		self._parentwindow.wid.GetWindowPort().QDFlushPortBuffer(None)  # needed under OSX
-		time.sleep(0.1)
-		self._control.HiliteControl(0)
-		if self._callback:
-			Wbase.CallbackCall(self._callback, 0)
-	
-	def enable(self, onoff):
-		if self._control and self._enabled <> onoff:
-			self._control.HiliteControl((not onoff) and 255)
-			self._enabled = onoff
-	
-	def show(self, onoff):
-		ControlWidget.show(self, onoff)
-	
-	def draw(self, visRgn = None):
-		if self._visible:
-			self._control.Draw1Control()
-	
-	def open(self):
-		ControlWidget.open(self)
-		if self._isdefault:
-			self._setdefault(self._isdefault)
-	
-	def _setdefault(self, onoff):
-		c = self._control
-		if c is not None:
-			if onoff:
-				data = "\xFF"
-			else:
-				data = "\0"
-			# hide before changing state, otherwise the button isn't always
-			# redrawn correctly, although it's quite different under Aqua
-			# and Classic...
-			c.HideControl()
-			c.SetControlData(Controls.kControlNoPart,
-					Controls.kControlPushButtonDefaultTag, data)
-			c.ShowControl()
-		self._isdefault = onoff
-	
-	def adjust(self, oldbounds):
-		if self._isdefault:
-			old = Qd.InsetRect(oldbounds, -4, -4)
-			new = Qd.InsetRect(self._bounds, -4, -4)
-			Qd.EraseRect(old)
-			self.GetWindow().InvalWindowRect(old)
-			self.GetWindow().InvalWindowRect(new)
-		ControlWidget.adjust(self, oldbounds)
+
+    """Standard push button."""
+
+    procID = Controls.pushButProc | Controls.useWFont
+
+    def __init__(self, possize, title = "Button", callback = None):
+        ControlWidget.__init__(self, possize, title, self.procID, callback, 0, 0, 1)
+        self._isdefault = 0
+
+    def push(self):
+        if not self._enabled:
+            return
+        # emulate the pushing of the button
+        import time
+        self._control.HiliteControl(Controls.kControlButtonPart)
+        self._parentwindow.wid.GetWindowPort().QDFlushPortBuffer(None)  # needed under OSX
+        time.sleep(0.1)
+        self._control.HiliteControl(0)
+        if self._callback:
+            Wbase.CallbackCall(self._callback, 0)
+
+    def enable(self, onoff):
+        if self._control and self._enabled <> onoff:
+            self._control.HiliteControl((not onoff) and 255)
+            self._enabled = onoff
+
+    def show(self, onoff):
+        ControlWidget.show(self, onoff)
+
+    def draw(self, visRgn = None):
+        if self._visible:
+            self._control.Draw1Control()
+
+    def open(self):
+        ControlWidget.open(self)
+        if self._isdefault:
+            self._setdefault(self._isdefault)
+
+    def _setdefault(self, onoff):
+        c = self._control
+        if c is not None:
+            if onoff:
+                data = "\xFF"
+            else:
+                data = "\0"
+            # hide before changing state, otherwise the button isn't always
+            # redrawn correctly, although it's quite different under Aqua
+            # and Classic...
+            c.HideControl()
+            c.SetControlData(Controls.kControlNoPart,
+                            Controls.kControlPushButtonDefaultTag, data)
+            c.ShowControl()
+        self._isdefault = onoff
+
+    def adjust(self, oldbounds):
+        if self._isdefault:
+            old = Qd.InsetRect(oldbounds, -4, -4)
+            new = Qd.InsetRect(self._bounds, -4, -4)
+            Qd.EraseRect(old)
+            self.GetWindow().InvalWindowRect(old)
+            self.GetWindow().InvalWindowRect(new)
+        ControlWidget.adjust(self, oldbounds)
 
 
 class BevelButton(Button):
-	procID = Controls.kControlBevelButtonNormalBevelProc | Controls.useWFont
+    procID = Controls.kControlBevelButtonNormalBevelProc | Controls.useWFont
 
 
 class CheckBox(ControlWidget):
-	
-	"""Standard checkbox."""
-	
-	def __init__(self, possize, title = "Checkbox", callback = None, value = 0):
-		procID = Controls.checkBoxProc | Controls.useWFont
-		ControlWidget.__init__(self, possize, title, procID, callback, value, 0, 1)
-	
-	def click(self, point, modifiers):
-		if not self._enabled:
-			return
-		part = self._control.TrackControl(point)
-		if part:
-			self.toggle()
-			if self._callback:
-				Wbase.CallbackCall(self._callback, 0, self.get())
-	
-	def push(self):
-		if not self._enabled:
-			return
-		self.toggle()
-		if self._callback:
-			Wbase.CallbackCall(self._callback, 0, self.get())
-	
-	def toggle(self):
-		self.set(not self.get())
+
+    """Standard checkbox."""
+
+    def __init__(self, possize, title = "Checkbox", callback = None, value = 0):
+        procID = Controls.checkBoxProc | Controls.useWFont
+        ControlWidget.__init__(self, possize, title, procID, callback, value, 0, 1)
+
+    def click(self, point, modifiers):
+        if not self._enabled:
+            return
+        part = self._control.TrackControl(point)
+        if part:
+            self.toggle()
+            if self._callback:
+                Wbase.CallbackCall(self._callback, 0, self.get())
+
+    def push(self):
+        if not self._enabled:
+            return
+        self.toggle()
+        if self._callback:
+            Wbase.CallbackCall(self._callback, 0, self.get())
+
+    def toggle(self):
+        self.set(not self.get())
 
 
 class RadioButton(ControlWidget):
-	
-	"""Standard radiobutton."""
-	
-	# XXX We need a radiogroup widget; this is too kludgy.
-	
-	def __init__(self, possize, title, thebuttons, callback = None, value = 0):
-		procID = Controls.radioButProc | Controls.useWFont
-		ControlWidget.__init__(self, possize, title, procID, callback, value, 0, 1)
-		self.thebuttons = thebuttons
-		thebuttons.append(self)
-	
-	def close(self):
-		self.thebuttons = None
-		ControlWidget.close(self)
-	
-	def click(self, point, modifiers):
-		if not self._enabled:
-			return
-		part = self._control.TrackControl(point)
-		if part:
-			self.set(1)
-			if self._callback:
-				Wbase.CallbackCall(self._callback, 0, 1)
-	
-	def push(self):
-		if not self._enabled:
-			return
-		self.set(1)
-		if self._callback:
-			Wbase.CallbackCall(self._callback, 0, 1)
-	
-	def set(self, value):
-		for button in self.thebuttons:
-			if button._control:
-				button._control.SetControlValue(button == self)
-			else:
-				button._value = (button == self)
+
+    """Standard radiobutton."""
+
+    # XXX We need a radiogroup widget; this is too kludgy.
+
+    def __init__(self, possize, title, thebuttons, callback = None, value = 0):
+        procID = Controls.radioButProc | Controls.useWFont
+        ControlWidget.__init__(self, possize, title, procID, callback, value, 0, 1)
+        self.thebuttons = thebuttons
+        thebuttons.append(self)
+
+    def close(self):
+        self.thebuttons = None
+        ControlWidget.close(self)
+
+    def click(self, point, modifiers):
+        if not self._enabled:
+            return
+        part = self._control.TrackControl(point)
+        if part:
+            self.set(1)
+            if self._callback:
+                Wbase.CallbackCall(self._callback, 0, 1)
+
+    def push(self):
+        if not self._enabled:
+            return
+        self.set(1)
+        if self._callback:
+            Wbase.CallbackCall(self._callback, 0, 1)
+
+    def set(self, value):
+        for button in self.thebuttons:
+            if button._control:
+                button._control.SetControlValue(button == self)
+            else:
+                button._value = (button == self)
 
 
 class Scrollbar(ControlWidget):
-	
-	"""Standard scrollbar."""
-	
-	def __init__(self, possize, callback=None, value=0, min=0, max=0, livefeedback=1):
-		if livefeedback:
-			procID = Controls.kControlScrollBarLiveProc
-		else:
-			procID = Controls.scrollBarProc
-		ControlWidget.__init__(self, possize, "", procID, callback, value, min, max)
-	
-	# interface
-#	def set(self, value):
-#		if self._callback:
-#			Wbase.CallbackCall(self._callback, 1, value)
-	
-	def up(self):
-		if self._callback:
-			Wbase.CallbackCall(self._callback, 1, '+')
-	
-	def down(self):
-		if self._callback:
-			Wbase.CallbackCall(self._callback, 1, '-')
-	
-	def pageup(self):
-		if self._callback:
-			Wbase.CallbackCall(self._callback, 1, '++')
-	
-	def pagedown(self):
-		if self._callback:
-			Wbase.CallbackCall(self._callback, 1, '--')
-	
-	def setmin(self, min):
-		if self._control is not None:
-			if -32768 <= min <= 32767:
-				# No 32-bit control support in MacOS 8.1, so use
-				# the 16-bit interface when possible.
-				self._control.SetControlMinimum(min)
-			else:
-				self._control.SetControl32BitMinimum(min)
-		else:
-			self._min = min
-	
-	def setmax(self, max):
-		if self._control is not None:
-			if -32768 <= max <= 32767:
-				# No 32-bit control support in MacOS 8.1, so use
-				# the 16-bit interface when possible.
-				self._control.SetControlMaximum(max)
-			else:
-				self._control.SetControl32BitMaximum(max)
-		else:
-			self._max = max
-	
-	def setviewsize(self, viewsize):
-		if self._control is not None:
-			try:
-				self._control.SetControlViewSize(viewsize)
-				# Not available in MacOS 8.1, but that's OK since it only affects
-				# proportional scrollbars which weren't available in 8.1 either.
-			except NotImplementedError:
-				pass
-		else:
-			self._viewsize = viewsize
-	
-	def getmin(self):
-		try:
-			return self._control.GetControl32BitMinimum()
-			# No 32-bit control support in MacOS 8.1, so fall
-			# back to the 16-bit interface when needed.
-		except NotImplementedError:
-			return self._control.GetControlMinimum()
-	
-	def getmax(self):
-		try:
-			return self._control.GetControl32BitMaximum()
-			# No 32-bit control support in MacOS 8.1, so fall
-			# back to the 16-bit interface when needed.
-		except NotImplementedError:
-			return self._control.GetControlMaximum()
-	
-	# internals
-	def click(self, point, modifiers):
-		if not self._enabled:
-			return
-		def hitter(ctl, part, self=self):
-			if part:
-				self._hit(part)
-		part = self._control.TrackControl(point, hitter)
-	
-	def _hit(self, part):
-		value = None
-		if part == Controls.inThumb:
-			try:
-				value = self._control.GetControl32BitValue()
-				# No 32-bit control support in MacOS 8.1, so fall
-				# back to the 16-bit interface when needed.
-			except NotImplementedError:
-				value = self._control.GetControlValue()
-		elif part == Controls.inUpButton:
-			value = "+"
-		elif part == Controls.inDownButton:
-			value = "-"
-		elif part == Controls.inPageUp:
-			value = "++"
-		elif part == Controls.inPageDown:
-			value = "--"
-		if value is not None and self._callback:
-			Wbase.CallbackCall(self._callback, 1, value)
-	
-	def draw(self, visRgn = None):
-		if self._visible:
-			self._control.Draw1Control()
-			#Qd.FrameRect(self._bounds)
-	
-	def adjust(self, oldbounds):
-		self.SetPort()
-		self.GetWindow().InvalWindowRect(oldbounds)
-		self._control.HideControl()
-		self._control.MoveControl(self._bounds[0], self._bounds[1])
-		self._control.SizeControl(self._bounds[2] - self._bounds[0], self._bounds[3] - self._bounds[1])
-		if self._visible:
-			Qd.EraseRect(self._bounds)
-			if self._activated:
-				self._control.ShowControl()
-			else:
-				Qd.FrameRect(self._bounds)
-			self.GetWindow().ValidWindowRect(self._bounds)
+
+    """Standard scrollbar."""
+
+    def __init__(self, possize, callback=None, value=0, min=0, max=0, livefeedback=1):
+        if livefeedback:
+            procID = Controls.kControlScrollBarLiveProc
+        else:
+            procID = Controls.scrollBarProc
+        ControlWidget.__init__(self, possize, "", procID, callback, value, min, max)
+
+    # interface
+#       def set(self, value):
+#               if self._callback:
+#                       Wbase.CallbackCall(self._callback, 1, value)
+
+    def up(self):
+        if self._callback:
+            Wbase.CallbackCall(self._callback, 1, '+')
+
+    def down(self):
+        if self._callback:
+            Wbase.CallbackCall(self._callback, 1, '-')
+
+    def pageup(self):
+        if self._callback:
+            Wbase.CallbackCall(self._callback, 1, '++')
+
+    def pagedown(self):
+        if self._callback:
+            Wbase.CallbackCall(self._callback, 1, '--')
+
+    def setmin(self, min):
+        if self._control is not None:
+            if -32768 <= min <= 32767:
+                # No 32-bit control support in MacOS 8.1, so use
+                # the 16-bit interface when possible.
+                self._control.SetControlMinimum(min)
+            else:
+                self._control.SetControl32BitMinimum(min)
+        else:
+            self._min = min
+
+    def setmax(self, max):
+        if self._control is not None:
+            if -32768 <= max <= 32767:
+                # No 32-bit control support in MacOS 8.1, so use
+                # the 16-bit interface when possible.
+                self._control.SetControlMaximum(max)
+            else:
+                self._control.SetControl32BitMaximum(max)
+        else:
+            self._max = max
+
+    def setviewsize(self, viewsize):
+        if self._control is not None:
+            try:
+                self._control.SetControlViewSize(viewsize)
+                # Not available in MacOS 8.1, but that's OK since it only affects
+                # proportional scrollbars which weren't available in 8.1 either.
+            except NotImplementedError:
+                pass
+        else:
+            self._viewsize = viewsize
+
+    def getmin(self):
+        try:
+            return self._control.GetControl32BitMinimum()
+            # No 32-bit control support in MacOS 8.1, so fall
+            # back to the 16-bit interface when needed.
+        except NotImplementedError:
+            return self._control.GetControlMinimum()
+
+    def getmax(self):
+        try:
+            return self._control.GetControl32BitMaximum()
+            # No 32-bit control support in MacOS 8.1, so fall
+            # back to the 16-bit interface when needed.
+        except NotImplementedError:
+            return self._control.GetControlMaximum()
+
+    # internals
+    def click(self, point, modifiers):
+        if not self._enabled:
+            return
+        def hitter(ctl, part, self=self):
+            if part:
+                self._hit(part)
+        part = self._control.TrackControl(point, hitter)
+
+    def _hit(self, part):
+        value = None
+        if part == Controls.inThumb:
+            try:
+                value = self._control.GetControl32BitValue()
+                # No 32-bit control support in MacOS 8.1, so fall
+                # back to the 16-bit interface when needed.
+            except NotImplementedError:
+                value = self._control.GetControlValue()
+        elif part == Controls.inUpButton:
+            value = "+"
+        elif part == Controls.inDownButton:
+            value = "-"
+        elif part == Controls.inPageUp:
+            value = "++"
+        elif part == Controls.inPageDown:
+            value = "--"
+        if value is not None and self._callback:
+            Wbase.CallbackCall(self._callback, 1, value)
+
+    def draw(self, visRgn = None):
+        if self._visible:
+            self._control.Draw1Control()
+            #Qd.FrameRect(self._bounds)
+
+    def adjust(self, oldbounds):
+        self.SetPort()
+        self.GetWindow().InvalWindowRect(oldbounds)
+        self._control.HideControl()
+        self._control.MoveControl(self._bounds[0], self._bounds[1])
+        self._control.SizeControl(self._bounds[2] - self._bounds[0], self._bounds[3] - self._bounds[1])
+        if self._visible:
+            Qd.EraseRect(self._bounds)
+            if self._activated:
+                self._control.ShowControl()
+            else:
+                Qd.FrameRect(self._bounds)
+            self.GetWindow().ValidWindowRect(self._bounds)
 
 
 def _scalebarvalue(absmin, absmax, curmin, curmax):
-	if curmin <= absmin and curmax >= absmax:
-		return None
-	if curmin <= absmin:
-		return 0
-	if curmax >= absmax:
-		return 32767
-	perc = float(curmin-absmin) / float((absmax - absmin) - (curmax - curmin))
-	return int(perc*32767)
-
+    if curmin <= absmin and curmax >= absmax:
+        return None
+    if curmin <= absmin:
+        return 0
+    if curmax >= absmax:
+        return 32767
+    perc = float(curmin-absmin) / float((absmax - absmin) - (curmax - curmin))
+    return int(perc*32767)
diff --git a/Mac/Tools/IDE/Wkeys.py b/Mac/Tools/IDE/Wkeys.py
index 876f02f..9bc4522 100644
--- a/Mac/Tools/IDE/Wkeys.py
+++ b/Mac/Tools/IDE/Wkeys.py
@@ -1,45 +1,45 @@
-spacekey		= ' '
-returnkey 		= '\r'
-tabkey 		= '\t'
-enterkey 		= '\003'
-backspacekey 	= '\010'
-deletekey 		= '\177'
-clearkey		= '\033'
-helpkey 		= '\005'
+spacekey                = ' '
+returnkey               = '\r'
+tabkey          = '\t'
+enterkey                = '\003'
+backspacekey    = '\010'
+deletekey               = '\177'
+clearkey                = '\033'
+helpkey                 = '\005'
 
-leftarrowkey 	= '\034'
-rightarrowkey 	= '\035'
-uparrowkey 		= '\036'
-downarrowkey 	= '\037'
-arrowkeys 		= [leftarrowkey, rightarrowkey, uparrowkey, downarrowkey]
+leftarrowkey    = '\034'
+rightarrowkey   = '\035'
+uparrowkey              = '\036'
+downarrowkey    = '\037'
+arrowkeys               = [leftarrowkey, rightarrowkey, uparrowkey, downarrowkey]
 
-topkey 		= '\001'
-bottomkey 		= '\004'
-pageupkey 		= '\013'
-pagedownkey 	= '\014'
-scrollkeys 		= [topkey, bottomkey, pageupkey, pagedownkey]
+topkey          = '\001'
+bottomkey               = '\004'
+pageupkey               = '\013'
+pagedownkey     = '\014'
+scrollkeys              = [topkey, bottomkey, pageupkey, pagedownkey]
 
 navigationkeys = arrowkeys + scrollkeys
 
 keycodes = {
-	"space"		: ' ',
-	"return"		: '\r',
-	"tab" 			: '\t',
-	"enter" 		: '\003',
-	"backspace"	: '\010',
-	"delete"		: '\177',
-	"help" 		: '\005',
-	"leftarrow"		: '\034',
-	"rightarrow" 	: '\035',
-	"uparrow" 		: '\036',
-	"downarrow"	: '\037',
-	"top" 			: '\001',
-	"bottom" 		: '\004',
-	"pageup" 		: '\013',
-	"pagedown" 	: '\014'
+        "space"         : ' ',
+        "return"                : '\r',
+        "tab"                   : '\t',
+        "enter"                 : '\003',
+        "backspace"     : '\010',
+        "delete"                : '\177',
+        "help"          : '\005',
+        "leftarrow"             : '\034',
+        "rightarrow"    : '\035',
+        "uparrow"               : '\036',
+        "downarrow"     : '\037',
+        "top"                   : '\001',
+        "bottom"                : '\004',
+        "pageup"                : '\013',
+        "pagedown"      : '\014'
 }
 
 keynames = {}
 for k, v in keycodes.items():
-	keynames[v] = k
+    keynames[v] = k
 del k, v
diff --git a/Mac/Tools/IDE/Wlists.py b/Mac/Tools/IDE/Wlists.py
index 1b66a8b..9aeb7c4 100644
--- a/Mac/Tools/IDE/Wlists.py
+++ b/Mac/Tools/IDE/Wlists.py
@@ -10,573 +10,572 @@
 
 
 class List(Wbase.SelectableWidget):
-	
-	"""Standard list widget."""
-	
-	LDEF_ID = 0
-	
-	def __init__(self, possize, items = None, callback = None, flags = 0, cols = 1, typingcasesens=0):
-		if items is None:
-			items = []
-		self.items = items
-		Wbase.SelectableWidget.__init__(self, possize)
-		self._selected = 0
-		self._enabled = 1
-		self._list = None
-		self._cols = cols
-		self._callback = callback
-		self._flags = flags
-		self.typingcasesens = typingcasesens
-		self.lasttyping = ""
-		self.lasttime = Evt.TickCount()
-		self.timelimit = 30
-		self.setitems(items)
-		self.drawingmode = 0
-	
-	def open(self):
-		self.setdrawingmode(0)
-		self.createlist()
-		self.setdrawingmode(1)
-	
-	def createlist(self):
-		self._calcbounds()
-		self.SetPort()
-		rect = self._bounds
-		rect = rect[0]+1, rect[1]+1, rect[2]-16, rect[3]-1
-		self._viewbounds = rect
-		self._list = LNew(rect, (0, 0, self._cols, 0), (0, 0), self.LDEF_ID, self._parentwindow.wid,
-					0, 1, 0, 1)
-		if self.drawingmode:
-			self._list.LSetDrawingMode(0)
-		self._list.selFlags = self._flags
-		self.setitems(self.items)
-		if hasattr(self, "_sel"):
-			self.setselection(self._sel)
-			del self._sel
-	
-	def adjust(self, oldbounds):
-		self.SetPort()
-		# Appearance frames are drawn outside the specified bounds,
-		# so we always need to outset the invalidated area.
-		self.GetWindow().InvalWindowRect(Qd.InsetRect(oldbounds, -3, -3))
-		self.GetWindow().InvalWindowRect(Qd.InsetRect(self._bounds, -3, -3))
 
-		if oldbounds[:2] == self._bounds[:2]:
-			# set visRgn to empty, to prevent nasty drawing side effect of LSize()
-			Qd.RectRgn(self._parentwindow.wid.GetWindowPort().visRgn, (0, 0, 0, 0))
-			# list still has the same upper/left coordinates, use LSize
-			l, t, r, b = self._bounds
-			width = r - l - 17
-			height = b - t - 2
-			vl, vt, vr, vb = self._viewbounds
-			self._viewbounds = vl, vt, vl + width, vt + height
-			self._list.LSize(width, height)
-			# now *why* doesn't the list manager recalc the cellrect???
-			l, t, r, b = self._list.LRect((0,0))
-			cellheight = b - t
-			self._list.LCellSize((width/self._cols, cellheight))
-			# reset visRgn
-			self._parentwindow.wid.CalcVis()
-		else:
-			# oh well, since the list manager doesn't have a LMove call,
-			# we have to make the list all over again...
-			sel = self.getselection()
-			topcell = self.gettopcell()
-			self._list = None
-			self.setdrawingmode(0)
-			self.createlist()
-			self.setselection(sel)
-			self.settopcell(topcell)
-			self.setdrawingmode(1)
-	
-	def close(self):
-		self._list = None
-		self._callback = None
-		self.items = []
-		Wbase.SelectableWidget.close(self)
-	
-	def set(self, items):
-		self.setitems(items)
-	
-	def setitems(self, items):
-		self.items = items
-		the_list = self._list
-		if not self._parent or not self._list:
-			return
-		self.setdrawingmode(0)
-		topcell = self.gettopcell()
-		the_list.LDelRow(0, 1)
-		the_list.LAddRow(len(self.items), 0)
-		self_itemrepr = self.itemrepr
-		set_cell = the_list.LSetCell
-		for i in range(len(items)):
-			set_cell(self_itemrepr(items[i]), (0, i))
-		self.settopcell(topcell)
-		self.setdrawingmode(1)
-	
-	def click(self, point, modifiers):
-		if not self._enabled:
-			return
-		isdoubleclick = self._list.LClick(point, modifiers)
-		if self._callback:
-			Wbase.CallbackCall(self._callback, 0, isdoubleclick)
-		return 1
-	
-	def key(self, char, event):
-		(what, message, when, where, modifiers) = event
-		sel = self.getselection()
-		newselection = []
-		if char == Wkeys.uparrowkey:
-			if len(sel) >= 1 and min(sel) > 0:
-				newselection = [min(sel) - 1]
-			else:
-				newselection = [0]
-		elif char == Wkeys.downarrowkey:
-			if len(sel) >= 1 and max(sel) < (len(self.items) - 1):
-					newselection = [max(sel) + 1]
-			else:
-				newselection = [len(self.items) - 1]
-		else:
-			modifiers = 0
-			if (self.lasttime + self.timelimit) < Evt.TickCount():
-				self.lasttyping = ""
-			if self.typingcasesens:
-				self.lasttyping = self.lasttyping + char
-			else:
-				self.lasttyping = self.lasttyping + string.lower(char)
-			self.lasttime = Evt.TickCount()
-			i = self.findmatch(self.lasttyping)
-			newselection = [i]
-		if modifiers & Events.shiftKey and not self._list.selFlags & Lists.lOnlyOne:
-			newselection = newselection + sel
-		self.setselection(newselection)
-		self._list.LAutoScroll()
-		self.click((-1, -1), 0)
-	
-	def findmatch(self, tag):
-		lower = string.lower
-		items = self.items
-		typingcasesens = self.typingcasesens
-		taglen = len(tag)
-		match = '\377' * 100
-		match_i = -1
-		for i in range(len(items)):
-			item = str(items[i])
-			if not typingcasesens:
-				item = lower(item)
-			if tag <= item < match:
-				match = item
-				match_i = i
-		if match_i >= 0:
-			return match_i
-		else:
-			return len(items) - 1
-	
-	def domenu_copy(self, *args):
-		sel = self.getselection()
-		selitems = []
-		for i in sel:
-			selitems.append(str(self.items[i]))
-		text = string.join(selitems, '\r')
-		if text:
-			if hasattr(Scrap, 'PutScrap'):
-				Scrap.ZeroScrap()
-				Scrap.PutScrap('TEXT', text)
-			else:
-				Scrap.ClearCurrentScrap()
-				sc = Scrap.GetCurrentScrap()
-				sc.PutScrapFlavor('TEXT', 0, text)
-	
-	def can_copy(self, *args):
-		return len(self.getselection()) <> 0
-	
-	def domenu_selectall(self, *args):
-		self.selectall()
-	
-	def can_selectall(self, *args):
-		return not self._list.selFlags & Lists.lOnlyOne
-	
-	def selectall(self):
-		if not self._list.selFlags & Lists.lOnlyOne:
-			self.setselection(range(len(self.items)))
-			self._list.LAutoScroll()
-			self.click((-1, -1), 0)
-	
-	def getselection(self):
-		if not self._parent or not self._list:
-			if hasattr(self, "_sel"):
-				return self._sel
-			return []
-		items = []
-		point = (0,0)
-		while 1:
-			ok, point = self._list.LGetSelect(1, point)
-			if not ok:
-				break
-			items.append(point[1])
-			point = point[0], point[1]+1
-		return items
-	
-	def setselection(self, selection):
-		if not self._parent or not self._list:
-			self._sel = selection
-			return
-		set_sel = self._list.LSetSelect
-		for i in range(len(self.items)):
-			if i in selection:
-				set_sel(1, (0, i))
-			else:
-				set_sel(0, (0, i))
-		self._list.LAutoScroll()
-	
-	def getselectedobjects(self):
-		sel = self.getselection()
-		objects = []
-		for i in sel:
-			objects.append(self.items[i])
-		return objects
-	
-	def setselectedobjects(self, objects):
-		sel = []
-		for o in objects:
-			try:
-				sel.append(self.items.index(o))
-			except:
-				pass
-		self.setselection(sel)
-	
-	def gettopcell(self):
-		l, t, r, b = self._bounds
-		t = t + 1
-		cl, ct, cr, cb = self._list.LRect((0, 0))
-		cellheight = cb - ct
-		return (t - ct) / cellheight
-	
-	def settopcell(self, topcell):
-		top = self.gettopcell()
-		diff = topcell - top
-		self._list.LScroll(0, diff)
-	
-	def draw(self, visRgn = None):
-		if self._visible:
-			if not visRgn:
-				visRgn = self._parentwindow.wid.GetWindowPort().visRgn
-			self._list.LUpdate(visRgn)
-			state = [kThemeStateActive, kThemeStateInactive][not self._activated]
-			App.DrawThemeListBoxFrame(Qd.InsetRect(self._bounds, 1, 1), state)
-			if self._selected and self._activated:
-				self.drawselframe(1)
-	
-	def select(self, onoff, isclick = 0):
-		if Wbase.SelectableWidget.select(self, onoff):
-			return
-		self.SetPort()
-		self.drawselframe(onoff)
-	
-	def activate(self, onoff):
-		self._activated = onoff
-		if self._visible:
-			self._list.LActivate(onoff)
-			#state = [kThemeStateActive, kThemeStateInactive][not onoff]
-			#App.DrawThemeListBoxFrame(Qd.InsetRect(self._bounds, 1, 1), state)
-			if self._selected:
-				self.drawselframe(onoff)
-	
-	def get(self):
-		return self.items
-	
-	def itemrepr(self, item):
-		return str(item)[:255]
-	
-	def __getitem__(self, index):
-		return self.items[index]
-	
-	def __setitem__(self, index, item):
-		if self._parent and self._list:
-			self._list.LSetCell(self.itemrepr(item), (0, index))
-		self.items[index] = item
-	
-	def __delitem__(self, index):
-		if self._parent and self._list:
-			self._list.LDelRow(1, index)
-		del self.items[index]
-	
-	def __getslice__(self, a, b):
-		return self.items[a:b]
-	
-	def __delslice__(self, a, b):
-		if b-a:
-			if self._parent and self._list:
-				self._list.LDelRow(b-a, a)
-			del self.items[a:b]
-	
-	def __setslice__(self, a, b, items):
-		if self._parent and self._list:
-			l = len(items)
-			the_list = self._list
-			self.setdrawingmode(0)
-			if b-a:
-				if b > len(self.items):
-					# fix for new 1.5 "feature" where b is sys.maxint instead of len(self)...
-					# LDelRow doesn't like maxint.
-					b = len(self.items)
-				the_list.LDelRow(b-a, a)
-			the_list.LAddRow(l, a)
-			self_itemrepr = self.itemrepr
-			set_cell = the_list.LSetCell
-			for i in range(len(items)):
-				set_cell(self_itemrepr(items[i]), (0, i + a))
-			self.items[a:b] = items
-			self.setdrawingmode(1)
-		else:
-			self.items[a:b] = items
-	
-	def __len__(self):
-		return len(self.items)
-	
-	def append(self, item):
-		if self._parent and self._list:
-			index = len(self.items)
-			self._list.LAddRow(1, index)
-			self._list.LSetCell(self.itemrepr(item), (0, index))
-		self.items.append(item)
-	
-	def remove(self, item):
-		index = self.items.index(item)
-		self.__delitem__(index)
-	
-	def index(self, item):
-		return self.items.index(item)
-	
-	def insert(self, index, item):
-		if index < 0:
-			index = 0
-		if self._parent and self._list:
-			self._list.LAddRow(1, index)
-			self._list.LSetCell(self.itemrepr(item), (0, index))
-		self.items.insert(index, item)
-	
-	def setdrawingmode(self, onoff):
-		if onoff:
-			self.drawingmode = self.drawingmode - 1
-			if self.drawingmode == 0 and self._list is not None:
-				self._list.LSetDrawingMode(1)
-				if self._visible:
-					bounds = l, t, r, b = Qd.InsetRect(self._bounds, 1, 1)
-					cl, ct, cr, cb = self._list.LRect((0, len(self.items)-1))
-					if cb < b:
-						self.SetPort()
-						Qd.EraseRect((l, cb, cr, b))
-					self._list.LUpdate(self._parentwindow.wid.GetWindowPort().visRgn)
-					self.GetWindow().ValidWindowRect(bounds)
-		else:
-			if self.drawingmode == 0 and self._list is not None:
-				self._list.LSetDrawingMode(0)
-			self.drawingmode = self.drawingmode + 1
+    """Standard list widget."""
+
+    LDEF_ID = 0
+
+    def __init__(self, possize, items = None, callback = None, flags = 0, cols = 1, typingcasesens=0):
+        if items is None:
+            items = []
+        self.items = items
+        Wbase.SelectableWidget.__init__(self, possize)
+        self._selected = 0
+        self._enabled = 1
+        self._list = None
+        self._cols = cols
+        self._callback = callback
+        self._flags = flags
+        self.typingcasesens = typingcasesens
+        self.lasttyping = ""
+        self.lasttime = Evt.TickCount()
+        self.timelimit = 30
+        self.setitems(items)
+        self.drawingmode = 0
+
+    def open(self):
+        self.setdrawingmode(0)
+        self.createlist()
+        self.setdrawingmode(1)
+
+    def createlist(self):
+        self._calcbounds()
+        self.SetPort()
+        rect = self._bounds
+        rect = rect[0]+1, rect[1]+1, rect[2]-16, rect[3]-1
+        self._viewbounds = rect
+        self._list = LNew(rect, (0, 0, self._cols, 0), (0, 0), self.LDEF_ID, self._parentwindow.wid,
+                                0, 1, 0, 1)
+        if self.drawingmode:
+            self._list.LSetDrawingMode(0)
+        self._list.selFlags = self._flags
+        self.setitems(self.items)
+        if hasattr(self, "_sel"):
+            self.setselection(self._sel)
+            del self._sel
+
+    def adjust(self, oldbounds):
+        self.SetPort()
+        # Appearance frames are drawn outside the specified bounds,
+        # so we always need to outset the invalidated area.
+        self.GetWindow().InvalWindowRect(Qd.InsetRect(oldbounds, -3, -3))
+        self.GetWindow().InvalWindowRect(Qd.InsetRect(self._bounds, -3, -3))
+
+        if oldbounds[:2] == self._bounds[:2]:
+            # set visRgn to empty, to prevent nasty drawing side effect of LSize()
+            Qd.RectRgn(self._parentwindow.wid.GetWindowPort().visRgn, (0, 0, 0, 0))
+            # list still has the same upper/left coordinates, use LSize
+            l, t, r, b = self._bounds
+            width = r - l - 17
+            height = b - t - 2
+            vl, vt, vr, vb = self._viewbounds
+            self._viewbounds = vl, vt, vl + width, vt + height
+            self._list.LSize(width, height)
+            # now *why* doesn't the list manager recalc the cellrect???
+            l, t, r, b = self._list.LRect((0,0))
+            cellheight = b - t
+            self._list.LCellSize((width/self._cols, cellheight))
+            # reset visRgn
+            self._parentwindow.wid.CalcVis()
+        else:
+            # oh well, since the list manager doesn't have a LMove call,
+            # we have to make the list all over again...
+            sel = self.getselection()
+            topcell = self.gettopcell()
+            self._list = None
+            self.setdrawingmode(0)
+            self.createlist()
+            self.setselection(sel)
+            self.settopcell(topcell)
+            self.setdrawingmode(1)
+
+    def close(self):
+        self._list = None
+        self._callback = None
+        self.items = []
+        Wbase.SelectableWidget.close(self)
+
+    def set(self, items):
+        self.setitems(items)
+
+    def setitems(self, items):
+        self.items = items
+        the_list = self._list
+        if not self._parent or not self._list:
+            return
+        self.setdrawingmode(0)
+        topcell = self.gettopcell()
+        the_list.LDelRow(0, 1)
+        the_list.LAddRow(len(self.items), 0)
+        self_itemrepr = self.itemrepr
+        set_cell = the_list.LSetCell
+        for i in range(len(items)):
+            set_cell(self_itemrepr(items[i]), (0, i))
+        self.settopcell(topcell)
+        self.setdrawingmode(1)
+
+    def click(self, point, modifiers):
+        if not self._enabled:
+            return
+        isdoubleclick = self._list.LClick(point, modifiers)
+        if self._callback:
+            Wbase.CallbackCall(self._callback, 0, isdoubleclick)
+        return 1
+
+    def key(self, char, event):
+        (what, message, when, where, modifiers) = event
+        sel = self.getselection()
+        newselection = []
+        if char == Wkeys.uparrowkey:
+            if len(sel) >= 1 and min(sel) > 0:
+                newselection = [min(sel) - 1]
+            else:
+                newselection = [0]
+        elif char == Wkeys.downarrowkey:
+            if len(sel) >= 1 and max(sel) < (len(self.items) - 1):
+                newselection = [max(sel) + 1]
+            else:
+                newselection = [len(self.items) - 1]
+        else:
+            modifiers = 0
+            if (self.lasttime + self.timelimit) < Evt.TickCount():
+                self.lasttyping = ""
+            if self.typingcasesens:
+                self.lasttyping = self.lasttyping + char
+            else:
+                self.lasttyping = self.lasttyping + string.lower(char)
+            self.lasttime = Evt.TickCount()
+            i = self.findmatch(self.lasttyping)
+            newselection = [i]
+        if modifiers & Events.shiftKey and not self._list.selFlags & Lists.lOnlyOne:
+            newselection = newselection + sel
+        self.setselection(newselection)
+        self._list.LAutoScroll()
+        self.click((-1, -1), 0)
+
+    def findmatch(self, tag):
+        lower = string.lower
+        items = self.items
+        typingcasesens = self.typingcasesens
+        taglen = len(tag)
+        match = '\377' * 100
+        match_i = -1
+        for i in range(len(items)):
+            item = str(items[i])
+            if not typingcasesens:
+                item = lower(item)
+            if tag <= item < match:
+                match = item
+                match_i = i
+        if match_i >= 0:
+            return match_i
+        else:
+            return len(items) - 1
+
+    def domenu_copy(self, *args):
+        sel = self.getselection()
+        selitems = []
+        for i in sel:
+            selitems.append(str(self.items[i]))
+        text = string.join(selitems, '\r')
+        if text:
+            if hasattr(Scrap, 'PutScrap'):
+                Scrap.ZeroScrap()
+                Scrap.PutScrap('TEXT', text)
+            else:
+                Scrap.ClearCurrentScrap()
+                sc = Scrap.GetCurrentScrap()
+                sc.PutScrapFlavor('TEXT', 0, text)
+
+    def can_copy(self, *args):
+        return len(self.getselection()) <> 0
+
+    def domenu_selectall(self, *args):
+        self.selectall()
+
+    def can_selectall(self, *args):
+        return not self._list.selFlags & Lists.lOnlyOne
+
+    def selectall(self):
+        if not self._list.selFlags & Lists.lOnlyOne:
+            self.setselection(range(len(self.items)))
+            self._list.LAutoScroll()
+            self.click((-1, -1), 0)
+
+    def getselection(self):
+        if not self._parent or not self._list:
+            if hasattr(self, "_sel"):
+                return self._sel
+            return []
+        items = []
+        point = (0,0)
+        while 1:
+            ok, point = self._list.LGetSelect(1, point)
+            if not ok:
+                break
+            items.append(point[1])
+            point = point[0], point[1]+1
+        return items
+
+    def setselection(self, selection):
+        if not self._parent or not self._list:
+            self._sel = selection
+            return
+        set_sel = self._list.LSetSelect
+        for i in range(len(self.items)):
+            if i in selection:
+                set_sel(1, (0, i))
+            else:
+                set_sel(0, (0, i))
+        self._list.LAutoScroll()
+
+    def getselectedobjects(self):
+        sel = self.getselection()
+        objects = []
+        for i in sel:
+            objects.append(self.items[i])
+        return objects
+
+    def setselectedobjects(self, objects):
+        sel = []
+        for o in objects:
+            try:
+                sel.append(self.items.index(o))
+            except:
+                pass
+        self.setselection(sel)
+
+    def gettopcell(self):
+        l, t, r, b = self._bounds
+        t = t + 1
+        cl, ct, cr, cb = self._list.LRect((0, 0))
+        cellheight = cb - ct
+        return (t - ct) / cellheight
+
+    def settopcell(self, topcell):
+        top = self.gettopcell()
+        diff = topcell - top
+        self._list.LScroll(0, diff)
+
+    def draw(self, visRgn = None):
+        if self._visible:
+            if not visRgn:
+                visRgn = self._parentwindow.wid.GetWindowPort().visRgn
+            self._list.LUpdate(visRgn)
+            state = [kThemeStateActive, kThemeStateInactive][not self._activated]
+            App.DrawThemeListBoxFrame(Qd.InsetRect(self._bounds, 1, 1), state)
+            if self._selected and self._activated:
+                self.drawselframe(1)
+
+    def select(self, onoff, isclick = 0):
+        if Wbase.SelectableWidget.select(self, onoff):
+            return
+        self.SetPort()
+        self.drawselframe(onoff)
+
+    def activate(self, onoff):
+        self._activated = onoff
+        if self._visible:
+            self._list.LActivate(onoff)
+            #state = [kThemeStateActive, kThemeStateInactive][not onoff]
+            #App.DrawThemeListBoxFrame(Qd.InsetRect(self._bounds, 1, 1), state)
+            if self._selected:
+                self.drawselframe(onoff)
+
+    def get(self):
+        return self.items
+
+    def itemrepr(self, item):
+        return str(item)[:255]
+
+    def __getitem__(self, index):
+        return self.items[index]
+
+    def __setitem__(self, index, item):
+        if self._parent and self._list:
+            self._list.LSetCell(self.itemrepr(item), (0, index))
+        self.items[index] = item
+
+    def __delitem__(self, index):
+        if self._parent and self._list:
+            self._list.LDelRow(1, index)
+        del self.items[index]
+
+    def __getslice__(self, a, b):
+        return self.items[a:b]
+
+    def __delslice__(self, a, b):
+        if b-a:
+            if self._parent and self._list:
+                self._list.LDelRow(b-a, a)
+            del self.items[a:b]
+
+    def __setslice__(self, a, b, items):
+        if self._parent and self._list:
+            l = len(items)
+            the_list = self._list
+            self.setdrawingmode(0)
+            if b-a:
+                if b > len(self.items):
+                # fix for new 1.5 "feature" where b is sys.maxint instead of len(self)...
+                # LDelRow doesn't like maxint.
+                    b = len(self.items)
+                the_list.LDelRow(b-a, a)
+            the_list.LAddRow(l, a)
+            self_itemrepr = self.itemrepr
+            set_cell = the_list.LSetCell
+            for i in range(len(items)):
+                set_cell(self_itemrepr(items[i]), (0, i + a))
+            self.items[a:b] = items
+            self.setdrawingmode(1)
+        else:
+            self.items[a:b] = items
+
+    def __len__(self):
+        return len(self.items)
+
+    def append(self, item):
+        if self._parent and self._list:
+            index = len(self.items)
+            self._list.LAddRow(1, index)
+            self._list.LSetCell(self.itemrepr(item), (0, index))
+        self.items.append(item)
+
+    def remove(self, item):
+        index = self.items.index(item)
+        self.__delitem__(index)
+
+    def index(self, item):
+        return self.items.index(item)
+
+    def insert(self, index, item):
+        if index < 0:
+            index = 0
+        if self._parent and self._list:
+            self._list.LAddRow(1, index)
+            self._list.LSetCell(self.itemrepr(item), (0, index))
+        self.items.insert(index, item)
+
+    def setdrawingmode(self, onoff):
+        if onoff:
+            self.drawingmode = self.drawingmode - 1
+            if self.drawingmode == 0 and self._list is not None:
+                self._list.LSetDrawingMode(1)
+                if self._visible:
+                    bounds = l, t, r, b = Qd.InsetRect(self._bounds, 1, 1)
+                    cl, ct, cr, cb = self._list.LRect((0, len(self.items)-1))
+                    if cb < b:
+                        self.SetPort()
+                        Qd.EraseRect((l, cb, cr, b))
+                    self._list.LUpdate(self._parentwindow.wid.GetWindowPort().visRgn)
+                    self.GetWindow().ValidWindowRect(bounds)
+        else:
+            if self.drawingmode == 0 and self._list is not None:
+                self._list.LSetDrawingMode(0)
+            self.drawingmode = self.drawingmode + 1
 
 
 class CustomList(List):
-	
-	"""Base class for writing custom list definitions."""
-	
-	_cellHeight = 0
-	
-	def createlist(self):
-		self._calcbounds()
-		self.SetPort()
-		rect = self._bounds
-		rect = rect[0]+1, rect[1]+1, rect[2]-16, rect[3]-1
-		self._viewbounds = rect
-		self._list = CreateCustomList(
-				rect,
-				(0, 0, 1, 0),
-				(0, self._cellHeight),
-				(kListDefUserProcType, self.listDefinitionFunc),
-				self._parentwindow.wid,
-				0, 1, 0, 1)
-		if self.drawingmode:
-			self._list.LSetDrawingMode(0)
-		self._list.selFlags = self._flags
-		self.setitems(self.items)
-		if hasattr(self, "_sel"):
-			self.setselection(self._sel)
-			del self._sel
-	
-	def listDefinitionFunc(self, message, selected, cellRect, theCell,
-			dataOffset, dataLen, theList):
-		"""The LDEF message dispatcher routine, no need to override."""
-		if message == lInitMsg:
-			self.listDefInit(theList)
-		elif message == lDrawMsg:
-			self.listDefDraw(selected, cellRect, theCell,
-					dataOffset, dataLen, theList)
-		elif message == lHiliteMsg:
-			self.listDefHighlight(selected, cellRect, theCell,
-					dataOffset, dataLen, theList)
-		elif message == lCloseMsg:
-			self.listDefClose(theList)
-	
-	def listDefInit(self, theList):
-		pass
-	def listDefClose(self, theList):
-		pass
-	def listDefDraw(self, selected, cellRect, theCell, 
-			dataOffset, dataLen, theList):
-		pass
-	def listDefHighlight(self, selected, cellRect, theCell, 
-			dataOffset, dataLen, theList):
-		pass
+
+    """Base class for writing custom list definitions."""
+
+    _cellHeight = 0
+
+    def createlist(self):
+        self._calcbounds()
+        self.SetPort()
+        rect = self._bounds
+        rect = rect[0]+1, rect[1]+1, rect[2]-16, rect[3]-1
+        self._viewbounds = rect
+        self._list = CreateCustomList(
+                        rect,
+                        (0, 0, 1, 0),
+                        (0, self._cellHeight),
+                        (kListDefUserProcType, self.listDefinitionFunc),
+                        self._parentwindow.wid,
+                        0, 1, 0, 1)
+        if self.drawingmode:
+            self._list.LSetDrawingMode(0)
+        self._list.selFlags = self._flags
+        self.setitems(self.items)
+        if hasattr(self, "_sel"):
+            self.setselection(self._sel)
+            del self._sel
+
+    def listDefinitionFunc(self, message, selected, cellRect, theCell,
+                    dataOffset, dataLen, theList):
+        """The LDEF message dispatcher routine, no need to override."""
+        if message == lInitMsg:
+            self.listDefInit(theList)
+        elif message == lDrawMsg:
+            self.listDefDraw(selected, cellRect, theCell,
+                            dataOffset, dataLen, theList)
+        elif message == lHiliteMsg:
+            self.listDefHighlight(selected, cellRect, theCell,
+                            dataOffset, dataLen, theList)
+        elif message == lCloseMsg:
+            self.listDefClose(theList)
+
+    def listDefInit(self, theList):
+        pass
+    def listDefClose(self, theList):
+        pass
+    def listDefDraw(self, selected, cellRect, theCell,
+                    dataOffset, dataLen, theList):
+        pass
+    def listDefHighlight(self, selected, cellRect, theCell,
+                    dataOffset, dataLen, theList):
+        pass
 
 
 class TwoLineList(CustomList):
-	
-	_cellHeight = 28
-	
-	def listDefDraw(self, selected, cellRect, theCell,
-			dataOffset, dataLen, theList):
-		savedPort = Qd.GetPort()
-		Qd.SetPort(theList.GetListPort())
-		savedClip = Qd.NewRgn()
-		Qd.GetClip(savedClip)
-		Qd.ClipRect(cellRect)
-		savedPenState = Qd.GetPenState()
-		Qd.PenNormal()
-		Qd.EraseRect(cellRect)
-		
-		#draw the cell if it contains data
-		ascent, descent, leading, size, hm = Fm.FontMetrics()
-		linefeed = ascent + descent + leading
-		
-		if dataLen:
-			left, top, right, bottom = cellRect
-			data = theList.LGetCell(dataLen, theCell)
-			lines = data.split("\r")
-			line1 = lines[0]
-			if len(lines) > 1:
-				line2 = lines[1]
-			else:
-				line2 = ""
-			Qd.MoveTo(int(left + 4), int(top + ascent))
-			Qd.DrawText(line1, 0, len(line1))
-			if line2:
-				Qd.MoveTo(int(left + 4), int(top + ascent + linefeed))
-				Qd.DrawText(line2, 0, len(line2))
-			Qd.PenPat("\x11\x11\x11\x11\x11\x11\x11\x11")
-			bottom = top + theList.cellSize[1]
-			Qd.MoveTo(left, bottom - 1)
-			Qd.LineTo(right, bottom - 1)
-		if selected:
-			self.listDefHighlight(selected, cellRect, theCell,
-					dataOffset, dataLen, theList)
-		#restore graphics environment
-		Qd.SetPort(savedPort)
-		Qd.SetClip(savedClip)
-		Qd.DisposeRgn(savedClip)
-		Qd.SetPenState(savedPenState)
-	
-	def listDefHighlight(self, selected, cellRect, theCell,
-			dataOffset, dataLen, theList):
-		savedPort = Qd.GetPort()
-		Qd.SetPort(theList.GetListPort())
-		savedClip = Qd.NewRgn()
-		Qd.GetClip(savedClip)
-		Qd.ClipRect(cellRect)
-		savedPenState = Qd.GetPenState()
-		Qd.PenNormal()
-		Qd.PenMode(hilitetransfermode)
-		Qd.PaintRect(cellRect)
-		
-		#restore graphics environment
-		Qd.SetPort(savedPort)
-		Qd.SetClip(savedClip)
-		Qd.DisposeRgn(savedClip)
-		Qd.SetPenState(savedPenState)
-	
+
+    _cellHeight = 28
+
+    def listDefDraw(self, selected, cellRect, theCell,
+                    dataOffset, dataLen, theList):
+        savedPort = Qd.GetPort()
+        Qd.SetPort(theList.GetListPort())
+        savedClip = Qd.NewRgn()
+        Qd.GetClip(savedClip)
+        Qd.ClipRect(cellRect)
+        savedPenState = Qd.GetPenState()
+        Qd.PenNormal()
+        Qd.EraseRect(cellRect)
+
+        #draw the cell if it contains data
+        ascent, descent, leading, size, hm = Fm.FontMetrics()
+        linefeed = ascent + descent + leading
+
+        if dataLen:
+            left, top, right, bottom = cellRect
+            data = theList.LGetCell(dataLen, theCell)
+            lines = data.split("\r")
+            line1 = lines[0]
+            if len(lines) > 1:
+                line2 = lines[1]
+            else:
+                line2 = ""
+            Qd.MoveTo(int(left + 4), int(top + ascent))
+            Qd.DrawText(line1, 0, len(line1))
+            if line2:
+                Qd.MoveTo(int(left + 4), int(top + ascent + linefeed))
+                Qd.DrawText(line2, 0, len(line2))
+            Qd.PenPat("\x11\x11\x11\x11\x11\x11\x11\x11")
+            bottom = top + theList.cellSize[1]
+            Qd.MoveTo(left, bottom - 1)
+            Qd.LineTo(right, bottom - 1)
+        if selected:
+            self.listDefHighlight(selected, cellRect, theCell,
+                            dataOffset, dataLen, theList)
+        #restore graphics environment
+        Qd.SetPort(savedPort)
+        Qd.SetClip(savedClip)
+        Qd.DisposeRgn(savedClip)
+        Qd.SetPenState(savedPenState)
+
+    def listDefHighlight(self, selected, cellRect, theCell,
+                    dataOffset, dataLen, theList):
+        savedPort = Qd.GetPort()
+        Qd.SetPort(theList.GetListPort())
+        savedClip = Qd.NewRgn()
+        Qd.GetClip(savedClip)
+        Qd.ClipRect(cellRect)
+        savedPenState = Qd.GetPenState()
+        Qd.PenNormal()
+        Qd.PenMode(hilitetransfermode)
+        Qd.PaintRect(cellRect)
+
+        #restore graphics environment
+        Qd.SetPort(savedPort)
+        Qd.SetClip(savedClip)
+        Qd.DisposeRgn(savedClip)
+        Qd.SetPenState(savedPenState)
+
 
 class ResultsWindow:
-	
-	"""Simple results window. The user cannot make this window go away completely:
-	closing it will just hide it. It will remain in the windows list. The owner of this window
-	should call the done() method to indicate it's done with it.
-	"""
-	
-	def __init__(self, possize=None, title="Results", callback=None):
-		import W
-		if possize is None:
-			possize = (500, 200)
-		self.w = W.Window(possize, title, minsize=(200, 100))
-		self.w.results = W.TwoLineList((-1, -1, 1, -14), callback=None)
-		self.w.bind("<close>", self.hide)
-		self.w.open()
-		self._done = 0
-	
-	def done(self):
-		self._done = 1
-		if not self.w.isvisible():
-			self.w.close()
-	
-	def hide(self):
-		if not self._done:
-			self.w.show(0)
-			return -1
-	
-	def append(self, msg):
-		if not self.w.isvisible():
-			self.w.show(1)
-			self.w.select()
-		msg = string.replace(msg, '\n', '\r')
-		self.w.results.append(msg)
-		self.w.results.setselection([len(self.w.results)-1])
-	
-	def __getattr__(self, attr):
-		return getattr(self.w.results, attr)
+
+    """Simple results window. The user cannot make this window go away completely:
+    closing it will just hide it. It will remain in the windows list. The owner of this window
+    should call the done() method to indicate it's done with it.
+    """
+
+    def __init__(self, possize=None, title="Results", callback=None):
+        import W
+        if possize is None:
+            possize = (500, 200)
+        self.w = W.Window(possize, title, minsize=(200, 100))
+        self.w.results = W.TwoLineList((-1, -1, 1, -14), callback=None)
+        self.w.bind("<close>", self.hide)
+        self.w.open()
+        self._done = 0
+
+    def done(self):
+        self._done = 1
+        if not self.w.isvisible():
+            self.w.close()
+
+    def hide(self):
+        if not self._done:
+            self.w.show(0)
+            return -1
+
+    def append(self, msg):
+        if not self.w.isvisible():
+            self.w.show(1)
+            self.w.select()
+        msg = string.replace(msg, '\n', '\r')
+        self.w.results.append(msg)
+        self.w.results.setselection([len(self.w.results)-1])
+
+    def __getattr__(self, attr):
+        return getattr(self.w.results, attr)
 
 
 class MultiList(List):
-	
-	"""XXX Experimantal!!!"""
-	
-	def setitems(self, items):
-		self.items = items
-		if not self._parent or not self._list:
-			return
-		self._list.LDelRow(0, 1)
-		self.setdrawingmode(0)
-		self._list.LAddRow(len(self.items), 0)
-		self_itemrepr = self.itemrepr
-		set_cell = self._list.LSetCell
-		for i in range(len(items)):
-			row = items[i]
-			for j in range(len(row)):
-				item = row[j]
-				set_cell(self_itemrepr(item), (j, i))
-		self.setdrawingmode(1)
-	
-	def getselection(self):
-		if not self._parent or not self._list:
-			if hasattr(self, "_sel"):
-				return self._sel
-			return []
-		items = []
-		point = (0,0)
-		while 1:
-			ok, point = self._list.LGetSelect(1, point)
-			if not ok:
-				break
-			items.append(point[1])
-			point = point[0], point[1]+1
-		return items
-	
-	def setselection(self, selection):
-		if not self._parent or not self._list:
-			self._sel = selection
-			return
-		set_sel = self._list.LSetSelect
-		for i in range(len(self.items)):
-			for j in range(len(self.items[i])):
-				if i in selection:
-					set_sel(1, (j, i))
-				else:
-					set_sel(0, (j, i))
-		#self._list.LAutoScroll()
 
+    """XXX Experimantal!!!"""
+
+    def setitems(self, items):
+        self.items = items
+        if not self._parent or not self._list:
+            return
+        self._list.LDelRow(0, 1)
+        self.setdrawingmode(0)
+        self._list.LAddRow(len(self.items), 0)
+        self_itemrepr = self.itemrepr
+        set_cell = self._list.LSetCell
+        for i in range(len(items)):
+            row = items[i]
+            for j in range(len(row)):
+                item = row[j]
+                set_cell(self_itemrepr(item), (j, i))
+        self.setdrawingmode(1)
+
+    def getselection(self):
+        if not self._parent or not self._list:
+            if hasattr(self, "_sel"):
+                return self._sel
+            return []
+        items = []
+        point = (0,0)
+        while 1:
+            ok, point = self._list.LGetSelect(1, point)
+            if not ok:
+                break
+            items.append(point[1])
+            point = point[0], point[1]+1
+        return items
+
+    def setselection(self, selection):
+        if not self._parent or not self._list:
+            self._sel = selection
+            return
+        set_sel = self._list.LSetSelect
+        for i in range(len(self.items)):
+            for j in range(len(self.items[i])):
+                if i in selection:
+                    set_sel(1, (j, i))
+                else:
+                    set_sel(0, (j, i))
+        #self._list.LAutoScroll()
diff --git a/Mac/Tools/IDE/Wmenus.py b/Mac/Tools/IDE/Wmenus.py
index bd119a5..01a8e1c 100644
--- a/Mac/Tools/IDE/Wmenus.py
+++ b/Mac/Tools/IDE/Wmenus.py
@@ -8,252 +8,252 @@
 #_arrowdown = Qd.GetPicture(473)
 
 _arrowright = Res.Resource(
-	'\x00I\x00\x00\x00\x00\x00\n\x00\n\x11\x01\x01\x00\n\x00\x00\x00'
-	'\x00\x00\n\x00\n\x90\x00\x02\x00\x00\x00\x00\x00\n\x00\n\x00\x00'
-	'\x00\x00\x00\n\x00\n\x00\x00\x00\x00\x00\n\x00\n\x00\x00\x10\x00'
-	'\x18\x00\x1c\x00\x1e\x00\x1f\x00\x1f\x00\x1e\x00\x1c\x00\x18\x00'
-	'\x10\x00\xff')
+        '\x00I\x00\x00\x00\x00\x00\n\x00\n\x11\x01\x01\x00\n\x00\x00\x00'
+        '\x00\x00\n\x00\n\x90\x00\x02\x00\x00\x00\x00\x00\n\x00\n\x00\x00'
+        '\x00\x00\x00\n\x00\n\x00\x00\x00\x00\x00\n\x00\n\x00\x00\x10\x00'
+        '\x18\x00\x1c\x00\x1e\x00\x1f\x00\x1f\x00\x1e\x00\x1c\x00\x18\x00'
+        '\x10\x00\xff')
 
 
 class PopupControl(Wcontrols.ControlWidget):
-	
-	def __init__(self, possize, items=None, callback=None):
-		if items is None:
-			items = []
-		procID = Controls.popupMenuProc|Controls.popupFixedWidth|Controls.useWFont
-		Wcontrols.ControlWidget.__init__(self, possize, "", procID, callback, 0, 0, 0)
-		self._items = items[:]
-	
-	def set(self, value):
-		self._control.SetControlValue(value+1)
-	
-	def get(self):
-		return self._control.GetControlValue() - 1
-	
-	def open(self):
-		self.menu = menu = FrameWork.Menu(self._parentwindow.parent.menubar, 'Foo', -1)
-		
-		for i in range(len(self._items)):
-			item = self._items[i]
-			if type(item) == StringType:
-				menuitemtext = object = item
-			elif type(item) == TupleType and len(item) == 2:
-				menuitemtext, object = item
-				self._items[i] = object
-			else:
-				raise Wbase.WidgetsError, "illegal itemlist for popup menu"
-			menuitem = FrameWork.MenuItem(menu, menuitemtext, None, None)
-		
-		self._calcbounds()
-		self._control = Ctl.NewControl(self._parentwindow.wid, 
-						self._bounds, 
-						self._title, 
-						1, 
-						self._value, 
-						self.menu.id, 
-						self._max, 
-						self._procID, 
-						0)
-		self.SetPort()
-		self.enable(self._enabled)
-	
-	def close(self):
-		self.menu.delete()
-		return Wcontrols.ControlWidget.close(self)
-	
-	def click(self, point, modifiers):
-		if not self._enabled:
-			return
-		part = self._control.TrackControl(point, -1)
-		if part:
-			if self._callback:
-				Wbase.CallbackCall(self._callback, 0, self._items[self.get()])
+
+    def __init__(self, possize, items=None, callback=None):
+        if items is None:
+            items = []
+        procID = Controls.popupMenuProc|Controls.popupFixedWidth|Controls.useWFont
+        Wcontrols.ControlWidget.__init__(self, possize, "", procID, callback, 0, 0, 0)
+        self._items = items[:]
+
+    def set(self, value):
+        self._control.SetControlValue(value+1)
+
+    def get(self):
+        return self._control.GetControlValue() - 1
+
+    def open(self):
+        self.menu = menu = FrameWork.Menu(self._parentwindow.parent.menubar, 'Foo', -1)
+
+        for i in range(len(self._items)):
+            item = self._items[i]
+            if type(item) == StringType:
+                menuitemtext = object = item
+            elif type(item) == TupleType and len(item) == 2:
+                menuitemtext, object = item
+                self._items[i] = object
+            else:
+                raise Wbase.WidgetsError, "illegal itemlist for popup menu"
+            menuitem = FrameWork.MenuItem(menu, menuitemtext, None, None)
+
+        self._calcbounds()
+        self._control = Ctl.NewControl(self._parentwindow.wid,
+                                        self._bounds,
+                                        self._title,
+                                        1,
+                                        self._value,
+                                        self.menu.id,
+                                        self._max,
+                                        self._procID,
+                                        0)
+        self.SetPort()
+        self.enable(self._enabled)
+
+    def close(self):
+        self.menu.delete()
+        return Wcontrols.ControlWidget.close(self)
+
+    def click(self, point, modifiers):
+        if not self._enabled:
+            return
+        part = self._control.TrackControl(point, -1)
+        if part:
+            if self._callback:
+                Wbase.CallbackCall(self._callback, 0, self._items[self.get()])
 
 
 class PopupWidget(Wbase.ClickableWidget):
-	
-	"""Simple title-less popup widget. Should be 16x16 pixels. 
-	Builds the menu items on the fly, good for dynamic popup menus."""
-	
-	def __init__(self, possize, items=None, callback=None):
-		Wbase.ClickableWidget.__init__(self, possize)
-		if items is None:
-			items = []
-		self._items = items
-		self._itemsdict = {}
-		self._callback = callback
-		self._enabled = 1
-	
-	def close(self):
-		Wbase.ClickableWidget.close(self)
-		self._items = None
-		self._itemsdict = {}
-	
-	def draw(self, visRgn = None):
-		if self._visible:
-			Qd.FrameRect(self._bounds)
-			Qd.EraseRect(Qd.InsetRect(self._bounds, 1, 1))
-			l, t, r, b = self._bounds
-			l = l + 2
-			t = t + 3
-			pictframe = (l, t, l + 10, t + 10)
-			Qd.DrawPicture(_arrowright, pictframe)
-	
-	def click(self, point, modifiers):
-		if not self._enabled:
-			return
-		self.menu = FrameWork.Menu(self._parentwindow.parent.menubar, 'Foo', -1)
-		self._additems(self._items, self.menu)
-		self.SetPort()
-		l, t, r, b = self._bounds
-		l, t = Qd.LocalToGlobal((l+1, t+1))
-		Wbase.SetCursor("arrow")
-		self.menu.menu.EnableMenuItem(0)
-		reply = self.menu.menu.PopUpMenuSelect(t, l, 1)
-		if reply:
-			id = reply >> 16
-			item = reply & 0xffff
-			self._menu_callback(id, item)
-		self._emptymenu()
-	
-	def set(self, items):
-		self._items = items
-	
-	def get(self):
-		return self._items
-	
-	def _additems(self, items, menu):
-		from FrameWork import SubMenu, MenuItem
-		menu_id = menu.id
-		for item in items:
-			if item == "-":
-				menu.addseparator()
-				continue
-			elif type(item) == ListType:
-				submenu = SubMenu(menu, item[0])
-				self._additems(item[1:], submenu)
-				continue
-			elif type(item) == StringType:
-				menuitemtext = object = item
-			elif type(item) == TupleType and len(item) == 2:
-				menuitemtext, object = item
-			else:
-				raise Wbase.WidgetsError, "illegal itemlist for popup menu"
-			
-			if menuitemtext[:1] == '\0':
-				check = ord(menuitemtext[1])
-				menuitemtext = menuitemtext[2:]
-			else:
-				check = 0
-			menuitem = MenuItem(menu, menuitemtext, None, None)
-			if check:
-				menuitem.check(1)
-			self._itemsdict[(menu_id, menuitem.item)] = object
-	
-	def _emptymenu(self):
-		menus = self._parentwindow.parent.menubar.menus
-		for id, item in self._itemsdict.keys():
-			if menus.has_key(id):
-				self.menu = menus[id]
-				self.menu.delete()
-		self._itemsdict = {}
-	
-	def _menu_callback(self, id, item):
-		thing = self._itemsdict[(id, item)]
-		if callable(thing):
-			thing()
-		elif self._callback:
-			Wbase.CallbackCall(self._callback, 0, thing)
+
+    """Simple title-less popup widget. Should be 16x16 pixels.
+    Builds the menu items on the fly, good for dynamic popup menus."""
+
+    def __init__(self, possize, items=None, callback=None):
+        Wbase.ClickableWidget.__init__(self, possize)
+        if items is None:
+            items = []
+        self._items = items
+        self._itemsdict = {}
+        self._callback = callback
+        self._enabled = 1
+
+    def close(self):
+        Wbase.ClickableWidget.close(self)
+        self._items = None
+        self._itemsdict = {}
+
+    def draw(self, visRgn = None):
+        if self._visible:
+            Qd.FrameRect(self._bounds)
+            Qd.EraseRect(Qd.InsetRect(self._bounds, 1, 1))
+            l, t, r, b = self._bounds
+            l = l + 2
+            t = t + 3
+            pictframe = (l, t, l + 10, t + 10)
+            Qd.DrawPicture(_arrowright, pictframe)
+
+    def click(self, point, modifiers):
+        if not self._enabled:
+            return
+        self.menu = FrameWork.Menu(self._parentwindow.parent.menubar, 'Foo', -1)
+        self._additems(self._items, self.menu)
+        self.SetPort()
+        l, t, r, b = self._bounds
+        l, t = Qd.LocalToGlobal((l+1, t+1))
+        Wbase.SetCursor("arrow")
+        self.menu.menu.EnableMenuItem(0)
+        reply = self.menu.menu.PopUpMenuSelect(t, l, 1)
+        if reply:
+            id = reply >> 16
+            item = reply & 0xffff
+            self._menu_callback(id, item)
+        self._emptymenu()
+
+    def set(self, items):
+        self._items = items
+
+    def get(self):
+        return self._items
+
+    def _additems(self, items, menu):
+        from FrameWork import SubMenu, MenuItem
+        menu_id = menu.id
+        for item in items:
+            if item == "-":
+                menu.addseparator()
+                continue
+            elif type(item) == ListType:
+                submenu = SubMenu(menu, item[0])
+                self._additems(item[1:], submenu)
+                continue
+            elif type(item) == StringType:
+                menuitemtext = object = item
+            elif type(item) == TupleType and len(item) == 2:
+                menuitemtext, object = item
+            else:
+                raise Wbase.WidgetsError, "illegal itemlist for popup menu"
+
+            if menuitemtext[:1] == '\0':
+                check = ord(menuitemtext[1])
+                menuitemtext = menuitemtext[2:]
+            else:
+                check = 0
+            menuitem = MenuItem(menu, menuitemtext, None, None)
+            if check:
+                menuitem.check(1)
+            self._itemsdict[(menu_id, menuitem.item)] = object
+
+    def _emptymenu(self):
+        menus = self._parentwindow.parent.menubar.menus
+        for id, item in self._itemsdict.keys():
+            if menus.has_key(id):
+                self.menu = menus[id]
+                self.menu.delete()
+        self._itemsdict = {}
+
+    def _menu_callback(self, id, item):
+        thing = self._itemsdict[(id, item)]
+        if callable(thing):
+            thing()
+        elif self._callback:
+            Wbase.CallbackCall(self._callback, 0, thing)
 
 
 class PopupMenu(PopupWidget):
-	
-	"""Simple title-less popup widget. Should be 16x16 pixels. 
-	Prebuilds the menu items, good for static (non changing) popup menus."""
-	
-	def open(self):
-		self._calcbounds()
-		self.menu = Wapplication.Menu(self._parentwindow.parent.menubar, 'Foo', -1)
-		self._additems(self._items, self.menu)
-	
-	def close(self):
-		self._emptymenu()
-		Wbase.Widget.close(self)
-		self._items = None
-		self._itemsdict = {}
-		self.menu = None
-	
-	def set(self, items):
-		if self._itemsdict:
-			self._emptymenu()
-		self.menu = Wapplication.Menu(self._parentwindow.parent.menubar, 'Foo', -1)
-		self._items = items
-		self._additems(self._items, self.menu)
-	
-	def click(self, point, modifiers):
-		if not self._enabled:
-			return
-		self.SetPort()
-		l, t, r, b = self._bounds
-		l, t = Qd.LocalToGlobal((l+1, t+1))
-		Wbase.SetCursor("arrow")
-		self.menu.menu.EnableMenuItem(0)
-		reply = self.menu.menu.PopUpMenuSelect(t, l, 1)
-		if reply:
-			id = reply >> 16
-			item = reply & 0xffff
-			self._menu_callback(id, item)
+
+    """Simple title-less popup widget. Should be 16x16 pixels.
+    Prebuilds the menu items, good for static (non changing) popup menus."""
+
+    def open(self):
+        self._calcbounds()
+        self.menu = Wapplication.Menu(self._parentwindow.parent.menubar, 'Foo', -1)
+        self._additems(self._items, self.menu)
+
+    def close(self):
+        self._emptymenu()
+        Wbase.Widget.close(self)
+        self._items = None
+        self._itemsdict = {}
+        self.menu = None
+
+    def set(self, items):
+        if self._itemsdict:
+            self._emptymenu()
+        self.menu = Wapplication.Menu(self._parentwindow.parent.menubar, 'Foo', -1)
+        self._items = items
+        self._additems(self._items, self.menu)
+
+    def click(self, point, modifiers):
+        if not self._enabled:
+            return
+        self.SetPort()
+        l, t, r, b = self._bounds
+        l, t = Qd.LocalToGlobal((l+1, t+1))
+        Wbase.SetCursor("arrow")
+        self.menu.menu.EnableMenuItem(0)
+        reply = self.menu.menu.PopUpMenuSelect(t, l, 1)
+        if reply:
+            id = reply >> 16
+            item = reply & 0xffff
+            self._menu_callback(id, item)
 
 
 class FontMenu(PopupMenu):
-	
-	"""A font popup menu."""
-	
-	menu = None
-	
-	def __init__(self, possize, callback):
-		PopupMenu.__init__(self, possize)
-		_makefontmenu()
-		self._callback = callback
-		self._enabled = 1
-	
-	def open(self):
-		self._calcbounds()
-	
-	def close(self):
-		del self._callback
-	
-	def set(self):
-		raise Wbase.WidgetsError, "can't change font menu widget"
-	
-	def _menu_callback(self, id, item):
-		fontname = self.menu.menu.GetMenuItemText(item)
-		if self._callback:
-			Wbase.CallbackCall(self._callback, 0, fontname)
 
-	def click(self, point, modifiers):
-		if not self._enabled:
-			return
-		_makefontmenu()
-		return PopupMenu.click(self, point, modifiers)
-	
+    """A font popup menu."""
+
+    menu = None
+
+    def __init__(self, possize, callback):
+        PopupMenu.__init__(self, possize)
+        _makefontmenu()
+        self._callback = callback
+        self._enabled = 1
+
+    def open(self):
+        self._calcbounds()
+
+    def close(self):
+        del self._callback
+
+    def set(self):
+        raise Wbase.WidgetsError, "can't change font menu widget"
+
+    def _menu_callback(self, id, item):
+        fontname = self.menu.menu.GetMenuItemText(item)
+        if self._callback:
+            Wbase.CallbackCall(self._callback, 0, fontname)
+
+    def click(self, point, modifiers):
+        if not self._enabled:
+            return
+        _makefontmenu()
+        return PopupMenu.click(self, point, modifiers)
+
 
 def _makefontmenu():
-	"""helper for font menu"""
-	if FontMenu.menu is not None:
-		return
-	import W
-	FontMenu.menu = Wapplication.Menu(W.getapplication().menubar, 'Foo', -1)
-	W.SetCursor('watch')
-	for i in range(FontMenu.menu.menu.CountMenuItems(), 0, -1):
-		FontMenu.menu.menu.DeleteMenuItem(i)
-	FontMenu.menu.menu.AppendResMenu('FOND')
+    """helper for font menu"""
+    if FontMenu.menu is not None:
+        return
+    import W
+    FontMenu.menu = Wapplication.Menu(W.getapplication().menubar, 'Foo', -1)
+    W.SetCursor('watch')
+    for i in range(FontMenu.menu.menu.CountMenuItems(), 0, -1):
+        FontMenu.menu.menu.DeleteMenuItem(i)
+    FontMenu.menu.menu.AppendResMenu('FOND')
 
 
 def _getfontlist():
-	from Carbon import Res
-	fontnames = []
-	for i in range(1, Res.CountResources('FOND') + 1):
-		r = Res.GetIndResource('FOND', i)
-		fontnames.append(r.GetResInfo()[2])
-	return fontnames
+    from Carbon import Res
+    fontnames = []
+    for i in range(1, Res.CountResources('FOND') + 1):
+        r = Res.GetIndResource('FOND', i)
+        fontnames.append(r.GetResInfo()[2])
+    return fontnames
diff --git a/Mac/Tools/IDE/Wminiapp.py b/Mac/Tools/IDE/Wminiapp.py
index e09e334..0c51583 100644
--- a/Mac/Tools/IDE/Wminiapp.py
+++ b/Mac/Tools/IDE/Wminiapp.py
@@ -5,18 +5,18 @@
 import os
 
 class TestApp(Wapplication.Application):
-	
-	def __init__(self):
-		from Carbon import Res
-#		macresource.open_pathname("Widgets.rsrc")
-		self._menustocheck = []
-		self.preffilepath = os.path.join("Python", "PythonIDE preferences")
-		Wapplication.Application.__init__(self, 'Pyth')
-		# open a new text editor
-		import PyEdit
-		PyEdit.Editor()
-		# start the mainloop
-		self.mainloop()
-	
+
+    def __init__(self):
+        from Carbon import Res
+#               macresource.open_pathname("Widgets.rsrc")
+        self._menustocheck = []
+        self.preffilepath = os.path.join("Python", "PythonIDE preferences")
+        Wapplication.Application.__init__(self, 'Pyth')
+        # open a new text editor
+        import PyEdit
+        PyEdit.Editor()
+        # start the mainloop
+        self.mainloop()
+
 
 TestApp()
diff --git a/Mac/Tools/IDE/Wquicktime.py b/Mac/Tools/IDE/Wquicktime.py
index 421d558..671aa09 100644
--- a/Mac/Tools/IDE/Wquicktime.py
+++ b/Mac/Tools/IDE/Wquicktime.py
@@ -9,106 +9,105 @@
 _moviesinitialized = 0
 
 def EnterMovies():
-	global _moviesinitialized
-	if not _moviesinitialized:
-		Qt.EnterMovies()
-		_moviesinitialized = 1
+    global _moviesinitialized
+    if not _moviesinitialized:
+        Qt.EnterMovies()
+        _moviesinitialized = 1
 
 class Movie(W.Widget):
-	
-	def __init__(self, possize):
-		EnterMovies()
-		self.movie = None
-		self.running = 0
-		W.Widget.__init__(self, possize)
-	
-	def adjust(self, oldbounds):
-		self.SetPort()
-		self.GetWindow().InvalWindowRect(oldbounds)
-		self.GetWindow().InvalWindowRect(self._bounds)
-		self.calcmoviebox()
-	
-	def set(self, path_or_fss, start = 0):
-		self.SetPort()
-		if self.movie:
-			#self.GetWindow().InvalWindowRect(self.movie.GetMovieBox())
-			Qd.PaintRect(self.movie.GetMovieBox())
-		path = File.pathname(path)
-		self.movietitle = os.path.basename(path)
-		movieResRef = Qt.OpenMovieFile(path_or_fss, 1)
-		self.movie, dummy, dummy = Qt.NewMovieFromFile(movieResRef, 0, QuickTime.newMovieActive)
-		self.moviebox = self.movie.GetMovieBox()
-		self.calcmoviebox()
-		Qd.ObscureCursor()	# XXX does this work at all?
-		self.movie.GoToBeginningOfMovie()
-		if start:
-			self.movie.StartMovie()
-			self.running = 1
-		else:
-			self.running = 0
-			self.movie.MoviesTask(0)
-	
-	def get(self):
-		return self.movie
-	
-	def getmovietitle(self):
-		return self.movietitle
-	
-	def start(self):
-		if self.movie:
-			Qd.ObscureCursor()
-			self.movie.StartMovie()
-			self.running = 1
-	
-	def stop(self):
-		if self.movie:
-			self.movie.StopMovie()
-			self.running = 0
-	
-	def rewind(self):
-		if self.movie:
-			self.movie.GoToBeginningOfMovie()
-	
-	def calcmoviebox(self):
-		if not self.movie:
-			return
-		ml, mt, mr, mb = self.moviebox
-		wl, wt, wr, wb = widgetbox = self._bounds
-		mheight = mb - mt
-		mwidth = mr - ml
-		wheight = wb - wt
-		wwidth = wr - wl
-		if (mheight * 2 < wheight) and (mwidth * 2 < wwidth):
-			scale = 2
-		elif mheight > wheight or mwidth > wwidth:
-			scale = min(float(wheight) / mheight, float(wwidth) / mwidth)
-		else:
-			scale = 1
-		mwidth, mheight = mwidth * scale, mheight * scale
-		ml, mt = wl + (wwidth - mwidth) / 2, wt + (wheight - mheight) / 2
-		mr, mb = ml + mwidth, mt + mheight
-		self.movie.SetMovieBox((ml, mt, mr, mb))
-	
-	def idle(self, *args):
-		if self.movie:
-			if not self.movie.IsMovieDone() and self.running:
-				Qd.ObscureCursor()
-				while 1:
-					self.movie.MoviesTask(0)
-					gotone, event = Evt.EventAvail(Events.everyEvent)
-					if gotone or self.movie.IsMovieDone():
-						break
-			elif self.running:
-				box = self.movie.GetMovieBox()
-				self.SetPort()
-				self.GetWindow().InvalWindowRect(box)
-				self.movie = None
-				self.running = 0
-	
-	def draw(self, visRgn = None):
-		if self._visible:
-			Qd.PaintRect(self._bounds)
-			if self.movie:
-				self.movie.UpdateMovie()
-				self.movie.MoviesTask(0)
 
+    def __init__(self, possize):
+        EnterMovies()
+        self.movie = None
+        self.running = 0
+        W.Widget.__init__(self, possize)
+
+    def adjust(self, oldbounds):
+        self.SetPort()
+        self.GetWindow().InvalWindowRect(oldbounds)
+        self.GetWindow().InvalWindowRect(self._bounds)
+        self.calcmoviebox()
+
+    def set(self, path_or_fss, start = 0):
+        self.SetPort()
+        if self.movie:
+            #self.GetWindow().InvalWindowRect(self.movie.GetMovieBox())
+            Qd.PaintRect(self.movie.GetMovieBox())
+        path = File.pathname(path)
+        self.movietitle = os.path.basename(path)
+        movieResRef = Qt.OpenMovieFile(path_or_fss, 1)
+        self.movie, dummy, dummy = Qt.NewMovieFromFile(movieResRef, 0, QuickTime.newMovieActive)
+        self.moviebox = self.movie.GetMovieBox()
+        self.calcmoviebox()
+        Qd.ObscureCursor()      # XXX does this work at all?
+        self.movie.GoToBeginningOfMovie()
+        if start:
+            self.movie.StartMovie()
+            self.running = 1
+        else:
+            self.running = 0
+            self.movie.MoviesTask(0)
+
+    def get(self):
+        return self.movie
+
+    def getmovietitle(self):
+        return self.movietitle
+
+    def start(self):
+        if self.movie:
+            Qd.ObscureCursor()
+            self.movie.StartMovie()
+            self.running = 1
+
+    def stop(self):
+        if self.movie:
+            self.movie.StopMovie()
+            self.running = 0
+
+    def rewind(self):
+        if self.movie:
+            self.movie.GoToBeginningOfMovie()
+
+    def calcmoviebox(self):
+        if not self.movie:
+            return
+        ml, mt, mr, mb = self.moviebox
+        wl, wt, wr, wb = widgetbox = self._bounds
+        mheight = mb - mt
+        mwidth = mr - ml
+        wheight = wb - wt
+        wwidth = wr - wl
+        if (mheight * 2 < wheight) and (mwidth * 2 < wwidth):
+            scale = 2
+        elif mheight > wheight or mwidth > wwidth:
+            scale = min(float(wheight) / mheight, float(wwidth) / mwidth)
+        else:
+            scale = 1
+        mwidth, mheight = mwidth * scale, mheight * scale
+        ml, mt = wl + (wwidth - mwidth) / 2, wt + (wheight - mheight) / 2
+        mr, mb = ml + mwidth, mt + mheight
+        self.movie.SetMovieBox((ml, mt, mr, mb))
+
+    def idle(self, *args):
+        if self.movie:
+            if not self.movie.IsMovieDone() and self.running:
+                Qd.ObscureCursor()
+                while 1:
+                    self.movie.MoviesTask(0)
+                    gotone, event = Evt.EventAvail(Events.everyEvent)
+                    if gotone or self.movie.IsMovieDone():
+                        break
+            elif self.running:
+                box = self.movie.GetMovieBox()
+                self.SetPort()
+                self.GetWindow().InvalWindowRect(box)
+                self.movie = None
+                self.running = 0
+
+    def draw(self, visRgn = None):
+        if self._visible:
+            Qd.PaintRect(self._bounds)
+            if self.movie:
+                self.movie.UpdateMovie()
+                self.movie.MoviesTask(0)
diff --git a/Mac/Tools/IDE/Wsocket.py b/Mac/Tools/IDE/Wsocket.py
index 913797c..eb5936d 100644
--- a/Mac/Tools/IDE/Wsocket.py
+++ b/Mac/Tools/IDE/Wsocket.py
@@ -17,375 +17,375 @@
 VERBOSE = 1
 
 class Server(asyncore.dispatcher):
-	
-	"""Generic asynchronous server class"""
-	
-	def __init__(self, port, handler_class, backlog=1, host=""):
-		"""arguments:
-		- port: the port to listen to
-		- handler_class: class to handle requests
-		- backlog: backlog queue size (optional) (don't fully understand, see socket docs)
-		- host: host name (optional: can be empty to use default host name)
-		"""
-		if VERBOSE:
-			print "Starting", self.__class__.__name__
-		self.handler_class = handler_class
-		asyncore.dispatcher.__init__(self)
-		self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
-		self.bind((host, port))
-		self.listen(backlog)
-	
-	def handle_accept(self):
-		conn, addr = self.accept()
-		if VERBOSE:
-			print 'Incoming Connection from %s:%d' % addr
-		self.handler_class(conn)
+
+    """Generic asynchronous server class"""
+
+    def __init__(self, port, handler_class, backlog=1, host=""):
+        """arguments:
+        - port: the port to listen to
+        - handler_class: class to handle requests
+        - backlog: backlog queue size (optional) (don't fully understand, see socket docs)
+        - host: host name (optional: can be empty to use default host name)
+        """
+        if VERBOSE:
+            print "Starting", self.__class__.__name__
+        self.handler_class = handler_class
+        asyncore.dispatcher.__init__(self)
+        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
+        self.bind((host, port))
+        self.listen(backlog)
+
+    def handle_accept(self):
+        conn, addr = self.accept()
+        if VERBOSE:
+            print 'Incoming Connection from %s:%d' % addr
+        self.handler_class(conn)
 
 
 class ProxyServer(Server):
-	
-	"""Generic proxy server class"""
-	
-	def __init__(self, port, handler_class, proxyaddr=None, closepartners=0):
-		"""arguments:
-		- port: the port to listen to
-		- handler_class: proxy class to handle requests
-		- proxyaddr: a tuple containing the address and 
-		  port of a remote host to connect to (optional)
-		- closepartners: boolean, specifies whether we should close
-		  all proxy connections or not (optional). http seems to *not*
-		  want this, but telnet does...
-		"""
-		Server.__init__(self, port, handler_class, 1, "")
-		self.proxyaddr = proxyaddr
-		self.closepartners = closepartners
-	
-	def handle_accept(self):
-		conn, addr = self.accept()
-		if VERBOSE:
-			print 'Incoming Connection from %s:%d' % addr
-		self.handler_class(conn, self.proxyaddr, closepartner=self.closepartners)
+
+    """Generic proxy server class"""
+
+    def __init__(self, port, handler_class, proxyaddr=None, closepartners=0):
+        """arguments:
+        - port: the port to listen to
+        - handler_class: proxy class to handle requests
+        - proxyaddr: a tuple containing the address and
+          port of a remote host to connect to (optional)
+        - closepartners: boolean, specifies whether we should close
+          all proxy connections or not (optional). http seems to *not*
+          want this, but telnet does...
+        """
+        Server.__init__(self, port, handler_class, 1, "")
+        self.proxyaddr = proxyaddr
+        self.closepartners = closepartners
+
+    def handle_accept(self):
+        conn, addr = self.accept()
+        if VERBOSE:
+            print 'Incoming Connection from %s:%d' % addr
+        self.handler_class(conn, self.proxyaddr, closepartner=self.closepartners)
 
 
 class Connection(asyncore.dispatcher):
-	
-	"""Generic connection class"""
-	
-	def __init__(self, sock_or_address=None, readfunc=None, terminator=None):
-		"""arguments: 
-		- sock_or_address: either a socket, or a tuple containing the name 
-		and port number of a remote host
-		- readfunc: callback function (optional). Will be called whenever
-		  there is some data available, or when an appropraite terminator
-		  is found.
-		- terminator: string which specifies when a read is complete (optional)"""
-		self._out_buffer = ""
-		self._in_buffer = ""
-		self.readfunc = readfunc
-		self.terminator = terminator
-		asyncore.dispatcher.__init__(self)
-		if hasattr(sock_or_address, "fileno"):
-			self.set_socket(sock_or_address)
-		else:
-			sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-			sock.setblocking(0)
-			self.set_socket(sock)
-			if sock_or_address:
-				self.connect(sock_or_address)
-	
-	# public methods
-	def send(self, data):
-		self._out_buffer = self._out_buffer + data
-	
-	def recv(self, bytes=-1):
-		if bytes == -1:
-			bytes = len(self._in_buffer)
-		data = self._in_buffer[:bytes]
-		self._in_buffer = self._in_buffer[bytes:]
-		return data
-	
-	def set_terminator(self, terminator):
-		self.terminator = terminator
-	
-	# override this if you want to control the incoming data stream 
-	def handle_incoming_data(self, data):
-		if self.readfunc:
-			if self.terminator:
-				self._in_buffer = self._in_buffer + data
-				pos = string.find(self._in_buffer, self.terminator)
-				if pos < 0:
-					return
-				data = self._in_buffer[:pos]
-				self._in_buffer = self._in_buffer[pos + len(self.terminator):]
-				self.readfunc(data)
-			else:
-				self.readfunc(self._in_buffer + data)
-				self._in_buffer = ""
-		else:
-			self._in_buffer = self._in_buffer + data
-	
-	# internal muck
-	def handle_read(self):
-		data = asyncore.dispatcher.recv(self, BUFSIZE)
-		if data:
-			if VERBOSE > 2:
-				print "incoming -> %x %r" % (id(self), data)
-			self.handle_incoming_data(data)
-	
-	def handle_write(self):
-		if self._out_buffer:
-			sent = self.socket.send(self._out_buffer[:BUFSIZE])
-			if VERBOSE > 2:
-				print "outgoing -> %x %r" % (id(self), self._out_buffer[:sent])
-			self._out_buffer = self._out_buffer[sent:]
-	
-	def close(self):
-		if self.readfunc and self._in_buffer:
-			self.readfunc(self._in_buffer)
-			self._in_buffer = ""
-		#elif VERBOSE > 1 and self._in_buffer:
-		#	print "--- there is unread data: %r", (self._in_buffer,)
-		asyncore.dispatcher.close(self)
-	
-	def handle_close(self):
-		self.close()
-	
-	def handle_connect(self):
-		pass
+
+    """Generic connection class"""
+
+    def __init__(self, sock_or_address=None, readfunc=None, terminator=None):
+        """arguments:
+        - sock_or_address: either a socket, or a tuple containing the name
+        and port number of a remote host
+        - readfunc: callback function (optional). Will be called whenever
+          there is some data available, or when an appropraite terminator
+          is found.
+        - terminator: string which specifies when a read is complete (optional)"""
+        self._out_buffer = ""
+        self._in_buffer = ""
+        self.readfunc = readfunc
+        self.terminator = terminator
+        asyncore.dispatcher.__init__(self)
+        if hasattr(sock_or_address, "fileno"):
+            self.set_socket(sock_or_address)
+        else:
+            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+            sock.setblocking(0)
+            self.set_socket(sock)
+            if sock_or_address:
+                self.connect(sock_or_address)
+
+    # public methods
+    def send(self, data):
+        self._out_buffer = self._out_buffer + data
+
+    def recv(self, bytes=-1):
+        if bytes == -1:
+            bytes = len(self._in_buffer)
+        data = self._in_buffer[:bytes]
+        self._in_buffer = self._in_buffer[bytes:]
+        return data
+
+    def set_terminator(self, terminator):
+        self.terminator = terminator
+
+    # override this if you want to control the incoming data stream
+    def handle_incoming_data(self, data):
+        if self.readfunc:
+            if self.terminator:
+                self._in_buffer = self._in_buffer + data
+                pos = string.find(self._in_buffer, self.terminator)
+                if pos < 0:
+                    return
+                data = self._in_buffer[:pos]
+                self._in_buffer = self._in_buffer[pos + len(self.terminator):]
+                self.readfunc(data)
+            else:
+                self.readfunc(self._in_buffer + data)
+                self._in_buffer = ""
+        else:
+            self._in_buffer = self._in_buffer + data
+
+    # internal muck
+    def handle_read(self):
+        data = asyncore.dispatcher.recv(self, BUFSIZE)
+        if data:
+            if VERBOSE > 2:
+                print "incoming -> %x %r" % (id(self), data)
+            self.handle_incoming_data(data)
+
+    def handle_write(self):
+        if self._out_buffer:
+            sent = self.socket.send(self._out_buffer[:BUFSIZE])
+            if VERBOSE > 2:
+                print "outgoing -> %x %r" % (id(self), self._out_buffer[:sent])
+            self._out_buffer = self._out_buffer[sent:]
+
+    def close(self):
+        if self.readfunc and self._in_buffer:
+            self.readfunc(self._in_buffer)
+            self._in_buffer = ""
+        #elif VERBOSE > 1 and self._in_buffer:
+        #       print "--- there is unread data: %r", (self._in_buffer,)
+        asyncore.dispatcher.close(self)
+
+    def handle_close(self):
+        self.close()
+
+    def handle_connect(self):
+        pass
 
 
 class ConnectionUI:
-	
-	"""Glue to let a connection tell things to the UI in a standardized way.
-	
-	The protocoll defines four functions, which the connection will call:
-	
-		def settotal(int total): gets called when the connection knows the data size
-		def setcurrent(int current): gets called when some new data has arrived
-		def done(): gets called when the transaction is complete
-		def error(type, value, tb): gets called wheneven an error occured
-	"""
-	
-	def __init__(self, settotal_func, setcurrent_func, done_func, error_func):
-		self.settotal = settotal_func
-		self.setcurrent = setcurrent_func
-		self.done = done_func
-		self.error = error_func
+
+    """Glue to let a connection tell things to the UI in a standardized way.
+
+    The protocoll defines four functions, which the connection will call:
+
+            def settotal(int total): gets called when the connection knows the data size
+            def setcurrent(int current): gets called when some new data has arrived
+            def done(): gets called when the transaction is complete
+            def error(type, value, tb): gets called wheneven an error occured
+    """
+
+    def __init__(self, settotal_func, setcurrent_func, done_func, error_func):
+        self.settotal = settotal_func
+        self.setcurrent = setcurrent_func
+        self.done = done_func
+        self.error = error_func
 
 
 class HTTPError(socket.error): pass
 
 
 class HTTPClient(Connection, httplib.HTTP):
-	
-	"""Asynchronous HTTP connection"""
-	
-	def __init__(self, (host, port), datahandler, ui=None):
-		Connection.__init__(self, (host, port))
-		self.datahandler = datahandler
-		self.ui = ui
-		self.buf = ""
-		self.doneheaders = 0
-		self.done = 0
-		self.headers = None
-		self.length = None
-		self.pos = 0
-	
-	def getreply(self):
-		raise TypeError, "getreply() is not supported in async HTTP connection"
-	
-	def handle_incoming_data(self, data):
-		assert not self.done
-		if not self.doneheaders:
-			self.buf = self.buf + data
-			pos = string.find(self.buf, "\r\n\r\n")
-			if pos >= 0:
-				self.handle_reply(self.buf[:pos+4])
-				length = self.headers.getheader("Content-Length")
-				if length is not None:
-					self.length = int(length)
-					if self.ui is not None:
-						self.ui.settotal(self.length)
-				else:
-					self.length = -1
-				self.doneheaders = 1
-				self.handle_data(self.buf[pos+4:])
-				self.buf = ""
-		else:
-			self.handle_data(data)
-	
-	def handle_reply(self, data):
-		f = cStringIO.StringIO(data)
-		ver, code, msg = string.split(f.readline(), None, 2)
-		code = int(code)
-		msg = string.strip(msg)
-		if code <> 200:
-			# Hm, this is what *I* need, but probably not correct...
-			raise HTTPError, (code, msg)
-		self.headers = mimetools.Message(f)
-	
-	def handle_data(self, data):
-		self.pos = self.pos + len(data)
-		if self.ui is not None:
-			self.ui.setcurrent(self.pos)
-		self.datahandler(data)
-		if self.pos >= self.length:
-			self.datahandler("")
-			self.done = 1
-			if self.ui is not None:
-				self.ui.done()
-	
-	def handle_error(self, type, value, tb):
-		if self.ui is not None:
-			self.ui.error(type, value, tb)
-		else:
-			Connection.handle_error(self, type, value, tb)
-	
-	def log(self, message):
-		if VERBOSE:
-			print 'LOG:', message
+
+    """Asynchronous HTTP connection"""
+
+    def __init__(self, (host, port), datahandler, ui=None):
+        Connection.__init__(self, (host, port))
+        self.datahandler = datahandler
+        self.ui = ui
+        self.buf = ""
+        self.doneheaders = 0
+        self.done = 0
+        self.headers = None
+        self.length = None
+        self.pos = 0
+
+    def getreply(self):
+        raise TypeError, "getreply() is not supported in async HTTP connection"
+
+    def handle_incoming_data(self, data):
+        assert not self.done
+        if not self.doneheaders:
+            self.buf = self.buf + data
+            pos = string.find(self.buf, "\r\n\r\n")
+            if pos >= 0:
+                self.handle_reply(self.buf[:pos+4])
+                length = self.headers.getheader("Content-Length")
+                if length is not None:
+                    self.length = int(length)
+                    if self.ui is not None:
+                        self.ui.settotal(self.length)
+                else:
+                    self.length = -1
+                self.doneheaders = 1
+                self.handle_data(self.buf[pos+4:])
+                self.buf = ""
+        else:
+            self.handle_data(data)
+
+    def handle_reply(self, data):
+        f = cStringIO.StringIO(data)
+        ver, code, msg = string.split(f.readline(), None, 2)
+        code = int(code)
+        msg = string.strip(msg)
+        if code <> 200:
+            # Hm, this is what *I* need, but probably not correct...
+            raise HTTPError, (code, msg)
+        self.headers = mimetools.Message(f)
+
+    def handle_data(self, data):
+        self.pos = self.pos + len(data)
+        if self.ui is not None:
+            self.ui.setcurrent(self.pos)
+        self.datahandler(data)
+        if self.pos >= self.length:
+            self.datahandler("")
+            self.done = 1
+            if self.ui is not None:
+                self.ui.done()
+
+    def handle_error(self, type, value, tb):
+        if self.ui is not None:
+            self.ui.error(type, value, tb)
+        else:
+            Connection.handle_error(self, type, value, tb)
+
+    def log(self, message):
+        if VERBOSE:
+            print 'LOG:', message
 
 
 class PyMessage:
-	
-	def __init__(self):
-		self._buf = ""
-		self._len = None
-		self._checksum = None
-	
-	def feed(self, data):
-		self._buf = self._buf + data
-		if self._len is None:
-			if len(self._buf) >= 8:
-				import struct
-				self._len, self._checksum = struct.unpack("ll", self._buf[:8])
-				self._buf = self._buf[8:]
-		if self._len is not None:
-			if len(self._buf) >= self._len:
-				import zlib
-				data = self._buf[:self._len]
-				leftover = self._buf[self._len:]
-				self._buf = None
-				assert self._checksum == zlib.adler32(data), "corrupt data"
-				self.data = data
-				return 1, leftover
-			else:
-				return 0, None
-		else:
-			return 0, None
+
+    def __init__(self):
+        self._buf = ""
+        self._len = None
+        self._checksum = None
+
+    def feed(self, data):
+        self._buf = self._buf + data
+        if self._len is None:
+            if len(self._buf) >= 8:
+                import struct
+                self._len, self._checksum = struct.unpack("ll", self._buf[:8])
+                self._buf = self._buf[8:]
+        if self._len is not None:
+            if len(self._buf) >= self._len:
+                import zlib
+                data = self._buf[:self._len]
+                leftover = self._buf[self._len:]
+                self._buf = None
+                assert self._checksum == zlib.adler32(data), "corrupt data"
+                self.data = data
+                return 1, leftover
+            else:
+                return 0, None
+        else:
+            return 0, None
 
 
 class PyConnection(Connection):
-	
-	def __init__(self, sock_or_address):
-		Connection.__init__(self, sock_or_address)
-		self.currentmessage = PyMessage()
-	
-	def handle_incoming_data(self, data):
-		while data:
-			done, data = self.currentmessage.feed(data)
-			if done:
-				import cPickle
-				self.handle_object(cPickle.loads(self.currentmessage.data))
-				self.currentmessage = PyMessage()
-	
-	def handle_object(self, object):
-		print 'unhandled object:', repr(object)
-	
-	def send(self, object):
-		import cPickle, zlib, struct
-		data = cPickle.dumps(object, 1)
-		length = len(data)
-		checksum = zlib.adler32(data)
-		data = struct.pack("ll", length, checksum) + data
-		Connection.send(self, data)
+
+    def __init__(self, sock_or_address):
+        Connection.__init__(self, sock_or_address)
+        self.currentmessage = PyMessage()
+
+    def handle_incoming_data(self, data):
+        while data:
+            done, data = self.currentmessage.feed(data)
+            if done:
+                import cPickle
+                self.handle_object(cPickle.loads(self.currentmessage.data))
+                self.currentmessage = PyMessage()
+
+    def handle_object(self, object):
+        print 'unhandled object:', repr(object)
+
+    def send(self, object):
+        import cPickle, zlib, struct
+        data = cPickle.dumps(object, 1)
+        length = len(data)
+        checksum = zlib.adler32(data)
+        data = struct.pack("ll", length, checksum) + data
+        Connection.send(self, data)
 
 
 class Echo(Connection):
-	
-	"""Simple echoing connection: it sends everything back it receives.""" 
-	
-	def handle_incoming_data(self, data):
-		self.send(data)
+
+    """Simple echoing connection: it sends everything back it receives."""
+
+    def handle_incoming_data(self, data):
+        self.send(data)
 
 
 class Proxy(Connection):
-	
-	"""Generic proxy connection"""
-	
-	def __init__(self, sock_or_address=None, proxyaddr=None, closepartner=0):
-		"""arguments:
-		- sock_or_address is either a socket or a tuple containing the 
-		name and port number of a remote host
-		- proxyaddr: a tuple containing a name and a port number of a 
-		  remote host (optional).
-		- closepartner: boolean, specifies whether we should close
-		  the proxy connection (optional)"""
-		
-		Connection.__init__(self, sock_or_address)
-		self.other = None
-		self.proxyaddr = proxyaddr
-		self.closepartner = closepartner
-	
-	def close(self):
-		if self.other:
-			other = self.other
-			self.other = None
-			other.other = None
-			if self.closepartner:
-				other.close()
-		Connection.close(self)
-	
-	def handle_incoming_data(self, data):
-		if not self.other:
-			# pass data for possible automatic remote host detection
-			# (see HTTPProxy)
-			data = self.connectproxy(data)
-		self.other.send(data)
-	
-	def connectproxy(self, data):
-		other = self.__class__(self.proxyaddr, closepartner=self.closepartner)
-		self.other = other
-		other.other = self
-		return data
+
+    """Generic proxy connection"""
+
+    def __init__(self, sock_or_address=None, proxyaddr=None, closepartner=0):
+        """arguments:
+        - sock_or_address is either a socket or a tuple containing the
+        name and port number of a remote host
+        - proxyaddr: a tuple containing a name and a port number of a
+          remote host (optional).
+        - closepartner: boolean, specifies whether we should close
+          the proxy connection (optional)"""
+
+        Connection.__init__(self, sock_or_address)
+        self.other = None
+        self.proxyaddr = proxyaddr
+        self.closepartner = closepartner
+
+    def close(self):
+        if self.other:
+            other = self.other
+            self.other = None
+            other.other = None
+            if self.closepartner:
+                other.close()
+        Connection.close(self)
+
+    def handle_incoming_data(self, data):
+        if not self.other:
+            # pass data for possible automatic remote host detection
+            # (see HTTPProxy)
+            data = self.connectproxy(data)
+        self.other.send(data)
+
+    def connectproxy(self, data):
+        other = self.__class__(self.proxyaddr, closepartner=self.closepartner)
+        self.other = other
+        other.other = self
+        return data
 
 
 class HTTPProxy(Proxy):
-	
-	"""Simple, useless, http proxy. It figures out itself where to connect to."""
-	
-	def connectproxy(self, data):
-		if VERBOSE:
-			print "--- proxy request", repr(data)
-		addr, data = de_proxify(data)
-		other = Proxy(addr)
-		self.other = other
-		other.other = self
-		return data
+
+    """Simple, useless, http proxy. It figures out itself where to connect to."""
+
+    def connectproxy(self, data):
+        if VERBOSE:
+            print "--- proxy request", repr(data)
+        addr, data = de_proxify(data)
+        other = Proxy(addr)
+        self.other = other
+        other.other = self
+        return data
 
 
 # helper for HTTPProxy
 def de_proxify(data):
-	import re
-	req_pattern = "GET http://([a-zA-Z0-9-_.]+)(:([0-9]+))?"
-	m = re.match(req_pattern, data)
-	host, dummy, port = m.groups()
-	if not port:
-		port = 80
-	else:
-		port = int(port)
-	# change "GET http://xx.xx.xx/yy" into "GET /yy"
-	data = re.sub(req_pattern, "GET ", data)
-	return (host, port), data
+    import re
+    req_pattern = "GET http://([a-zA-Z0-9-_.]+)(:([0-9]+))?"
+    m = re.match(req_pattern, data)
+    host, dummy, port = m.groups()
+    if not port:
+        port = 80
+    else:
+        port = int(port)
+    # change "GET http://xx.xx.xx/yy" into "GET /yy"
+    data = re.sub(req_pattern, "GET ", data)
+    return (host, port), data
 
 
 # if we're running "under W", let's register the socket poller to the event loop
 try:
-	import W
+    import W
 except:
-	pass
+    pass
 else:
-	W.getapplication().addidlefunc(asyncore.poll)
+    W.getapplication().addidlefunc(asyncore.poll)
 
 
 ## testing muck
diff --git a/Mac/Tools/IDE/Wtext.py b/Mac/Tools/IDE/Wtext.py
index 3894e16..b3d2f8e 100644
--- a/Mac/Tools/IDE/Wtext.py
+++ b/Mac/Tools/IDE/Wtext.py
@@ -14,640 +14,640 @@
 
 
 class TextBox(Wbase.Widget):
-	
-	"""A static text widget"""
-	
-	def __init__(self, possize, text="", align=TextEdit.teJustLeft, 
-				fontsettings=None,
-				backgroundcolor=(0xffff, 0xffff, 0xffff)
-				):
-		if fontsettings is None:
-			import W
-			fontsettings = W.getdefaultfont()
-		Wbase.Widget.__init__(self, possize)
-		self.fontsettings = fontsettings
-		self.text = text
-		self.align = align
-		self._backgroundcolor = backgroundcolor
-	
-	def draw(self, visRgn = None):
-		if self._visible:
-			(font, style, size, color) = self.fontsettings
-			fontid = GetFNum(font)
-			savestate = Qd.GetPenState()
-			Qd.TextFont(fontid)
-			Qd.TextFace(style)
-			Qd.TextSize(size)
-			Qd.RGBForeColor(color)
-			Qd.RGBBackColor(self._backgroundcolor)
-			TE.TETextBox(self.text, self._bounds, self.align)
-			Qd.RGBBackColor((0xffff, 0xffff, 0xffff))
-			Qd.SetPenState(savestate)
-	
-	def get(self):
-		return self.text
-	
-	def set(self, text):
-		self.text = text
-		if self._parentwindow and self._parentwindow.wid:
-			self.SetPort()
-			self.draw()
+
+    """A static text widget"""
+
+    def __init__(self, possize, text="", align=TextEdit.teJustLeft,
+                            fontsettings=None,
+                            backgroundcolor=(0xffff, 0xffff, 0xffff)
+                            ):
+        if fontsettings is None:
+            import W
+            fontsettings = W.getdefaultfont()
+        Wbase.Widget.__init__(self, possize)
+        self.fontsettings = fontsettings
+        self.text = text
+        self.align = align
+        self._backgroundcolor = backgroundcolor
+
+    def draw(self, visRgn = None):
+        if self._visible:
+            (font, style, size, color) = self.fontsettings
+            fontid = GetFNum(font)
+            savestate = Qd.GetPenState()
+            Qd.TextFont(fontid)
+            Qd.TextFace(style)
+            Qd.TextSize(size)
+            Qd.RGBForeColor(color)
+            Qd.RGBBackColor(self._backgroundcolor)
+            TE.TETextBox(self.text, self._bounds, self.align)
+            Qd.RGBBackColor((0xffff, 0xffff, 0xffff))
+            Qd.SetPenState(savestate)
+
+    def get(self):
+        return self.text
+
+    def set(self, text):
+        self.text = text
+        if self._parentwindow and self._parentwindow.wid:
+            self.SetPort()
+            self.draw()
 
 
 class _ScrollWidget:
-	
-	# to be overridden
-	def getscrollrects(self):
-		"""Return (destrect, viewrect)."""
-		return None, None
-	
-	# internal method
-	
-	def updatescrollbars(self):
-		(dl, dt, dr, db), (vl, vt, vr, vb) = self.getscrollrects()
-		if self._parent._barx:
-			viewwidth = vr - vl
-			destwidth = dr - dl
-			bar = self._parent._barx
-			bar.setmax(destwidth - viewwidth)
-			
-			# MacOS 8.1 doesn't automatically disable
-			# scrollbars whose max <= min
-			bar.enable(destwidth > viewwidth)
-			
-			bar.setviewsize(viewwidth)
-			bar.set(vl - dl)
-		if self._parent._bary:
-			viewheight = vb - vt
-			destheight = db - dt
-			bar = self._parent._bary
-			bar.setmax(destheight - viewheight)
-			
-			# MacOS 8.1 doesn't automatically disable
-			# scrollbars whose max <= min
-			bar.enable(destheight > viewheight)
-			
-			bar.setviewsize(viewheight)
-			bar.set(vt - dt)
+
+    # to be overridden
+    def getscrollrects(self):
+        """Return (destrect, viewrect)."""
+        return None, None
+
+    # internal method
+
+    def updatescrollbars(self):
+        (dl, dt, dr, db), (vl, vt, vr, vb) = self.getscrollrects()
+        if self._parent._barx:
+            viewwidth = vr - vl
+            destwidth = dr - dl
+            bar = self._parent._barx
+            bar.setmax(destwidth - viewwidth)
+
+            # MacOS 8.1 doesn't automatically disable
+            # scrollbars whose max <= min
+            bar.enable(destwidth > viewwidth)
+
+            bar.setviewsize(viewwidth)
+            bar.set(vl - dl)
+        if self._parent._bary:
+            viewheight = vb - vt
+            destheight = db - dt
+            bar = self._parent._bary
+            bar.setmax(destheight - viewheight)
+
+            # MacOS 8.1 doesn't automatically disable
+            # scrollbars whose max <= min
+            bar.enable(destheight > viewheight)
+
+            bar.setviewsize(viewheight)
+            bar.set(vt - dt)
 
 
-UNDOLABELS = [	# Indexed by WEGetUndoInfo() value
-	None, "", "typing", "Cut", "Paste", "Clear", "Drag", "Style",
-	"Ruler", "backspace", "delete", "transform", "resize"]
+UNDOLABELS = [  # Indexed by WEGetUndoInfo() value
+        None, "", "typing", "Cut", "Paste", "Clear", "Drag", "Style",
+        "Ruler", "backspace", "delete", "transform", "resize"]
 
 
 class EditText(Wbase.SelectableWidget, _ScrollWidget):
-	
-	"""A text edit widget, mainly for simple entry fields."""
-	
-	def __init__(self, possize, text="", 
-				callback=None, inset=(3, 3), 
-				fontsettings=None,
-				tabsettings = (32, 0),
-				readonly = 0):
-		if fontsettings is None:
-			import W
-			fontsettings = W.getdefaultfont()
-		Wbase.SelectableWidget.__init__(self, possize)
-		self.temptext = text
-		self.ted = None
-		self.selection = None
-		self.oldselection = None
-		self._callback = callback
-		self.changed = 0
-		self.selchanged = 0
-		self._selected = 0
-		self._enabled = 1
-		self.wrap = 1
-		self.readonly = readonly
-		self.fontsettings = fontsettings
-		self.tabsettings = tabsettings
-		if type(inset) <> TupleType:
-			self.inset = (inset, inset)
-		else:
-			self.inset = inset
-	
-	def open(self):
-		if not hasattr(self._parent, "_barx"):
-			self._parent._barx = None
-		if not hasattr(self._parent, "_bary"):
-			self._parent._bary = None
-		self._calcbounds()
-		self.SetPort()
-		viewrect, destrect = self._calctextbounds()
-		flags = self._getflags()
-		self.ted = waste.WENew(destrect, viewrect, flags)
-		self.ted.WEInstallTabHooks()
-		self.ted.WESetAlignment(WASTEconst.weFlushLeft)
-		self.setfontsettings(self.fontsettings)
-		self.settabsettings(self.tabsettings)
-		self.ted.WEUseText(Res.Resource(self.temptext))
-		self.ted.WECalText()
-		if self.selection:
-			self.setselection(self.selection[0], self.selection[1])
-			self.selection = None
-		else:
-			self.selview()
-		self.temptext = None
-		self.updatescrollbars()
-		self.bind("pageup", self.scrollpageup)
-		self.bind("pagedown", self.scrollpagedown)
-		self.bind("top", self.scrolltop)
-		self.bind("bottom", self.scrollbottom)
-		self.selchanged = 0
-	
-	def close(self):
-		self._parent._barx = None
-		self._parent._bary = None
-		self.ted = None
-		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
-	
-	def settabsettings(self, (tabsize, tabmode)):
-		self.tabsettings = (tabsize, tabmode)
-		if hasattr(self.ted, "WESetTabSize"):
-			port = self._parentwindow.wid.GetWindowPort()
-			if tabmode:
-				(font, style, size, color) = self.getfontsettings()
-				savesettings = GetPortFontSettings(port)
-				SetPortFontSettings(port, (font, style, size))
-				tabsize = Qd.StringWidth(' ' * tabsize)
-				SetPortFontSettings(port, savesettings)
-			tabsize = max(tabsize, 1)
-			self.ted.WESetTabSize(tabsize)
-			self.SetPort()
-			Qd.EraseRect(self.ted.WEGetViewRect())
-			self.ted.WEUpdate(port.visRgn)
-	
-	def getfontsettings(self):
-		from Carbon import Res
-		(font, style, size, color) = self.ted.WEGetRunInfo(0)[4]
-		font = Fm.GetFontName(font)
-		return (font, style, size, color)
-	
-	def setfontsettings(self, (font, style, size, color)):
-		self.SetPort()
-		if type(font) <> StringType:
-			font = Fm.GetFontName(font)
-		self.fontsettings = (font, style, size, color)
-		fontid = GetFNum(font)
-		readonly = self.ted.WEFeatureFlag(WASTEconst.weFReadOnly, -1)
-		if readonly:
-			self.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 0)
-		try:
-			self.ted.WEFeatureFlag(WASTEconst.weFInhibitRecal, 1)
-			selstart, selend = self.ted.WEGetSelection()
-			self.ted.WESetSelection(0, self.ted.WEGetTextLength())
-			self.ted.WESetStyle(WASTEconst.weDoFace, (0, 0, 0, (0, 0, 0)))
-			self.ted.WESetStyle(WASTEconst.weDoFace | 
-						WASTEconst.weDoColor | 
-						WASTEconst.weDoFont | 
-						WASTEconst.weDoSize, 
-						(fontid, style, size, color))
-			self.ted.WEFeatureFlag(WASTEconst.weFInhibitRecal, 0)
-			self.ted.WECalText()
-			self.ted.WESetSelection(selstart, selend)
-		finally:
-			if readonly:
-				self.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 1)
-		viewrect = self.ted.WEGetViewRect()
-		Qd.EraseRect(viewrect)
-		self.ted.WEUpdate(self._parentwindow.wid.GetWindowPort().visRgn)
-		self.selectionchanged()
-		self.updatescrollbars()
-	
-	def adjust(self, oldbounds):
-		self.SetPort()
-		# Note: if App.DrawThemeEditTextFrame is ever used, it will be necessary
-		# to unconditionally outset the invalidated rectangles, since Appearance
-		# frames are drawn outside the bounds.
-		if self._selected and self._parentwindow._hasselframes:
-			self.GetWindow().InvalWindowRect(Qd.InsetRect(oldbounds, -3, -3))
-			self.GetWindow().InvalWindowRect(Qd.InsetRect(self._bounds, -3, -3))
-		else:
-			self.GetWindow().InvalWindowRect(oldbounds)
-			self.GetWindow().InvalWindowRect(self._bounds)
-		viewrect, destrect = self._calctextbounds()
-		self.ted.WESetViewRect(viewrect)
-		self.ted.WESetDestRect(destrect)
-		if self.wrap:
-			self.ted.WECalText()
-		if self.ted.WEGetDestRect()[3] < viewrect[1]:
-			self.selview()
-		self.updatescrollbars()
-	
-	# interface -----------------------
-	# selection stuff
-	def selview(self):
-		self.ted.WESelView()
-	
-	def selectall(self):
-		self.ted.WESetSelection(0, self.ted.WEGetTextLength())
-		self.selectionchanged()
-		self.updatescrollbars()
-	
-	def selectline(self, lineno, charoffset = 0):
-		newselstart, newselend = self.ted.WEGetLineRange(lineno)
-		# Autoscroll makes the *end* of the selection visible, which, 
-		# in the case of a whole line, is the beginning of the *next* line. 
-		# So sometimes it leaves our line just above the view rect. 
-		# Let's fool Waste by initially selecting one char less:
-		self.ted.WESetSelection(newselstart + charoffset, newselend-1)
-		self.ted.WESetSelection(newselstart + charoffset, newselend)
-		self.selectionchanged()
-		self.updatescrollbars()
-	
-	def getselection(self):
-		if self.ted:
-			return self.ted.WEGetSelection()
-		else:
-			return self.selection
-	
-	def setselection(self, selstart, selend):
-		self.selectionchanged()
-		if self.ted:
-			self.ted.WESetSelection(selstart, selend)
-			self.ted.WESelView()
-			self.updatescrollbars()
-		else:
-			self.selection = selstart, selend
-	
-	def offsettoline(self, offset):
-		return self.ted.WEOffsetToLine(offset)
-	
-	def countlines(self):
-		return self.ted.WECountLines()
-	
-	def getselectedtext(self):
-		selstart, selend = self.ted.WEGetSelection()
-		return self.ted.WEGetText().data[selstart:selend]
-	
-	def expandselection(self):
-		oldselstart, oldselend = self.ted.WEGetSelection()
-		selstart, selend = min(oldselstart, oldselend), max(oldselstart, oldselend)
-		if selstart <> selend and chr(self.ted.WEGetChar(selend-1)) == '\r':
-			selend = selend - 1
-		newselstart, dummy = self.ted.WEFindLine(selstart, 1)
-		dummy, newselend = self.ted.WEFindLine(selend, 1)
-		if oldselstart <> newselstart or  oldselend <> newselend:
-			self.ted.WESetSelection(newselstart, newselend)
-			self.updatescrollbars()
-		self.selectionchanged()
-	
-	def insert(self, text):
-		self.ted.WEInsert(text, None, None)
-		self.textchanged()
-		self.selectionchanged()
-	
-	# text
-	def set(self, text):
-		if not self.ted:
-			self.temptext = text
-		else:
-			self.ted.WEUseText(Res.Resource(text))
-			self.ted.WECalText()
-			self.SetPort()
-			viewrect, destrect = self._calctextbounds()
-			self.ted.WESetViewRect(viewrect)
-			self.ted.WESetDestRect(destrect)
-			rgn = Qd.NewRgn()
-			Qd.RectRgn(rgn, viewrect)
-			Qd.EraseRect(viewrect)
-			self.draw(rgn)
-			self.updatescrollbars()
-			self.textchanged(1)
-	
-	def get(self):
-		if not self._parent:
-			return self.temptext
-		else:
-			return self.ted.WEGetText().data
-	
-	# events
-	def key(self, char, event):
-		(what, message, when, where, modifiers) = event
-		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.textchanged()
-			if char not in Wkeys.scrollkeys:
-				self.selectionchanged()
-			self.updatescrollbars()
-			if self._callback:
-				Wbase.CallbackCall(self._callback, 0, char, modifiers)
-	
-	def click(self, point, modifiers):
-		if not self._enabled:
-			return
-		self.ted.WEClick(point, modifiers, Evt.TickCount())
-		self.selectionchanged()
-		self.updatescrollbars()
-		return 1
-	
-	def idle(self):
-		self.SetPort()
-		self.ted.WEIdle()
-	
-	def rollover(self, point, onoff):
-		if onoff:
-			Wbase.SetCursor("iBeam")
-	
-	def activate(self, onoff):
-		self._activated = onoff
-		if self._visible:
-			self.SetPort()
-			
-			# DISABLED!  There are too many places where it is assumed that
-			# the frame of an EditText item is 1 pixel, inside the bounds.
-			#state = [kThemeStateActive, kThemeStateInactive][not onoff]
-			#App.DrawThemeEditTextFrame(Qd.InsetRect(self._bounds, 1, 1), state)
-			
-			if self._selected:
-				if onoff:
-					self.ted.WEActivate()
-				else:
-					self.ted.WEDeactivate()
-				self.drawselframe(onoff)
-	
-	def select(self, onoff, isclick = 0):
-		if Wbase.SelectableWidget.select(self, onoff):
-			return
-		self.SetPort()
-		if onoff:
-			self.ted.WEActivate()
-			if self._parentwindow._tabbable and not isclick:
-				self.selectall()
-		else:
-			self.ted.WEDeactivate()
-		self.drawselframe(onoff)
-	
-	def draw(self, visRgn = None):
-		if self._visible:
-			if not visRgn:
-				visRgn = self._parentwindow.wid.GetWindowPort().visRgn
-			self.ted.WEUpdate(visRgn)
 
-			# DISABLED!  There are too many places where it is assumed that
-			# the frame of an EditText item is 1 pixel, inside the bounds.
-			#state = [kThemeStateActive, kThemeStateInactive][not self._activated]
-			#App.DrawThemeEditTextFrame(Qd.InsetRect(self._bounds, 1, 1), state)
-			Qd.FrameRect(self._bounds)
+    """A text edit widget, mainly for simple entry fields."""
 
-			if self._selected and self._activated:
-				self.drawselframe(1)
-	
-	# scrolling
-	def scrollpageup(self):
-		if self._parent._bary and self._parent._bary._enabled:
-			self.vscroll("++")
-	
-	def scrollpagedown(self):
-		if self._parent._bary and self._parent._bary._enabled:
-			self.vscroll("--")
-	
-	def scrolltop(self):
-		if self._parent._bary and self._parent._bary._enabled:
-			self.vscroll(self._parent._bary.getmin())
-		if self._parent._barx and self._parent._barx._enabled:
-			self.hscroll(self._parent._barx.getmin())
-	
-	def scrollbottom(self):
-		if self._parent._bary and self._parent._bary._enabled:
-			self.vscroll(self._parent._bary.getmax())
-	
-	# menu handlers
-	def domenu_copy(self, *args):
-		selbegin, selend = self.ted.WEGetSelection()
-		if selbegin == selend:
-			return
-		if hasattr(Scrap, 'ZeroScrap'):
-			Scrap.ZeroScrap()
-		else:
-			Scrap.ClearCurrentScrap()
-		self.ted.WECopy()
-		self.updatescrollbars()
-	
-	def domenu_cut(self, *args):
-		selbegin, selend = self.ted.WEGetSelection()
-		if selbegin == selend:
-			return
-		if hasattr(Scrap, 'ZeroScrap'):
-			Scrap.ZeroScrap()
-		else:
-			Scrap.ClearCurrentScrap()
-		self.ted.WECut()
-		self.updatescrollbars()
-		self.selview()
-		self.textchanged()
-		self.selectionchanged()
-		if self._callback:
-			Wbase.CallbackCall(self._callback, 0, "", None)
-	
-	def domenu_paste(self, *args):
-		if not self.ted.WECanPaste():
-			return
-		self.selview()
-		self.ted.WEPaste()
-		self.updatescrollbars()
-		self.textchanged()
-		self.selectionchanged()
-		if self._callback:
-			Wbase.CallbackCall(self._callback, 0, "", None)
-	
-	def domenu_clear(self, *args):
-		self.ted.WEDelete()
-		self.selview()
-		self.updatescrollbars()
-		self.textchanged()
-		self.selectionchanged()
-		if self._callback:
-			Wbase.CallbackCall(self._callback, 0, "", None)
-	
-	def domenu_undo(self, *args):
-		which, redo = self.ted.WEGetUndoInfo()
-		if not which: 
-			return
-		self.ted.WEUndo()
-		self.updatescrollbars()
-		self.textchanged()
-		self.selectionchanged()
-		if self._callback:
-			Wbase.CallbackCall(self._callback, 0, "", None)
-	
-	def can_undo(self, menuitem):
-		#doundo = self.ted.WEFeatureFlag(WASTEconst.weFUndo, -1)
-		#print doundo
-		#if not doundo:
-		#	return 0
-		which, redo = self.ted.WEGetUndoInfo()
-		if which < len(UNDOLABELS):
-			which = UNDOLABELS[which]
-		else:
-			which = ""
-		if which == None: 
-			return None
-		if redo:
-			which = "Redo "+which
-		else:
-			which = "Undo "+which
-		menuitem.settext(which)
-		return 1
-	
-	def domenu_selectall(self, *args):
-		self.selectall()
-	
-	# private
-	def getscrollrects(self):
-		return self.ted.WEGetDestRect(), self.ted.WEGetViewRect()
-	
-	def vscroll(self, value):
-		lineheight = self.ted.WEGetHeight(0, 1)
-		dr = self.ted.WEGetDestRect()
-		vr = self.ted.WEGetViewRect()
-		viewheight = vr[3] - vr[1]
-		maxdelta = vr[1] - dr[1]
-		mindelta = vr[3] - dr[3]
-		if value == "+":
-			delta = lineheight
-		elif value == "-":
-			delta = - lineheight
-		elif value == "++":
-			delta = viewheight - lineheight
-		elif value == "--":
-			delta = lineheight - viewheight
-		else:	# in thumb
-			delta = vr[1] - dr[1] - value
-		delta = min(maxdelta, delta)
-		delta = max(mindelta, delta)
-		delta = int(delta)
-		self.ted.WEScroll(0, delta)
-		self.updatescrollbars()
-	
-	def hscroll(self, value):
-		dr = self.ted.WEGetDestRect()
-		vr = self.ted.WEGetViewRect()
-		destwidth = dr[2] - dr[0]
-		viewwidth = vr[2] - vr[0]
-		viewoffset = maxdelta = vr[0] - dr[0]
-		mindelta = vr[2] - dr[2]
-		if value == "+":
-			delta = 32
-		elif value == "-":
-			delta = - 32
-		elif value == "++":
-			delta = 0.5 * (vr[2] - vr[0])
-		elif value == "--":
-			delta = 0.5 * (vr[0] - vr[2])
-		else:	# in thumb
-			delta = vr[0] - dr[0] - value
-			#cur = (32767 * viewoffset) / (destwidth - viewwidth)
-			#delta = (cur-value)*(destwidth - viewwidth)/32767
-			#if abs(delta - viewoffset) <=2:
-			#	# compensate for irritating rounding error
-			#	delta = viewoffset
-		delta = min(maxdelta, delta)
-		delta = max(mindelta, delta)
-		delta = int(delta)
-		self.ted.WEScroll(delta, 0)
-		self.updatescrollbars()
-	
-	# some internals
-	def _getflags(self):
-		flags = WASTEconst.weDoAutoScroll | WASTEconst.weDoMonoStyled
-		if self.readonly:
-			flags = flags | WASTEconst.weDoReadOnly
-		else:
-			flags = flags | WASTEconst.weDoUndo
-		return flags
-	
-	def _getviewrect(self):
-		return Qd.InsetRect(self._bounds, self.inset[0], self.inset[1])
-	
-	def _calctextbounds(self):
-		viewrect = l, t, r, b = self._getviewrect()
-		if self.ted:
-			dl, dt, dr, db = self.ted.WEGetDestRect()
-			vl, vt, vr, vb = self.ted.WEGetViewRect()
-			yshift = t - vt
-			if (db - dt) < (b - t):
-				destrect = viewrect
-			else:
-				destrect = l, dt + yshift, r, db + yshift
-		else:
-			destrect = viewrect
-		return viewrect, destrect
-		
+    def __init__(self, possize, text="",
+                            callback=None, inset=(3, 3),
+                            fontsettings=None,
+                            tabsettings = (32, 0),
+                            readonly = 0):
+        if fontsettings is None:
+            import W
+            fontsettings = W.getdefaultfont()
+        Wbase.SelectableWidget.__init__(self, possize)
+        self.temptext = text
+        self.ted = None
+        self.selection = None
+        self.oldselection = None
+        self._callback = callback
+        self.changed = 0
+        self.selchanged = 0
+        self._selected = 0
+        self._enabled = 1
+        self.wrap = 1
+        self.readonly = readonly
+        self.fontsettings = fontsettings
+        self.tabsettings = tabsettings
+        if type(inset) <> TupleType:
+            self.inset = (inset, inset)
+        else:
+            self.inset = inset
+
+    def open(self):
+        if not hasattr(self._parent, "_barx"):
+            self._parent._barx = None
+        if not hasattr(self._parent, "_bary"):
+            self._parent._bary = None
+        self._calcbounds()
+        self.SetPort()
+        viewrect, destrect = self._calctextbounds()
+        flags = self._getflags()
+        self.ted = waste.WENew(destrect, viewrect, flags)
+        self.ted.WEInstallTabHooks()
+        self.ted.WESetAlignment(WASTEconst.weFlushLeft)
+        self.setfontsettings(self.fontsettings)
+        self.settabsettings(self.tabsettings)
+        self.ted.WEUseText(Res.Resource(self.temptext))
+        self.ted.WECalText()
+        if self.selection:
+            self.setselection(self.selection[0], self.selection[1])
+            self.selection = None
+        else:
+            self.selview()
+        self.temptext = None
+        self.updatescrollbars()
+        self.bind("pageup", self.scrollpageup)
+        self.bind("pagedown", self.scrollpagedown)
+        self.bind("top", self.scrolltop)
+        self.bind("bottom", self.scrollbottom)
+        self.selchanged = 0
+
+    def close(self):
+        self._parent._barx = None
+        self._parent._bary = None
+        self.ted = None
+        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
+
+    def settabsettings(self, (tabsize, tabmode)):
+        self.tabsettings = (tabsize, tabmode)
+        if hasattr(self.ted, "WESetTabSize"):
+            port = self._parentwindow.wid.GetWindowPort()
+            if tabmode:
+                (font, style, size, color) = self.getfontsettings()
+                savesettings = GetPortFontSettings(port)
+                SetPortFontSettings(port, (font, style, size))
+                tabsize = Qd.StringWidth(' ' * tabsize)
+                SetPortFontSettings(port, savesettings)
+            tabsize = max(tabsize, 1)
+            self.ted.WESetTabSize(tabsize)
+            self.SetPort()
+            Qd.EraseRect(self.ted.WEGetViewRect())
+            self.ted.WEUpdate(port.visRgn)
+
+    def getfontsettings(self):
+        from Carbon import Res
+        (font, style, size, color) = self.ted.WEGetRunInfo(0)[4]
+        font = Fm.GetFontName(font)
+        return (font, style, size, color)
+
+    def setfontsettings(self, (font, style, size, color)):
+        self.SetPort()
+        if type(font) <> StringType:
+            font = Fm.GetFontName(font)
+        self.fontsettings = (font, style, size, color)
+        fontid = GetFNum(font)
+        readonly = self.ted.WEFeatureFlag(WASTEconst.weFReadOnly, -1)
+        if readonly:
+            self.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 0)
+        try:
+            self.ted.WEFeatureFlag(WASTEconst.weFInhibitRecal, 1)
+            selstart, selend = self.ted.WEGetSelection()
+            self.ted.WESetSelection(0, self.ted.WEGetTextLength())
+            self.ted.WESetStyle(WASTEconst.weDoFace, (0, 0, 0, (0, 0, 0)))
+            self.ted.WESetStyle(WASTEconst.weDoFace |
+                                    WASTEconst.weDoColor |
+                                    WASTEconst.weDoFont |
+                                    WASTEconst.weDoSize,
+                                    (fontid, style, size, color))
+            self.ted.WEFeatureFlag(WASTEconst.weFInhibitRecal, 0)
+            self.ted.WECalText()
+            self.ted.WESetSelection(selstart, selend)
+        finally:
+            if readonly:
+                self.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 1)
+        viewrect = self.ted.WEGetViewRect()
+        Qd.EraseRect(viewrect)
+        self.ted.WEUpdate(self._parentwindow.wid.GetWindowPort().visRgn)
+        self.selectionchanged()
+        self.updatescrollbars()
+
+    def adjust(self, oldbounds):
+        self.SetPort()
+        # Note: if App.DrawThemeEditTextFrame is ever used, it will be necessary
+        # to unconditionally outset the invalidated rectangles, since Appearance
+        # frames are drawn outside the bounds.
+        if self._selected and self._parentwindow._hasselframes:
+            self.GetWindow().InvalWindowRect(Qd.InsetRect(oldbounds, -3, -3))
+            self.GetWindow().InvalWindowRect(Qd.InsetRect(self._bounds, -3, -3))
+        else:
+            self.GetWindow().InvalWindowRect(oldbounds)
+            self.GetWindow().InvalWindowRect(self._bounds)
+        viewrect, destrect = self._calctextbounds()
+        self.ted.WESetViewRect(viewrect)
+        self.ted.WESetDestRect(destrect)
+        if self.wrap:
+            self.ted.WECalText()
+        if self.ted.WEGetDestRect()[3] < viewrect[1]:
+            self.selview()
+        self.updatescrollbars()
+
+    # interface -----------------------
+    # selection stuff
+    def selview(self):
+        self.ted.WESelView()
+
+    def selectall(self):
+        self.ted.WESetSelection(0, self.ted.WEGetTextLength())
+        self.selectionchanged()
+        self.updatescrollbars()
+
+    def selectline(self, lineno, charoffset = 0):
+        newselstart, newselend = self.ted.WEGetLineRange(lineno)
+        # Autoscroll makes the *end* of the selection visible, which,
+        # in the case of a whole line, is the beginning of the *next* line.
+        # So sometimes it leaves our line just above the view rect.
+        # Let's fool Waste by initially selecting one char less:
+        self.ted.WESetSelection(newselstart + charoffset, newselend-1)
+        self.ted.WESetSelection(newselstart + charoffset, newselend)
+        self.selectionchanged()
+        self.updatescrollbars()
+
+    def getselection(self):
+        if self.ted:
+            return self.ted.WEGetSelection()
+        else:
+            return self.selection
+
+    def setselection(self, selstart, selend):
+        self.selectionchanged()
+        if self.ted:
+            self.ted.WESetSelection(selstart, selend)
+            self.ted.WESelView()
+            self.updatescrollbars()
+        else:
+            self.selection = selstart, selend
+
+    def offsettoline(self, offset):
+        return self.ted.WEOffsetToLine(offset)
+
+    def countlines(self):
+        return self.ted.WECountLines()
+
+    def getselectedtext(self):
+        selstart, selend = self.ted.WEGetSelection()
+        return self.ted.WEGetText().data[selstart:selend]
+
+    def expandselection(self):
+        oldselstart, oldselend = self.ted.WEGetSelection()
+        selstart, selend = min(oldselstart, oldselend), max(oldselstart, oldselend)
+        if selstart <> selend and chr(self.ted.WEGetChar(selend-1)) == '\r':
+            selend = selend - 1
+        newselstart, dummy = self.ted.WEFindLine(selstart, 1)
+        dummy, newselend = self.ted.WEFindLine(selend, 1)
+        if oldselstart <> newselstart or  oldselend <> newselend:
+            self.ted.WESetSelection(newselstart, newselend)
+            self.updatescrollbars()
+        self.selectionchanged()
+
+    def insert(self, text):
+        self.ted.WEInsert(text, None, None)
+        self.textchanged()
+        self.selectionchanged()
+
+    # text
+    def set(self, text):
+        if not self.ted:
+            self.temptext = text
+        else:
+            self.ted.WEUseText(Res.Resource(text))
+            self.ted.WECalText()
+            self.SetPort()
+            viewrect, destrect = self._calctextbounds()
+            self.ted.WESetViewRect(viewrect)
+            self.ted.WESetDestRect(destrect)
+            rgn = Qd.NewRgn()
+            Qd.RectRgn(rgn, viewrect)
+            Qd.EraseRect(viewrect)
+            self.draw(rgn)
+            self.updatescrollbars()
+            self.textchanged(1)
+
+    def get(self):
+        if not self._parent:
+            return self.temptext
+        else:
+            return self.ted.WEGetText().data
+
+    # events
+    def key(self, char, event):
+        (what, message, when, where, modifiers) = event
+        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.textchanged()
+            if char not in Wkeys.scrollkeys:
+                self.selectionchanged()
+            self.updatescrollbars()
+            if self._callback:
+                Wbase.CallbackCall(self._callback, 0, char, modifiers)
+
+    def click(self, point, modifiers):
+        if not self._enabled:
+            return
+        self.ted.WEClick(point, modifiers, Evt.TickCount())
+        self.selectionchanged()
+        self.updatescrollbars()
+        return 1
+
+    def idle(self):
+        self.SetPort()
+        self.ted.WEIdle()
+
+    def rollover(self, point, onoff):
+        if onoff:
+            Wbase.SetCursor("iBeam")
+
+    def activate(self, onoff):
+        self._activated = onoff
+        if self._visible:
+            self.SetPort()
+
+            # DISABLED!  There are too many places where it is assumed that
+            # the frame of an EditText item is 1 pixel, inside the bounds.
+            #state = [kThemeStateActive, kThemeStateInactive][not onoff]
+            #App.DrawThemeEditTextFrame(Qd.InsetRect(self._bounds, 1, 1), state)
+
+            if self._selected:
+                if onoff:
+                    self.ted.WEActivate()
+                else:
+                    self.ted.WEDeactivate()
+                self.drawselframe(onoff)
+
+    def select(self, onoff, isclick = 0):
+        if Wbase.SelectableWidget.select(self, onoff):
+            return
+        self.SetPort()
+        if onoff:
+            self.ted.WEActivate()
+            if self._parentwindow._tabbable and not isclick:
+                self.selectall()
+        else:
+            self.ted.WEDeactivate()
+        self.drawselframe(onoff)
+
+    def draw(self, visRgn = None):
+        if self._visible:
+            if not visRgn:
+                visRgn = self._parentwindow.wid.GetWindowPort().visRgn
+            self.ted.WEUpdate(visRgn)
+
+            # DISABLED!  There are too many places where it is assumed that
+            # the frame of an EditText item is 1 pixel, inside the bounds.
+            #state = [kThemeStateActive, kThemeStateInactive][not self._activated]
+            #App.DrawThemeEditTextFrame(Qd.InsetRect(self._bounds, 1, 1), state)
+            Qd.FrameRect(self._bounds)
+
+            if self._selected and self._activated:
+                self.drawselframe(1)
+
+    # scrolling
+    def scrollpageup(self):
+        if self._parent._bary and self._parent._bary._enabled:
+            self.vscroll("++")
+
+    def scrollpagedown(self):
+        if self._parent._bary and self._parent._bary._enabled:
+            self.vscroll("--")
+
+    def scrolltop(self):
+        if self._parent._bary and self._parent._bary._enabled:
+            self.vscroll(self._parent._bary.getmin())
+        if self._parent._barx and self._parent._barx._enabled:
+            self.hscroll(self._parent._barx.getmin())
+
+    def scrollbottom(self):
+        if self._parent._bary and self._parent._bary._enabled:
+            self.vscroll(self._parent._bary.getmax())
+
+    # menu handlers
+    def domenu_copy(self, *args):
+        selbegin, selend = self.ted.WEGetSelection()
+        if selbegin == selend:
+            return
+        if hasattr(Scrap, 'ZeroScrap'):
+            Scrap.ZeroScrap()
+        else:
+            Scrap.ClearCurrentScrap()
+        self.ted.WECopy()
+        self.updatescrollbars()
+
+    def domenu_cut(self, *args):
+        selbegin, selend = self.ted.WEGetSelection()
+        if selbegin == selend:
+            return
+        if hasattr(Scrap, 'ZeroScrap'):
+            Scrap.ZeroScrap()
+        else:
+            Scrap.ClearCurrentScrap()
+        self.ted.WECut()
+        self.updatescrollbars()
+        self.selview()
+        self.textchanged()
+        self.selectionchanged()
+        if self._callback:
+            Wbase.CallbackCall(self._callback, 0, "", None)
+
+    def domenu_paste(self, *args):
+        if not self.ted.WECanPaste():
+            return
+        self.selview()
+        self.ted.WEPaste()
+        self.updatescrollbars()
+        self.textchanged()
+        self.selectionchanged()
+        if self._callback:
+            Wbase.CallbackCall(self._callback, 0, "", None)
+
+    def domenu_clear(self, *args):
+        self.ted.WEDelete()
+        self.selview()
+        self.updatescrollbars()
+        self.textchanged()
+        self.selectionchanged()
+        if self._callback:
+            Wbase.CallbackCall(self._callback, 0, "", None)
+
+    def domenu_undo(self, *args):
+        which, redo = self.ted.WEGetUndoInfo()
+        if not which:
+            return
+        self.ted.WEUndo()
+        self.updatescrollbars()
+        self.textchanged()
+        self.selectionchanged()
+        if self._callback:
+            Wbase.CallbackCall(self._callback, 0, "", None)
+
+    def can_undo(self, menuitem):
+        #doundo = self.ted.WEFeatureFlag(WASTEconst.weFUndo, -1)
+        #print doundo
+        #if not doundo:
+        #       return 0
+        which, redo = self.ted.WEGetUndoInfo()
+        if which < len(UNDOLABELS):
+            which = UNDOLABELS[which]
+        else:
+            which = ""
+        if which == None:
+            return None
+        if redo:
+            which = "Redo "+which
+        else:
+            which = "Undo "+which
+        menuitem.settext(which)
+        return 1
+
+    def domenu_selectall(self, *args):
+        self.selectall()
+
+    # private
+    def getscrollrects(self):
+        return self.ted.WEGetDestRect(), self.ted.WEGetViewRect()
+
+    def vscroll(self, value):
+        lineheight = self.ted.WEGetHeight(0, 1)
+        dr = self.ted.WEGetDestRect()
+        vr = self.ted.WEGetViewRect()
+        viewheight = vr[3] - vr[1]
+        maxdelta = vr[1] - dr[1]
+        mindelta = vr[3] - dr[3]
+        if value == "+":
+            delta = lineheight
+        elif value == "-":
+            delta = - lineheight
+        elif value == "++":
+            delta = viewheight - lineheight
+        elif value == "--":
+            delta = lineheight - viewheight
+        else:   # in thumb
+            delta = vr[1] - dr[1] - value
+        delta = min(maxdelta, delta)
+        delta = max(mindelta, delta)
+        delta = int(delta)
+        self.ted.WEScroll(0, delta)
+        self.updatescrollbars()
+
+    def hscroll(self, value):
+        dr = self.ted.WEGetDestRect()
+        vr = self.ted.WEGetViewRect()
+        destwidth = dr[2] - dr[0]
+        viewwidth = vr[2] - vr[0]
+        viewoffset = maxdelta = vr[0] - dr[0]
+        mindelta = vr[2] - dr[2]
+        if value == "+":
+            delta = 32
+        elif value == "-":
+            delta = - 32
+        elif value == "++":
+            delta = 0.5 * (vr[2] - vr[0])
+        elif value == "--":
+            delta = 0.5 * (vr[0] - vr[2])
+        else:   # in thumb
+            delta = vr[0] - dr[0] - value
+            #cur = (32767 * viewoffset) / (destwidth - viewwidth)
+            #delta = (cur-value)*(destwidth - viewwidth)/32767
+            #if abs(delta - viewoffset) <=2:
+            #       # compensate for irritating rounding error
+            #       delta = viewoffset
+        delta = min(maxdelta, delta)
+        delta = max(mindelta, delta)
+        delta = int(delta)
+        self.ted.WEScroll(delta, 0)
+        self.updatescrollbars()
+
+    # some internals
+    def _getflags(self):
+        flags = WASTEconst.weDoAutoScroll | WASTEconst.weDoMonoStyled
+        if self.readonly:
+            flags = flags | WASTEconst.weDoReadOnly
+        else:
+            flags = flags | WASTEconst.weDoUndo
+        return flags
+
+    def _getviewrect(self):
+        return Qd.InsetRect(self._bounds, self.inset[0], self.inset[1])
+
+    def _calctextbounds(self):
+        viewrect = l, t, r, b = self._getviewrect()
+        if self.ted:
+            dl, dt, dr, db = self.ted.WEGetDestRect()
+            vl, vt, vr, vb = self.ted.WEGetViewRect()
+            yshift = t - vt
+            if (db - dt) < (b - t):
+                destrect = viewrect
+            else:
+                destrect = l, dt + yshift, r, db + yshift
+        else:
+            destrect = viewrect
+        return viewrect, destrect
+
 
 class TextEditor(EditText):
-	
-	"""A text edit widget."""
-	
-	def __init__(self, possize, text="", callback=None, wrap=1, inset=(4, 4),
-				fontsettings=None,
-				tabsettings=(32, 0),
-				readonly=0):
-		EditText.__init__(self, possize, text, callback, inset, fontsettings, tabsettings, readonly)
-		self.wrap = wrap
-	
-	def _getflags(self):
-		flags = WASTEconst.weDoAutoScroll | WASTEconst.weDoMonoStyled | \
-				WASTEconst.weDoOutlineHilite
-		if self.readonly:
-			flags = flags | WASTEconst.weDoReadOnly
-		else:
-			flags = flags | WASTEconst.weDoUndo
-		return flags
-	
-	def _getviewrect(self):
-		l, t, r, b = self._bounds
-		return (l + 5, t + 2, r, b - 2)
-	
-	def _calctextbounds(self):
-		if self.wrap:
-			return EditText._calctextbounds(self)
-		else:
-			viewrect = l, t, r, b = self._getviewrect()
-			if self.ted:
-				dl, dt, dr, db = self.ted.WEGetDestRect()
-				vl, vt, vr, vb = self.ted.WEGetViewRect()
-				xshift = l - vl
-				yshift = t - vt
-				if (db - dt) < (b - t):
-					yshift = t - dt
-				destrect = (dl + xshift, dt + yshift, dr + xshift, db + yshift)
-			else:
-				destrect = (l, t, r + 5000, b)
-			return viewrect, destrect
-	
-	def draw(self, visRgn = None):
-		if self._visible:
-			if not visRgn:
-				visRgn = self._parentwindow.wid.GetWindowPort().visRgn
-			self.ted.WEUpdate(visRgn)
-			if self._selected and self._activated:
-				self.drawselframe(1)
 
-	def activate(self, onoff):
-		self._activated = onoff
-		if self._visible:
-			self.SetPort()
-			# doesn't draw frame, as EditText.activate does
-			if self._selected:
-				if onoff:
-					self.ted.WEActivate()
-				else:
-					self.ted.WEDeactivate()
-				self.drawselframe(onoff)
+    """A text edit widget."""
+
+    def __init__(self, possize, text="", callback=None, wrap=1, inset=(4, 4),
+                            fontsettings=None,
+                            tabsettings=(32, 0),
+                            readonly=0):
+        EditText.__init__(self, possize, text, callback, inset, fontsettings, tabsettings, readonly)
+        self.wrap = wrap
+
+    def _getflags(self):
+        flags = WASTEconst.weDoAutoScroll | WASTEconst.weDoMonoStyled | \
+                        WASTEconst.weDoOutlineHilite
+        if self.readonly:
+            flags = flags | WASTEconst.weDoReadOnly
+        else:
+            flags = flags | WASTEconst.weDoUndo
+        return flags
+
+    def _getviewrect(self):
+        l, t, r, b = self._bounds
+        return (l + 5, t + 2, r, b - 2)
+
+    def _calctextbounds(self):
+        if self.wrap:
+            return EditText._calctextbounds(self)
+        else:
+            viewrect = l, t, r, b = self._getviewrect()
+            if self.ted:
+                dl, dt, dr, db = self.ted.WEGetDestRect()
+                vl, vt, vr, vb = self.ted.WEGetViewRect()
+                xshift = l - vl
+                yshift = t - vt
+                if (db - dt) < (b - t):
+                    yshift = t - dt
+                destrect = (dl + xshift, dt + yshift, dr + xshift, db + yshift)
+            else:
+                destrect = (l, t, r + 5000, b)
+            return viewrect, destrect
+
+    def draw(self, visRgn = None):
+        if self._visible:
+            if not visRgn:
+                visRgn = self._parentwindow.wid.GetWindowPort().visRgn
+            self.ted.WEUpdate(visRgn)
+            if self._selected and self._activated:
+                self.drawselframe(1)
+
+    def activate(self, onoff):
+        self._activated = onoff
+        if self._visible:
+            self.SetPort()
+            # doesn't draw frame, as EditText.activate does
+            if self._selected:
+                if onoff:
+                    self.ted.WEActivate()
+                else:
+                    self.ted.WEDeactivate()
+                self.drawselframe(onoff)
 
 
 import re
@@ -658,479 +658,479 @@
 
 
 class PyEditor(TextEditor):
-	
-	"""A specialized Python source edit widget"""
-	
-	def __init__(self, possize, text="", callback=None, inset=(4, 4),
-				fontsettings=None,
-				tabsettings=(32, 0),
-				readonly=0,
-				debugger=None,
-				file=''):
-		TextEditor.__init__(self, possize, text, callback, 0, inset, fontsettings, tabsettings, readonly)
-		self.bind("cmd[", self.domenu_shiftleft)
-		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()
-		selstart, selend = self.ted.WEGetSelection()
-		selstart, selend = min(selstart, selend), max(selstart, selend)
-		snippet = self.getselectedtext()
-		lines = string.split(snippet, '\r')
-		for i in range(len(lines)):
-			if lines[i][:1] == '\t':
-				lines[i] = lines[i][1:]
-		snippet = string.join(lines, '\r')
-		self.insert(snippet)
-		self.ted.WESetSelection(selstart, selstart + len(snippet))
-	
-	def domenu_shiftright(self):
-		self.expandselection()
-		selstart, selend = self.ted.WEGetSelection()
-		selstart, selend = min(selstart, selend), max(selstart, selend)
-		snippet = self.getselectedtext()
-		lines = string.split(snippet, '\r')
-		for i in range(len(lines) - (not lines[-1])):
-			lines[i] = '\t' + lines[i]
-		snippet = string.join(lines, '\r')
-		self.insert(snippet)
-		self.ted.WESetSelection(selstart, selstart + len(snippet))
-	
-	def domenu_uncomment(self):
-		self.expandselection()
-		selstart, selend = self.ted.WEGetSelection()
-		selstart, selend = min(selstart, selend), max(selstart, selend)
-		snippet = self.getselectedtext()
-		lines = string.split(snippet, '\r')
-		for i in range(len(lines)):
-			m = commentPat.match(lines[i])
-			if m:
-				pos = m.start(1)
-				lines[i] = lines[i][:pos] + lines[i][pos+1:]
-		snippet = string.join(lines, '\r')
-		self.insert(snippet)
-		self.ted.WESetSelection(selstart, selstart + len(snippet))
-	
-	def domenu_comment(self):
-		self.expandselection()
-		selstart, selend = self.ted.WEGetSelection()
-		selstart, selend = min(selstart, selend), max(selstart, selend)
-		snippet = self.getselectedtext()
-		lines = string.split(snippet, '\r')
-		indent = 3000 # arbitrary large number...
-		for line in lines:
-			if string.strip(line):
-				m = indentPat.match(line)
-				if m:
-					indent = min(indent, m.regs[0][1])
-				else:
-					indent = 0
-					break
-		for i in range(len(lines) - (not lines[-1])):
-			lines[i] = lines[i][:indent] + "#" + lines[i][indent:]
-		snippet = string.join(lines, '\r')
-		self.insert(snippet)
-		self.ted.WESetSelection(selstart, selstart + len(snippet))
-	
-	def setfile(self, file):
-		self.file = file
-	
-	def set(self, text, file = ''):
-		oldfile = self.file
-		self.file = file
-		if self._debugger:
-			self._debugger.unregister_editor(self, oldfile)
-			self._debugger.register_editor(self, file)
-		TextEditor.set(self, text)
-	
-	def close(self):
-		if self._debugger:
-			self._debugger.unregister_editor(self, self.file)
-			self._debugger = None
-		TextEditor.close(self)		
-	
-	def click(self, point, modifiers):
-		if not self._enabled:
-			return
-		if self._debugger and self.pt_in_breaks(point):
-			self.breakhit(point, modifiers)
-		elif self._debugger:
-			bl, bt, br, bb = self._getbreakrect()
-			Qd.EraseRect((bl, bt, br-1, bb))
-			TextEditor.click(self, point, modifiers)
-			self.drawbreakpoints()
-		else:
-			TextEditor.click(self, point, modifiers)
-			if self.ted.WEGetClickCount() >= 3:
-				# select block with our indent
-				lines = string.split(self.get(), '\r')
-				selstart, selend = self.ted.WEGetSelection()
-				lineno = self.ted.WEOffsetToLine(selstart)
-				tabs = 0
-				line = lines[lineno]
-				while line[tabs:] and line[tabs] == '\t':
-					tabs = tabs + 1
-				tabstag = '\t' * tabs
-				fromline = 0
-				toline = len(lines)
-				if tabs:
-					for i in range(lineno - 1, -1, -1):
-						line = lines[i]
-						if line[:tabs] <> tabstag:
-							fromline = i + 1
-							break
-					for i in range(lineno + 1, toline):
-						line = lines[i]
-						if line[:tabs] <> tabstag:
-							toline = i - 1
-							break
-				selstart, dummy = self.ted.WEGetLineRange(fromline)
-				dummy, selend = self.ted.WEGetLineRange(toline)
-				self.ted.WESetSelection(selstart, selend)
-	
-	def breakhit(self, point, modifiers):
-		if not self.file:
-			return
-		destrect = self.ted.WEGetDestRect()
-		offset, edge = self.ted.WEGetOffset(point)
-		lineno = self.ted.WEOffsetToLine(offset) + 1
-		if point[1] <= destrect[3]:
-			self._debugger.clear_breaks_above(self.file, self.countlines())
-			self._debugger.toggle_break(self.file, lineno)
-		else:
-			self._debugger.clear_breaks_above(self.file, lineno)
-	
-	def key(self, char, event):
-		(what, message, when, where, modifiers) = event
-		if modifiers & Events.cmdKey and not char in Wkeys.arrowkeys:
-			return
-		if char == '\r':
-			selstart, selend = self.ted.WEGetSelection()
-			selstart, selend = min(selstart, selend), max(selstart, selend)
-			lastchar = chr(self.ted.WEGetChar(selstart-1))
-			if lastchar <> '\r' and selstart:
-				pos, dummy = self.ted.WEFindLine(selstart, 0)
-				lineres = Res.Resource('')
-				self.ted.WECopyRange(pos, selstart, lineres, None, None)
-				line = lineres.data + '\n'
-				tabcount = self.extratabs(line)
-				self.ted.WEKey(ord('\r'), 0)
-				for i in range(tabcount):
-					self.ted.WEKey(ord('\t'), 0)
-			else:
-				self.ted.WEKey(ord('\r'), 0)
-		elif char in ')]}':
-			self.ted.WEKey(ord(char), modifiers)
-			self.balanceparens(char)
-		else:
-			self.ted.WEKey(ord(char), modifiers)
-		if char not in Wkeys.navigationkeys:
-			self.textchanged()
-		self.selectionchanged()
-		self.updatescrollbars()
-	
-	def balanceparens(self, char):
-		if char == ')':
-			target = '('
-		elif char == ']':
-			target = '['
-		elif char == '}':
-			target = '{'
-		recursionlevel = 1
-		selstart, selend = self.ted.WEGetSelection()
-		count = min(selstart, selend) - 2
-		mincount = max(0, count - 2048)
-		lastquote = None
-		while count > mincount:
-			testchar = chr(self.ted.WEGetChar(count))
-			if testchar in "\"'" and chr(self.ted.WEGetChar(count - 1)) <> '\\':
-				if lastquote == testchar:
-					recursionlevel = recursionlevel - 1
-					lastquote = None
-				elif not lastquote:
-					recursionlevel = recursionlevel + 1
-					lastquote = testchar
-			elif not lastquote and testchar == char:
-				recursionlevel = recursionlevel + 1
-			elif not lastquote and testchar == target:
-				recursionlevel = recursionlevel - 1
-				if recursionlevel == 0:
-					import time
-					autoscroll = self.ted.WEFeatureFlag(WASTEconst.weFAutoScroll, -1)
-					if autoscroll:
-						self.ted.WEFeatureFlag(WASTEconst.weFAutoScroll, 0)
-					self.ted.WESetSelection(count, count + 1)
-					self._parentwindow.wid.GetWindowPort().QDFlushPortBuffer(None)  # needed under OSX
-					time.sleep(0.2)
-					self.ted.WESetSelection(selstart, selend)
-					if autoscroll:
-						self.ted.WEFeatureFlag(WASTEconst.weFAutoScroll, 1)
-					break
-			count = count - 1
-	
-	def extratabs(self, line):
-		tabcount = 0
-		for c in line:
-			if c <> '\t':
-				break
-			tabcount = tabcount + 1
-		last = 0
-		cleanline = ''
-		tags = PyFontify.fontify(line)
-		# strip comments and strings
-		for tag, start, end, sublist in tags:
-			if tag in ('string', 'comment'):
-				cleanline = cleanline + line[last:start]
-				last = end
-		cleanline = cleanline + line[last:]
-		cleanline = string.strip(cleanline)
-		if cleanline and cleanline[-1] == ':':
-			tabcount = tabcount + 1
-		else:
-			# extra indent after unbalanced (, [ or {
-			for open, close in (('(', ')'), ('[', ']'), ('{', '}')):
-				count = string.count(cleanline, open)
-				if count and count > string.count(cleanline, close):
-					tabcount = tabcount + 2
-					break
-		return tabcount
-	
-	def rollover(self, point, onoff):
-		if onoff:
-			if self._debugger and self.pt_in_breaks(point):
-				Wbase.SetCursor("arrow")
-			else:
-				Wbase.SetCursor("iBeam")
-	
-	def draw(self, visRgn = None):
-		TextEditor.draw(self, visRgn)
-		if self._debugger:
-			self.drawbreakpoints()
-	
-	def showbreakpoints(self, onoff):
-		if (not not self._debugger) <> onoff:
-			if onoff:
-				if not __debug__:
-					import W
-					raise W.AlertError, "Can't debug in \"Optimize bytecode\" mode.\r(see \"Default startup options\" in EditPythonPreferences)"
-				import PyDebugger
-				self._debugger = PyDebugger.getdebugger()
-				self._debugger.register_editor(self, self.file)
-			elif self._debugger:
-				self._debugger.unregister_editor(self, self.file)
-				self._debugger = None
-			self.adjust(self._bounds)
-	
-	def togglebreakpoints(self):
-		self.showbreakpoints(not self._debugger)
-	
-	def clearbreakpoints(self):
-		if self.file:
-			self._debugger.clear_all_file_breaks(self.file)
-	
-	def editbreakpoints(self):
-		if self._debugger:
-			self._debugger.edit_breaks()
-			self._debugger.breaksviewer.selectfile(self.file)
-	
-	def drawbreakpoints(self, eraseall = 0):
-		breakrect = bl, bt, br, bb = self._getbreakrect()
-		br = br - 1
-		self.SetPort()
-		Qd.PenPat(Qd.GetQDGlobalsGray())
-		Qd.PaintRect((br, bt, br + 1, bb))
-		Qd.PenNormal()
-		self._parentwindow.tempcliprect(breakrect)
-		Qd.RGBForeColor((0xffff, 0, 0))
-		try:
-			lasttop = bt
-			self_ted = self.ted
-			Qd_PaintOval = Qd.PaintOval
-			Qd_EraseRect = Qd.EraseRect
-			for lineno in self._debugger.get_file_breaks(self.file):
-				start, end = self_ted.WEGetLineRange(lineno - 1)
-				if lineno <> self_ted.WEOffsetToLine(start) + 1:
-					# breakpoints beyond our text: erase rest, and back out
-					Qd_EraseRect((bl, lasttop, br, bb))
-					break
-				(x, y), h = self_ted.WEGetPoint(start, 0)
-				bottom = y + h
-				#print y, (lasttop, bottom)
-				if bottom > lasttop:
-					Qd_EraseRect((bl, lasttop, br, y + h * eraseall))
-					lasttop = bottom
-				redbullet = bl + 2, y + 3, bl + 8, y + 9
-				Qd_PaintOval(redbullet)
-			else:
-				Qd_EraseRect((bl, lasttop, br, bb))
-			Qd.RGBForeColor((0, 0, 0))
-		finally:
-			self._parentwindow.restoreclip()
-	
-	def updatescrollbars(self):
-		if self._debugger:
-			self.drawbreakpoints(1)
-		TextEditor.updatescrollbars(self)
-	
-	def pt_in_breaks(self, point):
-		return Qd.PtInRect(point, self._getbreakrect())
-	
-	def _getbreakrect(self):
-		if self._debugger:
-			l, t, r, b = self._bounds
-			return (l+1, t+1, l + 12, b-1)
-		else:
-			return (0, 0, 0, 0)
-	
-	def _getviewrect(self):
-		l, t, r, b = self._bounds
-		if self._debugger:
-			return (l + 17, t + 2, r, b - 2)
-		else:
-			return (l + 5, t + 2, r, b - 2)
-	
-	def _calctextbounds(self):
-		viewrect = l, t, r, b = self._getviewrect()
-		if self.ted:
-			dl, dt, dr, db = self.ted.WEGetDestRect()
-			vl, vt, vr, vb = self.ted.WEGetViewRect()
-			xshift = l - vl
-			yshift = t - vt
-			if (db - dt) < (b - t):
-				yshift = t - dt
-			destrect = (dl + xshift, dt + yshift, dr + xshift, db + yshift)
-		else:
-			destrect = (l, t, r + 5000, b)
-		return viewrect, destrect
+
+    """A specialized Python source edit widget"""
+
+    def __init__(self, possize, text="", callback=None, inset=(4, 4),
+                            fontsettings=None,
+                            tabsettings=(32, 0),
+                            readonly=0,
+                            debugger=None,
+                            file=''):
+        TextEditor.__init__(self, possize, text, callback, 0, inset, fontsettings, tabsettings, readonly)
+        self.bind("cmd[", self.domenu_shiftleft)
+        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()
+        selstart, selend = self.ted.WEGetSelection()
+        selstart, selend = min(selstart, selend), max(selstart, selend)
+        snippet = self.getselectedtext()
+        lines = string.split(snippet, '\r')
+        for i in range(len(lines)):
+            if lines[i][:1] == '\t':
+                lines[i] = lines[i][1:]
+        snippet = string.join(lines, '\r')
+        self.insert(snippet)
+        self.ted.WESetSelection(selstart, selstart + len(snippet))
+
+    def domenu_shiftright(self):
+        self.expandselection()
+        selstart, selend = self.ted.WEGetSelection()
+        selstart, selend = min(selstart, selend), max(selstart, selend)
+        snippet = self.getselectedtext()
+        lines = string.split(snippet, '\r')
+        for i in range(len(lines) - (not lines[-1])):
+            lines[i] = '\t' + lines[i]
+        snippet = string.join(lines, '\r')
+        self.insert(snippet)
+        self.ted.WESetSelection(selstart, selstart + len(snippet))
+
+    def domenu_uncomment(self):
+        self.expandselection()
+        selstart, selend = self.ted.WEGetSelection()
+        selstart, selend = min(selstart, selend), max(selstart, selend)
+        snippet = self.getselectedtext()
+        lines = string.split(snippet, '\r')
+        for i in range(len(lines)):
+            m = commentPat.match(lines[i])
+            if m:
+                pos = m.start(1)
+                lines[i] = lines[i][:pos] + lines[i][pos+1:]
+        snippet = string.join(lines, '\r')
+        self.insert(snippet)
+        self.ted.WESetSelection(selstart, selstart + len(snippet))
+
+    def domenu_comment(self):
+        self.expandselection()
+        selstart, selend = self.ted.WEGetSelection()
+        selstart, selend = min(selstart, selend), max(selstart, selend)
+        snippet = self.getselectedtext()
+        lines = string.split(snippet, '\r')
+        indent = 3000 # arbitrary large number...
+        for line in lines:
+            if string.strip(line):
+                m = indentPat.match(line)
+                if m:
+                    indent = min(indent, m.regs[0][1])
+                else:
+                    indent = 0
+                    break
+        for i in range(len(lines) - (not lines[-1])):
+            lines[i] = lines[i][:indent] + "#" + lines[i][indent:]
+        snippet = string.join(lines, '\r')
+        self.insert(snippet)
+        self.ted.WESetSelection(selstart, selstart + len(snippet))
+
+    def setfile(self, file):
+        self.file = file
+
+    def set(self, text, file = ''):
+        oldfile = self.file
+        self.file = file
+        if self._debugger:
+            self._debugger.unregister_editor(self, oldfile)
+            self._debugger.register_editor(self, file)
+        TextEditor.set(self, text)
+
+    def close(self):
+        if self._debugger:
+            self._debugger.unregister_editor(self, self.file)
+            self._debugger = None
+        TextEditor.close(self)
+
+    def click(self, point, modifiers):
+        if not self._enabled:
+            return
+        if self._debugger and self.pt_in_breaks(point):
+            self.breakhit(point, modifiers)
+        elif self._debugger:
+            bl, bt, br, bb = self._getbreakrect()
+            Qd.EraseRect((bl, bt, br-1, bb))
+            TextEditor.click(self, point, modifiers)
+            self.drawbreakpoints()
+        else:
+            TextEditor.click(self, point, modifiers)
+            if self.ted.WEGetClickCount() >= 3:
+                # select block with our indent
+                lines = string.split(self.get(), '\r')
+                selstart, selend = self.ted.WEGetSelection()
+                lineno = self.ted.WEOffsetToLine(selstart)
+                tabs = 0
+                line = lines[lineno]
+                while line[tabs:] and line[tabs] == '\t':
+                    tabs = tabs + 1
+                tabstag = '\t' * tabs
+                fromline = 0
+                toline = len(lines)
+                if tabs:
+                    for i in range(lineno - 1, -1, -1):
+                        line = lines[i]
+                        if line[:tabs] <> tabstag:
+                            fromline = i + 1
+                            break
+                    for i in range(lineno + 1, toline):
+                        line = lines[i]
+                        if line[:tabs] <> tabstag:
+                            toline = i - 1
+                            break
+                selstart, dummy = self.ted.WEGetLineRange(fromline)
+                dummy, selend = self.ted.WEGetLineRange(toline)
+                self.ted.WESetSelection(selstart, selend)
+
+    def breakhit(self, point, modifiers):
+        if not self.file:
+            return
+        destrect = self.ted.WEGetDestRect()
+        offset, edge = self.ted.WEGetOffset(point)
+        lineno = self.ted.WEOffsetToLine(offset) + 1
+        if point[1] <= destrect[3]:
+            self._debugger.clear_breaks_above(self.file, self.countlines())
+            self._debugger.toggle_break(self.file, lineno)
+        else:
+            self._debugger.clear_breaks_above(self.file, lineno)
+
+    def key(self, char, event):
+        (what, message, when, where, modifiers) = event
+        if modifiers & Events.cmdKey and not char in Wkeys.arrowkeys:
+            return
+        if char == '\r':
+            selstart, selend = self.ted.WEGetSelection()
+            selstart, selend = min(selstart, selend), max(selstart, selend)
+            lastchar = chr(self.ted.WEGetChar(selstart-1))
+            if lastchar <> '\r' and selstart:
+                pos, dummy = self.ted.WEFindLine(selstart, 0)
+                lineres = Res.Resource('')
+                self.ted.WECopyRange(pos, selstart, lineres, None, None)
+                line = lineres.data + '\n'
+                tabcount = self.extratabs(line)
+                self.ted.WEKey(ord('\r'), 0)
+                for i in range(tabcount):
+                    self.ted.WEKey(ord('\t'), 0)
+            else:
+                self.ted.WEKey(ord('\r'), 0)
+        elif char in ')]}':
+            self.ted.WEKey(ord(char), modifiers)
+            self.balanceparens(char)
+        else:
+            self.ted.WEKey(ord(char), modifiers)
+        if char not in Wkeys.navigationkeys:
+            self.textchanged()
+        self.selectionchanged()
+        self.updatescrollbars()
+
+    def balanceparens(self, char):
+        if char == ')':
+            target = '('
+        elif char == ']':
+            target = '['
+        elif char == '}':
+            target = '{'
+        recursionlevel = 1
+        selstart, selend = self.ted.WEGetSelection()
+        count = min(selstart, selend) - 2
+        mincount = max(0, count - 2048)
+        lastquote = None
+        while count > mincount:
+            testchar = chr(self.ted.WEGetChar(count))
+            if testchar in "\"'" and chr(self.ted.WEGetChar(count - 1)) <> '\\':
+                if lastquote == testchar:
+                    recursionlevel = recursionlevel - 1
+                    lastquote = None
+                elif not lastquote:
+                    recursionlevel = recursionlevel + 1
+                    lastquote = testchar
+            elif not lastquote and testchar == char:
+                recursionlevel = recursionlevel + 1
+            elif not lastquote and testchar == target:
+                recursionlevel = recursionlevel - 1
+                if recursionlevel == 0:
+                    import time
+                    autoscroll = self.ted.WEFeatureFlag(WASTEconst.weFAutoScroll, -1)
+                    if autoscroll:
+                        self.ted.WEFeatureFlag(WASTEconst.weFAutoScroll, 0)
+                    self.ted.WESetSelection(count, count + 1)
+                    self._parentwindow.wid.GetWindowPort().QDFlushPortBuffer(None)  # needed under OSX
+                    time.sleep(0.2)
+                    self.ted.WESetSelection(selstart, selend)
+                    if autoscroll:
+                        self.ted.WEFeatureFlag(WASTEconst.weFAutoScroll, 1)
+                    break
+            count = count - 1
+
+    def extratabs(self, line):
+        tabcount = 0
+        for c in line:
+            if c <> '\t':
+                break
+            tabcount = tabcount + 1
+        last = 0
+        cleanline = ''
+        tags = PyFontify.fontify(line)
+        # strip comments and strings
+        for tag, start, end, sublist in tags:
+            if tag in ('string', 'comment'):
+                cleanline = cleanline + line[last:start]
+                last = end
+        cleanline = cleanline + line[last:]
+        cleanline = string.strip(cleanline)
+        if cleanline and cleanline[-1] == ':':
+            tabcount = tabcount + 1
+        else:
+            # extra indent after unbalanced (, [ or {
+            for open, close in (('(', ')'), ('[', ']'), ('{', '}')):
+                count = string.count(cleanline, open)
+                if count and count > string.count(cleanline, close):
+                    tabcount = tabcount + 2
+                    break
+        return tabcount
+
+    def rollover(self, point, onoff):
+        if onoff:
+            if self._debugger and self.pt_in_breaks(point):
+                Wbase.SetCursor("arrow")
+            else:
+                Wbase.SetCursor("iBeam")
+
+    def draw(self, visRgn = None):
+        TextEditor.draw(self, visRgn)
+        if self._debugger:
+            self.drawbreakpoints()
+
+    def showbreakpoints(self, onoff):
+        if (not not self._debugger) <> onoff:
+            if onoff:
+                if not __debug__:
+                    import W
+                    raise W.AlertError, "Can't debug in \"Optimize bytecode\" mode.\r(see \"Default startup options\" in EditPythonPreferences)"
+                import PyDebugger
+                self._debugger = PyDebugger.getdebugger()
+                self._debugger.register_editor(self, self.file)
+            elif self._debugger:
+                self._debugger.unregister_editor(self, self.file)
+                self._debugger = None
+            self.adjust(self._bounds)
+
+    def togglebreakpoints(self):
+        self.showbreakpoints(not self._debugger)
+
+    def clearbreakpoints(self):
+        if self.file:
+            self._debugger.clear_all_file_breaks(self.file)
+
+    def editbreakpoints(self):
+        if self._debugger:
+            self._debugger.edit_breaks()
+            self._debugger.breaksviewer.selectfile(self.file)
+
+    def drawbreakpoints(self, eraseall = 0):
+        breakrect = bl, bt, br, bb = self._getbreakrect()
+        br = br - 1
+        self.SetPort()
+        Qd.PenPat(Qd.GetQDGlobalsGray())
+        Qd.PaintRect((br, bt, br + 1, bb))
+        Qd.PenNormal()
+        self._parentwindow.tempcliprect(breakrect)
+        Qd.RGBForeColor((0xffff, 0, 0))
+        try:
+            lasttop = bt
+            self_ted = self.ted
+            Qd_PaintOval = Qd.PaintOval
+            Qd_EraseRect = Qd.EraseRect
+            for lineno in self._debugger.get_file_breaks(self.file):
+                start, end = self_ted.WEGetLineRange(lineno - 1)
+                if lineno <> self_ted.WEOffsetToLine(start) + 1:
+                    # breakpoints beyond our text: erase rest, and back out
+                    Qd_EraseRect((bl, lasttop, br, bb))
+                    break
+                (x, y), h = self_ted.WEGetPoint(start, 0)
+                bottom = y + h
+                #print y, (lasttop, bottom)
+                if bottom > lasttop:
+                    Qd_EraseRect((bl, lasttop, br, y + h * eraseall))
+                    lasttop = bottom
+                redbullet = bl + 2, y + 3, bl + 8, y + 9
+                Qd_PaintOval(redbullet)
+            else:
+                Qd_EraseRect((bl, lasttop, br, bb))
+            Qd.RGBForeColor((0, 0, 0))
+        finally:
+            self._parentwindow.restoreclip()
+
+    def updatescrollbars(self):
+        if self._debugger:
+            self.drawbreakpoints(1)
+        TextEditor.updatescrollbars(self)
+
+    def pt_in_breaks(self, point):
+        return Qd.PtInRect(point, self._getbreakrect())
+
+    def _getbreakrect(self):
+        if self._debugger:
+            l, t, r, b = self._bounds
+            return (l+1, t+1, l + 12, b-1)
+        else:
+            return (0, 0, 0, 0)
+
+    def _getviewrect(self):
+        l, t, r, b = self._bounds
+        if self._debugger:
+            return (l + 17, t + 2, r, b - 2)
+        else:
+            return (l + 5, t + 2, r, b - 2)
+
+    def _calctextbounds(self):
+        viewrect = l, t, r, b = self._getviewrect()
+        if self.ted:
+            dl, dt, dr, db = self.ted.WEGetDestRect()
+            vl, vt, vr, vb = self.ted.WEGetViewRect()
+            xshift = l - vl
+            yshift = t - vt
+            if (db - dt) < (b - t):
+                yshift = t - dt
+            destrect = (dl + xshift, dt + yshift, dr + xshift, db + yshift)
+        else:
+            destrect = (l, t, r + 5000, b)
+        return viewrect, destrect
 
 
 def GetFNum(fontname):
-	"""Same as Fm.GetFNum(), but maps a missing font to Monaco instead of the system font."""
-	if fontname <> Fm.GetFontName(0):
-		fontid = Fm.GetFNum(fontname)
-		if fontid == 0:
-			fontid = Fonts.monaco
-	else:
-		fontid = 0
-	return fontid
+    """Same as Fm.GetFNum(), but maps a missing font to Monaco instead of the system font."""
+    if fontname <> Fm.GetFontName(0):
+        fontid = Fm.GetFNum(fontname)
+        if fontid == 0:
+            fontid = Fonts.monaco
+    else:
+        fontid = 0
+    return fontid
 
 # b/w compat. Anyone using this?
 GetFName = Fm.GetFontName
 
 def GetPortFontSettings(port):
-	return Fm.GetFontName(port.GetPortTextFont()), port.GetPortTextFace(), port.GetPortTextSize()
+    return Fm.GetFontName(port.GetPortTextFont()), port.GetPortTextFace(), port.GetPortTextSize()
 
 def SetPortFontSettings(port, (font, face, size)):
-	saveport = Qd.GetPort()
-	Qd.SetPort(port)
-	Qd.TextFont(GetFNum(font))
-	Qd.TextFace(face)
-	Qd.TextSize(size)
-	Qd.SetPort(saveport)
+    saveport = Qd.GetPort()
+    Qd.SetPort(port)
+    Qd.TextFont(GetFNum(font))
+    Qd.TextFace(face)
+    Qd.TextSize(size)
+    Qd.SetPort(saveport)
diff --git a/Mac/Tools/IDE/Wtraceback.py b/Mac/Tools/IDE/Wtraceback.py
index 90a25fe..e84349d 100644
--- a/Mac/Tools/IDE/Wtraceback.py
+++ b/Mac/Tools/IDE/Wtraceback.py
@@ -7,182 +7,181 @@
 
 
 class TraceBack:
-	
-	def __init__(self, title = "Traceback"):
-		app = W.getapplication()  # checks if W is properly initialized
-		self.title = title
-		self.w = None
-		self.closed = 1
-		self.start = 0
-		self.lastwindowtitle = ""
-		self.bounds = (360, 298)
-	
-	def traceback(self, start = 0, lastwindowtitle = ""):
-		try:
-			self.lastwindowtitle = lastwindowtitle
-			self.start = start
-			self.type, self.value, self.tb = sys.exc_info()
-			if self.type is not SyntaxError:
-				self.show()
-				if type(self.type) == types.ClassType:
-					errortext = self.type.__name__
-				else:
-					errortext = str(self.type)
-				value = str(self.value)
-				if self.value and value:
-					errortext = errortext + ": " + value
-				self.w.text.set(errortext)
-				self.buildtblist()
-				self.w.list.set(self.textlist)
-				self.w.list.setselection([len(self.textlist) - 1])
-				self.w.wid.SelectWindow()
-				self.closed = 0
-			else:
-				self.syntaxerror()
-		except:
-			traceback.print_exc()
-	
-	def syntaxerror(self):
-		try:
-			value, (filename, lineno, charno, line) = self.value
-		except:
-			filename = ""
-			lineno = None
-			value = self.value
-		if not filename and self.lastwindowtitle:
-			filename = self.lastwindowtitle
-		elif not filename:
-			filename = "<unknown>"
-		if filename and os.path.exists(filename):
-			filename = os.path.split(filename)[1]
-		if lineno and charno is not None:
-			charno = charno - 1
-			text = str(value) + '\rFile: "' + str(filename) + '", line ' + str(lineno) + '\r\r' + line[:charno] + "\xa5" + line[charno:-1]
-		else:
-			text = str(value) + '\rFile: "' + str(filename) + '"'
-		self.syntaxdialog = W.ModalDialog((360, 120), "Syntax Error")
-		self.syntaxdialog.text = W.TextBox((10, 10, -10, -40), text)
-		self.syntaxdialog.cancel = W.Button((-190, -32, 80, 16), "Cancel", self.syntaxclose)
-		self.syntaxdialog.edit = W.Button((-100, -32, 80, 16), "Edit", self.syntaxedit)
-		self.syntaxdialog.setdefaultbutton(self.syntaxdialog.edit)
-		self.syntaxdialog.bind("cmd.", self.syntaxdialog.cancel.push)
-		self.syntaxdialog.open()
-	
-	def syntaxclose(self):
-		self.syntaxdialog.close()
-		del self.syntaxdialog
-	
-	def syntaxedit(self):
-		try:
-			value, (filename, lineno, charno, line) = self.value
-		except:
-			filename = ""
-			lineno = None
-		if not filename and self.lastwindowtitle:
-			filename = self.lastwindowtitle
-		elif not filename:
-			filename = "<unknown>"
-		self.syntaxclose()
-		if lineno:
-			if charno is None:
-				charno = 1
-			W.getapplication().openscript(filename, lineno, charno - 1)
-		else:
-			W.getapplication().openscript(filename)
-	
-	def show(self):
-		if self.closed:
-			self.setupwidgets()
-			self.w.open()
-		else:
-			self.w.wid.ShowWindow()
-			self.w.wid.SelectWindow()
-	
-	def hide(self):
-		if self.closed:
-			return
-		self.w.close()
-	
-	def close(self):
-		self.bounds = self.w.getbounds()
-		self.closed = 1
-		self.type, self.value, self.tb = None, None, None
-		self.tblist = None
-	
-	def activate(self, onoff):
-		if onoff:
-			if self.closed:
-				self.traceback()
-			self.closed = 0
-			self.checkbuttons()
-	
-	def setupwidgets(self):
-		self.w = W.Window(self.bounds, self.title, minsize = (316, 168))
-		self.w.text = W.TextBox((10, 10, -10, 30))
-		self.w.tbtitle = W.TextBox((10, 40, -10, 10), "Traceback (innermost last):")
-		self.w.list = W.TwoLineList((10, 60, -10, -40), callback = self.listhit)
-		
-		self.w.editbutton = W.Button((10, -30, 60, 16), "Edit", self.edit)
-		self.w.editbutton.enable(0)
-		
-		self.w.browselocalsbutton = W.Button((80, -30, 100, 16), "Browse locals\xc9", self.browselocals)
-		self.w.browselocalsbutton.enable(0)
-		
-		self.w.postmortembutton = W.Button((190, -30, 100, 16), "Post mortem\xc9", self.postmortem)
-		
-		self.w.setdefaultbutton(self.w.editbutton)
-		self.w.bind("cmdb", self.w.browselocalsbutton.push)
-		self.w.bind("<close>", self.close)
-		self.w.bind("<activate>", self.activate)
-	
-	def buildtblist(self):
-		tb = self.tb
-		for i in range(self.start):
-			if tb.tb_next is None:
-				break
-			tb = tb.tb_next
-		self.tblist = traceback.extract_tb(tb)
-		self.textlist = []
-		for filename, lineno, func, line in self.tblist:
-			tbline = ""
-			if os.path.exists(filename):
-				filename = os.path.split(filename)[1]
-			tbline = 'File "%s", line %r, in %r' % (filename, lineno, func)
-			if line:
-				tbline = tbline + '\r      ' + line
-			self.textlist.append(tbline[:255])
-	
-	def edit(self):
-		sel = self.w.list.getselection()
-		for i in sel:
-			filename, lineno, func, line = self.tblist[i]
-			W.getapplication().openscript(filename, lineno)
-	
-	def browselocals(self):
-		sel = self.w.list.getselection()
-		for i in sel:
-			tb = self.tb
-			for j in range(i + self.start):
-				tb = tb.tb_next
-			self.browse(tb.tb_frame.f_locals)
-	
-	def browse(self, object):
-		import PyBrowser
-		PyBrowser.Browser(object)
-	
-	def postmortem(self):
-		import PyDebugger
-		PyDebugger.postmortem(self.type, self.value, self.tb)
-	
-	def listhit(self, isdbl):
-		if isdbl:
-			self.w.editbutton.push()
-		else:
-			self.checkbuttons()
-	
-	def checkbuttons(self):
-		havefile = len(self.w.list.getselection()) > 0
-		self.w.editbutton.enable(havefile)
-		self.w.browselocalsbutton.enable(havefile)
-		self.w.setdefaultbutton(havefile and self.w.editbutton or self.w.postmortembutton)
 
+    def __init__(self, title = "Traceback"):
+        app = W.getapplication()  # checks if W is properly initialized
+        self.title = title
+        self.w = None
+        self.closed = 1
+        self.start = 0
+        self.lastwindowtitle = ""
+        self.bounds = (360, 298)
+
+    def traceback(self, start = 0, lastwindowtitle = ""):
+        try:
+            self.lastwindowtitle = lastwindowtitle
+            self.start = start
+            self.type, self.value, self.tb = sys.exc_info()
+            if self.type is not SyntaxError:
+                self.show()
+                if type(self.type) == types.ClassType:
+                    errortext = self.type.__name__
+                else:
+                    errortext = str(self.type)
+                value = str(self.value)
+                if self.value and value:
+                    errortext = errortext + ": " + value
+                self.w.text.set(errortext)
+                self.buildtblist()
+                self.w.list.set(self.textlist)
+                self.w.list.setselection([len(self.textlist) - 1])
+                self.w.wid.SelectWindow()
+                self.closed = 0
+            else:
+                self.syntaxerror()
+        except:
+            traceback.print_exc()
+
+    def syntaxerror(self):
+        try:
+            value, (filename, lineno, charno, line) = self.value
+        except:
+            filename = ""
+            lineno = None
+            value = self.value
+        if not filename and self.lastwindowtitle:
+            filename = self.lastwindowtitle
+        elif not filename:
+            filename = "<unknown>"
+        if filename and os.path.exists(filename):
+            filename = os.path.split(filename)[1]
+        if lineno and charno is not None:
+            charno = charno - 1
+            text = str(value) + '\rFile: "' + str(filename) + '", line ' + str(lineno) + '\r\r' + line[:charno] + "\xa5" + line[charno:-1]
+        else:
+            text = str(value) + '\rFile: "' + str(filename) + '"'
+        self.syntaxdialog = W.ModalDialog((360, 120), "Syntax Error")
+        self.syntaxdialog.text = W.TextBox((10, 10, -10, -40), text)
+        self.syntaxdialog.cancel = W.Button((-190, -32, 80, 16), "Cancel", self.syntaxclose)
+        self.syntaxdialog.edit = W.Button((-100, -32, 80, 16), "Edit", self.syntaxedit)
+        self.syntaxdialog.setdefaultbutton(self.syntaxdialog.edit)
+        self.syntaxdialog.bind("cmd.", self.syntaxdialog.cancel.push)
+        self.syntaxdialog.open()
+
+    def syntaxclose(self):
+        self.syntaxdialog.close()
+        del self.syntaxdialog
+
+    def syntaxedit(self):
+        try:
+            value, (filename, lineno, charno, line) = self.value
+        except:
+            filename = ""
+            lineno = None
+        if not filename and self.lastwindowtitle:
+            filename = self.lastwindowtitle
+        elif not filename:
+            filename = "<unknown>"
+        self.syntaxclose()
+        if lineno:
+            if charno is None:
+                charno = 1
+            W.getapplication().openscript(filename, lineno, charno - 1)
+        else:
+            W.getapplication().openscript(filename)
+
+    def show(self):
+        if self.closed:
+            self.setupwidgets()
+            self.w.open()
+        else:
+            self.w.wid.ShowWindow()
+            self.w.wid.SelectWindow()
+
+    def hide(self):
+        if self.closed:
+            return
+        self.w.close()
+
+    def close(self):
+        self.bounds = self.w.getbounds()
+        self.closed = 1
+        self.type, self.value, self.tb = None, None, None
+        self.tblist = None
+
+    def activate(self, onoff):
+        if onoff:
+            if self.closed:
+                self.traceback()
+            self.closed = 0
+            self.checkbuttons()
+
+    def setupwidgets(self):
+        self.w = W.Window(self.bounds, self.title, minsize = (316, 168))
+        self.w.text = W.TextBox((10, 10, -10, 30))
+        self.w.tbtitle = W.TextBox((10, 40, -10, 10), "Traceback (innermost last):")
+        self.w.list = W.TwoLineList((10, 60, -10, -40), callback = self.listhit)
+
+        self.w.editbutton = W.Button((10, -30, 60, 16), "Edit", self.edit)
+        self.w.editbutton.enable(0)
+
+        self.w.browselocalsbutton = W.Button((80, -30, 100, 16), "Browse locals\xc9", self.browselocals)
+        self.w.browselocalsbutton.enable(0)
+
+        self.w.postmortembutton = W.Button((190, -30, 100, 16), "Post mortem\xc9", self.postmortem)
+
+        self.w.setdefaultbutton(self.w.editbutton)
+        self.w.bind("cmdb", self.w.browselocalsbutton.push)
+        self.w.bind("<close>", self.close)
+        self.w.bind("<activate>", self.activate)
+
+    def buildtblist(self):
+        tb = self.tb
+        for i in range(self.start):
+            if tb.tb_next is None:
+                break
+            tb = tb.tb_next
+        self.tblist = traceback.extract_tb(tb)
+        self.textlist = []
+        for filename, lineno, func, line in self.tblist:
+            tbline = ""
+            if os.path.exists(filename):
+                filename = os.path.split(filename)[1]
+            tbline = 'File "%s", line %r, in %r' % (filename, lineno, func)
+            if line:
+                tbline = tbline + '\r      ' + line
+            self.textlist.append(tbline[:255])
+
+    def edit(self):
+        sel = self.w.list.getselection()
+        for i in sel:
+            filename, lineno, func, line = self.tblist[i]
+            W.getapplication().openscript(filename, lineno)
+
+    def browselocals(self):
+        sel = self.w.list.getselection()
+        for i in sel:
+            tb = self.tb
+            for j in range(i + self.start):
+                tb = tb.tb_next
+            self.browse(tb.tb_frame.f_locals)
+
+    def browse(self, object):
+        import PyBrowser
+        PyBrowser.Browser(object)
+
+    def postmortem(self):
+        import PyDebugger
+        PyDebugger.postmortem(self.type, self.value, self.tb)
+
+    def listhit(self, isdbl):
+        if isdbl:
+            self.w.editbutton.push()
+        else:
+            self.checkbuttons()
+
+    def checkbuttons(self):
+        havefile = len(self.w.list.getselection()) > 0
+        self.w.editbutton.enable(havefile)
+        self.w.browselocalsbutton.enable(havefile)
+        self.w.setdefaultbutton(havefile and self.w.editbutton or self.w.postmortembutton)
diff --git a/Mac/Tools/IDE/Wwindows.py b/Mac/Tools/IDE/Wwindows.py
index d646bcf..cb8d855 100644
--- a/Mac/Tools/IDE/Wwindows.py
+++ b/Mac/Tools/IDE/Wwindows.py
@@ -8,629 +8,629 @@
 from types import InstanceType, StringType
 
 if hasattr(Win, "FrontNonFloatingWindow"):
-	MyFrontWindow = Win.FrontNonFloatingWindow
+    MyFrontWindow = Win.FrontNonFloatingWindow
 else:
-	MyFrontWindow = Win.FrontWindow
+    MyFrontWindow = Win.FrontWindow
 
 
 class Window(FrameWork.Window, Wbase.SelectableWidget):
-	
-	windowkind = Windows.documentProc
-	
-	def __init__(self, possize, title="", minsize=None, maxsize=None, 
-			tabbable=1, show=1, fontsettings=None):
-		import W
-		if fontsettings is None:
-			fontsettings = W.getdefaultfont()
-		self._fontsettings = fontsettings
-		W.SelectableWidget.__init__(self, possize)
-		self._globalbounds = l, t, r, b = self.getwindowbounds(possize, minsize)
-		self._bounds = (0, 0, r - l, b - t)
-		self._tabchain = []
-		self._currentwidget = None
-		self.title = title
-		self._parentwindow = self
-		self._tabbable = tabbable
-		self._defaultbutton = None
-		self._drawwidgetbounds = 0
-		self._show = show
-		self._lastrollover = None
-		self.hasclosebox = 1
-		# XXX the following is not really compatible with the
-		#  new (system >= 7.5) window procs. 
-		if minsize:
-			self._hasgrowbox = 1
-			self.windowkind = self.windowkind | 8
-			l, t = minsize
-			if maxsize:
-				r, b = maxsize[0] + 1, maxsize[1] + 1
-			else:
-				r, b = 32000, 32000
-			self.growlimit = (l, t, r, b)
-		else:
-			self._hasgrowbox = 0
-			if (self.windowkind == 0 or self.windowkind >= 8) and self.windowkind < 1000:
-				self.windowkind = self.windowkind | 4
-		FrameWork.Window.__init__(self, W.getapplication())
-	
-	def gettitle(self):
-		return self.title
-	
-	def settitle(self, title):
-		self.title = title
-		if self.wid:
-			self.wid.SetWTitle(title)
-	
-	def getwindowbounds(self, size, minsize = None):
-		return windowbounds(size, minsize)	
-	
-	def getcurrentwidget(self):
-		return self._currentwidget
-	
-	def show(self, onoff):
-		if onoff:
-			self.wid.ShowWindow()
-		else:
-			self.wid.HideWindow()
-	
-	def isvisible(self):
-		return self.wid.IsWindowVisible()
-	
-	def select(self):
-		self.wid.SelectWindow()
-		# not sure if this is the best place, I need it when
-		# an editor gets selected, and immediately scrolled
-		# to a certain line, waste scroll assumes everything 
-		# to be in tact.
-		self.do_rawupdate(self.wid, "DummyEvent")
-	
-	def open(self):
-		self.wid = Win.NewCWindow(self._globalbounds, self.title, self._show,
-			self.windowkind, -1, self.hasclosebox, 0)
-		self.SetPort()
-		fontname, fontstyle, fontsize, fontcolor = self._fontsettings
-		fnum = Fm.GetFNum(fontname)
-		if fnum == 0:
-			fnum = Fm.GetFNum("Geneva")
-		Qd.TextFont(fnum)
-		Qd.TextFace(fontstyle)
-		Qd.TextSize(fontsize)
-		if self._bindings.has_key("<open>"):
-			callback = self._bindings["<open>"]
-			callback()
-		for w in self._widgets:
-			w.forall_frombottom("open")
-		self._maketabchain()
-		if self._tabbable:
-			self.bind('tab', self.nextwidget)
-			self.bind('shifttab', self.previouswidget)
-		else:
-			self._hasselframes = 0
-		if self._tabchain:
-			self._tabchain[0].select(1)
-		self.do_postopen()
-	
-	def close(self):
-		if not self.wid:
-			return	# we are already closed
-		if self._bindings.has_key("<close>"):
-			callback = self._bindings["<close>"]
-			try:
-				rv = callback()
-			except:
-				print 'error in <close> callback'
-				traceback.print_exc()
-			else:
-				if rv:
-					return rv
-		#for key in self._widgetsdict.keys():
-		#	self._removewidget(key)
-		self.forall_butself("close")
-		Wbase.SelectableWidget.close(self)
-		self._tabchain = []
-		self._currentwidget = None
-		self.wid.HideWindow()
-		self.do_postclose()
-	
-	def domenu_close(self, *args):
-		self.close()
-	
-	def getbounds(self):
-		return self._globalbounds
-	
-	def setbounds(self, bounds):
-		l, t, r, b = bounds
-		self.move(l, t)
-		self.resize(r-l, b-t)
-	
-	def move(self, x, y = None):
-		"""absolute move"""
-		if y == None:
-			x, y = x
-		self.wid.MoveWindow(x, y, 0)
-	
-	def resize(self, x, y = None):
-		if not self._hasgrowbox:
-			return  # hands off!
-		if y == None:
-			x, y = x
-		self.SetPort()
-		self.GetWindow().InvalWindowRect(self.getgrowrect())
-		self.wid.SizeWindow(x, y, 1)
-		self._calcbounds()
-	
-	def test(self, point):
-		return 1
-	
-	def draw(self, visRgn = None):
-		if self._hasgrowbox:
-			self.tempcliprect(self.getgrowrect())
-			self.wid.DrawGrowIcon()
-			self.restoreclip()
-	
-	def idle(self, *args):
-		self.SetPort()
-		point = Evt.GetMouse()
-		widget = self.findwidget(point, 0)
-		if self._bindings.has_key("<idle>"):
-			callback = self._bindings["<idle>"]
-			if callback():
-				return
-		if self._currentwidget is not None and hasattr(self._currentwidget, "idle"):
-			if self._currentwidget._bindings.has_key("<idle>"):
-				callback = self._currentwidget._bindings["<idle>"]
-				if callback():
-					return
-			if self._currentwidget.idle():
-				return
-		if widget is not None and hasattr(widget, "rollover"):
-			if 1:	#self._lastrollover <> widget:
-				if self._lastrollover:
-					self._lastrollover.rollover(point, 0)
-				self._lastrollover = widget
-				self._lastrollover.rollover(point, 1)
-		else:
-			if self._lastrollover:
-				self._lastrollover.rollover(point, 0)
-			self._lastrollover = None
-			Wbase.SetCursor("arrow")
 
-	def xxx___select(self, widget):
-		if self._currentwidget == widget:
-			return
-		if self._bindings.has_key("<select>"):
-			callback = self._bindings["<select>"]
-			if callback(widget):
-				return
-		if widget is None:
-			if self._currentwidget is not None:
-				self._currentwidget.select(0)
-		elif type(widget) == InstanceType and widget._selectable:
-			widget.select(1)
-		elif widget == -1 or widget == 1:
-			if len(self._tabchain) <= 1:
-				return
-			temp = self._tabchain[(self._tabchain.index(self._currentwidget) + widget) % len(self._tabchain)]
-			temp.select(1)
-		else:
-			raise TypeError, "Widget is not selectable"
-	
-	def setdefaultbutton(self, newdefaultbutton = None, *keys):
-		if newdefaultbutton == self._defaultbutton:
-			return
-		if self._defaultbutton:
-			self._defaultbutton._setdefault(0)
-		if not newdefaultbutton:
-			self.bind("return", None)
-			self.bind("enter", None)
-			return
-		import Wcontrols
-		if not isinstance(newdefaultbutton, Wcontrols.Button):
-			raise TypeError, "widget is not a button"
-		self._defaultbutton = newdefaultbutton
-		self._defaultbutton._setdefault(1)
-		if not keys:
-			self.bind("return", self._defaultbutton.push)
-			self.bind("enter", self._defaultbutton.push)
-		else:
-			for key in keys:
-				self.bind(key, self._defaultbutton.push)
-	
-	def nextwidget(self):
-		self.xxx___select(1)
-	
-	def previouswidget(self):
-		self.xxx___select(-1)
-	
-	def drawwidgetbounds(self, onoff):
-		self._drawwidgetbounds = onoff
-		self.SetPort()
-		self.GetWindow().InvalWindowRect(self._bounds)
-	
-	def _drawbounds(self):
-		pass
+    windowkind = Windows.documentProc
 
-	def _maketabchain(self):
-		# XXX This has to change, it's no good when we are adding or deleting widgets.
-		# XXX Perhaps we shouldn't keep a "tabchain" at all.
-		self._hasselframes = 0
-		self._collectselectablewidgets(self._widgets)
-		if self._hasselframes and len(self._tabchain) > 1:
-			self._hasselframes = 1
-		else:
-			self._hasselframes = 0
-	
-	def _collectselectablewidgets(self, widgets):
-		import W
-		for w in widgets:
-			if w._selectable:
-				self._tabchain.append(w)
-				if isinstance(w, W.List):
-					self._hasselframes = 1
-			self._collectselectablewidgets(w._widgets)
-	
-	def _calcbounds(self):
-		self._possize = self.wid.GetWindowPort().GetPortBounds()[2:]
-		w, h = self._possize
-		self._bounds = (0, 0, w, h)
-		self.wid.GetWindowContentRgn(scratchRegion)
-		l, t, r, b = GetRgnBounds(scratchRegion)
-		self._globalbounds = l, t, l + w, t + h
-		for w in self._widgets:
-			w._calcbounds()
-	
-	# FrameWork override methods
-	def do_inDrag(self, partcode, window, event):
-		where = event[3]
-		self.wid.GetWindowContentRgn(scratchRegion)
-		was_l, was_t, r, b = GetRgnBounds(scratchRegion)
-		window.DragWindow(where, self.draglimit)
-		self.wid.GetWindowContentRgn(scratchRegion)
-		is_l, is_t, r, b = GetRgnBounds(scratchRegion)
-		self._globalbounds = Qd.OffsetRect(self._globalbounds, 
-					is_l - was_l, is_t - was_t)
-	
-	def do_char(self, char, event):
-		import Wkeys
-		(what, message, when, where, modifiers) = event
-		key = char
-		if Wkeys.keynames.has_key(key):
-			key = Wkeys.keynames[key]
-		if modifiers & Events.shiftKey:
-			key = 'shift' + key
-		if modifiers & Events.cmdKey:
-			key = 'cmd' + key
-		if modifiers & Events.controlKey:
-			key = 'control' + key
-		if self._bindings.has_key("<key>"):
-			callback = self._bindings["<key>"]
-			if Wbase.CallbackCall(callback, 0, char, event):
-				return
-		if self._bindings.has_key(key):
-			callback = self._bindings[key]
-			Wbase.CallbackCall(callback, 0, char, event)
-		elif self._currentwidget is not None:
-			if self._currentwidget._bindings.has_key(key):
-				callback = self._currentwidget._bindings[key]
-				Wbase.CallbackCall(callback, 0, char, event)
-			else:
-				if self._currentwidget._bindings.has_key("<key>"):
-					callback = self._currentwidget._bindings["<key>"]
-					if Wbase.CallbackCall(callback, 0, char, event):
-						return
-				self._currentwidget.key(char, event)
-	
-	def do_contentclick(self, point, modifiers, event):
-		widget = self.findwidget(point)
-		if widget is not None:
-			if self._bindings.has_key("<click>"):
-				callback = self._bindings["<click>"]
-				if Wbase.CallbackCall(callback, 0, point, modifiers):
-					return
-			if widget._bindings.has_key("<click>"):
-				callback = widget._bindings["<click>"]
-				if Wbase.CallbackCall(callback, 0, point, modifiers):
-					return
-			if widget._selectable:
-				widget.select(1, 1)
-			widget.click(point, modifiers)
-	
-	def do_update(self, window, event):
-		Qd.EraseRgn(window.GetWindowPort().visRgn)
-		self.forall_frombottom("draw", window.GetWindowPort().visRgn)
-		if self._drawwidgetbounds:
-			self.forall_frombottom("_drawbounds")
-	
-	def do_activate(self, onoff, event):
-		if not onoff:
-			if self._lastrollover:
-				self._lastrollover.rollover((0, 0), 0)
-				self._lastrollover = None
-		self.SetPort()
-		self.forall("activate", onoff)
-		self.draw()
-	
-	def do_postresize(self, width, height, window):
-		self.GetWindow().InvalWindowRect(self.getgrowrect())
-		self._calcbounds()
-	
-	def do_inGoAway(self, partcode, window, event):
-		where = event[3]
-		closeall = event[4] & Events.optionKey
-		if window.TrackGoAway(where):
-			if not closeall:
-				self.close()
-			else:
-				for window in self.parent._windows.values():
-					rv = window.close()
-					if rv and rv > 0:
-						return
-	
-	# utilities
-	def tempcliprect(self, tempcliprect):
-		tempclip = Qd.NewRgn()
-		Qd.RectRgn(tempclip, tempcliprect)
-		self.tempclip(tempclip)
-		Qd.DisposeRgn(tempclip)
-	
-	def tempclip(self, tempclip):
-		if not hasattr(self, "saveclip"):
-			self.saveclip = []
-		saveclip = Qd.NewRgn()
-		Qd.GetClip(saveclip)
-		self.saveclip.append(saveclip)
-		Qd.SetClip(tempclip)
-	
-	def restoreclip(self):
-		Qd.SetClip(self.saveclip[-1])
-		Qd.DisposeRgn(self.saveclip[-1])
-		del self.saveclip[-1]
-	
-	def getgrowrect(self):
-		l, t, r, b = self.wid.GetWindowPort().GetPortBounds()
-		return (r - 15, b - 15, r, b)
-	
-	def has_key(self, key):
-		return self._widgetsdict.has_key(key)
-	
-	def __getattr__(self, attr):
-		global _successcount, _failcount, _magiccount
-		if self._widgetsdict.has_key(attr):
-			_successcount = _successcount + 1
-			return self._widgetsdict[attr]
-		if self._currentwidget is None or (attr[:7] <> 'domenu_' and 
-				attr[:4] <> 'can_' and attr <> 'insert'):
-			_failcount = _failcount + 1
-			raise AttributeError, attr
-		# special case: if a domenu_xxx, can_xxx or insert method is asked for, 
-		# see if the active widget supports it
-		_magiccount = _magiccount + 1
-		return getattr(self._currentwidget, attr)
+    def __init__(self, possize, title="", minsize=None, maxsize=None,
+                    tabbable=1, show=1, fontsettings=None):
+        import W
+        if fontsettings is None:
+            fontsettings = W.getdefaultfont()
+        self._fontsettings = fontsettings
+        W.SelectableWidget.__init__(self, possize)
+        self._globalbounds = l, t, r, b = self.getwindowbounds(possize, minsize)
+        self._bounds = (0, 0, r - l, b - t)
+        self._tabchain = []
+        self._currentwidget = None
+        self.title = title
+        self._parentwindow = self
+        self._tabbable = tabbable
+        self._defaultbutton = None
+        self._drawwidgetbounds = 0
+        self._show = show
+        self._lastrollover = None
+        self.hasclosebox = 1
+        # XXX the following is not really compatible with the
+        #  new (system >= 7.5) window procs.
+        if minsize:
+            self._hasgrowbox = 1
+            self.windowkind = self.windowkind | 8
+            l, t = minsize
+            if maxsize:
+                r, b = maxsize[0] + 1, maxsize[1] + 1
+            else:
+                r, b = 32000, 32000
+            self.growlimit = (l, t, r, b)
+        else:
+            self._hasgrowbox = 0
+            if (self.windowkind == 0 or self.windowkind >= 8) and self.windowkind < 1000:
+                self.windowkind = self.windowkind | 4
+        FrameWork.Window.__init__(self, W.getapplication())
+
+    def gettitle(self):
+        return self.title
+
+    def settitle(self, title):
+        self.title = title
+        if self.wid:
+            self.wid.SetWTitle(title)
+
+    def getwindowbounds(self, size, minsize = None):
+        return windowbounds(size, minsize)
+
+    def getcurrentwidget(self):
+        return self._currentwidget
+
+    def show(self, onoff):
+        if onoff:
+            self.wid.ShowWindow()
+        else:
+            self.wid.HideWindow()
+
+    def isvisible(self):
+        return self.wid.IsWindowVisible()
+
+    def select(self):
+        self.wid.SelectWindow()
+        # not sure if this is the best place, I need it when
+        # an editor gets selected, and immediately scrolled
+        # to a certain line, waste scroll assumes everything
+        # to be in tact.
+        self.do_rawupdate(self.wid, "DummyEvent")
+
+    def open(self):
+        self.wid = Win.NewCWindow(self._globalbounds, self.title, self._show,
+                self.windowkind, -1, self.hasclosebox, 0)
+        self.SetPort()
+        fontname, fontstyle, fontsize, fontcolor = self._fontsettings
+        fnum = Fm.GetFNum(fontname)
+        if fnum == 0:
+            fnum = Fm.GetFNum("Geneva")
+        Qd.TextFont(fnum)
+        Qd.TextFace(fontstyle)
+        Qd.TextSize(fontsize)
+        if self._bindings.has_key("<open>"):
+            callback = self._bindings["<open>"]
+            callback()
+        for w in self._widgets:
+            w.forall_frombottom("open")
+        self._maketabchain()
+        if self._tabbable:
+            self.bind('tab', self.nextwidget)
+            self.bind('shifttab', self.previouswidget)
+        else:
+            self._hasselframes = 0
+        if self._tabchain:
+            self._tabchain[0].select(1)
+        self.do_postopen()
+
+    def close(self):
+        if not self.wid:
+            return  # we are already closed
+        if self._bindings.has_key("<close>"):
+            callback = self._bindings["<close>"]
+            try:
+                rv = callback()
+            except:
+                print 'error in <close> callback'
+                traceback.print_exc()
+            else:
+                if rv:
+                    return rv
+        #for key in self._widgetsdict.keys():
+        #       self._removewidget(key)
+        self.forall_butself("close")
+        Wbase.SelectableWidget.close(self)
+        self._tabchain = []
+        self._currentwidget = None
+        self.wid.HideWindow()
+        self.do_postclose()
+
+    def domenu_close(self, *args):
+        self.close()
+
+    def getbounds(self):
+        return self._globalbounds
+
+    def setbounds(self, bounds):
+        l, t, r, b = bounds
+        self.move(l, t)
+        self.resize(r-l, b-t)
+
+    def move(self, x, y = None):
+        """absolute move"""
+        if y == None:
+            x, y = x
+        self.wid.MoveWindow(x, y, 0)
+
+    def resize(self, x, y = None):
+        if not self._hasgrowbox:
+            return  # hands off!
+        if y == None:
+            x, y = x
+        self.SetPort()
+        self.GetWindow().InvalWindowRect(self.getgrowrect())
+        self.wid.SizeWindow(x, y, 1)
+        self._calcbounds()
+
+    def test(self, point):
+        return 1
+
+    def draw(self, visRgn = None):
+        if self._hasgrowbox:
+            self.tempcliprect(self.getgrowrect())
+            self.wid.DrawGrowIcon()
+            self.restoreclip()
+
+    def idle(self, *args):
+        self.SetPort()
+        point = Evt.GetMouse()
+        widget = self.findwidget(point, 0)
+        if self._bindings.has_key("<idle>"):
+            callback = self._bindings["<idle>"]
+            if callback():
+                return
+        if self._currentwidget is not None and hasattr(self._currentwidget, "idle"):
+            if self._currentwidget._bindings.has_key("<idle>"):
+                callback = self._currentwidget._bindings["<idle>"]
+                if callback():
+                    return
+            if self._currentwidget.idle():
+                return
+        if widget is not None and hasattr(widget, "rollover"):
+            if 1:   #self._lastrollover <> widget:
+                if self._lastrollover:
+                    self._lastrollover.rollover(point, 0)
+                self._lastrollover = widget
+                self._lastrollover.rollover(point, 1)
+        else:
+            if self._lastrollover:
+                self._lastrollover.rollover(point, 0)
+            self._lastrollover = None
+            Wbase.SetCursor("arrow")
+
+    def xxx___select(self, widget):
+        if self._currentwidget == widget:
+            return
+        if self._bindings.has_key("<select>"):
+            callback = self._bindings["<select>"]
+            if callback(widget):
+                return
+        if widget is None:
+            if self._currentwidget is not None:
+                self._currentwidget.select(0)
+        elif type(widget) == InstanceType and widget._selectable:
+            widget.select(1)
+        elif widget == -1 or widget == 1:
+            if len(self._tabchain) <= 1:
+                return
+            temp = self._tabchain[(self._tabchain.index(self._currentwidget) + widget) % len(self._tabchain)]
+            temp.select(1)
+        else:
+            raise TypeError, "Widget is not selectable"
+
+    def setdefaultbutton(self, newdefaultbutton = None, *keys):
+        if newdefaultbutton == self._defaultbutton:
+            return
+        if self._defaultbutton:
+            self._defaultbutton._setdefault(0)
+        if not newdefaultbutton:
+            self.bind("return", None)
+            self.bind("enter", None)
+            return
+        import Wcontrols
+        if not isinstance(newdefaultbutton, Wcontrols.Button):
+            raise TypeError, "widget is not a button"
+        self._defaultbutton = newdefaultbutton
+        self._defaultbutton._setdefault(1)
+        if not keys:
+            self.bind("return", self._defaultbutton.push)
+            self.bind("enter", self._defaultbutton.push)
+        else:
+            for key in keys:
+                self.bind(key, self._defaultbutton.push)
+
+    def nextwidget(self):
+        self.xxx___select(1)
+
+    def previouswidget(self):
+        self.xxx___select(-1)
+
+    def drawwidgetbounds(self, onoff):
+        self._drawwidgetbounds = onoff
+        self.SetPort()
+        self.GetWindow().InvalWindowRect(self._bounds)
+
+    def _drawbounds(self):
+        pass
+
+    def _maketabchain(self):
+        # XXX This has to change, it's no good when we are adding or deleting widgets.
+        # XXX Perhaps we shouldn't keep a "tabchain" at all.
+        self._hasselframes = 0
+        self._collectselectablewidgets(self._widgets)
+        if self._hasselframes and len(self._tabchain) > 1:
+            self._hasselframes = 1
+        else:
+            self._hasselframes = 0
+
+    def _collectselectablewidgets(self, widgets):
+        import W
+        for w in widgets:
+            if w._selectable:
+                self._tabchain.append(w)
+                if isinstance(w, W.List):
+                    self._hasselframes = 1
+            self._collectselectablewidgets(w._widgets)
+
+    def _calcbounds(self):
+        self._possize = self.wid.GetWindowPort().GetPortBounds()[2:]
+        w, h = self._possize
+        self._bounds = (0, 0, w, h)
+        self.wid.GetWindowContentRgn(scratchRegion)
+        l, t, r, b = GetRgnBounds(scratchRegion)
+        self._globalbounds = l, t, l + w, t + h
+        for w in self._widgets:
+            w._calcbounds()
+
+    # FrameWork override methods
+    def do_inDrag(self, partcode, window, event):
+        where = event[3]
+        self.wid.GetWindowContentRgn(scratchRegion)
+        was_l, was_t, r, b = GetRgnBounds(scratchRegion)
+        window.DragWindow(where, self.draglimit)
+        self.wid.GetWindowContentRgn(scratchRegion)
+        is_l, is_t, r, b = GetRgnBounds(scratchRegion)
+        self._globalbounds = Qd.OffsetRect(self._globalbounds,
+                                is_l - was_l, is_t - was_t)
+
+    def do_char(self, char, event):
+        import Wkeys
+        (what, message, when, where, modifiers) = event
+        key = char
+        if Wkeys.keynames.has_key(key):
+            key = Wkeys.keynames[key]
+        if modifiers & Events.shiftKey:
+            key = 'shift' + key
+        if modifiers & Events.cmdKey:
+            key = 'cmd' + key
+        if modifiers & Events.controlKey:
+            key = 'control' + key
+        if self._bindings.has_key("<key>"):
+            callback = self._bindings["<key>"]
+            if Wbase.CallbackCall(callback, 0, char, event):
+                return
+        if self._bindings.has_key(key):
+            callback = self._bindings[key]
+            Wbase.CallbackCall(callback, 0, char, event)
+        elif self._currentwidget is not None:
+            if self._currentwidget._bindings.has_key(key):
+                callback = self._currentwidget._bindings[key]
+                Wbase.CallbackCall(callback, 0, char, event)
+            else:
+                if self._currentwidget._bindings.has_key("<key>"):
+                    callback = self._currentwidget._bindings["<key>"]
+                    if Wbase.CallbackCall(callback, 0, char, event):
+                        return
+                self._currentwidget.key(char, event)
+
+    def do_contentclick(self, point, modifiers, event):
+        widget = self.findwidget(point)
+        if widget is not None:
+            if self._bindings.has_key("<click>"):
+                callback = self._bindings["<click>"]
+                if Wbase.CallbackCall(callback, 0, point, modifiers):
+                    return
+            if widget._bindings.has_key("<click>"):
+                callback = widget._bindings["<click>"]
+                if Wbase.CallbackCall(callback, 0, point, modifiers):
+                    return
+            if widget._selectable:
+                widget.select(1, 1)
+            widget.click(point, modifiers)
+
+    def do_update(self, window, event):
+        Qd.EraseRgn(window.GetWindowPort().visRgn)
+        self.forall_frombottom("draw", window.GetWindowPort().visRgn)
+        if self._drawwidgetbounds:
+            self.forall_frombottom("_drawbounds")
+
+    def do_activate(self, onoff, event):
+        if not onoff:
+            if self._lastrollover:
+                self._lastrollover.rollover((0, 0), 0)
+                self._lastrollover = None
+        self.SetPort()
+        self.forall("activate", onoff)
+        self.draw()
+
+    def do_postresize(self, width, height, window):
+        self.GetWindow().InvalWindowRect(self.getgrowrect())
+        self._calcbounds()
+
+    def do_inGoAway(self, partcode, window, event):
+        where = event[3]
+        closeall = event[4] & Events.optionKey
+        if window.TrackGoAway(where):
+            if not closeall:
+                self.close()
+            else:
+                for window in self.parent._windows.values():
+                    rv = window.close()
+                    if rv and rv > 0:
+                        return
+
+    # utilities
+    def tempcliprect(self, tempcliprect):
+        tempclip = Qd.NewRgn()
+        Qd.RectRgn(tempclip, tempcliprect)
+        self.tempclip(tempclip)
+        Qd.DisposeRgn(tempclip)
+
+    def tempclip(self, tempclip):
+        if not hasattr(self, "saveclip"):
+            self.saveclip = []
+        saveclip = Qd.NewRgn()
+        Qd.GetClip(saveclip)
+        self.saveclip.append(saveclip)
+        Qd.SetClip(tempclip)
+
+    def restoreclip(self):
+        Qd.SetClip(self.saveclip[-1])
+        Qd.DisposeRgn(self.saveclip[-1])
+        del self.saveclip[-1]
+
+    def getgrowrect(self):
+        l, t, r, b = self.wid.GetWindowPort().GetPortBounds()
+        return (r - 15, b - 15, r, b)
+
+    def has_key(self, key):
+        return self._widgetsdict.has_key(key)
+
+    def __getattr__(self, attr):
+        global _successcount, _failcount, _magiccount
+        if self._widgetsdict.has_key(attr):
+            _successcount = _successcount + 1
+            return self._widgetsdict[attr]
+        if self._currentwidget is None or (attr[:7] <> 'domenu_' and
+                        attr[:4] <> 'can_' and attr <> 'insert'):
+            _failcount = _failcount + 1
+            raise AttributeError, attr
+        # special case: if a domenu_xxx, can_xxx or insert method is asked for,
+        # see if the active widget supports it
+        _magiccount = _magiccount + 1
+        return getattr(self._currentwidget, attr)
 
 _successcount = 0
 _failcount = 0
 _magiccount = 0
 
 class Dialog(Window):
-	
-	windowkind = Windows.movableDBoxProc
-	
-	# this __init__ seems redundant, but it's not: it has less args
-	def __init__(self, possize, title = ""):
-		Window.__init__(self, possize, title)
-	
-	def can_close(self, *args):
-		return 0
-	
-	def getwindowbounds(self, size, minsize = None):
-		screenbounds = sl, st, sr, sb = Qd.GetQDGlobalsScreenBits().bounds
-		w, h = size
-		l = sl + (sr - sl - w) / 2
-		t = st + (sb - st - h) / 3
-		return l, t, l + w, t + h
+
+    windowkind = Windows.movableDBoxProc
+
+    # this __init__ seems redundant, but it's not: it has less args
+    def __init__(self, possize, title = ""):
+        Window.__init__(self, possize, title)
+
+    def can_close(self, *args):
+        return 0
+
+    def getwindowbounds(self, size, minsize = None):
+        screenbounds = sl, st, sr, sb = Qd.GetQDGlobalsScreenBits().bounds
+        w, h = size
+        l = sl + (sr - sl - w) / 2
+        t = st + (sb - st - h) / 3
+        return l, t, l + w, t + h
 
 
 class ModalDialog(Dialog):
-	
-	def __init__(self, possize, title = ""):
-		Dialog.__init__(self, possize, title)
-		if title:
-			self.windowkind = Windows.movableDBoxProc
-		else:
-			self.windowkind = Windows.dBoxProc
-	
-	def open(self):
-		import W
-		Dialog.open(self)
-		self.app = W.getapplication()
-		self.done = 0
-		Menu.HiliteMenu(0)
-		app = self.parent
-		app.enablemenubar(0)
-		try:
-			self.mainloop()
-		finally:
-			app.enablemenubar(1)
-	
-	def close(self):
-		if not self.wid:
-			return	# we are already closed
-		self.done = 1
-		del self.app
-		Dialog.close(self)
-	
-	def mainloop(self):
-		if hasattr(MacOS, 'EnableAppswitch'):
-			saveyield = MacOS.EnableAppswitch(-1)
-		while not self.done:
-			#self.do1event()
-			self.do1event(	Events.keyDownMask + 
-						Events.autoKeyMask + 
-						Events.activMask + 
-						Events.updateMask + 
-						Events.mDownMask +
-						Events.mUpMask, 
-						10)
-		if hasattr(MacOS, 'EnableAppswitch'):
-			MacOS.EnableAppswitch(saveyield)
-	
-	def do1event(self, mask = Events.everyEvent, wait = 0):
-		ok, event = self.app.getevent(mask, wait)
-		if Dlg.IsDialogEvent(event):
-			if self.app.do_dialogevent(event):
-				return
-		if ok:
-			self.dispatch(event)
-		else:
-			self.app.idle(event)
-	
-	def do_keyDown(self, event):
-		self.do_key(event)
-	
-	def do_autoKey(self, event):
-		if not event[-1] & Events.cmdKey:
-			self.do_key(event)
-	
-	def do_key(self, event):
-		(what, message, when, where, modifiers) = event
-		#w = Win.FrontWindow()
-		#if w <> self.wid:
-		#	return
-		c = chr(message & Events.charCodeMask)
-		if modifiers & Events.cmdKey:
-			self.app.checkmenus(self)
-			result = Menu.MenuKey(ord(c))
-			id = (result>>16) & 0xffff	# Hi word
-			item = result & 0xffff		# Lo word
-			if id:
-				self.app.do_rawmenu(id, item, None, event)
-				return
-		self.do_char(c, event)
-	
-	def do_mouseDown(self, event):
-		(what, message, when, where, modifiers) = event
-		partcode, wid = Win.FindWindow(where)
-		#
-		# Find the correct name.
-		#
-		if FrameWork.partname.has_key(partcode):
-			name = "do_" + FrameWork.partname[partcode]
-		else:
-			name = "do_%d" % partcode
-		
-		if name == "do_inDesk":
-			if hasattr(MacOS, "HandleEvent"):
-				MacOS.HandleEvent(event)
-			else:
-				print 'Unexpected inDesk event:', event
-			return
-		if wid == self.wid:
-			try:
-				handler = getattr(self, name)
-			except AttributeError:
-				handler = self.app.do_unknownpartcode
-		else:
-			#MacOS.HandleEvent(event)
-			if name == 'do_inMenuBar':
-				handler = getattr(self.parent, name)
-			else:
-				return		
-		handler(partcode, wid, event)
-	
-	def dispatch(self, event):
-		(what, message, when, where, modifiers) = event
-		if FrameWork.eventname.has_key(what):
-			name = "do_" + FrameWork.eventname[what]
-		else:
-			name = "do_%d" % what
-		try:
-			handler = getattr(self, name)
-		except AttributeError:
-			try:
-				handler = getattr(self.app, name)
-			except AttributeError:
-				handler = self.app.do_unknownevent
-		handler(event)
-	
+
+    def __init__(self, possize, title = ""):
+        Dialog.__init__(self, possize, title)
+        if title:
+            self.windowkind = Windows.movableDBoxProc
+        else:
+            self.windowkind = Windows.dBoxProc
+
+    def open(self):
+        import W
+        Dialog.open(self)
+        self.app = W.getapplication()
+        self.done = 0
+        Menu.HiliteMenu(0)
+        app = self.parent
+        app.enablemenubar(0)
+        try:
+            self.mainloop()
+        finally:
+            app.enablemenubar(1)
+
+    def close(self):
+        if not self.wid:
+            return  # we are already closed
+        self.done = 1
+        del self.app
+        Dialog.close(self)
+
+    def mainloop(self):
+        if hasattr(MacOS, 'EnableAppswitch'):
+            saveyield = MacOS.EnableAppswitch(-1)
+        while not self.done:
+            #self.do1event()
+            self.do1event(  Events.keyDownMask +
+                                    Events.autoKeyMask +
+                                    Events.activMask +
+                                    Events.updateMask +
+                                    Events.mDownMask +
+                                    Events.mUpMask,
+                                    10)
+        if hasattr(MacOS, 'EnableAppswitch'):
+            MacOS.EnableAppswitch(saveyield)
+
+    def do1event(self, mask = Events.everyEvent, wait = 0):
+        ok, event = self.app.getevent(mask, wait)
+        if Dlg.IsDialogEvent(event):
+            if self.app.do_dialogevent(event):
+                return
+        if ok:
+            self.dispatch(event)
+        else:
+            self.app.idle(event)
+
+    def do_keyDown(self, event):
+        self.do_key(event)
+
+    def do_autoKey(self, event):
+        if not event[-1] & Events.cmdKey:
+            self.do_key(event)
+
+    def do_key(self, event):
+        (what, message, when, where, modifiers) = event
+        #w = Win.FrontWindow()
+        #if w <> self.wid:
+        #       return
+        c = chr(message & Events.charCodeMask)
+        if modifiers & Events.cmdKey:
+            self.app.checkmenus(self)
+            result = Menu.MenuKey(ord(c))
+            id = (result>>16) & 0xffff      # Hi word
+            item = result & 0xffff          # Lo word
+            if id:
+                self.app.do_rawmenu(id, item, None, event)
+                return
+        self.do_char(c, event)
+
+    def do_mouseDown(self, event):
+        (what, message, when, where, modifiers) = event
+        partcode, wid = Win.FindWindow(where)
+        #
+        # Find the correct name.
+        #
+        if FrameWork.partname.has_key(partcode):
+            name = "do_" + FrameWork.partname[partcode]
+        else:
+            name = "do_%d" % partcode
+
+        if name == "do_inDesk":
+            if hasattr(MacOS, "HandleEvent"):
+                MacOS.HandleEvent(event)
+            else:
+                print 'Unexpected inDesk event:', event
+            return
+        if wid == self.wid:
+            try:
+                handler = getattr(self, name)
+            except AttributeError:
+                handler = self.app.do_unknownpartcode
+        else:
+            #MacOS.HandleEvent(event)
+            if name == 'do_inMenuBar':
+                handler = getattr(self.parent, name)
+            else:
+                return
+        handler(partcode, wid, event)
+
+    def dispatch(self, event):
+        (what, message, when, where, modifiers) = event
+        if FrameWork.eventname.has_key(what):
+            name = "do_" + FrameWork.eventname[what]
+        else:
+            name = "do_%d" % what
+        try:
+            handler = getattr(self, name)
+        except AttributeError:
+            try:
+                handler = getattr(self.app, name)
+            except AttributeError:
+                handler = self.app.do_unknownevent
+        handler(event)
+
 
 def FrontWindowInsert(stuff):
-	if not stuff:
-		return
-	if type(stuff) <> StringType:
-		raise TypeError, 'string expected'
-	import W
-	app = W.getapplication()
-	wid = MyFrontWindow()
-	if wid and app._windows.has_key(wid):
-		window = app._windows[wid]
-		if hasattr(window, "insert"):
-			try:
-				window.insert(stuff)
-				return
-			except:
-				pass
-	import EasyDialogs
-	if EasyDialogs.AskYesNoCancel(
-			"Can't find window or widget to insert text into; copy to clipboard instead?", 
-			1) == 1:
-		from Carbon import Scrap
-		if hasattr(Scrap, 'PutScrap'):
-			Scrap.ZeroScrap()
-			Scrap.PutScrap('TEXT', stuff)
-		else:
-			Scrap.ClearCurrentScrap()
-			sc = Scrap.GetCurrentScrap()
-			sc.PutScrapFlavor('TEXT', 0, stuff)
+    if not stuff:
+        return
+    if type(stuff) <> StringType:
+        raise TypeError, 'string expected'
+    import W
+    app = W.getapplication()
+    wid = MyFrontWindow()
+    if wid and app._windows.has_key(wid):
+        window = app._windows[wid]
+        if hasattr(window, "insert"):
+            try:
+                window.insert(stuff)
+                return
+            except:
+                pass
+    import EasyDialogs
+    if EasyDialogs.AskYesNoCancel(
+                    "Can't find window or widget to insert text into; copy to clipboard instead?",
+                    1) == 1:
+        from Carbon import Scrap
+        if hasattr(Scrap, 'PutScrap'):
+            Scrap.ZeroScrap()
+            Scrap.PutScrap('TEXT', stuff)
+        else:
+            Scrap.ClearCurrentScrap()
+            sc = Scrap.GetCurrentScrap()
+            sc.PutScrapFlavor('TEXT', 0, stuff)
 
 
-# not quite based on the same function in FrameWork	
+# not quite based on the same function in FrameWork
 _windowcounter = 0
 
 def getnextwindowpos():
-	global _windowcounter
-	rows = 8
-	l = 4 * (rows + 1 - (_windowcounter % rows) + _windowcounter / rows)
-	t = 44 + 20 * (_windowcounter % rows)
-	_windowcounter = _windowcounter + 1
-	return l, t
+    global _windowcounter
+    rows = 8
+    l = 4 * (rows + 1 - (_windowcounter % rows) + _windowcounter / rows)
+    t = 44 + 20 * (_windowcounter % rows)
+    _windowcounter = _windowcounter + 1
+    return l, t
 
 def windowbounds(preferredsize, minsize=None):
-	"Return sensible window bounds"
-	
-	global _windowcounter
-	if len(preferredsize) == 4:
-		bounds = l, t, r, b = preferredsize
-		desktopRgn = Win.GetGrayRgn()
-		tempRgn = Qd.NewRgn()
-		Qd.RectRgn(tempRgn, bounds)
-		union = Qd.UnionRgn(tempRgn, desktopRgn, tempRgn)
-		equal = Qd.EqualRgn(tempRgn, desktopRgn)
-		Qd.DisposeRgn(tempRgn)
-		if equal:
-			return bounds
-		else:
-			preferredsize = r - l, b - t
-	if not minsize:
-		minsize = preferredsize
-	minwidth, minheight = minsize
-	width, height = preferredsize
-	
-	sl, st, sr, sb = screenbounds = Qd.InsetRect(Qd.GetQDGlobalsScreenBits().bounds, 4, 4)
-	l, t = getnextwindowpos()
-	if (l + width) > sr:
-		_windowcounter = 0
-		l, t = getnextwindowpos()
-	r = l + width
-	b = t + height
-	if (t + height) > sb:
-		b = sb
-		if (b - t) < minheight:
-			b = t + minheight
-	return l, t, r, b
+    "Return sensible window bounds"
+
+    global _windowcounter
+    if len(preferredsize) == 4:
+        bounds = l, t, r, b = preferredsize
+        desktopRgn = Win.GetGrayRgn()
+        tempRgn = Qd.NewRgn()
+        Qd.RectRgn(tempRgn, bounds)
+        union = Qd.UnionRgn(tempRgn, desktopRgn, tempRgn)
+        equal = Qd.EqualRgn(tempRgn, desktopRgn)
+        Qd.DisposeRgn(tempRgn)
+        if equal:
+            return bounds
+        else:
+            preferredsize = r - l, b - t
+    if not minsize:
+        minsize = preferredsize
+    minwidth, minheight = minsize
+    width, height = preferredsize
+
+    sl, st, sr, sb = screenbounds = Qd.InsetRect(Qd.GetQDGlobalsScreenBits().bounds, 4, 4)
+    l, t = getnextwindowpos()
+    if (l + width) > sr:
+        _windowcounter = 0
+        l, t = getnextwindowpos()
+    r = l + width
+    b = t + height
+    if (t + height) > sb:
+        b = sb
+        if (b - t) < minheight:
+            b = t + minheight
+    return l, t, r, b
 
 scratchRegion = Qd.NewRgn()
 
 # util -- move somewhere convenient???
 def GetRgnBounds(the_Rgn):
-	(t, l, b, r) = struct.unpack("hhhh", the_Rgn.data[2:10])
-	return (l, t, r, b)
+    (t, l, b, r) = struct.unpack("hhhh", the_Rgn.data[2:10])
+    return (l, t, r, b)