# wdb.py -- a window-based Python debugger

# XXX To do:
# - don't fall out of bottom frame


import stdwin
from stdwinevents import *
import sys
import basewin
import bdb
import repr

WIDTH = 40
HEIGHT = 8

WdbDone = 'wdb.WdbDone' # Exception to continue execution


class Wdb(bdb.Bdb, basewin.BaseWindow): # Window debugger
	
	def __init__(self):
		self.sourcewindows = {}
		self.framewindows = {}
		bdb.Bdb.__init__(self)
		width = WIDTH*stdwin.textwidth('0')
		height = HEIGHT*stdwin.lineheight()
		stdwin.setdefwinsize(width, height)
		basewin.BaseWindow.__init__(self, '--Stack--')
		self.closed = 0
	
	def reset(self):
		if self.closed: raise RuntimeError, 'already closed'
		bdb.Bdb.reset(self)
		self.forget()
	
	def forget(self):
		self.lineno = None
		self.stack = []
		self.curindex = 0
		self.curframe = None
		for fn in self.sourcewindows.keys():
			self.sourcewindows[fn].resetlineno()
	
	def setup(self, f, t):
		self.forget()
		self.stack, self.curindex = self.get_stack(f, t)
		self.curframe = self.stack[self.curindex][0]
		# Build a list of current frames
		cfl = []
		for f, i in self.stack: cfl.append(f)
		# Remove deactivated frame windows
		for name in self.framewindows.keys():
			fw = self.framewindows[name]
			if fw.frame not in cfl: fw.close()
			else: fw.refreshframe()
		# Refresh the stack window
		self.refreshstack()
	
	# Override Bdb methods (except user_call, for now)
	
	def user_line(self, frame):
		# This function is called when we stop or break at this line
		self.interaction(frame, None)
	
	def user_return(self, frame, return_value):
		# This function is called when a return trap is set here
		frame.f_locals['__return__'] = return_value
		self.settitle('--Return--')
		self.interaction(frame, None)
		if not self.closed:
			self.settitle('--Stack--')
	
	def user_exception(self, frame, (exc_type, exc_value, exc_traceback)):
		# This function is called if an exception occurs,
		# but only if we are to stop at or just below this level
		frame.f_locals['__exception__'] = exc_type, exc_value
		if type(exc_type) == type(''):
			exc_type_name = exc_type
		else: exc_type_name = exc_type.__name__
		self.settitle(exc_type_name + ': ' + repr.repr(exc_value))
		stdwin.fleep()
		self.interaction(frame, exc_traceback)
		if not self.closed:
			self.settitle('--Stack--')
	
	# Change the title
	
	def settitle(self, title):
		self.savetitle = self.win.gettitle()
		self.win.settitle(title)
	
	# General interaction function
	
	def interaction(self, frame, traceback):
		import mainloop
		self.popup()
		self.setup(frame, traceback)
		try:
			mainloop.mainloop()
		except WdbDone:
			pass
		self.forget()
	
	# Functions whose name is do_X for some character X
	# are callable directly from the keyboard.
	
	def do_up(self):
		if self.curindex == 0:
			stdwin.fleep()
		else:
			self.curindex = self.curindex - 1
			self.curframe = self.stack[self.curindex][0]
			self.refreshstack()
	do_u = do_up
	
	def do_down(self):
		if self.curindex + 1 == len(self.stack):
			stdwin.fleep()
		else:
			self.curindex = self.curindex + 1
			self.curframe = self.stack[self.curindex][0]
			self.refreshstack()
	do_d = do_down
	
	def do_step(self):
		self.set_step()
		raise WdbDone
	do_s = do_step
	
	def do_next(self):
		self.set_next(self.curframe)
		raise WdbDone
	do_n = do_next
	
	def do_return(self):
		self.set_return(self.curframe)
		raise WdbDone
	do_r = do_return
	
	def do_continue(self):
		self.set_continue()
		raise WdbDone
	do_c = do_cont = do_continue
	
	def do_quit(self):
		self.close()
		raise WdbDone
	do_q = do_quit
	
	def do_list(self):
		fn = self.curframe.f_code.co_filename
		if not self.sourcewindows.has_key(fn):
			import wdbsrcwin
			try:
				self.sourcewindows[fn] = wdbsrcwin. \
					  DebuggerSourceWindow(self, fn)
			except IOError:
				stdwin.fleep()
				return
		w = self.sourcewindows[fn]
		lineno = self.stack[self.curindex][1]
		w.setlineno(lineno)
		w.popup()
	do_l = do_list
	
	def do_frame(self):
		name = 'locals' + `self.curframe`[16:-1]
		if self.framewindows.has_key(name):
			self.framewindows[name].popup()
		else:
			import wdbframewin
			self.framewindows[name] = \
				wdbframewin.FrameWindow(self, \
					self.curframe, \
					self.curframe.f_locals, name)
	do_f = do_frame
	
	def do_globalframe(self):
		name = 'globals' + `self.curframe`[16:-1]
		if self.framewindows.has_key(name):
			self.framewindows[name].popup()
		else:
			import wdbframewin
			self.framewindows[name] = \
				wdbframewin.FrameWindow(self, \
					self.curframe, \
					self.curframe.f_globals, name)
	do_g = do_globalframe
	
	# Link between the debugger and the window
	
	def refreshstack(self):
		height = stdwin.lineheight() * (1 + len(self.stack))
		self.win.setdocsize((0, height))
		self.refreshall() # XXX be more subtle later
		# Also pass the information on to the source windows
		filename = self.curframe.f_code.co_filename
		lineno = self.curframe.f_lineno
		for fn in self.sourcewindows.keys():
			w = self.sourcewindows[fn]
			if fn == filename:
				w.setlineno(lineno)
			else:
				w.resetlineno()
	
	# The remaining methods override BaseWindow methods
	
	def close(self):
		if not self.closed:
			basewin.BaseWindow.close(self)
		self.closed = 1
		for key in self.sourcewindows.keys():
			self.sourcewindows[key].close()
		for key in self.framewindows.keys():
			self.framewindows[key].close()
		self.set_quit()
	
	def char(self, detail):
		try:
			func = eval('self.do_' + detail)
		except (AttributeError, SyntaxError):
			stdwin.fleep()
			return
		func()
	
	def command(self, detail):
		if detail == WC_UP:
			self.do_up()
		elif detail == WC_DOWN:
			self.do_down()
	
	def mouse_down(self, detail):
		(h, v), clicks, button, mask = detail
		i = v / stdwin.lineheight()
		if 0 <= i < len(self.stack):
			if i != self.curindex:
				self.curindex = i
				self.curframe = self.stack[self.curindex][0]
				self.refreshstack()
			elif clicks == 2:
				self.do_frame()
		else:
			stdwin.fleep()
	
	def draw(self, detail):
		import linecache, string
		d = self.win.begindrawing()
		try:
			h, v = 0, 0
			for f, lineno in self.stack:
				fn = f.f_code.co_filename
				if f is self.curframe:
					s = '> '
				else:
					s = '  '
				s = s + fn + '(' + `lineno` + ')'
				s = s + f.f_code.co_name
				if f.f_locals.has_key('__args__'):
					args = f.f_locals['__args__']
					if args is not None:
						s = s + repr.repr(args)
				if f.f_locals.has_key('__return__'):
					rv = f.f_locals['__return__']
					s = s + '->'
					s = s + repr.repr(rv)
				line = linecache.getline(fn, lineno)
				if line: s = s + ': ' + string.strip(line)
				d.text((h, v), s)
				v = v + d.lineheight()
		finally:
			d.close()


# Simplified interface

def run(statement, globals=None, locals=None):
	x = Wdb()
	try: x.run(statement, globals, locals)
	finally: x.close()

def runeval(expression, globals=None, locals=None):
	x = Wdb()
	try: return x.runeval(expression, globals, locals)
	finally: x.close()

def runctx(statement, globals, locals):
	# B/W compatibility
	run(statement, globals, locals)

def runcall(*args):
	x = Wdb()
	try: return apply(x.runcall, args)
	finally: x.close()

def set_trace():
	Wdb().set_trace()

# Post-Mortem interface

def post_mortem(traceback):
	x = Wdb()
	x.reset()
	x.interaction(None, traceback)

def pm():
	import sys
	post_mortem(sys.last_traceback)


# Main program for testing

TESTCMD = 'import x; x.main()'

def test():
	run(TESTCMD)
