summaryrefslogtreecommitdiffstats
path: root/Demo/stdwin/ibrowse/ibrowse.py
diff options
context:
space:
mode:
Diffstat (limited to 'Demo/stdwin/ibrowse/ibrowse.py')
-rwxr-xr-xDemo/stdwin/ibrowse/ibrowse.py617
1 files changed, 0 insertions, 617 deletions
diff --git a/Demo/stdwin/ibrowse/ibrowse.py b/Demo/stdwin/ibrowse/ibrowse.py
deleted file mode 100755
index eec5eb7..0000000
--- a/Demo/stdwin/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