mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	constructors.  There is no backward compatibility.  Not everything has
  been tested.
* aiff.{py,doc}: deleted in favor of aifc.py (which contains its docs as
  comments)
		
	
			
		
			
				
	
	
		
			256 lines
		
	
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			256 lines
		
	
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# Standard main loop for *all* STDWIN applications.
 | 
						|
# This requires that applications:
 | 
						|
# - register their windows on creation and unregister them when closed
 | 
						|
# - have a 'dispatch' function as a window member
 | 
						|
 | 
						|
 | 
						|
import stdwin, stdwinq
 | 
						|
from stdwinevents import *
 | 
						|
 | 
						|
 | 
						|
# List of windows known to the main loop.
 | 
						|
#
 | 
						|
windows = []
 | 
						|
 | 
						|
 | 
						|
# Last window that ever received an event
 | 
						|
#
 | 
						|
last_window = None
 | 
						|
 | 
						|
 | 
						|
# Function to register a window.
 | 
						|
#
 | 
						|
def register(win):
 | 
						|
	# First test the dispatch function by passing it a null event --
 | 
						|
	# this catches registration of unconforming windows.
 | 
						|
	win.dispatch((WE_NULL, win, None))
 | 
						|
	if win not in windows:
 | 
						|
		windows.append(win)
 | 
						|
 | 
						|
 | 
						|
# Function to unregister a window.
 | 
						|
# It is not an error to unregister an already unregistered window
 | 
						|
# (this is useful for cleanup actions).
 | 
						|
#
 | 
						|
def unregister(win):
 | 
						|
	global last_window
 | 
						|
	if win == last_window:
 | 
						|
		last_window = None
 | 
						|
	if win in windows:
 | 
						|
		windows.remove(win) # Not in 0.9.1
 | 
						|
		# 0.9.1 solution:
 | 
						|
		#for i in range(len(windows)):
 | 
						|
		#	if windows[i] = win:
 | 
						|
		#		del windows[i]
 | 
						|
		#		break
 | 
						|
 | 
						|
 | 
						|
# Interfaces used by WindowSched.
 | 
						|
#
 | 
						|
def countwindows():
 | 
						|
	return len(windows)
 | 
						|
#
 | 
						|
def anywindow():
 | 
						|
	if windows:
 | 
						|
		return windows[0]
 | 
						|
	else:
 | 
						|
		return None
 | 
						|
 | 
						|
 | 
						|
# NEW: register any number of file descriptors
 | 
						|
#
 | 
						|
fdlist = []
 | 
						|
select_args = None
 | 
						|
select_handlers = None
 | 
						|
#
 | 
						|
def registerfd(fd, mode, handler):
 | 
						|
	if mode not in ('r', 'w', 'x'):
 | 
						|
		raise ValueError, 'mode must be r, w or x'
 | 
						|
	if type(fd) <> type(0):
 | 
						|
		fd = fd.fileno() # If this fails it's not a proper select arg
 | 
						|
	for i in range(len(fdlist)):
 | 
						|
		if fdlist[i][:2] == (fd, mode):
 | 
						|
			raise ValueError, \
 | 
						|
				'(fd, mode) combination already registered'
 | 
						|
	fdlist.append((fd, mode, handler))
 | 
						|
	make_select_args()
 | 
						|
#
 | 
						|
def unregisterfd(fd, *args):
 | 
						|
	if type(fd) <> type(0):
 | 
						|
		fd = fd.fileno() # If this fails it's not a proper select arg
 | 
						|
	args = (fd,) + args
 | 
						|
	n = len(args)
 | 
						|
	for i in range(len(fdlist)):
 | 
						|
		if fdlist[i][:n] == args:
 | 
						|
			del fdlist[i]
 | 
						|
	make_select_args()
 | 
						|
#
 | 
						|
def make_select_args():
 | 
						|
	global select_args, select_handlers
 | 
						|
	rlist, wlist, xlist = [], [], []
 | 
						|
	rhandlers, whandlers, xhandlers = {}, {}, {}
 | 
						|
	for fd, mode, handler in fdlist:
 | 
						|
		if mode == 'r':
 | 
						|
			rlist.append(fd)
 | 
						|
			rhandlers[`fd`] = handler
 | 
						|
		if mode == 'w':
 | 
						|
			wlist.append(fd)
 | 
						|
			whandlers[`fd`] = handler
 | 
						|
		if mode == 'x':
 | 
						|
			xlist.append(fd)
 | 
						|
			xhandlers[`fd`] = handler
 | 
						|
	if rlist or wlist or xlist:
 | 
						|
		select_args = rlist, wlist, xlist
 | 
						|
		select_handlers = rhandlers, whandlers, xhandlers
 | 
						|
	else:
 | 
						|
		select_args = None
 | 
						|
		select_handlers = None
 | 
						|
#
 | 
						|
def do_select():
 | 
						|
	import select
 | 
						|
	reply = apply(select.select, select_args)
 | 
						|
	for mode in 0, 1, 2:
 | 
						|
		list = reply[mode]
 | 
						|
		for fd in list:
 | 
						|
			handler = select_handlers[mode][`fd`]
 | 
						|
			handler(fd, 'rwx'[mode])
 | 
						|
 | 
						|
 | 
						|
# Event processing main loop.
 | 
						|
# Return when there are no windows left, or when an unhandled
 | 
						|
# exception occurs.  (It is safe to restart the main loop after
 | 
						|
# an unsuccessful exit.)
 | 
						|
# Python's stdwin.getevent() turns WE_COMMAND/WC_CANCEL events
 | 
						|
# into KeyboardInterrupt exceptions; these are turned back in events.
 | 
						|
#
 | 
						|
recursion_level = 0 # Hack to make it reentrant
 | 
						|
def mainloop():
 | 
						|
	global recursion_level
 | 
						|
	recursion_level = recursion_level + 1
 | 
						|
	try:
 | 
						|
		stdwin_select_handler() # Process events already in queue
 | 
						|
		while 1:
 | 
						|
			if windows and not fdlist:
 | 
						|
				while windows and not fdlist:
 | 
						|
					try:
 | 
						|
						event = stdwinq.getevent()
 | 
						|
					except KeyboardInterrupt:
 | 
						|
						event = (WE_COMMAND, \
 | 
						|
							 None, WC_CANCEL)
 | 
						|
					dispatch(event)
 | 
						|
			elif windows and fdlist:
 | 
						|
				fd = stdwin.fileno()
 | 
						|
				if recursion_level == 1:
 | 
						|
				    registerfd(fd, 'r', stdwin_select_handler)
 | 
						|
				try:
 | 
						|
					while windows:
 | 
						|
						do_select()
 | 
						|
						stdwin_select_handler()
 | 
						|
				finally:
 | 
						|
					if recursion_level == 1:
 | 
						|
						unregisterfd(fd)
 | 
						|
			elif fdlist:
 | 
						|
				while fdlist and not windows:
 | 
						|
					do_select()
 | 
						|
			else:
 | 
						|
				break
 | 
						|
	finally:
 | 
						|
		recursion_level = recursion_level - 1
 | 
						|
 | 
						|
 | 
						|
# Check for events without ever blocking
 | 
						|
#
 | 
						|
def check():
 | 
						|
	stdwin_select_handler()
 | 
						|
	# XXX Should check for socket stuff as well
 | 
						|
 | 
						|
 | 
						|
# Handle stdwin events until none are left
 | 
						|
#
 | 
						|
def stdwin_select_handler(*args):
 | 
						|
	while 1:
 | 
						|
		try:
 | 
						|
			event = stdwinq.pollevent()
 | 
						|
		except KeyboardInterrupt:
 | 
						|
			event = (WE_COMMAND, None, WC_CANCEL)
 | 
						|
		if event is None:
 | 
						|
			break
 | 
						|
		dispatch(event)
 | 
						|
 | 
						|
 | 
						|
# Run a modal dialog loop for a window.  The dialog window must have
 | 
						|
# been registered first.  This prohibits most events (except size/draw
 | 
						|
# events) to other windows.  The modal dialog loop ends when the
 | 
						|
# dialog window unregisters itself.
 | 
						|
#
 | 
						|
passthrough = WE_SIZE, WE_DRAW
 | 
						|
beeping = WE_MOUSE_DOWN, WE_COMMAND, WE_CHAR, WE_KEY, WE_CLOSE, WE_MENU
 | 
						|
#
 | 
						|
def modaldialog(window):
 | 
						|
	if window not in windows:
 | 
						|
		raise ValueError, 'modaldialog window not registered'
 | 
						|
	while window in windows:
 | 
						|
		try:
 | 
						|
			event = stdwinq.getevent()
 | 
						|
		except KeyboardInterrupt:
 | 
						|
			event = WE_COMMAND, None, WC_CANCEL
 | 
						|
		etype, ewindow, edetail = event
 | 
						|
		if etype not in passthrough and ewindow <> window:
 | 
						|
			if etype in beeping:
 | 
						|
				stdwin.fleep()
 | 
						|
			continue
 | 
						|
		dispatch(event)
 | 
						|
 | 
						|
 | 
						|
# Dispatch a single event.
 | 
						|
# Events for the no window in particular are sent to the active window
 | 
						|
# or to the last window that received an event (these hacks are for the
 | 
						|
# WE_LOST_SEL event, which is directed to no particular window).
 | 
						|
# Windows not in the windows list don't get their events:
 | 
						|
# events for such windows are silently ignored.
 | 
						|
#
 | 
						|
def dispatch(event):
 | 
						|
	global last_window
 | 
						|
	if event[1] == None:
 | 
						|
		active = stdwin.getactive()
 | 
						|
		if active: last_window = active
 | 
						|
	else:
 | 
						|
		last_window = event[1]
 | 
						|
	if last_window in windows:
 | 
						|
		last_window.dispatch(event)
 | 
						|
 | 
						|
 | 
						|
# Dialog base class
 | 
						|
#
 | 
						|
class Dialog:
 | 
						|
	#
 | 
						|
	def __init__(self, title):
 | 
						|
		self.window = stdwin.open(title)
 | 
						|
		self.window.dispatch = self.dispatch
 | 
						|
		register(self.window)
 | 
						|
	#
 | 
						|
	def close(self):
 | 
						|
		unregister(self.window)
 | 
						|
		del self.window.dispatch
 | 
						|
		self.window.close()
 | 
						|
	#
 | 
						|
	def dispatch(self, event):
 | 
						|
		etype, ewindow, edetail = event
 | 
						|
		if etype == WE_CLOSE:
 | 
						|
			self.close()
 | 
						|
 | 
						|
 | 
						|
# Standard modal dialogs
 | 
						|
# XXX implemented using stdwin dialogs for now
 | 
						|
#
 | 
						|
def askstr(prompt, default):
 | 
						|
	return stdwin.askstr(prompt, default)
 | 
						|
#
 | 
						|
def askync(prompt, yesorno):
 | 
						|
	return stdwin.askync(prompt, yesorno)
 | 
						|
#
 | 
						|
def askfile(prompt, default, new):
 | 
						|
	return stdwin.askfile(prompt, default, new)
 | 
						|
#
 | 
						|
def message(msg):
 | 
						|
	stdwin.message(msg)
 |