Initial revision
diff --git a/Demo/tkinter/guido/MimeViewer.py b/Demo/tkinter/guido/MimeViewer.py
new file mode 100755
index 0000000..5bf194a
--- /dev/null
+++ b/Demo/tkinter/guido/MimeViewer.py
@@ -0,0 +1,143 @@
+#! /ufs/guido/bin/sgi/tkpython
+
+# View a single MIME multipart message.
+# Display each part as a box.
+
+import string
+from types import *
+from Tkinter import *
+from ScrolledText import ScrolledText
+
+class MimeViewer:
+	def __init__(self, parent, title, msg):
+		self.title = title
+		self.msg = msg
+		self.frame = Frame(parent, {'relief': 'raised', 'bd': 2})
+		self.frame.packing = {'expand': 0, 'fill': 'both'}
+		self.button = Checkbutton(self.frame,
+				     {'text': title,
+				      'command': self.toggle})
+		self.button.pack({'anchor': 'w'})
+		headertext = msg.getheadertext(
+			lambda x: x != 'received' and x[:5] != 'x400-')
+		height = countlines(headertext, 4)
+		if height:
+			self.htext = ScrolledText(self.frame,
+					  {'height': height,
+					   'width': 80,
+					   'wrap': 'none',
+					   'relief': 'raised',
+					   'bd': 2})
+			self.htext.packing = {'expand': 1, 'fill': 'both',
+					      'after': self.button}
+			self.htext.insert('end', headertext)
+		else:
+			self.htext = Frame(self.frame,
+					   {'relief': 'raised', 'bd': 2})
+			self.htext.packing = {'side': 'top',
+					      'ipady': 2,
+					      'fill': 'x',
+					      'after': self.button}
+		body = msg.getbody()
+		if type(body) == StringType:
+			self.pad = None
+			height = countlines(body, 10)
+			if height:
+				self.btext = ScrolledText(self.frame,
+						  {'height': height,
+						   'width': 80,
+						   'wrap': 'none',
+						   'relief': 'raised',
+						   'bd': 2})
+				self.btext.packing = {'expand': 1,
+						      'fill': 'both'}
+				self.btext.insert('end', body)
+			else:
+				self.btext = None
+			self.parts = None
+		else:
+			self.pad = Frame(self.frame,
+					 {'relief': 'flat', 'bd': 2})
+			self.pad.packing = {'side': 'left', 'ipadx': 10,
+					    'fill': 'y', 'after': self.htext}
+			self.parts = []
+			for i in range(len(body)):
+				p = MimeViewer(self.frame,
+					       '%s.%d' % (title, i+1),
+					       body[i])
+				self.parts.append(p)
+			self.btext = None
+		self.collapsed = 1
+	def pack(self):
+		self.frame.pack(self.frame.packing)
+	def destroy(self):
+		self.frame.destroy()
+	def show(self):
+		if self.collapsed:
+			self.button.invoke()
+	def toggle(self):
+		if self.collapsed:
+			self.explode()
+		else:
+			self.collapse()
+	def collapse(self):
+		self.collapsed = 1
+		for comp in self.htext, self.btext, self.pad:
+			if comp:
+				comp.forget()
+		if self.parts:
+			for part in self.parts:
+				part.frame.forget()
+		self.frame.pack({'expand': 0})
+	def explode(self):
+		self.collapsed = 0
+		for comp in self.htext, self.btext, self.pad:
+			if comp: comp.pack(comp.packing)
+		if self.parts:
+			for part in self.parts:
+				part.pack()
+		self.frame.pack({'expand': 1})
+
+def countlines(str, limit):
+	i = 0
+	n = 0
+	while  n < limit:
+		i = string.find(str, '\n', i)
+		if i < 0: break
+		n = n+1
+		i = i+1
+	return n
+
+def main():
+	import sys
+	import getopt
+	import mhlib
+	opts, args = getopt.getopt(sys.argv[1:], '')
+	for o, a in opts:
+		pass
+	message = None
+	folder = 'inbox'
+	for arg in args:
+		if arg[:1] == '+':
+			folder = arg[1:]
+		else:
+			message = string.atoi(arg)
+
+	mh = mhlib.MH()
+	f = mh.openfolder(folder)
+	if not message:
+		message = f.getcurrent()
+	m = f.openmessage(message)
+
+	root = Tk()
+	tk = root.tk
+
+	top = MimeViewer(root, '+%s/%d' % (folder, message), m)
+	top.pack()
+	top.show()
+
+	root.minsize(1, 1)
+
+	tk.mainloop()
+
+if __name__ == '__main__': main()
diff --git a/Demo/tkinter/guido/dialog.py b/Demo/tkinter/guido/dialog.py
new file mode 100755
index 0000000..31f5340
--- /dev/null
+++ b/Demo/tkinter/guido/dialog.py
@@ -0,0 +1,119 @@
+#! /ufs/guido/bin/sgi/tkpython
+
+# A Python function that generates dialog boxes with a text message,
+# optional bitmap, and any number of buttons.
+# Cf. Ousterhout, Tcl and the Tk Toolkit, Figs. 27.2-3, pp. 269-270.
+
+from Tkinter import *
+
+def dialog(master, title, text, bitmap, default, *args):
+
+    # 1. Create the top-level window and divide it into top
+    # and bottom parts.
+
+    w = Toplevel(master, {'class': 'Dialog'})
+    w.tk.call('global', 'button')
+    w.title(title)
+    w.iconname('Dialog')
+
+    top = Frame(w, {'relief': 'raised', 'bd': 1,
+		    Pack: {'side': 'top', 'fill': 'both'}})
+    bot = Frame(w, {'relief': 'raised', 'bd': 1,
+		    Pack: {'side': 'bottom', 'fill': 'both'}})
+
+    # 2. Fill the top part with the bitmap and message.
+
+    msg = Message(top,
+		  {'width': '3i',
+		   'text': text,
+		   'font': '-Adobe-Times-Medium-R-Normal-*-180-*',
+		   Pack: {'side': 'right', 'expand': 1,
+			  'fill': 'both',
+			  'padx': '3m', 'pady': '3m'}})
+    if bitmap:
+	bm = Label(top, {'bitmap': bitmap,
+			 Pack: {'side': 'left',
+				'padx': '3m', 'pady': '3m'}})
+
+    # 3. Create a row of buttons at the bottom of the dialog.
+
+    buttons = []
+    i = 0
+    for but in args:
+	b = Button(bot, {'text': but,
+			 'command': ('set', 'button', i)})
+	buttons.append(b)
+	if i == default:
+	    bd = Frame(bot, {'relief': 'sunken', 'bd': 1,
+			     Pack: {'side': 'left', 'expand': 1,
+				    'padx': '3m', 'pady': '2m'}})
+	    w.tk.call('raise', b)
+	    b.pack ({'in': bd, 'side': 'left',
+		     'padx': '2m', 'pady': '2m',
+		     'ipadx': '2m', 'ipady': '1m'})
+	else:
+	    b.pack ({'side': 'left', 'expand': 1,
+		     'padx': '3m', 'pady': '3m',
+		     'ipady': '2m', 'ipady': '1m'})
+	i = i+1
+
+    # 4. Set up a binding for <Return>, if there's a default,
+    # set a grab, and claim the focus too.
+
+    if default >= 0:
+	w.bind('<Return>',
+	       lambda b=buttons[default], i=default:
+	       (b.cmd('flash'),
+		b.tk.call('set', 'button', i)))
+
+    oldFocus = w.tk.call('focus')
+    w.tk.call('grab', 'set', w)
+    w.tk.call('focus', w)
+
+    # 5. Wait for the user to respond, then restore the focus
+    # and return the index of the selected button.
+
+    w.tk.call('tkwait', 'variable', 'button')
+    w.tk.call('destroy', w)
+    w.tk.call('focus', oldFocus)
+    return w.tk.call('set', 'button')
+
+# The rest is the test program.
+
+def go():
+    i = dialog(mainWidget,
+	       'Not Responding',
+	       "The file server isn't responding right now; "
+	       "I'll keep trying.",
+	       '',
+	       -1,
+	       'OK')
+    print 'pressed button', i
+    i = dialog(mainWidget,
+	       'File Modified',
+	       'File "tcl.h" has been modified since '
+	       'the last time it was saved. '
+	       'Do you want to save it before exiting the application?',
+	       'warning',
+	       0,
+	       'Save File',
+	       'Discard Changes',
+	       'Return To Editor')
+    print 'pressed button', i
+
+def test():
+    import sys
+    global mainWidget
+    mainWidget = Frame()
+    Pack.config(mainWidget)
+    start = Button(mainWidget,
+		   {'text': 'Press Here To Start', 'command': go})
+    start.pack()
+    endit = Button(mainWidget,
+		   {'text': 'Exit',
+		    'command': 'exit',
+		    Pack: {'fill' : 'both'}})
+    mainWidget.tk.mainloop()
+
+if __name__ == '__main__':
+    test()
diff --git a/Demo/tkinter/guido/mbox.py b/Demo/tkinter/guido/mbox.py
new file mode 100755
index 0000000..a4e86da
--- /dev/null
+++ b/Demo/tkinter/guido/mbox.py
@@ -0,0 +1,288 @@
+#! /ufs/guido/bin/sgi/tkpython
+
+# Scan MH folder, display results in window
+
+import os
+import sys
+import regex
+import getopt
+import string
+import mhlib
+
+from Tkinter import *
+
+from dialog import dialog
+
+mailbox = os.environ['HOME'] + '/Mail'
+
+def main():
+	global root, tk, top, mid, bot
+	global folderbox, foldermenu, scanbox, scanmenu, viewer
+	global folder, seq
+	global mh, mhf
+
+	# Parse command line options
+
+	folder = 'inbox'
+	seq = 'all'
+	try:
+		opts, args = getopt.getopt(sys.argv[1:], '')
+	except getopt.error, msg:
+		print msg
+		sys.exit(2)
+	for arg in args:
+		if arg[:1] == '+':
+			folder = arg[1:]
+		else:
+			seq = arg
+
+	# Initialize MH
+
+	mh = mhlib.MH()
+	mhf = mh.openfolder(folder)
+
+	# Build widget hierarchy
+
+	root = Tk()
+	tk = root.tk
+
+	top = Frame(root)
+	top.pack({'expand': 1, 'fill': 'both'})
+
+	# Build right part: folder list
+
+	right = Frame(top)
+	right.pack({'fill': 'y', 'side': 'right'})
+
+	folderbar = Scrollbar(right, {'relief': 'sunken', 'bd': 2})
+	folderbar.pack({'fill': 'y', 'side': 'right'})
+
+	folderbox = Listbox(right)
+	folderbox.pack({'expand': 1, 'fill': 'both', 'side': 'left'})
+
+	foldermenu = Menu(root)
+	foldermenu.add('command',
+		       {'label': 'Open Folder',
+			'command': open_folder})
+	foldermenu.add('separator')
+	foldermenu.add('command',
+		       {'label': 'Quit',
+			'command': 'exit'})
+	foldermenu.bind('<ButtonRelease-3>', folder_unpost)
+
+	folderbox['yscrollcommand'] = (folderbar, 'set')
+	folderbar['command'] = (folderbox, 'yview')
+	folderbox.bind('<Double-1>', open_folder, 1)
+	folderbox.bind('<3>', folder_post)
+
+	# Build left part: scan list
+
+	left = Frame(top)
+	left.pack({'expand': 1, 'fill': 'both', 'side': 'left'})
+
+	scanbar = Scrollbar(left, {'relief': 'sunken', 'bd': 2})
+	scanbar.pack({'fill': 'y', 'side': 'right'})
+
+	scanbox = Listbox(left, {'font': 'fixed'})
+	scanbox.pack({'expand': 1, 'fill': 'both', 'side': 'left'})
+
+	scanmenu = Menu(root)
+	scanmenu.add('command',
+		     {'label': 'Open Message',
+		      'command': open_message})
+	scanmenu.add('command',
+		     {'label': 'Remove Message',
+		      'command': remove_message})
+	scanmenu.add('command',
+		     {'label': 'Refile Message',
+		      'command': refile_message})
+	scanmenu.add('separator')
+	scanmenu.add('command',
+		     {'label': 'Quit',
+		      'command': 'exit'})
+	scanmenu.bind('<ButtonRelease-3>', scan_unpost)
+
+	scanbox['yscrollcommand'] = (scanbar, 'set')
+	scanbar['command'] = (scanbox, 'yview')
+	scanbox.bind('<Double-1>', open_message)
+	scanbox.bind('<3>', scan_post)
+
+	# Separator between middle and bottom part
+
+	rule2 = Frame(root, {'bg': 'black'})
+	rule2.pack({'fill': 'x'})
+
+	# Build bottom part: current message
+
+	bot = Frame(root)
+	bot.pack({'expand': 1, 'fill': 'both'})
+	#
+	viewer = None
+
+	# Window manager commands
+
+	root.minsize(800, 1) # Make window resizable
+
+	# Fill folderbox with text
+
+	setfolders()
+
+	# Fill scanbox with text
+
+	rescan()
+
+	# Enter mainloop
+
+	root.mainloop()
+
+def folder_post(e):
+	x, y = e.x_root, e.y_root
+	foldermenu.post(x - 10, y - 10)
+	foldermenu.grab_set()
+
+def folder_unpost(e):
+	tk.call('update', 'idletasks')
+	foldermenu.grab_release()
+	foldermenu.unpost()
+	foldermenu.invoke('active')
+
+def scan_post(e):
+	x, y = e.x_root, e.y_root
+	scanmenu.post(x - 10, y - 10)
+	scanmenu.grab_set()
+
+def scan_unpost(e):
+	tk.call('update', 'idletasks')
+	scanmenu.grab_release()
+	scanmenu.unpost()
+	scanmenu.invoke('active')
+
+scanparser = regex.compile('^ *\([0-9]+\)')
+
+def open_folder(*e):
+	global folder, mhf
+	sel = folderbox.curselection()
+	if len(sel) != 1:
+		if len(sel) > 1:
+			msg = "Please open one folder at a time"
+		else:
+			msg = "Please select a folder to open"
+		dialog(root, "Can't Open Folder", msg, "", 0, "OK")
+		return
+	i = sel[0]
+	folder = folderbox.get(i)
+	mhf = mh.openfolder(folder)
+	rescan()
+
+def open_message(*e):
+	global viewer
+	sel = scanbox.curselection()
+	if len(sel) != 1:
+		if len(sel) > 1:
+			msg = "Please open one message at a time"
+		else:
+			msg = "Please select a message to open"
+		dialog(root, "Can't Open Message", msg, "", 0, "OK")
+		return
+	cursor = scanbox['cursor']
+	scanbox['cursor'] = 'watch'
+	tk.call('update', 'idletasks')
+	i = sel[0]
+	line = scanbox.get(i)
+	if scanparser.match(line) >= 0:
+		num = string.atoi(scanparser.group(1))
+		m = mhf.openmessage(num)
+		if viewer: viewer.destroy()
+		from MimeViewer import MimeViewer
+		viewer = MimeViewer(bot, '+%s/%d' % (folder, num), m)
+		viewer.pack()
+		viewer.show()
+	scanbox['cursor'] = cursor
+
+def interestingheader(header):
+	return header != 'received'
+
+def remove_message():
+	itop = scanbox.nearest(0)
+	sel = scanbox.curselection()
+	if not sel:
+		dialog(root, "No Message To Remove",
+		       "Please select a message to remove", "", 0, "OK")
+		return
+	todo = []
+	for i in sel:
+		line = scanbox.get(i)
+		if scanparser.match(line) >= 0:
+			todo.append(string.atoi(scanparser.group(1)))
+	mhf.removemessages(todo)
+	rescan()
+	fixfocus(min(todo), itop)
+
+lastrefile = ''
+tofolder = None
+def refile_message():
+	global lastrefile, tofolder
+	itop = scanbox.nearest(0)
+	sel = scanbox.curselection()
+	if not sel:
+		dialog(root, "No Message To Refile",
+		       "Please select a message to refile", "", 0, "OK")
+		return
+	foldersel = folderbox.curselection()
+	if len(foldersel) != 1:
+		if not foldersel:
+			msg = "Please select a folder to refile to"
+		else:
+			msg = "Please select exactly one folder to refile to"
+		dialog(root, "No Folder To Refile", msg, "", 0, "OK")
+		return
+	refileto = folderbox.get(foldersel[0])
+	todo = []
+	for i in sel:
+		line = scanbox.get(i)
+		if scanparser.match(line) >= 0:
+			todo.append(string.atoi(scanparser.group(1)))
+	print 'refile', todo, tofolder
+	if lastrefile != refileto or not tofolder:
+		print 'new folder'
+		lastrefile = refileto
+		tofolder = None
+		tofolder = mh.openfolder(lastrefile)
+	mhf.refilemessages(todo, tofolder)
+	rescan()
+	fixfocus(min(todo), itop)
+
+def fixfocus(near, itop):
+	n = scanbox.size()
+	for i in range(n):
+		line = scanbox.get(`i`)
+		if scanparser.match(line) >= 0:
+			num = string.atoi(scanparser.group(1))
+			if num >= near:
+				break
+	else:
+		i = 'end'
+	scanbox.select_from(i)
+	print 'yview', `itop`
+	scanbox.yview(itop)
+
+def setfolders():
+	folderbox.delete(0, 'end')
+	for fn in mh.listallfolders():
+		folderbox.insert('end', fn)
+
+def rescan():
+	global viewer
+	if viewer:
+		viewer.destroy()
+		viewer = None
+	scanbox.delete(0, 'end')
+	for line in scanfolder(folder, seq):
+		scanbox.insert('end', line)
+
+def scanfolder(folder = 'inbox', sequence = 'all'):
+	return map(
+		lambda line: line[:-1],
+		os.popen('scan +%s %s' % (folder, sequence), 'r').readlines())
+
+main()
diff --git a/Demo/tkinter/guido/rmt.py b/Demo/tkinter/guido/rmt.py
new file mode 100755
index 0000000..2ac2408
--- /dev/null
+++ b/Demo/tkinter/guido/rmt.py
@@ -0,0 +1,152 @@
+#! /ufs/guido/bin/sgi/tkpython
+
+# A Python program implementing rmt, an application for remotely
+# controlling other Tk applications.
+# Cf. Ousterhout, Tcl and the Tk Toolkit, Figs. 27.5-8, pp. 273-276.
+
+# Note that because of forward references in the original, we
+# sometimes delay bindings until after the corresponding procedure is
+# defined.  We also introduce names for some unnamed code blocks in
+# the original because of restrictions on lambda forms in Python.
+
+from Tkinter import *
+
+# 1. Create basic application structure: menu bar on top of
+# text widget, scrollbar on right.
+
+root = Tk()
+tk = root.tk
+mBar = Frame(root, {'relief': 'raised', 'bd': 2,
+		    Pack: {'side': 'top', 'fill': 'x'}})
+f = Frame(root)
+f.pack({'expand': 1, 'fill': 'both'})
+s = Scrollbar(f, {'relief': 'flat',
+		  Pack: {'side': 'right', 'fill': 'y'}})
+t = Text(f, {'relief': 'raised', 'bd': 2, 'yscrollcommand': (s, 'set'),
+	     'setgrid': 1,
+	     Pack: {'side': 'left', 'fill': 'both', 'expand': 1}})
+
+t.tag_config('bold', {'font': '-Adobe-Courier-Bold-R-Normal-*-120-*'}) 
+s['command'] = (t, 'yview')
+root.title('Tk Remote Controller')
+root.iconname('Tk Remote')
+
+# 2. Create menu button and menus.
+
+file = Menubutton(mBar, {'text': 'File', 'underline': 0,
+			 Pack: {'side': 'left'}})
+file_m = Menu(file)
+file['menu'] = file_m
+file_m_apps = Menu(file_m)
+file_m.add('cascade', {'label': 'Select Application', 'underline': 0,
+		       'menu': file_m_apps})
+file_m.add('command', {'label': 'Quit', 'underline': 0, 'command': 'exit'})
+
+# 3. Create bindings for text widget to allow commands to be
+# entered and information to be selected.  New characters
+# can only be added at the end of the text (can't ever move
+# insertion point).
+
+def single1(e):
+	x = e.x
+	y = e.y
+	tk.setvar('tk_priv(selectMode)', 'char')
+	t.mark_set('anchor', At(x, y))
+	# Should focus W
+t.bind('<1>', single1)
+
+def double1(e):
+	x = e.x
+	y = e.y
+	tk.setvar('tk_priv(selectMode)', 'word')
+	tk.call('tk_textSelectTo', t, At(x, y))
+t.bind('<Double-1>', double1)
+
+def triple1(e):
+	x = e.x
+	y = e.y
+	tk.setvar('tk_priv(selectMode)', 'line')
+	tk.call('tk_textSelectTo', t, At(x, y))
+t.bind('<Triple-1>', triple1)
+
+def returnkey(e):
+	t.insert('insert', '\n')
+	invoke()
+t.bind('<Return>', returnkey)
+
+def controlv(e):
+	t.insert('insert', tk.call('selection', 'get'))
+	t.yview_pickplace('insert')
+	if t.index('insert')[-2:] == '.0':
+		invoke()
+t.bind('<Control-v>', controlv)
+
+# 4. Procedure to backspace over one character, as long as
+# the character isn't part of the prompt.
+
+def backspace(e):
+	if t.index('promptEnd') != t.index('insert - 1 char'):
+		t.delete('insert - 1 char', 'insert')
+		t.yview_pickplace('insert')
+t.bind('<BackSpace>', backspace)
+t.bind('<Control-h>', backspace)
+t.bind('<Delete>', backspace)
+
+
+# 5. Procedure that's invoked when return is typed:  if
+# there's not yet a complete command (e.g. braces are open)
+# then do nothing.  Otherwise, execute command (locally or
+# remotely), output the result or error message, and issue
+# a new prompt.
+
+def invoke():
+	cmd = t.get('promptEnd + 1 char', 'insert')
+	if tk.getboolean(tk.call('info', 'complete', cmd)):
+		if app == tk.call('winfo', 'name', '.'):
+			msg = tk.call('eval', cmd)
+		else:
+			msg = tk.call('send', app, cmd)
+		if msg:
+			t.insert('insert', msg + '\n')
+		prompt()
+	t.yview_pickplace('insert')
+
+def prompt():
+	t.insert('insert', app + ': ')
+	t.mark_set('promptEnd', 'insert - 1 char')
+	t.tag_add('bold', 'insert linestart', 'promptEnd')
+
+# 6. Procedure to select a new application.  Also changes
+# the prompt on the current command line to reflect the new
+# name.
+
+def newApp(appName):
+	global app
+	app = appName
+	t.delete('promptEnd linestart', 'promptEnd')
+	t.insert('promptEnd', appName + ':')
+	t.tag_add('bold', 'promptEnd linestart', 'promptEnd')
+
+newApp_tcl = `id(newApp)`
+tk.createcommand(newApp_tcl, newApp)
+
+def fillAppsMenu():
+	file_m_apps.add('command')
+	file_m_apps.delete(0, 'last')
+	names = tk.splitlist(tk.call('winfo', 'interps'))
+	names = map(None, names) # convert tuple to list
+	names.sort()
+	for name in names:
+		file_m_apps.add('command', {'label': name,
+					    'command': (newApp_tcl, name)})
+
+file_m_apps['postcommand'] = fillAppsMenu
+mBar.tk_menuBar(file)
+
+# 7. Miscellaneous initialization.
+
+app = tk.call('winfo', 'name', '.')
+prompt()
+tk.call('focus', t)
+
+root.mainloop()
diff --git a/Demo/tkinter/guido/tst.py b/Demo/tkinter/guido/tst.py
new file mode 100755
index 0000000..ea573d2
--- /dev/null
+++ b/Demo/tkinter/guido/tst.py
@@ -0,0 +1,81 @@
+# tst.py
+from Tkinter import *
+import sys
+
+def do_hello():
+	print 'Hello world!'
+
+class Quit(Button):
+	def action(self):
+		self.quit()
+	def __init__(self, master=None, cnf={}):
+		Button.__init__(self, master, 
+				{'text': 'Quit', 
+				 'command': self.action})
+		Button.config(self, cnf)
+
+class Stuff(Canvas):
+	def enter(self, e):
+		print 'Enter'
+		self.itemconfig('current', {'fill': 'red'})
+	def leave(self, e):
+		print 'Leave'
+		self.itemconfig('current', {'fill': 'blue'})
+	def __init__(self, master=None, cnf={}):
+		Canvas.__init__(self, master, 
+				{'width': 100, 'height': 100})
+		Canvas.config(self, cnf)
+		self.create_rectangle(30, 30, 70, 70, 
+				      {'fill': 'red', 'tags': 'box'})
+		Canvas.bind(self, 'box', '<Enter>', self.enter)
+		Canvas.bind(self, 'box', '<Leave>', self.leave)
+
+class Test(Frame):
+	text = 'Testing'
+	num = 1
+	def do_xy(self, e):
+		print (e.x, e.y)
+	def do_test(self):
+		if not self.num % 10:
+			self.text = 'Testing 1 ...'
+		self.text = self.text + ' ' + `self.num`
+		self.num = self.num + 1
+		self.testing['text'] = self.text
+	def do_err(self):
+		1/0
+	def do_after(self):
+		self.testing.invoke()
+		self.after(10000, self.do_after)
+	def __init__(self, master=None):
+		Frame.__init__(self, master)
+		self['bd'] = 30
+		Pack.config(self)
+		self.bind('<Motion>', self.do_xy)
+		self.hello = Button(self, {'name': 'hello', 
+					   'text': 'Hello', 
+					   'command': do_hello,
+					   Pack: {'fill': 'both'}})
+		self.testing = Button(self)
+		self.testing['text'] = self.text
+		self.testing['command'] = self.do_test
+		Pack.config(self.testing, {'fill': 'both'})
+		self.err = Button(self, {'text': 'Error', 
+					 'command': self.do_err,
+					 Pack: {'fill': 'both'}})
+		self.quit = Quit(self, {Pack: {'fill': 'both'}})
+		self.exit = Button(self, 
+				   {'text': 'Exit', 
+				    'command': lambda: sys.exit(0),
+				    Pack: {'fill': 'both'}})
+		self.stuff = Stuff(self, {Pack: {'padx': 2, 'pady': 2}})
+		self.do_after()
+
+test = Test()
+test.master.title('Tkinter Test')
+test.master.iconname('Test')
+test.master.maxsize(500, 500)
+test.testing.invoke()
+
+# Use the -i option and type ^C to get a prompt
+test.mainloop()
+
diff --git a/Demo/tkinter/guido/wish.py b/Demo/tkinter/guido/wish.py
new file mode 100755
index 0000000..16cacde
--- /dev/null
+++ b/Demo/tkinter/guido/wish.py
@@ -0,0 +1,26 @@
+# This is about all it requires to write a wish shell in Python!
+
+import tkinter
+
+tk = tkinter.create(':0', 'wish', 'Tk', 1)
+tk.call('update')
+
+cmd = ''
+
+while 1:
+	if cmd: prompt = ''
+	else: prompt = '% '
+	try:
+		line = raw_input(prompt)
+	except EOFError:
+		break
+	cmd = cmd + (line + '\n')
+	tk.record(line)
+	if tk.getboolean(tk.call('info', 'complete', cmd)):
+		try:
+			result = tk.call('eval', cmd)
+		except tkinter.TclError, msg:
+			print 'TclError:', msg
+		else:
+			if result: print result
+		cmd = ''
diff --git a/Lib/lib-tk/Canvas.py b/Lib/lib-tk/Canvas.py
new file mode 100644
index 0000000..4d21928
--- /dev/null
+++ b/Lib/lib-tk/Canvas.py
@@ -0,0 +1,115 @@
+# This module exports classes for the various canvas item types
+
+# vi:set tabsize=4:
+
+from Tkinter import Canvas, _isfunctype
+
+class CanvasItem:
+	def __init__(self, canvas, itemType, args = (), cnf={}):
+		self.canvas = canvas
+		self.id = canvas._create(itemType, args + (cnf,))
+	def __str__(self):
+		return str(self.id)
+	def __repr__(self):
+		return '<%s, id=%d>' % (self.__class__.__name__, self.id)
+	def __del__(self):
+		self.canvas.delete(self.id)
+	delete = __del__
+	def __getitem__(self, key):
+		v = self.canvas.tk.split(self.canvas.tk.call(self.canvas.pathName, 
+							     'itemconfigure',
+							     str(self.id),
+							     '-' + key))
+		return v[4]
+	def __setitem__(self, key, value):
+		self.canvas._itemconfig(self.id, {key: value})
+	def keys(self):
+		if not hasattr(self, '_keys'):
+			self._keys = map(lambda x, tk=self.canvas.tk:
+							        tk.splitlist(x)[0][1:],
+							 self.canvas._splitlist(
+								 self.canvas.cmd('itemconfigure', self.id)))
+			return self._keys
+	def has_key(self, key):
+		return key in self.keys()
+	def addtag(self, tag, option='withtag'):
+		self.canvas.addtag(tag, option, self.id)
+	def bbox(self):
+		x1, y1, x2, y2 = self.canvas.bbox(self.id)
+		return (x1, y1), (x2, y2)
+	def bind(self, sequence=None, command=None):
+		return self.canvas.bind(self.id, sequence, command)
+	def coords(self, pts = ()):
+		flat = ()
+		for x, y in pts: flat = flat + (x, y)
+		return apply(self.canvas.coords, (self.id,) + flat)
+	def dchars(self, first, last=None):
+		self.canvas.dchars(self.id, first, last)
+	def dtag(self, ttd):
+		self.canvas.dtag(self.id, ttd)
+	def focus(self):
+		self.canvas.focus(self.id)
+	def gettags(self):
+		return self.canvas.gettags(self.id)
+	def icursor(self):
+		self.canvas.icursor(self.id)
+	def index(self):
+		return self.canvas.index(self.id)
+	def insert(self, beforethis, string):
+		self.canvas.insert(self.id, beforethis, string)
+	def lower(self, belowthis=None):
+		self.canvas.lower(self.id, belowthis)
+	def move(self, xamount, yamount):
+		self.canvas.move(self.id, xamount, yamount)
+	def raise_(self, abovethis=None):
+		self.canvas.raise_(self.id, abovethis)
+	def scale(self, xorigin, yorigin, xscale, yscale):
+		self.canvas.scale(self.id, xorigin, yorigin, xscale, yscale)
+	def type(self):
+		return self.canvas.type(self.id)
+
+class Arc(CanvasItem):
+	def __init__(self, canvas, (x1, y1), (x2, y2), cnf={}):
+		CanvasItem.__init__(self, canvas, 'arc',
+							(str(x1), str(y1), str(x2), str(y2)), cnf)
+
+class Bitmap(CanvasItem):
+	def __init__(self, canvas, (x1, y1), cnf={}):
+		CanvasItem.__init__(self, canvas, 'bitmap', (str(x1), str(y1)), cnf)
+
+class Line(CanvasItem):
+	def __init__(self, canvas, pts, cnf={}):
+		pts = reduce(lambda a, b: a+b,
+					 map(lambda pt: (str(pt[0]), str(pt[1])), pts))
+		CanvasItem.__init__(self, canvas, 'line', pts, cnf)
+
+class Oval(CanvasItem):
+	def __init__(self, canvas, (x1, y1), (x2, y2), cnf={}):
+		CanvasItem.__init__(self, canvas, 'oval',
+							(str(x1), str(y1), str(x2), str(y2)), cnf)
+
+class Polygon(CanvasItem):
+	def __init__(self, canvas, pts, cnf={}):
+		pts = reduce(lambda a, b: a+b,
+					 map(lambda pt: (str(pt[0]), str(pt[1])), pts))
+		CanvasItem.__init__(self, canvas, 'polygon', pts, cnf)
+
+class Curve(Polygon):
+	def __init__(self, canvas, pts, cnf={}):
+		cnf['smooth'] = 'yes'
+		Polygon.__init__(self, canvas, pts, cnf)
+
+class Rectangle(CanvasItem):
+	def __init__(self, canvas, (x1, y1), (x2, y2), cnf={}):
+		CanvasItem.__init__(self, canvas, 'rectangle',
+							(str(x1), str(y1), str(x2), str(y2)), cnf)
+
+# XXX Can't use name "Text" since that is already taken by the Text widget...
+class String(CanvasItem):
+	def __init__(self, canvas, (x1, y1), cnf={}):
+		CanvasItem.__init__(self, canvas, 'text', (str(x1), str(y1)), cnf)
+
+class Window(CanvasItem):
+	def __init__(self, canvas, where, cnf={}):
+		CanvasItem.__init__(self, canvas, 'window',
+							(str(where[0]), str(where[1])), cnf)
diff --git a/Lib/lib-tk/ScrolledText.py b/Lib/lib-tk/ScrolledText.py
new file mode 100644
index 0000000..9effae0
--- /dev/null
+++ b/Lib/lib-tk/ScrolledText.py
@@ -0,0 +1,35 @@
+# A ScrolledText widget feels like a text widget but also has a
+# vertical scroll bar on its right.  (Later, options may be added to
+# add a horizontal bar as well, to make the bars disappear
+# automatically when not needed, to move them to the other side of the
+# window, etc.)
+#
+# Configuration options are passed to the Text widget.
+# A Frame widget is inserted between the master and the text, to hold
+# the Scrollbar widget.
+# Most methods calls are passed to the Text widget; the pack command
+# is redirected to the Frame widget however.
+
+from Tkinter import *
+
+class ScrolledText(Pack, Place):
+	def __init__(self, master=None, cnf={}):
+		fcnf = {}
+		self.frame = Frame(master, {})
+		if cnf.has_key(Pack):
+			self.frame.pack(cnf[Pack])
+			del cnf[Pack]
+		self.vbar = Scrollbar(self.frame, {})
+		self.vbar.pack({'side': 'right', 'fill': 'y'})
+		cnf[Pack] = {'side': 'left', 'fill': 'both',
+			     'expand': 'yes'}
+		self.text = Text(self.frame, cnf)
+		self.text['yscrollcommand'] = (self.vbar, 'set')
+		self.vbar['command'] = (self.text, 'yview')
+		self.insert = self.text.insert
+		# XXX should do all Text methods...
+		self.pack = self.frame.pack
+		self.forget = self.frame.forget
+		self.tk = master.tk
+	def __str__(self):
+		return str(self.frame)
diff --git a/Lib/lib-tk/Tkinter.py b/Lib/lib-tk/Tkinter.py
new file mode 100644
index 0000000..e9e641c
--- /dev/null
+++ b/Lib/lib-tk/Tkinter.py
@@ -0,0 +1,874 @@
+# Tkinter.py -- Tk/Tcl widget wrappers
+import tkinter
+from tkinter import TclError
+
+class _Dummy:
+	def meth(self):	return
+
+def _isfunctype(func):
+	return type(func) in (type(_Dummy.meth), type(_isfunctype))	
+
+FunctionType = type(_isfunctype)
+ClassType = type(_Dummy)
+MethodType = type(_Dummy.meth)
+
+def tkerror(err):
+	pass
+
+class Event:
+	pass
+
+class Misc:
+	def tk_strictMotif(self, boolean=None):
+		self.tk.getboolean(self.tk.call(
+			'set', 'tk_strictMotif', boolean))
+	def waitvar(self, name='VAR'):
+		self.tk.call('tkwait', 'variable', name)
+	def setvar(self, name='VAR', value='1'):
+		self.tk.setvar(name, value)
+	def focus(self):
+		self.tk.call('focus', self._w)
+	def focus_default(self):
+		self.tk.call('focus', 'default', self._w)
+	def focus_none(self):
+		self.tk.call('focus', 'none')
+	#XXX focus_get?
+	def after(self, ms, func=None, *args):
+		if not func:
+			self.tk.call('after', ms)
+		else:
+			name = self._register(func)
+			apply(self.tk.call, ('after', ms, name) + args)
+	#XXX grab_current
+	def grab_release(self):
+		self.tk.call('grab', 'release', self._w)
+	def grab_set(self):
+		self.tk.call('grab', 'set', self._w)
+	def grab_set_global(self):
+		self.tk.call('grab', 'set', '-global', self._w)
+	def grab_status(self):
+		self.tk.call('grab', 'status', self._w)
+	def lower(self, belowThis=None):
+		self.tk.call('lower', self._w, belowThis)
+	def selection_clear(self):
+		self.tk.call('selection', 'clear', self._w)
+	def selection_get(self, type=None):
+		self.tk.call('selection', 'get', type)
+	def selection_handle(self, func, type=None, format=None):
+		name = self._register(func)
+		self.tk.call('selection', 'handle',
+			     self._w, name, type, format)
+	#XXX def selection_own(self):
+	#	self.tk.call('selection', 'own', self._w)
+	def send(self, interp, cmd, *args): #XXX
+		return apply(self.tk.call, ('send', interp, cmd) + args)
+	def colormodel(self, value=None):
+		return self.tk.call('tk', 'colormodel', self._w, value)
+	def winfo_atom(self, name):
+		return self.tk.getint(self.tk.call('winfo', 'atom', name))
+	def winfo_atomname(self, id):
+		return self.tk.call('winfo', 'atomname', id)
+	def winfo_cells(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'cells', self._w))
+	#XXX winfo_children
+	def winfo_class(self):
+		return self.tk.call('winfo', 'class', self._w)
+	def winfo_containing(self, rootX, rootY):
+		return self.tk.call('winfo', 'containing', rootx, rootY)
+	def winfo_depth(self):
+		return self.tk.getint(self.tk.call('winfo', 'depth', self._w))
+	def winfo_exists(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'exists', self._w))
+	def winfo_fpixels(self, number):
+		return self.tk.getdouble(self.tk.call(
+			'winfo', 'fpixels', self._w, number))
+	def winfo_geometry(self):
+		return self.tk.call('winfo', 'geometry', self._w)
+	def winfo_height(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'height', self._w))
+	def winfo_id(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'id', self._w))
+	def winfo_interps(self):
+		return self.tk.splitlist(
+			self.tk.call('winfo', 'interps'))
+	def winfo_ismapped(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'ismapped', self._w))
+	def winfo_name(self):
+		return self.tk.call('winfo', 'name', self._w)
+	def winfo_parent(self):
+		return self.tk.call('winfo', 'parent', self._w)
+	def winfo_pathname(self, id):
+		return self.tk.call('winfo', 'pathname', id)
+	def winfo_pixels(self, number):
+		return self.tk.getint(
+			self.tk.call('winfo', 'pixels', self._w, number))
+	def winfo_reqheight(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'reqheight', self._w))
+	def winfo_reqwidth(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'reqwidth', self._w))
+	def winfo_rgb(self, color):
+		return self._getints(
+			self.tk.call('winfo', 'rgb', self._w, color))
+	def winfo_rootx(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'rootx', self._w))
+	def winfo_rooty(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'rooty', self._w))
+	def winfo_screen(self):
+		return self.tk.call('winfo', 'screen', self._w)
+	def winfo_screencells(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'screencells', self._w))
+	def winfo_screendepth(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'screendepth', self._w))
+	def winfo_screenheight(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'screenheight', self._w))
+	def winfo_screenmmheight(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'screenmmheight', self._w))
+	def winfo_screenmmwidth(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'screenmmwidth', self._w))
+	def winfo_screenvisual(self):
+		return self.tk.call('winfo', 'screenvisual', self._w)
+	def winfo_screenwidth(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'screenwidth', self._w))
+	def winfo_toplevel(self):
+		return self.tk.call('winfo', 'toplevel', self._w)
+	def winfo_visual(self):
+		return self.tk.call('winfo', 'visual', self._w)
+	def winfo_vrootheight(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'vrootheight', self._w))
+	def winfo_vrootwidth(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'vrootwidth', self._w))
+	def winfo_vrootx(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'vrootx', self._w))
+	def winfo_vrooty(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'vrooty', self._w))
+	def winfo_width(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'width', self._w))
+	def winfo_x(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'x', self._w))
+	def winfo_y(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'y', self._w))
+	def update(self):
+		self.tk.call('update')
+	def update_idletasks(self):
+		self.tk.call('update', 'idletasks')
+	def bind(self, sequence, func, add=''):
+		global _substitute, _subst_prefix
+		if add: add = '+'
+		name = self._register(func, _substitute)
+		self.tk.call('bind', self._w, sequence, 
+			     (add + name,) + _subst_prefix)
+	def bind_all(self, sequence, func, add=''):
+		global _substitute, _subst_prefix
+		if add: add = '+'
+		name = self._register(func, _substitute)
+		self.tk.call('bind', 'all' , sequence, 
+			     (add + `name`,) + _subst_prefix)
+	def bind_class(self, className, sequence, func, add=''):
+		global _substitute, _subst_prefix
+		if add: add = '+'
+		name = self._register(func, _substitute)
+		self.tk.call('bind', className , sequence, 
+			     (add + name,) + _subst_prefix)
+	def mainloop(self):
+		self.tk.mainloop()
+	def quit(self):
+		self.tk.quit()
+	# Utilities
+	def _getints(self, string):
+		if string:
+			res = ()
+			for v in self.tk.split(string):
+				res = res +  (self.tk.getint(v),)
+			return res
+		else:
+			return string
+	def _getboolean(self, string):
+		if string:
+			return self.tk.getboolean(string)
+		else:
+			return string
+	def _options(self, cnf):
+		res = ()
+		for k, v in cnf.items():
+			if _isfunctype(v):
+				v = self._register(v)
+			res = res + ('-'+k, v)
+		return res
+	def _register(self, func, subst=None):
+		f = func
+		f = _CallSafely(func, subst).__call__
+		name = `id(f)`
+		if hasattr(func, 'im_func'):
+			func = func.im_func
+		if hasattr(func, 'func_name') and \
+		   type(func.func_name) == type(''):
+			name = name + func.func_name
+		self.tk.createcommand(name, f)
+		return name
+
+_subst_prefix = ('%#', '%b', '%f', '%h', '%k', 
+		 '%s', '%t', '%w', '%x', '%y',
+		 '%A', '%E', '%K', '%N', '%T', '%X', '%Y')
+
+def _substitute(*args):
+	global default_root
+	global _subst_prefix
+	tk = default_root.tk
+	if len(args) != len(_subst_prefix): return args
+	nsign, b, f, h, k, s, t, w, x, y, A, E, K, N, T, X, Y = args
+	# Missing: (a, c, d, m, o, v, B, R, W)
+	#XXX Convert %W (_w) to class instance?
+	e = Event()
+	e.serial = tk.getint(nsign)
+	e.num = tk.getint(b)
+	try: e.focus = tk.getboolean(f)
+	except TclError: pass
+	e.height = tk.getint(h)
+	e.keycode = tk.getint(k)
+	e.state = tk.getint(s)
+	e.time = tk.getint(t)
+	e.width = tk.getint(w)
+	e.x = tk.getint(x)
+	e.y = tk.getint(y)
+	e.char = A
+	try: e.send_event = tk.getboolean(E)
+	except TclError: pass
+	e.keysym = K
+	e.keysym_num = tk.getint(N)
+	e.type = T
+	#XXX %W stuff
+	e.x_root = tk.getint(X)
+	e.y_root = tk.getint(Y)
+	return (e,)
+
+class _CallSafely:
+	def __init__(self, func, subst=None):
+		self.func = func
+		self.subst = subst
+	def __call__(self, *args):
+		if self.subst:
+			args = self.apply_func(self.subst, args)
+		args = self.apply_func(self.func, args)
+	def apply_func(self, func, args):
+		import sys
+		try:
+			return apply(func, args)
+		except:
+			try:
+				try:
+					t = sys.exc_traceback
+					while t:
+						sys.stderr.write(
+							'  %s, line %s\n' %
+							(t.tb_frame.f_code,
+							 t.tb_lineno))
+						t = t.tb_next
+				finally:
+					sys.stderr.write('%s: %s\n' %
+							 (sys.exc_type,
+							  sys.exc_value))
+			except:
+				print '*** Error in error handling ***'
+				print sys.exc_type, ':', sys.exc_value
+
+class Wm:
+	def aspect(self, 
+		   minNumer=None, minDenom=None, 
+		   maxNumer=None, maxDenom=None):
+		return self._getints(
+			self.tk.call('wm', 'aspect', self._w, 
+				     minNumer, minDenom, 
+				     maxNumer, maxDenom))
+	def client(self, name=None):
+		return self.tk.call('wm', 'client', self._w, name)
+	def command(self, value=None):
+		return self.tk.call('wm', 'command', self._w, value)
+	def deiconify(self):
+		return self.tk.call('wm', 'deiconify', self._w)
+	def focusmodel(self, model=None):
+		return self.tk.call('wm', 'focusmodel', self._w, model)
+	def frame(self):
+		return self.tk.call('wm', 'frame', self._w)
+	def geometry(self, newGeometry=None):
+		return self.tk.call('wm', 'geometry', self._w, newGeometry)
+	def grid(self,
+		 baseWidht=None, baseHeight=None, 
+		 widthInc=None, heightInc=None):
+		return self._getints(self.tk.call(
+			'wm', 'grid', self._w,
+			baseWidht, baseHeight, widthInc, heightInc))
+	def group(self, pathName=None):
+		return self.tk.call('wm', 'group', self._w, pathName)
+	def iconbitmap(self, bitmap=None):
+		return self.tk.call('wm', 'iconbitmap', self._w, bitmap)
+	def iconify(self):
+		return self.tk.call('wm', 'iconify', self._w)
+	def iconmask(self, bitmap=None):
+		return self.tk.call('wm', 'iconmask', self._w, bitmap)
+	def iconname(self, newName=None):
+		return self.tk.call('wm', 'iconname', self._w, newName)
+	def iconposition(self, x=None, y=None):
+		return self._getints(self.tk.call(
+			'wm', 'iconposition', self._w, x, y))
+	def iconwindow(self, pathName=None):
+		return self.tk.call('wm', 'iconwindow', self._w, pathName)
+	def maxsize(self, width=None, height=None):
+		return self._getints(self.tk.call(
+			'wm', 'maxsize', self._w, width, height))
+	def minsize(self, width=None, height=None):
+		return self._getints(self.tk.call(
+			'wm', 'minsize', self._w, width, height))
+	def overrideredirect(self, boolean=None):
+		return self._getboolean(self.tk.call(
+			'wm', 'overrideredirect', self._w, boolean))
+	def positionfrom(self, who=None):
+		return self.tk.call('wm', 'positionfrom', self._w, who)
+	def protocol(self, name=None, func=None):
+		if _isfunctype(func):
+			command = self._register(func)
+		else:
+			command = func
+		return self.tk.call(
+			'wm', 'protocol', self._w, name, command)
+	def sizefrom(self, who=None):
+		return self.tk.call('wm', 'sizefrom', self._w, who)
+	def state(self):
+		return self.tk.call('wm', 'state', self._w)
+	def title(self, string=None):
+		return self.tk.call('wm', 'title', self._w, string)
+	def transient(self, master=None):
+		return self.tk.call('wm', 'transient', self._w, master)
+	def withdraw(self):
+		return self.tk.call('wm', 'withdraw', self._w)
+
+class Tk(Misc, Wm):
+	_w = '.'
+	def __init__(self, screenName=None, baseName=None, className='Tk'):
+		if baseName is None:
+			import sys, os
+			baseName = os.path.basename(sys.argv[0])
+			if baseName[-3:] == '.py': baseName = baseName[:-3]
+		self.tk = tkinter.create(screenName, baseName, className)
+		self.tk.createcommand('tkerror', tkerror)
+	def __del__(self):
+		self.tk.call('destroy', '.')
+	def __str__(self):
+		return '.'
+
+class Pack:
+	def config(self, cnf={}):
+		apply(self.tk.call, 
+		      ('pack', 'configure', self._w) 
+		      + self._options(cnf))
+	pack = config
+	def __setitem__(self, key, value):
+		Pack.config({key: value})
+	def forget(self):
+		self.tk.call('pack', 'forget', self._w)
+	def newinfo(self):
+		return self.tk.call('pack', 'newinfo', self._w)
+	info = newinfo
+	def propagate(self, boolean=None):
+		if boolean:
+			self.tk.call('pack', 'propagate', self._w)
+		else:
+			return self._getboolean(self.tk.call(
+				'pack', 'propagate', self._w))
+	def slaves(self):
+		return self.tk.splitlist(self.tk.call(
+			'pack', 'slaves', self._w))
+
+class Place:
+	def config(self, cnf={}):
+		apply(self.tk.call, 
+		      ('place', 'configure', self._w) 
+		      + self._options(cnf))
+	place = config
+	def __setitem__(self, key, value):
+		Place.config({key: value})
+	def forget(self):
+		self.tk.call('place', 'forget', self._w)
+	def info(self):
+		return self.tk.call('place', 'info', self._w)
+	def slaves(self):
+		return self.tk.splitlist(self.tk.call(
+			'place', 'slaves', self._w))
+
+default_root = None
+
+class Widget(Misc, Pack, Place):
+	def __init__(self, master, widgetName, cnf={}, extra=()):
+		global default_root
+		if not master:
+			if not default_root:
+				default_root = Tk()
+			master = default_root
+		if not default_root:
+			default_root = master
+		self.master = master
+		self.tk = master.tk
+		if cnf.has_key('name'):
+			name = cnf['name']
+			del cnf['name']
+		else:
+			name = `id(self)`
+		if master._w=='.':
+			self._w = '.' + name
+		else:
+			self._w = master._w + '.' + name
+		self.widgetName = widgetName
+		apply(self.tk.call, (widgetName, self._w) + extra)
+		Widget.config(self, cnf)
+	def config(self, cnf={}):
+		for k in cnf.keys():
+			if type(k) == ClassType:
+				k.config(self, cnf[k])
+				del cnf[k]
+		apply(self.tk.call, (self._w, 'configure')
+		      + self._options(cnf))
+	def __getitem__(self, key):
+		v = self.tk.split(self.tk.call(
+			self._w, 'configure', '-' + key))
+		return v[4]
+	def __setitem__(self, key, value):
+		Widget.config(self, {key: value})
+	def __str__(self):
+		return self._w
+	def __del__(self):
+		self.tk.call('destroy', self._w)
+	destroy = __del__
+	def _do(self, name, args=()):
+		apply(self.tk.call, (self._w, name) + args) 
+
+class Toplevel(Widget, Wm):
+	def __init__(self, master=None, cnf={}):
+		extra = ()
+		if cnf.has_key('screen'):
+			extra = ('-screen', cnf['screen'])
+			del cnf['screen']
+		if cnf.has_key('class'):
+			extra = extra + ('-class', cnf['class'])
+			del cnf['class']
+		Widget.__init__(self, master, 'toplevel', cnf, extra)
+		self.iconname(self.tk.call('wm', 'iconname', '.'))
+		self.title(self.tk.call('wm', 'title', '.'))
+
+class Button(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'button', cnf)
+	def tk_butEnter(self):
+		self.tk.call('tk_butEnter', self._w)
+	def tk_butLeave(self):
+		self.tk.call('tk_butLeave', self._w)
+	def tk_butDown(self):
+		self.tk.call('tk_butDown', self._w)
+	def tk_butUp(self):
+		self.tk.call('tk_butUp', self._w)
+	def flash(self):
+		self.tk.call(self._w, 'flash')
+	def invoke(self):
+		self.tk.call(self._w, 'invoke')
+
+# Indices:
+def AtEnd():
+	return 'end'
+def AtInsert():
+	return 'insert'
+def AtSelFirst():
+	return 'sel.first'
+def AtSelLast():
+	return 'sel.last'
+def At(x, y=None):
+	if y:
+		return '@' + `x` + ',' + `y`
+	else:
+		return '@' + `x` 
+
+class Canvas(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'canvas', cnf)
+	def addtag(self, *args):
+		self._do('addtag', args)
+	def bbox(self, *args):
+		return self._getints(self._do('bbox', args))
+	def bind(self, tagOrId, sequence, func, add=''):
+		global _substitute, _subst_prefix
+		if add: add='+'
+		name = self._register(func, _substitute)
+		self.tk.call(self._w, 'bind', tagOrId, sequence, 
+			     (add + name,) + _subst_prefix)
+	def canvasx(self, screenx, gridspacing=None):
+		return self.tk.getint(self.tk.call(
+			self._w, 'canvasx', screenx, gridspacing))
+	def canvasy(self, screeny, gridspacing=None):
+		return self.tk.getint(self.tk.call(
+			self._w, 'canvasy', screeny, gridspacing))
+	def coords(self, *args):
+		return self._do('coords', args)
+	def _create(self, itemType, args): # Args: (value, value, ..., cnf={})
+		cnf = args[-1]
+		if type(cnf) == type({}):
+			args = args[:-1]
+		else:
+			cnf = {}
+		v = (self._w, 'create', itemType) + args
+		for k in cnf.keys():
+			v = v + ('-' + k, cnf[k])
+		return self.tk.getint(apply(self.tk.call, v))
+	def create_arc(self, *args):
+		Canvas._create(self, 'arc', args)
+	def create_bitmap(self, *args):
+		Canvas._create(self, 'bitmap', args)
+	def create_line(self, *args):
+		Canvas._create(self, 'line', args)
+	def create_oval(self, *args):
+		Canvas._create(self, 'oval', args)
+	def create_polygon(self, *args):
+		Canvas._create(self, 'polygon', args)
+	def create_rectangle(self, *args):
+		Canvas._create(self, 'rectangle', args)
+	def create_text(self, *args):
+		Canvas._create(self, 'text', args)
+	def create_window(self, *args):
+		Canvas._create(self, 'window', args)
+	def dchars(self, *args):
+		self._do('dchars', args)
+	def delete(self, *args):
+		self._do('delete', args)
+	def dtag(self, *args):
+		self._do('dtag', args)
+	def find(self, *args):
+		self.tk.splitlist(self._do('find', args))
+	def focus(self, *args):
+		return self._do('focus', args)
+	def gettags(self, *args):
+		return self.tk.splitlist(self._do('gettags', args))
+	def icursor(self, *args):
+		self._do('icursor', args)
+	def index(self, *args):
+		return self.tk.getint(self._do('index', args))
+	def insert(self, *args):
+		self._do('insert', args)
+	def itemconfig(self, tagOrId, cnf={}):
+		self._do('itemconfigure', (tagOrId,) + self._options(cnf))
+	def lower(self, *args):
+		self._do('lower', args)
+	def move(self, *args):
+		self._do('move', args)
+	def postscript(self, cnf={}):
+		return self._do('postscript', self._options(cnf))
+	def tkraise(self, *args):
+		self._do('raise', args)
+	def scale(self, *args):
+		self._do('scale', args)
+	def scan_mark(self, x, y):
+		self.tk.call(self._w, 'scan', 'mark', x, y)
+	def scan_dragto(self, x, y):
+		self.tk.call(self._w, 'scan', 'dragto', x, y)
+	def select_adjust(self, tagOrId, index):
+		self.tk.call(
+			self._w, 'select', 'adjust', tagOrId, index)
+	def select_clear(self):
+		self.tk.call(self._w, 'select', 'clear')
+	def select_from(self, tagOrId, index):
+		self.tk.call(
+			self._w, 'select', 'from', tagOrId, index)
+	def select_item(self):
+		self.tk.call(self._w, 'select', 'item')
+	def select_to(self, tagOrId, index):
+		self.tk.call(
+			self._w, 'select', 'to', tagOrId, index)
+	def type(self, tagOrId):
+		return self.tk.splitlist(self.tk.call(
+			self._w, 'type', tagOrId))
+	def xview(self, index):
+		self.tk.call(self._w, 'xview', index)
+	def yview(self, index):
+		self.tk.call(self._w, 'yview', index)
+
+class Checkbutton(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'checkbutton', cnf)
+	def deselect(self):
+		self.tk.call(self._w, 'deselect')
+	def flash(self):
+		self.tk.call(self._w, 'flash')
+	def invoke(self):
+		self.tk.call(self._w, 'invoke')
+	def select(self):
+		self.tk.call(self._w, 'select')
+	def toggle(self):
+		self.tk.call(self._w, 'toggle')
+
+class Entry(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'entry', cnf)
+	def tk_entryBackspace(self):
+		self.tk.call('tk_entryBackspace', self._w)
+	def tk_entryBackword(self):
+		self.tk.call('tk_entryBackword', self._w)
+	def tk_entrySeeCaret(self):
+		self.tk.call('tk_entrySeeCaret', self._w)
+	def delete(self, first, last=None):
+		self.tk.call(self._w, 'delete', first, last)
+	def get(self):
+		return self.tk.call(self._w, 'get')
+	def icursor(self, index):
+		self.tk.call(self._w, 'icursor', index)
+	def index(self, index):
+		return self.tk.getint(self.tk.call(
+			self._w, 'index', index))
+	def insert(self, index, string):
+		self.tk.call(self._w, 'insert', index, string)
+	def scan_mark(self, x):
+		self.tk.call(self._w, 'scan', 'mark', x)
+	def scan_dragto(self, x):
+		self.tk.call(self._w, 'scan', 'dragto', x)
+	def select_adjust(self, index):
+		self.tk.call(self._w, 'select', 'adjust', index)
+	def select_clear(self):
+		self.tk.call(self._w, 'select', 'clear')
+	def select_from(self, index):
+		self.tk.call(self._w, 'select', 'from', index)
+	def select_to(self, index):
+		self.tk.call(self._w, 'select', 'to', index)
+	def select_view(self, index):
+		self.tk.call(self._w, 'select', 'view', index)
+
+class Frame(Widget):
+	def __init__(self, master=None, cnf={}):
+		extra = ()
+		if cnf.has_key('class'):
+			extra = ('-class', cnf['class'])
+			del cnf['class']
+		Widget.__init__(self, master, 'frame', cnf, extra)
+	def tk_menuBar(self, *args):
+		apply(self.tk.call, ('tk_menuBar', self._w) + args)
+
+class Label(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'label', cnf)
+
+class Listbox(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'listbox', cnf)
+	def tk_listboxSingleSelect(self):
+		self.tk.call('tk_listboxSingleSelect', self._w) 
+	def curselection(self):
+		return self.tk.splitlist(self.tk.call(
+			self._w, 'curselection'))
+	def delete(self, first, last=None):
+		self.tk.call(self._w, 'delete', first, last)
+	def get(self, index):
+		return self.tk.call(self._w, 'get', index)
+	def insert(self, index, *elements):
+		apply(self.tk.call,
+		      (self._w, 'insert', index) + elements)
+	def nearest(self, y):
+		return self.tk.getint(self.tk.call(
+			self._w, 'nearest', y))
+	def scan_mark(self, x, y):
+		self.tk.call(self._w, 'scan', 'mark', x, y)
+	def scan_dragto(self, x, y):
+		self.tk.call(self._w, 'scan', 'dragto', x, y)
+	def select_adjust(self, index):
+		self.tk.call(self._w, 'select', 'adjust', index)
+	def select_clear(self):
+		self.tk.call(self._w, 'select', 'clear')
+	def select_from(self, index):
+		self.tk.call(self._w, 'select', 'from', index)
+	def select_to(self, index):
+		self.tk.call(self._w, 'select', 'to', index)
+	def size(self):
+		return self.tk.getint(self.tk.call(self._w, 'size'))
+	def xview(self, index):
+		self.tk.call(self._w, 'xview', index)
+	def yview(self, index):
+		self.tk.call(self._w, 'yview', index)
+
+class Menu(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'menu', cnf)
+	def tk_menuBar(self, *args):
+		apply(self.tk.call, ('tk_menuBar', self._w) + args)
+	def tk_bindForTraversal(self):
+		self.tk.call('tk_bindForTraversal', self._w)
+	def tk_mbPost(self):
+		self.tk.call('tk_mbPost', self._w)
+	def tk_mbUnpost(self):
+		self.tk.call('tk_mbUnpost')
+	def tk_traverseToMenu(self, char):
+		self.tk.call('tk_traverseToMenu', self._w, char)
+	def tk_traverseWithinMenu(self, char):
+		self.tk.call('tk_traverseWithinMenu', self._w, char)
+	def tk_getMenuButtons(self):
+		return self.tk.call('tk_getMenuButtons', self._w)
+	def tk_nextMenu(self, count):
+		self.tk.call('tk_nextMenu', count)
+	def tk_nextMenuEntry(self, count):
+		self.tk.call('tk_nextMenuEntry', count)
+	def tk_invokeMenu(self):
+		self.tk.call('tk_invokeMenu', self._w)
+	def tk_firstMenu(self):
+		self.tk.call('tk_firstMenu', self._w)
+	def tk_mbButtonDown(self):
+		self.tk.call('tk_mbButtonDown', self._w)
+	def activate(self, index):
+		self.tk.call(self._w, 'activate', index)
+	def add(self, itemType, cnf={}):
+		apply(self.tk.call, (self._w, 'add', itemType) 
+		      + self._options(cnf))
+	def delete(self, index1, index2=None):
+		self.tk.call(self._w, 'delete', index1, index2)
+	def entryconfig(self, index, cnf={}):
+		apply(self.tk.call, (self._w, 'entryconfigure', index)
+		      + self._options(cnf))
+	def index(self, index):
+		return self.tk.call(self._w, 'index', index)
+	def invoke(self, index):
+		return self.tk.call(self._w, 'invoke', index)
+	def post(self, x, y):
+		self.tk.call(self._w, 'post', x, y)
+	def unpost(self):
+		self.tk.call(self._w, 'unpost')
+	def yposition(self, index):
+		return self.tk.getint(self.tk.call(
+			self._w, 'yposition', index))
+
+class Menubutton(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'menubutton', cnf)
+
+class Message(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'message', cnf)
+
+class Radiobutton(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'radiobutton', cnf)
+	def deselect(self):
+		self.tk.call(self._w, 'deselect')
+	def flash(self):
+		self.tk.call(self._w, 'flash')
+	def invoke(self):
+		self.tk.call(self._w, 'invoke')
+	def select(self):
+		self.tk.call(self._w, 'select')
+
+class Scale(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'scale', cnf)
+	def get(self):
+		return self.tk.getint(self.tk.call(self._w, 'get'))
+	def set(self, value):
+		self.tk.call(self._w, 'set', value)
+
+class Scrollbar(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'scrollbar', cnf)
+	def get(self):
+		return self.tk.getints(self.tk.call(self._w, 'get'))
+	def set(self, totalUnits, windowUnits, firstUnit, lastUnit):
+		self.tk.call(self._w, 'set', 
+			     totalUnits, windowUnits, firstUnit, lastUnit)
+
+class Text(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'text', cnf)
+	def tk_textSelectTo(self, index):
+		self.tk.call('tk_textSelectTo', self._w, index)
+	def tk_textBackspace(self):
+		self.tk.call('tk_textBackspace', self._w)
+	def tk_textIndexCloser(self, a, b, c):
+		self.tk.call('tk_textIndexCloser', self._w, a, b, c)
+	def tk_textResetAnchor(self, index):
+		self.tk.call('tk_textResetAnchor', self._w, index)
+	def compare(self, index1, op, index2):
+		return self.tk.getboolean(self.tk.call(
+			self._w, 'compare', index1, op, index2))
+	def debug(self, boolean=None):
+		return self.tk.getboolean(self.tk.call(
+			self._w, 'debug', boolean))
+	def delete(self, index1, index2=None):
+		self.tk.call(self._w, 'delete', index1, index2)
+	def get(self, index1, index2=None):
+		return self.tk.call(self._w, 'get', index1, index2)
+	def index(self, index):
+		return self.tk.call(self._w, 'index', index)
+	def insert(self, index, chars):
+		self.tk.call(self._w, 'insert', index, chars)
+	def mark_names(self):
+		return self.tk.splitlist(self.tk.call(
+			self._w, 'mark', 'names'))
+	def mark_set(self, markName, index):
+		self.tk.call(self._w, 'mark', 'set', markName, index)
+	def mark_unset(self, markNames):
+		apply(self.tk.call, (self._w, 'mark', 'unset') + markNames)
+	def scan_mark(self, y):
+		self.tk.call(self._w, 'scan', 'mark', y)
+	def scan_dragto(self, y):
+		self.tk.call(self._w, 'scan', 'dragto', y)
+	def tag_add(self, tagName, index1, index2=None):
+		self.tk.call(
+			self._w, 'tag', 'add', tagName, index1, index2)
+	def tag_bind(self, tagName, sequence, func, add=''):
+		global _substitute, _subst_prefix
+		if add: add='+'
+		name = self._register(func, _substitute)
+		self.tk.call(self._w, 'tag', 'bind', 
+			     tagName, sequence, 
+			     (add + name,) + _subst_prefix)
+	def tag_config(self, tagName, cnf={}):
+		apply(self.tk.call, 
+		      (self._w, 'tag', 'configure', tagName) 
+		      + self._options(cnf))
+	def tag_delete(self, tagNames):
+		apply(self.tk.call, (self._w, 'tag', 'delete') 
+		      + tagNames)
+	def tag_lower(self, tagName, belowThis=None):
+		self.tk.call(self._w, 'tag', 'lower', 
+			     tagName, belowThis)
+	def tag_names(self, index=None):
+		return self.tk.splitlist(
+			self.tk.call(self._w, 'tag', 'names', index))
+	def tag_nextrange(self, tagName, index1, index2=None):
+		return self.tk.splitlist(self.tk.call(
+			self._w, 'tag', 'nextrange', index1, index2))
+	def tag_raise(self, tagName, aboveThis=None):
+		self.tk.call(
+			self._w, 'tag', 'raise', tagName, aboveThis)
+	def tag_ranges(self, tagName):
+		return self.tk.splitlist(self.tk.call(
+			self._w, 'tag', 'ranges', tagName))
+	def tag_remove(self, tagName, index1, index2=None):
+		self.tk.call(
+			self._w, 'tag', 'remove', index1, index2)
+	def yview(self, what):
+		self.tk.call(self._w, 'yview', what)
+	def yview_pickplace(self, what):
+		self.tk.call(self._w, 'yview', '-pickplace', what)
+
+#class Dialog:
+	
diff --git a/Lib/tkinter/Canvas.py b/Lib/tkinter/Canvas.py
new file mode 100755
index 0000000..4d21928
--- /dev/null
+++ b/Lib/tkinter/Canvas.py
@@ -0,0 +1,115 @@
+# This module exports classes for the various canvas item types
+
+# vi:set tabsize=4:
+
+from Tkinter import Canvas, _isfunctype
+
+class CanvasItem:
+	def __init__(self, canvas, itemType, args = (), cnf={}):
+		self.canvas = canvas
+		self.id = canvas._create(itemType, args + (cnf,))
+	def __str__(self):
+		return str(self.id)
+	def __repr__(self):
+		return '<%s, id=%d>' % (self.__class__.__name__, self.id)
+	def __del__(self):
+		self.canvas.delete(self.id)
+	delete = __del__
+	def __getitem__(self, key):
+		v = self.canvas.tk.split(self.canvas.tk.call(self.canvas.pathName, 
+							     'itemconfigure',
+							     str(self.id),
+							     '-' + key))
+		return v[4]
+	def __setitem__(self, key, value):
+		self.canvas._itemconfig(self.id, {key: value})
+	def keys(self):
+		if not hasattr(self, '_keys'):
+			self._keys = map(lambda x, tk=self.canvas.tk:
+							        tk.splitlist(x)[0][1:],
+							 self.canvas._splitlist(
+								 self.canvas.cmd('itemconfigure', self.id)))
+			return self._keys
+	def has_key(self, key):
+		return key in self.keys()
+	def addtag(self, tag, option='withtag'):
+		self.canvas.addtag(tag, option, self.id)
+	def bbox(self):
+		x1, y1, x2, y2 = self.canvas.bbox(self.id)
+		return (x1, y1), (x2, y2)
+	def bind(self, sequence=None, command=None):
+		return self.canvas.bind(self.id, sequence, command)
+	def coords(self, pts = ()):
+		flat = ()
+		for x, y in pts: flat = flat + (x, y)
+		return apply(self.canvas.coords, (self.id,) + flat)
+	def dchars(self, first, last=None):
+		self.canvas.dchars(self.id, first, last)
+	def dtag(self, ttd):
+		self.canvas.dtag(self.id, ttd)
+	def focus(self):
+		self.canvas.focus(self.id)
+	def gettags(self):
+		return self.canvas.gettags(self.id)
+	def icursor(self):
+		self.canvas.icursor(self.id)
+	def index(self):
+		return self.canvas.index(self.id)
+	def insert(self, beforethis, string):
+		self.canvas.insert(self.id, beforethis, string)
+	def lower(self, belowthis=None):
+		self.canvas.lower(self.id, belowthis)
+	def move(self, xamount, yamount):
+		self.canvas.move(self.id, xamount, yamount)
+	def raise_(self, abovethis=None):
+		self.canvas.raise_(self.id, abovethis)
+	def scale(self, xorigin, yorigin, xscale, yscale):
+		self.canvas.scale(self.id, xorigin, yorigin, xscale, yscale)
+	def type(self):
+		return self.canvas.type(self.id)
+
+class Arc(CanvasItem):
+	def __init__(self, canvas, (x1, y1), (x2, y2), cnf={}):
+		CanvasItem.__init__(self, canvas, 'arc',
+							(str(x1), str(y1), str(x2), str(y2)), cnf)
+
+class Bitmap(CanvasItem):
+	def __init__(self, canvas, (x1, y1), cnf={}):
+		CanvasItem.__init__(self, canvas, 'bitmap', (str(x1), str(y1)), cnf)
+
+class Line(CanvasItem):
+	def __init__(self, canvas, pts, cnf={}):
+		pts = reduce(lambda a, b: a+b,
+					 map(lambda pt: (str(pt[0]), str(pt[1])), pts))
+		CanvasItem.__init__(self, canvas, 'line', pts, cnf)
+
+class Oval(CanvasItem):
+	def __init__(self, canvas, (x1, y1), (x2, y2), cnf={}):
+		CanvasItem.__init__(self, canvas, 'oval',
+							(str(x1), str(y1), str(x2), str(y2)), cnf)
+
+class Polygon(CanvasItem):
+	def __init__(self, canvas, pts, cnf={}):
+		pts = reduce(lambda a, b: a+b,
+					 map(lambda pt: (str(pt[0]), str(pt[1])), pts))
+		CanvasItem.__init__(self, canvas, 'polygon', pts, cnf)
+
+class Curve(Polygon):
+	def __init__(self, canvas, pts, cnf={}):
+		cnf['smooth'] = 'yes'
+		Polygon.__init__(self, canvas, pts, cnf)
+
+class Rectangle(CanvasItem):
+	def __init__(self, canvas, (x1, y1), (x2, y2), cnf={}):
+		CanvasItem.__init__(self, canvas, 'rectangle',
+							(str(x1), str(y1), str(x2), str(y2)), cnf)
+
+# XXX Can't use name "Text" since that is already taken by the Text widget...
+class String(CanvasItem):
+	def __init__(self, canvas, (x1, y1), cnf={}):
+		CanvasItem.__init__(self, canvas, 'text', (str(x1), str(y1)), cnf)
+
+class Window(CanvasItem):
+	def __init__(self, canvas, where, cnf={}):
+		CanvasItem.__init__(self, canvas, 'window',
+							(str(where[0]), str(where[1])), cnf)
diff --git a/Lib/tkinter/ScrolledText.py b/Lib/tkinter/ScrolledText.py
new file mode 100755
index 0000000..9effae0
--- /dev/null
+++ b/Lib/tkinter/ScrolledText.py
@@ -0,0 +1,35 @@
+# A ScrolledText widget feels like a text widget but also has a
+# vertical scroll bar on its right.  (Later, options may be added to
+# add a horizontal bar as well, to make the bars disappear
+# automatically when not needed, to move them to the other side of the
+# window, etc.)
+#
+# Configuration options are passed to the Text widget.
+# A Frame widget is inserted between the master and the text, to hold
+# the Scrollbar widget.
+# Most methods calls are passed to the Text widget; the pack command
+# is redirected to the Frame widget however.
+
+from Tkinter import *
+
+class ScrolledText(Pack, Place):
+	def __init__(self, master=None, cnf={}):
+		fcnf = {}
+		self.frame = Frame(master, {})
+		if cnf.has_key(Pack):
+			self.frame.pack(cnf[Pack])
+			del cnf[Pack]
+		self.vbar = Scrollbar(self.frame, {})
+		self.vbar.pack({'side': 'right', 'fill': 'y'})
+		cnf[Pack] = {'side': 'left', 'fill': 'both',
+			     'expand': 'yes'}
+		self.text = Text(self.frame, cnf)
+		self.text['yscrollcommand'] = (self.vbar, 'set')
+		self.vbar['command'] = (self.text, 'yview')
+		self.insert = self.text.insert
+		# XXX should do all Text methods...
+		self.pack = self.frame.pack
+		self.forget = self.frame.forget
+		self.tk = master.tk
+	def __str__(self):
+		return str(self.frame)
diff --git a/Lib/tkinter/Tkinter.py b/Lib/tkinter/Tkinter.py
new file mode 100755
index 0000000..e9e641c
--- /dev/null
+++ b/Lib/tkinter/Tkinter.py
@@ -0,0 +1,874 @@
+# Tkinter.py -- Tk/Tcl widget wrappers
+import tkinter
+from tkinter import TclError
+
+class _Dummy:
+	def meth(self):	return
+
+def _isfunctype(func):
+	return type(func) in (type(_Dummy.meth), type(_isfunctype))	
+
+FunctionType = type(_isfunctype)
+ClassType = type(_Dummy)
+MethodType = type(_Dummy.meth)
+
+def tkerror(err):
+	pass
+
+class Event:
+	pass
+
+class Misc:
+	def tk_strictMotif(self, boolean=None):
+		self.tk.getboolean(self.tk.call(
+			'set', 'tk_strictMotif', boolean))
+	def waitvar(self, name='VAR'):
+		self.tk.call('tkwait', 'variable', name)
+	def setvar(self, name='VAR', value='1'):
+		self.tk.setvar(name, value)
+	def focus(self):
+		self.tk.call('focus', self._w)
+	def focus_default(self):
+		self.tk.call('focus', 'default', self._w)
+	def focus_none(self):
+		self.tk.call('focus', 'none')
+	#XXX focus_get?
+	def after(self, ms, func=None, *args):
+		if not func:
+			self.tk.call('after', ms)
+		else:
+			name = self._register(func)
+			apply(self.tk.call, ('after', ms, name) + args)
+	#XXX grab_current
+	def grab_release(self):
+		self.tk.call('grab', 'release', self._w)
+	def grab_set(self):
+		self.tk.call('grab', 'set', self._w)
+	def grab_set_global(self):
+		self.tk.call('grab', 'set', '-global', self._w)
+	def grab_status(self):
+		self.tk.call('grab', 'status', self._w)
+	def lower(self, belowThis=None):
+		self.tk.call('lower', self._w, belowThis)
+	def selection_clear(self):
+		self.tk.call('selection', 'clear', self._w)
+	def selection_get(self, type=None):
+		self.tk.call('selection', 'get', type)
+	def selection_handle(self, func, type=None, format=None):
+		name = self._register(func)
+		self.tk.call('selection', 'handle',
+			     self._w, name, type, format)
+	#XXX def selection_own(self):
+	#	self.tk.call('selection', 'own', self._w)
+	def send(self, interp, cmd, *args): #XXX
+		return apply(self.tk.call, ('send', interp, cmd) + args)
+	def colormodel(self, value=None):
+		return self.tk.call('tk', 'colormodel', self._w, value)
+	def winfo_atom(self, name):
+		return self.tk.getint(self.tk.call('winfo', 'atom', name))
+	def winfo_atomname(self, id):
+		return self.tk.call('winfo', 'atomname', id)
+	def winfo_cells(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'cells', self._w))
+	#XXX winfo_children
+	def winfo_class(self):
+		return self.tk.call('winfo', 'class', self._w)
+	def winfo_containing(self, rootX, rootY):
+		return self.tk.call('winfo', 'containing', rootx, rootY)
+	def winfo_depth(self):
+		return self.tk.getint(self.tk.call('winfo', 'depth', self._w))
+	def winfo_exists(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'exists', self._w))
+	def winfo_fpixels(self, number):
+		return self.tk.getdouble(self.tk.call(
+			'winfo', 'fpixels', self._w, number))
+	def winfo_geometry(self):
+		return self.tk.call('winfo', 'geometry', self._w)
+	def winfo_height(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'height', self._w))
+	def winfo_id(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'id', self._w))
+	def winfo_interps(self):
+		return self.tk.splitlist(
+			self.tk.call('winfo', 'interps'))
+	def winfo_ismapped(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'ismapped', self._w))
+	def winfo_name(self):
+		return self.tk.call('winfo', 'name', self._w)
+	def winfo_parent(self):
+		return self.tk.call('winfo', 'parent', self._w)
+	def winfo_pathname(self, id):
+		return self.tk.call('winfo', 'pathname', id)
+	def winfo_pixels(self, number):
+		return self.tk.getint(
+			self.tk.call('winfo', 'pixels', self._w, number))
+	def winfo_reqheight(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'reqheight', self._w))
+	def winfo_reqwidth(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'reqwidth', self._w))
+	def winfo_rgb(self, color):
+		return self._getints(
+			self.tk.call('winfo', 'rgb', self._w, color))
+	def winfo_rootx(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'rootx', self._w))
+	def winfo_rooty(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'rooty', self._w))
+	def winfo_screen(self):
+		return self.tk.call('winfo', 'screen', self._w)
+	def winfo_screencells(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'screencells', self._w))
+	def winfo_screendepth(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'screendepth', self._w))
+	def winfo_screenheight(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'screenheight', self._w))
+	def winfo_screenmmheight(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'screenmmheight', self._w))
+	def winfo_screenmmwidth(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'screenmmwidth', self._w))
+	def winfo_screenvisual(self):
+		return self.tk.call('winfo', 'screenvisual', self._w)
+	def winfo_screenwidth(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'screenwidth', self._w))
+	def winfo_toplevel(self):
+		return self.tk.call('winfo', 'toplevel', self._w)
+	def winfo_visual(self):
+		return self.tk.call('winfo', 'visual', self._w)
+	def winfo_vrootheight(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'vrootheight', self._w))
+	def winfo_vrootwidth(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'vrootwidth', self._w))
+	def winfo_vrootx(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'vrootx', self._w))
+	def winfo_vrooty(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'vrooty', self._w))
+	def winfo_width(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'width', self._w))
+	def winfo_x(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'x', self._w))
+	def winfo_y(self):
+		return self.tk.getint(
+			self.tk.call('winfo', 'y', self._w))
+	def update(self):
+		self.tk.call('update')
+	def update_idletasks(self):
+		self.tk.call('update', 'idletasks')
+	def bind(self, sequence, func, add=''):
+		global _substitute, _subst_prefix
+		if add: add = '+'
+		name = self._register(func, _substitute)
+		self.tk.call('bind', self._w, sequence, 
+			     (add + name,) + _subst_prefix)
+	def bind_all(self, sequence, func, add=''):
+		global _substitute, _subst_prefix
+		if add: add = '+'
+		name = self._register(func, _substitute)
+		self.tk.call('bind', 'all' , sequence, 
+			     (add + `name`,) + _subst_prefix)
+	def bind_class(self, className, sequence, func, add=''):
+		global _substitute, _subst_prefix
+		if add: add = '+'
+		name = self._register(func, _substitute)
+		self.tk.call('bind', className , sequence, 
+			     (add + name,) + _subst_prefix)
+	def mainloop(self):
+		self.tk.mainloop()
+	def quit(self):
+		self.tk.quit()
+	# Utilities
+	def _getints(self, string):
+		if string:
+			res = ()
+			for v in self.tk.split(string):
+				res = res +  (self.tk.getint(v),)
+			return res
+		else:
+			return string
+	def _getboolean(self, string):
+		if string:
+			return self.tk.getboolean(string)
+		else:
+			return string
+	def _options(self, cnf):
+		res = ()
+		for k, v in cnf.items():
+			if _isfunctype(v):
+				v = self._register(v)
+			res = res + ('-'+k, v)
+		return res
+	def _register(self, func, subst=None):
+		f = func
+		f = _CallSafely(func, subst).__call__
+		name = `id(f)`
+		if hasattr(func, 'im_func'):
+			func = func.im_func
+		if hasattr(func, 'func_name') and \
+		   type(func.func_name) == type(''):
+			name = name + func.func_name
+		self.tk.createcommand(name, f)
+		return name
+
+_subst_prefix = ('%#', '%b', '%f', '%h', '%k', 
+		 '%s', '%t', '%w', '%x', '%y',
+		 '%A', '%E', '%K', '%N', '%T', '%X', '%Y')
+
+def _substitute(*args):
+	global default_root
+	global _subst_prefix
+	tk = default_root.tk
+	if len(args) != len(_subst_prefix): return args
+	nsign, b, f, h, k, s, t, w, x, y, A, E, K, N, T, X, Y = args
+	# Missing: (a, c, d, m, o, v, B, R, W)
+	#XXX Convert %W (_w) to class instance?
+	e = Event()
+	e.serial = tk.getint(nsign)
+	e.num = tk.getint(b)
+	try: e.focus = tk.getboolean(f)
+	except TclError: pass
+	e.height = tk.getint(h)
+	e.keycode = tk.getint(k)
+	e.state = tk.getint(s)
+	e.time = tk.getint(t)
+	e.width = tk.getint(w)
+	e.x = tk.getint(x)
+	e.y = tk.getint(y)
+	e.char = A
+	try: e.send_event = tk.getboolean(E)
+	except TclError: pass
+	e.keysym = K
+	e.keysym_num = tk.getint(N)
+	e.type = T
+	#XXX %W stuff
+	e.x_root = tk.getint(X)
+	e.y_root = tk.getint(Y)
+	return (e,)
+
+class _CallSafely:
+	def __init__(self, func, subst=None):
+		self.func = func
+		self.subst = subst
+	def __call__(self, *args):
+		if self.subst:
+			args = self.apply_func(self.subst, args)
+		args = self.apply_func(self.func, args)
+	def apply_func(self, func, args):
+		import sys
+		try:
+			return apply(func, args)
+		except:
+			try:
+				try:
+					t = sys.exc_traceback
+					while t:
+						sys.stderr.write(
+							'  %s, line %s\n' %
+							(t.tb_frame.f_code,
+							 t.tb_lineno))
+						t = t.tb_next
+				finally:
+					sys.stderr.write('%s: %s\n' %
+							 (sys.exc_type,
+							  sys.exc_value))
+			except:
+				print '*** Error in error handling ***'
+				print sys.exc_type, ':', sys.exc_value
+
+class Wm:
+	def aspect(self, 
+		   minNumer=None, minDenom=None, 
+		   maxNumer=None, maxDenom=None):
+		return self._getints(
+			self.tk.call('wm', 'aspect', self._w, 
+				     minNumer, minDenom, 
+				     maxNumer, maxDenom))
+	def client(self, name=None):
+		return self.tk.call('wm', 'client', self._w, name)
+	def command(self, value=None):
+		return self.tk.call('wm', 'command', self._w, value)
+	def deiconify(self):
+		return self.tk.call('wm', 'deiconify', self._w)
+	def focusmodel(self, model=None):
+		return self.tk.call('wm', 'focusmodel', self._w, model)
+	def frame(self):
+		return self.tk.call('wm', 'frame', self._w)
+	def geometry(self, newGeometry=None):
+		return self.tk.call('wm', 'geometry', self._w, newGeometry)
+	def grid(self,
+		 baseWidht=None, baseHeight=None, 
+		 widthInc=None, heightInc=None):
+		return self._getints(self.tk.call(
+			'wm', 'grid', self._w,
+			baseWidht, baseHeight, widthInc, heightInc))
+	def group(self, pathName=None):
+		return self.tk.call('wm', 'group', self._w, pathName)
+	def iconbitmap(self, bitmap=None):
+		return self.tk.call('wm', 'iconbitmap', self._w, bitmap)
+	def iconify(self):
+		return self.tk.call('wm', 'iconify', self._w)
+	def iconmask(self, bitmap=None):
+		return self.tk.call('wm', 'iconmask', self._w, bitmap)
+	def iconname(self, newName=None):
+		return self.tk.call('wm', 'iconname', self._w, newName)
+	def iconposition(self, x=None, y=None):
+		return self._getints(self.tk.call(
+			'wm', 'iconposition', self._w, x, y))
+	def iconwindow(self, pathName=None):
+		return self.tk.call('wm', 'iconwindow', self._w, pathName)
+	def maxsize(self, width=None, height=None):
+		return self._getints(self.tk.call(
+			'wm', 'maxsize', self._w, width, height))
+	def minsize(self, width=None, height=None):
+		return self._getints(self.tk.call(
+			'wm', 'minsize', self._w, width, height))
+	def overrideredirect(self, boolean=None):
+		return self._getboolean(self.tk.call(
+			'wm', 'overrideredirect', self._w, boolean))
+	def positionfrom(self, who=None):
+		return self.tk.call('wm', 'positionfrom', self._w, who)
+	def protocol(self, name=None, func=None):
+		if _isfunctype(func):
+			command = self._register(func)
+		else:
+			command = func
+		return self.tk.call(
+			'wm', 'protocol', self._w, name, command)
+	def sizefrom(self, who=None):
+		return self.tk.call('wm', 'sizefrom', self._w, who)
+	def state(self):
+		return self.tk.call('wm', 'state', self._w)
+	def title(self, string=None):
+		return self.tk.call('wm', 'title', self._w, string)
+	def transient(self, master=None):
+		return self.tk.call('wm', 'transient', self._w, master)
+	def withdraw(self):
+		return self.tk.call('wm', 'withdraw', self._w)
+
+class Tk(Misc, Wm):
+	_w = '.'
+	def __init__(self, screenName=None, baseName=None, className='Tk'):
+		if baseName is None:
+			import sys, os
+			baseName = os.path.basename(sys.argv[0])
+			if baseName[-3:] == '.py': baseName = baseName[:-3]
+		self.tk = tkinter.create(screenName, baseName, className)
+		self.tk.createcommand('tkerror', tkerror)
+	def __del__(self):
+		self.tk.call('destroy', '.')
+	def __str__(self):
+		return '.'
+
+class Pack:
+	def config(self, cnf={}):
+		apply(self.tk.call, 
+		      ('pack', 'configure', self._w) 
+		      + self._options(cnf))
+	pack = config
+	def __setitem__(self, key, value):
+		Pack.config({key: value})
+	def forget(self):
+		self.tk.call('pack', 'forget', self._w)
+	def newinfo(self):
+		return self.tk.call('pack', 'newinfo', self._w)
+	info = newinfo
+	def propagate(self, boolean=None):
+		if boolean:
+			self.tk.call('pack', 'propagate', self._w)
+		else:
+			return self._getboolean(self.tk.call(
+				'pack', 'propagate', self._w))
+	def slaves(self):
+		return self.tk.splitlist(self.tk.call(
+			'pack', 'slaves', self._w))
+
+class Place:
+	def config(self, cnf={}):
+		apply(self.tk.call, 
+		      ('place', 'configure', self._w) 
+		      + self._options(cnf))
+	place = config
+	def __setitem__(self, key, value):
+		Place.config({key: value})
+	def forget(self):
+		self.tk.call('place', 'forget', self._w)
+	def info(self):
+		return self.tk.call('place', 'info', self._w)
+	def slaves(self):
+		return self.tk.splitlist(self.tk.call(
+			'place', 'slaves', self._w))
+
+default_root = None
+
+class Widget(Misc, Pack, Place):
+	def __init__(self, master, widgetName, cnf={}, extra=()):
+		global default_root
+		if not master:
+			if not default_root:
+				default_root = Tk()
+			master = default_root
+		if not default_root:
+			default_root = master
+		self.master = master
+		self.tk = master.tk
+		if cnf.has_key('name'):
+			name = cnf['name']
+			del cnf['name']
+		else:
+			name = `id(self)`
+		if master._w=='.':
+			self._w = '.' + name
+		else:
+			self._w = master._w + '.' + name
+		self.widgetName = widgetName
+		apply(self.tk.call, (widgetName, self._w) + extra)
+		Widget.config(self, cnf)
+	def config(self, cnf={}):
+		for k in cnf.keys():
+			if type(k) == ClassType:
+				k.config(self, cnf[k])
+				del cnf[k]
+		apply(self.tk.call, (self._w, 'configure')
+		      + self._options(cnf))
+	def __getitem__(self, key):
+		v = self.tk.split(self.tk.call(
+			self._w, 'configure', '-' + key))
+		return v[4]
+	def __setitem__(self, key, value):
+		Widget.config(self, {key: value})
+	def __str__(self):
+		return self._w
+	def __del__(self):
+		self.tk.call('destroy', self._w)
+	destroy = __del__
+	def _do(self, name, args=()):
+		apply(self.tk.call, (self._w, name) + args) 
+
+class Toplevel(Widget, Wm):
+	def __init__(self, master=None, cnf={}):
+		extra = ()
+		if cnf.has_key('screen'):
+			extra = ('-screen', cnf['screen'])
+			del cnf['screen']
+		if cnf.has_key('class'):
+			extra = extra + ('-class', cnf['class'])
+			del cnf['class']
+		Widget.__init__(self, master, 'toplevel', cnf, extra)
+		self.iconname(self.tk.call('wm', 'iconname', '.'))
+		self.title(self.tk.call('wm', 'title', '.'))
+
+class Button(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'button', cnf)
+	def tk_butEnter(self):
+		self.tk.call('tk_butEnter', self._w)
+	def tk_butLeave(self):
+		self.tk.call('tk_butLeave', self._w)
+	def tk_butDown(self):
+		self.tk.call('tk_butDown', self._w)
+	def tk_butUp(self):
+		self.tk.call('tk_butUp', self._w)
+	def flash(self):
+		self.tk.call(self._w, 'flash')
+	def invoke(self):
+		self.tk.call(self._w, 'invoke')
+
+# Indices:
+def AtEnd():
+	return 'end'
+def AtInsert():
+	return 'insert'
+def AtSelFirst():
+	return 'sel.first'
+def AtSelLast():
+	return 'sel.last'
+def At(x, y=None):
+	if y:
+		return '@' + `x` + ',' + `y`
+	else:
+		return '@' + `x` 
+
+class Canvas(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'canvas', cnf)
+	def addtag(self, *args):
+		self._do('addtag', args)
+	def bbox(self, *args):
+		return self._getints(self._do('bbox', args))
+	def bind(self, tagOrId, sequence, func, add=''):
+		global _substitute, _subst_prefix
+		if add: add='+'
+		name = self._register(func, _substitute)
+		self.tk.call(self._w, 'bind', tagOrId, sequence, 
+			     (add + name,) + _subst_prefix)
+	def canvasx(self, screenx, gridspacing=None):
+		return self.tk.getint(self.tk.call(
+			self._w, 'canvasx', screenx, gridspacing))
+	def canvasy(self, screeny, gridspacing=None):
+		return self.tk.getint(self.tk.call(
+			self._w, 'canvasy', screeny, gridspacing))
+	def coords(self, *args):
+		return self._do('coords', args)
+	def _create(self, itemType, args): # Args: (value, value, ..., cnf={})
+		cnf = args[-1]
+		if type(cnf) == type({}):
+			args = args[:-1]
+		else:
+			cnf = {}
+		v = (self._w, 'create', itemType) + args
+		for k in cnf.keys():
+			v = v + ('-' + k, cnf[k])
+		return self.tk.getint(apply(self.tk.call, v))
+	def create_arc(self, *args):
+		Canvas._create(self, 'arc', args)
+	def create_bitmap(self, *args):
+		Canvas._create(self, 'bitmap', args)
+	def create_line(self, *args):
+		Canvas._create(self, 'line', args)
+	def create_oval(self, *args):
+		Canvas._create(self, 'oval', args)
+	def create_polygon(self, *args):
+		Canvas._create(self, 'polygon', args)
+	def create_rectangle(self, *args):
+		Canvas._create(self, 'rectangle', args)
+	def create_text(self, *args):
+		Canvas._create(self, 'text', args)
+	def create_window(self, *args):
+		Canvas._create(self, 'window', args)
+	def dchars(self, *args):
+		self._do('dchars', args)
+	def delete(self, *args):
+		self._do('delete', args)
+	def dtag(self, *args):
+		self._do('dtag', args)
+	def find(self, *args):
+		self.tk.splitlist(self._do('find', args))
+	def focus(self, *args):
+		return self._do('focus', args)
+	def gettags(self, *args):
+		return self.tk.splitlist(self._do('gettags', args))
+	def icursor(self, *args):
+		self._do('icursor', args)
+	def index(self, *args):
+		return self.tk.getint(self._do('index', args))
+	def insert(self, *args):
+		self._do('insert', args)
+	def itemconfig(self, tagOrId, cnf={}):
+		self._do('itemconfigure', (tagOrId,) + self._options(cnf))
+	def lower(self, *args):
+		self._do('lower', args)
+	def move(self, *args):
+		self._do('move', args)
+	def postscript(self, cnf={}):
+		return self._do('postscript', self._options(cnf))
+	def tkraise(self, *args):
+		self._do('raise', args)
+	def scale(self, *args):
+		self._do('scale', args)
+	def scan_mark(self, x, y):
+		self.tk.call(self._w, 'scan', 'mark', x, y)
+	def scan_dragto(self, x, y):
+		self.tk.call(self._w, 'scan', 'dragto', x, y)
+	def select_adjust(self, tagOrId, index):
+		self.tk.call(
+			self._w, 'select', 'adjust', tagOrId, index)
+	def select_clear(self):
+		self.tk.call(self._w, 'select', 'clear')
+	def select_from(self, tagOrId, index):
+		self.tk.call(
+			self._w, 'select', 'from', tagOrId, index)
+	def select_item(self):
+		self.tk.call(self._w, 'select', 'item')
+	def select_to(self, tagOrId, index):
+		self.tk.call(
+			self._w, 'select', 'to', tagOrId, index)
+	def type(self, tagOrId):
+		return self.tk.splitlist(self.tk.call(
+			self._w, 'type', tagOrId))
+	def xview(self, index):
+		self.tk.call(self._w, 'xview', index)
+	def yview(self, index):
+		self.tk.call(self._w, 'yview', index)
+
+class Checkbutton(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'checkbutton', cnf)
+	def deselect(self):
+		self.tk.call(self._w, 'deselect')
+	def flash(self):
+		self.tk.call(self._w, 'flash')
+	def invoke(self):
+		self.tk.call(self._w, 'invoke')
+	def select(self):
+		self.tk.call(self._w, 'select')
+	def toggle(self):
+		self.tk.call(self._w, 'toggle')
+
+class Entry(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'entry', cnf)
+	def tk_entryBackspace(self):
+		self.tk.call('tk_entryBackspace', self._w)
+	def tk_entryBackword(self):
+		self.tk.call('tk_entryBackword', self._w)
+	def tk_entrySeeCaret(self):
+		self.tk.call('tk_entrySeeCaret', self._w)
+	def delete(self, first, last=None):
+		self.tk.call(self._w, 'delete', first, last)
+	def get(self):
+		return self.tk.call(self._w, 'get')
+	def icursor(self, index):
+		self.tk.call(self._w, 'icursor', index)
+	def index(self, index):
+		return self.tk.getint(self.tk.call(
+			self._w, 'index', index))
+	def insert(self, index, string):
+		self.tk.call(self._w, 'insert', index, string)
+	def scan_mark(self, x):
+		self.tk.call(self._w, 'scan', 'mark', x)
+	def scan_dragto(self, x):
+		self.tk.call(self._w, 'scan', 'dragto', x)
+	def select_adjust(self, index):
+		self.tk.call(self._w, 'select', 'adjust', index)
+	def select_clear(self):
+		self.tk.call(self._w, 'select', 'clear')
+	def select_from(self, index):
+		self.tk.call(self._w, 'select', 'from', index)
+	def select_to(self, index):
+		self.tk.call(self._w, 'select', 'to', index)
+	def select_view(self, index):
+		self.tk.call(self._w, 'select', 'view', index)
+
+class Frame(Widget):
+	def __init__(self, master=None, cnf={}):
+		extra = ()
+		if cnf.has_key('class'):
+			extra = ('-class', cnf['class'])
+			del cnf['class']
+		Widget.__init__(self, master, 'frame', cnf, extra)
+	def tk_menuBar(self, *args):
+		apply(self.tk.call, ('tk_menuBar', self._w) + args)
+
+class Label(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'label', cnf)
+
+class Listbox(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'listbox', cnf)
+	def tk_listboxSingleSelect(self):
+		self.tk.call('tk_listboxSingleSelect', self._w) 
+	def curselection(self):
+		return self.tk.splitlist(self.tk.call(
+			self._w, 'curselection'))
+	def delete(self, first, last=None):
+		self.tk.call(self._w, 'delete', first, last)
+	def get(self, index):
+		return self.tk.call(self._w, 'get', index)
+	def insert(self, index, *elements):
+		apply(self.tk.call,
+		      (self._w, 'insert', index) + elements)
+	def nearest(self, y):
+		return self.tk.getint(self.tk.call(
+			self._w, 'nearest', y))
+	def scan_mark(self, x, y):
+		self.tk.call(self._w, 'scan', 'mark', x, y)
+	def scan_dragto(self, x, y):
+		self.tk.call(self._w, 'scan', 'dragto', x, y)
+	def select_adjust(self, index):
+		self.tk.call(self._w, 'select', 'adjust', index)
+	def select_clear(self):
+		self.tk.call(self._w, 'select', 'clear')
+	def select_from(self, index):
+		self.tk.call(self._w, 'select', 'from', index)
+	def select_to(self, index):
+		self.tk.call(self._w, 'select', 'to', index)
+	def size(self):
+		return self.tk.getint(self.tk.call(self._w, 'size'))
+	def xview(self, index):
+		self.tk.call(self._w, 'xview', index)
+	def yview(self, index):
+		self.tk.call(self._w, 'yview', index)
+
+class Menu(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'menu', cnf)
+	def tk_menuBar(self, *args):
+		apply(self.tk.call, ('tk_menuBar', self._w) + args)
+	def tk_bindForTraversal(self):
+		self.tk.call('tk_bindForTraversal', self._w)
+	def tk_mbPost(self):
+		self.tk.call('tk_mbPost', self._w)
+	def tk_mbUnpost(self):
+		self.tk.call('tk_mbUnpost')
+	def tk_traverseToMenu(self, char):
+		self.tk.call('tk_traverseToMenu', self._w, char)
+	def tk_traverseWithinMenu(self, char):
+		self.tk.call('tk_traverseWithinMenu', self._w, char)
+	def tk_getMenuButtons(self):
+		return self.tk.call('tk_getMenuButtons', self._w)
+	def tk_nextMenu(self, count):
+		self.tk.call('tk_nextMenu', count)
+	def tk_nextMenuEntry(self, count):
+		self.tk.call('tk_nextMenuEntry', count)
+	def tk_invokeMenu(self):
+		self.tk.call('tk_invokeMenu', self._w)
+	def tk_firstMenu(self):
+		self.tk.call('tk_firstMenu', self._w)
+	def tk_mbButtonDown(self):
+		self.tk.call('tk_mbButtonDown', self._w)
+	def activate(self, index):
+		self.tk.call(self._w, 'activate', index)
+	def add(self, itemType, cnf={}):
+		apply(self.tk.call, (self._w, 'add', itemType) 
+		      + self._options(cnf))
+	def delete(self, index1, index2=None):
+		self.tk.call(self._w, 'delete', index1, index2)
+	def entryconfig(self, index, cnf={}):
+		apply(self.tk.call, (self._w, 'entryconfigure', index)
+		      + self._options(cnf))
+	def index(self, index):
+		return self.tk.call(self._w, 'index', index)
+	def invoke(self, index):
+		return self.tk.call(self._w, 'invoke', index)
+	def post(self, x, y):
+		self.tk.call(self._w, 'post', x, y)
+	def unpost(self):
+		self.tk.call(self._w, 'unpost')
+	def yposition(self, index):
+		return self.tk.getint(self.tk.call(
+			self._w, 'yposition', index))
+
+class Menubutton(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'menubutton', cnf)
+
+class Message(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'message', cnf)
+
+class Radiobutton(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'radiobutton', cnf)
+	def deselect(self):
+		self.tk.call(self._w, 'deselect')
+	def flash(self):
+		self.tk.call(self._w, 'flash')
+	def invoke(self):
+		self.tk.call(self._w, 'invoke')
+	def select(self):
+		self.tk.call(self._w, 'select')
+
+class Scale(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'scale', cnf)
+	def get(self):
+		return self.tk.getint(self.tk.call(self._w, 'get'))
+	def set(self, value):
+		self.tk.call(self._w, 'set', value)
+
+class Scrollbar(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'scrollbar', cnf)
+	def get(self):
+		return self.tk.getints(self.tk.call(self._w, 'get'))
+	def set(self, totalUnits, windowUnits, firstUnit, lastUnit):
+		self.tk.call(self._w, 'set', 
+			     totalUnits, windowUnits, firstUnit, lastUnit)
+
+class Text(Widget):
+	def __init__(self, master=None, cnf={}):
+		Widget.__init__(self, master, 'text', cnf)
+	def tk_textSelectTo(self, index):
+		self.tk.call('tk_textSelectTo', self._w, index)
+	def tk_textBackspace(self):
+		self.tk.call('tk_textBackspace', self._w)
+	def tk_textIndexCloser(self, a, b, c):
+		self.tk.call('tk_textIndexCloser', self._w, a, b, c)
+	def tk_textResetAnchor(self, index):
+		self.tk.call('tk_textResetAnchor', self._w, index)
+	def compare(self, index1, op, index2):
+		return self.tk.getboolean(self.tk.call(
+			self._w, 'compare', index1, op, index2))
+	def debug(self, boolean=None):
+		return self.tk.getboolean(self.tk.call(
+			self._w, 'debug', boolean))
+	def delete(self, index1, index2=None):
+		self.tk.call(self._w, 'delete', index1, index2)
+	def get(self, index1, index2=None):
+		return self.tk.call(self._w, 'get', index1, index2)
+	def index(self, index):
+		return self.tk.call(self._w, 'index', index)
+	def insert(self, index, chars):
+		self.tk.call(self._w, 'insert', index, chars)
+	def mark_names(self):
+		return self.tk.splitlist(self.tk.call(
+			self._w, 'mark', 'names'))
+	def mark_set(self, markName, index):
+		self.tk.call(self._w, 'mark', 'set', markName, index)
+	def mark_unset(self, markNames):
+		apply(self.tk.call, (self._w, 'mark', 'unset') + markNames)
+	def scan_mark(self, y):
+		self.tk.call(self._w, 'scan', 'mark', y)
+	def scan_dragto(self, y):
+		self.tk.call(self._w, 'scan', 'dragto', y)
+	def tag_add(self, tagName, index1, index2=None):
+		self.tk.call(
+			self._w, 'tag', 'add', tagName, index1, index2)
+	def tag_bind(self, tagName, sequence, func, add=''):
+		global _substitute, _subst_prefix
+		if add: add='+'
+		name = self._register(func, _substitute)
+		self.tk.call(self._w, 'tag', 'bind', 
+			     tagName, sequence, 
+			     (add + name,) + _subst_prefix)
+	def tag_config(self, tagName, cnf={}):
+		apply(self.tk.call, 
+		      (self._w, 'tag', 'configure', tagName) 
+		      + self._options(cnf))
+	def tag_delete(self, tagNames):
+		apply(self.tk.call, (self._w, 'tag', 'delete') 
+		      + tagNames)
+	def tag_lower(self, tagName, belowThis=None):
+		self.tk.call(self._w, 'tag', 'lower', 
+			     tagName, belowThis)
+	def tag_names(self, index=None):
+		return self.tk.splitlist(
+			self.tk.call(self._w, 'tag', 'names', index))
+	def tag_nextrange(self, tagName, index1, index2=None):
+		return self.tk.splitlist(self.tk.call(
+			self._w, 'tag', 'nextrange', index1, index2))
+	def tag_raise(self, tagName, aboveThis=None):
+		self.tk.call(
+			self._w, 'tag', 'raise', tagName, aboveThis)
+	def tag_ranges(self, tagName):
+		return self.tk.splitlist(self.tk.call(
+			self._w, 'tag', 'ranges', tagName))
+	def tag_remove(self, tagName, index1, index2=None):
+		self.tk.call(
+			self._w, 'tag', 'remove', index1, index2)
+	def yview(self, what):
+		self.tk.call(self._w, 'yview', what)
+	def yview_pickplace(self, what):
+		self.tk.call(self._w, 'yview', '-pickplace', what)
+
+#class Dialog:
+	
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
new file mode 100644
index 0000000..2bb7060
--- /dev/null
+++ b/Modules/_tkinter.c
@@ -0,0 +1,1056 @@
+/* tkintermodule.c -- Interface to libtk.a and libtcl.a.
+   Copyright (C) 1994 Steen Lumholt */
+
+#if 0
+#include <Py/Python.h>
+#else
+
+#include "allobjects.h"
+#include "pythonrun.h"
+#include "intrcheck.h"
+#include "modsupport.h"
+#include "sysmodule.h"
+
+#define PyObject object
+typedef struct methodlist PyMethodDef;
+#define PyInit_tkinter inittkinter
+
+#undef Py_True
+#define Py_True ((object *) &TrueObject)
+#undef True
+
+#undef Py_False
+#define Py_False ((object *) &FalseObject)
+#undef False
+
+#undef Py_None
+#define Py_None (&NoObject)
+#undef None
+
+#endif /* 0 */
+
+#include <tcl.h>
+#include <tk.h>
+
+extern char *getprogramname ();
+extern int tk_NumMainWindows;
+
+/**** Tkapp Object Declaration ****/
+
+staticforward PyTypeObject Tkapp_Type;
+
+typedef struct
+  {
+    PyObject_HEAD
+    Tcl_Interp *interp;
+    Tk_Window tkwin;
+  }
+TkappObject;
+
+#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
+#define Tkapp_Tkwin(v)  (((TkappObject *) (v))->tkwin)
+#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
+#define Tkapp_Result(v) (((TkappObject *) (v))->interp->result)
+
+#define DEBUG_REFCNT(v) (printf ("DEBUG: id=%p, refcnt=%i\n", \
+				 (void *) v, ((PyObject *) v)->ob_refcnt))
+
+/**** Error Handling ****/
+
+static PyObject *Tkinter_TclError;
+static int errorInCmd = 0;
+static PyObject *excInCmd;
+static PyObject *valInCmd;
+
+static PyObject *
+Tkinter_Error (v)
+     PyObject *v;
+{
+  if (Tkapp_Check (v))
+    PyErr_BadInternalCall ();
+  PyErr_SetString (Tkinter_TclError, Tkapp_Result (v));
+  return NULL;
+}
+
+int
+PythonCmd_Error (interp)
+     Tcl_Interp *interp;
+{
+  errorInCmd = 1;
+  PyErr_GetAndClear (&excInCmd, &valInCmd);
+  return TCL_ERROR;
+}
+
+/**** Utils ****/
+
+static char *
+AsString (value, tmp)
+     PyObject *value;
+     PyObject *tmp;
+{
+  if (PyString_Check (value))
+    return PyString_AsString (value);
+  else
+    {
+      PyObject *v;
+
+      v = strobject (value);
+      PyList_Append (tmp, v);
+      Py_DECREF (v);
+      return PyString_AsString (v);
+    }
+}
+
+#define ARGSZ 64
+
+static char *
+Merge (args)
+     PyObject *args;
+{
+  PyObject *tmp;
+  char *argvStore[ARGSZ];
+  char **argv;
+  int fvStore[ARGSZ];
+  int *fv;
+  int argc;
+  char *res;
+  int i;
+
+  tmp = PyList_New (0);
+  argv = argvStore;
+  fv = fvStore;
+
+  if (!PyTuple_Check (args))
+    {
+      argc = 1;
+      fv[0] = 0;
+      argv[0] = AsString (args, tmp);
+    }
+  else
+    {
+      PyObject *v;
+
+      if (PyTuple_Size (args) > ARGSZ)
+	{
+	  argv = malloc (PyTuple_Size (args) * sizeof (char *));
+	  fv = malloc (PyTuple_Size (args) * sizeof (int));
+	  if (argv == NULL || fv == NULL)
+	    PyErr_NoMemory ();
+	}
+
+      argc = PyTuple_Size (args);
+      for (i = 0; i < argc; i++)
+	{
+	  v = PyTuple_GetItem (args, i);
+	  if (PyTuple_Check (v))
+	    {
+	      fv[i] = 1;
+	      argv[i] = Merge (v);
+	    }
+	  else if (v == Py_None)
+	    {
+	      argc = i;
+	      break;
+	    }
+	  else
+	    {
+	      fv[i] = 0;
+	      argv[i] = AsString (v, tmp);
+	    }
+	}
+    }
+
+  res = Tcl_Merge (argc, argv);
+
+  Py_DECREF (tmp);
+  for (i = 0; i < argc; i++)
+    if (fv[i]) free (argv[i]);
+  if (argv != argvStore)
+    free (argv);
+  if (fv != fvStore)
+    free (fv);
+
+  return res;
+}
+
+static PyObject *
+Split (self, list)
+     PyObject *self;
+     char *list;
+{
+  int argc;
+  char **argv;
+  PyObject *v;
+
+  if (list == NULL)
+    {
+      Py_INCREF (Py_None);
+      return Py_None;
+    }
+
+  if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR)
+    return Tkinter_Error (self);
+
+  if (argc == 0)
+    v = PyString_FromString ("");
+  else if (argc == 1)
+    v = PyString_FromString (argv[0]);
+  else
+    {
+      int i;
+
+      v = PyTuple_New (argc);
+      for (i = 0; i < argc; i++)
+	PyTuple_SetItem (v, i, Split (self, argv[i]));
+    }
+
+  free (argv);
+  return v;
+}
+
+/**** Tkapp Object ****/
+
+#ifndef WITH_APPINIT
+int
+Tcl_AppInit (interp)
+     Tcl_Interp *interp;
+{
+  if (Tcl_Init (interp) == TCL_ERROR)
+    return TCL_ERROR;
+  if (Tk_Init (interp) == TCL_ERROR)
+    return TCL_ERROR;
+  return TCL_OK;
+}
+#endif /* !WITH_APPINIT */
+
+/* Initialize the Tk application; see the `main' function in
+   `tkMain.c'.  */
+static TkappObject *
+Tkapp_New (screenName, baseName, className, interactive)
+     char *screenName;
+     char *baseName;
+     char *className;
+     int interactive;
+{
+  TkappObject *v;
+  
+  v = PyObject_NEW (TkappObject, &Tkapp_Type);
+  if (v == NULL)
+    return NULL;
+
+  v->interp = Tcl_CreateInterp ();
+  v->tkwin = Tk_CreateMainWindow (v->interp, screenName, 
+				  baseName, className);
+  if (v->tkwin == NULL)
+    return (TkappObject *) Tkinter_Error ((PyObject *) v);
+
+  Tk_GeometryRequest (v->tkwin, 200, 200);
+
+  if (screenName != NULL)
+    Tcl_SetVar2 (v->interp, "env", "DISPLAY", screenName, TCL_GLOBAL_ONLY);
+
+  if (interactive)
+    Tcl_SetVar (v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
+  else
+    Tcl_SetVar (v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
+
+#ifndef WITH_APPINIT
+  if (Tcl_AppInit (v->interp) != TCL_OK)
+    {
+      PyErr_SetString (Tkinter_TclError, "Tcl_AppInit failed"); /* XXX */
+      return NULL;
+    }
+#endif /* !WITH_APPINIT */
+
+  return v;
+}
+
+/** Tcl Eval **/
+
+static PyObject *
+Tkapp_Call (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *cmd;
+
+  cmd = Merge (args);
+  if (Tcl_Eval (Tkapp_Interp (self), cmd) == TCL_ERROR)
+    {
+      free (cmd);
+      return Tkinter_Error (self);
+    }
+
+  free (cmd);
+  return PyString_FromString (Tkapp_Result (self));
+}
+
+static PyObject *
+Tkapp_GlobalCall (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *cmd;
+
+  cmd = Merge (args);
+  if (Tcl_GlobalEval (Tkapp_Interp (self), cmd) == TCL_ERROR)
+    {
+      free (cmd);
+      return Tkinter_Error (self);
+    }
+  
+  free (cmd);
+  return PyString_FromString (Tkapp_Result (self));
+}
+
+static PyObject *
+Tkapp_Eval (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *script;
+  
+  if (!PyArg_Parse (args, "s", &script))
+    return NULL;
+
+  if (Tcl_Eval (Tkapp_Interp (self), script) == TCL_ERROR)
+    return Tkinter_Error (self);
+  
+  return PyString_FromString (Tkapp_Result (self));
+}
+
+static PyObject *
+Tkapp_GlobalEval (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *script;
+  
+  if (!PyArg_Parse (args, "s", &script))
+    return NULL;
+
+  if (Tcl_GlobalEval (Tkapp_Interp (self), script) == TCL_ERROR)
+    return Tkinter_Error (self);
+
+  return PyString_FromString (Tkapp_Result (self));
+}
+
+static PyObject *
+Tkapp_EvalFile (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *fileName;
+
+  if (!PyArg_Parse (args, "s", &fileName))
+    return NULL;
+
+  if (Tcl_EvalFile (Tkapp_Interp (self), fileName) == TCL_ERROR)
+    return Tkinter_Error (self);
+
+  return PyString_FromString (Tkapp_Result (self));
+}
+
+static PyObject *
+Tkapp_Record (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *script;
+
+  if (!PyArg_Parse (args, "s", &script))
+    return NULL;
+
+  if (Tcl_RecordAndEval (Tkapp_Interp (self), 
+			 script, TCL_NO_EVAL) == TCL_ERROR)
+    return Tkinter_Error (self);
+
+  return PyString_FromString (Tkapp_Result (self));
+}
+
+static PyObject *
+Tkapp_AddErrorInfo (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *msg;
+
+  if (!PyArg_Parse (args, "s", &msg))
+    return NULL;
+  Tcl_AddErrorInfo (Tkapp_Interp (self), msg);
+
+  Py_INCREF(Py_None);
+  return Py_None;
+}
+
+/** Tcl Variable **/
+
+static PyObject *
+SetVar (self, args, flags)
+     PyObject *self;
+     PyObject *args;
+     int flags;
+{
+  char *name1, *name2, *ok;
+  PyObject *newValue;
+  PyObject *tmp;
+
+  tmp = PyList_New (0);
+
+  if (PyArg_Parse (args, "(sO)", &name1, &newValue))
+    ok = Tcl_SetVar (Tkapp_Interp (self), name1, 
+		     AsString (newValue, tmp), flags); /* XXX Merge? */
+  else if (PyArg_Parse (args, "(ssO)", &name1, &name2, &newValue))
+    ok = Tcl_SetVar2 (Tkapp_Interp (self), name1, name2, 
+		      AsString (newValue, tmp), flags);
+  else
+    {
+      Py_DECREF (tmp);
+      return NULL;
+    }
+  Py_DECREF (tmp);
+
+  if (!ok)
+    return Tkinter_Error (self);
+
+  Py_INCREF (Py_None);
+  return Py_None;
+}
+
+static PyObject *
+Tkapp_SetVar (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  return SetVar (self, args, TCL_LEAVE_ERR_MSG);
+}
+
+static PyObject *
+Tkapp_GlobalSetVar (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  return SetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
+}
+
+static PyObject *
+GetVar (self, args, flags)
+     PyObject *self;
+     PyObject *args;
+     int flags;
+{
+  char *name1, *name2, *s;
+
+  if (PyArg_Parse (args, "s", &name1))
+    s = Tcl_GetVar (Tkapp_Interp (self), name1, flags);
+  else if (PyArg_Parse (args, "(ss)", &name1, &name2))
+    s = Tcl_GetVar2 (Tkapp_Interp (self), name1, name2, flags);
+  else
+    return NULL;
+
+  if (s == NULL)
+    return Tkinter_Error (self);
+
+  return PyString_FromString (s);
+}
+
+static PyObject *
+Tkapp_GetVar (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  return GetVar (self, args, TCL_LEAVE_ERR_MSG);
+}
+
+static PyObject *
+Tkapp_GlobalGetVar (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  return GetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
+}
+
+static PyObject *
+UnsetVar (self, args, flags)
+     PyObject *self;
+     PyObject *args;
+     int flags;
+{
+  char *name1, *name2;
+  int code;
+
+  if (PyArg_Parse (args, "s", &name1))
+    code = Tcl_UnsetVar (Tkapp_Interp (self), name1, flags);
+  else if (PyArg_Parse (args, "(ss)", &name1, &name2))
+    code = Tcl_UnsetVar2 (Tkapp_Interp (self), name1, name2, flags);
+  else
+    return NULL;
+
+  if (code == TCL_ERROR)
+    return Tkinter_Error (self);
+
+  Py_INCREF (Py_None);
+  return Py_None;
+}
+
+static PyObject *
+Tkapp_UnsetVar (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  return UnsetVar (self, args, TCL_LEAVE_ERR_MSG);
+}
+
+static PyObject *
+Tkapp_GlobalUnsetVar (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  return UnsetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
+}
+
+/** Tcl to Python **/
+
+static PyObject *
+Tkapp_GetInt (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *s;
+  int v;
+
+  if (!PyArg_Parse (args, "s", &s))
+    return NULL;
+  if (Tcl_GetInt (Tkapp_Interp (self), s, &v) == TCL_ERROR)
+    return Tkinter_Error (self);
+  return Py_BuildValue ("i", v);
+}
+
+static PyObject *
+Tkapp_GetDouble (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *s;
+  double v;
+
+  if (!PyArg_Parse (args, "s", &s))
+    return NULL;
+  if (Tcl_GetDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR)
+    return Tkinter_Error (self);
+  return Py_BuildValue ("d", v);
+}
+
+static PyObject *
+Tkapp_GetBoolean (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *s;
+  int v;
+
+  if (!PyArg_Parse (args, "s", &s))
+    return NULL;
+  if (Tcl_GetBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR)
+    return Tkinter_Error (self);
+  return Py_BuildValue ("i", v);
+}
+
+static PyObject *
+Tkapp_ExprString (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *s;
+
+  if (!PyArg_Parse (args, "s", &s))
+    return NULL;
+  if (Tcl_ExprString (Tkapp_Interp (self), s) == TCL_ERROR)
+    return Tkinter_Error (self);
+  return Py_BuildValue ("s", Tkapp_Result (self));
+}
+
+static PyObject *
+Tkapp_ExprLong (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *s;
+  long v;
+
+  if (!PyArg_Parse (args, "s", &s))
+    return NULL;
+  if (Tcl_ExprLong (Tkapp_Interp (self), s, &v) == TCL_ERROR)
+    return Tkinter_Error (self);
+  return Py_BuildValue ("l", v);
+}
+
+static PyObject *
+Tkapp_ExprDouble (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *s;
+  double v;
+
+  if (!PyArg_Parse (args, "s", &s))
+    return NULL;
+  if (Tcl_ExprDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR)
+    return Tkinter_Error (self);
+  return Py_BuildValue ("d", v);
+}
+
+static PyObject *
+Tkapp_ExprBoolean (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *s;
+  int v;
+
+  if (!PyArg_Parse (args, "s", &s))
+    return NULL;
+  if (Tcl_ExprBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR)
+    return Tkinter_Error (self);
+  return Py_BuildValue ("i", v);
+}
+
+static PyObject *
+Tkapp_SplitList (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *list;
+  int argc;
+  char **argv;
+  PyObject *v;
+  int i;
+
+  if (!PyArg_Parse (args, "s", &list))
+    return NULL;
+
+  if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR)
+    return Tkinter_Error (self);
+
+  v = PyTuple_New (argc);
+  for (i = 0; i < argc; i++)
+    PyTuple_SetItem (v, i, PyString_FromString (argv[i]));
+
+  free (argv);
+  return v;
+}
+
+static PyObject *
+Tkapp_Split (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *list;
+
+  if (!PyArg_Parse (args, "s", &list))
+    return NULL;
+  return Split (self, list);
+}
+
+static PyObject *
+Tkapp_Merge (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *s;
+  PyObject *v;
+
+  s = Merge (args);
+  v = PyString_FromString (s);
+  free (s);
+  return v;
+}
+
+/** Tcl Command **/
+
+/* This is the Tcl command that acts as a wrapper for Python
+   function or method.  */
+static int
+PythonCmd (clientData, interp, argc, argv)
+     ClientData clientData;	/* Is (self, func) */
+     Tcl_Interp *interp;
+     int argc;
+     char *argv[];
+{
+  PyObject *self, *func, *arg, *res, *tmp;
+  int i;
+
+  self = PyTuple_GetItem ((PyObject *) clientData, 0);
+  func = PyTuple_GetItem ((PyObject *) clientData, 1);
+
+  /* Create argument list (argv1, ..., argvN) */
+  arg = PyTuple_New (argc - 1);
+  for (i = 0; i < (argc - 1); i++)
+    PyTuple_SetItem (arg, i, PyString_FromString (argv[i + 1]));
+  
+  res = PyEval_CallObject (func, arg);
+  Py_DECREF (arg);
+  if (res == NULL)
+    return PythonCmd_Error (interp);
+
+  tmp = PyList_New (0);
+  Tcl_SetResult (Tkapp_Interp (self), AsString (res, tmp), TCL_VOLATILE);
+  Py_DECREF (res);
+  Py_DECREF (tmp);
+
+  return TCL_OK;
+}
+
+static void
+PythonCmdDelete (clientData)
+     ClientData clientData;	/* Is (self, func) */
+{
+  Py_DECREF ((PyObject *) clientData);
+}
+
+static PyObject *
+Tkapp_CreateCommand (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *cmdName;
+  PyObject *data;
+  PyObject *func;
+  
+  /* Args is: (cmdName, func) */
+  if (!PyTuple_Check (args) 
+      || !(PyTuple_Size (args) == 2)
+      || !PyString_Check (PyTuple_GetItem (args, 0))
+      || !(PyMethod_Check (PyTuple_GetItem (args, 1)) 
+	   || PyFunction_Check (PyTuple_GetItem (args, 1))))
+    {
+      PyErr_SetString (PyExc_TypeError, "bad argument list");
+      return NULL;
+    }
+
+  cmdName = PyString_AsString (PyTuple_GetItem (args, 0));
+  func = PyTuple_GetItem (args, 1);
+
+  data = PyTuple_New (2);   /* ClientData is: (self, func) */
+
+  Py_INCREF (self);
+  PyTuple_SetItem (data, 0, self);
+
+  Py_INCREF (func);
+  PyTuple_SetItem (data, 1, func);
+
+  Tcl_CreateCommand (Tkapp_Interp (self), cmdName, PythonCmd,
+		     (ClientData) data, PythonCmdDelete);
+
+  Py_INCREF (Py_None);
+  return Py_None;
+}
+
+static PyObject *
+Tkapp_DeleteCommand (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *cmdName;
+
+  if (!PyArg_Parse (args, "s", &cmdName))
+    return NULL;
+  if (Tcl_DeleteCommand (Tkapp_Interp (self), cmdName) == -1)
+    {
+      PyErr_SetString (Tkinter_TclError, "can't delete Tcl command");
+      return NULL;
+    }
+  Py_INCREF (Py_None);
+  return Py_None;
+}
+
+/** File Handler **/
+
+void
+FileHandler (clientData, mask)
+     ClientData clientData;	/* Is: func */
+     int mask;
+{
+  PyObject *func;
+  PyObject *arg, *res;
+
+  func = (PyObject *) clientData;
+
+  arg = PyInt_FromLong ((long) mask);
+  res = PyEval_CallObject (func, arg);
+  Py_DECREF (arg);
+  if (res == NULL)
+    {
+      errorInCmd = 1;
+      PyErr_GetAndClear (&excInCmd, &valInCmd);
+    }
+}
+
+static PyObject *
+Tkapp_CreateFileHandler (self, args)
+     PyObject *self;
+     PyObject *args;		/* Is (file, mask, func) */
+{
+  PyObject *file;
+  int mask;
+  PyObject *func;
+  int id;
+
+  if (!PyArg_Parse (args, "(OiO)", &file, &mask, &func))
+    return NULL;
+  if (!PyFile_Check (file) 
+      || !(PyMethod_Check(func) || PyFunction_Check(func)))
+    {
+      PyErr_SetString (PyExc_TypeError, "bad argument list");
+      return NULL;
+    }
+
+  id = fileno (PyFile_AsFile (file));
+  Py_DECREF (file);
+  Tk_CreateFileHandler (id, mask, FileHandler, (ClientData) func);
+  /* XXX fileHandlerDict */
+  Py_INCREF (Py_None);
+  return Py_None;
+}
+
+static PyObject *
+Tkapp_DeleteFileHandler (self, args)
+     PyObject *self;
+     PyObject *args;		/* Args: file */
+{
+  int id;
+
+  if (!PyFile_Check (args))
+    {
+      PyErr_SetString (PyExc_TypeError, "bad argument list");
+      return NULL;
+    }
+
+  id = fileno (PyFile_AsFile (args));
+  Tk_DeleteFileHandler (id);
+  /* XXX fileHandlerDict */
+  Py_INCREF (Py_None);
+  return Py_None;
+}
+
+/** Event Loop **/
+
+static int quitMainLoop;
+
+static PyObject *
+Tkapp_MainLoop (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  if (!PyArg_Parse (args, ""))
+    return NULL;
+
+  quitMainLoop = 0;
+  while (tk_NumMainWindows > 0 && !quitMainLoop && !errorInCmd)
+    {
+      if (PyOS_InterruptOccurred ())
+	{
+	  PyErr_SetNone (PyExc_KeyboardInterrupt);
+	  return NULL;
+	}
+      Tk_DoOneEvent (0);
+    }
+
+  if (errorInCmd)
+    {
+      errorInCmd = 0;
+      PyErr_SetObject (excInCmd, valInCmd);
+      return NULL;
+    }
+  Py_INCREF (Py_None);
+  return Py_None;
+}
+
+static PyObject *
+Tkapp_Quit (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+
+  if (!PyArg_Parse (args, ""))
+    return NULL;
+  quitMainLoop = 1;
+  Py_INCREF (Py_None);
+  return Py_None;
+}
+
+/**** Tkapp Method List ****/
+
+static PyMethodDef Tkapp_methods[] =
+{
+  {"call", Tkapp_Call},
+  {"globalcall", Tkapp_GlobalCall},
+  {"eval", Tkapp_Eval},
+  {"globaleval", Tkapp_GlobalEval},
+  {"evalfile", Tkapp_EvalFile},
+  {"record", Tkapp_Record},
+  {"adderrorinfo", Tkapp_AddErrorInfo},
+  {"setvar", Tkapp_SetVar},
+  {"globalsetvar", Tkapp_GlobalSetVar},
+  {"getvar", Tkapp_GetVar},
+  {"globalgetvar", Tkapp_GlobalGetVar},
+  {"unsetvar", Tkapp_UnsetVar},
+  {"globalunsetvar", Tkapp_GlobalUnsetVar},
+  {"getint", Tkapp_GetInt},
+  {"getdouble", Tkapp_GetDouble},
+  {"getboolean", Tkapp_GetBoolean},
+  {"exprstring", Tkapp_ExprString},
+  {"exprlong", Tkapp_ExprLong},
+  {"exprdouble", Tkapp_ExprDouble},
+  {"exprboolean", Tkapp_ExprBoolean},
+  {"splitlist", Tkapp_SplitList},
+  {"split", Tkapp_Split},
+  {"merge", Tkapp_Merge},
+  {"createcommand", Tkapp_CreateCommand},
+  {"deletecommand", Tkapp_DeleteCommand},
+  {"createfilehandler", Tkapp_CreateFileHandler},
+  {"deletefilehandler", Tkapp_DeleteFileHandler},
+  {"mainloop", Tkapp_MainLoop},
+  {"quit", Tkapp_Quit},
+  {NULL, NULL}
+};
+
+/**** Tkapp Type Methods ****/
+
+static void
+Tkapp_Dealloc (self)
+     PyObject *self;
+{
+  Tk_DestroyWindow (Tkapp_Tkwin (self));
+  Tcl_DeleteInterp (Tkapp_Interp (self));
+  PyMem_DEL (self);
+}
+
+static PyObject *
+Tkapp_GetAttr (self, name)
+     PyObject *self;
+     char *name;
+{
+  return Py_FindMethod (Tkapp_methods, self, name);
+}
+
+static PyTypeObject Tkapp_Type =
+{
+  OB_HEAD_INIT (&PyType_Type)
+  0,				/*ob_size */
+  "tkapp",			/*tp_name */
+  sizeof (TkappObject),		/*tp_basicsize */
+  0,				/*tp_itemsize */
+  Tkapp_Dealloc,		/*tp_dealloc */
+  0,				/*tp_print */
+  Tkapp_GetAttr,		/*tp_getattr */
+  0,				/*tp_setattr */
+  0,				/*tp_compare */
+  0,				/*tp_repr */
+  0,				/*tp_as_number */
+  0,				/*tp_as_sequence */
+  0,				/*tp_as_mapping */
+  0,				/*tp_hash */
+};
+
+/**** Tkinter Module ****/
+
+static PyObject *
+Tkinter_Create (self, args)
+     PyObject *self;
+     PyObject *args;
+{
+  char *screenName = NULL;
+  char *baseName;
+  char *className;
+  int interactive = 0;
+
+  baseName = strrchr (getprogramname (), '/');
+  if (baseName != NULL)
+    baseName++;
+  else
+    baseName = getprogramname ();
+  className = "Tk";
+  
+  if (PyArg_Parse (args, ""))
+    /* VOID */ ;
+  else if (PyArg_Parse (args, "z", 
+			&screenName))
+    /* VOID */ ;
+  else if (PyArg_Parse (args, "(zs)", 
+			&screenName, &baseName))
+    /* VOID */ ;
+  else if (PyArg_Parse (args, "(zss)", 
+			&screenName, &baseName, &className))
+    /* VOID */ ;
+  else if (PyArg_Parse (args, "(zssi)", 
+			&screenName, &baseName, &className, &interactive))
+    /* VOID */ ;
+  else
+    return NULL;
+
+  return (PyObject *) Tkapp_New (screenName, baseName, className, 
+				 interactive);
+}
+
+static PyMethodDef moduleMethods[] =
+{
+  {"create", Tkinter_Create},
+  {NULL, NULL}
+};
+
+#ifdef WITH_READLINE
+static int
+EventHook ()
+{
+  if (errorInCmd)		/* XXX Reset tty */
+    {
+      errorInCmd = 0;
+      PyErr_SetObject (excInCmd, valInCmd);
+      PyErr_Print ();
+     }
+  if (tk_NumMainWindows > 0)
+    Tk_DoOneEvent (0);
+  return 0;
+}
+#endif /* WITH_READLINE */
+
+static void
+StdinProc (clientData, mask)
+     ClientData clientData;
+     int mask;
+{
+  /* Do nothing. */
+}
+
+void
+PyInit_tkinter ()
+{
+#ifdef WITH_READLINE
+  extern int (*rl_event_hook) ();
+#endif /* WITH_READLINE */
+  PyObject *m, *d, *v;
+
+  m = Py_InitModule ("tkinter", moduleMethods);
+
+  d = PyModule_GetDict (m);
+  Tkinter_TclError = Py_BuildValue ("s", "TclError");
+  PyDict_SetItemString (d, "TclError", Tkinter_TclError);
+
+  v = Py_BuildValue ("i", TK_READABLE);
+  PyDict_SetItemString (d, "READABLE", v);
+  v = Py_BuildValue ("i", TK_WRITABLE);
+  PyDict_SetItemString (d, "WRITABLE", v);
+  v = Py_BuildValue ("i", TK_EXCEPTION);
+  PyDict_SetItemString (d, "EXCEPTION", v);
+
+  /* Unblock stdin. */
+  Tk_CreateFileHandler (0, TK_READABLE, StdinProc, (ClientData) 0);
+
+#ifdef WITH_READLINE
+  rl_event_hook = EventHook;
+#endif /* WITH_READLINE */
+
+  if (PyErr_Occurred ())
+    Py_FatalError ("can't initialize module tkinter");
+}