summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1990-10-13 19:23:40 (GMT)
committerGuido van Rossum <guido@python.org>1990-10-13 19:23:40 (GMT)
commitc636014c430620325f8d213e9ba10d925991b8d7 (patch)
tree058a21f7da3d8c6e7da0756ef7b1402fe7169a1a /Lib
parentdf79a1ee192231a75a381798bb35cefaf6c31a2a (diff)
downloadcpython-c636014c430620325f8d213e9ba10d925991b8d7.zip
cpython-c636014c430620325f8d213e9ba10d925991b8d7.tar.gz
cpython-c636014c430620325f8d213e9ba10d925991b8d7.tar.bz2
Initial revision
Diffstat (limited to 'Lib')
-rw-r--r--Lib/calendar.py213
-rw-r--r--Lib/cmp.py61
-rw-r--r--Lib/cmpcache.py74
-rw-r--r--Lib/commands.py73
-rw-r--r--Lib/dircache.py36
-rw-r--r--Lib/dircmp.py215
-rw-r--r--Lib/dump.py63
-rw-r--r--Lib/getopt.py47
-rwxr-xr-xLib/irix5/DEVICE.py423
-rwxr-xr-xLib/irix5/GL.py365
-rwxr-xr-xLib/irix5/auds.py106
-rwxr-xr-xLib/irix5/panel.py281
-rwxr-xr-xLib/irix5/panelparser.py128
-rw-r--r--Lib/lib-old/dump.py63
-rw-r--r--Lib/lib-old/rand.py12
-rw-r--r--Lib/lib-old/util.py9
-rw-r--r--Lib/lib-stdwin/anywin.py14
-rw-r--r--Lib/lib-stdwin/dirwin.py28
-rw-r--r--Lib/lib-stdwin/filewin.py31
-rw-r--r--Lib/lib-stdwin/gwin.py118
-rw-r--r--Lib/lib-stdwin/listwin.py47
-rw-r--r--Lib/lib-stdwin/rect.py87
-rw-r--r--Lib/lib-stdwin/stdwinevents.py36
-rw-r--r--Lib/lib-stdwin/tablewin.py237
-rw-r--r--Lib/lib-stdwin/textwin.py119
-rwxr-xr-xLib/plat-irix5/DEVICE.py423
-rwxr-xr-xLib/plat-irix5/GL.py365
-rwxr-xr-xLib/plat-irix5/panel.py281
-rwxr-xr-xLib/plat-irix5/panelparser.py128
-rw-r--r--Lib/poly.py55
-rw-r--r--Lib/posixpath.py124
-rw-r--r--Lib/rand.py12
-rw-r--r--Lib/shutil.py70
-rw-r--r--Lib/statcache.py90
-rwxr-xr-xLib/stdwin/anywin.py14
-rwxr-xr-xLib/stdwin/dirwin.py28
-rwxr-xr-xLib/stdwin/filewin.py31
-rwxr-xr-xLib/stdwin/gwin.py118
-rwxr-xr-xLib/stdwin/listwin.py47
-rwxr-xr-xLib/stdwin/rect.py87
-rwxr-xr-xLib/stdwin/stdwinevents.py36
-rwxr-xr-xLib/stdwin/tablewin.py237
-rwxr-xr-xLib/stdwin/textwin.py119
-rw-r--r--Lib/string.py129
-rw-r--r--Lib/stringold.py129
-rw-r--r--Lib/util.py9
-rw-r--r--Lib/whrandom.py74
47 files changed, 5492 insertions, 0 deletions
diff --git a/Lib/calendar.py b/Lib/calendar.py
new file mode 100644
index 0000000..49e8e63
--- /dev/null
+++ b/Lib/calendar.py
@@ -0,0 +1,213 @@
+# module calendar
+
+##############################
+# Calendar support functions #
+##############################
+
+# This is based on UNIX ctime() et al. (also Standard C and POSIX)
+# Subtle but crucial differences:
+# - the order of the elements of a 'struct tm' differs, to ease sorting
+# - months numbers are 1-12, not 0-11; month arrays have a dummy element 0
+# - Monday is the first day of the week (numbered 0)
+
+# These are really parameters of the 'time' module:
+epoch = 1970 # Time began on January 1 of this year (00:00:00 UCT)
+day_0 = 3 # The epoch begins on a Thursday (Monday = 0)
+
+# Return 1 for leap years, 0 for non-leap years
+def isleap(year):
+ return year % 4 = 0 and (year % 100 <> 0 or year % 400 = 0)
+
+# Constants for months referenced later
+January = 1
+February = 2
+
+# Number of days per month (except for February in leap years)
+mdays = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
+
+# Exception raised for bad input (with string parameter for details)
+error = 'calendar error'
+
+# Turn seconds since epoch into calendar time
+def gmtime(secs):
+ if secs < 0: raise error, 'negative input to gmtime()'
+ mins, secs = divmod(secs, 60)
+ hours, mins = divmod(mins, 60)
+ days, hours = divmod(hours, 24)
+ wday = (days + day_0) % 7
+ year = epoch
+ # XXX Most of the following loop can be replaced by one division
+ while 1:
+ yd = 365 + isleap(year)
+ if days < yd: break
+ days = days - yd
+ year = year + 1
+ yday = days
+ month = January
+ while 1:
+ md = mdays[month] + (month = February and isleap(year))
+ if days < md: break
+ days = days - md
+ month = month + 1
+ return year, month, days + 1, hours, mins, secs, yday, wday
+ # XXX Week number also?
+
+# Return number of leap years in range [y1, y2)
+# Assume y1 <= y2 and no funny (non-leap century) years
+def leapdays(y1, y2):
+ return (y2+3)/4 - (y1+3)/4
+
+# Inverse of gmtime():
+# Turn UCT calendar time (less yday, wday) into seconds since epoch
+def mktime(year, month, day, hours, mins, secs):
+ days = day - 1
+ for m in range(January, month): days = days + mdays[m]
+ if isleap(year) and month > February: days = days+1
+ days = days + (year-epoch)*365 + leapdays(epoch, year)
+ return ((days*24 + hours)*60 + mins)*60 + secs
+
+# Full and abbreviated names of weekdays
+day_name = ('Monday', 'Tuesday', 'Wednesday', 'Thursday')
+day_name = day_name + ('Friday', 'Saturday', 'Sunday')
+day_abbr = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
+
+# Full and abbreviated of months (1-based arrays!!!)
+month_name = ('', 'January', 'February', 'March', 'April')
+month_name = month_name + ('May', 'June', 'July', 'August')
+month_name = month_name + ('September', 'October', 'November', 'December')
+month_abbr = (' ', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun')
+month_abbr = month_abbr + ('Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')
+
+# Zero-fill string to two positions (helper for asctime())
+def dd(s):
+ while len(s) < 2: s = '0' + s
+ return s
+
+# Blank-fill string to two positions (helper for asctime())
+def zd(s):
+ while len(s) < 2: s = ' ' + s
+ return s
+
+# Turn calendar time as returned by gmtime() into a string
+# (the yday parameter is for compatibility with gmtime())
+def asctime(year, month, day, hours, mins, secs, yday, wday):
+ s = day_abbr[wday] + ' ' + month_abbr[month] + ' ' + zd(`day`)
+ s = s + ' ' + dd(`hours`) + ':' + dd(`mins`) + ':' + dd(`secs`)
+ return s + ' ' + `year`
+
+# Localization: Minutes West from Greenwich
+# timezone = -2*60 # Middle-European time with DST on
+timezone = 5*60 # EST (sigh -- THINK time() doesn't return UCT)
+
+# Local time ignores DST issues for now -- adjust 'timezone' to fake it
+def localtime(secs):
+ return gmtime(secs - timezone*60)
+
+# UNIX-style ctime (except it doesn't append '\n'!)
+def ctime(secs):
+ return asctime(localtime(secs))
+
+######################
+# Non-UNIX additions #
+######################
+
+# Calendar printing etc.
+
+# Return weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12), day (1-31)
+def weekday(year, month, day):
+ secs = mktime(year, month, day, 0, 0, 0)
+ days = secs / (24*60*60)
+ return (days + day_0) % 7
+
+# Return weekday (0-6 ~ Mon-Sun) and number of days (28-31) for year, month
+def monthrange(year, month):
+ day1 = weekday(year, month, 1)
+ ndays = mdays[month] + (month = February and isleap(year))
+ return day1, ndays
+
+# Return a matrix representing a month's calendar
+# Each row represents a week; days outside this month are zero
+def _monthcalendar(year, month):
+ day1, ndays = monthrange(year, month)
+ rows = []
+ r7 = range(7)
+ day = 1 - day1
+ while day <= ndays:
+ row = [0, 0, 0, 0, 0, 0, 0]
+ for i in r7:
+ if 1 <= day <= ndays: row[i] = day
+ day = day + 1
+ rows.append(row)
+ return rows
+
+# Caching interface to _monthcalendar
+mc_cache = {}
+def monthcalendar(year, month):
+ key = `year` + month_abbr[month]
+ try:
+ return mc_cache[key]
+ except RuntimeError:
+ mc_cache[key] = ret = _monthcalendar(year, month)
+ return ret
+
+# Center a string in a field
+def center(str, width):
+ n = width - len(str)
+ if n < 0: return str
+ return ' '*(n/2) + str + ' '*(n-n/2)
+
+# XXX The following code knows that print separates items with space!
+
+# Print a single week (no newline)
+def prweek(week, width):
+ for day in week:
+ if day = 0: print ' '*width,
+ else:
+ if width > 2: print ' '*(width-3),
+ if day < 10: print '',
+ print day,
+
+# Return a header for a week
+def weekheader(width):
+ str = ''
+ for i in range(7):
+ if str: str = str + ' '
+ str = str + day_abbr[i%7][:width]
+ return str
+
+# Print a month's calendar
+def prmonth(year, month):
+ print weekheader(3)
+ for week in monthcalendar(year, month):
+ prweek(week, 3)
+ print
+
+# Spacing between month columns
+spacing = ' '
+
+# 3-column formatting for year calendars
+def format3c(a, b, c):
+ print center(a, 20), spacing, center(b, 20), spacing, center(c, 20)
+
+# Print a year's calendar
+def prcal(year):
+ header = weekheader(2)
+ format3c('', `year`, '')
+ for q in range(January, January+12, 3):
+ print
+ format3c(month_name[q], month_name[q+1], month_name[q+2])
+ format3c(header, header, header)
+ data = []
+ height = 0
+ for month in range(q, q+3):
+ cal = monthcalendar(year, month)
+ if len(cal) > height: height = len(cal)
+ data.append(cal)
+ for i in range(height):
+ for cal in data:
+ if i >= len(cal):
+ print ' '*20,
+ else:
+ prweek(cal[i], 2)
+ print spacing,
+ print
diff --git a/Lib/cmp.py b/Lib/cmp.py
new file mode 100644
index 0000000..434caee
--- /dev/null
+++ b/Lib/cmp.py
@@ -0,0 +1,61 @@
+# Module 'cmp'
+
+# Efficiently compare files, boolean outcome only (equal / not equal).
+
+# Tricks (used in this order):
+# - Files with identical type, size & mtime are assumed to be clones
+# - Files with different type or size cannot be identical
+# - We keep a cache of outcomes of earlier comparisons
+# - We don't fork a process to run 'cmp' but read the files ourselves
+
+import posix
+
+cache = {}
+
+def cmp(f1, f2): # Compare two files, use the cache if possible.
+ # Return 1 for identical files, 0 for different.
+ # Raise exceptions if either file could not be statted, read, etc.
+ s1, s2 = sig(posix.stat(f1)), sig(posix.stat(f2))
+ if s1[0] <> 8 or s2[0] <> 8:
+ # Either is a not a plain file -- always report as different
+ return 0
+ if s1 = s2:
+ # type, size & mtime match -- report same
+ return 1
+ if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother
+ # types or sizes differ -- report different
+ return 0
+ # same type and size -- look in the cache
+ key = f1 + ' ' + f2
+ try:
+ cs1, cs2, outcome = cache[key]
+ # cache hit
+ if s1 = cs1 and s2 = cs2:
+ # cached signatures match
+ return outcome
+ # stale cached signature(s)
+ except RuntimeError:
+ # cache miss
+ pass
+ # really compare
+ outcome = do_cmp(f1, f2)
+ cache[key] = s1, s2, outcome
+ return outcome
+
+def sig(st): # Return signature (i.e., type, size, mtime) from raw stat data
+ # 0-5: st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid
+ # 6-9: st_size, st_atime, st_mtime, st_ctime
+ type = st[0] / 4096
+ size = st[6]
+ mtime = st[8]
+ return type, size, mtime
+
+def do_cmp(f1, f2): # Compare two files, really
+ bufsize = 8096 # Could be tuned
+ fp1 = open(f1, 'r')
+ fp2 = open(f2, 'r')
+ while 1:
+ b1 = fp1.read(bufsize)
+ b2 = fp2.read(bufsize)
+ if b1 <> b2: return 0
+ if not b1: return 1
diff --git a/Lib/cmpcache.py b/Lib/cmpcache.py
new file mode 100644
index 0000000..a47a4fd
--- /dev/null
+++ b/Lib/cmpcache.py
@@ -0,0 +1,74 @@
+# Module 'cmpcache'
+#
+# Efficiently compare files, boolean outcome only (equal / not equal).
+#
+# Tricks (used in this order):
+# - Use the statcache module to avoid statting files more than once
+# - Files with identical type, size & mtime are assumed to be clones
+# - Files with different type or size cannot be identical
+# - We keep a cache of outcomes of earlier comparisons
+# - We don't fork a process to run 'cmp' but read the files ourselves
+#
+# XXX There is a dependency on constants in <sys/stat.h> here.
+
+import posix
+import statcache
+
+
+# The cache.
+#
+cache = {}
+
+
+# Compare two files, use the cache if possible.
+# May raise posix.error if a stat or open of either fails.
+#
+def cmp(f1, f2):
+ # Return 1 for identical files, 0 for different.
+ # Raise exceptions if either file could not be statted, read, etc.
+ s1, s2 = sig(statcache.stat(f1)), sig(statcache.stat(f2))
+ if s1[0] <> 8 or s2[0] <> 8: # XXX 8 is S_IFREG in <sys/stat.h>
+ # Either is a not a plain file -- always report as different
+ return 0
+ if s1 = s2:
+ # type, size & mtime match -- report same
+ return 1
+ if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother
+ # types or sizes differ -- report different
+ return 0
+ # same type and size -- look in the cache
+ key = f1 + ' ' + f2
+ if cache.has_key(key):
+ cs1, cs2, outcome = cache[key]
+ # cache hit
+ if s1 = cs1 and s2 = cs2:
+ # cached signatures match
+ return outcome
+ # stale cached signature(s)
+ # really compare
+ outcome = do_cmp(f1, f2)
+ cache[key] = s1, s2, outcome
+ return outcome
+
+# Return signature (i.e., type, size, mtime) from raw stat data.
+#
+def sig(st):
+ # 0-5: st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid
+ # 6-9: st_size, st_atime, st_mtime, st_ctime
+ type = st[0] / 4096 # XXX dependent on S_IFMT in <sys/stat.h>
+ size = st[6]
+ mtime = st[8]
+ return type, size, mtime
+
+# Compare two files, really.
+#
+def do_cmp(f1, f2):
+ #print ' cmp', f1, f2 # XXX remove when debugged
+ bufsize = 8096 # Could be tuned
+ fp1 = open(f1, 'r')
+ fp2 = open(f2, 'r')
+ while 1:
+ b1 = fp1.read(bufsize)
+ b2 = fp2.read(bufsize)
+ if b1 <> b2: return 0
+ if not b1: return 1
diff --git a/Lib/commands.py b/Lib/commands.py
new file mode 100644
index 0000000..145f5db
--- /dev/null
+++ b/Lib/commands.py
@@ -0,0 +1,73 @@
+# Module 'commands'
+#
+# Various tools for executing commands and looking at their output and status.
+
+import rand
+import posix
+import path
+
+
+# Get 'ls -l' status for an object into a string
+#
+def getstatus(file):
+ return getoutput('ls -ld' + mkarg(file))
+
+
+# Get the output from a shell command into a string.
+# The exit status is ignored; a trailing newline is stripped.
+# Assume the command will work with ' >tempfile 2>&1' appended.
+# XXX This should use posix.popen() instead, should it exist.
+#
+def getoutput(cmd):
+ return getstatusoutput(cmd)[1]
+
+
+# Ditto but preserving the exit status.
+# Returns a pair (sts, output)
+#
+def getstatusoutput(cmd):
+ tmp = '/usr/tmp/wdiff' + `rand.rand()`
+ sts = -1
+ try:
+ sts = posix.system(cmd + ' >' + tmp + ' 2>&1')
+ text = readfile(tmp)
+ finally:
+ altsts = posix.system('rm -f ' + tmp)
+ if text[-1:] = '\n': text = text[:-1]
+ return sts, text
+
+
+# Return a string containing a file's contents.
+#
+def readfile(fn):
+ fp = open(fn, 'r')
+ a = ''
+ n = 8096
+ while 1:
+ b = fp.read(n)
+ if not b: break
+ a = a + b
+ return a
+
+
+# Make command argument from directory and pathname (prefix space, add quotes).
+#
+def mk2arg(head, x):
+ return mkarg(path.cat(head, x))
+
+
+# Make a shell command argument from a string.
+# Two strategies: enclose in single quotes if it contains none;
+# otherwis, enclose in double quotes and prefix quotable characters
+# with backslash.
+#
+def mkarg(x):
+ if '\'' not in x:
+ return ' \'' + x + '\''
+ s = ' "'
+ for c in x:
+ if c in '\\$"':
+ s = s + '\\'
+ s = s + c
+ s = s + '"'
+ return s
diff --git a/Lib/dircache.py b/Lib/dircache.py
new file mode 100644
index 0000000..b40f76e
--- /dev/null
+++ b/Lib/dircache.py
@@ -0,0 +1,36 @@
+# Module 'dircache'
+#
+# Return a sorted list of the files in a POSIX directory, using a cache
+# to avoid reading the directory more often than necessary.
+# Also contains a subroutine to append slashes to directories.
+
+import posix
+import path
+
+cache = {}
+
+def listdir(path): # List directory contents, using cache
+ try:
+ cached_mtime, list = cache[path]
+ del cache[path]
+ except RuntimeError:
+ cached_mtime, list = -1, []
+ try:
+ mtime = posix.stat(path)[8]
+ except posix.error:
+ return []
+ if mtime <> cached_mtime:
+ try:
+ list = posix.listdir(path)
+ except posix.error:
+ return []
+ list.sort()
+ cache[path] = mtime, list
+ return list
+
+opendir = listdir # XXX backward compatibility
+
+def annotate(head, list): # Add '/' suffixes to directories
+ for i in range(len(list)):
+ if path.isdir(path.cat(head, list[i])):
+ list[i] = list[i] + '/'
diff --git a/Lib/dircmp.py b/Lib/dircmp.py
new file mode 100644
index 0000000..762a186
--- /dev/null
+++ b/Lib/dircmp.py
@@ -0,0 +1,215 @@
+# Module 'dirmp'
+#
+# Defines a class to build directory diff tools on.
+
+import posix
+
+import path
+
+import dircache
+import cmpcache
+import statcache
+
+
+# File type constants from <sys/stat.h>.
+#
+S_IFDIR = 4
+S_IFREG = 8
+
+# Extract the file type from a stat buffer.
+#
+def S_IFMT(st): return st[0] / 4096
+
+
+# Directory comparison class.
+#
+class dircmp():
+ #
+ def new(dd, (a, b)): # Initialize
+ dd.a = a
+ dd.b = b
+ # Properties that caller may change before callingdd. run():
+ dd.hide = ['.', '..'] # Names never to be shown
+ dd.ignore = ['RCS', 'tags'] # Names ignored in comparison
+ #
+ return dd
+ #
+ def run(dd): # Compare everything except common subdirectories
+ dd.a_list = filter(dircache.listdir(dd.a), dd.hide)
+ dd.b_list = filter(dircache.listdir(dd.b), dd.hide)
+ dd.a_list.sort()
+ dd.b_list.sort()
+ dd.phase1()
+ dd.phase2()
+ dd.phase3()
+ #
+ def phase1(dd): # Compute common names
+ dd.a_only = []
+ dd.common = []
+ for x in dd.a_list:
+ if x in dd.b_list:
+ dd.common.append(x)
+ else:
+ dd.a_only.append(x)
+ #
+ dd.b_only = []
+ for x in dd.b_list:
+ if x not in dd.common:
+ dd.b_only.append(x)
+ #
+ def phase2(dd): # Distinguish files, directories, funnies
+ dd.common_dirs = []
+ dd.common_files = []
+ dd.common_funny = []
+ #
+ for x in dd.common:
+ a_path = path.cat(dd.a, x)
+ b_path = path.cat(dd.b, x)
+ #
+ ok = 1
+ try:
+ a_stat = statcache.stat(a_path)
+ except posix.error, why:
+ # print 'Can\'t stat', a_path, ':', why[1]
+ ok = 0
+ try:
+ b_stat = statcache.stat(b_path)
+ except posix.error, why:
+ # print 'Can\'t stat', b_path, ':', why[1]
+ ok = 0
+ #
+ if ok:
+ a_type = S_IFMT(a_stat)
+ b_type = S_IFMT(b_stat)
+ if a_type <> b_type:
+ dd.common_funny.append(x)
+ elif a_type = S_IFDIR:
+ dd.common_dirs.append(x)
+ elif a_type = S_IFREG:
+ dd.common_files.append(x)
+ else:
+ dd.common_funny.append(x)
+ else:
+ dd.common_funny.append(x)
+ #
+ def phase3(dd): # Find out differences between common files
+ xx = cmpfiles(dd.a, dd.b, dd.common_files)
+ dd.same_files, dd.diff_files, dd.funny_files = xx
+ #
+ def phase4(dd): # Find out differences between common subdirectories
+ # A new dircmp object is created for each common subdirectory,
+ # these are stored in a dictionary indexed by filename.
+ # The hide and ignore properties are inherited from the parent
+ dd.subdirs = {}
+ for x in dd.common_dirs:
+ a_x = path.cat(dd.a, x)
+ b_x = path.cat(dd.b, x)
+ dd.subdirs[x] = newdd = dircmp().new(a_x, b_x)
+ newdd.hide = dd.hide
+ newdd.ignore = dd.ignore
+ newdd.run()
+ #
+ def phase4_closure(dd): # Recursively call phase4() on subdirectories
+ dd.phase4()
+ for x in dd.subdirs.keys():
+ dd.subdirs[x].phase4_closure()
+ #
+ def report(dd): # Print a report on the differences between a and b
+ # Assume that phases 1 to 3 have been executed
+ # Output format is purposely lousy
+ print 'diff', dd.a, dd.b
+ if dd.a_only:
+ print 'Only in', dd.a, ':', dd.a_only
+ if dd.b_only:
+ print 'Only in', dd.b, ':', dd.b_only
+ if dd.same_files:
+ print 'Identical files :', dd.same_files
+ if dd.diff_files:
+ print 'Differing files :', dd.diff_files
+ if dd.funny_files:
+ print 'Trouble with common files :', dd.funny_files
+ if dd.common_dirs:
+ print 'Common subdirectories :', dd.common_dirs
+ if dd.common_funny:
+ print 'Common funny cases :', dd.common_funny
+ #
+ def report_closure(dd): # Print reports on dd and on subdirs
+ # If phase 4 hasn't been done, no subdir reports are printed
+ dd.report()
+ try:
+ x = dd.subdirs
+ except NameError:
+ return # No subdirectories computed
+ for x in dd.subdirs.keys():
+ print
+ dd.subdirs[x].report_closure()
+ #
+ def report_phase4_closure(dd): # Report and do phase 4 recursively
+ dd.report()
+ dd.phase4()
+ for x in dd.subdirs.keys():
+ print
+ dd.subdirs[x].report_phase4_closure()
+
+
+# Compare common files in two directories.
+# Return:
+# - files that compare equal
+# - files that compare different
+# - funny cases (can't stat etc.)
+#
+def cmpfiles(a, b, common):
+ res = ([], [], [])
+ for x in common:
+ res[cmp(path.cat(a, x), path.cat(b, x))].append(x)
+ return res
+
+
+# Compare two files.
+# Return:
+# 0 for equal
+# 1 for different
+# 2 for funny cases (can't stat, etc.)
+#
+def cmp(a, b):
+ try:
+ if cmpcache.cmp(a, b): return 0
+ return 1
+ except posix.error:
+ return 2
+
+
+# Remove a list item.
+# NB: This modifies the list argument.
+#
+def remove(list, item):
+ for i in range(len(list)):
+ if list[i] = item:
+ del list[i]
+ break
+
+
+# Return a copy with items that occur in skip removed.
+#
+def filter(list, skip):
+ result = []
+ for item in list:
+ if item not in skip: result.append(item)
+ return result
+
+
+# Demonstration and testing.
+#
+def demo():
+ import sys
+ import getopt
+ options, args = getopt.getopt(sys.argv[1:], 'r')
+ if len(args) <> 2: raise getopt.error, 'need exactly two args'
+ dd = dircmp().new(args[0], args[1])
+ dd.run()
+ if ('-r', '') in options:
+ dd.report_phase4_closure()
+ else:
+ dd.report()
+
+# demo()
diff --git a/Lib/dump.py b/Lib/dump.py
new file mode 100644
index 0000000..cecc275
--- /dev/null
+++ b/Lib/dump.py
@@ -0,0 +1,63 @@
+# Module 'dump'
+#
+# Print python code that reconstructs a variable.
+# This only works in certain cases.
+#
+# It works fine for:
+# - ints and floats (except NaNs and other weird things)
+# - strings
+# - compounds and lists, provided it works for all their elements
+# - imported modules, provided their name is the module name
+#
+# It works for top-level dictionaries but not for dictionaries
+# contained in other objects (could be made to work with some hassle
+# though).
+#
+# It does not work for functions (all sorts), classes, class objects,
+# windows, files etc.
+#
+# Finally, objects referenced by more than one name or contained in more
+# than one other object lose their sharing property (this is bad for
+# strings used as exception identifiers, for instance).
+
+# Dump a whole symbol table
+#
+def dumpsymtab(dict):
+ for key in dict.keys():
+ dumpvar(key, dict[key])
+
+# Dump a single variable
+#
+def dumpvar(name, x):
+ import sys
+ t = type(x)
+ if t = type({}):
+ print name, '= {}'
+ for key in x.keys():
+ item = x[key]
+ if not printable(item):
+ print '#',
+ print name, '[', `key`, '] =', `item`
+ elif t in (type(''), type(0), type(0.0), type([]), type(())):
+ if not printable(x):
+ print '#',
+ print name, '=', `x`
+ elif t = type(sys):
+ print 'import', name, '#', x
+ else:
+ print '#', name, '=', x
+
+# check if a value is printable in a way that can be read back with input()
+#
+def printable(x):
+ t = type(x)
+ if t in (type(''), type(0), type(0.0)):
+ return 1
+ if t in (type([]), type(())):
+ for item in x:
+ if not printable(item):
+ return 0
+ return 1
+ if x = {}:
+ return 1
+ return 0
diff --git a/Lib/getopt.py b/Lib/getopt.py
new file mode 100644
index 0000000..ef72fbc
--- /dev/null
+++ b/Lib/getopt.py
@@ -0,0 +1,47 @@
+# module getopt -- Standard command line processing.
+
+# Function getopt.getopt() has a different interface but provides the
+# same functionality as the Unix getopt() function.
+
+# It has two arguments: the first should be argv[1:] (it doesn't want
+# the script name), the second the string of option letters as passed
+# to Unix getopt() (i.e., a string of allowable option letters, with
+# options requiring an argument followed by a colon).
+
+# It raises the exception getopt.error with a string argument if it
+# detects an error.
+
+# It returns two items:
+# (1) a list of pairs (option, option_argument) giving the options in
+# the order in which they were specified. (I'd use a dictionary
+# but applications may depend on option order or multiple
+# occurrences.) Boolean options have '' as option_argument.
+# (2) the list of remaining arguments (may be empty).
+
+error = 'getopt error'
+
+def getopt(args, options):
+ list = []
+ while args and args[0][0] = '-' and args[0] <> '-':
+ if args[0] = '--':
+ args = args[1:]
+ break
+ optstring, args = args[0][1:], args[1:]
+ while optstring <> '':
+ opt, optstring = optstring[0], optstring[1:]
+ if classify(opt, options): # May raise exception as well
+ if optstring = '':
+ if not args:
+ raise error, 'option -' + opt + ' requires argument'
+ optstring, args = args[0], args[1:]
+ optarg, optstring = optstring, ''
+ else:
+ optarg = ''
+ list.append('-' + opt, optarg)
+ return list, args
+
+def classify(opt, options): # Helper to check type of option
+ for i in range(len(options)):
+ if opt = options[i] <> ':':
+ return options[i+1:i+2] = ':'
+ raise error, 'option -' + opt + ' not recognized'
diff --git a/Lib/irix5/DEVICE.py b/Lib/irix5/DEVICE.py
new file mode 100755
index 0000000..00eddfc
--- /dev/null
+++ b/Lib/irix5/DEVICE.py
@@ -0,0 +1,423 @@
+#/**************************************************************************
+# * *
+# * Copyright (C) 1984, Silicon Graphics, Inc. *
+# * *
+# * These coded instructions, statements, and computer programs contain *
+# * unpublished proprietary information of Silicon Graphics, Inc., and *
+# * are protected by Federal copyright law. They may not be disclosed *
+# * to third parties or copied or duplicated in any form, in whole or *
+# * in part, without the prior written consent of Silicon Graphics, Inc. *
+# * *
+# **************************************************************************/
+#/* file with device definitions (see /usr/include/device.h) */
+
+NULLDEV = 0
+BUTOFFSET = 1
+VALOFFSET = 256
+TIMOFFSET = 515
+XKBDOFFSET = 143
+INOFFSET = 1024
+OUTOFFSET = 1033
+BUTCOUNT = 190
+VALCOUNT = 27
+TIMCOUNT = 4
+XKBDCOUNT = 28
+INCOUNT = 8
+OUTCOUNT = 8
+#
+#
+#
+#
+BUT0 = 1
+BUT1 = 2
+BUT2 = 3
+BUT3 = 4
+BUT4 = 5
+BUT5 = 6
+BUT6 = 7
+BUT7 = 8
+BUT8 = 9
+BUT9 = 10
+BUT10 = 11
+BUT11 = 12
+BUT12 = 13
+BUT13 = 14
+BUT14 = 15
+BUT15 = 16
+BUT16 = 17
+BUT17 = 18
+BUT18 = 19
+BUT19 = 20
+BUT20 = 21
+BUT21 = 22
+BUT22 = 23
+BUT23 = 24
+BUT24 = 25
+BUT25 = 26
+BUT26 = 27
+BUT27 = 28
+BUT28 = 29
+BUT29 = 30
+BUT30 = 31
+BUT31 = 32
+BUT32 = 33
+BUT33 = 34
+BUT34 = 35
+BUT35 = 36
+BUT36 = 37
+BUT37 = 38
+BUT38 = 39
+BUT39 = 40
+BUT40 = 41
+BUT41 = 42
+BUT42 = 43
+BUT43 = 44
+BUT44 = 45
+BUT45 = 46
+BUT46 = 47
+BUT47 = 48
+BUT48 = 49
+BUT49 = 50
+BUT50 = 51
+BUT51 = 52
+BUT52 = 53
+BUT53 = 54
+BUT54 = 55
+BUT55 = 56
+BUT56 = 57
+BUT57 = 58
+BUT58 = 59
+BUT59 = 60
+BUT60 = 61
+BUT61 = 62
+BUT62 = 63
+BUT63 = 64
+BUT64 = 65
+BUT65 = 66
+BUT66 = 67
+BUT67 = 68
+BUT68 = 69
+BUT69 = 70
+BUT70 = 71
+BUT71 = 72
+BUT72 = 73
+BUT73 = 74
+BUT74 = 75
+BUT75 = 76
+BUT76 = 77
+BUT77 = 78
+BUT78 = 79
+BUT79 = 80
+BUT80 = 81
+BUT81 = 82
+BUT82 = 83
+MAXKBDBUT = 83
+BUT100 = 101
+BUT101 = 102
+BUT102 = 103
+BUT110 = 111
+BUT111 = 112
+BUT112 = 113
+BUT113 = 114
+BUT114 = 115
+BUT115 = 116
+BUT116 = 117
+BUT117 = 118
+BUT118 = 119
+BUT119 = 120
+BUT120 = 121
+BUT121 = 122
+BUT122 = 123
+BUT123 = 124
+BUT124 = 125
+BUT125 = 126
+BUT126 = 127
+BUT127 = 128
+BUT128 = 129
+BUT129 = 130
+BUT130 = 131
+BUT131 = 132
+BUT132 = 133
+BUT133 = 134
+BUT134 = 135
+BUT135 = 136
+BUT136 = 137
+BUT137 = 138
+BUT138 = 139
+BUT139 = 140
+BUT140 = 141
+BUT141 = 142
+BUT142 = 143
+BUT143 = 144
+BUT144 = 145
+BUT145 = 146
+BUT146 = 147
+BUT147 = 148
+BUT148 = 149
+BUT149 = 150
+BUT150 = 151
+BUT151 = 152
+BUT152 = 153
+BUT153 = 154
+BUT154 = 155
+BUT155 = 156
+BUT156 = 157
+BUT157 = 158
+BUT158 = 159
+BUT159 = 160
+BUT160 = 161
+BUT161 = 162
+BUT162 = 163
+BUT163 = 164
+BUT164 = 165
+BUT165 = 166
+BUT166 = 167
+BUT167 = 168
+BUT168 = 169
+BUT181 = 182
+BUT182 = 183
+BUT183 = 184
+BUT184 = 185
+BUT185 = 186
+BUT186 = 187
+BUT187 = 188
+BUT188 = 189
+BUT189 = 190
+MOUSE1 = 101
+MOUSE2 = 102
+MOUSE3 = 103
+LEFTMOUSE = 103
+MIDDLEMOUSE = 102
+RIGHTMOUSE = 101
+LPENBUT = 104
+BPAD0 = 105
+BPAD1 = 106
+BPAD2 = 107
+BPAD3 = 108
+LPENVALID = 109
+SWBASE = 111
+SW0 = 111
+SW1 = 112
+SW2 = 113
+SW3 = 114
+SW4 = 115
+SW5 = 116
+SW6 = 117
+SW7 = 118
+SW8 = 119
+SW9 = 120
+SW10 = 121
+SW11 = 122
+SW12 = 123
+SW13 = 124
+SW14 = 125
+SW15 = 126
+SW16 = 127
+SW17 = 128
+SW18 = 129
+SW19 = 130
+SW20 = 131
+SW21 = 132
+SW22 = 133
+SW23 = 134
+SW24 = 135
+SW25 = 136
+SW26 = 137
+SW27 = 138
+SW28 = 139
+SW29 = 140
+SW30 = 141
+SW31 = 142
+SBBASE = 182
+SBPICK = 182
+SBBUT1 = 183
+SBBUT2 = 184
+SBBUT3 = 185
+SBBUT4 = 186
+SBBUT5 = 187
+SBBUT6 = 188
+SBBUT7 = 189
+SBBUT8 = 190
+AKEY = 11
+BKEY = 36
+CKEY = 28
+DKEY = 18
+EKEY = 17
+FKEY = 19
+GKEY = 26
+HKEY = 27
+IKEY = 40
+JKEY = 34
+KKEY = 35
+LKEY = 42
+MKEY = 44
+NKEY = 37
+OKEY = 41
+PKEY = 48
+QKEY = 10
+RKEY = 24
+SKEY = 12
+TKEY = 25
+UKEY = 33
+VKEY = 29
+WKEY = 16
+XKEY = 21
+YKEY = 32
+ZKEY = 20
+ZEROKEY = 46
+ONEKEY = 8
+TWOKEY = 14
+THREEKEY = 15
+FOURKEY = 22
+FIVEKEY = 23
+SIXKEY = 30
+SEVENKEY = 31
+EIGHTKEY = 38
+NINEKEY = 39
+BREAKKEY = 1
+SETUPKEY = 2
+CTRLKEY = 3
+LEFTCTRLKEY = CTRLKEY
+CAPSLOCKKEY = 4
+RIGHTSHIFTKEY = 5
+LEFTSHIFTKEY = 6
+NOSCRLKEY = 13
+ESCKEY = 7
+TABKEY = 9
+RETKEY = 51
+SPACEKEY = 83
+LINEFEEDKEY = 60
+BACKSPACEKEY = 61
+DELKEY = 62
+SEMICOLONKEY = 43
+PERIODKEY = 52
+COMMAKEY = 45
+QUOTEKEY = 50
+ACCENTGRAVEKEY = 55
+MINUSKEY = 47
+VIRGULEKEY = 53
+BACKSLASHKEY = 57
+EQUALKEY = 54
+LEFTBRACKETKEY = 49
+RIGHTBRACKETKEY = 56
+LEFTARROWKEY = 73
+DOWNARROWKEY = 74
+RIGHTARROWKEY = 80
+UPARROWKEY = 81
+PAD0 = 59
+PAD1 = 58
+PAD2 = 64
+PAD3 = 65
+PAD4 = 63
+PAD5 = 69
+PAD6 = 70
+PAD7 = 67
+PAD8 = 68
+PAD9 = 75
+PADPF1 = 72
+PADPF2 = 71
+PADPF3 = 79
+PADPF4 = 78
+PADPERIOD = 66
+PADMINUS = 76
+PADCOMMA = 77
+PADENTER = 82
+LEFTALTKEY = 143
+RIGHTALTKEY = 144
+RIGHTCTRLKEY = 145
+F1KEY = 146
+F2KEY = 147
+F3KEY = 148
+F4KEY = 149
+F5KEY = 150
+F6KEY = 151
+F7KEY = 152
+F8KEY = 153
+F9KEY = 154
+F10KEY = 155
+F11KEY = 156
+F12KEY = 157
+PRINTSCREENKEY = 158
+SCROLLLOCKKEY = 159
+PAUSEKEY = 160
+INSERTKEY = 161
+HOMEKEY = 162
+PAGEUPKEY = 163
+ENDKEY = 164
+PAGEDOWNKEY = 165
+NUMLOCKKEY = 166
+PADVIRGULEKEY = 167
+PADASTERKEY = 168
+PADPLUSKEY = 169
+SGIRESERVED = 256
+DIAL0 = 257
+DIAL1 = 258
+DIAL2 = 259
+DIAL3 = 260
+DIAL4 = 261
+DIAL5 = 262
+DIAL6 = 263
+DIAL7 = 264
+DIAL8 = 265
+MOUSEX = 266
+MOUSEY = 267
+LPENX = 268
+LPENY = 269
+BPADX = 270
+BPADY = 271
+CURSORX = 272
+CURSORY = 273
+GHOSTX = 274
+GHOSTY = 275
+SBTX = 276
+SBTY = 277
+SBTZ = 278
+SBRX = 279
+SBRY = 280
+SBRZ = 281
+SBPERIOD = 282
+TIMER0 = 515
+TIMER1 = 516
+TIMER2 = 517
+TIMER3 = 518
+KEYBD = 513
+RAWKEYBD = 514
+VALMARK = 523
+GERROR = 524
+REDRAW = 528
+WMSEND = 529
+WMREPLY = 530
+WMGFCLOSE = 531
+WMTXCLOSE = 532
+MODECHANGE = 533
+INPUTCHANGE = 534
+QFULL = 535
+PIECECHANGE = 536
+WINCLOSE = 537
+QREADERROR = 538
+WINFREEZE = 539
+WINTHAW = 540
+REDRAWICONIC = 541
+WINQUIT = 542
+DEPTHCHANGE = 543
+KEYBDFNAMES = 544
+KEYBDFSTRINGS = 545
+WINSHUT = 546
+INPUT0 = 1024
+INPUT1 = 1025
+INPUT2 = 1026
+INPUT3 = 1027
+INPUT4 = 1028
+INPUT5 = 1029
+INPUT6 = 1030
+INPUT7 = 1032
+OUTPUT0 = 1033
+OUTPUT1 = 1034
+OUTPUT2 = 1035
+OUTPUT3 = 1036
+OUTPUT4 = 1037
+OUTPUT5 = 1038
+OUTPUT6 = 1039
+OUTPUT7 = 1040
+MAXSGIDEVICE = 20000
+MENUBUTTON = RIGHTMOUSE
diff --git a/Lib/irix5/GL.py b/Lib/irix5/GL.py
new file mode 100755
index 0000000..35487a7
--- /dev/null
+++ b/Lib/irix5/GL.py
@@ -0,0 +1,365 @@
+# Constants defined in <gl.h>
+
+#**************************************************************************
+#* *
+#* Copyright (C) 1984, Silicon Graphics, Inc. *
+#* *
+#* These coded instructions, statements, and computer programs contain *
+#* unpublished proprietary information of Silicon Graphics, Inc., and *
+#* are protected by Federal copyright law. They may not be disclosed *
+#* to third parties or copied or duplicated in any form, in whole or *
+#* in part, without the prior written consent of Silicon Graphics, Inc. *
+#* *
+#**************************************************************************
+
+# Graphics Libary constants
+
+# Booleans
+TRUE = 1
+FALSE = 0
+
+# maximum X and Y screen coordinates
+XMAXSCREEN = 1279
+YMAXSCREEN = 1023
+XMAXMEDIUM = 1023 # max for medium res monitor
+YMAXMEDIUM = 767
+XMAX170 = 645 # max for RS-170
+YMAX170 = 484
+XMAXPAL = 779 # max for PAL
+YMAXPAL = 574
+
+# various hardware/software limits
+ATTRIBSTACKDEPTH = 10
+VPSTACKDEPTH = 8
+MATRIXSTACKDEPTH = 32
+NAMESTACKDEPTH = 1025
+STARTTAG = -2
+ENDTAG = -3
+CPOSX_INVALID = -(2*XMAXSCREEN)
+
+# names for colors in color map loaded by greset
+BLACK = 0
+RED = 1
+GREEN = 2
+YELLOW = 3
+BLUE = 4
+MAGENTA = 5
+CYAN = 6
+WHITE = 7
+
+# popup colors
+PUP_CLEAR = 0
+PUP_COLOR = 1
+PUP_BLACK = 2
+PUP_WHITE = 3
+
+# defines for drawmode
+NORMALDRAW = 0
+PUPDRAW = 1
+OVERDRAW = 2
+UNDERDRAW = 3
+CURSORDRAW = 4
+
+# defines for defpattern
+PATTERN_16 = 16
+PATTERN_32 = 32
+PATTERN_64 = 64
+
+PATTERN_16_SIZE = 16
+PATTERN_32_SIZE = 64
+PATTERN_64_SIZE = 256
+
+# defines for readsource
+SRC_AUTO = 0
+SRC_FRONT = 1
+SRC_BACK = 2
+SRC_ZBUFFER = 3
+SRC_PUP = 4
+SRC_OVER = 5
+SRC_UNDER = 6
+SRC_FRAMEGRABBER = 7
+
+# defines for blendfunction
+BF_ZERO = 0
+BF_ONE = 1
+BF_DC = 2
+BF_SC = 2
+BF_MDC = 3
+BF_MSC = 3
+BF_SA = 4
+BF_MSA = 5
+BF_DA = 6
+BF_MDA = 7
+
+# defines for zfunction
+ZF_NEVER = 0
+ZF_LESS = 1
+ZF_EQUAL = 2
+ZF_LEQUAL = 3
+ZF_GREATER = 4
+ZF_NOTEQUAL = 5
+ZF_GEQUAL = 6
+ZF_ALWAYS = 7
+
+# defines for zsource
+ZSRC_DEPTH = 0
+ZSRC_COLOR = 1
+
+# defines for pntsmooth
+SMP_OFF = 0
+SMP_ON = 1
+
+# defines for linesmooth
+SML_OFF = 0
+SML_ON = 1
+
+# defines for setpup
+PUP_NONE = 0
+PUP_GREY = 1
+
+# defines for glcompat
+GLC_OLDPOLYGON = 0
+GLC_ZRANGEMAP = 1
+
+# defines for curstype
+C16X1 = 0
+C16X2 = 1
+C32X1 = 2
+C32X2 = 3
+CCROSS = 4
+
+# defines for shademodel
+FLAT = 0
+GOURAUD = 1
+
+# defines for logicop
+### LO_ZERO = 0x0
+### LO_AND = 0x1
+### LO_ANDR = 0x2
+### LO_SRC = 0x3
+### LO_ANDI = 0x4
+### LO_DST = 0x5
+### LO_XOR = 0x6
+### LO_OR = 0x7
+### LO_NOR = 0x8
+### LO_XNOR = 0x9
+### LO_NDST = 0xa
+### LO_ORR = 0xb
+### LO_NSRC = 0xc
+### LO_ORI = 0xd
+### LO_NAND = 0xe
+### LO_ONE = 0xf
+
+
+#
+# START defines for getgdesc
+#
+
+GD_XPMAX = 0
+GD_YPMAX = 1
+GD_XMMAX = 2
+GD_YMMAX = 3
+GD_ZMIN = 4
+GD_ZMAX = 5
+GD_BITS_NORM_SNG_RED = 6
+GD_BITS_NORM_SNG_GREEN = 7
+GD_BITS_NORM_SNG_BLUE = 8
+GD_BITS_NORM_DBL_RED = 9
+GD_BITS_NORM_DBL_GREEN = 10
+GD_BITS_NORM_DBL_BLUE = 11
+GD_BITS_NORM_SNG_CMODE = 12
+GD_BITS_NORM_DBL_CMODE = 13
+GD_BITS_NORM_SNG_MMAP = 14
+GD_BITS_NORM_DBL_MMAP = 15
+GD_BITS_NORM_ZBUFFER = 16
+GD_BITS_OVER_SNG_CMODE = 17
+GD_BITS_UNDR_SNG_CMODE = 18
+GD_BITS_PUP_SNG_CMODE = 19
+GD_BITS_NORM_SNG_ALPHA = 21
+GD_BITS_NORM_DBL_ALPHA = 22
+GD_BITS_CURSOR = 23
+GD_OVERUNDER_SHARED = 24
+GD_BLEND = 25
+GD_CIFRACT = 26
+GD_CROSSHAIR_CINDEX = 27
+GD_DITHER = 28
+GD_LINESMOOTH_CMODE = 30
+GD_LINESMOOTH_RGB = 31
+GD_LOGICOP = 33
+GD_NSCRNS = 35
+GD_NURBS_ORDER = 36
+GD_NBLINKS = 37
+GD_NVERTEX_POLY = 39
+GD_PATSIZE_64 = 40
+GD_PNTSMOOTH_CMODE = 41
+GD_PNTSMOOTH_RGB = 42
+GD_PUP_TO_OVERUNDER = 43
+GD_READSOURCE = 44
+GD_READSOURCE_ZBUFFER = 48
+GD_STEREO = 50
+GD_SUBPIXEL_LINE = 51
+GD_SUBPIXEL_PNT = 52
+GD_SUBPIXEL_POLY = 53
+GD_TRIMCURVE_ORDER = 54
+GD_WSYS = 55
+GD_ZDRAW_GEOM = 57
+GD_ZDRAW_PIXELS = 58
+GD_SCRNTYPE = 61
+GD_TEXTPORT = 62
+GD_NMMAPS = 63
+GD_FRAMEGRABBER = 64
+GD_TIMERHZ = 66
+GD_DBBOX = 67
+GD_AFUNCTION = 68
+GD_ALPHA_OVERUNDER = 69
+GD_BITS_ACBUF = 70
+GD_BITS_ACBUF_HW = 71
+GD_BITS_STENCIL = 72
+GD_CLIPPLANES = 73
+GD_FOGVERTEX = 74
+GD_LIGHTING_TWOSIDE = 76
+GD_POLYMODE = 77
+GD_POLYSMOOTH = 78
+GD_SCRBOX = 79
+GD_TEXTURE = 80
+
+# return value for inquiries when there is no limit
+GD_NOLIMIT = 2
+
+# return values for GD_WSYS
+GD_WSYS_NONE = 0
+GD_WSYS_4S = 1
+
+# return values for GD_SCRNTYPE
+GD_SCRNTYPE_WM = 0
+GD_SCRNTYPE_NOWM = 1
+
+#
+# END defines for getgdesc
+#
+
+
+#
+# START NURBS interface definitions
+#
+
+# NURBS Rendering Properties
+N_PIXEL_TOLERANCE = 1
+N_CULLING = 2
+N_DISPLAY = 3
+N_ERRORCHECKING = 4
+N_SUBDIVISIONS = 5
+N_S_STEPS = 6
+N_T_STEPS = 7
+N_TILES = 8
+
+N_SHADED = 1.0
+
+# ---------------------------------------------------------------------------
+# FLAGS FOR NURBS SURFACES AND CURVES
+#
+# Bit: 9876 5432 1 0
+# |tttt|nnnn|f|r| : r - 1 bit = 1 if rational coordinate exists
+# : f - 1 bit = 1 if rational coordinate is before rest
+# : = 0 if rational coordinate is after rest
+# : nnnn - 4 bits for number of coordinates
+# : tttt - 4 bits for type of data (color, position, etc.)
+#
+# NURBS data type
+# N_T_ST 0 parametric space data
+# N_T_XYZ 1 model space data
+#
+# rational or non-rational data and position in memory
+# N_NONRATIONAL 0 non-rational data
+# N_RATAFTER 1 rational data with rat coord after rest
+# N_RATBEFORE 3 rational data with rat coord before rest
+#
+# N_MKFLAG(a,b,c) ((a<<6) | (b<<2) | c)
+#
+# ---------------------------------------------------------------------------
+#
+N_ST = 0x8 # N_MKFLAG( N_T_ST, 2, N_NONRATIONAL )
+N_STW = 0xd # N_MKFLAG( N_T_ST, 3, N_RATAFTER )
+N_WST = 0xf # N_MKFLAG( N_T_ST, 3, N_RATBEFORE )
+N_XYZ = 0x4c # N_MKFLAG( N_T_XYZ, 3, N_NONRATIONAL )
+N_XYZW = 0x51 # N_MKFLAG( N_T_XYZ, 4, N_RATAFTER )
+N_WXYZ = 0x53 # N_MKFLAG( N_T_XYZ, 4, N_RATBEFORE )
+
+#
+# END NURBS interface definitions
+#
+
+
+#
+# START lighting model defines
+#
+
+LMNULL = 0.0
+
+# MATRIX modes
+MSINGLE = 0
+MPROJECTION = 1
+MVIEWING = 2
+
+# LIGHT constants
+MAXLIGHTS = 8
+MAXRESTRICTIONS = 4
+
+# MATERIAL properties
+DEFMATERIAL = 0
+EMISSION = 1
+AMBIENT = 2
+DIFFUSE = 3
+SPECULAR = 4
+SHININESS = 5
+COLORINDEXES = 6
+ALPHA = 7
+
+# LIGHT properties
+DEFLIGHT = 100
+LCOLOR = 101
+POSITION = 102
+
+# LIGHTINGMODEL properties
+DEFLMODEL = 200
+LOCALVIEWER = 201
+ATTENUATION = 202
+
+# TARGET constants
+MATERIAL = 1000
+LIGHT0 = 1100
+LIGHT1 = 1101
+LIGHT2 = 1102
+LIGHT3 = 1103
+LIGHT4 = 1104
+LIGHT5 = 1105
+LIGHT6 = 1106
+LIGHT7 = 1107
+LMODEL = 1200
+
+# lmcolor modes
+LMC_COLOR = 0
+LMC_EMISSION = 1
+LMC_AMBIENT = 2
+LMC_DIFFUSE = 3
+LMC_SPECULAR = 4
+LMC_AD = 5
+LMC_NULL = 6
+
+#
+# END lighting model defines
+#
+
+
+#
+# START distributed graphics library defines
+#
+
+DGLSINK = 0 # sink connection
+DGLLOCAL = 1 # local connection
+DGLTSOCKET = 2 # tcp socket connection
+DGL4DDN = 3 # 4DDN (DECnet)
+
+#
+# END distributed graphics library defines
+#
diff --git a/Lib/irix5/auds.py b/Lib/irix5/auds.py
new file mode 100755
index 0000000..549c0a7
--- /dev/null
+++ b/Lib/irix5/auds.py
@@ -0,0 +1,106 @@
+import audio
+
+RATE = 8192
+
+# Initialize the audio stuff
+audio.setrate(3)
+audio.setoutgain(100) # for speaker
+
+play = audio.write
+
+def samp(n):
+ savegain = audio.getoutgain()
+ try:
+ audio.setoutgain(0)
+ x = raw_input('Hit Enter to sample ' + `n` + ' seconds: ')
+ return audio.read(n*RATE)
+ finally:
+ audio.setoutgain(savegain)
+
+def echo(s, delay, gain):
+ return s[:delay] + audio.add(s[delay:], audio.amplify(s, gain, gain))
+
+def save(s, file):
+ f = open(file, 'w')
+ f.write(s)
+
+def load(file):
+ return loadfp(open(file, 'r'))
+
+def loadfp(fp):
+ s = ''
+ while 1:
+ buf = fp.read(16*1024)
+ if not buf: break
+ s = s + buf
+ return s
+
+def unbias(s):
+ if not s: return s
+ a = audio.chr2num(s)
+ sum = 0
+ for i in a: sum = sum + i
+ bias = (sum + len(a)/2) / len(a)
+ print 'Bias value:', bias
+ if bias:
+ for i in range(len(a)):
+ a[i] = a[i] - bias
+ s = audio.num2chr(a)
+ return s
+
+# Stretch by a/b.
+# Think of this as converting the sampling rate from a samples/sec
+# to b samples/sec. Or, if the input is a bytes long, the output
+# will be b bytes long.
+#
+def stretch(s, a, b):
+ y = audio.chr2num(s)
+ m = len(y)
+ out = []
+ n = m * b / a
+ # i, j will walk through y and out (step 1)
+ # ib, ja are i*b, j*a and are kept as close together as possible
+ i, ib = 0, 0
+ j, ja = 0, 0
+ for j in range(n):
+ ja = ja+a
+ while ib < ja:
+ i = i+1
+ ib = ib+b
+ if i >= m:
+ break
+ if ib = ja:
+ out.append(y[i])
+ else:
+ out.append((y[i]*(ja-(ib-b)) + y[i-1]*(ib-ja)) / b)
+ return audio.num2chr(out)
+
+def sinus(freq): # return a 1-second sine wave
+ from math import sin, pi
+ factor = 2.0*pi*float(freq)/float(RATE)
+ list = range(RATE)
+ for i in list:
+ list[i] = int(sin(float(i) * factor) * 127.0)
+ return audio.num2chr(list)
+
+def softclip(s):
+ if '\177' not in s and '\200' not in s:
+ return s
+ num = audio.chr2num(s)
+ extremes = (-128, 127)
+ for i in range(1, len(num)-1):
+ if num[i] in extremes:
+ num[i] = (num[i-1] + num[i+1]) / 2
+ return audio.num2chr(num)
+
+def demo():
+ gday = load('gday')[1000:6000]
+ save(gday, 'gday0')
+ gg = [gday]
+ for i in range(1, 10):
+ for g in gg: play(g)
+ g = stretch(gday, 10, 10-i)
+ save(g, 'gday' + `i`)
+ gg.append(g)
+ while 1:
+ for g in gg: play(g)
diff --git a/Lib/irix5/panel.py b/Lib/irix5/panel.py
new file mode 100755
index 0000000..eb11508
--- /dev/null
+++ b/Lib/irix5/panel.py
@@ -0,0 +1,281 @@
+# Module 'panel'
+#
+# Support for the Panel library.
+# Uses built-in module 'pnl'.
+# Applciations should use 'panel.function' instead of 'pnl.function';
+# most 'pnl' functions are transparently exported by 'panel',
+# but dopanel() is overridden and you have to use this version
+# if you want to use callbacks.
+
+
+import pnl
+
+
+debug = 0
+
+
+# Test if an object is a list.
+#
+def is_list(x):
+ return type(x) = type([])
+
+
+# Reverse a list.
+#
+def reverse(list):
+ res = []
+ for item in list:
+ res.insert(0, item)
+ return res
+
+
+# Get an attribute of a list, which may itself be another list.
+# Don't use 'prop' for name.
+#
+def getattrlist(list, name):
+ for item in list:
+ if item and is_list(item) and item[0] = name:
+ return item[1:]
+ return []
+
+
+# Get a property of a list, which may itself be another list.
+#
+def getproplist(list, name):
+ for item in list:
+ if item and is_list(item) and item[0] = 'prop':
+ if len(item) > 1 and item[1] = name:
+ return item[2:]
+ return []
+
+
+# Test if an actuator description contains the property 'end-of-group'
+#
+def is_endgroup(list):
+ x = getproplist(list, 'end-of-group')
+ return (x and x[0] = '#t')
+
+
+# Neatly display an actuator definition given as S-expression
+# the prefix string is printed before each line.
+#
+def show_actuator(prefix, a):
+ for item in a:
+ if not is_list(item):
+ print prefix, item
+ elif item and item[0] = 'al':
+ print prefix, 'Subactuator list:'
+ for a in item[1:]:
+ show_actuator(prefix + ' ', a)
+ elif len(item) = 2:
+ print prefix, item[0], '=>', item[1]
+ elif len(item) = 3 and item[0] = 'prop':
+ print prefix, 'Prop', item[1], '=>',
+ print item[2]
+ else:
+ print prefix, '?', item
+
+
+# Neatly display a panel.
+#
+def show_panel(prefix, p):
+ for item in p:
+ if not is_list(item):
+ print prefix, item
+ elif item and item[0] = 'al':
+ print prefix, 'Actuator list:'
+ for a in item[1:]:
+ show_actuator(prefix + ' ', a)
+ elif len(item) = 2:
+ print prefix, item[0], '=>', item[1]
+ elif len(item) = 3 and item[0] = 'prop':
+ print prefix, 'Prop', item[1], '=>',
+ print item[2]
+ else:
+ print prefix, '?', item
+
+
+# Exception raised by build_actuator or build_panel.
+#
+panel_error = 'panel error'
+
+
+# Dummy callback used to initialize the callbacks.
+#
+def dummy_callback(arg):
+ pass
+
+
+# Assign attributes to members of the target.
+# Attribute names in exclist are ignored.
+# The member name is the attribute name prefixed with the prefix.
+#
+def assign_members(target, attrlist, exclist, prefix):
+ for item in attrlist:
+ if is_list(item) and len(item) = 2 and item[0] not in exclist:
+ name, value = item[0], item[1]
+ ok = 1
+ if value[0] in '-0123456789':
+ value = eval(value)
+ elif value[0] = '"':
+ value = value[1:-1]
+ elif value = 'move-then-resize':
+ # Strange default set by Panel Editor...
+ ok = 0
+ else:
+ print 'unknown value', value, 'for', name
+ ok = 0
+ if ok:
+ lhs = 'target.' + prefix + name
+ stmt = lhs + '=' + `value`
+ if debug: print 'exec', stmt
+ try:
+ exec(stmt + '\n')
+ except KeyboardInterrupt: # Don't catch this!
+ raise KeyboardInterrupt
+ except:
+ print 'assign failed:', stmt
+
+
+# Build a real actuator from an actuator descriptior.
+# Return a pair (actuator, name).
+#
+def build_actuator(descr):
+ namelist = getattrlist(descr, 'name')
+ if namelist:
+ # Assume it is a string
+ actuatorname = namelist[0][1:-1]
+ else:
+ actuatorname = ''
+ type = descr[0]
+ if type[:4] = 'pnl_': type = type[4:]
+ act = pnl.mkact(type)
+ act.downfunc = act.activefunc = act.upfunc = dummy_callback
+ #
+ assign_members(act, descr[1:], ('al', 'data', 'name'), '')
+ #
+ # Treat actuator-specific data
+ #
+ datalist = getattrlist(descr, 'data')
+ prefix = ''
+ if type[-4:] = 'puck':
+ prefix = 'puck_'
+ elif type = 'mouse':
+ prefix = 'mouse_'
+ assign_members(act, datalist, (), prefix)
+ #
+ return act, actuatorname
+
+
+# Build all sub-actuators and add them to the super-actuator.
+# The super-actuator must already have been added to the panel.
+# Sub-actuators with defined names are added as members to the panel
+# so they can be referenced as p.name.
+#
+# Note: I have no idea how panel.endgroup() works when applied
+# to a sub-actuator.
+#
+def build_subactuators(panel, super_act, al):
+ #
+ # This is nearly the same loop as below in build_panel(),
+ # except a call is made to addsubact() instead of addact().
+ #
+ for a in al:
+ act, name = build_actuator(a)
+ act.addsubact(super_act)
+ if name:
+ stmt = 'panel.' + name + ' = act'
+ if debug: print 'exec', stmt
+ exec(stmt + '\n')
+ if is_endgroup(a):
+ panel.endgroup()
+ sub_al = getattrlist(a, 'al')
+ if sub_al:
+ build_subactuators(panel, act, sub_al)
+ #
+ # Fix the actuator to which whe just added subactuators.
+ # This can't hurt (I hope) and is needed for the scroll actuator.
+ #
+ super_act.fixact()
+
+
+# Build a real panel from a panel definition.
+# Return a panel object p, where for each named actuator a, p.name is a
+# reference to a.
+#
+def build_panel(descr):
+ #
+ # Sanity check
+ #
+ if (not descr) or descr[0] <> 'panel':
+ raise panel_error, 'panel description must start with "panel"'
+ #
+ if debug: show_panel('', descr)
+ #
+ # Create an empty panel
+ #
+ panel = pnl.mkpanel()
+ #
+ # Assign panel attributes
+ #
+ assign_members(panel, descr[1:], ('al'), '')
+ #
+ # Look for actuator list
+ #
+ al = getattrlist(descr, 'al')
+ #
+ # The order in which actuators are created is important
+ # because of the endgroup() operator.
+ # Unfortunately the Panel Editor outputs the actuator list
+ # in reverse order, so we reverse it here.
+ #
+ al = reverse(al)
+ #
+ for a in al:
+ act, name = build_actuator(a)
+ act.addact(panel)
+ if name:
+ stmt = 'panel.' + name + ' = act'
+ exec(stmt + '\n')
+ if is_endgroup(a):
+ panel.endgroup()
+ sub_al = getattrlist(a, 'al')
+ if sub_al:
+ build_subactuators(panel, act, sub_al)
+ #
+ return panel
+
+
+# Wrapper around pnl.dopanel() which calls call-back functions.
+#
+def my_dopanel():
+ # Extract only the first 4 elements to allow for future expansion
+ a, down, active, up = pnl.dopanel()[:4]
+ if down:
+ down.downfunc(down)
+ if active:
+ active.activefunc(active)
+ if up:
+ up.upfunc(up)
+ return a
+
+
+# Create one or more panels from a description file (S-expressions)
+# generated by the Panel Editor.
+#
+def defpanellist(file):
+ import parser
+ descrlist = parser.parse_file(open(file, 'r'))
+ panellist = []
+ for descr in descrlist:
+ panellist.append(build_panel(descr))
+ return panellist
+
+
+# Import everything from built-in method pnl, so the user can always
+# use panel.foo() instead of pnl.foo().
+# This gives *no* performance penalty once this module is imported.
+#
+from pnl import * # for export
+
+dopanel = my_dopanel # override pnl.dopanel
diff --git a/Lib/irix5/panelparser.py b/Lib/irix5/panelparser.py
new file mode 100755
index 0000000..9c9ee02
--- /dev/null
+++ b/Lib/irix5/panelparser.py
@@ -0,0 +1,128 @@
+# Module 'parser'
+#
+# Parse S-expressions output by the Panel Editor
+# (which is written in Scheme so it can't help writing S-expressions).
+#
+# See notes at end of file.
+
+
+whitespace = ' \t\n'
+operators = '()\''
+separators = operators + whitespace + ';' + '"'
+
+
+# Tokenize a string.
+# Return a list of tokens (strings).
+#
+def tokenize_string(s):
+ tokens = []
+ while s:
+ c = s[:1]
+ if c in whitespace:
+ s = s[1:]
+ elif c = ';':
+ s = ''
+ elif c = '"':
+ n = len(s)
+ i = 1
+ while i < n:
+ c = s[i]
+ i = i+1
+ if c = '"': break
+ if c = '\\': i = i+1
+ tokens.append(s[:i])
+ s = s[i:]
+ elif c in operators:
+ tokens.append(c)
+ s = s[1:]
+ else:
+ n = len(s)
+ i = 1
+ while i < n:
+ if s[i] in separators: break
+ i = i+1
+ tokens.append(s[:i])
+ s = s[i:]
+ return tokens
+
+
+# Tokenize a whole file (given as file object, not as file name).
+# Return a list of tokens (strings).
+#
+def tokenize_file(fp):
+ tokens = []
+ while 1:
+ line = fp.readline()
+ if not line: break
+ tokens = tokens + tokenize_string(line)
+ return tokens
+
+
+# Exception raised by parse_exr.
+#
+syntax_error = 'syntax error'
+
+
+# Parse an S-expression.
+# Input is a list of tokens as returned by tokenize_*().
+# Return a pair (expr, tokens)
+# where expr is a list representing the s-expression,
+# and tokens contains the remaining tokens.
+# May raise syntax_error.
+#
+def parse_expr(tokens):
+ if (not tokens) or tokens[0] <> '(':
+ raise syntax_error, 'expected "("'
+ tokens = tokens[1:]
+ expr = []
+ while 1:
+ if not tokens:
+ raise syntax_error, 'missing ")"'
+ if tokens[0] = ')':
+ return expr, tokens[1:]
+ elif tokens[0] = '(':
+ subexpr, tokens = parse_expr(tokens)
+ expr.append(subexpr)
+ else:
+ expr.append(tokens[0])
+ tokens = tokens[1:]
+
+
+# Parse a file (given as file object, not as file name).
+# Return a list of parsed S-expressions found at the top level.
+#
+def parse_file(fp):
+ tokens = tokenize_file(fp)
+ exprlist = []
+ while tokens:
+ expr, tokens = parse_expr(tokens)
+ exprlist.append(expr)
+ return exprlist
+
+
+# EXAMPLE:
+#
+# The input
+# '(hip (hop hur-ray))'
+#
+# passed to tokenize_string() returns the token list
+# ['(', 'hip', '(', 'hop', 'hur-ray', ')', ')']
+#
+# When this is passed to parse_expr() it returns the expression
+# ['hip', ['hop', 'hur-ray']]
+# plus an empty token list (because there are no tokens left.
+#
+# When a file containing the example is passed to parse_file() it returns
+# a list whose only element is the output of parse_expr() above:
+# [['hip', ['hop', 'hur-ray']]]
+
+
+# TOKENIZING:
+#
+# Comments start with semicolon (;) and continue till the end of the line.
+#
+# Tokens are separated by whitespace, except the following characters
+# always form a separate token (outside strings):
+# ( ) '
+# Strings are enclosed in double quotes (") and backslash (\) is used
+# as escape character in strings.
diff --git a/Lib/lib-old/dump.py b/Lib/lib-old/dump.py
new file mode 100644
index 0000000..cecc275
--- /dev/null
+++ b/Lib/lib-old/dump.py
@@ -0,0 +1,63 @@
+# Module 'dump'
+#
+# Print python code that reconstructs a variable.
+# This only works in certain cases.
+#
+# It works fine for:
+# - ints and floats (except NaNs and other weird things)
+# - strings
+# - compounds and lists, provided it works for all their elements
+# - imported modules, provided their name is the module name
+#
+# It works for top-level dictionaries but not for dictionaries
+# contained in other objects (could be made to work with some hassle
+# though).
+#
+# It does not work for functions (all sorts), classes, class objects,
+# windows, files etc.
+#
+# Finally, objects referenced by more than one name or contained in more
+# than one other object lose their sharing property (this is bad for
+# strings used as exception identifiers, for instance).
+
+# Dump a whole symbol table
+#
+def dumpsymtab(dict):
+ for key in dict.keys():
+ dumpvar(key, dict[key])
+
+# Dump a single variable
+#
+def dumpvar(name, x):
+ import sys
+ t = type(x)
+ if t = type({}):
+ print name, '= {}'
+ for key in x.keys():
+ item = x[key]
+ if not printable(item):
+ print '#',
+ print name, '[', `key`, '] =', `item`
+ elif t in (type(''), type(0), type(0.0), type([]), type(())):
+ if not printable(x):
+ print '#',
+ print name, '=', `x`
+ elif t = type(sys):
+ print 'import', name, '#', x
+ else:
+ print '#', name, '=', x
+
+# check if a value is printable in a way that can be read back with input()
+#
+def printable(x):
+ t = type(x)
+ if t in (type(''), type(0), type(0.0)):
+ return 1
+ if t in (type([]), type(())):
+ for item in x:
+ if not printable(item):
+ return 0
+ return 1
+ if x = {}:
+ return 1
+ return 0
diff --git a/Lib/lib-old/rand.py b/Lib/lib-old/rand.py
new file mode 100644
index 0000000..0616483
--- /dev/null
+++ b/Lib/lib-old/rand.py
@@ -0,0 +1,12 @@
+# Module 'rand'
+
+import whrandom
+
+def srand(seed):
+ whrandom.seed(seed%256, seed/256%256, seed/65536%256)
+
+def rand():
+ return int(whrandom.random() * 32768.0) % 32768
+
+def choice(seq):
+ return seq[rand() % len(seq)]
diff --git a/Lib/lib-old/util.py b/Lib/lib-old/util.py
new file mode 100644
index 0000000..dc67686
--- /dev/null
+++ b/Lib/lib-old/util.py
@@ -0,0 +1,9 @@
+# Module 'util' -- some useful functions that dont fit elsewhere
+
+# Remove an item from a list at most once
+#
+def remove(item, list):
+ for i in range(len(list)):
+ if list[i] = item:
+ del list[i]
+ break
diff --git a/Lib/lib-stdwin/anywin.py b/Lib/lib-stdwin/anywin.py
new file mode 100644
index 0000000..bb7e865
--- /dev/null
+++ b/Lib/lib-stdwin/anywin.py
@@ -0,0 +1,14 @@
+# Module 'anywin'
+# Open a file or directory in a window
+
+import dirwin
+import filewin
+import path
+
+def open(name):
+ print 'opening', name, '...'
+ if path.isdir(name):
+ w = dirwin.open(name)
+ else:
+ w = filewin.open(name)
+ return w
diff --git a/Lib/lib-stdwin/dirwin.py b/Lib/lib-stdwin/dirwin.py
new file mode 100644
index 0000000..5df85e7
--- /dev/null
+++ b/Lib/lib-stdwin/dirwin.py
@@ -0,0 +1,28 @@
+# Module 'dirwin'
+
+# Directory windows, a subclass of listwin
+
+import gwin
+import listwin
+import anywin
+import path
+import dircache
+
+def action(w, string, i, detail):
+ (h, v), clicks, button, mask = detail
+ if clicks = 2:
+ name = path.cat(w.name, string)
+ try:
+ w = anywin.open(name)
+ except posix.error, why:
+ stdwin.message('Can\'t open ' + name + ': ' + why[1])
+
+def open(name):
+ name = path.cat(name, '')
+ list = dircache.opendir(name)[:]
+ list.sort()
+ dircache.annotate(name, list)
+ w = listwin.open(name, list)
+ w.name = name
+ w.action = action
+ return w
diff --git a/Lib/lib-stdwin/filewin.py b/Lib/lib-stdwin/filewin.py
new file mode 100644
index 0000000..1beb0b6
--- /dev/null
+++ b/Lib/lib-stdwin/filewin.py
@@ -0,0 +1,31 @@
+# Module 'filewin'
+# File windows, a subclass of textwin (which is a subclass of gwin)
+
+import stdwin
+import textwin
+import path
+
+builtin_open = open
+
+def readfile(fn): # Return a string containing the file's contents
+ fp = builtin_open(fn, 'r')
+ a = ''
+ n = 8096
+ while 1:
+ b = fp.read(n)
+ if not b: break
+ a = a + b
+ return a
+
+
+# FILE WINDOW
+
+def open_readonly(fn): # Open a file window
+ w = textwin.open_readonly(fn, readfile(fn))
+ w.fn = fn
+ return w
+
+def open(fn): # Open a file window
+ w = textwin.open(fn, readfile(fn))
+ w.fn = fn
+ return w
diff --git a/Lib/lib-stdwin/gwin.py b/Lib/lib-stdwin/gwin.py
new file mode 100644
index 0000000..15aa432
--- /dev/null
+++ b/Lib/lib-stdwin/gwin.py
@@ -0,0 +1,118 @@
+# Module 'gwin'
+# Generic stdwin windows
+
+# This is used as a base class from which to derive other window types.
+# The mainloop() function here is an event dispatcher for all window types.
+
+import stdwin
+import stdwinsupport
+
+S = stdwinsupport # Shorthand
+
+windows = [] # List of open windows
+
+
+# Open a window
+
+def open(title): # Open a generic window
+ w = stdwin.open(title)
+ stdwin.setdefwinsize(0, 0)
+ # Set default event handlers
+ w.draw = nop
+ w.char = nop
+ w.mdown = nop
+ w.mmove = nop
+ w.mup = nop
+ w.m2down = m2down
+ w.m2up = m2up
+ w.size = nop
+ w.move = nop
+ w.activate = w.deactivate = nop
+ w.timer = nop
+ # default command handlers
+ w.close = close
+ w.tab = tab
+ w.enter = enter
+ w.backspace = backspace
+ w.arrow = arrow
+ w.kleft = w.kup = w.kright = w.kdown = nop
+ windows.append(w)
+ return w
+
+
+# Generic event dispatching
+
+def mainloop(): # Handle events until no windows left
+ while windows:
+ treatevent(stdwin.getevent())
+
+def treatevent(e): # Handle a stdwin event
+ type, w, detail = e
+ if type = S.we_draw:
+ w.draw(w, detail)
+ elif type = S.we_menu:
+ m, item = detail
+ m.action[item](w, m, item)
+ elif type = S.we_command:
+ treatcommand(w, detail)
+ elif type = S.we_char:
+ w.char(w, detail)
+ elif type = S.we_mouse_down:
+ if detail[1] > 1: w.m2down(w, detail)
+ else: w.mdown(w, detail)
+ elif type = S.we_mouse_move:
+ w.mmove(w, detail)
+ elif type = S.we_mouse_up:
+ if detail[1] > 1: w.m2up(w, detail)
+ else: w.mup(w, detail)
+ elif type = S.we_size:
+ w.size(w, w.getwinsize())
+ elif type = S.we_activate:
+ w.activate(w)
+ elif type = S.we_deactivate:
+ w.deactivate(w)
+ elif type = S.we_move:
+ w.move(w)
+ elif type = S.we_timer:
+ w.timer(w)
+
+def treatcommand(w, type): # Handle a we_command event
+ if type = S.wc_close:
+ w.close(w)
+ elif type = S.wc_return:
+ w.enter(w)
+ elif type = S.wc_tab:
+ w.tab(w)
+ elif type = S.wc_backspace:
+ w.backspace(w)
+ elif type in (S.wc_left, S.wc_up, S.wc_right, S.wc_down):
+ w.arrow(w, type)
+
+
+# Methods
+
+def close(w): # Close method
+ for i in range(len(windows)):
+ if windows[i] is w:
+ del windows[i]
+ break
+
+def arrow(w, detail): # Arrow key method
+ if detail = S.wc_left:
+ w.kleft(w)
+ elif detail = S.wc_up:
+ w.kup(w)
+ elif detail = S.wc_right:
+ w.kright(w)
+ elif detail = S.wc_down:
+ w.kdown(w)
+
+
+# Trivial methods
+
+def tab(w): w.char(w, '\t')
+def enter(w): w.char(w, '\n') # 'return' is a Python reserved word
+def backspace(w): w.char(w, '\b')
+def m2down(w, detail): w.mdown(w, detail)
+def m2up(w, detail): w.mup(w, detail)
+def nop(args): pass
diff --git a/Lib/lib-stdwin/listwin.py b/Lib/lib-stdwin/listwin.py
new file mode 100644
index 0000000..9480a81
--- /dev/null
+++ b/Lib/lib-stdwin/listwin.py
@@ -0,0 +1,47 @@
+# Module 'listwin'
+# List windows, a subclass of gwin
+
+import gwin
+import stdwin
+
+def maxlinewidth(a): # Compute maximum textwidth of lines in a sequence
+ max = 0
+ for line in a:
+ width = stdwin.textwidth(line)
+ if width > max: max = width
+ return max
+
+def action(w, string, i, detail): # Default item selection method
+ pass
+
+def mup(w, detail): # Mouse up method
+ (h, v), clicks, button, mask = detail
+ i = divmod(v, w.lineheight)[0]
+ if 0 <= i < len(w.data):
+ w.action(w, w.data[i], i, detail)
+
+def draw(w, ((left, top), (right, bottom))): # Text window draw method
+ data = w.data
+ d = w.begindrawing()
+ lh = w.lineheight
+ itop = top/lh
+ ibot = (bottom-1)/lh + 1
+ if itop < 0: itop = 0
+ if ibot > len(data): ibot = len(data)
+ for i in range(itop, ibot): d.text((0, i*lh), data[i])
+
+def open(title, data): # Display a list of texts in a window
+ lineheight = stdwin.lineheight()
+ h, v = maxlinewidth(data), len(data)*lineheight
+ h0, v0 = h + stdwin.textwidth(' '), v + lineheight
+ if h0 > stdwin.textwidth(' ')*80: h0 = 0
+ if v0 > stdwin.lineheight()*24: v0 = 0
+ stdwin.setdefwinsize(h0, v0)
+ w = gwin.open(title)
+ w.setdocsize(h, v)
+ w.lineheight = lineheight
+ w.data = data
+ w.draw = draw
+ w.action = action
+ w.mup = mup
+ return w
diff --git a/Lib/lib-stdwin/rect.py b/Lib/lib-stdwin/rect.py
new file mode 100644
index 0000000..c044b9f
--- /dev/null
+++ b/Lib/lib-stdwin/rect.py
@@ -0,0 +1,87 @@
+# Module 'rect'.
+#
+# Operations on rectangles.
+# There is some normalization: all results return the object 'empty'
+# if their result would contain no points.
+
+
+# Exception.
+#
+error = 'rect.error'
+
+
+# The empty rectangle.
+#
+empty = (0, 0), (0, 0)
+
+
+# Check if a rectangle is empty.
+#
+def is_empty((left, top), (right, bottom)):
+ return left >= right or top >= bottom
+
+
+# Compute the intersection or two or more rectangles.
+# This works with a list or tuple argument.
+#
+def intersect(list):
+ if not list: raise error, 'intersect called with empty list'
+ if is_empty(list[0]): return empty
+ (left, top), (right, bottom) = list[0]
+ for rect in list[1:]:
+ if not is_empty(rect):
+ (l, t), (r, b) = rect
+ if left < l: left = l
+ if top < t: top = t
+ if right > r: right = r
+ if bottom > b: bottom = b
+ if is_empty((left, top), (right, bottom)):
+ return empty
+ return (left, top), (right, bottom)
+
+
+# Compute the smallest rectangle containing all given rectangles.
+# This works with a list or tuple argument.
+#
+def union(list):
+ (left, top), (right, bottom) = empty
+ for (l, t), (r, b) in list[1:]:
+ if not is_empty((l, t), (r, b)):
+ if l < left: left = l
+ if t < top: top = t
+ if r > right: right = r
+ if b > bottom: bottom = b
+ res = (left, top), (right, bottom)
+ if is_empty(res):
+ return empty
+ return res
+
+
+# Check if a point is in a rectangle.
+#
+def pointinrect((h, v), ((left, top), (right, bottom))):
+ return left <= h < right and top <= v < bottom
+
+
+# Return a rectangle that is dh, dv inside another
+#
+def inset(((left, top), (right, bottom)), (dh, dv)):
+ left = left + dh
+ top = top + dv
+ right = right - dh
+ bottom = bottom - dv
+ r = (left, top), (right, bottom)
+ if is_empty(r):
+ return empty
+ else:
+ return r
+
+
+# Conversions between rectangles and 'geometry tuples',
+# given as origin (h, v) and dimensions (width, height).
+#
+def rect2geom((left, top), (right, bottom)):
+ return (left, top), (right-left, bottom-top)
+
+def geom2rect((h, v), (width, height)):
+ return (h, v), (h+width, v+height)
diff --git a/Lib/lib-stdwin/stdwinevents.py b/Lib/lib-stdwin/stdwinevents.py
new file mode 100644
index 0000000..889dd95
--- /dev/null
+++ b/Lib/lib-stdwin/stdwinevents.py
@@ -0,0 +1,36 @@
+# Module 'stdwinevents' -- Constants for stdwin event types
+#
+# Suggested usage:
+# from stdwinevents import *
+
+# The function stdwin.getevent() returns a tuple containing:
+# (type, window, detail)
+# where detail may be <no value> or a value depending on type, see below:
+
+# Values for type:
+
+WE_NULL = 0 # not reported -- means 'no event' internally
+WE_ACTIVATE = 1 # detail is <no object>
+WE_CHAR = 2 # detail is the character
+WE_COMMAND = 3 # detail is one of the WC_* constants below
+WE_MOUSE_DOWN = 4 # detail is ((h, v), clicks, button, mask)
+WE_MOUSE_MOVE = 5 # ditto
+WE_MOUSE_UP = 6 # ditto
+WE_MENU = 7 # detail is (menu, item)
+WE_SIZE = 8 # detail is (width, height) [???]
+WE_MOVE = 9 # not reported -- reserved for future use
+WE_DRAW = 10 # detail is ((left, top), (right, bottom))
+WE_TIMER = 11 # detail is <no object>
+WE_DEACTIVATE = 12 # detail is <no object>
+
+# Values for detail when type is WE_COMMAND:
+
+WC_CLOSE = 1 # user hit close box
+WC_LEFT = 2 # left arrow key
+WC_RIGHT = 3 # right arrow key
+WC_UP = 4 # up arrow key
+WC_DOWN = 5 # down arrow key
+WC_CANCEL = 6 # not reported -- turned into KeyboardInterrupt
+WC_BACKSPACE = 7 # backspace key
+WC_TAB = 8 # tab key
+WC_RETURN = 9 # return or enter key
diff --git a/Lib/lib-stdwin/tablewin.py b/Lib/lib-stdwin/tablewin.py
new file mode 100644
index 0000000..05a954e
--- /dev/null
+++ b/Lib/lib-stdwin/tablewin.py
@@ -0,0 +1,237 @@
+# Module 'tablewin'
+
+# Display a table, with per-item actions:
+
+# A1 | A2 | A3 | .... | AN
+# B1 | B2 | B3 | .... | BN
+# C1 | C2 | C3 | .... | CN
+# .. | .. | .. | .... | ..
+# Z1 | Z2 | Z3 | .... | ZN
+
+# Not all columns need to have the same length.
+# The data structure is a list of columns;
+# each column is a list of items.
+# Each item is a pair of a string and an action procedure.
+# The first item may be a column title.
+
+import stdwin
+import gwin
+
+def open(title, data): # Public function to open a table window
+ #
+ # Set geometry parameters (one day, these may be changeable)
+ #
+ margin = stdwin.textwidth(' ')
+ lineheight = stdwin.lineheight()
+ #
+ # Geometry calculations
+ #
+ colstarts = [0]
+ totwidth = 0
+ maxrows = 0
+ for coldata in data:
+ # Height calculations
+ rows = len(coldata)
+ if rows > maxrows: maxrows = rows
+ # Width calculations
+ width = colwidth(coldata) + margin
+ totwidth = totwidth + width
+ colstarts.append(totwidth)
+ #
+ # Calculate document and window height
+ #
+ docwidth, docheight = totwidth, maxrows*lineheight
+ winwidth, winheight = docwidth, docheight
+ if winwidth > stdwin.textwidth('n')*100: winwidth = 0
+ if winheight > stdwin.lineheight()*30: winheight = 0
+ #
+ # Create the window
+ #
+ stdwin.setdefwinsize(winwidth, winheight)
+ w = gwin.open(title)
+ #
+ # Set properties and override methods
+ #
+ w.data = data
+ w.margin = margin
+ w.lineheight = lineheight
+ w.colstarts = colstarts
+ w.totwidth = totwidth
+ w.maxrows = maxrows
+ w.selection = (-1, -1)
+ w.lastselection = (-1, -1)
+ w.selshown = 0
+ w.setdocsize(docwidth, docheight)
+ w.draw = draw
+ w.mup = mup
+ w.arrow = arrow
+ #
+ # Return
+ #
+ return w
+
+def update(w, data): # Change the data
+ #
+ # Hide selection
+ #
+ hidesel(w, w.begindrawing())
+ #
+ # Get old geometry parameters
+ #
+ margin = w.margin
+ lineheight = w.lineheight
+ #
+ # Geometry calculations
+ #
+ colstarts = [0]
+ totwidth = 0
+ maxrows = 0
+ for coldata in data:
+ # Height calculations
+ rows = len(coldata)
+ if rows > maxrows: maxrows = rows
+ # Width calculations
+ width = colwidth(coldata) + margin
+ totwidth = totwidth + width
+ colstarts.append(totwidth)
+ #
+ # Calculate document and window height
+ #
+ docwidth, docheight = totwidth, maxrows*lineheight
+ #
+ # Set changed properties and change window size
+ #
+ w.data = data
+ w.colstarts = colstarts
+ w.totwidth = totwidth
+ w.maxrows = maxrows
+ w.change((0, 0), (10000, 10000))
+ w.setdocsize(docwidth, docheight)
+ w.change((0, 0), (docwidth, docheight))
+ #
+ # Show selection, or forget it if out of range
+ #
+ showsel(w, w.begindrawing())
+ if not w.selshown: w.selection = (-1, -1)
+
+def colwidth(coldata): # Subroutine to calculate column width
+ maxwidth = 0
+ for string, action in coldata:
+ width = stdwin.textwidth(string)
+ if width > maxwidth: maxwidth = width
+ return maxwidth
+
+def draw(w, ((left, top), (right, bottom))): # Draw method
+ ileft = whichcol(w, left)
+ iright = whichcol(w, right-1) + 1
+ if iright > len(w.data): iright = len(w.data)
+ itop = divmod(top, w.lineheight)[0]
+ if itop < 0: itop = 0
+ ibottom, remainder = divmod(bottom, w.lineheight)
+ if remainder: ibottom = ibottom + 1
+ d = w.begindrawing()
+ if ileft <= w.selection[0] < iright:
+ if itop <= w.selection[1] < ibottom:
+ hidesel(w, d)
+ d.erase((left, top), (right, bottom))
+ for i in range(ileft, iright):
+ col = w.data[i]
+ jbottom = len(col)
+ if ibottom < jbottom: jbottom = ibottom
+ h = w.colstarts[i]
+ v = itop * w.lineheight
+ for j in range(itop, jbottom):
+ string, action = col[j]
+ d.text((h, v), string)
+ v = v + w.lineheight
+ showsel(w, d)
+
+def mup(w, detail): # Mouse up method
+ (h, v), nclicks, button, mask = detail
+ icol = whichcol(w, h)
+ if 0 <= icol < len(w.data):
+ irow = divmod(v, w.lineheight)[0]
+ col = w.data[icol]
+ if 0 <= irow < len(col):
+ string, action = col[irow]
+ action(w, string, (icol, irow), detail)
+
+def whichcol(w, h): # Return column number (may be >= len(w.data))
+ for icol in range(0, len(w.data)):
+ if h < w.colstarts[icol+1]:
+ return icol
+ return len(w.data)
+
+def arrow(w, type):
+ import stdwinsupport
+ S = stdwinsupport
+ if type = S.wc_left:
+ incr = -1, 0
+ elif type = S.wc_up:
+ incr = 0, -1
+ elif type = S.wc_right:
+ incr = 1, 0
+ elif type = S.wc_down:
+ incr = 0, 1
+ else:
+ return
+ icol, irow = w.lastselection
+ icol = icol + incr[0]
+ if icol < 0: icol = len(w.data)-1
+ if icol >= len(w.data): icol = 0
+ if 0 <= icol < len(w.data):
+ irow = irow + incr[1]
+ if irow < 0: irow = len(w.data[icol]) - 1
+ if irow >= len(w.data[icol]): irow = 0
+ else:
+ irow = 0
+ if 0 <= icol < len(w.data) and 0 <= irow < len(w.data[icol]):
+ w.lastselection = icol, irow
+ string, action = w.data[icol][irow]
+ detail = (0, 0), 1, 1, 1
+ action(w, string, (icol, irow), detail)
+
+
+# Selection management
+# TO DO: allow multiple selected entries
+
+def select(w, selection): # Public function to set the item selection
+ d = w.begindrawing()
+ hidesel(w, d)
+ w.selection = selection
+ showsel(w, d)
+ if w.selshown: lastselection = selection
+
+def hidesel(w, d): # Hide the selection, if shown
+ if w.selshown: invertsel(w, d)
+
+def showsel(w, d): # Show the selection, if hidden
+ if not w.selshown: invertsel(w, d)
+
+def invertsel(w, d): # Invert the selection, if valid
+ icol, irow = w.selection
+ if 0 <= icol < len(w.data) and 0 <= irow < len(w.data[icol]):
+ left = w.colstarts[icol]
+ right = w.colstarts[icol+1]
+ top = irow * w.lineheight
+ bottom = (irow+1) * w.lineheight
+ d.invert((left, top), (right, bottom))
+ w.selshown = (not w.selshown)
+
+
+# Demonstration
+
+def demo_action(w, string, (icol, irow), detail): # Action function for demo
+ select(w, (irow, icol))
+
+def demo(): # Demonstration
+ da = demo_action # shorthand
+ col0 = [('a1', da), ('bbb1', da), ('c1', da)]
+ col1 = [('a2', da), ('bbb2', da)]
+ col2 = [('a3', da), ('b3', da), ('c3', da), ('d4', da), ('d5', da)]
+ col3 = []
+ for i in range(1, 31): col3.append('xxx' + `i`, da)
+ data = [col0, col1, col2, col3]
+ w = open('tablewin.demo', data)
+ gwin.mainloop()
+ return w
diff --git a/Lib/lib-stdwin/textwin.py b/Lib/lib-stdwin/textwin.py
new file mode 100644
index 0000000..2631ca4
--- /dev/null
+++ b/Lib/lib-stdwin/textwin.py
@@ -0,0 +1,119 @@
+# Module 'textwin'
+
+# Text windows, a subclass of gwin
+
+import stdwin
+import stdwinsupport
+import gwin
+
+S = stdwinsupport # Shorthand
+
+
+def fixsize(w):
+ docwidth, docheight = w.text.getrect()[1]
+ winheight = w.getwinsize()[1]
+ if winheight > docheight: docheight = winheight
+ w.setdocsize(0, docheight)
+ fixeditmenu(w)
+
+def cut(w, m, id):
+ s = w.text.getfocustext()
+ if s:
+ stdwin.setcutbuffer(s)
+ w.text.replace('')
+ fixsize(w)
+
+def copy(w, m, id):
+ s = w.text.getfocustext()
+ if s:
+ stdwin.setcutbuffer(s)
+ fixeditmenu(w)
+
+def paste(w, m, id):
+ w.text.replace(stdwin.getcutbuffer())
+ fixsize(w)
+
+def addeditmenu(w):
+ m = w.editmenu = w.menucreate('Edit')
+ m.action = []
+ m.additem('Cut', 'X')
+ m.action.append(cut)
+ m.additem('Copy', 'C')
+ m.action.append(copy)
+ m.additem('Paste', 'V')
+ m.action.append(paste)
+
+def fixeditmenu(w):
+ m = w.editmenu
+ f = w.text.getfocus()
+ can_copy = (f[0] < f[1])
+ m.enable(1, can_copy)
+ if not w.readonly:
+ m.enable(0, can_copy)
+ m.enable(2, (stdwin.getcutbuffer() <> ''))
+
+def draw(w, area): # Draw method
+ w.text.draw(area)
+
+def size(w, newsize): # Size method
+ w.text.move((0, 0), newsize)
+ fixsize(w)
+
+def close(w): # Close method
+ del w.text # Break circular ref
+ gwin.close(w)
+
+def char(w, c): # Char method
+ w.text.replace(c)
+ fixsize(w)
+
+def backspace(w): # Backspace method
+ void = w.text.event(S.we_command, w, S.wc_backspace)
+ fixsize(w)
+
+def arrow(w, detail): # Arrow method
+ w.text.arrow(detail)
+ fixeditmenu(w)
+
+def mdown(w, detail): # Mouse down method
+ void = w.text.event(S.we_mouse_down, w, detail)
+ fixeditmenu(w)
+
+def mmove(w, detail): # Mouse move method
+ void = w.text.event(S.we_mouse_move, w, detail)
+
+def mup(w, detail): # Mouse up method
+ void = w.text.event(S.we_mouse_up, w, detail)
+ fixeditmenu(w)
+
+def activate(w): # Activate method
+ fixeditmenu(w)
+
+def open(title, str): # Display a string in a window
+ w = gwin.open(title)
+ w.readonly = 0
+ w.text = w.textcreate((0, 0), w.getwinsize())
+ w.text.replace(str)
+ w.text.setfocus(0, 0)
+ addeditmenu(w)
+ fixsize(w)
+ w.draw = draw
+ w.size = size
+ w.close = close
+ w.mdown = mdown
+ w.mmove = mmove
+ w.mup = mup
+ w.char = char
+ w.backspace = backspace
+ w.arrow = arrow
+ w.activate = activate
+ return w
+
+def open_readonly(title, str): # Same with char input disabled
+ w = open(title, str)
+ w.readonly = 1
+ w.char = w.backspace = gwin.nop
+ # Disable Cut and Paste menu item; leave Copy alone
+ w.editmenu.enable(0, 0)
+ w.editmenu.enable(2, 0)
+ return w
diff --git a/Lib/plat-irix5/DEVICE.py b/Lib/plat-irix5/DEVICE.py
new file mode 100755
index 0000000..00eddfc
--- /dev/null
+++ b/Lib/plat-irix5/DEVICE.py
@@ -0,0 +1,423 @@
+#/**************************************************************************
+# * *
+# * Copyright (C) 1984, Silicon Graphics, Inc. *
+# * *
+# * These coded instructions, statements, and computer programs contain *
+# * unpublished proprietary information of Silicon Graphics, Inc., and *
+# * are protected by Federal copyright law. They may not be disclosed *
+# * to third parties or copied or duplicated in any form, in whole or *
+# * in part, without the prior written consent of Silicon Graphics, Inc. *
+# * *
+# **************************************************************************/
+#/* file with device definitions (see /usr/include/device.h) */
+
+NULLDEV = 0
+BUTOFFSET = 1
+VALOFFSET = 256
+TIMOFFSET = 515
+XKBDOFFSET = 143
+INOFFSET = 1024
+OUTOFFSET = 1033
+BUTCOUNT = 190
+VALCOUNT = 27
+TIMCOUNT = 4
+XKBDCOUNT = 28
+INCOUNT = 8
+OUTCOUNT = 8
+#
+#
+#
+#
+BUT0 = 1
+BUT1 = 2
+BUT2 = 3
+BUT3 = 4
+BUT4 = 5
+BUT5 = 6
+BUT6 = 7
+BUT7 = 8
+BUT8 = 9
+BUT9 = 10
+BUT10 = 11
+BUT11 = 12
+BUT12 = 13
+BUT13 = 14
+BUT14 = 15
+BUT15 = 16
+BUT16 = 17
+BUT17 = 18
+BUT18 = 19
+BUT19 = 20
+BUT20 = 21
+BUT21 = 22
+BUT22 = 23
+BUT23 = 24
+BUT24 = 25
+BUT25 = 26
+BUT26 = 27
+BUT27 = 28
+BUT28 = 29
+BUT29 = 30
+BUT30 = 31
+BUT31 = 32
+BUT32 = 33
+BUT33 = 34
+BUT34 = 35
+BUT35 = 36
+BUT36 = 37
+BUT37 = 38
+BUT38 = 39
+BUT39 = 40
+BUT40 = 41
+BUT41 = 42
+BUT42 = 43
+BUT43 = 44
+BUT44 = 45
+BUT45 = 46
+BUT46 = 47
+BUT47 = 48
+BUT48 = 49
+BUT49 = 50
+BUT50 = 51
+BUT51 = 52
+BUT52 = 53
+BUT53 = 54
+BUT54 = 55
+BUT55 = 56
+BUT56 = 57
+BUT57 = 58
+BUT58 = 59
+BUT59 = 60
+BUT60 = 61
+BUT61 = 62
+BUT62 = 63
+BUT63 = 64
+BUT64 = 65
+BUT65 = 66
+BUT66 = 67
+BUT67 = 68
+BUT68 = 69
+BUT69 = 70
+BUT70 = 71
+BUT71 = 72
+BUT72 = 73
+BUT73 = 74
+BUT74 = 75
+BUT75 = 76
+BUT76 = 77
+BUT77 = 78
+BUT78 = 79
+BUT79 = 80
+BUT80 = 81
+BUT81 = 82
+BUT82 = 83
+MAXKBDBUT = 83
+BUT100 = 101
+BUT101 = 102
+BUT102 = 103
+BUT110 = 111
+BUT111 = 112
+BUT112 = 113
+BUT113 = 114
+BUT114 = 115
+BUT115 = 116
+BUT116 = 117
+BUT117 = 118
+BUT118 = 119
+BUT119 = 120
+BUT120 = 121
+BUT121 = 122
+BUT122 = 123
+BUT123 = 124
+BUT124 = 125
+BUT125 = 126
+BUT126 = 127
+BUT127 = 128
+BUT128 = 129
+BUT129 = 130
+BUT130 = 131
+BUT131 = 132
+BUT132 = 133
+BUT133 = 134
+BUT134 = 135
+BUT135 = 136
+BUT136 = 137
+BUT137 = 138
+BUT138 = 139
+BUT139 = 140
+BUT140 = 141
+BUT141 = 142
+BUT142 = 143
+BUT143 = 144
+BUT144 = 145
+BUT145 = 146
+BUT146 = 147
+BUT147 = 148
+BUT148 = 149
+BUT149 = 150
+BUT150 = 151
+BUT151 = 152
+BUT152 = 153
+BUT153 = 154
+BUT154 = 155
+BUT155 = 156
+BUT156 = 157
+BUT157 = 158
+BUT158 = 159
+BUT159 = 160
+BUT160 = 161
+BUT161 = 162
+BUT162 = 163
+BUT163 = 164
+BUT164 = 165
+BUT165 = 166
+BUT166 = 167
+BUT167 = 168
+BUT168 = 169
+BUT181 = 182
+BUT182 = 183
+BUT183 = 184
+BUT184 = 185
+BUT185 = 186
+BUT186 = 187
+BUT187 = 188
+BUT188 = 189
+BUT189 = 190
+MOUSE1 = 101
+MOUSE2 = 102
+MOUSE3 = 103
+LEFTMOUSE = 103
+MIDDLEMOUSE = 102
+RIGHTMOUSE = 101
+LPENBUT = 104
+BPAD0 = 105
+BPAD1 = 106
+BPAD2 = 107
+BPAD3 = 108
+LPENVALID = 109
+SWBASE = 111
+SW0 = 111
+SW1 = 112
+SW2 = 113
+SW3 = 114
+SW4 = 115
+SW5 = 116
+SW6 = 117
+SW7 = 118
+SW8 = 119
+SW9 = 120
+SW10 = 121
+SW11 = 122
+SW12 = 123
+SW13 = 124
+SW14 = 125
+SW15 = 126
+SW16 = 127
+SW17 = 128
+SW18 = 129
+SW19 = 130
+SW20 = 131
+SW21 = 132
+SW22 = 133
+SW23 = 134
+SW24 = 135
+SW25 = 136
+SW26 = 137
+SW27 = 138
+SW28 = 139
+SW29 = 140
+SW30 = 141
+SW31 = 142
+SBBASE = 182
+SBPICK = 182
+SBBUT1 = 183
+SBBUT2 = 184
+SBBUT3 = 185
+SBBUT4 = 186
+SBBUT5 = 187
+SBBUT6 = 188
+SBBUT7 = 189
+SBBUT8 = 190
+AKEY = 11
+BKEY = 36
+CKEY = 28
+DKEY = 18
+EKEY = 17
+FKEY = 19
+GKEY = 26
+HKEY = 27
+IKEY = 40
+JKEY = 34
+KKEY = 35
+LKEY = 42
+MKEY = 44
+NKEY = 37
+OKEY = 41
+PKEY = 48
+QKEY = 10
+RKEY = 24
+SKEY = 12
+TKEY = 25
+UKEY = 33
+VKEY = 29
+WKEY = 16
+XKEY = 21
+YKEY = 32
+ZKEY = 20
+ZEROKEY = 46
+ONEKEY = 8
+TWOKEY = 14
+THREEKEY = 15
+FOURKEY = 22
+FIVEKEY = 23
+SIXKEY = 30
+SEVENKEY = 31
+EIGHTKEY = 38
+NINEKEY = 39
+BREAKKEY = 1
+SETUPKEY = 2
+CTRLKEY = 3
+LEFTCTRLKEY = CTRLKEY
+CAPSLOCKKEY = 4
+RIGHTSHIFTKEY = 5
+LEFTSHIFTKEY = 6
+NOSCRLKEY = 13
+ESCKEY = 7
+TABKEY = 9
+RETKEY = 51
+SPACEKEY = 83
+LINEFEEDKEY = 60
+BACKSPACEKEY = 61
+DELKEY = 62
+SEMICOLONKEY = 43
+PERIODKEY = 52
+COMMAKEY = 45
+QUOTEKEY = 50
+ACCENTGRAVEKEY = 55
+MINUSKEY = 47
+VIRGULEKEY = 53
+BACKSLASHKEY = 57
+EQUALKEY = 54
+LEFTBRACKETKEY = 49
+RIGHTBRACKETKEY = 56
+LEFTARROWKEY = 73
+DOWNARROWKEY = 74
+RIGHTARROWKEY = 80
+UPARROWKEY = 81
+PAD0 = 59
+PAD1 = 58
+PAD2 = 64
+PAD3 = 65
+PAD4 = 63
+PAD5 = 69
+PAD6 = 70
+PAD7 = 67
+PAD8 = 68
+PAD9 = 75
+PADPF1 = 72
+PADPF2 = 71
+PADPF3 = 79
+PADPF4 = 78
+PADPERIOD = 66
+PADMINUS = 76
+PADCOMMA = 77
+PADENTER = 82
+LEFTALTKEY = 143
+RIGHTALTKEY = 144
+RIGHTCTRLKEY = 145
+F1KEY = 146
+F2KEY = 147
+F3KEY = 148
+F4KEY = 149
+F5KEY = 150
+F6KEY = 151
+F7KEY = 152
+F8KEY = 153
+F9KEY = 154
+F10KEY = 155
+F11KEY = 156
+F12KEY = 157
+PRINTSCREENKEY = 158
+SCROLLLOCKKEY = 159
+PAUSEKEY = 160
+INSERTKEY = 161
+HOMEKEY = 162
+PAGEUPKEY = 163
+ENDKEY = 164
+PAGEDOWNKEY = 165
+NUMLOCKKEY = 166
+PADVIRGULEKEY = 167
+PADASTERKEY = 168
+PADPLUSKEY = 169
+SGIRESERVED = 256
+DIAL0 = 257
+DIAL1 = 258
+DIAL2 = 259
+DIAL3 = 260
+DIAL4 = 261
+DIAL5 = 262
+DIAL6 = 263
+DIAL7 = 264
+DIAL8 = 265
+MOUSEX = 266
+MOUSEY = 267
+LPENX = 268
+LPENY = 269
+BPADX = 270
+BPADY = 271
+CURSORX = 272
+CURSORY = 273
+GHOSTX = 274
+GHOSTY = 275
+SBTX = 276
+SBTY = 277
+SBTZ = 278
+SBRX = 279
+SBRY = 280
+SBRZ = 281
+SBPERIOD = 282
+TIMER0 = 515
+TIMER1 = 516
+TIMER2 = 517
+TIMER3 = 518
+KEYBD = 513
+RAWKEYBD = 514
+VALMARK = 523
+GERROR = 524
+REDRAW = 528
+WMSEND = 529
+WMREPLY = 530
+WMGFCLOSE = 531
+WMTXCLOSE = 532
+MODECHANGE = 533
+INPUTCHANGE = 534
+QFULL = 535
+PIECECHANGE = 536
+WINCLOSE = 537
+QREADERROR = 538
+WINFREEZE = 539
+WINTHAW = 540
+REDRAWICONIC = 541
+WINQUIT = 542
+DEPTHCHANGE = 543
+KEYBDFNAMES = 544
+KEYBDFSTRINGS = 545
+WINSHUT = 546
+INPUT0 = 1024
+INPUT1 = 1025
+INPUT2 = 1026
+INPUT3 = 1027
+INPUT4 = 1028
+INPUT5 = 1029
+INPUT6 = 1030
+INPUT7 = 1032
+OUTPUT0 = 1033
+OUTPUT1 = 1034
+OUTPUT2 = 1035
+OUTPUT3 = 1036
+OUTPUT4 = 1037
+OUTPUT5 = 1038
+OUTPUT6 = 1039
+OUTPUT7 = 1040
+MAXSGIDEVICE = 20000
+MENUBUTTON = RIGHTMOUSE
diff --git a/Lib/plat-irix5/GL.py b/Lib/plat-irix5/GL.py
new file mode 100755
index 0000000..35487a7
--- /dev/null
+++ b/Lib/plat-irix5/GL.py
@@ -0,0 +1,365 @@
+# Constants defined in <gl.h>
+
+#**************************************************************************
+#* *
+#* Copyright (C) 1984, Silicon Graphics, Inc. *
+#* *
+#* These coded instructions, statements, and computer programs contain *
+#* unpublished proprietary information of Silicon Graphics, Inc., and *
+#* are protected by Federal copyright law. They may not be disclosed *
+#* to third parties or copied or duplicated in any form, in whole or *
+#* in part, without the prior written consent of Silicon Graphics, Inc. *
+#* *
+#**************************************************************************
+
+# Graphics Libary constants
+
+# Booleans
+TRUE = 1
+FALSE = 0
+
+# maximum X and Y screen coordinates
+XMAXSCREEN = 1279
+YMAXSCREEN = 1023
+XMAXMEDIUM = 1023 # max for medium res monitor
+YMAXMEDIUM = 767
+XMAX170 = 645 # max for RS-170
+YMAX170 = 484
+XMAXPAL = 779 # max for PAL
+YMAXPAL = 574
+
+# various hardware/software limits
+ATTRIBSTACKDEPTH = 10
+VPSTACKDEPTH = 8
+MATRIXSTACKDEPTH = 32
+NAMESTACKDEPTH = 1025
+STARTTAG = -2
+ENDTAG = -3
+CPOSX_INVALID = -(2*XMAXSCREEN)
+
+# names for colors in color map loaded by greset
+BLACK = 0
+RED = 1
+GREEN = 2
+YELLOW = 3
+BLUE = 4
+MAGENTA = 5
+CYAN = 6
+WHITE = 7
+
+# popup colors
+PUP_CLEAR = 0
+PUP_COLOR = 1
+PUP_BLACK = 2
+PUP_WHITE = 3
+
+# defines for drawmode
+NORMALDRAW = 0
+PUPDRAW = 1
+OVERDRAW = 2
+UNDERDRAW = 3
+CURSORDRAW = 4
+
+# defines for defpattern
+PATTERN_16 = 16
+PATTERN_32 = 32
+PATTERN_64 = 64
+
+PATTERN_16_SIZE = 16
+PATTERN_32_SIZE = 64
+PATTERN_64_SIZE = 256
+
+# defines for readsource
+SRC_AUTO = 0
+SRC_FRONT = 1
+SRC_BACK = 2
+SRC_ZBUFFER = 3
+SRC_PUP = 4
+SRC_OVER = 5
+SRC_UNDER = 6
+SRC_FRAMEGRABBER = 7
+
+# defines for blendfunction
+BF_ZERO = 0
+BF_ONE = 1
+BF_DC = 2
+BF_SC = 2
+BF_MDC = 3
+BF_MSC = 3
+BF_SA = 4
+BF_MSA = 5
+BF_DA = 6
+BF_MDA = 7
+
+# defines for zfunction
+ZF_NEVER = 0
+ZF_LESS = 1
+ZF_EQUAL = 2
+ZF_LEQUAL = 3
+ZF_GREATER = 4
+ZF_NOTEQUAL = 5
+ZF_GEQUAL = 6
+ZF_ALWAYS = 7
+
+# defines for zsource
+ZSRC_DEPTH = 0
+ZSRC_COLOR = 1
+
+# defines for pntsmooth
+SMP_OFF = 0
+SMP_ON = 1
+
+# defines for linesmooth
+SML_OFF = 0
+SML_ON = 1
+
+# defines for setpup
+PUP_NONE = 0
+PUP_GREY = 1
+
+# defines for glcompat
+GLC_OLDPOLYGON = 0
+GLC_ZRANGEMAP = 1
+
+# defines for curstype
+C16X1 = 0
+C16X2 = 1
+C32X1 = 2
+C32X2 = 3
+CCROSS = 4
+
+# defines for shademodel
+FLAT = 0
+GOURAUD = 1
+
+# defines for logicop
+### LO_ZERO = 0x0
+### LO_AND = 0x1
+### LO_ANDR = 0x2
+### LO_SRC = 0x3
+### LO_ANDI = 0x4
+### LO_DST = 0x5
+### LO_XOR = 0x6
+### LO_OR = 0x7
+### LO_NOR = 0x8
+### LO_XNOR = 0x9
+### LO_NDST = 0xa
+### LO_ORR = 0xb
+### LO_NSRC = 0xc
+### LO_ORI = 0xd
+### LO_NAND = 0xe
+### LO_ONE = 0xf
+
+
+#
+# START defines for getgdesc
+#
+
+GD_XPMAX = 0
+GD_YPMAX = 1
+GD_XMMAX = 2
+GD_YMMAX = 3
+GD_ZMIN = 4
+GD_ZMAX = 5
+GD_BITS_NORM_SNG_RED = 6
+GD_BITS_NORM_SNG_GREEN = 7
+GD_BITS_NORM_SNG_BLUE = 8
+GD_BITS_NORM_DBL_RED = 9
+GD_BITS_NORM_DBL_GREEN = 10
+GD_BITS_NORM_DBL_BLUE = 11
+GD_BITS_NORM_SNG_CMODE = 12
+GD_BITS_NORM_DBL_CMODE = 13
+GD_BITS_NORM_SNG_MMAP = 14
+GD_BITS_NORM_DBL_MMAP = 15
+GD_BITS_NORM_ZBUFFER = 16
+GD_BITS_OVER_SNG_CMODE = 17
+GD_BITS_UNDR_SNG_CMODE = 18
+GD_BITS_PUP_SNG_CMODE = 19
+GD_BITS_NORM_SNG_ALPHA = 21
+GD_BITS_NORM_DBL_ALPHA = 22
+GD_BITS_CURSOR = 23
+GD_OVERUNDER_SHARED = 24
+GD_BLEND = 25
+GD_CIFRACT = 26
+GD_CROSSHAIR_CINDEX = 27
+GD_DITHER = 28
+GD_LINESMOOTH_CMODE = 30
+GD_LINESMOOTH_RGB = 31
+GD_LOGICOP = 33
+GD_NSCRNS = 35
+GD_NURBS_ORDER = 36
+GD_NBLINKS = 37
+GD_NVERTEX_POLY = 39
+GD_PATSIZE_64 = 40
+GD_PNTSMOOTH_CMODE = 41
+GD_PNTSMOOTH_RGB = 42
+GD_PUP_TO_OVERUNDER = 43
+GD_READSOURCE = 44
+GD_READSOURCE_ZBUFFER = 48
+GD_STEREO = 50
+GD_SUBPIXEL_LINE = 51
+GD_SUBPIXEL_PNT = 52
+GD_SUBPIXEL_POLY = 53
+GD_TRIMCURVE_ORDER = 54
+GD_WSYS = 55
+GD_ZDRAW_GEOM = 57
+GD_ZDRAW_PIXELS = 58
+GD_SCRNTYPE = 61
+GD_TEXTPORT = 62
+GD_NMMAPS = 63
+GD_FRAMEGRABBER = 64
+GD_TIMERHZ = 66
+GD_DBBOX = 67
+GD_AFUNCTION = 68
+GD_ALPHA_OVERUNDER = 69
+GD_BITS_ACBUF = 70
+GD_BITS_ACBUF_HW = 71
+GD_BITS_STENCIL = 72
+GD_CLIPPLANES = 73
+GD_FOGVERTEX = 74
+GD_LIGHTING_TWOSIDE = 76
+GD_POLYMODE = 77
+GD_POLYSMOOTH = 78
+GD_SCRBOX = 79
+GD_TEXTURE = 80
+
+# return value for inquiries when there is no limit
+GD_NOLIMIT = 2
+
+# return values for GD_WSYS
+GD_WSYS_NONE = 0
+GD_WSYS_4S = 1
+
+# return values for GD_SCRNTYPE
+GD_SCRNTYPE_WM = 0
+GD_SCRNTYPE_NOWM = 1
+
+#
+# END defines for getgdesc
+#
+
+
+#
+# START NURBS interface definitions
+#
+
+# NURBS Rendering Properties
+N_PIXEL_TOLERANCE = 1
+N_CULLING = 2
+N_DISPLAY = 3
+N_ERRORCHECKING = 4
+N_SUBDIVISIONS = 5
+N_S_STEPS = 6
+N_T_STEPS = 7
+N_TILES = 8
+
+N_SHADED = 1.0
+
+# ---------------------------------------------------------------------------
+# FLAGS FOR NURBS SURFACES AND CURVES
+#
+# Bit: 9876 5432 1 0
+# |tttt|nnnn|f|r| : r - 1 bit = 1 if rational coordinate exists
+# : f - 1 bit = 1 if rational coordinate is before rest
+# : = 0 if rational coordinate is after rest
+# : nnnn - 4 bits for number of coordinates
+# : tttt - 4 bits for type of data (color, position, etc.)
+#
+# NURBS data type
+# N_T_ST 0 parametric space data
+# N_T_XYZ 1 model space data
+#
+# rational or non-rational data and position in memory
+# N_NONRATIONAL 0 non-rational data
+# N_RATAFTER 1 rational data with rat coord after rest
+# N_RATBEFORE 3 rational data with rat coord before rest
+#
+# N_MKFLAG(a,b,c) ((a<<6) | (b<<2) | c)
+#
+# ---------------------------------------------------------------------------
+#
+N_ST = 0x8 # N_MKFLAG( N_T_ST, 2, N_NONRATIONAL )
+N_STW = 0xd # N_MKFLAG( N_T_ST, 3, N_RATAFTER )
+N_WST = 0xf # N_MKFLAG( N_T_ST, 3, N_RATBEFORE )
+N_XYZ = 0x4c # N_MKFLAG( N_T_XYZ, 3, N_NONRATIONAL )
+N_XYZW = 0x51 # N_MKFLAG( N_T_XYZ, 4, N_RATAFTER )
+N_WXYZ = 0x53 # N_MKFLAG( N_T_XYZ, 4, N_RATBEFORE )
+
+#
+# END NURBS interface definitions
+#
+
+
+#
+# START lighting model defines
+#
+
+LMNULL = 0.0
+
+# MATRIX modes
+MSINGLE = 0
+MPROJECTION = 1
+MVIEWING = 2
+
+# LIGHT constants
+MAXLIGHTS = 8
+MAXRESTRICTIONS = 4
+
+# MATERIAL properties
+DEFMATERIAL = 0
+EMISSION = 1
+AMBIENT = 2
+DIFFUSE = 3
+SPECULAR = 4
+SHININESS = 5
+COLORINDEXES = 6
+ALPHA = 7
+
+# LIGHT properties
+DEFLIGHT = 100
+LCOLOR = 101
+POSITION = 102
+
+# LIGHTINGMODEL properties
+DEFLMODEL = 200
+LOCALVIEWER = 201
+ATTENUATION = 202
+
+# TARGET constants
+MATERIAL = 1000
+LIGHT0 = 1100
+LIGHT1 = 1101
+LIGHT2 = 1102
+LIGHT3 = 1103
+LIGHT4 = 1104
+LIGHT5 = 1105
+LIGHT6 = 1106
+LIGHT7 = 1107
+LMODEL = 1200
+
+# lmcolor modes
+LMC_COLOR = 0
+LMC_EMISSION = 1
+LMC_AMBIENT = 2
+LMC_DIFFUSE = 3
+LMC_SPECULAR = 4
+LMC_AD = 5
+LMC_NULL = 6
+
+#
+# END lighting model defines
+#
+
+
+#
+# START distributed graphics library defines
+#
+
+DGLSINK = 0 # sink connection
+DGLLOCAL = 1 # local connection
+DGLTSOCKET = 2 # tcp socket connection
+DGL4DDN = 3 # 4DDN (DECnet)
+
+#
+# END distributed graphics library defines
+#
diff --git a/Lib/plat-irix5/panel.py b/Lib/plat-irix5/panel.py
new file mode 100755
index 0000000..eb11508
--- /dev/null
+++ b/Lib/plat-irix5/panel.py
@@ -0,0 +1,281 @@
+# Module 'panel'
+#
+# Support for the Panel library.
+# Uses built-in module 'pnl'.
+# Applciations should use 'panel.function' instead of 'pnl.function';
+# most 'pnl' functions are transparently exported by 'panel',
+# but dopanel() is overridden and you have to use this version
+# if you want to use callbacks.
+
+
+import pnl
+
+
+debug = 0
+
+
+# Test if an object is a list.
+#
+def is_list(x):
+ return type(x) = type([])
+
+
+# Reverse a list.
+#
+def reverse(list):
+ res = []
+ for item in list:
+ res.insert(0, item)
+ return res
+
+
+# Get an attribute of a list, which may itself be another list.
+# Don't use 'prop' for name.
+#
+def getattrlist(list, name):
+ for item in list:
+ if item and is_list(item) and item[0] = name:
+ return item[1:]
+ return []
+
+
+# Get a property of a list, which may itself be another list.
+#
+def getproplist(list, name):
+ for item in list:
+ if item and is_list(item) and item[0] = 'prop':
+ if len(item) > 1 and item[1] = name:
+ return item[2:]
+ return []
+
+
+# Test if an actuator description contains the property 'end-of-group'
+#
+def is_endgroup(list):
+ x = getproplist(list, 'end-of-group')
+ return (x and x[0] = '#t')
+
+
+# Neatly display an actuator definition given as S-expression
+# the prefix string is printed before each line.
+#
+def show_actuator(prefix, a):
+ for item in a:
+ if not is_list(item):
+ print prefix, item
+ elif item and item[0] = 'al':
+ print prefix, 'Subactuator list:'
+ for a in item[1:]:
+ show_actuator(prefix + ' ', a)
+ elif len(item) = 2:
+ print prefix, item[0], '=>', item[1]
+ elif len(item) = 3 and item[0] = 'prop':
+ print prefix, 'Prop', item[1], '=>',
+ print item[2]
+ else:
+ print prefix, '?', item
+
+
+# Neatly display a panel.
+#
+def show_panel(prefix, p):
+ for item in p:
+ if not is_list(item):
+ print prefix, item
+ elif item and item[0] = 'al':
+ print prefix, 'Actuator list:'
+ for a in item[1:]:
+ show_actuator(prefix + ' ', a)
+ elif len(item) = 2:
+ print prefix, item[0], '=>', item[1]
+ elif len(item) = 3 and item[0] = 'prop':
+ print prefix, 'Prop', item[1], '=>',
+ print item[2]
+ else:
+ print prefix, '?', item
+
+
+# Exception raised by build_actuator or build_panel.
+#
+panel_error = 'panel error'
+
+
+# Dummy callback used to initialize the callbacks.
+#
+def dummy_callback(arg):
+ pass
+
+
+# Assign attributes to members of the target.
+# Attribute names in exclist are ignored.
+# The member name is the attribute name prefixed with the prefix.
+#
+def assign_members(target, attrlist, exclist, prefix):
+ for item in attrlist:
+ if is_list(item) and len(item) = 2 and item[0] not in exclist:
+ name, value = item[0], item[1]
+ ok = 1
+ if value[0] in '-0123456789':
+ value = eval(value)
+ elif value[0] = '"':
+ value = value[1:-1]
+ elif value = 'move-then-resize':
+ # Strange default set by Panel Editor...
+ ok = 0
+ else:
+ print 'unknown value', value, 'for', name
+ ok = 0
+ if ok:
+ lhs = 'target.' + prefix + name
+ stmt = lhs + '=' + `value`
+ if debug: print 'exec', stmt
+ try:
+ exec(stmt + '\n')
+ except KeyboardInterrupt: # Don't catch this!
+ raise KeyboardInterrupt
+ except:
+ print 'assign failed:', stmt
+
+
+# Build a real actuator from an actuator descriptior.
+# Return a pair (actuator, name).
+#
+def build_actuator(descr):
+ namelist = getattrlist(descr, 'name')
+ if namelist:
+ # Assume it is a string
+ actuatorname = namelist[0][1:-1]
+ else:
+ actuatorname = ''
+ type = descr[0]
+ if type[:4] = 'pnl_': type = type[4:]
+ act = pnl.mkact(type)
+ act.downfunc = act.activefunc = act.upfunc = dummy_callback
+ #
+ assign_members(act, descr[1:], ('al', 'data', 'name'), '')
+ #
+ # Treat actuator-specific data
+ #
+ datalist = getattrlist(descr, 'data')
+ prefix = ''
+ if type[-4:] = 'puck':
+ prefix = 'puck_'
+ elif type = 'mouse':
+ prefix = 'mouse_'
+ assign_members(act, datalist, (), prefix)
+ #
+ return act, actuatorname
+
+
+# Build all sub-actuators and add them to the super-actuator.
+# The super-actuator must already have been added to the panel.
+# Sub-actuators with defined names are added as members to the panel
+# so they can be referenced as p.name.
+#
+# Note: I have no idea how panel.endgroup() works when applied
+# to a sub-actuator.
+#
+def build_subactuators(panel, super_act, al):
+ #
+ # This is nearly the same loop as below in build_panel(),
+ # except a call is made to addsubact() instead of addact().
+ #
+ for a in al:
+ act, name = build_actuator(a)
+ act.addsubact(super_act)
+ if name:
+ stmt = 'panel.' + name + ' = act'
+ if debug: print 'exec', stmt
+ exec(stmt + '\n')
+ if is_endgroup(a):
+ panel.endgroup()
+ sub_al = getattrlist(a, 'al')
+ if sub_al:
+ build_subactuators(panel, act, sub_al)
+ #
+ # Fix the actuator to which whe just added subactuators.
+ # This can't hurt (I hope) and is needed for the scroll actuator.
+ #
+ super_act.fixact()
+
+
+# Build a real panel from a panel definition.
+# Return a panel object p, where for each named actuator a, p.name is a
+# reference to a.
+#
+def build_panel(descr):
+ #
+ # Sanity check
+ #
+ if (not descr) or descr[0] <> 'panel':
+ raise panel_error, 'panel description must start with "panel"'
+ #
+ if debug: show_panel('', descr)
+ #
+ # Create an empty panel
+ #
+ panel = pnl.mkpanel()
+ #
+ # Assign panel attributes
+ #
+ assign_members(panel, descr[1:], ('al'), '')
+ #
+ # Look for actuator list
+ #
+ al = getattrlist(descr, 'al')
+ #
+ # The order in which actuators are created is important
+ # because of the endgroup() operator.
+ # Unfortunately the Panel Editor outputs the actuator list
+ # in reverse order, so we reverse it here.
+ #
+ al = reverse(al)
+ #
+ for a in al:
+ act, name = build_actuator(a)
+ act.addact(panel)
+ if name:
+ stmt = 'panel.' + name + ' = act'
+ exec(stmt + '\n')
+ if is_endgroup(a):
+ panel.endgroup()
+ sub_al = getattrlist(a, 'al')
+ if sub_al:
+ build_subactuators(panel, act, sub_al)
+ #
+ return panel
+
+
+# Wrapper around pnl.dopanel() which calls call-back functions.
+#
+def my_dopanel():
+ # Extract only the first 4 elements to allow for future expansion
+ a, down, active, up = pnl.dopanel()[:4]
+ if down:
+ down.downfunc(down)
+ if active:
+ active.activefunc(active)
+ if up:
+ up.upfunc(up)
+ return a
+
+
+# Create one or more panels from a description file (S-expressions)
+# generated by the Panel Editor.
+#
+def defpanellist(file):
+ import parser
+ descrlist = parser.parse_file(open(file, 'r'))
+ panellist = []
+ for descr in descrlist:
+ panellist.append(build_panel(descr))
+ return panellist
+
+
+# Import everything from built-in method pnl, so the user can always
+# use panel.foo() instead of pnl.foo().
+# This gives *no* performance penalty once this module is imported.
+#
+from pnl import * # for export
+
+dopanel = my_dopanel # override pnl.dopanel
diff --git a/Lib/plat-irix5/panelparser.py b/Lib/plat-irix5/panelparser.py
new file mode 100755
index 0000000..9c9ee02
--- /dev/null
+++ b/Lib/plat-irix5/panelparser.py
@@ -0,0 +1,128 @@
+# Module 'parser'
+#
+# Parse S-expressions output by the Panel Editor
+# (which is written in Scheme so it can't help writing S-expressions).
+#
+# See notes at end of file.
+
+
+whitespace = ' \t\n'
+operators = '()\''
+separators = operators + whitespace + ';' + '"'
+
+
+# Tokenize a string.
+# Return a list of tokens (strings).
+#
+def tokenize_string(s):
+ tokens = []
+ while s:
+ c = s[:1]
+ if c in whitespace:
+ s = s[1:]
+ elif c = ';':
+ s = ''
+ elif c = '"':
+ n = len(s)
+ i = 1
+ while i < n:
+ c = s[i]
+ i = i+1
+ if c = '"': break
+ if c = '\\': i = i+1
+ tokens.append(s[:i])
+ s = s[i:]
+ elif c in operators:
+ tokens.append(c)
+ s = s[1:]
+ else:
+ n = len(s)
+ i = 1
+ while i < n:
+ if s[i] in separators: break
+ i = i+1
+ tokens.append(s[:i])
+ s = s[i:]
+ return tokens
+
+
+# Tokenize a whole file (given as file object, not as file name).
+# Return a list of tokens (strings).
+#
+def tokenize_file(fp):
+ tokens = []
+ while 1:
+ line = fp.readline()
+ if not line: break
+ tokens = tokens + tokenize_string(line)
+ return tokens
+
+
+# Exception raised by parse_exr.
+#
+syntax_error = 'syntax error'
+
+
+# Parse an S-expression.
+# Input is a list of tokens as returned by tokenize_*().
+# Return a pair (expr, tokens)
+# where expr is a list representing the s-expression,
+# and tokens contains the remaining tokens.
+# May raise syntax_error.
+#
+def parse_expr(tokens):
+ if (not tokens) or tokens[0] <> '(':
+ raise syntax_error, 'expected "("'
+ tokens = tokens[1:]
+ expr = []
+ while 1:
+ if not tokens:
+ raise syntax_error, 'missing ")"'
+ if tokens[0] = ')':
+ return expr, tokens[1:]
+ elif tokens[0] = '(':
+ subexpr, tokens = parse_expr(tokens)
+ expr.append(subexpr)
+ else:
+ expr.append(tokens[0])
+ tokens = tokens[1:]
+
+
+# Parse a file (given as file object, not as file name).
+# Return a list of parsed S-expressions found at the top level.
+#
+def parse_file(fp):
+ tokens = tokenize_file(fp)
+ exprlist = []
+ while tokens:
+ expr, tokens = parse_expr(tokens)
+ exprlist.append(expr)
+ return exprlist
+
+
+# EXAMPLE:
+#
+# The input
+# '(hip (hop hur-ray))'
+#
+# passed to tokenize_string() returns the token list
+# ['(', 'hip', '(', 'hop', 'hur-ray', ')', ')']
+#
+# When this is passed to parse_expr() it returns the expression
+# ['hip', ['hop', 'hur-ray']]
+# plus an empty token list (because there are no tokens left.
+#
+# When a file containing the example is passed to parse_file() it returns
+# a list whose only element is the output of parse_expr() above:
+# [['hip', ['hop', 'hur-ray']]]
+
+
+# TOKENIZING:
+#
+# Comments start with semicolon (;) and continue till the end of the line.
+#
+# Tokens are separated by whitespace, except the following characters
+# always form a separate token (outside strings):
+# ( ) '
+# Strings are enclosed in double quotes (") and backslash (\) is used
+# as escape character in strings.
diff --git a/Lib/poly.py b/Lib/poly.py
new file mode 100644
index 0000000..abac4c8
--- /dev/null
+++ b/Lib/poly.py
@@ -0,0 +1,55 @@
+# module 'poly' -- Polynomials
+
+# A polynomial is represented by a list of coefficients, e.g.,
+# [1, 10, 5] represents 1*x**0 + 10*x**1 + 5*x**2 (or 1 + 10x + 5x**2).
+# There is no way to suppress internal zeros; trailing zeros are
+# taken out by normalize().
+
+def normalize(p): # Strip unnecessary zero coefficients
+ n = len(p)
+ while p:
+ if p[n-1]: return p[:n]
+ n = n-1
+ return []
+
+def plus(a, b):
+ if len(a) < len(b): a, b = b, a # make sure a is the longest
+ res = a[:] # make a copy
+ for i in range(len(b)):
+ res[i] = res[i] + b[i]
+ return normalize(res)
+
+def minus(a, b):
+ if len(a) < len(b): a, b = b, a # make sure a is the longest
+ res = a[:] # make a copy
+ for i in range(len(b)):
+ res[i] = res[i] - b[i]
+ return normalize(res)
+
+def one(power, coeff): # Representation of coeff * x**power
+ res = []
+ for i in range(power): res.append(0)
+ return res + [coeff]
+
+def times(a, b):
+ res = []
+ for i in range(len(a)):
+ for j in range(len(b)):
+ res = plus(res, one(i+j, a[i]*b[j]))
+ return res
+
+def power(a, n): # Raise polynomial a to the positive integral power n
+ if n = 0: return [1]
+ if n = 1: return a
+ if n/2*2 = n:
+ b = power(a, n/2)
+ return times(b, b)
+ return times(power(a, n-1), a)
+
+def der(a): # First derivative
+ res = a[1:]
+ for i in range(len(res)):
+ res[i] = res[i] * (i+1)
+ return res
+
+# Computing a primitive function would require rational arithmetic...
diff --git a/Lib/posixpath.py b/Lib/posixpath.py
new file mode 100644
index 0000000..e314cb3
--- /dev/null
+++ b/Lib/posixpath.py
@@ -0,0 +1,124 @@
+# Module 'path' -- common operations on POSIX pathnames
+
+import posix
+
+
+# Intelligent pathname concatenation.
+# Inserts a '/' unless the first part is empty or already ends in '/'.
+# Ignores the first part altogether if the second part is absolute
+# (begins with '/').
+#
+def cat(a, b):
+ if b[:1] = '/': return b
+ if a = '' or a[-1:] = '/': return a + b
+ return a + '/' + b
+
+
+# Split a path in head (empty or ending in '/') and tail (no '/').
+# The tail will be empty if the path ends in '/'.
+#
+def split(p):
+ head, tail = '', ''
+ for c in p:
+ tail = tail + c
+ if c = '/':
+ head, tail = head + tail, ''
+ return head, tail
+
+
+# Return the tail (basename) part of a path.
+#
+def basename(p):
+ return split(p)[1]
+
+
+# Return the longest prefix of all list elements.
+#
+def commonprefix(m):
+ if not m: return ''
+ prefix = m[0]
+ for item in m:
+ for i in range(len(prefix)):
+ if prefix[:i+1] <> item[:i+1]:
+ prefix = prefix[:i]
+ if i = 0: return ''
+ break
+ return prefix
+
+
+# Does a file/directory exist?
+#
+def exists(path):
+ try:
+ st = posix.stat(path)
+ except posix.error:
+ return 0
+ return 1
+
+
+# Is a path a posix directory?
+#
+def isdir(path):
+ try:
+ st = posix.stat(path)
+ except posix.error:
+ return 0
+ return st[0] / 4096 = 4 # S_IFDIR
+
+
+# Is a path a symbolic link?
+# This will always return false on systems where posix.lstat doesn't exist.
+#
+def islink(path):
+ try:
+ st = posix.lstat(path)
+ except (posix.error, NameError):
+ return 0
+ return st[0] / 4096 = 10 # S_IFLNK
+
+
+_mounts = []
+
+def _getmounts():
+ import commands, string
+ mounts = []
+ data = commands.getoutput('/etc/mount')
+ lines = string.splitfields(data, '\n')
+ for line in lines:
+ words = string.split(line)
+ if len(words) >= 3 and words[1] = 'on':
+ mounts.append(words[2])
+ return mounts
+
+
+# Is a path a mount point?
+# This only works for normalized, absolute paths,
+# and only if the mount table as printed by /etc/mount is correct.
+# Sorry.
+#
+def ismount(path):
+ if not _mounts:
+ _mounts[:] = _getmounts()
+ return path in _mounts
+
+
+# Directory tree walk.
+# For each directory under top (including top itself),
+# func(arg, dirname, filenames) is called, where dirname
+# is the name of the directory and filenames is the list of
+# files (and subdirectories etc.) in the directory.
+# func may modify the filenames list, to implement a filter,
+# or to impose a different order of visiting.
+#
+def walk(top, func, arg):
+ try:
+ names = posix.listdir(top)
+ except posix.error:
+ return
+ func(arg, top, names)
+ exceptions = ('.', '..')
+ for name in names:
+ if name not in exceptions:
+ name = cat(top, name)
+ if isdir(name):
+ walk(name, func, arg)
diff --git a/Lib/rand.py b/Lib/rand.py
new file mode 100644
index 0000000..0616483
--- /dev/null
+++ b/Lib/rand.py
@@ -0,0 +1,12 @@
+# Module 'rand'
+
+import whrandom
+
+def srand(seed):
+ whrandom.seed(seed%256, seed/256%256, seed/65536%256)
+
+def rand():
+ return int(whrandom.random() * 32768.0) % 32768
+
+def choice(seq):
+ return seq[rand() % len(seq)]
diff --git a/Lib/shutil.py b/Lib/shutil.py
new file mode 100644
index 0000000..cf63396
--- /dev/null
+++ b/Lib/shutil.py
@@ -0,0 +1,70 @@
+# Module 'shutil' -- utility functions usable in a shell-like program
+
+import posix
+import path
+
+MODEBITS = 010000 # Lower 12 mode bits
+# Change this to 01000 (9 mode bits) to avoid copying setuid etc.
+
+# Copy data from src to dst
+#
+def copyfile(src, dst):
+ fsrc = open(src, 'r')
+ fdst = open(dst, 'w')
+ while 1:
+ buf = fsrc.read(16*1024)
+ if not buf: break
+ fdst.write(buf)
+
+# Copy mode bits from src to dst
+#
+def copymode(src, dst):
+ st = posix.stat(src)
+ mode = divmod(st[0], MODEBITS)[1]
+ posix.chmod(dst, mode)
+
+# Copy all stat info (mode bits, atime and mtime) from src to dst
+#
+def copystat(src, dst):
+ st = posix.stat(src)
+ mode = divmod(st[0], MODEBITS)[1]
+ posix.chmod(dst, mode)
+ posix.utimes(dst, st[7:9])
+
+# Copy data and mode bits ("cp src dst")
+#
+def copy(src, dst):
+ copyfile(src, dst)
+ copymode(src, dst)
+
+# Copy data and all stat info ("cp -p src dst")
+#
+def copy2(src, dst):
+ copyfile(src, dst)
+ copystat(src, dst)
+
+# Recursively copy a directory tree.
+# The destination must not already exist.
+#
+def copytree(src, dst):
+ names = posix.listdir(src)
+ posix.mkdir(dst, 0777)
+ dot_dotdot = '.', '..'
+ for name in names:
+ if name not in dot_dotdot:
+ srcname = path.cat(src, name)
+ dstname = path.cat(dst, name)
+ #print 'Copying', srcname, 'to', dstname
+ try:
+ #if path.islink(srcname):
+ # linkto = posix.readlink(srcname)
+ # posix.symlink(linkto, dstname)
+ #elif path.isdir(srcname):
+ if path.isdir(srcname):
+ copytree(srcname, dstname)
+ else:
+ copy2(srcname, dstname)
+ # XXX What about devices, sockets etc.?
+ except posix.error, why:
+ print 'Could not copy', srcname, 'to', dstname,
+ print '(', why[1], ')'
diff --git a/Lib/statcache.py b/Lib/statcache.py
new file mode 100644
index 0000000..eeb0ca4
--- /dev/null
+++ b/Lib/statcache.py
@@ -0,0 +1,90 @@
+# Module 'statcache'
+#
+# Maintain a cache of file stats.
+# There are functions to reset the cache or to selectively remove items.
+
+import posix
+
+
+# The cache.
+# Keys are pathnames, values are `posix.stat' outcomes.
+#
+cache = {}
+
+
+# Stat a file, possibly out of the cache.
+#
+def stat(path):
+ try:
+ return cache[path]
+ except RuntimeError:
+ pass
+ cache[path] = ret = posix.stat(path)
+ return ret
+
+
+# Reset the cache completely.
+# Hack: to reset a global variable, we import this module.
+#
+def reset():
+ import statcache
+ # Check that we really imported the same module
+ if cache is not statcache.cache:
+ raise 'sorry, statcache identity crisis'
+ statcache.cache = {}
+
+
+# Remove a given item from the cache, if it exists.
+#
+def forget(path):
+ try:
+ del cache[path]
+ except RuntimeError:
+ pass
+
+
+# Remove all pathnames with a given prefix.
+#
+def forget_prefix(prefix):
+ n = len(prefix)
+ for path in cache.keys():
+ if path[:n] = prefix:
+ del cache[path]
+
+
+# Forget about a directory and all entries in it, but not about
+# entries in subdirectories.
+#
+def forget_dir(prefix):
+ if prefix[-1:] = '/' and prefix <> '/':
+ prefix = prefix[:-1]
+ forget(prefix)
+ if prefix[-1:] <> '/':
+ prefix = prefix + '/'
+ n = len(prefix)
+ for path in cache.keys():
+ if path[:n] = prefix:
+ rest = path[n:]
+ if rest[-1:] = '/': rest = rest[:-1]
+ if '/' not in rest:
+ del cache[path]
+
+
+# Remove all pathnames except with a given prefix.
+# Normally used with prefix = '/' after a chdir().
+#
+def forget_except_prefix(prefix):
+ n = len(prefix)
+ for path in cache.keys():
+ if path[:n] <> prefix:
+ del cache[path]
+
+
+# Check for directory.
+#
+def isdir(path):
+ try:
+ # mode is st[0]; type is mode/4096; S_IFDIR is 4
+ return stat(path)[0] / 4096 = 4
+ except RuntimeError:
+ return 0
diff --git a/Lib/stdwin/anywin.py b/Lib/stdwin/anywin.py
new file mode 100755
index 0000000..bb7e865
--- /dev/null
+++ b/Lib/stdwin/anywin.py
@@ -0,0 +1,14 @@
+# Module 'anywin'
+# Open a file or directory in a window
+
+import dirwin
+import filewin
+import path
+
+def open(name):
+ print 'opening', name, '...'
+ if path.isdir(name):
+ w = dirwin.open(name)
+ else:
+ w = filewin.open(name)
+ return w
diff --git a/Lib/stdwin/dirwin.py b/Lib/stdwin/dirwin.py
new file mode 100755
index 0000000..5df85e7
--- /dev/null
+++ b/Lib/stdwin/dirwin.py
@@ -0,0 +1,28 @@
+# Module 'dirwin'
+
+# Directory windows, a subclass of listwin
+
+import gwin
+import listwin
+import anywin
+import path
+import dircache
+
+def action(w, string, i, detail):
+ (h, v), clicks, button, mask = detail
+ if clicks = 2:
+ name = path.cat(w.name, string)
+ try:
+ w = anywin.open(name)
+ except posix.error, why:
+ stdwin.message('Can\'t open ' + name + ': ' + why[1])
+
+def open(name):
+ name = path.cat(name, '')
+ list = dircache.opendir(name)[:]
+ list.sort()
+ dircache.annotate(name, list)
+ w = listwin.open(name, list)
+ w.name = name
+ w.action = action
+ return w
diff --git a/Lib/stdwin/filewin.py b/Lib/stdwin/filewin.py
new file mode 100755
index 0000000..1beb0b6
--- /dev/null
+++ b/Lib/stdwin/filewin.py
@@ -0,0 +1,31 @@
+# Module 'filewin'
+# File windows, a subclass of textwin (which is a subclass of gwin)
+
+import stdwin
+import textwin
+import path
+
+builtin_open = open
+
+def readfile(fn): # Return a string containing the file's contents
+ fp = builtin_open(fn, 'r')
+ a = ''
+ n = 8096
+ while 1:
+ b = fp.read(n)
+ if not b: break
+ a = a + b
+ return a
+
+
+# FILE WINDOW
+
+def open_readonly(fn): # Open a file window
+ w = textwin.open_readonly(fn, readfile(fn))
+ w.fn = fn
+ return w
+
+def open(fn): # Open a file window
+ w = textwin.open(fn, readfile(fn))
+ w.fn = fn
+ return w
diff --git a/Lib/stdwin/gwin.py b/Lib/stdwin/gwin.py
new file mode 100755
index 0000000..15aa432
--- /dev/null
+++ b/Lib/stdwin/gwin.py
@@ -0,0 +1,118 @@
+# Module 'gwin'
+# Generic stdwin windows
+
+# This is used as a base class from which to derive other window types.
+# The mainloop() function here is an event dispatcher for all window types.
+
+import stdwin
+import stdwinsupport
+
+S = stdwinsupport # Shorthand
+
+windows = [] # List of open windows
+
+
+# Open a window
+
+def open(title): # Open a generic window
+ w = stdwin.open(title)
+ stdwin.setdefwinsize(0, 0)
+ # Set default event handlers
+ w.draw = nop
+ w.char = nop
+ w.mdown = nop
+ w.mmove = nop
+ w.mup = nop
+ w.m2down = m2down
+ w.m2up = m2up
+ w.size = nop
+ w.move = nop
+ w.activate = w.deactivate = nop
+ w.timer = nop
+ # default command handlers
+ w.close = close
+ w.tab = tab
+ w.enter = enter
+ w.backspace = backspace
+ w.arrow = arrow
+ w.kleft = w.kup = w.kright = w.kdown = nop
+ windows.append(w)
+ return w
+
+
+# Generic event dispatching
+
+def mainloop(): # Handle events until no windows left
+ while windows:
+ treatevent(stdwin.getevent())
+
+def treatevent(e): # Handle a stdwin event
+ type, w, detail = e
+ if type = S.we_draw:
+ w.draw(w, detail)
+ elif type = S.we_menu:
+ m, item = detail
+ m.action[item](w, m, item)
+ elif type = S.we_command:
+ treatcommand(w, detail)
+ elif type = S.we_char:
+ w.char(w, detail)
+ elif type = S.we_mouse_down:
+ if detail[1] > 1: w.m2down(w, detail)
+ else: w.mdown(w, detail)
+ elif type = S.we_mouse_move:
+ w.mmove(w, detail)
+ elif type = S.we_mouse_up:
+ if detail[1] > 1: w.m2up(w, detail)
+ else: w.mup(w, detail)
+ elif type = S.we_size:
+ w.size(w, w.getwinsize())
+ elif type = S.we_activate:
+ w.activate(w)
+ elif type = S.we_deactivate:
+ w.deactivate(w)
+ elif type = S.we_move:
+ w.move(w)
+ elif type = S.we_timer:
+ w.timer(w)
+
+def treatcommand(w, type): # Handle a we_command event
+ if type = S.wc_close:
+ w.close(w)
+ elif type = S.wc_return:
+ w.enter(w)
+ elif type = S.wc_tab:
+ w.tab(w)
+ elif type = S.wc_backspace:
+ w.backspace(w)
+ elif type in (S.wc_left, S.wc_up, S.wc_right, S.wc_down):
+ w.arrow(w, type)
+
+
+# Methods
+
+def close(w): # Close method
+ for i in range(len(windows)):
+ if windows[i] is w:
+ del windows[i]
+ break
+
+def arrow(w, detail): # Arrow key method
+ if detail = S.wc_left:
+ w.kleft(w)
+ elif detail = S.wc_up:
+ w.kup(w)
+ elif detail = S.wc_right:
+ w.kright(w)
+ elif detail = S.wc_down:
+ w.kdown(w)
+
+
+# Trivial methods
+
+def tab(w): w.char(w, '\t')
+def enter(w): w.char(w, '\n') # 'return' is a Python reserved word
+def backspace(w): w.char(w, '\b')
+def m2down(w, detail): w.mdown(w, detail)
+def m2up(w, detail): w.mup(w, detail)
+def nop(args): pass
diff --git a/Lib/stdwin/listwin.py b/Lib/stdwin/listwin.py
new file mode 100755
index 0000000..9480a81
--- /dev/null
+++ b/Lib/stdwin/listwin.py
@@ -0,0 +1,47 @@
+# Module 'listwin'
+# List windows, a subclass of gwin
+
+import gwin
+import stdwin
+
+def maxlinewidth(a): # Compute maximum textwidth of lines in a sequence
+ max = 0
+ for line in a:
+ width = stdwin.textwidth(line)
+ if width > max: max = width
+ return max
+
+def action(w, string, i, detail): # Default item selection method
+ pass
+
+def mup(w, detail): # Mouse up method
+ (h, v), clicks, button, mask = detail
+ i = divmod(v, w.lineheight)[0]
+ if 0 <= i < len(w.data):
+ w.action(w, w.data[i], i, detail)
+
+def draw(w, ((left, top), (right, bottom))): # Text window draw method
+ data = w.data
+ d = w.begindrawing()
+ lh = w.lineheight
+ itop = top/lh
+ ibot = (bottom-1)/lh + 1
+ if itop < 0: itop = 0
+ if ibot > len(data): ibot = len(data)
+ for i in range(itop, ibot): d.text((0, i*lh), data[i])
+
+def open(title, data): # Display a list of texts in a window
+ lineheight = stdwin.lineheight()
+ h, v = maxlinewidth(data), len(data)*lineheight
+ h0, v0 = h + stdwin.textwidth(' '), v + lineheight
+ if h0 > stdwin.textwidth(' ')*80: h0 = 0
+ if v0 > stdwin.lineheight()*24: v0 = 0
+ stdwin.setdefwinsize(h0, v0)
+ w = gwin.open(title)
+ w.setdocsize(h, v)
+ w.lineheight = lineheight
+ w.data = data
+ w.draw = draw
+ w.action = action
+ w.mup = mup
+ return w
diff --git a/Lib/stdwin/rect.py b/Lib/stdwin/rect.py
new file mode 100755
index 0000000..c044b9f
--- /dev/null
+++ b/Lib/stdwin/rect.py
@@ -0,0 +1,87 @@
+# Module 'rect'.
+#
+# Operations on rectangles.
+# There is some normalization: all results return the object 'empty'
+# if their result would contain no points.
+
+
+# Exception.
+#
+error = 'rect.error'
+
+
+# The empty rectangle.
+#
+empty = (0, 0), (0, 0)
+
+
+# Check if a rectangle is empty.
+#
+def is_empty((left, top), (right, bottom)):
+ return left >= right or top >= bottom
+
+
+# Compute the intersection or two or more rectangles.
+# This works with a list or tuple argument.
+#
+def intersect(list):
+ if not list: raise error, 'intersect called with empty list'
+ if is_empty(list[0]): return empty
+ (left, top), (right, bottom) = list[0]
+ for rect in list[1:]:
+ if not is_empty(rect):
+ (l, t), (r, b) = rect
+ if left < l: left = l
+ if top < t: top = t
+ if right > r: right = r
+ if bottom > b: bottom = b
+ if is_empty((left, top), (right, bottom)):
+ return empty
+ return (left, top), (right, bottom)
+
+
+# Compute the smallest rectangle containing all given rectangles.
+# This works with a list or tuple argument.
+#
+def union(list):
+ (left, top), (right, bottom) = empty
+ for (l, t), (r, b) in list[1:]:
+ if not is_empty((l, t), (r, b)):
+ if l < left: left = l
+ if t < top: top = t
+ if r > right: right = r
+ if b > bottom: bottom = b
+ res = (left, top), (right, bottom)
+ if is_empty(res):
+ return empty
+ return res
+
+
+# Check if a point is in a rectangle.
+#
+def pointinrect((h, v), ((left, top), (right, bottom))):
+ return left <= h < right and top <= v < bottom
+
+
+# Return a rectangle that is dh, dv inside another
+#
+def inset(((left, top), (right, bottom)), (dh, dv)):
+ left = left + dh
+ top = top + dv
+ right = right - dh
+ bottom = bottom - dv
+ r = (left, top), (right, bottom)
+ if is_empty(r):
+ return empty
+ else:
+ return r
+
+
+# Conversions between rectangles and 'geometry tuples',
+# given as origin (h, v) and dimensions (width, height).
+#
+def rect2geom((left, top), (right, bottom)):
+ return (left, top), (right-left, bottom-top)
+
+def geom2rect((h, v), (width, height)):
+ return (h, v), (h+width, v+height)
diff --git a/Lib/stdwin/stdwinevents.py b/Lib/stdwin/stdwinevents.py
new file mode 100755
index 0000000..889dd95
--- /dev/null
+++ b/Lib/stdwin/stdwinevents.py
@@ -0,0 +1,36 @@
+# Module 'stdwinevents' -- Constants for stdwin event types
+#
+# Suggested usage:
+# from stdwinevents import *
+
+# The function stdwin.getevent() returns a tuple containing:
+# (type, window, detail)
+# where detail may be <no value> or a value depending on type, see below:
+
+# Values for type:
+
+WE_NULL = 0 # not reported -- means 'no event' internally
+WE_ACTIVATE = 1 # detail is <no object>
+WE_CHAR = 2 # detail is the character
+WE_COMMAND = 3 # detail is one of the WC_* constants below
+WE_MOUSE_DOWN = 4 # detail is ((h, v), clicks, button, mask)
+WE_MOUSE_MOVE = 5 # ditto
+WE_MOUSE_UP = 6 # ditto
+WE_MENU = 7 # detail is (menu, item)
+WE_SIZE = 8 # detail is (width, height) [???]
+WE_MOVE = 9 # not reported -- reserved for future use
+WE_DRAW = 10 # detail is ((left, top), (right, bottom))
+WE_TIMER = 11 # detail is <no object>
+WE_DEACTIVATE = 12 # detail is <no object>
+
+# Values for detail when type is WE_COMMAND:
+
+WC_CLOSE = 1 # user hit close box
+WC_LEFT = 2 # left arrow key
+WC_RIGHT = 3 # right arrow key
+WC_UP = 4 # up arrow key
+WC_DOWN = 5 # down arrow key
+WC_CANCEL = 6 # not reported -- turned into KeyboardInterrupt
+WC_BACKSPACE = 7 # backspace key
+WC_TAB = 8 # tab key
+WC_RETURN = 9 # return or enter key
diff --git a/Lib/stdwin/tablewin.py b/Lib/stdwin/tablewin.py
new file mode 100755
index 0000000..05a954e
--- /dev/null
+++ b/Lib/stdwin/tablewin.py
@@ -0,0 +1,237 @@
+# Module 'tablewin'
+
+# Display a table, with per-item actions:
+
+# A1 | A2 | A3 | .... | AN
+# B1 | B2 | B3 | .... | BN
+# C1 | C2 | C3 | .... | CN
+# .. | .. | .. | .... | ..
+# Z1 | Z2 | Z3 | .... | ZN
+
+# Not all columns need to have the same length.
+# The data structure is a list of columns;
+# each column is a list of items.
+# Each item is a pair of a string and an action procedure.
+# The first item may be a column title.
+
+import stdwin
+import gwin
+
+def open(title, data): # Public function to open a table window
+ #
+ # Set geometry parameters (one day, these may be changeable)
+ #
+ margin = stdwin.textwidth(' ')
+ lineheight = stdwin.lineheight()
+ #
+ # Geometry calculations
+ #
+ colstarts = [0]
+ totwidth = 0
+ maxrows = 0
+ for coldata in data:
+ # Height calculations
+ rows = len(coldata)
+ if rows > maxrows: maxrows = rows
+ # Width calculations
+ width = colwidth(coldata) + margin
+ totwidth = totwidth + width
+ colstarts.append(totwidth)
+ #
+ # Calculate document and window height
+ #
+ docwidth, docheight = totwidth, maxrows*lineheight
+ winwidth, winheight = docwidth, docheight
+ if winwidth > stdwin.textwidth('n')*100: winwidth = 0
+ if winheight > stdwin.lineheight()*30: winheight = 0
+ #
+ # Create the window
+ #
+ stdwin.setdefwinsize(winwidth, winheight)
+ w = gwin.open(title)
+ #
+ # Set properties and override methods
+ #
+ w.data = data
+ w.margin = margin
+ w.lineheight = lineheight
+ w.colstarts = colstarts
+ w.totwidth = totwidth
+ w.maxrows = maxrows
+ w.selection = (-1, -1)
+ w.lastselection = (-1, -1)
+ w.selshown = 0
+ w.setdocsize(docwidth, docheight)
+ w.draw = draw
+ w.mup = mup
+ w.arrow = arrow
+ #
+ # Return
+ #
+ return w
+
+def update(w, data): # Change the data
+ #
+ # Hide selection
+ #
+ hidesel(w, w.begindrawing())
+ #
+ # Get old geometry parameters
+ #
+ margin = w.margin
+ lineheight = w.lineheight
+ #
+ # Geometry calculations
+ #
+ colstarts = [0]
+ totwidth = 0
+ maxrows = 0
+ for coldata in data:
+ # Height calculations
+ rows = len(coldata)
+ if rows > maxrows: maxrows = rows
+ # Width calculations
+ width = colwidth(coldata) + margin
+ totwidth = totwidth + width
+ colstarts.append(totwidth)
+ #
+ # Calculate document and window height
+ #
+ docwidth, docheight = totwidth, maxrows*lineheight
+ #
+ # Set changed properties and change window size
+ #
+ w.data = data
+ w.colstarts = colstarts
+ w.totwidth = totwidth
+ w.maxrows = maxrows
+ w.change((0, 0), (10000, 10000))
+ w.setdocsize(docwidth, docheight)
+ w.change((0, 0), (docwidth, docheight))
+ #
+ # Show selection, or forget it if out of range
+ #
+ showsel(w, w.begindrawing())
+ if not w.selshown: w.selection = (-1, -1)
+
+def colwidth(coldata): # Subroutine to calculate column width
+ maxwidth = 0
+ for string, action in coldata:
+ width = stdwin.textwidth(string)
+ if width > maxwidth: maxwidth = width
+ return maxwidth
+
+def draw(w, ((left, top), (right, bottom))): # Draw method
+ ileft = whichcol(w, left)
+ iright = whichcol(w, right-1) + 1
+ if iright > len(w.data): iright = len(w.data)
+ itop = divmod(top, w.lineheight)[0]
+ if itop < 0: itop = 0
+ ibottom, remainder = divmod(bottom, w.lineheight)
+ if remainder: ibottom = ibottom + 1
+ d = w.begindrawing()
+ if ileft <= w.selection[0] < iright:
+ if itop <= w.selection[1] < ibottom:
+ hidesel(w, d)
+ d.erase((left, top), (right, bottom))
+ for i in range(ileft, iright):
+ col = w.data[i]
+ jbottom = len(col)
+ if ibottom < jbottom: jbottom = ibottom
+ h = w.colstarts[i]
+ v = itop * w.lineheight
+ for j in range(itop, jbottom):
+ string, action = col[j]
+ d.text((h, v), string)
+ v = v + w.lineheight
+ showsel(w, d)
+
+def mup(w, detail): # Mouse up method
+ (h, v), nclicks, button, mask = detail
+ icol = whichcol(w, h)
+ if 0 <= icol < len(w.data):
+ irow = divmod(v, w.lineheight)[0]
+ col = w.data[icol]
+ if 0 <= irow < len(col):
+ string, action = col[irow]
+ action(w, string, (icol, irow), detail)
+
+def whichcol(w, h): # Return column number (may be >= len(w.data))
+ for icol in range(0, len(w.data)):
+ if h < w.colstarts[icol+1]:
+ return icol
+ return len(w.data)
+
+def arrow(w, type):
+ import stdwinsupport
+ S = stdwinsupport
+ if type = S.wc_left:
+ incr = -1, 0
+ elif type = S.wc_up:
+ incr = 0, -1
+ elif type = S.wc_right:
+ incr = 1, 0
+ elif type = S.wc_down:
+ incr = 0, 1
+ else:
+ return
+ icol, irow = w.lastselection
+ icol = icol + incr[0]
+ if icol < 0: icol = len(w.data)-1
+ if icol >= len(w.data): icol = 0
+ if 0 <= icol < len(w.data):
+ irow = irow + incr[1]
+ if irow < 0: irow = len(w.data[icol]) - 1
+ if irow >= len(w.data[icol]): irow = 0
+ else:
+ irow = 0
+ if 0 <= icol < len(w.data) and 0 <= irow < len(w.data[icol]):
+ w.lastselection = icol, irow
+ string, action = w.data[icol][irow]
+ detail = (0, 0), 1, 1, 1
+ action(w, string, (icol, irow), detail)
+
+
+# Selection management
+# TO DO: allow multiple selected entries
+
+def select(w, selection): # Public function to set the item selection
+ d = w.begindrawing()
+ hidesel(w, d)
+ w.selection = selection
+ showsel(w, d)
+ if w.selshown: lastselection = selection
+
+def hidesel(w, d): # Hide the selection, if shown
+ if w.selshown: invertsel(w, d)
+
+def showsel(w, d): # Show the selection, if hidden
+ if not w.selshown: invertsel(w, d)
+
+def invertsel(w, d): # Invert the selection, if valid
+ icol, irow = w.selection
+ if 0 <= icol < len(w.data) and 0 <= irow < len(w.data[icol]):
+ left = w.colstarts[icol]
+ right = w.colstarts[icol+1]
+ top = irow * w.lineheight
+ bottom = (irow+1) * w.lineheight
+ d.invert((left, top), (right, bottom))
+ w.selshown = (not w.selshown)
+
+
+# Demonstration
+
+def demo_action(w, string, (icol, irow), detail): # Action function for demo
+ select(w, (irow, icol))
+
+def demo(): # Demonstration
+ da = demo_action # shorthand
+ col0 = [('a1', da), ('bbb1', da), ('c1', da)]
+ col1 = [('a2', da), ('bbb2', da)]
+ col2 = [('a3', da), ('b3', da), ('c3', da), ('d4', da), ('d5', da)]
+ col3 = []
+ for i in range(1, 31): col3.append('xxx' + `i`, da)
+ data = [col0, col1, col2, col3]
+ w = open('tablewin.demo', data)
+ gwin.mainloop()
+ return w
diff --git a/Lib/stdwin/textwin.py b/Lib/stdwin/textwin.py
new file mode 100755
index 0000000..2631ca4
--- /dev/null
+++ b/Lib/stdwin/textwin.py
@@ -0,0 +1,119 @@
+# Module 'textwin'
+
+# Text windows, a subclass of gwin
+
+import stdwin
+import stdwinsupport
+import gwin
+
+S = stdwinsupport # Shorthand
+
+
+def fixsize(w):
+ docwidth, docheight = w.text.getrect()[1]
+ winheight = w.getwinsize()[1]
+ if winheight > docheight: docheight = winheight
+ w.setdocsize(0, docheight)
+ fixeditmenu(w)
+
+def cut(w, m, id):
+ s = w.text.getfocustext()
+ if s:
+ stdwin.setcutbuffer(s)
+ w.text.replace('')
+ fixsize(w)
+
+def copy(w, m, id):
+ s = w.text.getfocustext()
+ if s:
+ stdwin.setcutbuffer(s)
+ fixeditmenu(w)
+
+def paste(w, m, id):
+ w.text.replace(stdwin.getcutbuffer())
+ fixsize(w)
+
+def addeditmenu(w):
+ m = w.editmenu = w.menucreate('Edit')
+ m.action = []
+ m.additem('Cut', 'X')
+ m.action.append(cut)
+ m.additem('Copy', 'C')
+ m.action.append(copy)
+ m.additem('Paste', 'V')
+ m.action.append(paste)
+
+def fixeditmenu(w):
+ m = w.editmenu
+ f = w.text.getfocus()
+ can_copy = (f[0] < f[1])
+ m.enable(1, can_copy)
+ if not w.readonly:
+ m.enable(0, can_copy)
+ m.enable(2, (stdwin.getcutbuffer() <> ''))
+
+def draw(w, area): # Draw method
+ w.text.draw(area)
+
+def size(w, newsize): # Size method
+ w.text.move((0, 0), newsize)
+ fixsize(w)
+
+def close(w): # Close method
+ del w.text # Break circular ref
+ gwin.close(w)
+
+def char(w, c): # Char method
+ w.text.replace(c)
+ fixsize(w)
+
+def backspace(w): # Backspace method
+ void = w.text.event(S.we_command, w, S.wc_backspace)
+ fixsize(w)
+
+def arrow(w, detail): # Arrow method
+ w.text.arrow(detail)
+ fixeditmenu(w)
+
+def mdown(w, detail): # Mouse down method
+ void = w.text.event(S.we_mouse_down, w, detail)
+ fixeditmenu(w)
+
+def mmove(w, detail): # Mouse move method
+ void = w.text.event(S.we_mouse_move, w, detail)
+
+def mup(w, detail): # Mouse up method
+ void = w.text.event(S.we_mouse_up, w, detail)
+ fixeditmenu(w)
+
+def activate(w): # Activate method
+ fixeditmenu(w)
+
+def open(title, str): # Display a string in a window
+ w = gwin.open(title)
+ w.readonly = 0
+ w.text = w.textcreate((0, 0), w.getwinsize())
+ w.text.replace(str)
+ w.text.setfocus(0, 0)
+ addeditmenu(w)
+ fixsize(w)
+ w.draw = draw
+ w.size = size
+ w.close = close
+ w.mdown = mdown
+ w.mmove = mmove
+ w.mup = mup
+ w.char = char
+ w.backspace = backspace
+ w.arrow = arrow
+ w.activate = activate
+ return w
+
+def open_readonly(title, str): # Same with char input disabled
+ w = open(title, str)
+ w.readonly = 1
+ w.char = w.backspace = gwin.nop
+ # Disable Cut and Paste menu item; leave Copy alone
+ w.editmenu.enable(0, 0)
+ w.editmenu.enable(2, 0)
+ return w
diff --git a/Lib/string.py b/Lib/string.py
new file mode 100644
index 0000000..2a4feae
--- /dev/null
+++ b/Lib/string.py
@@ -0,0 +1,129 @@
+# module 'string' -- A collection of string operations
+
+# XXX Some of these operations are incredibly slow and should be built in
+
+# Some strings for ctype-style character classification
+whitespace = ' \t\n'
+lowercase = 'abcdefghijklmnopqrstuvwxyz'
+uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+letters = lowercase + uppercase
+digits = '0123456789'
+hexdigits = digits + 'abcdef' + 'ABCDEF'
+octdigits = '01234567'
+
+# Case conversion helpers
+_caseswap = {}
+for i in range(26):
+ _caseswap[lowercase[i]] = uppercase[i]
+ _caseswap[uppercase[i]] = lowercase[i]
+del i
+
+# convert UPPER CASE letters to lower case
+def lower(s):
+ res = ''
+ for c in s:
+ if 'A' <= c <= 'Z': c = _caseswap[c]
+ res = res + c
+ return res
+
+# Convert lower case letters to UPPER CASE
+def upper(s):
+ res = ''
+ for c in s:
+ if 'a' <= c <= 'z': c = _caseswap[c]
+ res = res + c
+ return res
+
+# Swap lower case letters and UPPER CASE
+def swapcase(s):
+ res = ''
+ for c in s:
+ if 'a' <= c <= 'z' or 'A' <= c <= 'Z': c = _caseswap[c]
+ res = res + c
+ return res
+
+# Strip leading and trailing tabs and spaces
+def strip(s):
+ i, j = 0, len(s)
+ while i < j and s[i] in whitespace: i = i+1
+ while i < j and s[j-1] in whitespace: j = j-1
+ return s[i:j]
+
+# Split a string into a list of space/tab-separated words
+# NB: split(s) is NOT the same as splitfields(s, ' ')!
+def split(s):
+ res = []
+ i, n = 0, len(s)
+ while i < n:
+ while i < n and s[i] in whitespace: i = i+1
+ if i = n: break
+ j = i
+ while j < n and s[j] not in whitespace: j = j+1
+ res.append(s[i:j])
+ i = j
+ return res
+
+# Split a list into fields separated by a given string
+# NB: splitfields(s, ' ') is NOT the same as split(s)!
+def splitfields(s, sep):
+ res = []
+ ns = len(s)
+ nsep = len(sep)
+ i = j = 0
+ while j+nsep <= ns:
+ if s[j:j+nsep] = sep:
+ res.append(s[i:j])
+ i = j = j + nsep
+ else:
+ j = j + 1
+ res.append(s[i:])
+ return res
+
+# Find substring
+index_error = 'substring not found in string.index'
+def index(s, sub):
+ n = len(sub)
+ for i in range(len(s) - n):
+ if sub = s[i:i+n]: return i
+ raise index_error, (s, sub)
+
+# Convert string to integer
+atoi_error = 'non-numeric argument to string.atoi'
+def atoi(str):
+ s = str
+ if s[:1] in '+-': s = s[1:]
+ if not s: raise atoi_error, str
+ for c in s:
+ if c not in digits: raise atoi_error, str
+ return eval(str)
+
+# Left-justify a string
+def ljust(s, width):
+ n = len(s)
+ if n >= width: return s
+ return s + ' '*(width-n)
+
+# Right-justify a string
+def rjust(s, width):
+ n = len(s)
+ if n >= width: return s
+ return ' '*(width-n) + s
+
+# Center a string
+def center(s, width):
+ n = len(s)
+ if n >= width: return s
+ return ' '*((width-n)/2) + s + ' '*(width -(width-n)/2)
+
+# Zero-fill a number, e.g., (12, 3) --> '012' and (-3, 3) --> '-03'
+# Decadent feature: the argument may be a string or a number
+# (Use of this is deprecated; it should be a string as with ljust c.s.)
+def zfill(x, width):
+ if type(x) = type(''): s = x
+ else: s = `x`
+ n = len(s)
+ if n >= width: return s
+ sign = ''
+ if s[0] = '-':
+ sign, s = '-', s[1:]
+ return sign + '0'*(width-n) + s
diff --git a/Lib/stringold.py b/Lib/stringold.py
new file mode 100644
index 0000000..2a4feae
--- /dev/null
+++ b/Lib/stringold.py
@@ -0,0 +1,129 @@
+# module 'string' -- A collection of string operations
+
+# XXX Some of these operations are incredibly slow and should be built in
+
+# Some strings for ctype-style character classification
+whitespace = ' \t\n'
+lowercase = 'abcdefghijklmnopqrstuvwxyz'
+uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+letters = lowercase + uppercase
+digits = '0123456789'
+hexdigits = digits + 'abcdef' + 'ABCDEF'
+octdigits = '01234567'
+
+# Case conversion helpers
+_caseswap = {}
+for i in range(26):
+ _caseswap[lowercase[i]] = uppercase[i]
+ _caseswap[uppercase[i]] = lowercase[i]
+del i
+
+# convert UPPER CASE letters to lower case
+def lower(s):
+ res = ''
+ for c in s:
+ if 'A' <= c <= 'Z': c = _caseswap[c]
+ res = res + c
+ return res
+
+# Convert lower case letters to UPPER CASE
+def upper(s):
+ res = ''
+ for c in s:
+ if 'a' <= c <= 'z': c = _caseswap[c]
+ res = res + c
+ return res
+
+# Swap lower case letters and UPPER CASE
+def swapcase(s):
+ res = ''
+ for c in s:
+ if 'a' <= c <= 'z' or 'A' <= c <= 'Z': c = _caseswap[c]
+ res = res + c
+ return res
+
+# Strip leading and trailing tabs and spaces
+def strip(s):
+ i, j = 0, len(s)
+ while i < j and s[i] in whitespace: i = i+1
+ while i < j and s[j-1] in whitespace: j = j-1
+ return s[i:j]
+
+# Split a string into a list of space/tab-separated words
+# NB: split(s) is NOT the same as splitfields(s, ' ')!
+def split(s):
+ res = []
+ i, n = 0, len(s)
+ while i < n:
+ while i < n and s[i] in whitespace: i = i+1
+ if i = n: break
+ j = i
+ while j < n and s[j] not in whitespace: j = j+1
+ res.append(s[i:j])
+ i = j
+ return res
+
+# Split a list into fields separated by a given string
+# NB: splitfields(s, ' ') is NOT the same as split(s)!
+def splitfields(s, sep):
+ res = []
+ ns = len(s)
+ nsep = len(sep)
+ i = j = 0
+ while j+nsep <= ns:
+ if s[j:j+nsep] = sep:
+ res.append(s[i:j])
+ i = j = j + nsep
+ else:
+ j = j + 1
+ res.append(s[i:])
+ return res
+
+# Find substring
+index_error = 'substring not found in string.index'
+def index(s, sub):
+ n = len(sub)
+ for i in range(len(s) - n):
+ if sub = s[i:i+n]: return i
+ raise index_error, (s, sub)
+
+# Convert string to integer
+atoi_error = 'non-numeric argument to string.atoi'
+def atoi(str):
+ s = str
+ if s[:1] in '+-': s = s[1:]
+ if not s: raise atoi_error, str
+ for c in s:
+ if c not in digits: raise atoi_error, str
+ return eval(str)
+
+# Left-justify a string
+def ljust(s, width):
+ n = len(s)
+ if n >= width: return s
+ return s + ' '*(width-n)
+
+# Right-justify a string
+def rjust(s, width):
+ n = len(s)
+ if n >= width: return s
+ return ' '*(width-n) + s
+
+# Center a string
+def center(s, width):
+ n = len(s)
+ if n >= width: return s
+ return ' '*((width-n)/2) + s + ' '*(width -(width-n)/2)
+
+# Zero-fill a number, e.g., (12, 3) --> '012' and (-3, 3) --> '-03'
+# Decadent feature: the argument may be a string or a number
+# (Use of this is deprecated; it should be a string as with ljust c.s.)
+def zfill(x, width):
+ if type(x) = type(''): s = x
+ else: s = `x`
+ n = len(s)
+ if n >= width: return s
+ sign = ''
+ if s[0] = '-':
+ sign, s = '-', s[1:]
+ return sign + '0'*(width-n) + s
diff --git a/Lib/util.py b/Lib/util.py
new file mode 100644
index 0000000..dc67686
--- /dev/null
+++ b/Lib/util.py
@@ -0,0 +1,9 @@
+# Module 'util' -- some useful functions that dont fit elsewhere
+
+# Remove an item from a list at most once
+#
+def remove(item, list):
+ for i in range(len(list)):
+ if list[i] = item:
+ del list[i]
+ break
diff --git a/Lib/whrandom.py b/Lib/whrandom.py
new file mode 100644
index 0000000..2ce5f8f
--- /dev/null
+++ b/Lib/whrandom.py
@@ -0,0 +1,74 @@
+# WICHMANN-HILL RANDOM NUMBER GENERATOR
+#
+# Wichmann, B. A. & Hill, I. D. (1982)
+# Algorithm AS 183:
+# An efficient and portable pseudo-random number generator
+# Applied Statistics 31 (1982) 188-190
+#
+# see also:
+# Correction to Algorithm AS 183
+# Applied Statistics 33 (1984) 123
+#
+# McLeod, A. I. (1985)
+# A remark on Algorithm AS 183
+# Applied Statistics 34 (1985),198-200
+#
+#
+# USE:
+# whrandom.random() yields double precision random numbers
+# uniformly distributed between 0 and 1.
+#
+# whrandom.seed() must be called before whrandom.random()
+# to seed the generator
+
+
+# Translated by Guido van Rossum from C source provided by
+# Adrian Baddeley.
+
+
+# The seed
+#
+_seed = [0, 0, 0]
+
+
+# Set the seed
+#
+def seed(x, y, z):
+ _seed[:] = [x, y, z]
+
+
+# Return the next random number in the range [0.0 .. 1.0)
+#
+def random():
+ from math import floor # floor() function
+ #
+ [x, y, z] = _seed
+ x = 171 * (x % 177) - 2 * (x/177)
+ y = 172 * (y % 176) - 35 * (y/176)
+ z = 170 * (z % 178) - 63 * (z/178)
+ #
+ if x < 0: x = x + 30269
+ if y < 0: y = y + 30307
+ if z < 0: z = z + 30323
+ #
+ _seed[:] = [x, y, z]
+ #
+ term = float(x)/30269.0 + float(y)/30307.0 + float(z)/30323.0
+ rand = term - floor(term)
+ #
+ if rand >= 1.0: rand = 0.0 # floor() inaccuracy?
+ #
+ return rand
+
+
+# Initialize from the current time
+#
+def init():
+ import time
+ t = time.time()
+ seed(t%256, t/256%256, t/65536%256)
+
+
+# Make sure the generator is preset to a nonzero value
+#
+init()