Initial revision
This commit is contained in:
parent
df79a1ee19
commit
c636014c43
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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] + '/'
|
|
@ -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()
|
|
@ -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
|
|
@ -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'
|
|
@ -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
|
|
@ -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
|
||||||
|
#
|
|
@ -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)
|
|
@ -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
|
|
@ -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.
|
|
@ -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
|
|
@ -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)]
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||||
|
#
|
|
@ -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
|
|
@ -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.
|
|
@ -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...
|
|
@ -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)
|
|
@ -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)]
|
|
@ -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], ')'
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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()
|
Loading…
Reference in New Issue