From 81b4e41cd9c4587c56f4ff87c04864c8bc532921 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Thu, 11 May 2000 18:27:21 +0000 Subject: removing more stdwin users --- Demo/cwilib/cwilib.py | 213 -------------- Demo/cwilib/form.py | 170 ------------ Demo/cwilib/vt100.py | 328 ---------------------- Demo/cwilib/vt100win.py | 78 ------ Demo/ibrowse/README | 34 --- Demo/ibrowse/ib | 2 - Demo/ibrowse/ib.py | 21 -- Demo/ibrowse/ibrowse | 719 ------------------------------------------------ Demo/ibrowse/ibrowse.py | 617 ----------------------------------------- Demo/ibrowse/icache.py | 74 ----- Demo/ibrowse/ifile.py | 328 ---------------------- Demo/ibrowse/itags.py | 127 --------- Demo/sgi/cd/cdwin.py | 103 ------- Demo/threads/wpi.py | 80 ------ 14 files changed, 2894 deletions(-) delete mode 100755 Demo/cwilib/cwilib.py delete mode 100755 Demo/cwilib/form.py delete mode 100755 Demo/cwilib/vt100.py delete mode 100755 Demo/cwilib/vt100win.py delete mode 100644 Demo/ibrowse/README delete mode 100755 Demo/ibrowse/ib delete mode 100755 Demo/ibrowse/ib.py delete mode 100755 Demo/ibrowse/ibrowse delete mode 100755 Demo/ibrowse/ibrowse.py delete mode 100755 Demo/ibrowse/icache.py delete mode 100755 Demo/ibrowse/ifile.py delete mode 100755 Demo/ibrowse/itags.py delete mode 100755 Demo/sgi/cd/cdwin.py delete mode 100644 Demo/threads/wpi.py diff --git a/Demo/cwilib/cwilib.py b/Demo/cwilib/cwilib.py deleted file mode 100755 index 2b19637..0000000 --- a/Demo/cwilib/cwilib.py +++ /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 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 index 8dd6ef9..0000000 --- a/Demo/cwilib/form.py +++ /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 index 9edd481..0000000 --- a/Demo/cwilib/vt100.py +++ /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 index 122e5f9..0000000 --- a/Demo/cwilib/vt100win.py +++ /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 index 22e4039..0000000 --- a/Demo/ibrowse/README +++ /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 index 04cb790..0000000 --- a/Demo/ibrowse/ib +++ /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 index ce6e16a..0000000 --- a/Demo/ibrowse/ib.py +++ /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 index 8b0dcde..0000000 --- a/Demo/ibrowse/ibrowse +++ /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. - -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. - -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. - -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. - -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. - -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. - -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. - -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. - -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. - -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. - -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. - -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. - -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. - -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. - -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. - -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! - -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-refs21419 -File: ibrowse, Node: Tags22145 -^_ -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.) - -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. - -Tag table: -Node: Top117 -Node: Summary952 -Node: Help-Small-Screen997 -Node: Help2628 -Node: Help-P3588 -Node: Help-Page4348 -Node: Help-M7763 -Node: Help-FOO13183 -Node: Help-Adv13887 -Node: Help-Cross15923 -Node: Help-Q16443 -Node: Expert17326 -Node: Add20280 -Node: Menus23273 -Node: Cross-refs26394 -Node: Tags27050 -Node: Checking28966 - -End tag table diff --git a/Demo/ibrowse/ibrowse.py b/Demo/ibrowse/ibrowse.py deleted file mode 100755 index 41574ad..0000000 --- a/Demo/ibrowse/ibrowse.py +++ /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 index 0629bf9..0000000 --- a/Demo/ibrowse/icache.py +++ /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 index 7e66fcd..0000000 --- a/Demo/ibrowse/ifile.py +++ /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 index 7cddcfa..0000000 --- a/Demo/ibrowse/itags.py +++ /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 index 284ad82..0000000 --- a/Demo/sgi/cd/cdwin.py +++ /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 index d4c0ef9..0000000 --- a/Demo/threads/wpi.py +++ /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() -- cgit v0.12