diff options
Diffstat (limited to 'Demo/stdwin/ibrowse/ibrowse.py')
-rwxr-xr-x | Demo/stdwin/ibrowse/ibrowse.py | 617 |
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 |