removing more stdwin users
authorGuido van Rossum <guido@python.org>
Thu, 11 May 2000 18:27:21 +0000 (18:27 +0000)
committerGuido van Rossum <guido@python.org>
Thu, 11 May 2000 18:27:21 +0000 (18:27 +0000)
14 files changed:
Demo/cwilib/cwilib.py [deleted file]
Demo/cwilib/form.py [deleted file]
Demo/cwilib/vt100.py [deleted file]
Demo/cwilib/vt100win.py [deleted file]
Demo/ibrowse/README [deleted file]
Demo/ibrowse/ib [deleted file]
Demo/ibrowse/ib.py [deleted file]
Demo/ibrowse/ibrowse [deleted file]
Demo/ibrowse/ibrowse.py [deleted file]
Demo/ibrowse/icache.py [deleted file]
Demo/ibrowse/ifile.py [deleted file]
Demo/ibrowse/itags.py [deleted file]
Demo/sgi/cd/cdwin.py [deleted file]
Demo/threads/wpi.py [deleted file]

diff --git a/Demo/cwilib/cwilib.py b/Demo/cwilib/cwilib.py
deleted file mode 100755 (executable)
index 2b19637..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-# Interface to the interactive CWI library catalog.
-
-import sys
-import stdwin
-from stdwinevents import *
-import select
-import telnetlib
-import vt100win
-from form import Form
-
-
-# Main program
-
-def main():
-    vt = vt100win.VT100win()
-    #
-    host = 'biefstuk.cwi.nl'
-    tn = telnetlib.Telnet(host, 0)
-    #
-    try:
-        vt.send(tn.read_until('login: ', 10))
-        tn.write('cwilib\r')
-        #
-        vt.send(tn.read_until('Hit <RETURN> to continue...', 10))
-        tn.write('\r')
-        #
-        vt.send(tn.read_until('QUIT', 20))
-    except EOFError:
-        sys.stderr.write('Connection closed prematurely\n')
-        sys.exit(1)
-    #
-    define_screens(vt)
-    matches = vt.which_screens()
-    if 'menu' not in matches:
-        sys.stderr.write('Main menu does not appear\n')
-        sys.exit(1)
-    #
-    tn.write('\r\r')
-    vt.open('Progress -- CWI Library')
-    vt.set_debuglevel(0)
-    ui = UserInterface()
-    #
-    while 1:
-        try:
-            data = tn.read_very_eager()
-        except EOFError:
-            stdwin.message('Connection closed--goodbye')
-            break
-        if data:
-            print 'send...'
-            vt.send(data)
-            print 'send...done'
-            continue
-        event = stdwin.pollevent()
-        if event:
-            type, window, detail = event
-            if window == None and type == WE_LOST_SEL:
-                window = ui.queryform.window
-                event = type, window, detail
-            if type == WE_CLOSE:
-                break
-            if window in ui.windows:
-                ui.dispatch(type, window, detail)
-            elif window == vt.window:
-                if type == WE_NULL:
-                    pass
-                elif type == WE_COMMAND:
-                    if detail == WC_RETURN:
-                        tn.write('\r')
-                    elif detail == WC_BACKSPACE:
-                        tn.write('\b')
-                    elif detail == WC_TAB:
-                        tn.write('\t')
-                    elif detail == WC_UP:
-                        tn.write('\033[A')
-                    elif detail == WC_DOWN:
-                        tn.write('\033[B')
-                    elif detail == WC_RIGHT:
-                        tn.write('\033[C')
-                    elif detail == WC_LEFT:
-                        tn.write('\033[D')
-                    else:
-                        print '*** Command:', detail
-                elif type == WE_CHAR:
-                    tn.write(detail)
-                elif type == WE_DRAW:
-                    vt.draw(detail)
-                elif type in (WE_ACTIVATE, WE_DEACTIVATE):
-                    pass
-                else:
-                    print '*** VT100 event:', type, detail
-            else:
-                print '*** Alien event:', type, window, detail
-            continue
-        rfd, wfd, xfd = select.select([tn, stdwin], [], [])
-
-
-# Subroutine to define our screen recognition patterns
-
-def define_screens(vt):
-    vt.define_screen('menu', {
-              'title': ('search', 0, 0, 80,
-                        ' SEARCH FUNCTIONS  +OTHER FUNCTIONS '),
-              })
-    vt.define_screen('search', {
-              'title': ('search', 0, 0, 80, ' Search '),
-              })
-    vt.define_screen('shortlist', {'title': ('search', 0, 0, 80,
-              ' Short-list')})
-    vt.define_screen('showrecord', {
-              'title': ('search', 0, 0, 80, ' Show record '),
-              })
-    vt.define_screen('timelimit', {
-              'limit': ('search', 12, 0, 80, ' TIME LIMIT '),
-              })
-    vt.define_screen('attention', {
-              'BASE': ('copy', 0, 0, 0, 'search'),
-              'title': ('search', 10, 0, 80, ' ATTENTION ')})
-    vt.define_screen('syntaxerror', {
-              'BASE': ('copy', 0, 0, 0, 'attention'),
-              'message': ('search', 12, 0, 80, ' Syntax error'),
-              })
-    vt.define_screen('emptyerror', {
-              'BASE': ('copy', 0, 0, 0, 'attention'),
-              'message': ('search', 12, 0, 80,
-                          ' Check your input. Search at least one term'),
-              })
-    vt.define_screen('unsortedwarning', {
-              'BASE': ('copy', 0, 0, 0, 'attention'),
-              'message': ('search', 12, 0, 80,
-                          ' Number of records exceeds sort limit'),
-              })
-    vt.define_screen('thereismore', {
-              'BASE': ('copy', 0, 0, 0, 'showrecord'),
-              'message': ('search', 15, 0, 80,
-                 'There is more within this record. Use the arrow keys'),
-              })
-    vt.define_screen('nofurther', {
-              'BASE': ('copy', 0, 0, 0, 'showrecord'),
-              'message': ('search', 17, 0, 80, 'You cannot go further\.'),
-              })
-    vt.define_screen('nofurtherback', {
-              'BASE': ('copy', 0, 0, 0, 'showrecord'),
-              'message': ('search', 17, 0, 80,
-                          'You cannot go further back'),
-              })
-
-
-# Class to implement our user interface.
-
-class UserInterface:
-
-    def __init__(self):
-        stdwin.setfont('7x14')
-        self.queryform = QueryForm()
-        self.listform = ListForm()
-        self.recordform = RecordForm()
-        self.forms = [self.queryform, self.listform, self.recordform]
-        define_query_fields(self.queryform)
-        self.windows = []
-        for form in self.forms:
-            if form.formheight > 0:
-                form.open()
-                self.windows.append(form.window)
-
-    def __del__(self):
-        self.close()
-
-    def close(self):
-        for form in self.forms:
-            form.close()
-
-    def dispatch(self, type, window, detail):
-        for form in self.forms:
-            if window == form.window:
-                form.dispatch(type, detail)
-
-
-def define_query_fields(f):
-    f.define_field('name', 'Name auth./ed.', 1, 60)
-    f.define_field('title',  'Title', 4, 60)
-    f.define_field('shelfmark', 'Shelf mark', 1, 60)
-    f.define_field('class', 'Prim. classif.', 1, 60)
-    f.define_field('series', 'Series', 1, 60)
-    f.define_field('congress', 'Congr. pl./year', 1, 60)
-    f.define_field('type', 'Type', 1, 60)
-
-
-class QueryForm(Form):
-
-    def __init__(self):
-        Form.__init__(self, 'Query form -- CWI Library')
-
-    def dispatch(self, type, detail):
-        if type == WE_COMMAND and detail == WC_RETURN:
-            print '*** SUBMIT ***'
-        else:
-            Form.dispatch(self, type, detail)
-
-
-class ListForm(Form):
-
-    def __init__(self):
-        Form.__init__(self, 'Short list -- CWI Library')
-
-
-class RecordForm(Form):
-
-    def __init__(self):
-        Form.__init__(self, 'Record detail -- CWI Library')
-
-
-main()
diff --git a/Demo/cwilib/form.py b/Demo/cwilib/form.py
deleted file mode 100755 (executable)
index 8dd6ef9..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-# Fill-out form window
-
-import stdwin
-from stdwinevents import *
-
-
-class Form:
-
-       def __init__(self, title):
-               self.title = title
-               self.window = None
-               self.fields = {}
-               self.fieldnames = []
-               self.formwidth = self.formheight = 0
-               self.focusname = None
-               self.tefocus = None
-
-       def define_field(self, name, label, lines, chars):
-               self.fieldnames.append(name)
-               lh = stdwin.lineheight()
-               cw = stdwin.textwidth('m')
-               left = 20*cw
-               top = self.formheight + 4
-               right = left + chars*cw
-               bottom = top + lines*lh
-               te = None
-               self.fields[name] = (label, left, top, right, bottom, te)
-               self.formheight = bottom + 2
-               self.formwidth = max(self.formwidth, right + 4)
-
-       def open(self):
-               if self.window: return
-               self.formwidth = max(100, self.formwidth)
-               self.formheight = max(50, self.formheight)
-               stdwin.setdefwinsize(self.formwidth, self.formheight)
-               stdwin.setdefscrollbars(0, 0)
-               self.window = stdwin.open(self.title)
-               self.window.setdocsize(self.formwidth, self.formheight)
-               for name in self.fieldnames:
-                       label, left, top, right, bottom, te = \
-                                 self.fields[name]
-                       rect = (left, top), (right, bottom)
-                       te = self.window.textcreate(rect)
-                       te.setactive(0)
-                       te.setview(rect)
-                       self.fields[name] = \
-                                 label, left, top, right, bottom, te
-               if self.fieldnames:
-                       self.setfocus(self.fieldnames[0])
-
-       def setfocus(self, name):
-               if name <> self.focusname and self.tefocus:
-                       self.tefocus.setactive(0)
-               self.focusname = name
-               if self.focusname:
-                       self.tefocus = self.fields[self.focusname][-1]
-                       self.tefocus.setactive(1)
-               else:
-                       self.tefocus = None
-
-       def dispatch(self, type, detail):
-               event = type, self.window, detail
-               if type == WE_NULL:
-                       pass
-               elif type == WE_DRAW:
-                       self.draw(detail)
-               elif type == WE_MOUSE_DOWN:
-                       x, y = detail[0]
-                       for name in self.fieldnames:
-                               label, left, top, right, bottom, te = \
-                                         self.fields[name]
-                               if left <= x < right and \
-                                         top <= y < bottom:
-                                       self.setfocus(name)
-                                       break
-                       else:
-                               stdwin.fleep()
-                               return
-                       if self.tefocus:
-                               (left, top), (right, bottom) = \
-                                         self.tefocus.getrect()
-                               if x < left: x = left
-                               if x >= right: x = right-1
-                               if y < top: y = top
-                               if y >= bottom:
-                                       y = bottom-1
-                                       x = right-1
-                               event = type, self.window, ((x,y),)+detail[1:]
-                               if not self.tefocus.event(event):
-                                       stdwin.fleep()
-               elif type in (WE_MOUSE_MOVE, WE_MOUSE_UP, WE_CHAR):
-                       if not self.tefocus or not self.tefocus.event(event):
-                               stdwin.fleep()
-                       elif type == WE_MOUSE_UP:
-                               button = detail[2]
-                               if button == 2:
-                                       self.paste_selection()
-                               else:
-                                       self.make_selection()
-               elif type == WE_COMMAND:
-                       if detail in (WC_BACKSPACE, WC_UP, WC_DOWN,
-                                     WC_LEFT, WC_RIGHT):
-                               if not self.tefocus or \
-                                         not self.tefocus.event(event):
-                                       stdwin.fleep()
-                       elif detail == WC_RETURN:
-                               print '*** Submit query'
-                       elif detail == WC_TAB:
-                               if not self.fields:
-                                       stdwin.fleep()
-                                       return
-                               if not self.focusname:
-                                       i = 0
-                               else:
-                                       i = self.fieldnames.index(
-                                                 self.focusname)
-                                       i = (i+1) % len(self.fieldnames)
-                               self.setfocus(self.fieldnames[i])
-                               self.tefocus.setfocus(0, 0x7fff)
-                               self.make_selection()
-               elif type in (WE_ACTIVATE, WE_DEACTIVATE):
-                       pass
-               elif type == WE_LOST_SEL:
-                       if self.tefocus:
-                               a, b = self.tefocus.getfocus()
-                               self.tefocus.setfocus(a, a)
-               else:
-                       print 'Form.dispatch(%d, %s)' % (type, `detail`)
-
-       def draw(self, detail):
-               d = self.window.begindrawing()
-               d.cliprect(detail)
-               d.erase(detail)
-               self.drawform(d, detail)
-               d.noclip()
-               d.close()
-               # Stupid textedit objects can't draw with open draw object...
-               self.drawtextedit(detail)
-
-       def drawform(self, d, detail):
-               for name in self.fieldnames:
-                       label, left, top, right, bottom, te = self.fields[name]
-                       d.text((0, top), label)
-                       d.box((left-3, top-2), (right+4, bottom+2))
-
-       def drawtextedit(self, detail):
-               for name in self.fieldnames:
-                       label, left, top, right, bottom, te = self.fields[name]
-                       te.draw(detail)
-
-       def make_selection(self):
-               s = self.tefocus.getfocustext()
-               if not s:
-                       return
-               stdwin.rotatecutbuffers(1)
-               stdwin.setcutbuffer(0, s)
-               if not self.window.setselection(WS_PRIMARY, s):
-                       stdwin.fleep()
-
-       def paste_selection(self):
-               if not self.tefocus:
-                       stdwin.fleep()
-                       return
-               s = stdwin.getselection(WS_PRIMARY)
-               if not s:
-                       s = stdwin.getcutbuffer(0)
-                       if not s:
-                               stdwin.fleep()
-                               return
-               self.tefocus.replace(s)
diff --git a/Demo/cwilib/vt100.py b/Demo/cwilib/vt100.py
deleted file mode 100755 (executable)
index 9edd481..0000000
+++ /dev/null
@@ -1,328 +0,0 @@
-# VT100 terminal emulator.
-# This is incomplete and slow, but will do for now...
-# It shouldn't be difficult to extend it to be a more-or-less complete
-# VT100 emulator.  And little bit of profiling could go a long way...
-
-from array import array
-import regex
-import string
-
-# Tunable parameters
-DEBUGLEVEL = 1
-
-# Symbolic constants
-ESC = '\033'
-
-
-# VT100 emulation class
-
-class VT100:
-
-       def __init__(self):
-               self.debuglevel = DEBUGLEVEL
-               # Unchangeable parameters (for now)
-               self.width = 80
-               self.height = 24
-               self.blankline = array('c', ' '*self.width)
-               self.blankattr = array('b', '\0'*self.width)
-               # Set mutable display state
-               self.reset()
-               # Set parser state
-               self.unfinished = ''
-               # Set screen recognition state
-               self.reset_recognizer()
-
-       def msg(self, msg, *args):
-               if self.debuglevel > 0:
-                       print 'VT100:', msg%args
-
-       def set_debuglevel(self, debuglevel):
-               self.debuglevel = debuglevel
-
-       def reset(self):
-               self.lines = []
-               self.attrs = []
-               self.fill_bottom()
-               self.x = 0
-               self.y = 0
-               self.curattrs = []
-
-       def show(self):
-               lineno = 0
-               for line in self.lines:
-                       lineno = lineno + 1
-                       i = len(line)
-                       while i > 0 and line[i-1] == ' ': i = i-1
-                       print line[:i]
-                       print 'CURSOR:', self.x, self.y
-
-       def fill_bottom(self):
-               while len(self.lines) < self.height:
-                       self.lines.append(self.blankline[:])
-                       self.attrs.append(self.blankattr[:])
-
-       def fill_top(self):
-               while len(self.lines) < self.height:
-                       self.lines.insert(0, self.blankline[:])
-                       self.attrs.insert(0, self.blankattr[:])
-
-       def clear_all(self):
-               self.lines = []
-               self.attrs = []
-               self.fill_bottom()
-
-       def clear_below(self):
-               del self.lines[self.y:]
-               del self.attrs[self.y:]
-               self.fill_bottom()
-
-       def clear_above(self):
-               del self.lines[:self.y]
-               del self.attrs[:self.y]
-               self.fill_top()
-
-       def send(self, buffer):
-               self.msg('send: unfinished=%s, buffer=%s',
-                         `self.unfinished`, `buffer`)
-               self.unfinished = self.unfinished + buffer
-               i = 0
-               n = len(self.unfinished)
-               while i < n:
-                       c = self.unfinished[i]
-                       i = i+1
-                       if c != ESC:
-                               self.add_char(c)
-                               continue
-                       if i >= n:
-                               i = i-1
-                               break
-                       c = self.unfinished[i]
-                       i = i+1
-                       if c == 'c':
-                               self.reset()
-                               continue
-                       if c <> '[':
-                               self.msg('unrecognized: ESC %s', `c`)
-                               continue
-                       argstr = ''
-                       while i < n:
-                               c = self.unfinished[i]
-                               i = i+1
-                               if c not in '0123456789;':
-                                       break
-                               argstr = argstr + c
-                       else:
-                               i = i - len(argstr) - 2
-                               break
-##                     self.msg('found ESC [ %s %s' % (`argstr`, `c`))
-                       args = string.splitfields(argstr, ';')
-                       for j in range(len(args)):
-                               s = args[j]
-                               while s[:1] == '0': s = s[1:]
-                               if s: args[j] = eval(s)
-                               else: args[j] = 0
-                       p1 = p2 = 0
-                       if args: p1 = args[0]
-                       if args[1:]: p2 = args[1]
-                       if c in '@ABCDH':
-                               if not p1: p1 = 1
-                       if c in 'H':
-                               if not p2: p2 = 1
-                       if c == '@':
-                               for j in range(p1):
-                                       self.add_char(' ')
-                       elif c == 'A':
-                               self.move_by(0, -p1)
-                       elif c == 'B':
-                               self.move_by(0, p1)
-                       elif c == 'C':
-                               self.move_by(p1, 0)
-                       elif c == 'D':
-                               self.move_by(-p1, 0)
-                       elif c == 'H':
-                               self.move_to(p2-1, p1-1)
-                       elif c == 'J':
-                               if p1 == 0: self.clear_above()
-                               elif p1 == 1: self.clear_below()
-                               elif p1 == 2: self.clear_all()
-                               else: self.msg('weird ESC [ %d J', p1)
-                       elif c == 'K':
-                               if p1 == 0: self.erase_right()
-                               elif p1 == 1: self.erase_left()
-                               elif p1 == 2: self.erase_line()
-                               else: self.msg('weird ESC [ %d K', p1)
-                       elif c == 'm':
-                               if p1 == 0:
-                                       self.curattrs = []
-                               else:
-                                       if p1 not in self.curattrs:
-                                               self.curattrs.append(p1)
-                                               self.curattrs.sort()
-                       else:
-                               self.msg('unrecognized: ESC [ %s', `argstr+c`)
-               self.unfinished = self.unfinished[i:]
-
-       def add_char(self, c):
-               if c == '\r':
-                       self.move_to(0, self.y)
-                       return
-               if c in '\n\f\v':
-                       self.move_to(self.x, self.y + 1)
-                       if self.y >= self.height:
-                               self.scroll_up(1)
-                               self.move_to(self.x, self.height - 1)
-                       return
-               if c == '\b':
-                       self.move_by(-1, 0)
-                       return
-               if c == '\a':
-                       self.msg('BELL')
-                       return
-               if c == '\t':
-                       self.move_to((self.x+8)/8*8, self.y)
-                       return
-               if c == '\0':
-                       return
-               if c < ' ' or c > '~':
-                       self.msg('ignored control char: %s', `c`)
-                       return
-               if self.x >= self.width:
-                       self.move_to(0, self.y + 1)
-               if self.y >= self.height:
-                       self.scroll_up(1)
-                       self.move_to(self.x, self.height - 1)
-               self.lines[self.y][self.x] = c
-               if self.curattrs:
-                       self.attrs[self.y][self.x] = max(self.curattrs)
-               else:
-                       self.attrs[self.y][self.x] = 0
-               self.move_by(1, 0)
-
-       def move_to(self, x, y):
-               self.x = min(max(0, x), self.width)
-               self.y = min(max(0, y), self.height)
-
-       def move_by(self, dx, dy):
-               self.move_to(self.x + dx, self.y + dy)
-
-       def scroll_up(self, nlines):
-               del self.lines[:max(0, nlines)]
-               del self.attrs[:max(0, nlines)]
-               self.fill_bottom()
-
-       def scroll_down(self, nlines):
-               del self.lines[-max(0, nlines):]
-               del self.attrs[-max(0, nlines):]
-               self.fill_top()
-
-       def erase_left(self):
-               x = min(self.width-1, x)
-               y = min(self.height-1, y)
-               self.lines[y][:x] = self.blankline[:x]
-               self.attrs[y][:x] = self.blankattr[:x]
-
-       def erase_right(self):
-               x = min(self.width-1, x)
-               y = min(self.height-1, y)
-               self.lines[y][x:] = self.blankline[x:]
-               self.attrs[y][x:] = self.blankattr[x:]
-
-       def erase_line(self):
-               self.lines[y][:] = self.blankline
-               self.attrs[y][:] = self.blankattr
-
-       # The following routines help automating the recognition of
-       # standard screens.  A standard screen is characterized by
-       # a number of fields.  A field is part of a line,
-       # characterized by a (lineno, begin, end) tuple;
-       # e.g. the first 10 characters of the second line are
-       # specified by the tuple (1, 0, 10).  Fields can be:
-       # - regex: desired contents given by a regular expression,
-       # - extract: can be extracted,
-       # - cursor: screen is only valid if cursor in field,
-       # - copy: identical to another screen (position is ignored).
-       # A screen is defined as a dictionary full of fields.  Screens
-       # also have names and are placed in a dictionary.
-
-       def reset_recognizer(self):
-               self.screens = {}
-
-       def define_screen(self, screenname, fields):
-               fieldscopy = {}
-               # Check if the fields make sense
-               for fieldname in fields.keys():
-                       field = fields[fieldname]
-                       ftype, lineno, begin, end, extra = field
-                       if ftype in ('match', 'search'):
-                               extra = regex.compile(extra)
-                       elif ftype == 'extract':
-                               extra = None
-                       elif ftype == 'cursor':
-                               extra = None
-                       elif ftype == 'copy':
-                               if not self.screens.has_key(extra):
-                                       raise ValueError, 'bad copy ref'
-                       else:
-                               raise ValueError, 'bad ftype: %s' % `ftype`
-                       fieldscopy[fieldname] = (
-                                 ftype, lineno, begin, end, extra)
-               self.screens[screenname] = fieldscopy
-
-       def which_screens(self):
-               self.busy = []
-               self.okay = []
-               self.fail = []
-               for name in self.screens.keys():
-                       ok = self.match_screen(name)
-               return self.okay[:]
-
-       def match_screen(self, name):
-               if name in self.busy: raise RuntimeError, 'recursive match'
-               if name in self.okay: return 1
-               if name in self.fail: return 0
-               self.busy.append(name)
-               fields = self.screens[name]
-               ok = 0
-               for key in fields.keys():
-                       field = fields[key]
-                       ftype, lineno, begin, end, extra = field
-                       if ftype == 'copy':
-                               if not self.match_screen(extra): break
-                       elif ftype == 'search':
-                               text = self.lines[lineno][begin:end].tostring()
-                               if extra.search(text) < 0:
-                                       break
-                       elif ftype == 'match':
-                               text = self.lines[lineno][begin:end].tostring()
-                               if extra.match(text) < 0:
-                                       break
-                       elif ftype == 'cursor':
-                               if self.x != lineno or not \
-                                         begin <= self.y < end:
-                                       break
-               else:
-                       ok = 1
-               if ok:
-                       self.okay.append(name)
-               else:
-                       self.fail.append(name)
-               self.busy.remove(name)
-               return ok
-
-       def extract_field(self, screenname, fieldname):
-               ftype, lineno, begin, end, extra = \
-                         self.screens[screenname][fieldname]
-               return stripright(self.lines[lineno][begin:end].tostring())
-
-       def extract_rect(self, left, top, right, bottom):
-               lines = []
-               for i in range(top, bottom):
-                       lines.append(stripright(self.lines[i][left:right])
-                                 .tostring())
-               return lines
-
-
-def stripright(line):
-       i = len(line)
-       while i > 0 and line[i-1] in string.whitespace: i = i-1
-       return line[:i]
diff --git a/Demo/cwilib/vt100win.py b/Demo/cwilib/vt100win.py
deleted file mode 100755 (executable)
index 122e5f9..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-# VT100 terminal emulator in a STDWIN window.
-
-import stdwin
-from stdwinevents import *
-from vt100 import VT100
-
-class VT100win(VT100):
-
-       def __init__(self):
-               VT100.__init__(self)
-               self.window = None
-               self.last_x = -1
-               self.last_y = -1
-
-       def __del__(self):
-               self.close()
-
-       def open(self, title):
-               stdwin.setfont('7x14')
-               self.charwidth = stdwin.textwidth('m')
-               self.lineheight = stdwin.lineheight()
-               self.docwidth = self.width * self.charwidth
-               self.docheight = self.height * self.lineheight
-               stdwin.setdefwinsize(self.docwidth + 2, self.docheight + 2)
-               stdwin.setdefscrollbars(0, 0)
-               self.window = stdwin.open(title)
-               self.window.setdocsize(self.docwidth + 2, self.docheight + 2)
-
-       def close(self):
-               if self.window:
-                       self.window.close()
-               self.window = None
-
-       def show(self):
-               if not self.window: return
-               self.window.change(((-10, -10),
-                         (self.docwidth+10, self.docheight+10)))
-
-       def draw(self, detail):
-               d = self.window.begindrawing()
-               fg = stdwin.getfgcolor()
-               red = stdwin.fetchcolor('red')
-               d.cliprect(detail)
-               d.erase(detail)
-               lh = self.lineheight
-               cw = self.charwidth
-               for y in range(self.height):
-                       d.text((0, y*lh), self.lines[y].tostring())
-                       if self.attrs[y] <> self.blankattr:
-                               for x in range(len(self.attrs[y])):
-                                       if self.attrs[y][x] == 7:
-                                               p1 = x*cw, y*lh
-                                               p2 = (x+1)*cw, (y+1)*lh
-                                               d.invert((p1, p2))
-               x = self.x * cw
-               y = self.y * lh
-               d.setfgcolor(red)
-               d.invert((x, y), (x+cw, y+lh))
-               d.setfgcolor(fg)
-               d.close()
-
-       def move_to(self, x, y):
-               VT100.move_to(self, x, y)
-               if not self.window: return
-               if self.y != self.last_y:
-                       self.window.change((0, self.last_y * self.lineheight),
-                                 (self.width*self.charwidth,
-                                 (self.last_y+1) * self.lineheight))
-               self.last_x = self.x
-               self.last_y = y
-               self.window.change((0, self.y * self.lineheight),
-                         (self.width*self.charwidth,
-                         (self.y+1) * self.lineheight))
-
-       def send(self, str):
-               VT100.send(self, str)
-##             self.show()
-
diff --git a/Demo/ibrowse/README b/Demo/ibrowse/README
deleted file mode 100644 (file)
index 22e4039..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-This directory contains a browser written in Python for "Info files"
-as used by the Emacs documentation system.  The browser requires that
-Python is built with the "stdwin" option and runs under X11 or the
-Mac window system.
-
-Now you can read Info files even if you can't spare the memory, time or
-disk space to run Emacs.  (I have used this extensively on a Macintosh
-with 1 Megabyte main memory and a 20 Meg harddisk.)
-
-You can give this to someone with great fear of complex computer
-systems, as long as they can use a mouse.
-
-Another reason to use this is to encourage the use of Info for on-line
-documentation of software that is not related to Emacs or GNU.
-(In particular, I plan to redo the Python and STDWIN documentation
-in texinfo.)
-
-The main program is in file "ib.py"; this accepts a file name and a
-node name as optional command line arguments, i.e., its usage is
-
-       python ib.py [file [node]]
-
-
-Configuration:
-
-- The pathname of the directory (or directories) containing
-the standard Info files should be set by editing the
-value assigned to INFOPATH in module ifile.py.
-
-- The default font should be set by editing the value of FONT
-in this module (ibrowse.py).
-
-- For fastest I/O, you may look at BLOCKSIZE and a few other
-constants in ifile.py.
diff --git a/Demo/ibrowse/ib b/Demo/ibrowse/ib
deleted file mode 100755 (executable)
index 04cb790..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-: ${ARCH}=`arch`
-exec /ufs/guido/bin/$ARCH/python ib.py ${1+"$@"}
diff --git a/Demo/ibrowse/ib.py b/Demo/ibrowse/ib.py
deleted file mode 100755 (executable)
index ce6e16a..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#! /usr/bin/env python
-
-# Call ibrowse (the info file browser) under UNIX.
-
-import sys
-import ibrowse
-
-if len(sys.argv) > 1:
-       file = sys.argv[1]
-       if len(sys.argv) > 2:
-               if len(sys.argv) > 3:
-                       sys.stdout = sys.stderr
-                       print 'usage:', sys.argv[0], '[file [node]]'
-                       sys.exit(2)
-               else:
-                       node = sys.argv[2]
-       else:
-               node = ''
-       ibrowse.start('(' + file + ')' + node)
-else:
-       ibrowse.main()
diff --git a/Demo/ibrowse/ibrowse b/Demo/ibrowse/ibrowse
deleted file mode 100755 (executable)
index 8b0dcde..0000000
+++ /dev/null
@@ -1,719 +0,0 @@
-This file documents the ibrowse program.  -*-Text-*-
-The H command of ibrowse goes to the node Help in this file.
-\1f
-File: ibrowse  Node: Top       Up: (DIR)       Next: Expert
-
-Ibrowse is a program for reading documentation, which you are using now.
-** Ibrowse uses the file format of the Emacs Info program, and its
-** commands are similar, but not identical.
-
-To learn how to use Ibrowse, type the command "h".  It will bring you
-to a programmed instruction sequence.
-
-* Menu:
-
-* Expert::     Advanced Ibrowse commands: c, k, g, s, 1 - 9, arrows.
-* Add::                Describes how to add new nodes to the hierarchy.
-               Also tells what nodes look like.
-* Menus::      How to add to or create menus in Info nodes.
-* Cross-refs:: How to add cross-references to Info nodes.
-* Tags::       How to make tag tables for Info files.
-* Checking::   How to check the consistency of an Info file.
-* Texinfo: (texinfo).
-               How to generate an Info file and a printed manual
-               from the same source file.
-\1f\f
-File: ibrowse  Node: Summary                   Next: Help
-
-Ibrowse is a Python program for browsing through the Emacs Info
-documentation tree.  Documentation in Info is divided into "nodes",
-each of which discusses one topic and contains references to other
-nodes which discuss related topics.  Ibrowse has commands to follow the
-references and show you other nodes.
-
-h      Invoke the Ibrowse tutorial.
-?      Display this Summary node.
-q      Quit Ibrowse.
-w      Close current window.
-
-Selecting other nodes:
-n      Move to the "next" node of this node.
-p      Move to the "previous" node of this node.
-m      Pick menu item specified by name (or abbreviation).
-1-9    Pick first..ninth in node's menu.
-       Menu items select nodes that are "subsections" of this node.
-u      Move "up" from this node (i.e., from a subsection to a section).
-f      Follow a cross reference by name (or abbrev).  Type `l' to get back.
-l      Move back to the last node you were in.
-
-Moving within a node:
-Space  Scroll forward a full screen.     DEL, BS Scroll backward.
-b      Go to beginning of node.          
-
-Advanced commands:
-k      Clone current window (create an independent duplicate).
-c      Copy text selection to clipboard (for paste in another application).
-g      Move to node specified by name.
-       You may include a filename as well, as (FILENAME)NODENAME.
-d      Go to the main directory of Info files.
-t      Go to Top node of this file.
-s      Search through this Info file for node with specified regexp.
-\1f\f
-File: ibrowse  Node: Help-Small-Screen         Next: Help
-
-Since your terminal has an unusually small number of lines on its
-screen, it is necessary to give you special advice at the beginning.
-
-If you see the text "--All----" at near the bottom right corner of
-the screen, it means the entire text you are looking at fits on the
-screen.  If you see "--Top----" instead, it means that there is more
-text below that does not fit.  To move forward through the text and
-see another screen full, press the Space bar.  To move back up, press
-the key labeled Rubout or Delete or DEL.
-
-Here are 40 lines of junk, so you can try Spaces and Rubout and
-see what they do.  At the end are instructions of what you should do
-next.
-
-This is line 17
-This is line 18
-This is line 19
-This is line 20
-This is line 21
-This is line 22
-This is line 23
-This is line 24
-This is line 25
-This is line 26
-This is line 27
-This is line 28
-This is line 29
-This is line 30
-This is line 31
-This is line 32
-This is line 33
-This is line 34
-This is line 35
-This is line 36
-This is line 37
-This is line 38
-This is line 39
-This is line 40
-This is line 41
-This is line 42
-This is line 43
-This is line 44
-This is line 45
-This is line 46
-This is line 47
-This is line 48
-This is line 49
-This is line 50
-This is line 51
-This is line 52
-This is line 53
-This is line 54
-This is line 55
-This is line 56
-
-If you have managed to get here, go back to the beginning with
-Rubout, and come back here again, then you understand Space and
-Rubout.  So now type an "n"--just one character; don't type the
-quotes and don't type a Return afterward-- to get to the normal start
-of the course.
-\1f\f
-File: ibrowse  Node: Help      Next: Help-P    Previous: Help-Small-Screen
-
-You are talking to the program Ibrowse, for reading documentation.
-
-  Right now you are looking at one "Node" of Information.
-A node contains text describing a specific topic at a specific
-level of detail.  This node's topic is "how to use Ibrowse".
-
-  The top line of a node is its "header".  This node's header (look at
-it now) says that it is the node named "Help" in the file "ibrowse".
-It says that the Next node after this one is the node called "Help-P".
-An advanced Ibrowse command lets you go to any node whose name you know.
-
-  Besides a "Next", a node can have a "Previous" or an "Up".
-This node has a "Previous" but no "Up", as you can see.
-
-  Now it's time to move on to the Next node, named "Help-P".
-
->> Type "n" to move there.  Type just one character;
-   don't type the quotes and don't type a Return afterward.
-
-">>" in the margin means it is really time to try a command.
-\1f
-File: ibrowse  Node: Help-P    Next: Help-Page Previous: Help
-
-This node is called "Help-P".  The "Previous" node, as you see, is
-"Help", which is the one you just came from using the "N" command.
-Another "N" command now would take you to the Next node, "Help-Page".
-
->> But don't do that yet.  First, try the "p" command, which takes
-you to the Previous node.  When you get there, you can do an "n"
-again to return here.
-
-  This all probably seems insultingly simple so far, but DON'T be
-led into skimming.  Things will get more complicated soon.  Also,
-don't try a new command until you are told it's time to.  Otherwise,
-you may make Ibrowse skip past an important warning that was coming up.
-
->> Now do an "n" to get to the node "Help-Page" and learn more.
-\1f\f
-File: ibrowse  Node: Help-Page Next: Help-M    Previous: Help-P
-
-Space, Backspace, and B commands.
-
-  This node's header tells you that you are now at node "Help-Page", and
-that "P" would get you back to "Help-P".  The line starting "Space,"
-is a "Title", saying what the node is about (most nodes have titles).
-
-  This is a big node and it doesn't all fit on your display screen.
-You can tell that there is more that isn't visible because you
-the scroll bar on the side of the window has become active (gray).
-
-  The Space, Backspace and B commands exist to allow you to "move
-around" in a node that doesn't all fit on the screen at once.
-Space moves forward, to show what was below the bottom of the screen.
-Backspace moves backward, to show what was above the top of the screen
-(there isn't anything above the top until you have typed some spaces).
-
->> Now try typing a Space (afterward, type a Backspace to return here).
-
-  When you type the space, the two lines that were at the bottom of the 
-screen appear at the top, followed by more lines.  Backspace takes the
-two lines from the top and moves them to the bottom, USUALLY, but if
-there are not a full screen's worth of lines above them they may not
-make it all the way to the bottom.
-
-  If you type a Space when there is no more to see, it will ring the
-bell and otherwise do nothing.  The same goes for a Backspace when
-the header of the node is visible.
-
-  Of course you can use the mouse and directly move the scroll bar
-as well, but Ibrowse has keyboard commands for almost everything,
-including scrolling.  These keyboard commands are called "shortcuts",
-because it generally takes less effort to press a key on the
-keyboard than to move the mouse.  On the other hand, if you are
-an infrequent user of Ibrowse, you can do everything with the
-mouse that you can do with the keyboard.  Just look in the menus
-(I'm sure you must know how to use the menus on this system, or
-else you couldn't have gotten this far...).  In fact you'll see that
-the commands and shortcuts listed in the menus are the same as those
-described in this course.  You can use the shortcuts either with or
-without the "Command" or "Meta" key.
-
-  Two menus are always available: the "Ibrowse" menu contains commands
-pertaining to the Ibrowse program at large, while the "Navigation" menu
-contains commands that move around between nodes.  There may be other
-menus; these will be explained later.
-
-  To move back to the beginning of the node you are on, you can type
-a lot of Backspaces.  You can also type simply "b" for beginning.
->> Try that now.  (I have put in enough verbiage to make sure you are
-   not on the first screenful now).  Then come back, with Spaces.
-
-  You have just learned a considerable number of commands.  If you
-want to use one but have trouble remembering which, just pull down
-the menus to get a summary of commands and shortcuts.  Some additional
-shortcuts (not listed in the menus) are listed by the "Short help"
-command.  This brings up a dialog box which you can acknowledge
-by clicking the OK button or pressing the Return key.
-
-  From now on, you will encounter large nodes without warning, and
-will be expected to know how to use Space and Backspace to move
-around in them without being told.  Since you could change the
-size of the window used, it would be impossible to warn you anyway.
-
->> Now type "n" to see the description of the "m" command.
-\1f\f
-File: ibrowse  Node: Help-M    Next: Help-Adv  Previous: Help-Page
-
-Menus and the "m" command
-
-  With only the "n" and "p" commands for moving between nodes, nodes
-are restricted to a linear sequence.  Menus allow a branching
-structure.  A menu is a list of other nodes you can move to.  It is
-actually just part of the text of the node formatted specially so that
-Ibrowse can interpret it.  The beginning of a menu is always identified
-by a line which starts with "* Menu:".  A node contains a menu if and
-only if it has a line in it which starts that way.  The only menu you
-can use at any moment is the one in the node you are in.  To use a
-menu in any other node, you must move to that node first.
-
-  (There is an unfortunate confusion of terms here.  "Menu" may refer
-to one of the Ibrowse menus at the top, such as as the "Ibrowse" and
-"Navigation" menus explained in the previous node, or to the menu in
-a node.  Where confusion is possible, these will be disambiguated by
-calling them "Ibrowse menus" or "node menu".)
-
-  After the start of the menu, each line that starts with a "*"
-identifies one subtopic.  The line will usually contain a brief name
-for the subtopic (followed by a ":"), the name of the node that talks
-about that subtopic, and optionally some further description of the
-subtopic.  Lines in the menu that don't start with a "*" have no
-special meaning - they are only for the human reader's benefit and do
-not define additional subtopics.  Here is an example:
-* Foo: FOO's Node      This tells about FOO
-The subtopic name is Foo, and the node describing it is "FOO's Node".
-The rest of the line is just for the reader's Information.
-[[ But this line is not a real menu item, simply because there is
-no line above it which starts with "* Menu:".]]
-
-  When you use a menu to go to another node (in a way that will be
-described soon), what you specify is the subtopic name, the first
-thing in the menu line.  Ibrowse uses it to find the menu line, extracts
-the node name from it, and goes to that node.  The reason that there
-is both a subtopic name and a node name is that the node name must be
-meaningful to the computer and may therefore have to be ugly looking.
-The subtopic name can be chosen just to be convenient for the user to
-specify.  Often the node name is convenient for the user to specify
-and so both it and the subtopic name are the same.  There is an
-abbreviation for this:
-* Foo::   This tells about FOO
-This means that the subtopic name and node name are the same; they are
-both "Foo".
-
->>  Now use Spaces to find the menu in this node, then come back to
-the front with a "b".  As you see, a menu is actually visible
-in its node.  If you can't find a menu in a node by looking at it,
-then the node doesn't have a menu and the "m" command is not available.
-
-  (Actually, a quicker way to see if there is a node menu, is to look
-for an Ibrowse menu at the top named "Menu".)
-
-  The command to go to one of the subnodes is "m" - but DON'T DO IT
-YET!  Before you use "m", you must understand the difference between
-commands and arguments.  So far, you have learned several commands
-that do not need arguments.  When you type one, Ibrowse processes it and
-is instantly ready for another command.  The "m" command is different:
-it is incomplete without the NAME OF THE SUBTOPIC.  Once you have
-typed "m", Ibrowse wants to read the subtopic name.
-
-  Thanks to modern user interface technology, this will be obvious:
-you are prompted for the subtopic name in a dialog box.  When you are
-finished typing the name, press Return or click the OK button.  You can
-cancel the dialog box by clicking the Cancel button.  The first subtopic
-is provided as a default choice, so if you want to go there, you can
-just press Return.
-
-  You can abbreviate the subtopic name.  If the abbreviation is not
-unique, the first matching subtopic is chosen.  Some menus will put
-the shortest possible abbreviation for each subtopic name in capital
-letters, so you can see how much you need to type.  It does not
-matter whether you use upper case or lower case when you type the
-subtopic.  You should not put any spaces at the end, or inside of the
-item name, except for one space where a space appears in the item in
-the menu.
-
-  Here is a menu to give you a chance to practice.
-
-* Menu:           The menu starts here.
-
-This menu gives you three ways of going to one place, Help-FOO.
-
-* Foo: Help-FOO        A node you can visit for fun
-* Bar: Help-FOO        Strange!  two ways to get to the same place.
-* Help-FOO::           And yet another!
-
->> Now type just an "m" and see what happens. (Read ahead before
->> trying this out, as the dialog box will probably cover these
->> instructions!)
-
-  Now you are "inside" an "m" command.  Commands can't be used now;
-the next thing you will type must be the name of a subtopic.
-
-  You can change your mind about doing the "m" by clicking the Cancel
-button.
->> Try that now;  notice the dialog box disappear.
->> Then type another "m".
-
->> Now type "BAR", the item name.  Don't type Return yet.
-
-  While you are typing the item name, you can use the Backspace
-key to cancel one character at a time if you make a mistake.
->> Type one to cancel the "R".  You could type another "R" to
-replace it.  You don't have to, since "BA" is a valid abbreviation.
->> Now you are ready to go.  Type a Return.
-
-  After visiting Help-FOO, you should return here (it will tell how).
-
->> Type "n" to see more commands.
-\1f
-File: ibrowse  Node: Help-FOO  Up: Help-M
-
-The "u" command
-
-  Congratulations!  This is the node Help-FOO.  Unlike the other
-nodes you have seen, this one has an "Up": "Help-M", the node you
-just came from via the "m" command.  This is the usual convention--
-the nodes you reach from a menu have Ups that lead back to the menu.
-Menus move Down in the tree, and Up moves Up.  Previous, on the other
-hand, is usually used to "stay on the same level but go backwards".
-
-  You can go back to the node Help-M by typing the command
-"u" for "Up".  That will put you at the FRONT of the node - to get
-back to where you were reading you will have to type some Spaces.
-
->> Now type "u" to move back up to Help-M.
-\1f\f
-File: ibrowse  Node: Help-Adv  Next: Help-Q    Previous: Help-M
-
-Some advanced Ibrowse commands
-
-  The course is almost over, so please stick with it to the end.
-
-  If you have been moving around to different nodes and wish to
-retrace your steps, the "l" command ("l" for "last") will do that, one
-node at a time.  If you have been following directions, an "l" command
-now will get you back to Help-M.  Another "l" command would undo the "u"
-and get you back to Help-FOO.  Another "l" would undo the M and get you
-back to Help-M.
-
->> Try typing three "l"'s, pausing in between to see what each "l" does.
-Then follow directions again and you will end up back here.
-
-  Note the difference between "l" and "p":  "l" moves to where YOU
-last were, whereas "p" always moves to the node which the header says
-is the "Previous" node (from this node, to Help-M).
-
-  The "d" command gets you instantly to the Directory node.
-This node, which is the first one you saw when you entered Ibrowse,
-has a menu which leads (directly, or indirectly through other menus),
-to all the nodes that exist.
-
->> Try doing a "d", then do an "l" to return here (yes, DO return).
-
-  Sometimes, in Ibrowse documentation, you will see a cross reference.
-Cross references look like this: *Note Cross: Help-Cross.  That is a
-real, live cross reference which is named "Cross" and points at the
-node named "Help-Cross".
-
-  If you wish to follow a cross reference, you must use the "f"
-command.  The "f" prompts for the cross reference name (in this case,
-"Cross") with a dialog box.
-
->> Type "f", followed by "Cross", and a Return.
-
-  The "f" command allows abbreviations just like "m".
-
-  To get a list of all the cross references in the current node,
-look in the Ibrowse menu at the top labeled "Footnotes".  This menu is
-only present if there are cross references in the current node, and
-can be used to directly follow a cross reference, just like the "Menu"
-menu is another way to choose an item of the node's menu.
-
->> Now type "n" to see the last node of the course.
-\1f
-File: ibrowse  Node: Help-Cross
-
-  This is the node reached by the cross reference named "Cross".
-
-  While this node is specifically intended to be reached by a cross
-reference, most cross references lead to nodes that "belong" someplace
-else far away in the structure of Ibrowse.  So you can't expect the
-footnote to have a Next, Previous or Up pointing back to where you
-came from.  In general, the "l" (el) command is the only way to get
-back there.
-
->> Type "l" to return to the node where the cross reference was.
-\1f
-File: ibrowse  Node: Help-Q    Previous: Help-Adv      Up: Top
-
-  To get out of Ibrowse, type "q" for "Quit".  All Ibrowse windows
-will be closed (on UNIX, only those managed by the same process).
-To close just one window, use the standard method of closing windows
-on your system; you can also use "w".
-
-  This is the end of the course on using Ibrowse.  There are some other
-commands that are not essential or meant for experienced users;  they
-are useful, and you can find them by looking in the directory for
-documentation on Ibrowse.  Finding them will be a good exercise in using
-Ibrowse in the usual manner.
-
->> Close this window and find back the window where you typed "h"
-   to enter this tutorial.
-   Then type "d" to go to the Ibrowse directory node if necessary,
-   and choose the "Ibrowse" menu item, to get to the node about
-   Ibrowse and see what other help is available.
-\1f\f
-File: ibrowse,  Node: Expert,  Up: Top,  Previous: Top,  Next: Add
-
-Some Advanced Ibrowse Commands ("c", "k", "g", "s", "1" - "9", arrows).
-
-The "c" command lets you copy text from the window to the clipboard.
-You must first select the text to be copied with the mouse.
-
-The "k" command means "klone" (we are running out of letters now...).
-It creates a new Ibrowse window, showing the same node as the current.
-You can then make an excursion in the new window to different nodes or
-files, while the old window keeps showing the original node.  Each
-window has its own history for use by the "l" command.
-
-If you know a node's name, you can go there with the "g" command.
-This prompts for a node name with a dialog box.  Entering, "Top"
-would go to the node called Top in this file (its directory node).
-Pressing "g" again and entering "Expert" would come back here.
-
-Unlike "m", "g" does not allow the use of abbreviations.
-
-To go to a node in another file, you can include the filename in the
-node name by putting it at the front, in parentheses.  Thus,
-"(dir)Top" would go to the Ibrowse Directory node, which is
-node Top in the file dir.
-
-The node name "*" specifies the whole file.  So you can look at all
-of the current file by typing "*" or all of any other file
-with "(FILENAME)*".
-
-File names are converted to lower case before they are tried; this
-is necessary to be compatible with Emacs Info.  (File names are
-generally relative to the Info directory, but needn't be.)
-
-The "s" command allows you to search a whole file for a regular
-expression.  Unlike the corresponding Emacs Info command, it will
-not search beyond the end of the current node.
-
-Regular expressions are like in UNIX egrep; if you don't know what
-regular expressions are, limit your search strings to letters, digits
-and spaces.  Searches in Ibrowse are case-sensitive; searching for
-"foo" will not find "Foo" or "FOO"!
-
-A description of regular expressions as they occur in Emacs is
-available.  (*Note Emacs Regular Expressions: (regex)syntax.)
-Ibrowse regular expressions are slightly different: the meaning
-of \( \| \) is swapped with that of ( | ), and there are no
-escapes to handle "words" specially.
-
-Searching starts after the current focus position.  The "B" command
-resets the focus to the beginning of the file, but space and backspace
-leave it unchanged (so they may render the focus invisible).
-
-If you grudge the system each character of type-in it requires,
-you might like to use the commands "1", "2", "3", through "9".
-They are short for the first nine entries of the node menu.
-
-The left, right and up arrow keys are duplicates of "p", "n" and "u".
-
-The down arrow key, as well as the Return key, goes to the first item
-of the node's menu if there is one, else it executes "n".  This is a
-quick way to visit all nodes in a tree in pre-order: use Return to go
-down and right as far as possible, then use "u" and "n" to go right
-at the next higher level.
-\1f\f
-File: ibrowse,  Node: Add,  Up: Top,  Previous: Expert,  Next: Menus
-
-To add a new topic to the list in the directory, you must
- 1) enter the Emacs text editor.  *Note Emacs: (emacs).
- 2) create a node, in some file, to document that topic.
- 3) put that topic in the menu in the directory.  *Note Menu: Menus.
-
-  The new node can live in an existing documentation file, or in a new
-one.  It must have a ^_ character before it (invisible to the user;
-this node has one but you can't see it), and it ends with either a ^_,
-or the end of file.  A nice way to make a node boundary be a
-page boundary as well is to put a ^L RIGHT AFTER the ^_.
-
-  The ^_ starting a node must be followed by a newline or a ^L newline,
-after which comes the node's header line.  The header line must give
-the node's name (by which Ibrowse will find it), and state the names of
-the Next, Previous, and Up nodes (if there are any).  As you can see,
-this node's Up node is the node Top, which points at all the
-documentation for Ibrowse.  The Next node is "Menus".
-
-  The keywords "Node", "Previous", "Up" and "Next",  may appear in
-any order, anywhere in the header line, but the recommended order is
-the one in this sentence.  Each keyword must be followed by a colon,
-spaces and tabs, and then the appropriate name.  The name may be
-terminated with a tab, a comma, or a newline.  A space does not end
-it; node names may contain spaces.  The case of letters in the names
-is insignificant.  "Previous" can be abbreviated to "Prev".
-
-  A node name has two forms.  A node in the current file is named by
-what appears after the "Node: " in that node's first line.  For
-example, this node's name is "Add".  A node in another file is named
-by "(FILENAME)NODE-WITHIN-FILE", as in "(ibrowse)Add" for this node.
-If the file name is relative, it is taken starting from the standard
-Info file directory of your site.  The name "(FILENAME)Top" can be
-abbreviated to just "(FILENAME)".  By convention, the name "Top" is
-used for the "highest" node in any single file - the node whose "Up"
-points out of the file.  The Directory node is "(dir)".  The Top node
-of a document file listed in the Directory should have an "Up: (dir)"
-in it.
-
-  The node name "*" is special: it refers to the entire file.  Thus,
-g* will show you the whole current file.  The use of the node * is to
-make it possible to make old-fashioned, unstructured files into nodes
-of the tree.  Footnotes and node menus appearing in a file are disabled
-when it is viewed in this way.
-
-  The "Node:" name, in which a node states its own name, must not
-contain a filename, since Ibrowse when searching for a node does not
-expect one to be there.  The Next, Previous and Up names may contain
-them.  In this node, since the Up node is in the same file, it was not
-necessary to use one. 
-
-  Note that the nodes in this file have a File name in the header
-line.  The File names are ignored by Ibrowse, but they serve as
-comments to help identify the node for the user.
-\1f\f
-File: ibrowse, Node: Menus, Previous: Add, Up: Top, Next: Cross-refs
-
-How to Create Menus:
-
-  Any node in the Ibrowse hierarchy may have a MENU--a list of subnodes. 
-The "m" command searches the current node's menu for the topic which it
-reads from the terminal.
-
-  A menu begins with a line starting with "* Menu:".  The rest of the
-line is a comment.  After the starting line, every line that begins
-with a "* " lists a single topic.  The name of the topic--the arg
-that the user must give to the "m" command to select this topic--
-comes right after the star and space, and is followed by 
-a colon, spaces and tabs, and the name of the node which discusses
-that topic.  The node name, like node names following Next,
-Previous and Up, may be terminated with a tab, comma, or newline;
-it may also be terminated with a period.
-
-  If the node name and topic name are the same, than rather than
-giving the name twice, the abbreviation "* NAME::" may be used
-(and should be used, whenever possible, as it reduces the visual
-clutter in the menu).
-
-  It is considerate to choose the topic names so that they differ
-from each other very near the beginning--this allows the user to type
-short abbreviations.  In a long menu, it is a good idea to capitalize
-the beginning of each item name which is the minimum acceptable
-abbreviation for it (a long menu is more than 5 or so entries).
-
-  The node's listed in a node's menu are called its "subnodes", and
-it is their "superior".  They should each have an "Up:" pointing at
-the superior.  It is often useful to arrange all or most of the
-subnodes in a sequence of Next's/Previous's so that someone who
-wants to see them all need not keep revisiting the Menu.
-
-  The Info Directory is simply the menu of the node "(dir)Top"--that
-is, node Top in file .../info/dir.  You can put new entries in that
-menu just like any other menu.  The Info Directory is NOT the same as
-the file directory called "info".  It happens that many of Ibrowse's
-files live on that file directory, but they don't have to; and files
-on that directory are not automatically listed in the Info Directory
-node.
-
-  The Ibrowse program uses a second directory called .../ibrowse,
-which contains versions of the "dir" and "info" files adapted to
-Ibrowse (the latter renamed to "ibrowse", obviously).  It searches
-any file first in the "ibrowse", then in the "info" directory.
-(Actually, the search path is configurable.)
-
-  Also, although the Info node graph is claimed to be a "hierarchy",
-in fact it can be ANY directed graph.  Shared structures and pointer
-cycles are perfectly possible, and can be used if they are
-appropriate to the meaning to be expressed.  There is no need for all
-the nodes in a file to form a connected structure.  In fact, this
-file has two connected components.  You are in one of them, which is
-under the node Top;  the other contains the node Help which the "h"
-command goes to.  In fact, since there is no garbage collector,
-nothing terrible happens if a substructure is not pointed to, but
-such a substructure will be rather useless since nobody will ever
-find out that it exists.
-\1f
-File: ibrowse, Node: Cross-refs, Previous: Menus, Up: Top, Next: Tags
-
-Creating Cross References:
-
-  A cross reference can be placed anywhere in the text, unlike a menu
-item which must go at the front of a line.  A cross reference looks
-like a menu item except that it has "*note" instead of "*".  It CANNOT
-be terminated by a ")", because ")"'s are so often part of node names.
-If you wish to enclose a cross reference in parentheses, terminate it
-with a period first.  Here are two examples of cross references pointers:
-
-     *Note details: commands.  (See *note 3: Full Proof.)
-
-They are just examples.  The places they "lead to" don't really exist!
-\1f
-File: ibrowse,  Node: Tags,  Previous: Cross-refs,  Up: Top,  Next: Checking
-
-Tag Tables for Info Files:
-
-  You can speed up the access to nodes of a large Info file by giving
-it a tag table.  Unlike the tag table for a program, the tag table for
-an Info file lives inside the file itself and will automatically be
-used whenever Ibrowse reads in the file.
-
-  To make a tag table, go to a node in the file using Emacs Info and type
-M-x Info-tagify.  Then you must use C-x C-s to save the file.
-
-  Once the Info file has a tag table, you must make certain it is up
-to date.  If, as a result of deletion of text, any node moves back
-more than a thousand characters in the file from the position
-recorded in the tag table, Ibrowse will no longer be able to find that
-node.  To update the tag table, use the Info-tagify command again.
-
-  An Info file tag table appears at the end of the file and looks like
-this:
-
-^_^L
-Tag Table:
-File: ibrowse, Node: Cross-refs\7f21419
-File: ibrowse,  Node: Tags\7f22145
-^_
-End Tag Table
-
-Note that it contains one line per node, and this line contains
-the beginning of the node's header (ending just after the node name),
-a rubout (DEL) character, and the character position in the file of the
-beginning of the node.  The words "Tag Table" may occur in lower case
-as well.
-
-It is also possible for an extra level of indirection to be present.
-In this case, the first line of the Tag table contains the string
-"(Indirect)", and preceding the tag table is another "pseudo node"
-whose header reads "Indirect:".  Each following line has the form
-"filename: offset", meaning that nodes at that offset or larger (but
-less than the offset in the next line) really occur in the file named
-here, and that the file's offset should be subtracted from the node's
-offset.  (Indirect tables are created by texinfo for large files.
-*Note Texinfo: (texinfo).  *Note Splitting files: (texinfo)Splitting.)
-\1f
-File: ibrowse,  Node: Checking,  Previous: Tags,  Up: Top
-
-Checking an Info File:
-
-  When creating an Info file, it is easy to forget the name of a node
-when you are making a pointer to it from another node.  If you put in
-the wrong name for a node, this will not be detected until someone
-tries to go through the pointer using Ibrowse.  Verification of the Info
-file is an automatic process which checks all pointers to nodes and
-reports any pointers which are invalid.  Every Next, Previous, and Up
-is checked, as is every menu item and every cross reference.  In addition,
-any Next which doesn't have a Previous pointing back is reported.
-Only pointers within the file are checked, because checking pointers
-to other files would be terribly slow.  But those are usually few.
-
-  To check an Info file, do M-x Info-validate while looking at any
-node of the file with Emacs Info.
-\1f\f
-Tag table:
-Node: Top\7f117
-Node: Summary\7f952
-Node: Help-Small-Screen\7f997
-Node: Help\7f2628
-Node: Help-P\7f3588
-Node: Help-Page\7f4348
-Node: Help-M\7f7763
-Node: Help-FOO\7f13183
-Node: Help-Adv\7f13887
-Node: Help-Cross\7f15923
-Node: Help-Q\7f16443
-Node: Expert\7f17326
-Node: Add\7f20280
-Node: Menus\7f23273
-Node: Cross-refs\7f26394
-Node: Tags\7f27050
-Node: Checking\7f28966
-\1f
-End tag table
diff --git a/Demo/ibrowse/ibrowse.py b/Demo/ibrowse/ibrowse.py
deleted file mode 100755 (executable)
index 41574ad..0000000
+++ /dev/null
@@ -1,617 +0,0 @@
-# Browser for "Info files" as used by the Emacs documentation system.
-#
-# Now you can read Info files even if you can't spare the memory, time or
-# disk space to run Emacs.  (I have used this extensively on a Macintosh
-# with 1 Megabyte main memory and a 20 Meg harddisk.)
-#
-# You can give this to someone with great fear of complex computer
-# systems, as long as they can use a mouse.
-#
-# Another reason to use this is to encourage the use of Info for on-line
-# documentation of software that is not related to Emacs or GNU.
-# (In particular, I plan to redo the Python and STDWIN documentation
-# in texinfo.)
-
-
-# NB: this is not a self-executing script.  You must startup Python,
-# import ibrowse, and call ibrowse.main().  On UNIX, the script 'ib'
-# runs the browser.
-
-
-# Configuration:
-#
-# - The pathname of the directory (or directories) containing
-#   the standard Info files should be set by editing the
-#   value assigned to INFOPATH in module ifile.py.
-#
-# - The default font should be set by editing the value of FONT
-#   in this module (ibrowse.py).
-#
-# - For fastest I/O, you may look at BLOCKSIZE and a few other
-#   constants in ifile.py.
-
-
-# This is a fairly large Python program, split in the following modules:
-#
-# ibrowse.py   Main program and user interface.
-#              This is the only module that imports stdwin.
-#
-# ifile.py     This module knows about the format of Info files.
-#              It is imported by all of the others.
-#
-# itags.py     This module knows how to read prebuilt tag tables,
-#              including indirect ones used by large texinfo files.
-#
-# icache.py    Caches tag tables and visited nodes.
-
-
-# XXX There should really be a different tutorial, as the user interface
-# XXX differs considerably from Emacs...
-
-
-import sys
-import regexp
-import stdwin
-from stdwinevents import *
-import string
-from ifile import NoSuchFile, NoSuchNode
-import icache
-
-
-# Default font.
-# This should be an acceptable argument for stdwin.setfont();
-# on the Mac, this can be a pair (fontname, pointsize), while
-# under X11 it should be a standard X11 font name.
-# For best results, use a constant width font like Courier;
-# many Info files contain tabs that don't align with other text
-# unless all characters have the same width.
-#
-#FONT = ('Monaco', 9)          # Mac
-FONT = '-schumacher-clean-medium-r-normal--14-140-75-75-c-70-iso8859-1'        # X11
-
-
-# Try not to destroy the list of windows when reload() is used.
-# This is useful during debugging, and harmless in production...
-#
-try:
-       dummy = windows
-       del dummy
-except NameError:
-       windows = []
-
-
-# Default main function -- start at the '(dir)' node.
-#
-def main():
-       start('(dir)')
-
-
-# Start at an arbitrary node.
-# The default file is 'ibrowse'.
-#
-def start(ref):
-       stdwin.setdefscrollbars(0, 1)
-       stdwin.setfont(FONT)
-       stdwin.setdefwinsize(76*stdwin.textwidth('x'), 22*stdwin.lineheight())
-       makewindow('ibrowse', ref)
-       mainloop()
-
-
-# Open a new browser window.
-# Arguments specify the default file and a node reference
-# (if the node reference specifies a file, the default file is ignored).
-#
-def makewindow(file, ref):
-       win = stdwin.open('Info file Browser, by Guido van Rossum')
-       win.mainmenu = makemainmenu(win)
-       win.navimenu = makenavimenu(win)
-       win.textobj = win.textcreate((0, 0), win.getwinsize())
-       win.file = file
-       win.node = ''
-       win.last = []
-       win.pat = ''
-       win.dispatch = idispatch
-       win.nodemenu = None
-       win.footmenu = None
-       windows.append(win)
-       imove(win, ref)
-
-# Create the 'Ibrowse' menu for a new browser window.
-#
-def makemainmenu(win):
-       mp = win.menucreate('Ibrowse')
-       mp.callback = []
-       additem(mp, 'New window (clone)',       'K', iclone)
-       additem(mp, 'Help (tutorial)',          'H', itutor)
-       additem(mp, 'Command summary',          '?', isummary)
-       additem(mp, 'Close this window',        'W', iclose)
-       additem(mp, '', '', None)
-       additem(mp, 'Copy to clipboard',        'C', icopy)
-       additem(mp, '', '', None)
-       additem(mp, 'Search regexp...',         'S', isearch)
-       additem(mp, '', '', None)
-       additem(mp, 'Reset node cache',         '',  iresetnodecache)
-       additem(mp, 'Reset entire cache',       '',  iresetcache)
-       additem(mp, '', '', None)
-       additem(mp, 'Quit',                     'Q', iquit)
-       return mp
-
-# Create the 'Navigation' menu for a new browser window.
-#
-def makenavimenu(win):
-       mp = win.menucreate('Navigation')
-       mp.callback = []
-       additem(mp, 'Menu item...',             'M', imenu)
-       additem(mp, 'Follow reference...',      'F', ifollow)
-       additem(mp, 'Go to node...',            'G', igoto)
-       additem(mp, '', '', None)
-       additem(mp, 'Next node in tree',        'N', inext)
-       additem(mp, 'Previous node in tree',    'P', iprev)
-       additem(mp, 'Up in tree',               'U', iup)
-       additem(mp, 'Last visited node',        'L', ilast)
-       additem(mp, 'Top of tree',              'T', itop)
-       additem(mp, 'Directory node',           'D', idir)
-       return mp
-
-# Add an item to a menu, and a function to its list of callbacks.
-# (Specifying all in one call is the only way to keep the menu
-# and the list of callbacks in synchrony.)
-#
-def additem(mp, text, shortcut, function):
-       if shortcut:
-               mp.additem(text, shortcut)
-       else:
-               mp.additem(text)
-       mp.callback.append(function)
-
-
-# Stdwin event processing main loop.
-# Return when there are no windows left.
-# Note that windows not in the windows list don't get their events.
-#
-def mainloop():
-       while windows:
-               event = stdwin.getevent()
-               if event[1] in windows:
-                       try:
-                               event[1].dispatch(event)
-                       except KeyboardInterrupt:
-                               # The user can type Control-C (or whatever)
-                               # to leave the browser without closing
-                               # the window.  Mainly useful for
-                               # debugging.
-                               break
-                       except:
-                               # During debugging, it was annoying if
-                               # every mistake in a callback caused the
-                               # whole browser to crash, hence this
-                               # handler.  In a production version
-                               # it may be better to disable this.
-                               #
-                               msg = sys.exc_type
-                               if sys.exc_value:
-                                       val = sys.exc_value
-                                       if type(val) <> type(''):
-                                               val = `val`
-                                       msg = msg + ': ' + val
-                               msg = 'Oops, an exception occurred: ' + msg
-                               event = None
-                               stdwin.message(msg)
-               event = None
-
-
-# Handle one event.  The window is taken from the event's window item.
-# This function is placed as a method (named 'dispatch') on the window,
-# so the main loop will be able to handle windows of a different kind
-# as well, as long as they are all placed in the list of windows.
-#
-def idispatch(event):
-       type, win, detail = event
-       if type == WE_CHAR:
-               if not keybindings.has_key(detail):
-                       detail = string.lower(detail)
-               if keybindings.has_key(detail):
-                       keybindings[detail](win)
-                       return
-               if detail in '0123456789':
-                       i = eval(detail) - 1
-                       if i < 0: i = len(win.menu) + i
-                       if 0 <= i < len(win.menu):
-                               topic, ref = win.menu[i]
-                               imove(win, ref)
-                               return
-               stdwin.fleep()
-               return
-       if type == WE_COMMAND:
-               if detail == WC_LEFT:
-                       iprev(win)
-               elif detail == WC_RIGHT:
-                       inext(win)
-               elif detail == WC_UP:
-                       iup(win)
-               elif detail == WC_DOWN:
-                       idown(win)
-               elif detail == WC_BACKSPACE:
-                       ibackward(win)
-               elif detail == WC_RETURN:
-                       idown(win)
-               else:
-                       stdwin.fleep()
-               return
-       if type == WE_MENU:
-               mp, item = detail
-               if mp == None:
-                       pass # A THINK C console menu was selected
-               elif mp in (win.mainmenu, win.navimenu):
-                       mp.callback[item](win)
-               elif mp == win.nodemenu:
-                       topic, ref = win.menu[item]
-                       imove(win, ref)
-               elif mp == win.footmenu:
-                       topic, ref = win.footnotes[item]
-                       imove(win, ref)
-               return
-       if type == WE_SIZE:
-               win.textobj.move((0, 0), win.getwinsize())
-               (left, top), (right, bottom) = win.textobj.getrect()
-               win.setdocsize(0, bottom)
-               return
-       if type == WE_CLOSE:
-               iclose(win)
-               return
-       if not win.textobj.event(event):
-               pass
-
-
-# Paging callbacks
-
-def ibeginning(win):
-       win.setorigin(0, 0)
-       win.textobj.setfocus(0, 0) # To restart searches
-
-def iforward(win):
-       lh = stdwin.lineheight() # XXX Should really use the window's...
-       h, v = win.getorigin()
-       docwidth, docheight = win.getdocsize()
-       width, height = win.getwinsize()
-       if v + height >= docheight:
-               stdwin.fleep()
-               return
-       increment = max(lh, ((height - 2*lh) / lh) * lh)
-       v = v + increment
-       win.setorigin(h, v)
-
-def ibackward(win):
-       lh = stdwin.lineheight() # XXX Should really use the window's...
-       h, v = win.getorigin()
-       if v <= 0:
-               stdwin.fleep()
-               return
-       width, height = win.getwinsize()
-       increment = max(lh, ((height - 2*lh) / lh) * lh)
-       v = max(0, v - increment)
-       win.setorigin(h, v)
-
-
-# Ibrowse menu callbacks
-
-def iclone(win):
-       stdwin.setdefwinsize(win.getwinsize())
-       makewindow(win.file, win.node)
-
-def itutor(win):
-       # The course looks best at 76x22...
-       stdwin.setdefwinsize(76*stdwin.textwidth('x'), 22*stdwin.lineheight())
-       makewindow('ibrowse', 'Help')
-
-def isummary(win):
-       stdwin.setdefwinsize(76*stdwin.textwidth('x'), 22*stdwin.lineheight())
-       makewindow('ibrowse', 'Summary')
-
-def iclose(win):
-       #
-       # Remove the window from the windows list so the mainloop
-       # will notice if all windows are gone.
-       # Delete the textobj since it constitutes a circular reference
-       # to the window which would prevent it from being closed.
-       # (Deletion is done by assigning None to avoid crashes
-       # when closing a half-initialized window.)
-       #
-       if win in windows:
-               windows.remove(win)
-       win.textobj = None
-
-def icopy(win):
-       focustext = win.textobj.getfocustext()
-       if not focustext:
-               stdwin.fleep()
-       else:
-               stdwin.rotatecutbuffers(1)
-               stdwin.setcutbuffer(0, focustext)
-               # XXX Should also set the primary selection...
-
-def isearch(win):
-       try:
-               pat = stdwin.askstr('Search pattern:', win.pat)
-       except KeyboardInterrupt:
-               return
-       if not pat:
-               pat = win.pat
-               if not pat:
-                       stdwin.message('No previous pattern')
-                       return
-       try:
-               cpat = regexp.compile(pat)
-       except regexp.error, msg:
-               stdwin.message('Bad pattern: ' + msg)
-               return
-       win.pat = pat
-       f1, f2 = win.textobj.getfocus()
-       text = win.text
-       match = cpat.match(text, f2)
-       if not match:
-               stdwin.fleep()
-               return
-       a, b = match[0]
-       win.textobj.setfocus(a, b)
-
-
-def iresetnodecache(win):
-       icache.resetnodecache()
-
-def iresetcache(win):
-       icache.resetcache()
-
-def iquit(win):
-       for win in windows[:]:
-               iclose(win)
-
-
-# Navigation menu callbacks
-
-def imenu(win):
-       ichoice(win, 'Menu item (abbreviated):', win.menu, whichmenuitem(win))
-
-def ifollow(win):
-       ichoice(win, 'Follow reference named (abbreviated):', \
-               win.footnotes, whichfootnote(win))
-
-def igoto(win):
-       try:
-               choice = stdwin.askstr('Go to node (full name):', '')
-       except KeyboardInterrupt:
-               return
-       if not choice:
-               stdwin.message('Sorry, Go to has no default')
-               return
-       imove(win, choice)
-
-def inext(win):
-       prev, next, up = win.header
-       if next:
-               imove(win, next)
-       else:
-               stdwin.fleep()
-
-def iprev(win):
-       prev, next, up = win.header
-       if prev:
-               imove(win, prev)
-       else:
-               stdwin.fleep()
-
-def iup(win):
-       prev, next, up = win.header
-       if up:
-               imove(win, up)
-       else:
-               stdwin.fleep()
-
-def ilast(win):
-       if not win.last:
-               stdwin.fleep()
-       else:
-               i = len(win.last)-1
-               lastnode, lastfocus = win.last[i]
-               imove(win, lastnode)
-               if len(win.last) > i+1:
-                       # The move succeeded -- restore the focus
-                       win.textobj.setfocus(lastfocus)
-               # Delete the stack top even if the move failed,
-               # else the whole stack would remain unreachable
-               del win.last[i:] # Delete the entry pushed by imove as well!
-
-def itop(win):
-       imove(win, '')
-
-def idir(win):
-       imove(win, '(dir)')
-
-
-# Special and generic callbacks
-
-def idown(win):
-       if win.menu:
-               default = whichmenuitem(win)
-               for topic, ref in win.menu:
-                       if default == topic:
-                               break
-               else:
-                       topic, ref = win.menu[0]
-               imove(win, ref)
-       else:
-               inext(win)
-
-def ichoice(win, prompt, list, default):
-       if not list:
-               stdwin.fleep()
-               return
-       if not default:
-               topic, ref = list[0]
-               default = topic
-       try:
-               choice = stdwin.askstr(prompt, default)
-       except KeyboardInterrupt:
-               return
-       if not choice:
-               return
-       choice = string.lower(choice)
-       n = len(choice)
-       for topic, ref in list:
-               topic = string.lower(topic)
-               if topic[:n] == choice:
-                       imove(win, ref)
-                       return
-       stdwin.message('Sorry, no topic matches ' + `choice`)
-
-
-# Follow a reference, in the same window.
-#
-def imove(win, ref):
-       savetitle = win.gettitle()
-       win.settitle('Looking for ' + ref + '...')
-       #
-       try:
-               file, node, header, menu, footnotes, text = \
-                       icache.get_node(win.file, ref)
-       except NoSuchFile, file:
-               win.settitle(savetitle)
-               stdwin.message(\
-               'Sorry, I can\'t find a file named ' + `file` + '.')
-               return
-       except NoSuchNode, node:
-               win.settitle(savetitle)
-               stdwin.message(\
-               'Sorry, I can\'t find a node named ' + `node` + '.')
-               return
-       #
-       win.settitle('Found (' + file + ')' + node + '...')
-       #
-       if win.file and win.node:
-               lastnode = '(' + win.file + ')' + win.node
-               win.last.append(lastnode, win.textobj.getfocus())
-       win.file = file
-       win.node = node
-       win.header = header
-       win.menu = menu
-       win.footnotes = footnotes
-       win.text = text
-       #
-       win.setorigin(0, 0) # Scroll to the beginnning
-       win.textobj.settext(text)
-       win.textobj.setfocus(0, 0)
-       (left, top), (right, bottom) = win.textobj.getrect()
-       win.setdocsize(0, bottom)
-       #
-       if win.footmenu: win.footmenu.close()
-       if win.nodemenu: win.nodemenu.close()
-       win.footmenu = None
-       win.nodemenu = None
-       #
-       win.menu = menu
-       if menu:
-               win.nodemenu = win.menucreate('Menu')
-               digit = 1
-               for topic, ref in menu:
-                       if digit < 10:
-                               win.nodemenu.additem(topic, `digit`)
-                       else:
-                               win.nodemenu.additem(topic)
-                       digit = digit + 1
-       #
-       win.footnotes = footnotes
-       if footnotes:
-               win.footmenu = win.menucreate('Footnotes')
-               for topic, ref in footnotes:
-                       win.footmenu.additem(topic)
-       #
-       win.settitle('(' + win.file + ')' + win.node)
-
-
-# Find menu item at focus
-#
-findmenu = regexp.compile('^\* [mM]enu:').match
-findmenuitem = regexp.compile( \
-       '^\* ([^:]+):[ \t]*(:|\([^\t]*\)[^\t,\n.]*|[^:(][^\t,\n.]*)').match
-#
-def whichmenuitem(win):
-       if not win.menu:
-               return ''
-       match = findmenu(win.text)
-       if not match:
-               return ''
-       a, b = match[0]
-       i = b
-       f1, f2 = win.textobj.getfocus()
-       lastmatch = ''
-       while i < len(win.text):
-               match = findmenuitem(win.text, i)
-               if not match:
-                       break
-               (a, b), (a1, b1), (a2, b2) = match
-               if a > f1:
-                       break
-               lastmatch = win.text[a1:b1]
-               i = b
-       return lastmatch
-
-
-# Find footnote at focus
-#
-findfootnote = \
-       regexp.compile('\*[nN]ote ([^:]+):[ \t]*(:|[^:][^\t,\n.]*)').match
-#
-def whichfootnote(win):
-       if not win.footnotes:
-               return ''
-       i = 0
-       f1, f2 = win.textobj.getfocus()
-       lastmatch = ''
-       while i < len(win.text):
-               match = findfootnote(win.text, i)
-               if not match:
-                       break
-               (a, b), (a1, b1), (a2, b2) = match
-               if a > f1:
-                       break
-               lastmatch = win.text[a1:b1]
-               i = b
-       return lastmatch
-
-
-# Now all the "methods" are defined, we can initialize the table
-# of key bindings.
-#
-keybindings = {}
-
-# Window commands
-
-keybindings['k'] = iclone
-keybindings['h'] = itutor
-keybindings['?'] = isummary
-keybindings['w'] = iclose
-
-keybindings['c'] = icopy
-
-keybindings['s'] = isearch
-
-keybindings['q'] = iquit
-
-# Navigation commands
-
-keybindings['m'] = imenu
-keybindings['f'] = ifollow
-keybindings['g'] = igoto
-
-keybindings['n'] = inext
-keybindings['p'] = iprev
-keybindings['u'] = iup
-keybindings['l'] = ilast
-keybindings['d'] = idir
-keybindings['t'] = itop
-
-# Paging commands
-
-keybindings['b'] = ibeginning
-keybindings['.'] = ibeginning
-keybindings[' '] = iforward
diff --git a/Demo/ibrowse/icache.py b/Demo/ibrowse/icache.py
deleted file mode 100755 (executable)
index 0629bf9..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-# Cache management for info file processing.
-# The function get_node() is the standard interface;
-# its signature is the same as ifile.get_node() but it uses
-# the cache and supports indirect tag tables.
-
-
-import string
-import ifile
-from ifile import NoSuchNode, NoSuchFile
-import itags
-
-
-# Special hack to save the cache when using reload().
-# This can just be "cache = {}" in a production version.
-#
-try:
-       dummy = cache
-       del dummy
-except NameError:
-       cache = {}
-
-
-# Clear the entire cache.
-#
-def resetcache():
-       for key in cache.keys():
-               del cache[key]
-
-
-# Clear the node info from the cache (the most voluminous data).
-#
-def resetnodecache():
-       for key in cache.keys():
-               tags, nodes = cache[key]
-               cache[key] = tags, {}
-
-
-# Get a node.
-#
-def get_node(curfile, ref):
-       file, node = ifile.parse_ref(curfile, ref)
-       file = string.lower(file)
-       node = string.lower(node)
-       if node == '*':
-               # Don't cache whole file references;
-               # reading the data is faster than displaying it anyway.
-               return ifile.get_whole_file(file) # May raise NoSuchFile
-       if not cache.has_key(file):
-               cache[file] = get_tags(file), {} # May raise NoSuchFile
-       tags, nodes = cache[file]
-       if not nodes.has_key(node):
-               if not tags.has_key(node):
-                       raise NoSuchNode, ref
-               file1, offset, line = tags[node]
-               if not file1:
-                       file1 = file
-               file1, node1, header, menu, footnotes, text = \
-                       ifile.get_file_node(file1, offset, node)
-               nodes[node] = file, node1, header, menu, footnotes, text
-       return nodes[node]
-
-
-# Get the tag table for a file.
-# Either construct one or get the one found in the file.
-# Raise NoSuchFile if the file isn't found.
-#
-def get_tags(file):
-       f = ifile.try_open(file) # May raise NoSuchFile
-       tags = itags.get_tags(f)
-       if not tags:
-               ###print 'Scanning file...'
-               f.seek(0)
-               tags = ifile.make_tags(f)
-       return tags
diff --git a/Demo/ibrowse/ifile.py b/Demo/ibrowse/ifile.py
deleted file mode 100755 (executable)
index 7e66fcd..0000000
+++ /dev/null
@@ -1,328 +0,0 @@
-# Tools for info file processing.
-
-# XXX Need to be more careful with reading ahead searching for nodes.
-
-
-import regexp
-import string
-
-
-# Exported exceptions.
-#
-NoSuchFile = 'no such file'
-NoSuchNode = 'no such node'
-
-
-# The search path for info files; this is site-specific.
-# Directory names should end in a partname delimiter,
-# so they can simply be concatenated to a relative pathname.
-#
-#INFOPATH = ['', ':Info.Ibrowse:', ':Info:']   # Mac
-INFOPATH = ['', '/usr/local/emacs/info/']      # X11 on UNIX
-
-
-# Tunable constants.
-#
-BLOCKSIZE = 512                        # Qty to align reads to, if possible
-FUZZ = 2*BLOCKSIZE             # Qty to back-up before searching for a node
-CHUNKSIZE = 4*BLOCKSIZE                # Qty to read at once when reading lots of data
-
-
-# Regular expressions used.
-# Note that it is essential that Python leaves unrecognized backslash
-# escapes in a string so they can be seen by regexp.compile!
-#
-findheader = regexp.compile('\037\014?\n(.*\n)').match
-findescape = regexp.compile('\037').match
-parseheader = regexp.compile('[nN]ode:[ \t]*([^\t,\n]*)').match
-findfirstline = regexp.compile('^.*\n').match
-findnode = regexp.compile('[nN]ode:[ \t]*([^\t,\n]*)').match
-findprev = regexp.compile('[pP]rev[ious]*:[ \t]*([^\t,\n]*)').match
-findnext = regexp.compile('[nN]ext:[ \t]*([^\t,\n]*)').match
-findup = regexp.compile('[uU]p:[ \t]*([^\t,\n]*)').match
-findmenu = regexp.compile('^\* [mM]enu:').match
-findmenuitem = regexp.compile( \
-       '^\* ([^:]+):[ \t]*(:|\([^\t]*\)[^\t,\n.]*|[^:(][^\t,\n.]*)').match
-findfootnote = regexp.compile( \
-       '\*[nN]ote ([^:]+):[ \t]*(:|[^:][^\t,\n.]*)').match
-parsenoderef = regexp.compile('^\((.*)\)(.*)$').match
-
-
-# Get a node and all information pertaining to it.
-# This doesn't work if there is an indirect tag table,
-# and in general you are better off using icache.get_node() instead.
-# Functions get_whole_file() and get_file_node() provide part
-# functionality used by icache.
-# Raise NoSuchFile or NoSuchNode as appropriate.
-#
-def get_node(curfile, ref):
-       file, node = parse_ref(curfile, ref)
-       if node == '*':
-               return get_whole_file(file)
-       else:
-               return get_file_node(file, 0, node)
-#
-def get_whole_file(file):
-       f = try_open(file) # May raise NoSuchFile
-       text = f.read()
-       header, menu, footnotes = ('', '', ''), [], []
-       return file, '*', header, menu, footnotes, text
-#
-def get_file_node(file, offset, node):
-       f = try_open(file) # May raise NoSuchFile
-       text = find_node(f, offset, node) # May raise NoSuchNode
-       node, header, menu, footnotes = analyze_node(text)
-       return file, node, header, menu, footnotes, text
-
-
-# Parse a node reference into a file (possibly default) and node name.
-# Possible reference formats are: "NODE", "(FILE)", "(FILE)NODE".
-# Default file is the curfile argument; default node is Top.
-# A node value of '*' is a special case: the whole file should
-# be interpreted (by the caller!) as a single node.
-#
-def parse_ref(curfile, ref):
-       match = parsenoderef(ref)
-       if not match:
-               file, node = curfile, ref
-       else:
-               (a, b), (a1, b1), (a2, b2) = match
-               file, node = ref[a1:b1], ref[a2:b2]
-       if not file:
-               file = curfile # (Is this necessary?)
-       if not node:
-               node = 'Top'
-       return file, node
-
-
-# Extract node name, links, menu and footnotes from the node text.
-#
-def analyze_node(text):
-       #
-       # Get node name and links from the header line
-       #
-       match = findfirstline(text)
-       if match:
-               (a, b) = match[0]
-               line = text[a:b]
-       else:
-               line = ''
-       node = get_it(text, findnode)
-       prev = get_it(text, findprev)
-       next = get_it(text, findnext)
-       up = get_it(text, findup)
-       #
-       # Get the menu items, if there is a menu
-       #
-       menu = []
-       match = findmenu(text)
-       if match:
-               (a, b) = match[0]
-               while 1:
-                       match = findmenuitem(text, b)
-                       if not match:
-                               break
-                       (a, b), (a1, b1), (a2, b2) = match
-                       topic, ref = text[a1:b1], text[a2:b2]
-                       if ref == ':':
-                               ref = topic
-                       menu.append((topic, ref))
-       #
-       # Get the footnotes
-       #
-       footnotes = []
-       b = 0
-       while 1:
-               match = findfootnote(text, b)
-               if not match:
-                       break
-               (a, b), (a1, b1), (a2, b2) = match
-               topic, ref = text[a1:b1], text[a2:b2]
-               if ref == ':':
-                       ref = topic
-               footnotes.append((topic, ref))
-       #
-       return node, (prev, next, up), menu, footnotes
-#
-def get_it(line, matcher):
-       match = matcher(line)
-       if not match:
-               return ''
-       else:
-               (a, b), (a1, b1) = match
-               return line[a1:b1]
-
-
-# Find a node in an open file.
-# The offset (from the tags table) is a hint about the node's position.
-# Pass zero if there is no tags table.
-# Raise NoSuchNode if the node isn't found.
-# NB: This seeks around in the file.
-#
-def find_node(f, offset, node):
-       node = string.lower(node) # Just to be sure
-       #
-       # Position a little before the given offset,
-       # so we may find the node even if it has moved around
-       # in the file a little.
-       #
-       offset = max(0, ((offset-FUZZ) / BLOCKSIZE) * BLOCKSIZE)
-       f.seek(offset)
-       #
-       # Loop, hunting for a matching node header.
-       #
-       while 1:
-               buf = f.read(CHUNKSIZE)
-               if not buf:
-                       break
-               i = 0
-               while 1:
-                       match = findheader(buf, i)
-                       if match:
-                               (a,b), (a1,b1) = match
-                               start = a1
-                               line = buf[a1:b1]
-                               i = b
-                               match = parseheader(line)
-                               if match:
-                                       (a,b), (a1,b1) = match
-                                       key = string.lower(line[a1:b1])
-                                       if key == node:
-                                               # Got it!  Now read the rest.
-                                               return read_node(f, buf[start:])
-                       elif findescape(buf, i):
-                               next = f.read(CHUNKSIZE)
-                               if not next:
-                                       break
-                               buf = buf + next
-                       else:
-                               break
-       #
-       # If we get here, we didn't find it.  Too bad.
-       #
-       raise NoSuchNode, node
-
-
-# Finish off getting a node (subroutine for find_node()).
-# The node begins at the start of buf and may end in buf;
-# if it doesn't end there, read additional data from f.
-#
-def read_node(f, buf):
-       i = 0
-       match = findescape(buf, i)
-       while not match:
-               next = f.read(CHUNKSIZE)
-               if not next:
-                       end = len(buf)
-                       break
-               i = len(buf)
-               buf = buf + next
-               match = findescape(buf, i)
-       else:
-               # Got a match
-               (a, b) = match[0]
-               end = a
-       # Strip trailing newlines
-       while end > 0 and buf[end-1] == '\n':
-               end = end-1
-       buf = buf[:end]
-       return buf
-
-
-# Read reverse starting at offset until the beginning of a node is found.
-# Then return a buffer containing the beginning of the node,
-# with f positioned just after the buffer.
-# The buffer will contain at least the full header line of the node;
-# the caller should finish off with read_node() if it is the right node.
-# (It is also possible that the buffer extends beyond the node!)
-# Return an empty string if there is no node before the given offset.
-#
-def backup_node(f, offset):
-       start = max(0, ((offset-CHUNKSIZE) / BLOCKSIZE) * BLOCKSIZE)
-       end = offset
-       while start < end:
-               f.seek(start)
-               buf = f.read(end-start)
-               i = 0
-               hit = -1
-               while 1:
-                       match = findheader(buf, i)
-                       if match:
-                               (a,b), (a1,b1) = match
-                               hit = a1
-                               i = b
-                       elif end < offset and findescape(buf, i):
-                               next = f.read(min(offset-end, BLOCKSIZE))
-                               if not next:
-                                       break
-                               buf = buf + next
-                               end = end + len(next)
-                       else:
-                               break
-               if hit >= 0:
-                       return buf[hit:]
-               end = start
-               start = max(0, end - CHUNKSIZE)
-       return ''
-
-
-# Make a tag table for the given file by scanning the file.
-# The file must be open for reading, and positioned at the beginning
-# (or wherever the hunt for tags must begin; it is read till the end).
-#
-def make_tags(f):
-       tags = {}
-       while 1:
-               offset = f.tell()
-               buf = f.read(CHUNKSIZE)
-               if not buf:
-                       break
-               i = 0
-               while 1:
-                       match = findheader(buf, i)
-                       if match:
-                               (a,b), (a1,b1) = match
-                               start = offset+a1
-                               line = buf[a1:b1]
-                               i = b
-                               match = parseheader(line)
-                               if match:
-                                       (a,b), (a1,b1) = match
-                                       key = string.lower(line[a1:b1])
-                                       if tags.has_key(key):
-                                               print 'Duplicate node:',
-                                               print key
-                                       tags[key] = '', start, line
-                       elif findescape(buf, i):
-                               next = f.read(CHUNKSIZE)
-                               if not next:
-                                       break
-                               buf = buf + next
-                       else:
-                               break
-       return tags
-
-
-# Try to open a file, return a file object if succeeds.
-# Raise NoSuchFile if the file can't be opened.
-# Should treat absolute pathnames special.
-#
-def try_open(file):
-       for dir in INFOPATH:
-               try:
-                       return open(dir + file, 'r')
-               except IOError:
-                       pass
-       raise NoSuchFile, file
-
-
-# A little test for the speed of make_tags().
-#
-TESTFILE = 'texinfo-1'
-def test_make_tags():
-       import time
-       f = try_open(TESTFILE)
-       t1 = time.time()
-       tags = make_tags(f)
-       t2 = time.time()
-       print 'Making tag table for', `TESTFILE`, 'took', t2-t1, 'sec.'
diff --git a/Demo/ibrowse/itags.py b/Demo/ibrowse/itags.py
deleted file mode 100755 (executable)
index 7cddcfa..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-# Utility module for 'icache.py': interpret tag tables and indirect nodes.
-
-# (This module is a bit chatty when confronted with the unexpected.)
-
-
-import regexp
-import string
-import ifile
-
-
-# Get the tag table of an open file, as a dictionary.
-# Seeks around in the file; after reading, the position is undefined.
-# Return an empty tag table if none is found.
-#
-def get_tags(f):
-       #
-       # First see if the last "node" is the end of tag table marker.
-       #
-       f.seek(0, 2) # Seek to EOF
-       end = f.tell()
-       buf = ifile.backup_node(f, end)
-       if not labelmatch(buf, 0, 'end tag table\n'):
-               return {} # No succes
-       #
-       # Next backup to the previous "node" -- the tag table itself.
-       #
-       ###print 'Getting prebuilt tag table...'
-       end = f.tell() - len(buf)
-       buf = ifile.backup_node(f, end)
-       label = 'tag table:\n'
-       if not labelmatch(buf, 0, label):
-               print 'Weird: end tag table marker but no tag table?'
-               print 'Node begins:', `buf[:50]`
-               return {}
-       #
-       # Now read the whole tag table.
-       #
-       end = f.tell() - len(buf) # Do this first!
-       buf = ifile.read_node(f, buf)
-       #
-       # First check for an indirection table.
-       #
-       indirlist = []
-       if labelmatch(buf, len(label), '(indirect)\n'):
-               indirbuf = ifile.backup_node(f, end)
-               if not labelmatch(indirbuf, 0, 'indirect:\n'):
-                       print 'Weird: promised indirection table not found'
-                       print 'Node begins:', `indirbuf[:50]`
-                       # Carry on.  Things probably won't work though.
-               else:
-                       indirbuf = ifile.read_node(f, indirbuf)
-                       indirlist = parse_indirlist(indirbuf)
-       #
-       # Now parse the tag table.
-       #
-       findtag = regexp.compile('^(.*[nN]ode:[ \t]*(.*))\177([0-9]+)$').match
-       i = 0
-       tags = {}
-       while 1:
-               match = findtag(buf, i)
-               if not match:
-                       break
-               (a,b), (a1,b1), (a2,b2), (a3,b3) = match
-               i = b
-               line = buf[a1:b1]
-               node = string.lower(buf[a2:b2])
-               offset = eval(buf[a3:b3]) # XXX What if it overflows?
-               if tags.has_key(node):
-                       print 'Duplicate key in tag table:', `node`
-               file, offset = map_offset(offset, indirlist)
-               tags[node] = file, offset, line
-       #
-       return tags
-
-
-# Return true if buf[i:] begins with a label, after lower case conversion.
-# The label argument must be in lower case.
-#
-def labelmatch(buf, i, label):
-       return string.lower(buf[i:i+len(label)]) == label
-
-
-# Parse the indirection list.
-# Return a list of (filename, offset) pairs ready for use.
-#
-def parse_indirlist(buf):
-       list = []
-       findindir = regexp.compile('^(.+):[ \t]*([0-9]+)$').match
-       i = 0
-       while 1:
-               match = findindir(buf, i)
-               if not match:
-                       break
-               (a,b), (a1,b1), (a2,b2) = match
-               file = buf[a1:b1]
-               offset = eval(buf[a2:b2]) # XXX What if this gets overflow?
-               list.append((file, offset))
-               i = b
-       return list
-
-
-# Map an offset through the indirection list.
-# Return (filename, new_offset).
-# If the list is empty, return the given offset and an empty file name.
-#
-def map_offset(offset, indirlist):
-       if not indirlist:
-               return '', offset
-       #
-       # XXX This could be done more elegant.
-       #
-       filex, offx = indirlist[0]
-       for i in range(len(indirlist)):
-               file1, off1 = indirlist[i]
-               if i+1 >= len(indirlist):
-                       file2, off2 = '', 0x7fffffff
-               else:
-                       file2, off2 = indirlist[i+1]
-               if off1 <= offset < off2:
-                       # Add offx+2 to compensate for extra header.
-                       # No idea whether this is always correct.
-                       return file1, offset-off1 + offx+2
-       #
-       # XXX Shouldn't get here.
-       #
-       print 'Oops, map_offset fell through'
-       return '', offset # Not likely to get good results
diff --git a/Demo/sgi/cd/cdwin.py b/Demo/sgi/cd/cdwin.py
deleted file mode 100755 (executable)
index 284ad82..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-# Window interface to (some of) the CD player's vital audio functions
-
-import cd
-import stdwin
-from stdwinevents import *
-import mainloop
-
-def main():
-       player = cd.open()
-       stdwin.setdefscrollbars(0, 0)
-       win = stdwin.open('CD')
-       win.player = player
-       win.dispatch = cddispatch
-       mainloop.register(win)
-       win.settimer(10)
-       mainloop.mainloop()
-
-def cddispatch(type, win, detail):
-       if type == WE_NULL:
-               pass
-       elif type == WE_CLOSE:
-               mainloop.unregister(win)
-               win.close()
-       elif type == WE_DRAW:
-               draw(win)
-       elif type == WE_TIMER:
-               update(win)
-       elif type == WE_MOUSE_UP:
-               left, top, right, bottom, v1, v2 = getgeo(win)
-               h, v = detail[0]
-               if left < h < right:
-                       if top < v < v1:
-                               but1(win)
-                       elif v1 < v < v2:
-                               but2(win)
-                       elif v2 < v < bottom:
-                               but3(win)
-                       else:
-                               stdwin.fleep()
-
-def but1(win):
-       update(win)
-
-def but2(win):
-       state = win.player.getstatus()[0]
-       if state == cd.ready:
-               win.player.play(1, 1)
-       elif state in (cd.playing, cd.paused):
-               win.player.togglepause()
-       else:
-               stdwin.fleep()
-       update(win)
-
-def but3(win):
-       win.player.stop()
-       update(win)
-
-def update(win):
-       d = win.begindrawing()
-       drawstatus(win, d)
-       d.enddrawing()
-       win.settimer(10)
-
-statedict = ['ERROR', 'NODISK', 'READY', 'PLAYING', 'PAUSED', 'STILL']
-
-def draw(win):
-       left, top, right, bottom, v1, v2 = getgeo(win)
-       d = win.begindrawing()
-       drawstatus(win, d)
-       box(d, left, v1, right, v2, 'Play/Pause')
-       box(d, left, v2, right, bottom, 'Stop')
-       d.enddrawing()
-
-def drawstatus(win, d):
-       left, top, right, bottom, v1, v2 = getgeo(win)
-       state, track, curtime, abstime, totaltime, first, last, \
-               scsi_audio, cur_block, dummy = win.player.getstatus()
-       if 0 <= state < len(statedict):
-               message = statedict[state]
-       else:
-               message = `status`
-       message = message + ' track ' + `track` + ' of ' + `last`
-       d.erase((left, top), (right, v1))
-       box(d, left, top, right, v1, message)
-
-def box(d, left, top, right, bottom, label):
-       R = (left+1, top+1), (right-1, bottom-1)
-       width = d.textwidth(label)
-       height = d.lineheight()
-       h = (left + right - width) / 2
-       v = (top + bottom - height) / 2
-       d.box(R)
-       d.cliprect(R)
-       d.text((h, v), label)
-       d.noclip()
-
-def getgeo(win):
-       (left, top), (right, bottom) = (0, 0), win.getwinsize()
-       v1 = top + (bottom - top) / 3
-       v2 = top + (bottom - top) * 2 / 3
-       return left, top, right, bottom, v1, v2
-
-main()
diff --git a/Demo/threads/wpi.py b/Demo/threads/wpi.py
deleted file mode 100644 (file)
index d4c0ef9..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-# Display digits of pi in a window, calculating in a separate thread.
-# Compare ../scripts/pi.py.
-
-import sys
-import time
-import thread
-import stdwin
-from stdwinevents import *
-
-ok = 1
-
-digits = []
-
-def worker():
-       k, a, b, a1, b1 = 2l, 4l, 1l, 12l, 4l
-       while ok:
-               # Next approximation
-               p, q, k = k*k, 2l*k+1l, k+1l
-               a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1
-               # Print common digits
-               d, d1 = a/b, a1/b1
-               #print a, b, a1, b1
-               while d == d1:
-                       digits.append(`int(d)`)
-                       a, a1 = 10l*(a%b), 10l*(a1%b1)
-                       d, d1 = a/b, a1/b1
-
-def main():
-       global ok
-       digits_seen = 0
-       thread.start_new_thread(worker, ())
-       tw = stdwin.textwidth('0 ')
-       lh = stdwin.lineheight()
-       stdwin.setdefwinsize(20 * tw, 20 * lh)
-       stdwin.setdefscrollbars(0, 1)
-       win = stdwin.open('digits of pi')
-       options = win.menucreate('Options')
-       options.additem('Auto scroll')
-       autoscroll = 1
-       options.check(0, autoscroll)
-       while 1:
-               win.settimer(1)
-               type, w, detail = stdwin.getevent()
-               if type == WE_CLOSE:
-                       ok = 0
-                       sys.exit(0)
-               elif type == WE_DRAW:
-                       (left, top), (right, bottom) = detail
-                       digits_seen = len(digits)
-                       d = win.begindrawing()
-                       for i in range(digits_seen):
-                               h = (i % 20) * tw
-                               v = (i / 20) * lh
-                               if top-lh < v < bottom:
-                                       d.text((h, v), digits[i])
-                       d.close()
-               elif type == WE_TIMER:
-                       n = len(digits)
-                       if n > digits_seen:
-                               win.settitle(`n` + ' digits of pi')
-                               d = win.begindrawing()
-                               for i in range(digits_seen, n):
-                                       h = (i % 20) * tw
-                                       v = (i / 20) * lh
-                                       d.text((h, v), digits[i])
-                               d.close()
-                               digits_seen = n
-                               height = (v + 20*lh) / (20*lh) * (20*lh)
-                               win.setdocsize(0, height)
-                               if autoscroll:
-                                       win.show((0, v), (h+tw, v+lh))
-               elif type == WE_MENU:
-                       menu, item = detail
-                       if menu == options:
-                               if item == 0:
-                                       autoscroll = (not autoscroll)
-                                       options.check(0, autoscroll)
-                                       
-
-main()