import FrameWork
from Carbon import Win
from Carbon import Qd
from Carbon import Evt
import MacOS
from Carbon import Events
import traceback
from types import *
from Carbon import Menu; MenuToolbox = Menu; del Menu
import macresource

if hasattr(Win, "FrontNonFloatingWindow"):
	MyFrontWindow = Win.FrontNonFloatingWindow
else:
	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 %s; 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 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-" +`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
		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 done is None:
			done = {}
		if done.has_key(top):
			return
		done[top] = 1
		import os, macfs, string
		try:
			names = os.listdir(top)
		except os.error:
			FrameWork.MenuItem(menu, '(Scripts Folder not found)', None, None)
			return
		savedir = os.getcwd()
		os.chdir(top)
		for name in names:
			if name == "CVS":
				continue
			try:
				fss, isdir, isalias = macfs.ResolveAliasFile(name)
			except:
				# maybe a broken alias
				continue
			path = fss.as_pathname()
			if done.has_key(path):
				continue
			name = string.strip(name)
			if name[-3:] == '---':
				menu.addseparator()
			elif isdir:
				submenu = FrameWork.SubMenu(menu, name)
				self.scriptswalk(path, submenu, done)
			else:
				creator, type = fss.GetCreatorType()
				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)
	
	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)
	

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

