From dab6cb8f6dacc107e9482976ca2f8e0313f05131 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Thu, 11 May 2000 14:43:52 +0000 Subject: removing more stdwin users --- Demo/sgi/audio_stdwin/README | 19 - Demo/sgi/audio_stdwin/jukebox.py | 321 ----------------- Demo/sgi/audio_stdwin/rec.py | 268 -------------- Demo/sgi/audio_stdwin/vumeter.py | 35 -- Demo/sgi/gl/glstdwin/fontchart.py | 34 -- Demo/sgi/gl/glstdwin/glstdwdraw.py | 135 ------- Demo/sgi/gl/glstdwin/glstdwin.py | 400 --------------------- Demo/sgi/gl/glstdwin/glstdwmenu.py | 62 ---- Demo/sgi/gl/glstdwin/glstdwwin.py | 139 ------- Demo/sgi/gl/glstdwin/stdwingl.py | 10 - Demo/sgi/gl/glstdwin/tcolor.py | 43 --- Demo/sgi/gl/glstdwin/tglsw.py | 70 ---- Demo/sgi/gl/glstdwin/tmenu.py | 44 --- Demo/stdwin/FormTest.py | 30 -- Demo/stdwin/README | 18 - Demo/stdwin/RadioGroups.py | 98 ----- Demo/stdwin/TestCSplit.py | 25 -- Demo/stdwin/TestDirList.py | 18 - Demo/stdwin/TestFormSplit.py | 27 -- Demo/stdwin/TestSched.py | 38 -- Demo/stdwin/TestTextEdit.py | 13 - Demo/stdwin/clock.py | 193 ---------- Demo/stdwin/ibrowse/README | 34 -- Demo/stdwin/ibrowse/dir | 62 ---- Demo/stdwin/ibrowse/ib | 2 - Demo/stdwin/ibrowse/ib.py | 21 -- Demo/stdwin/ibrowse/ibrowse | 719 ------------------------------------- Demo/stdwin/ibrowse/ibrowse.py | 617 ------------------------------- Demo/stdwin/ibrowse/icache.py | 74 ---- Demo/stdwin/ibrowse/ifile.py | 328 ----------------- Demo/stdwin/ibrowse/itags.py | 127 ------- Demo/stdwin/jukebox.py | 413 --------------------- Demo/stdwin/lpwin.py | 198 ---------- Demo/stdwin/microedit.py | 183 ---------- Demo/stdwin/miniedit.py | 356 ------------------ Demo/stdwin/python.py | 449 ----------------------- Demo/stdwin/wdiff.py | 484 ------------------------- 37 files changed, 6107 deletions(-) delete mode 100644 Demo/sgi/audio_stdwin/README delete mode 100755 Demo/sgi/audio_stdwin/jukebox.py delete mode 100755 Demo/sgi/audio_stdwin/rec.py delete mode 100755 Demo/sgi/audio_stdwin/vumeter.py delete mode 100644 Demo/sgi/gl/glstdwin/fontchart.py delete mode 100644 Demo/sgi/gl/glstdwin/glstdwdraw.py delete mode 100644 Demo/sgi/gl/glstdwin/glstdwin.py delete mode 100644 Demo/sgi/gl/glstdwin/glstdwmenu.py delete mode 100644 Demo/sgi/gl/glstdwin/glstdwwin.py delete mode 100644 Demo/sgi/gl/glstdwin/stdwingl.py delete mode 100644 Demo/sgi/gl/glstdwin/tcolor.py delete mode 100644 Demo/sgi/gl/glstdwin/tglsw.py delete mode 100644 Demo/sgi/gl/glstdwin/tmenu.py delete mode 100755 Demo/stdwin/FormTest.py delete mode 100644 Demo/stdwin/README delete mode 100755 Demo/stdwin/RadioGroups.py delete mode 100755 Demo/stdwin/TestCSplit.py delete mode 100755 Demo/stdwin/TestDirList.py delete mode 100755 Demo/stdwin/TestFormSplit.py delete mode 100755 Demo/stdwin/TestSched.py delete mode 100755 Demo/stdwin/TestTextEdit.py delete mode 100755 Demo/stdwin/clock.py delete mode 100644 Demo/stdwin/ibrowse/README delete mode 100755 Demo/stdwin/ibrowse/dir delete mode 100755 Demo/stdwin/ibrowse/ib delete mode 100755 Demo/stdwin/ibrowse/ib.py delete mode 100755 Demo/stdwin/ibrowse/ibrowse delete mode 100755 Demo/stdwin/ibrowse/ibrowse.py delete mode 100755 Demo/stdwin/ibrowse/icache.py delete mode 100755 Demo/stdwin/ibrowse/ifile.py delete mode 100755 Demo/stdwin/ibrowse/itags.py delete mode 100755 Demo/stdwin/jukebox.py delete mode 100755 Demo/stdwin/lpwin.py delete mode 100755 Demo/stdwin/microedit.py delete mode 100755 Demo/stdwin/miniedit.py delete mode 100755 Demo/stdwin/python.py delete mode 100755 Demo/stdwin/wdiff.py diff --git a/Demo/sgi/audio_stdwin/README b/Demo/sgi/audio_stdwin/README deleted file mode 100644 index 6d96fe1..0000000 --- a/Demo/sgi/audio_stdwin/README +++ /dev/null @@ -1,19 +0,0 @@ -Three programs that provide a user interface based upon STDWIN to the -audio device of the SGI 4D/25. These scripts also demonstrate the power -of a set of window interface classes implemented in Python that simplify -the construction of all sorts of buttons, etc. - -XXX This hardware is already obsolete; see ../al for examples of audio -XXX on the Indigo and 4D/35. - -jukebox Browses a directory full of sound samples and lets you - play selected ones. (Probably not fully functional, it - requires a conversion program.) - -rec A tape recorder that lets you record a sound sample, - play it back, and save it to a file. Various options to - set sampling rate, volume etc. When idle it doubles - as a VU meter. - -vumeter A VU meter that displays a history of the volume of - sound recently sampled from the microphone. diff --git a/Demo/sgi/audio_stdwin/jukebox.py b/Demo/sgi/audio_stdwin/jukebox.py deleted file mode 100755 index 2aaaa83..0000000 --- a/Demo/sgi/audio_stdwin/jukebox.py +++ /dev/null @@ -1,321 +0,0 @@ -#! /usr/bin/env python - -# JUKEBOX: browse directories full of sampled sound files. -# -# One or more "list windows" display the files and subdirectories of -# the arguments. Double-clicking on a subdirectory opens a new window -# displaying its contents (and so on recursively). Double clicking -# on a file plays it as a sound file (assuming it is one). -# -# Playing is asynchronous: the application keeps listening to events -# while the sample is playing, so you can change the volume (gain) -# during playing, cancel playing or start a new sample right away. -# -# The control window displays the current output gain and a primitive -# "stop button" to cancel the current play request. -# -# Sound files must currently be in Dik Winter's compressed Mac format. -# Since decompression is costly, decompressed samples are saved in -# /usr/tmp/@j* until the application is left. The files are read -# afresh each time, though. - -import audio -import sunaudio -import commands -import getopt -import path -import posix -import rand -import stdwin -from stdwinevents import * -import string -import sys - -from WindowParent import WindowParent -from HVSplit import VSplit -from Buttons import PushButton -from Sliders import ComplexSlider - -# Pathnames - -HOME_BIN_SGI = '/ufs/guido/bin/sgi/' # Directory where macsound2sgi lives -DEF_DB = '/ufs/dik/sounds/Mac/HCOM' # Default directory of sounds - - -# Global variables - -class struct: pass # Class to define featureless structures - -G = struct() # Holds writable global variables - - -# Main program - -def main(): - G.synchronous = 0 # If set, use synchronous audio.write() - G.debug = 0 # If set, print debug messages - G.gain = 75 # Output gain - G.rate = 3 # Sampling rate - G.busy = 0 # Set while asynchronous playing is active - G.windows = [] # List of open windows (except control) - G.mode = 'mac' # Macintosh mode - G.tempprefix = '/usr/tmp/@j' + `rand.rand()` + '-' - # - optlist, args = getopt.getopt(sys.argv[1:], 'dg:r:sSa') - for optname, optarg in optlist: - if optname == '-d': - G.debug = 1 - elif optname == '-g': - G.gain = string.atoi(optarg) - if not (0 < G.gain < 256): - raise optarg.error, '-g gain out of range' - elif optname == '-r': - G.rate = string.atoi(optarg) - if not (1 <= G.rate <= 3): - raise optarg.error, '-r rate out of range' - elif optname == '-s': - G.synchronous = 1 - elif optname == '-S': - G.mode = 'sgi' - elif optname == '-a': - G.mode = 'sun' - # - if not args: - args = [DEF_DB] - # - G.cw = opencontrolwindow() - for dirname in args: - G.windows.append(openlistwindow(dirname)) - # - # - savegain = audio.getoutgain() - try: - # Initialize stdaudio - audio.setoutgain(0) - audio.start_playing('') - dummy = audio.wait_playing() - audio.setoutgain(0) - maineventloop() - finally: - audio.setoutgain(savegain) - audio.done() - clearcache() - -def maineventloop(): - mouse_events = WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP - while G.windows: - type, w, detail = event = stdwin.getevent() - if w == G.cw.win: - if type == WE_CLOSE: - return - G.cw.dispatch(event) - else: - if type == WE_DRAW: - w.drawproc(w, detail) - elif type in mouse_events: - w.mouse(w, type, detail) - elif type == WE_CLOSE: - w.close(w) - del w, event - else: - if G.debug: print type, w, detail - -# Control window -- to set gain and cancel play operations in progress - -def opencontrolwindow(): - cw = WindowParent().create('Jukebox', (0, 0)) - v = VSplit().create(cw) - # - gain = ComplexSlider().define(v) - gain.setminvalmax(0, G.gain, 255) - gain.settexts(' ', ' ') - gain.sethook(gain_setval_hook) - # - stop = PushButton().definetext(v, 'Stop') - stop.hook = stop_hook - # - cw.realize() - return cw - -def gain_setval_hook(self): - G.gain = self.val - if G.busy: audio.setoutgain(G.gain) - -def stop_hook(self): - if G.busy: - audio.setoutgain(0) - dummy = audio.stop_playing() - G.busy = 0 - - -# List windows -- to display list of files and subdirectories - -def openlistwindow(dirname): - list = posix.listdir(dirname) - list.sort() - i = 0 - while i < len(list): - if list[i] == '.' or list[i] == '..': - del list[i] - else: - i = i+1 - for i in range(len(list)): - name = list[i] - if path.isdir(path.join(dirname, name)): - list[i] = list[i] + '/' - width = maxwidth(list) - width = width + stdwin.textwidth(' ') # XXX X11 stdwin bug workaround - height = len(list) * stdwin.lineheight() - stdwin.setdefwinsize(width, min(height, 500)) - w = stdwin.open(dirname) - stdwin.setdefwinsize(0, 0) - w.setdocsize(width, height) - w.drawproc = drawlistwindow - w.mouse = mouselistwindow - w.close = closelistwindow - w.dirname = dirname - w.list = list - w.selected = -1 - return w - -def maxwidth(list): - width = 1 - for name in list: - w = stdwin.textwidth(name) - if w > width: width = w - return width - -def drawlistwindow(w, area): - d = w.begindrawing() - d.erase((0, 0), (1000, 10000)) - lh = d.lineheight() - h, v = 0, 0 - for name in w.list: - d.text((h, v), name) - v = v + lh - showselection(w, d) - -def hideselection(w, d): - if w.selected >= 0: - invertselection(w, d) - -def showselection(w, d): - if w.selected >= 0: - invertselection(w, d) - -def invertselection(w, d): - lh = d.lineheight() - h1, v1 = p1 = 0, w.selected*lh - h2, v2 = p2 = 1000, v1 + lh - d.invert(p1, p2) - -def mouselistwindow(w, type, detail): - (h, v), clicks, button = detail[:3] - d = w.begindrawing() - lh = d.lineheight() - if 0 <= v < lh*len(w.list): - i = v / lh - else: - i = -1 - if w.selected <> i: - hideselection(w, d) - w.selected = i - showselection(w, d) - if type == WE_MOUSE_DOWN and clicks >= 2 and i >= 0: - name = path.join(w.dirname, w.list[i]) - if name[-1:] == '/': - if clicks == 2: - G.windows.append(openlistwindow(name[:-1])) - else: - playfile(name) - -def closelistwindow(w): - remove(G.windows, w) - -def remove(list, item): - for i in range(len(list)): - if list[i] == item: - del list[i] - break - - -# Playing tools - -cache = {} - -def clearcache(): - for x in cache.keys(): - try: - sts = posix.system('rm -f ' + cache[x]) - if sts: - print cmd - print 'Exit status', sts - except: - print cmd - print 'Exception?!' - del cache[x] - -def playfile(name): - if G.mode <> 'mac': - tempname = name - elif cache.has_key(name): - tempname = cache[name] - else: - tempname = G.tempprefix + `rand.rand()` - cmd = HOME_BIN_SGI + 'macsound2sgi' - cmd = cmd + ' ' + commands.mkarg(name) - cmd = cmd + ' >' + tempname - if G.debug: print cmd - sts = posix.system(cmd) - if sts: - print cmd - print 'Exit status', sts - stdwin.fleep() - return - cache[name] = tempname - fp = open(tempname, 'r') - try: - hdr = sunaudio.gethdr(fp) - except sunaudio.error, msg: - hdr = () - if hdr: - data_size = hdr[0] - data = fp.read(data_size) - # XXX this doesn't work yet, need to convert from uLAW!!! - del fp - else: - del fp - data = readfile(tempname) - if G.debug: print len(data), 'bytes read from', tempname - if G.busy: - G.busy = 0 - dummy = audio.stop_playing() - # - # Completely reset the audio device - audio.setrate(G.rate) - audio.setduration(0) - audio.setoutgain(G.gain) - # - if G.synchronous: - audio.write(data) - audio.setoutgain(0) - else: - try: - audio.start_playing(data) - G.busy = 1 - except: - stdwin.fleep() - del data - -def readfile(filename): - return readfp(open(filename, 'r')) - -def readfp(fp): - data = '' - while 1: - buf = fp.read(102400) # Reads most samples in one fell swoop - if not buf: - return data - data = data + buf - -main() diff --git a/Demo/sgi/audio_stdwin/rec.py b/Demo/sgi/audio_stdwin/rec.py deleted file mode 100755 index 76e924e..0000000 --- a/Demo/sgi/audio_stdwin/rec.py +++ /dev/null @@ -1,268 +0,0 @@ -#! /usr/bin/env python - -import sys -import audio -import stdwin - -import string -import getopt - -from stdwinevents import * -from Buttons import * -from Sliders import * -#from Soundogram import Soundogram -from VUMeter import VUMeter -from WindowParent import WindowParent, MainLoop -from HVSplit import HSplit, VSplit - -class TimeOutToggleButton(ToggleButton): - def define(self, parent): - self = ToggleButton.define(self, parent) - self.parent.need_timer(self) - self.timer_hook = 0 - return self - def timer(self): - if self.timer_hook: - self.timer_hook(self) - -K = 1024 -BUFSIZE = 30*8*K -Rates = [0, 32*K, 16*K, 8*K] -Magics = ['', '0032', '0016', '0008'] - -class Struct: pass -G = Struct() - -def main(): - # - # Turn off scroll bars - # - stdwin.setdefscrollbars(0, 0) - # - # Set default state - # - G.gain = 60 - G.rate = 3 - G.nomuting = 0 - G.savefile = '@rec' - # - # Set default values - # - G.data = '' - G.playing = 0 - G.recording = 0 - G.sogram = 0 - # - # Parse options - # - optlist, args = getopt.getopt(sys.argv[1:], 'mdg:r:') - # - for optname, optarg in optlist: - if 0: # (So all cases start with elif) - pass - elif optname == '-d': - G.debug = 1 - elif optname == '-g': - G.gain = string.atoi(optarg) - if not (0 < G.gain < 256): - raise optarg.error, '-g gain out of range' - elif optname == '-m': - G.nomuting = (not G.nomuting) - elif optname == '-r': - G.rate = string.atoi(optarg) - if not (1 <= G.rate <= 3): - raise optarg.error, '-r rate out of range' - # - if args: - G.savefile = args[0] - # - # Initialize the sound package - # - audio.setoutgain(G.nomuting * G.gain) # Silence the speaker - audio.setrate(G.rate) - # - # Create the WindowParent and VSplit - # - G.window = WindowParent().create('Recorder', (0, 0)) - w = G.vsplit = VSplit().create(G.window) - # - # VU-meter - # - G.vubtn = VUMeter().define(w) - # - # Radiobuttons for rates - # - r1btn = RadioButton().definetext(w, '32 K/sec') - r1btn.on_hook = rate_hook - r1btn.rate = 1 - # - r2btn = RadioButton().definetext(w, '16 K/sec') - r2btn.on_hook = rate_hook - r2btn.rate = 2 - # - r3btn = RadioButton().definetext(w, '8 K/sec') - r3btn.on_hook = rate_hook - r3btn.rate = 3 - # - radios = [r1btn, r2btn, r3btn] - r1btn.group = r2btn.group = r3btn.group = radios - for r in radios: - if r.rate == G.rate: r.select(1) - # - # Other controls - # - G.recbtn = TimeOutToggleButton().definetext(w, 'Record') - G.recbtn.on_hook = record_on_hook - G.recbtn.timer_hook = record_timer_hook - G.recbtn.off_hook = record_off_hook - # - G.mutebtn = CheckButton().definetext(w, 'Mute') - G.mutebtn.select(not G.nomuting) - G.mutebtn.hook = mute_hook - # - G.playbtn = TimeOutToggleButton().definetext(w, 'Playback') - G.playbtn.on_hook = play_on_hook - G.playbtn.timer_hook = play_timer_hook - G.playbtn.off_hook = play_off_hook - # - G.gainbtn = ComplexSlider().define(w) - G.gainbtn.settexts(' Volume: ', ' ') - G.gainbtn.setminvalmax(0, G.gain, 255) - G.gainbtn.sethook(gain_hook) - # - G.sizebtn = Label().definetext(w, `len(G.data)` + ' bytes') - # - #G.showbtn = PushButton().definetext(w, 'Sound-o-gram...') - #G.showbtn.hook = show_hook - # - G.savebtn = PushButton().definetext(w, 'Save...') - G.savebtn.hook = save_hook - # - G.quitbtn = PushButton().definetext(w, 'Quit') - G.quitbtn.hook = quit_hook - G.playbtn.enable(0) - G.savebtn.enable(0) - #G.showbtn.enable(0) - start_vu() - G.window.realize() - # - # Event loop - # - MainLoop() - -# XXX Disabled... -def show_hook(self): - savetext = self.text - self.settext('Be patient...') - close_sogram() - stdwin.setdefwinsize(400, 300) - win = stdwin.open('Sound-o-gram') - G.sogram = Soundogram().define(win, G.data) - win.buttons = [G.sogram] - self.settext(savetext) - -def close_sogram(): - if G.sogram: - # Break circular references - G.sogram.win.buttons[:] = [] - del G.sogram.win - G.sogram = 0 - -def mute_hook(self): - G.nomuting = (not self.selected) - audio.setoutgain(G.nomuting * G.gain) - -def rate_hook(self): - G.rate = self.rate - audio.setrate(G.rate) - -def record_on_hook(self): - stop_vu() - close_sogram() - audio.setrate(G.rate) - audio.setoutgain(G.nomuting * G.gain) - audio.start_recording(BUFSIZE) - G.recording = 1 - G.playbtn.enable(0) - G.window.settimer(10 * BUFSIZE / Rates[G.rate]) - -def record_timer_hook(self): - if G.recording: - if audio.poll_recording(): - self.hilite(0) - record_off_hook(self) - else: - self.parent.settimer(5) - -def record_off_hook(self): - if not G.recording: - return - G.data = audio.stop_recording() - G.recording = 0 - G.sizebtn.settext(`len(G.data)` + ' bytes') - audio.setoutgain(G.nomuting * G.gain) - G.playbtn.enable((len(G.data) > 0)) - G.savebtn.enable((len(G.data) > 0)) - #G.showbtn.enable((len(G.data) > 0)) - G.window.settimer(0) - start_vu() - -def play_on_hook(self): - stop_vu() - audio.setrate(G.rate) - audio.setoutgain(G.gain) - audio.start_playing(G.data) - G.playing = 1 - G.recbtn.enable(0) - G.window.settimer(max(10 * len(G.data) / Rates[G.rate], 1)) - -def play_timer_hook(self): - if G.playing: - if audio.poll_playing(): - self.hilite(0) - play_off_hook(self) - else: - self.parent.settimer(5) - -def play_off_hook(self): - if not G.playing: - return - x = audio.stop_playing() - G.playing = 0 - audio.setoutgain(G.nomuting * G.gain) - G.recbtn.enable(1) - G.window.settimer(0) - start_vu() - -def gain_hook(self): - G.gain = self.val - if G.playing or G.nomuting: audio.setoutgain(G.gain) - -def save_hook(self): - if not G.data: - stdwin.fleep() - else: - prompt = 'Store sampled data on file: ' - try: - G.savefile = stdwin.askfile(prompt, G.savefile, 1) - except KeyboardInterrupt: - return - try: - fp = open(G.savefile, 'w') - fp.write(Magics[G.rate] + G.data) - except: - stdwin.message('Cannot create ' + file) - -def stop_vu(): - G.vubtn.stop() - -def start_vu(): - G.vubtn.start() - -def quit_hook(self): - G.window.delayed_destroy() - -try: - main() -finally: - audio.setoutgain(0) diff --git a/Demo/sgi/audio_stdwin/vumeter.py b/Demo/sgi/audio_stdwin/vumeter.py deleted file mode 100755 index e27c538..0000000 --- a/Demo/sgi/audio_stdwin/vumeter.py +++ /dev/null @@ -1,35 +0,0 @@ -#! /usr/bin/env python - -import audio -import stdwin - -from VUMeter import VUMeter -from WindowParent import WindowParent -import MainLoop - -NBUFS=20 -BUFSIZE = NBUFS*48 -SCALE=128 - -class MyVUMeter(VUMeter): - def init_reactivity(self): - self.parent.need_mouse(self) - def mouse_down(self, detail): - if self.enabled: - self.stop() - else: - self.start() - def mouse_move(self, detail): pass - def mouse_up(self, detail): pass - -def main(): - audio.setrate(3) - audio.setoutgain(0) - w = WindowParent().create('VU Meter', (200, 100)) - v = MyVUMeter().define(w) - v.start() - w.realize() - while 1: - w.dispatch(stdwin.getevent()) - -main() diff --git a/Demo/sgi/gl/glstdwin/fontchart.py b/Demo/sgi/gl/glstdwin/fontchart.py deleted file mode 100644 index 6b58f12..0000000 --- a/Demo/sgi/gl/glstdwin/fontchart.py +++ /dev/null @@ -1,34 +0,0 @@ -import stdwingl - -import stdwin -from stdwinevents import * - -def main(): - size = 12 - w = stdwin.open('Font chart ' + `size`) - while 1: - type, window, detail = stdwin.getevent() - if type == WE_CLOSE: - break - if type == WE_DRAW: - width, height = w.getwinsize() - d = w.begindrawing() - d.setsize(size) - h, v = 0, 0 - for c in range(32, 256): - ch = chr(c) - chw = d.textwidth(ch) - if h + chw > width: - v = v + d.lineheight() - h = 0 - if v >= height: - break - d.text((h, v), ch) - h = h + chw - del d - if type == WE_MOUSE_UP: - size = size + 1 - w.settitle('Font chart ' + `size`) - w.change((0, 0), (2000, 2000)) - -main() diff --git a/Demo/sgi/gl/glstdwin/glstdwdraw.py b/Demo/sgi/gl/glstdwin/glstdwdraw.py deleted file mode 100644 index 4ddc7a6..0000000 --- a/Demo/sgi/gl/glstdwin/glstdwdraw.py +++ /dev/null @@ -1,135 +0,0 @@ -# Define drawing operations for GL stdwin - -import gl -import fm -from GL import LO_XOR, LO_SRC -from glstdwin import MASK - -class DrawingObject: - # - def _init(self, win): - self.fg = win._fg - self.bg = win._bg - self.font = win._font - self.size = win._size - self.width, self.height = win._area[1] - gl.winset(win._gid) - gl.color(self.fg) - return self - # - def setfont(self, fontname): - self.font = fm.findfont(fontname).scalefont(self.size) - # - def setsize(self, size): - ratio = float(size) / float(self.size) - self.size = size - self.font = self.font.scalefont(ratio) - # - def setfgcolor(self, color): - self.fg = color - gl.color(self.fg) - # - def setbgcolor(self, color): - self.bg = color - # - def cliprect(self, area): - #print 'cliprect', area - (left, top), (right, bottom) = area - gl.scrmask(left, right, self.height-bottom, self.height-top) - # - def noclip(self): - #print 'noclip()' - gl.scrmask(0, self.width, 0, self.height) - # - def paint(self, ((left, top), (right, bottom))): - gl.rectf(left, top, right, bottom) - # - def box(self, ((left, top), (right, bottom))): - #print 'box', ((left, top), (right, bottom)) - gl.rect(left, top, right, bottom) - # - def circle(self, (h, v), radius): - gl.circ(h, v, radius) - # - def elarc(self, center, (rh, rv), (a1, a2)): - pass # XXX - # - def erase(self, ((left, top), (right, bottom))): - #print 'erase', ((left, top), (right, bottom)) - gl.color(self.bg) - gl.rectf(left, top, right, bottom) - gl.color(self.fg) - # - def invert(self, ((left, top), (right, bottom))): - #print 'invert', ((h0, v0), (h1, v1)) - gl.logicop(LO_XOR) - gl.color(self.bg) - gl.rectf(left, top, right, bottom) - gl.color(self.fg) - gl.logicop(LO_SRC) - # - def line(self, (h0, v0), (h1, v1)): - #print 'line', ((h0, v0), (h1, v1)) - gl.bgnline() - gl.v2i(h0, v0) - gl.v2i(h1, v1) - gl.endline() - # - def xorline(self, (h0, v0), (h1, v1)): - #print 'xorline', ((h0, v0), (h1, v1)) - gl.logicop(LO_XOR) - gl.color(self.bg) - gl.bgnline() - gl.v2i(h0, v0) - gl.v2i(h1, v1) - gl.endline() - gl.color(self.fg) - gl.logicop(LO_SRC) - # - def point(self, (h, v)): - #print 'point', (h, v) - gl.bgnpoint() - gl.v2i(h, v) - gl.endpoint() - # - def text(self, (h, v), string): - #print 'text', ((h, v), string) - if h < 0: - # If the point is outside the window - # the whole string isn't drawn. - # Skip the beginning of the string. - # XXX What if the font is bigger than 20 pixels? - i, n = 0, len(string) - while h < -MASK and i < n: - h = h + self.font.getstrwidth(string[i]) - i = i + 1 - string = string[i:] - gl.cmov2(h, v + self.baseline()) - self.font.setfont() - fm.prstr(string) - # - def shade(self, (h, v), percent): - pass # XXX - # - def baseline(self): - (printermatched, fixed_width, xorig, yorig, xsize, ysize, \ - height, nglyphs) = self.font.getfontinfo() - return height - yorig - # - def lineheight(self): - (printermatched, fixed_width, xorig, yorig, xsize, ysize, \ - height, nglyphs) = self.font.getfontinfo() - return height - # - def textbreak(self, string, width): - # XXX Slooooow! - n = len(string) - nwidth = self.textwidth(string[:n]) - while nwidth > width: - n = n-1 - nwidth = self.textwidth(string[:n]) - return n - # - def textwidth(self, string): - return self.font.getstrwidth(string) - # diff --git a/Demo/sgi/gl/glstdwin/glstdwin.py b/Demo/sgi/gl/glstdwin/glstdwin.py deleted file mode 100644 index b7d02c7..0000000 --- a/Demo/sgi/gl/glstdwin/glstdwin.py +++ /dev/null @@ -1,400 +0,0 @@ -# GL STDWIN -# -# See stdwingl for a convenient hack to use this instead of built-in stdwin -# without modifying your application, except for one line in the main file. -# -# Intrinsic differences with built-in stdwin (hard or impossible to fix): -# - Need to call w.close() to close a window !!! -# - Need to call m.close() to remove a menu !!! -# - Doesn't enforce the existence of at most one drawing object -# - No textedit package -# - No X11 selections -# -# Not yet implemented: -# - shade drawing -# - elliptical arc drawing (need to play with transformation) -# - more than one mouse button -# - scroll bars (need to redo viewport handling to get this) -# - partial redraws -# - dialog boxes -# - timer events -# - cursors -# -# Extra features: -# - color (for now, you need to know the colormap index) - - -import gl -import fm -from GL import * -from DEVICE import * -from stdwinevents import * - - -# Customizable constants -# -DEF_FONT = 'Times-Roman' # Default font -DEF_SIZE = 12 # Default font size (points) -MASK = 20 # Viewport minus scrmask - - -# A structure to hold global variables -# -class Struct: pass -G = Struct() -# -G.queue = [] # Pending STDWIN events -G.drawqueue = [] # Windows that need WE_REDRAW -G.windowmap = {} # Map window id to window object -G.windowmap['0'] = None # For convenience -G.focus = None # Input focus -G.fg = BLACK # Foreground color -G.bg = WHITE # Background color -G.def_size = 0, 0 # Default window size -G.def_pos = 0, 0 # Default window position -# -G.size = DEF_SIZE -G.font = fm.findfont(DEF_FONT).scalefont(G.size) - - -# Initialize GL -# -gl.foreground() -gl.noport() -dummygid = gl.winopen('') - -# Ask for all sorts of events -# -# Both REDRAW (= resize and/or redraw!) and INPUTCHANGE are implicitly queued -#qdevice(REDRAW) -#qdevice(INPUTCHANGE) -# -# Keyboard -gl.qdevice(KEYBD) -gl.qdevice(LEFTARROWKEY) -gl.qdevice(RIGHTARROWKEY) -gl.qdevice(UPARROWKEY) -gl.qdevice(DOWNARROWKEY) -gl.qdevice(LEFTALTKEY) -gl.qdevice(RIGHTALTKEY) -# -# Mouse -gl.qdevice(LEFTMOUSE) -#gl.qdevice(MIDDLEMOUSE) -gl.qdevice(RIGHTMOUSE) # Menu button -# NB MOUSEX, MOUSEY events are queued on button down -# -# Window close requests -gl.qdevice(WINQUIT) -gl.qdevice(WINSHUT) -# -# These aren't needed -#gl.qdevice(TIMER0) -#gl.qdevice(WINFREEZE) -#gl.qdevice(WINTHAW) -#gl.qdevice(REDRAWICONIC) - - -# STDWIN: create a new window -# -def open(title): - h, v = G.def_pos - width, height = G.def_size - if h > 0 or v > 0: - # Choose arbitrary defaults - if h < 0: h = 10 - if v < 0: v = 30 - if width <= 0: width = 400 - if height <= 0: height = 300 - gl.prefposition(h, h+width, 1024-v, 1024-v-height) - elif width > 0 or height > 0: - if width <= 0: width = 400 - if height <= 0: height = 300 - gl.prefsize(width, height) - from glstdwwin import WindowObject - win = WindowObject()._init(title) - G.windowmap[`win._gid`] = win - return win - - -# STDWIN: set default initial window position (0 means use default) -# -def setdefwinpos(h, v): - G.def_pos = h, v - - -# STDWIN: set default window size (0 means use default) -# -def setdefwinsize(width, height): - G.def_size = width, height - - -# STDWIN: beep or ring the bell -# -def fleep(): - gl.ringbell() - - -# STDWIN: set default foreground color -# -def setfgcolor(color): - G.fg = color - - -# STDWIN: set default background color -# -def setbgcolor(color): - G.bg = color - - -# STDWIN: get default foreground color -# -def getfgcolor(): - return G.fgcolor - - -# STDWIN: get default background color -# -def getbgcolor(): - return G.bgcolor - - -# Table mapping characters to key codes -# -key2code = key = {} -key['A'] = AKEY -key['B'] = BKEY -key['C'] = CKEY -key['D'] = DKEY -key['E'] = EKEY -key['F'] = FKEY -key['G'] = GKEY -key['H'] = HKEY -key['I'] = IKEY -key['J'] = JKEY -key['K'] = KKEY -key['L'] = LKEY -key['M'] = MKEY -key['N'] = NKEY -key['O'] = OKEY -key['P'] = PKEY -key['Q'] = QKEY -key['R'] = RKEY -key['S'] = SKEY -key['T'] = TKEY -key['U'] = UKEY -key['V'] = VKEY -key['W'] = WKEY -key['X'] = XKEY -key['Y'] = YKEY -key['Z'] = ZKEY -key['0'] = ZEROKEY -key['1'] = ONEKEY -key['2'] = TWOKEY -key['3'] = THREEKEY -key['4'] = FOURKEY -key['5'] = FIVEKEY -key['6'] = SIXKEY -key['7'] = SEVENKEY -key['8'] = EIGHTKEY -key['9'] = NINEKEY -del key -# -code2key = {} -codelist = [] -for key in key2code.keys(): - code = key2code[key] - code2key[`code`] = key - codelist.append(code) -del key - - -# STDWIN: wait for the next event -# -commands = {} -commands['\r'] = WC_RETURN -commands['\b'] = WC_BACKSPACE -commands['\t'] = WC_TAB -# -def getevent(): - while 1: - # - # Get next event from the processed queue, if any - # - if G.queue: - event = G.queue[0] - del G.queue[0] - #print 'getevent from queue -->', event - return event - # - # Get next event from the draw queue, if any, - # but only if there is nothing in the system queue. - # - if G.drawqueue and not gl.qtest(): - win = G.drawqueue[0] - del G.drawqueue[0] - gl.winset(win._gid) - gl.color(win._bg) - gl.clear() - event = WE_DRAW, win, win._area - #print 'getevent from drawqueue -->', event - return event - # - # Get next event from system queue, blocking if necessary - # until one is available. - # Some cases immediately return the event, others do nothing - # or append one or more events to the processed queue. - # - dev, val = gl.qread() - # - if dev == REDRAW: - win = G.windowmap[`val`] - old_area = win._area - win._fixviewport() - win._needredraw() - if old_area <> win._area: - #print 'getevent --> WE_SIZE' - return WE_SIZE, win, None - elif dev == KEYBD: - if val == 3: - raise KeyboardInterrupt # Control-C in window - character = chr(val) - if commands.has_key(character): - return WE_COMMAND, G.focus, commands[character] - return WE_CHAR, G.focus, character - elif dev == LEFTARROWKEY: - if val: - return WE_COMMAND, G.focus, WC_LEFT - elif dev == RIGHTARROWKEY: - if val: - return WE_COMMAND, G.focus, WC_RIGHT - elif dev == UPARROWKEY: - if val: - return WE_COMMAND, G.focus, WC_UP - elif dev == DOWNARROWKEY: - if val: - return WE_COMMAND, G.focus, WC_DOWN - elif dev in (LEFTALTKEY, RIGHTALTKEY): - if val: - for code in codelist: - gl.qdevice(code) - else: - for code in codelist: - gl.unqdevice(code) - elif dev in codelist: - if val: - event = G.focus._doshortcut(code2key[`dev`]) - if event: - return event - elif dev == LEFTMOUSE: - G.mousex = gl.getvaluator(MOUSEX) - G.mousey = gl.getvaluator(MOUSEY) - if val: - type = WE_MOUSE_DOWN - gl.qdevice(MOUSEX) - gl.qdevice(MOUSEY) - else: - type = WE_MOUSE_UP - gl.unqdevice(MOUSEX) - gl.unqdevice(MOUSEY) - return _mouseevent(type) - elif dev == MOUSEX: - G.mousex = val - return _mouseevent(WE_MOUSE_MOVE) - elif dev == MOUSEY: - G.mousey = val - return _mouseevent(WE_MOUSE_MOVE) - elif dev == RIGHTMOUSE: # Menu button press/release - if val: # Press - event = G.focus._domenu() - if event: - return event - elif dev == INPUTCHANGE: - if G.focus: - G.queue.append(WE_DEACTIVATE, G.focus, None) - G.focus = G.windowmap[`val`] - if G.focus: - G.queue.append(WE_ACTIVATE, G.focus, None) - elif dev in (WINSHUT, WINQUIT): - return WE_CLOSE, G.windowmap[`val`], None - else: - print '*** qread() --> dev:', dev, 'val:', val - -# Helper routine to construct a mouse (up, move or down) event -# -def _mouseevent(type): - gl.winset(G.focus._gid) - orgx, orgy = gl.getorigin() - sizex, sizey = gl.getsize() - x = G.mousex - orgx - y = G.mousey - orgy - return type, G.focus, ((x, sizey-y), 1, 0, 0) - - - - -# STDWIN: text measuring functions - -def baseline(): - (printermatched, fixed_width, xorig, yorig, xsize, ysize, \ - height, nglyphs) = G.font.getfontinfo() - return height - yorig - -def lineheight(): - (printermatched, fixed_width, xorig, yorig, xsize, ysize, \ - height, nglyphs) = G.font.getfontinfo() - return height - -def textbreak(string, width): - # XXX Slooooow! - n = len(string) - nwidth = textwidth(string[:n]) - while nwidth > width: - n = n-1 - nwidth = textwidth(string[:n]) - return n - -def textwidth(string): - return G.font.getstrwidth(string) - - -# STDWIN: set default font and size - -def setfont(fontname): - G.font = fm.findfont(fontname).scalefont(G.size) - -def setsize(size): - ratio = float(size) / float(G.size) - G.size = size - G.font = G.font.scalefont(ratio) - - -# Utility functions - -# Exclusive-or of two BYTES -# -def xor(x, y): - a = bits(x) - b = bits(y) - c = [0, 0, 0, 0, 0, 0, 0, 0] - for i in range(8): - c[i] = (a[i] + b[i]) % 2 - return stib(c) - -# Return the bits of a byte as a list of 8 integers -# -def bits(x): - b = [0, 0, 0, 0, 0, 0, 0, 0] - for i in range(8): - x, b[i] = divmod(x, 2) - return b - -# Convert a list of 8 integers (0|1) to a byte -# -def stib(b): - x = 0 - shift = 1 - for i in range(8): - x = x + b[i]*shift - shift = shift*2 - return x diff --git a/Demo/sgi/gl/glstdwin/glstdwmenu.py b/Demo/sgi/gl/glstdwin/glstdwmenu.py deleted file mode 100644 index dd6d90b..0000000 --- a/Demo/sgi/gl/glstdwin/glstdwmenu.py +++ /dev/null @@ -1,62 +0,0 @@ -# Define menu operations for GL stdwin - -import gl -from glstdwin import key2code - -class MenuObject: - # - def _init(self, win, title): - self._win = win - self._title = title - self._items = [] - return self - # - def close(self): - self._win.remove(self) - del self._win - # - def additem(self, *args): - if len(args) == 2: - text, shortcut = args - elif len(args) == 1: - text, shortcut = args[0], None - else: - raise TypeError, 'arg count' - self._items.append([text, shortcut, 1, 0]) - # - def setitem(self, i, text): - self._items[i][0] = text - # - def enable(self, i, flag): - self._items[i][2] = flag - # - def check(self, i, flag): - self._items[i][3] = flag - # - def _makepup(self, firstitem): - pup = gl.newpup() - if self._title: - gl.addtopup(pup, self._title + '%t', 0) - for item in self._items: - text = item[0] - if not item[2]: # Disabled - text = ' ( ' + text + ' )%x-1' - else: - if item[3]: # Check mark - text = '-> ' + text - else: - text = ' ' + text - if key2code.has_key(item[1]): - text = text + ' [Alt-' + item[1] + ']' - text = text + '%x' + `firstitem` - gl.addtopup(pup, text, 0) - firstitem = firstitem + 1 - return pup - # - def _checkshortcut(self, char): - for i in range(len(self._items)): - item = self._items[i] - if item[2] and item[1] == char: - return i - return -1 - # diff --git a/Demo/sgi/gl/glstdwin/glstdwwin.py b/Demo/sgi/gl/glstdwin/glstdwwin.py deleted file mode 100644 index b880b9a..0000000 --- a/Demo/sgi/gl/glstdwin/glstdwwin.py +++ /dev/null @@ -1,139 +0,0 @@ -# Define window operations for STDWIN - -import gl -from stdwinevents import * -from glstdwin import G # Global variables -from glstdwin import MASK # Tunable constant - -class WindowObject: - # - def _init(self, title): - self._docsize = (0, 0) - self._fg = G.fg - self._bg = G.bg - self._title = title - self._font = G.font - self._size = G.size - self._menus = [] - self._gid = gl.winopen(title) - gl.winconstraints() # To remove prefsize() effect - self._fixviewport() - self._needredraw() - return self - # - def close(self): - del G.windowmap[`self._gid`] - gl.winclose(self._gid) - self._gid = 0 - # - def _needredraw(self): - if self in G.drawqueue: - G.drawqueue.remove(self) - G.drawqueue.append(self) - # - def begindrawing(self): - from glstdwdraw import DrawingObject - return DrawingObject()._init(self) - # - def change(self, area): - self._needredraw() - # XXX Should record the area to be drawn? - # - def gettitle(self): - return self._title - # - def getdocsize(self): - return self._docsize - # - def getorigin(self): - return self._area[0] - # - def getwinsize(self): - return self._area[1] - # - def scroll(self, area, by): - # XXX ought to use gl.rectcopy() - if by <> (0, 0): - self.change(area) - # - def setdocsize(self, docsize): - self._docsize = docsize - # - def setorigin(self, origin): - pass # XXX - # - def settimer(self, decisecs): - pass # XXX - # - def settitle(self, title): - self._title = title - gl.wintitle(title) - # - def show(self, area): - pass # XXX - # - def _fixviewport(self): - # - # Called after redraw or resize, and initially. - # - # Fix the coordinate system so that (0, 0) is top left, - # units are pixels, and positive axes point right and down. - # - # Make the viewport slightly larger than the window, - # and set the screenmask exactly to the window; this - # help fixing character clipping. - # - # Set self._area to the window rectangle in STDWIN coords. - # - gl.winset(self._gid) - gl.reshapeviewport() - x0, x1, y0, y1 = gl.getviewport() - width, height = x1-x0, y1-y0 - gl.viewport(x0-MASK, x1+MASK, y0-MASK, y1+MASK) - gl.scrmask(x0, x1, y0, y1) - gl.ortho2(-MASK, width+MASK, height+MASK, -MASK) - self._area = (0, 0), (width, height) - # - def menucreate(self, title): - from glstdwmenu import MenuObject - menu = MenuObject()._init(self, title) - self._menus.append(menu) - return menu - # - def _domenu(self): - if not self._menus: - return None - if len(self._menus) == 1: - pup = self._menus[0]._makepup(0) - val = gl.dopup(pup) - gl.freepup(pup) - if val < 0: - return None - return WE_MENU, self, (self._menus[0], val) - # - # More than one menu: use nested menus. - # - pups = [] - firstitem = 0 - for menu in self._menus: - pups.append(menu._makepup(firstitem)) - firstitem = firstitem + 100 - pup = gl.newpup() - for i in range(len(self._menus)): - gl.addtopup(pup, self._menus[i]._title + '%m', pups[i]) - val = gl.dopup(pup) - gl.freepup(pup) - for pup in pups: - gl.freepup(pup) - if val < 0: - return None - i_menu, i_item = divmod(val, 100) - return WE_MENU, self, (self._menus[i_menu], i_item) - # - def _doshortcut(self, char): - for menu in self._menus: - i = menu._checkshortcut(char) - if i >= 0: - return WE_MENU, self, (menu, i) - return None - # diff --git a/Demo/sgi/gl/glstdwin/stdwingl.py b/Demo/sgi/gl/glstdwin/stdwingl.py deleted file mode 100644 index 4427593..0000000 --- a/Demo/sgi/gl/glstdwin/stdwingl.py +++ /dev/null @@ -1,10 +0,0 @@ -# If you put 'import stdwin_gl' in front of the main program of a program -# using stdwin (before it has a chance to import the real stdwin!), -# it will use glstdwin and think it is stdwin. - -import sys -if sys.modules.has_key('stdwin'): - raise RuntimeError, 'too late -- stdwin has already been imported' - -import glstdwin -sys.modules['stdwin'] = glstdwin diff --git a/Demo/sgi/gl/glstdwin/tcolor.py b/Demo/sgi/gl/glstdwin/tcolor.py deleted file mode 100644 index d1c49e1..0000000 --- a/Demo/sgi/gl/glstdwin/tcolor.py +++ /dev/null @@ -1,43 +0,0 @@ -# Try colors -- display all 256 possible colors, with their color index - -import stdwingl - -import stdwin -from stdwinevents import * - -NROWS = 16 -NCOLS = 16 - -def main(): - stdwin.setdefwinsize(NCOLS * stdwin.textwidth('12345'), \ - NROWS * stdwin.lineheight() * 3) - w = stdwin.open('TestColors') - # - while 1: - type, window, detail = stdwin.getevent() - if type == WE_CLOSE: - print 'Bye.' - break - elif type == WE_SIZE: - w.change((0,0), (10000, 10000)) - elif type == WE_DRAW: - width, height = w.getwinsize() - d = w.begindrawing() - for row in range(NROWS): - for col in range(NCOLS): - color = row*NCOLS + col - d.setfgcolor(color) - p = col*width/NCOLS, row*height/NROWS - q = (col+1)*width/NCOLS, \ - (row+1)*height/NROWS - d.paint((p, q)) - d.setfgcolor(0) - d.box((p, q)) - d.text(p, `color`) - p = p[0] , p[1]+ d.lineheight() - d.setfgcolor(7) - d.text(p, `color`) - del d - # - -main() diff --git a/Demo/sgi/gl/glstdwin/tglsw.py b/Demo/sgi/gl/glstdwin/tglsw.py deleted file mode 100644 index 8854e98..0000000 --- a/Demo/sgi/gl/glstdwin/tglsw.py +++ /dev/null @@ -1,70 +0,0 @@ -import sys - -if len(sys.argv) < 2: - import stdwingl - color = 1 - needclose = 1 -else: - color = 0 - needclose = 0 - -import stdwin -import time -from stdwinevents import * -from GL import BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE - -def main(): - # - stdwin.setdefwinsize(300, 300) - stdwin.setdefwinpos(0, 0) - if color: stdwin.setbgcolor(YELLOW) - w1 = stdwin.open('Hello, world') - w1.box = (10, 10), (90, 90) - # - stdwin.setdefwinsize(0, 0) - stdwin.setdefwinpos(50, 50) - if color: stdwin.setbgcolor(GREEN) - w2 = stdwin.open('Second window') - w2.box = (10, 10), (90, 90) - # - while w1 or w2: - type, window, detail = stdwin.getevent() - if type == WE_DRAW: - d = window.begindrawing() - if window == w1: - if color: d.setfgcolor(BLACK) - d.box(((50, 50), (250, 250))) - if color: d.setfgcolor(RED) - d.cliprect(((50, 50), (250, 250))) - d.paint(w1.box) - d.noclip() - if color: d.setfgcolor(BLUE) - d.line((0, 0), w1.box[0]) - elif window == w2: - if color: d.setfgcolor(WHITE) - d.box(w2.box) - if color: d.setfgcolor(BLACK) - d.text(w2.box[0], 'Hello world') - else: - print 'Strange draw???', window, detail - del d - elif type == WE_CLOSE: - if needclose: window.close() - if window == w1: - w1 = None - elif window == w2: - w2 = None - else: - print 'weird close event???', window, detail - elif type in (WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP): - h, v = detail[0] - window.box = (h, v), (h+80, v+80) - window.change(((0,0), (2000, 2000))) - elif type == WE_CHAR: - print 'character', `detail` - else: - print type, window, detail - # - -main() -print 'Done.' diff --git a/Demo/sgi/gl/glstdwin/tmenu.py b/Demo/sgi/gl/glstdwin/tmenu.py deleted file mode 100644 index 233edae..0000000 --- a/Demo/sgi/gl/glstdwin/tmenu.py +++ /dev/null @@ -1,44 +0,0 @@ -# Test menus - -import stdwingl - -import stdwin -from stdwinevents import * - -def main(): - w = stdwin.open('TestMenus') - # - items1 = 'Aap', 'Noot', 'Mies' - m1 = w.menucreate('Menu-1') - for item in items1: - m1.additem(item, item[0]) - # - items2 = 'Wim', 'Zus', 'Jet', 'Teun', 'Vuur' - m2 = w.menucreate('Menu-2') - for item in items2: - m2.additem(item, `len(item)`) - # - m1.enable(1, 0) - m2.check(1, 1) - # - while 1: - type, window, detail = stdwin.getevent() - if type == WE_CLOSE: - break - elif type == WE_DRAW: - d = w.begindrawing() - d.box(((50,50), (100,100))) - del d - elif type == WE_MENU: - mp, i = detail - if mp == m1: - print 'Choice:', items1[i] - elif mp == m2: - print 'Choice:', items2[i] - else: - print 'Not one of my menus!' - elif type == WE_CHAR: - print 'Character', `detail` - # - -main() diff --git a/Demo/stdwin/FormTest.py b/Demo/stdwin/FormTest.py deleted file mode 100755 index 15e3b36..0000000 --- a/Demo/stdwin/FormTest.py +++ /dev/null @@ -1,30 +0,0 @@ -#! /usr/bin/env python - -testlabels = 'Name', 'Address', 'City', 'Country', 'Comments' - -def main(): - import stdwin - from WindowParent import WindowParent, MainLoop - from FormSplit import FormSplit - from Buttons import Label - from TextEdit import TextEdit - # - stdwin.setdefscrollbars(0, 0) - # - w = WindowParent().create('FormTest', (0, 0)) - f = FormSplit().create(w) - # - h, v = 0, 0 - for label in testlabels: - f.placenext(h, v) - lbl = Label().definetext(f, label) - f.placenext(h + 100, v) - txt = TextEdit().createboxed(f, (40, 2), (2, 2)) - #txt = TextEdit().create(f, (40, 2)) - v = v + 2*stdwin.lineheight() + 10 - # - w.realize() - # - MainLoop() - -main() diff --git a/Demo/stdwin/README b/Demo/stdwin/README deleted file mode 100644 index 5291225..0000000 --- a/Demo/stdwin/README +++ /dev/null @@ -1,18 +0,0 @@ -Contents of this directory: - -FormTest.py Show how a form can be built to enter multiple fields -RadioGroups.py Show how to use multiple groups of radio buttons -TestCSplit.py Test CSplit widget (a clock-like split) -TestDirList.py Test DirList widget (lists directory contents) -TestFormSplit.py Test FormSplit widget (arbitrary grouping) -TestSched.py Test WindowSched widget (event scheduling) -TestTextEdit.py Test TextEdit widget (probably doen't work any more) -clock.py A simple clock, with alarm -jukebox.py Play audio files (SGI only, needs SOX and SFPLAY) -lpwin.py Watch line printer queues -microedit.py The smallest window editor -miniedit.py A small multi-window editor -python.py A window interface to the Python interpreter -wdiff.py A window-based directory diff - -See ../ibrowse for another demo written using stdwin. diff --git a/Demo/stdwin/RadioGroups.py b/Demo/stdwin/RadioGroups.py deleted file mode 100755 index 93b6a2d..0000000 --- a/Demo/stdwin/RadioGroups.py +++ /dev/null @@ -1,98 +0,0 @@ -#! /usr/bin/env python - -# radiogroups.py -# -# Demonstrate multiple groups of radio buttons - -import stdwin -from Buttons import * -from WindowParent import WindowParent, MainLoop -from HVSplit import HSplit, VSplit - -def main(): - # - # Create the widget hierarchy, top-down - # - # 1. Create the window - # - window = WindowParent().create('Radio Groups', (0, 0)) - # - # 2. Create a horizontal split to contain the groups - # - topsplit = HSplit().create(window) - # - # 3. Create vertical splits, one for each group - # - group1 = VSplit().create(topsplit) - group2 = VSplit().create(topsplit) - group3 = VSplit().create(topsplit) - # - # 4. Create individual radio buttons, each in their own split - # - b11 = RadioButton().definetext(group1, 'Group 1 button 1') - b12 = RadioButton().definetext(group1, 'Group 1 button 2') - b13 = RadioButton().definetext(group1, 'Group 1 button 3') - # - b21 = RadioButton().definetext(group2, 'Group 2 button 1') - b22 = RadioButton().definetext(group2, 'Group 2 button 2') - b23 = RadioButton().definetext(group2, 'Group 2 button 3') - # - b31 = RadioButton().definetext(group3, 'Group 3 button 1') - b32 = RadioButton().definetext(group3, 'Group 3 button 2') - b33 = RadioButton().definetext(group3, 'Group 3 button 3') - # - # 5. Define the grouping for the radio buttons. - # Note: this doesn't have to be the same as the - # grouping is splits (although it usually is). - # Also set the 'hook' procedure for each button - # - list1 = [b11, b12, b13] - list2 = [b21, b22, b23] - list3 = [b31, b32, b33] - # - for b in list1: - b.group = list1 - b.on_hook = myhook - for b in list2: - b.group = list2 - b.on_hook = myhook - for b in list3: - b.group = list3 - b.on_hook = myhook - # - # 6. Select a default button in each group - # - b11.select(1) - b22.select(1) - b33.select(1) - # - # 6. Realize the window - # - window.realize() - # - # 7. Dispatch events until the window is closed - # - MainLoop() - # - # 8. Report final selections - # - print 'You selected the following choices:' - if b11.selected: print '1.1' - if b12.selected: print '1.2' - if b13.selected: print '1.3' - if b21.selected: print '2.1' - if b22.selected: print '2.2' - if b23.selected: print '2.3' - if b31.selected: print '3.1' - if b32.selected: print '3.2' - if b33.selected: print '3.3' - - -# My 'hook' procedure -# This is placed as 'hook' attribute on each button. -# The example just prints the title of the selected button. -# -def myhook(self): - print 'Selected:', self.text - -main() diff --git a/Demo/stdwin/TestCSplit.py b/Demo/stdwin/TestCSplit.py deleted file mode 100755 index 720b8c3..0000000 --- a/Demo/stdwin/TestCSplit.py +++ /dev/null @@ -1,25 +0,0 @@ -#! /usr/bin/env python - -# TestCSplit - -import stdwin -from WindowParent import WindowParent, MainLoop -from Buttons import PushButton - -def main(n): - from CSplit import CSplit - # - stdwin.setdefscrollbars(0, 0) - # - the_window = WindowParent().create('TestCSplit', (0, 0)) - the_csplit = CSplit().create(the_window) - # - for i in range(n): - the_child = PushButton().define(the_csplit) - the_child.settext(`(i+n-1)%n+1`) - # - the_window.realize() - # - MainLoop() - -main(12) diff --git a/Demo/stdwin/TestDirList.py b/Demo/stdwin/TestDirList.py deleted file mode 100755 index 321c2d9..0000000 --- a/Demo/stdwin/TestDirList.py +++ /dev/null @@ -1,18 +0,0 @@ -#! /usr/bin/env python - -# TestDirList - -from DirList import DirListWindow -from WindowParent import MainLoop - -def main(): - import sys - args = sys.argv[1:] - if not args: - args = ['.'] - # Mac: args = [':'] - for arg in args: - w = DirListWindow().create(arg) - MainLoop() - -main() diff --git a/Demo/stdwin/TestFormSplit.py b/Demo/stdwin/TestFormSplit.py deleted file mode 100755 index e67c3f9..0000000 --- a/Demo/stdwin/TestFormSplit.py +++ /dev/null @@ -1,27 +0,0 @@ -#! /usr/bin/env python - -# TestFormSplit - -import stdwin -from WindowParent import WindowParent, MainLoop -from Buttons import PushButton - -def main(n): - from FormSplit import FormSplit - # - stdwin.setdefscrollbars(1, 1) - # - the_window = WindowParent().create('TestFormSplit', (0, 0)) - the_form = FormSplit().create(the_window) - # - for i in range(n): - if i % 3 == 0: - the_form.placenext(i*40, 0) - the_child = PushButton().define(the_form) - the_child.settext('XXX-' + `i` + '-YYY') - # - the_window.realize() - # - MainLoop() - -main(6) diff --git a/Demo/stdwin/TestSched.py b/Demo/stdwin/TestSched.py deleted file mode 100755 index 29274e6..0000000 --- a/Demo/stdwin/TestSched.py +++ /dev/null @@ -1,38 +0,0 @@ -#! /usr/bin/env python - -# TestSched - -import stdwin -from WindowParent import WindowParent, MainLoop -import WindowSched -from Buttons import PushButton - -def my_ringer(child): - child.my_id = None - stdwin.fleep() - -def my_hook(child): - # schedule for the bell to ring in N seconds; cancel previous - if child.my_id: - WindowSched.cancel(child.my_id) - child.my_id = \ - WindowSched.enter(child.my_number*1000, 0, my_ringer, (child,)) - -def main(n): - from CSplit import CSplit - - window = WindowParent().create('TestSched', (0, 0)) - csplit = CSplit().create(window) - - for i in range(n): - child = PushButton().define(csplit) - child.my_number = i - child.my_id = None - child.settext(`(i+n-1)%n+1`) - child.hook = my_hook - - window.realize() - - WindowSched.run() - -main(12) diff --git a/Demo/stdwin/TestTextEdit.py b/Demo/stdwin/TestTextEdit.py deleted file mode 100755 index b15b049..0000000 --- a/Demo/stdwin/TestTextEdit.py +++ /dev/null @@ -1,13 +0,0 @@ -#! /usr/bin/env python - -# Test TextEdit widgets - -def main(): - from TextEdit import TextEdit - from WindowParent import WindowParent, MainLoop - w = WindowParent().create('Test TextEdit', (0, 0)) - t = TextEdit().create(w, (40, 4)) - w.realize() - MainLoop() - -main() diff --git a/Demo/stdwin/clock.py b/Demo/stdwin/clock.py deleted file mode 100755 index 90f1d22..0000000 --- a/Demo/stdwin/clock.py +++ /dev/null @@ -1,193 +0,0 @@ -#! /usr/bin/env python - -# 'clock' -- A simple alarm clock - -# The alarm can be set at 5 minute intervals on a 12 hour basis. -# It is controlled with the mouse: -# - Click and drag around the circle to set the alarm. -# - Click far outside the circle to clear the alarm. -# - Click near the center to set the alarm at the last time set. -# The alarm time is indicated by a small triangle just outside the circle, -# and also by a digital time at the bottom. -# The indicators disappear when the alarm is not set. -# When the alarm goes off, it beeps every minute for five minutes, -# and the clock turns into inverse video. -# Click or activate the window to turn the ringing off. - -import stdwin -from stdwinevents import WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP, \ - WE_TIMER, WE_DRAW, WE_SIZE, WE_CLOSE, WE_ACTIVATE -import mainloop -import time -from math import sin, cos, atan2, pi, sqrt - -DEFWIDTH, DEFHEIGHT = 200, 200 - -MOUSE_EVENTS = (WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP) -ORIGIN = 0, 0 -FARAWAY = 2000, 2000 -EVERYWHERE = ORIGIN, FARAWAY - - -def main(): - win = makewindow() - del win - mainloop.mainloop() - -def makewindow(): - stdwin.setdefwinsize(DEFWIDTH, DEFHEIGHT + stdwin.lineheight()) - win = stdwin.open('clock') - setdimensions(win) - win.set = 1 # True when alarm is set - win.time = 11*60 + 40 # Time when alarm must go off - win.ring = 0 # True when alarm is ringing - win.dispatch = cdispatch - mainloop.register(win) - settimer(win) - return win - -def cdispatch(event): - type, win, detail = event - if type == WE_DRAW: - drawproc(win, detail) - elif type == WE_TIMER: - settimer(win) - drawproc(win, EVERYWHERE) - elif type in MOUSE_EVENTS: - mouseclick(win, type, detail) - elif type == WE_ACTIVATE: - if win.ring: - # Turn the ringing off - win.ring = 0 - win.begindrawing().invert(win.mainarea) - elif type == WE_SIZE: - win.change(EVERYWHERE) - setdimensions(win) - elif type == WE_CLOSE: - mainloop.unregister(win) - win.close() - -def setdimensions(win): - width, height = win.getwinsize() - height = height - stdwin.lineheight() - if width < height: size = width - else: size = height - halfwidth = width/2 - halfheight = height/2 - win.center = halfwidth, halfheight - win.radius = size*45/100 - win.width = width - win.height = height - win.corner = width, height - win.mainarea = ORIGIN, win.corner - win.lineheight = stdwin.lineheight() - win.farcorner = width, height + win.lineheight - win.statusarea = (0, height), win.farcorner - win.fullarea = ORIGIN, win.farcorner - -def settimer(win): - now = time.time() - hours, minutes, seconds = win.times = calctime(now) - delay = 61 - seconds - win.settimer(10 * delay) - minutes = minutes + hours*60 - if win.ring: - # Is it time to stop the alarm ringing? - since = (minutes - win.time + 720) % 720 - if since >= 5: - # Stop it now - win.ring = 0 - else: - # Ring again, once every minute - stdwin.fleep() - elif win.set and minutes == win.time: - # Start the alarm ringing - win.ring = 1 - stdwin.fleep() - -def drawproc(win, area): - hours, minutes, seconds = win.times - d = win.begindrawing() - d.cliprect(area) - d.erase(EVERYWHERE) - d.circle(win.center, win.radius) - d.line(win.center, calcpoint(win, hours*30 + minutes/2, 0.6)) - d.line(win.center, calcpoint(win, minutes*6, 1.0)) - str = "%02d:%02d" % (hours, minutes) - p = (win.width - d.textwidth(str))/2, win.height * 3 / 4 - d.text(p, str) - if win.set: - drawalarm(win, d) - drawalarmtime(win, d) - if win.ring: - d.invert(win.mainarea) - -def mouseclick(win, type, detail): - d = win.begindrawing() - if win.ring: - # First turn the ringing off - win.ring = 0 - d.invert(win.mainarea) - h, v = detail[0] - ch, cv = win.center - x, y = h-ch, cv-v - dist = sqrt(x*x + y*y) / float(win.radius) - if dist > 1.2: - if win.set: - drawalarm(win, d) - erasealarmtime(win, d) - win.set = 0 - elif dist < 0.8: - if not win.set: - win.set = 1 - drawalarm(win, d) - drawalarmtime(win, d) - else: - # Convert to half-degrees (range 0..720) - alpha = atan2(y, x) - hdeg = alpha*360.0/pi - hdeg = 180.0 - hdeg - hdeg = (hdeg + 720.0) % 720.0 - atime = 5*int(hdeg/5.0 + 0.5) - if atime <> win.time or not win.set: - if win.set: - drawalarm(win, d) - erasealarmtime(win, d) - win.set = 1 - win.time = atime - drawalarm(win, d) - drawalarmtime(win, d) - -def drawalarm(win, d): - p1 = calcpoint(win, float(win.time)/2.0, 1.02) - p2 = calcpoint(win, float(win.time)/2.0 - 4.0, 1.1) - p3 = calcpoint(win, float(win.time)/2.0 + 4.0, 1.1) - d.xorline(p1, p2) - d.xorline(p2, p3) - d.xorline(p3, p1) - -def erasealarmtime(win, d): - d.erase(win.statusarea) - -def drawalarmtime(win, d): - # win.time is in the range 0..720 with origin at 12 o'clock - # Convert to hours (0..12) and minutes (12*(0..60)) - hh = win.time/60 - mm = win.time%60 - str = 'Alarm@%02d:%02d' % (hh, mm) - p1 = (win.width - d.textwidth(str))/2, win.height - d.text(p1, str) - -def calcpoint(win, degrees, size): - alpha = pi/2.0 - float(degrees) * pi/180.0 - x, y = cos(alpha), sin(alpha) - h, v = win.center - r = float(win.radius) - return h + int(x*size*r), v - int(y*size*r) - -def calctime(now): - hours, minutes, seconds = time.localtime(now)[3:6] - hours = hours % 12 - return hours, minutes, seconds - -main() diff --git a/Demo/stdwin/ibrowse/README b/Demo/stdwin/ibrowse/README deleted file mode 100644 index 22e4039..0000000 --- a/Demo/stdwin/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/stdwin/ibrowse/dir b/Demo/stdwin/ibrowse/dir deleted file mode 100755 index 21d1989..0000000 --- a/Demo/stdwin/ibrowse/dir +++ /dev/null @@ -1,62 +0,0 @@ --*- Text -*- -This is the file .../ibrowse/dir, which contains the topmost node of the -Info hierarchy. The first time you invoke Ibrowse you start off -looking at that node, which is (dir)Top. (This is a copy of the Info -dir node, except that the reference to Info is replaced by one to Ibrowse.) - -File: dir Node: Top This is the top of the INFO tree - This (the Directory node) gives a menu of major topics. - Typing "d" returns here, "q" exits, "?" lists all INFO commands, "h" - gives a primer for first-timers, "mTexinfo" visits Texinfo topic, - etc. - --- PLEASE ADD DOCUMENTATION TO THIS TREE. (See INFO topic first.) --- - -* Menu: The list of major topics begins on the next line. - -* Ibrowse: (ibrowse). Documentation browsing system. - -* Emacs: (emacs). The extensible self-documenting text editor. - -* VIP: (vip). A VI-emulation for Emacs. - -* Texinfo: (texinfo). - With one source file, make either a printed manual - (through TeX) or an Info file (through texinfo). - Full documentation in this menu item. - -* Termcap: (termcap). - The termcap library, which enables application programs - to handle all types of character-display terminals. - -* Regex: (regex). - The GNU regular expression library. - -* Bison: (bison.info). - The GNU yacc-compatible parser generator. - -* GCC: (gcc.info). - The GNU C compiler. - -* G++: (g-whiz). - The GNU C++ compiler. - -* LibG++: (libg++). - The GNU C++ library. - -* GDB: (gdb.info). - The GNU debugger. - -* CPP: (cpp.info). - The GNU C preprocessor. - -* Lispref: (lispref). - The GNU Emacs Lisp reference manual. - -* Make: (make-info). - The GNU make program. - -* M4: (m4). - The GNU m4 program. - -* Gawk: (gawk-info). - GNU awk. diff --git a/Demo/stdwin/ibrowse/ib b/Demo/stdwin/ibrowse/ib deleted file mode 100755 index 04cb790..0000000 --- a/Demo/stdwin/ibrowse/ib +++ /dev/null @@ -1,2 +0,0 @@ -: ${ARCH}=`arch` -exec /ufs/guido/bin/$ARCH/python ib.py ${1+"$@"} diff --git a/Demo/stdwin/ibrowse/ib.py b/Demo/stdwin/ibrowse/ib.py deleted file mode 100755 index ce6e16a..0000000 --- a/Demo/stdwin/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/stdwin/ibrowse/ibrowse b/Demo/stdwin/ibrowse/ibrowse deleted file mode 100755 index 8b0dcde..0000000 --- a/Demo/stdwin/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/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 diff --git a/Demo/stdwin/ibrowse/icache.py b/Demo/stdwin/ibrowse/icache.py deleted file mode 100755 index 0629bf9..0000000 --- a/Demo/stdwin/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/stdwin/ibrowse/ifile.py b/Demo/stdwin/ibrowse/ifile.py deleted file mode 100755 index 9447164..0000000 --- a/Demo/stdwin/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.millitimer() - tags = make_tags(f) - t2 = time.millitimer() - print 'Making tag table for', `TESTFILE`, 'took', t2-t1, 'msec.' diff --git a/Demo/stdwin/ibrowse/itags.py b/Demo/stdwin/ibrowse/itags.py deleted file mode 100755 index 7cddcfa..0000000 --- a/Demo/stdwin/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/stdwin/jukebox.py b/Demo/stdwin/jukebox.py deleted file mode 100755 index e3c9db8..0000000 --- a/Demo/stdwin/jukebox.py +++ /dev/null @@ -1,413 +0,0 @@ -#! /usr/bin/env python - -# XXX This only works on SGIs running IRIX 4.0 or higher - -# JUKEBOX: browse directories full of sampled sound files. -# -# One or more "list windows" display the files and subdirectories of -# the arguments. Double-clicking on a subdirectory opens a new window -# displaying its contents (and so on recursively). Double clicking -# on a file plays it as a sound file (assuming it is one). -# -# Playing is asynchronous: the application keeps listening for events -# while the sample is playing, so you can cancel playing or start a -# new sample right away. Synchronous playing is available through the -# -s option. -# -# The control window displays a "stop button" that cancel the current -# play request. -# -# Most sound file formats recognized by SOX or SFPLAY are recognized. -# Since conversion is costly, converted files are cached in -# /usr/tmp/@j* until the user quits or changes the sampling rate via -# the Rate menu. - -import commands -import getopt -import os -from stat import * -import rand -import stdwin -from stdwinevents import * -import sys -import tempfile -import sndhdr - -from WindowParent import WindowParent -from Buttons import PushButton - -# Pathnames - -DEF_DB = '/usr/local/sounds' # Default directory of sounds -SOX = '/usr/local/bin/sox' # Sound format conversion program -SFPLAY = '/usr/sbin/sfplay' # Sound playing program - - -# Global variables - -class struct: pass # Class to define featureless structures - -G = struct() # Holds writable global variables - - -# Main program - -def main(): - G.synchronous = 0 # If set, use synchronous audio.write() - G.debug = 0 # If set, print debug messages - G.busy = 0 # Set while asynchronous playing is active - G.windows = [] # List of open windows, except control - G.mode = '' # File type (default any that sfplay knows) - G.rate = 0 # Sampling rate (default " " " ") - G.tempprefix = tempfile.mktemp() - # - try: - optlist, args = getopt.getopt(sys.argv[1:], 'dr:st:') - except getopt.error, msg: - sys.stdout = sys.stderr - print msg - print 'usage: jukebox [-d] [-s] [-t type] [-r rate]' - print ' -d debugging (-dd event debugging)' - print ' -s synchronous playing' - print ' -t type file type' - print ' -r rate sampling rate' - sys.exit(2) - # - for optname, optarg in optlist: - if optname == '-d': - G.debug = G.debug + 1 - elif optname == '-r': - G.rate = int(eval(optarg)) - elif optname == '-s': - G.synchronous = 1 - elif optname == '-t': - G.mode = optarg - # - if G.debug: - for name in G.__dict__.keys(): - print 'G.' + name, '=', `G.__dict__[name]` - # - if not args: - args = [DEF_DB] - # - G.cw = opencontrolwindow() - for dirname in args: - G.windows.append(openlistwindow(dirname)) - # - # - try: - maineventloop() - finally: - clearcache() - killchild() - -# Entries in Rate menu: -rates = ['default', '7350', \ - '8000', '11025', '16000', '22050', '32000', '41000', '48000'] - -def maineventloop(): - mouse_events = WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP - while G.windows: - try: - type, w, detail = event = stdwin.getevent() - except KeyboardInterrupt: - killchild() - continue - if w == G.cw.win: - if type == WE_CLOSE: - return - if type == WE_TIMER: - checkchild() - if G.busy: - G.cw.win.settimer(1) - elif type == WE_MENU: - menu, item = detail - if menu is G.ratemenu: - clearcache() - if item == 0: - G.rate = 0 - else: - G.rate = eval(rates[item]) - for i in range(len(rates)): - menu.check(i, (i == item)) - else: - G.cw.dispatch(event) - else: - if type == WE_DRAW: - w.drawproc(w, detail) - elif type in mouse_events: - w.mouse(w, type, detail) - elif type == WE_CLOSE: - w.close(w) - del w, event - else: - if G.debug > 1: print type, w, detail - -def checkchild(): - if G.busy: - waitchild(1) - -def killchild(): - if G.busy: - os.kill(G.busy, 9) - waitchild(0) - -def waitchild(options): - pid, sts = os.waitpid(G.busy, options) - if pid == G.busy: - G.busy = 0 - G.stop.enable(0) - - -# Control window -- to set gain and cancel play operations in progress - -def opencontrolwindow(): - stdwin.setdefscrollbars(0, 0) - cw = WindowParent().create('Jukebox', (0, 0)) - # - stop = PushButton().definetext(cw, ' Stop ') - stop.hook = stop_hook - stop.enable(0) - G.stop = stop - # - cw.realize() - # - G.ratemenu = cw.win.menucreate('Rate') - for r in rates: - G.ratemenu.additem(r) - if G.rate == 0: - G.ratemenu.check(0, 1) - else: - for i in len(range(rates)): - if rates[i] == `G.rate`: - G.ratemenu.check(i, 1) - # - return cw - -def stop_hook(self): - killchild() - - -# List windows -- to display list of files and subdirectories - -def openlistwindow(dirname): - list = os.listdir(dirname) - list.sort() - i = 0 - while i < len(list): - if list[i][0] == '.': - del list[i] - else: - i = i+1 - for i in range(len(list)): - fullname = os.path.join(dirname, list[i]) - if os.path.isdir(fullname): - info = '/' - else: - try: - size = os.stat(fullname)[ST_SIZE] - info = `(size + 1023)/1024` + 'k' - except IOError: - info = '???' - info = '(' + info + ')' - list[i] = list[i], info - width = maxwidth(list) - # width = width + stdwin.textwidth(' ') # XXX X11 stdwin bug workaround - height = len(list) * stdwin.lineheight() - stdwin.setdefwinsize(width, min(height, 500)) - stdwin.setdefscrollbars(0, 1) - w = stdwin.open(dirname) - stdwin.setdefwinsize(0, 0) - w.setdocsize(width, height) - w.drawproc = drawlistwindow - w.mouse = mouselistwindow - w.close = closelistwindow - w.dirname = dirname - w.list = list - w.selected = -1 - return w - -def maxwidth(list): - width = 1 - for name, info in list: - w = stdwin.textwidth(name + ' ' + info) - if w > width: width = w - return width - -def drawlistwindow(w, area): -## (left, top), (right, bottom) = area - d = w.begindrawing() - d.erase((0, 0), (1000, 10000)) - lh = d.lineheight() - h, v = 0, 0 - for name, info in w.list: - if info == '/': - text = name + '/' - else: - text = name + ' ' + info - d.text((h, v), text) - v = v + lh - showselection(w, d) - d.close() - -def hideselection(w, d): - if w.selected >= 0: - invertselection(w, d) - -def showselection(w, d): - if w.selected >= 0: - invertselection(w, d) - -def invertselection(w, d): - lh = d.lineheight() - h1, v1 = p1 = 0, w.selected*lh - h2, v2 = p2 = 1000, v1 + lh - d.invert(p1, p2) - -def mouselistwindow(w, type, detail): - (h, v), clicks, button = detail[:3] - d = w.begindrawing() - lh = d.lineheight() - if 0 <= v < lh*len(w.list): - i = v / lh - else: - i = -1 - if w.selected <> i: - hideselection(w, d) - w.selected = i - showselection(w, d) - d.close() - if type == WE_MOUSE_DOWN and clicks >= 2 and i >= 0: - setcursors('watch') - name, info = w.list[i] - fullname = os.path.join(w.dirname, name) - if info == '/': - if clicks == 2: - G.windows.append(openlistwindow(fullname)) - else: - playfile(fullname) - setcursors('cross') - -def closelistwindow(w): - G.windows.remove(w) - -def setcursors(cursor): - for w in G.windows: - w.setwincursor(cursor) - G.cw.win.setwincursor(cursor) - - -# Playing tools - -cache = {} - -def clearcache(): - for x in cache.keys(): - cmd = 'rm -f ' + cache[x] - if G.debug: print cmd - sts = os.system(cmd) - if sts: - print cmd - print 'Exit status', sts - del cache[x] - -validrates = (8000, 11025, 16000, 22050, 32000, 44100, 48000) - -def playfile(filename): - killchild() - try: - tuple = sndhdr.what(filename) - except IOError, msg: - print 'Can\'t open', filename, msg - stdwin.fleep() - return - raw = 0 - if tuple: - mode, rate = tuple[:2] - if rate == 0: - rate = G.rate - if rate == 0: - rate = 8000 - else: - mode = G.mode - rate = G.rate - if G.debug: print 'mode =', mode, 'rate =', rate - if mode in ('au', 'aiff', 'wav', 'aifc', 'ul', 'ub', 'sb') and \ - rate in validrates: - tempname = filename - if mode in ('ul', 'ub', 'sb'): - raw = 1 - elif cache.has_key(filename): - tempname = cache[filename] - else: - tempname = G.tempprefix + `rand.rand()` + '.aiff' - cmd = SOX - if G.debug: - cmd = cmd + ' -V' - if mode <> '': - cmd = cmd + ' -t ' + mode - cmd = cmd + ' ' + commands.mkarg(filename) - cmd = cmd + ' -t aiff' - if rate not in validrates: - rate = 32000 - if rate: - cmd = cmd + ' -r ' + `rate` - cmd = cmd + ' ' + tempname - if G.debug: print cmd - sts = os.system(cmd) - if sts: - print cmd - print 'Exit status', sts - stdwin.fleep() - try: - os.unlink(tempname) - except: - pass - return - cache[filename] = tempname - if raw: - pid = sfplayraw(tempname, tuple) - else: - pid = sfplay(tempname, []) - if G.synchronous: - sts = os.wait(pid, 0) - else: - G.busy = pid - G.stop.enable(1) - G.cw.win.settimer(1) - -def sfplayraw(filename, tuple): - args = ['-i'] - type, rate, channels, frames, bits = tuple - if type == 'ul': - args.append('mulaw') - elif type == 'ub': - args = args + ['integer', '8', 'unsigned'] - elif type == 'sb': - args = args + ['integer', '8', '2scomp'] - else: - print 'sfplayraw: warning: unknown type in', tuple - if channels > 1: - args = args + ['channels', `channels`] - if not rate: - rate = G.rate - if rate: - args = args + ['rate', `rate`] - args.append('end') - return sfplay(filename, args) - -def sfplay(filename, args): - if G.debug: - args = ['-p'] + args - args = [SFPLAY, '-r'] + args + [filename] - if G.debug: print 'sfplay:', args - pid = os.fork() - if pid == 0: - # Child - os.execv(SFPLAY, args) - # NOTREACHED - else: - # Parent - return pid - -main() diff --git a/Demo/stdwin/lpwin.py b/Demo/stdwin/lpwin.py deleted file mode 100755 index 519b428..0000000 --- a/Demo/stdwin/lpwin.py +++ /dev/null @@ -1,198 +0,0 @@ -#! /usr/bin/env python - -# Watch line printer queues (only works with BSD 4.3 lpq). -# -# This brings up a window containing one line per printer argument. -# -# Each line gives a small summary of the printer's status and queue. -# The status tries to give as much relevant information as possible, -# and gives extra info if you have jobs in the queue. -# -# The line's background color gives a hint at the status: navajo white -# for idle, green if your job is now printing, yellow/orange for -# small/large queue, red for errors. -# -# To reduce the duration of the unresponsive time while it is waiting -# for an lpq subprocess to finish, it polls one printer every -# delay/len(printers) seconds. A tiny dot indicates the last printer -# updated. Hit the mouse button in the window to update the next one. -# -# To do: -# - add an argument to override the default delay -# - add arguments to override the default colors -# - better heuristic for small/large queue (and more colors!) -# - mouse clicks should update the printer clicked in -# - better visual appearance, e.g., boxes around the lines? - -import posix -import sys -import time -import string - -import stdwin -from stdwinevents import * -import mainloop - -# Default parameters -DEF_PRINTER = 'oce' # This is CWI specific! -DEF_DELAY = 10 - -# Color assignments -c_unknown = stdwin.fetchcolor('white') -c_idle = stdwin.fetchcolor('navajo white') -c_ontop = stdwin.fetchcolor('green') -c_smallqueue = stdwin.fetchcolor('yellow') -c_bigqueue = stdwin.fetchcolor('orange') -c_error = stdwin.fetchcolor('red') - -def main(): - delay = DEF_DELAY - # - try: - thisuser = posix.environ['LOGNAME'] - except: - thisuser = posix.environ['USER'] - # - printers = sys.argv[1:] - if printers: - # Strip '-P' from printer names just in case - # the user specified it... - for i in range(len(printers)): - if printers[i][:2] == '-P': - printers[i] = printers[i][2:] - else: - if posix.environ.has_key('PRINTER'): - printers = [posix.environ['PRINTER']] - else: - printers = [DEF_PRINTER] - # - width = stdwin.textwidth('in')*20 - height = len(printers) * stdwin.lineheight() + 5 - stdwin.setdefwinsize(width, height) - stdwin.setdefscrollbars(0, 0) - # - win = stdwin.open('lpwin') - # - win.printers = printers - win.colors = [c_unknown] * len(printers) - win.texts = printers[:] - win.next = 0 - win.delay = DEF_DELAY - win.thisuser = thisuser - win.dispatch = lpdispatch - # - win.settimer(1) - # - mainloop.register(win) - mainloop.mainloop() - -def lpdispatch(event): - type, win, detail = event - if type == WE_CLOSE or type == WE_CHAR and detail in ('q', 'Q'): - mainloop.unregister(win) - elif type == WE_DRAW: - drawproc(win) - elif type == WE_TIMER: - update(win) - win.change((0,0), (10000, 10000)) - elif type == WE_MOUSE_UP: - win.settimer(1) - -def drawproc(win): - d = win.begindrawing() - offset = d.textwidth('.') - h, v = 0, 0 - for i in range(len(win.printers)): - text = win.texts[i] - color = win.colors[i] - d.setbgcolor(color) - d.erase((h, v), (h+10000, v+d.lineheight())) - if (i+1) % len(win.printers) == win.next and color <> c_unknown: - d.text((h, v), '.') - d.text((h+offset, v), text) - v = v + d.lineheight() - -def update(win): - i = win.next - win.next = (i+1) % len(win.printers) - win.texts[i], win.colors[i] = makestatus(win.printers[i], win.thisuser) - win.settimer(int(win.delay * 10.0 / len(win.printers))) - -def makestatus(name, thisuser): - pipe = posix.popen('lpq -P' + name + ' 2>&1', 'r') - lines = [] - users = {} - aheadbytes = 0 - aheadjobs = 0 - userseen = 0 - totalbytes = 0 - totaljobs = 0 - color = c_unknown - while 1: - line = pipe.readline() - if not line: break - fields = string.split(line) - n = len(fields) - if len(fields) >= 6 and fields[n-1] == 'bytes': - rank = fields[0] - user = fields[1] - job = fields[2] - files = fields[3:-2] - bytes = eval(fields[n-2]) - if user == thisuser: - userseen = 1 - if aheadjobs == 0: - color = c_ontop - elif not userseen: - aheadbytes = aheadbytes + bytes - aheadjobs = aheadjobs + 1 - totalbytes = totalbytes + bytes - totaljobs = totaljobs + 1 - if color == c_unknown: - color = c_smallqueue - elif color == c_smallqueue: - color = c_bigqueue - if users.has_key(user): - ujobs, ubytes = users[user] - else: - ujobs, ubytes = 0, 0 - ujobs = ujobs + 1 - ubytes = ubytes + bytes - users[user] = ujobs, ubytes - else: - if fields and fields[0] <> 'Rank': - line = string.strip(line) - if line == 'no entries': - line = name + ': idle' - if color == c_unknown: - color = c_idle - elif line[-22:] == ' is ready and printing': - line = line[:-22] - else: - line = name + ': ' + line - color = c_error - lines.append(line) - # - if totaljobs: - line = `(totalbytes+1023)/1024` + ' K' - if totaljobs <> len(users): - line = line + ' (' + `totaljobs` + ' jobs)' - if len(users) == 1: - line = line + ' for ' + users.keys()[0] - else: - line = line + ' for ' + `len(users)` + ' users' - if userseen: - if aheadjobs == 0: - line = line + ' (' + thisuser + ' first)' - else: - line = line + ' (' + `(aheadbytes+1023)/1024` - line = line + ' K before ' + thisuser + ')' - lines.append(line) - # - sts = pipe.close() - if sts: - lines.append('lpq exit status ' + `sts`) - color = c_error - return string.joinfields(lines, ': '), color - -main() diff --git a/Demo/stdwin/microedit.py b/Demo/stdwin/microedit.py deleted file mode 100755 index 1091676..0000000 --- a/Demo/stdwin/microedit.py +++ /dev/null @@ -1,183 +0,0 @@ -#! /usr/bin/env python - -# A minimal single-window text editor using STDWIN's text objects. -# -# Usage: microedit file -# -# This is not intended as a real application but as an introduction -# to STDWIN programming in Python, especially text objects. -# Once you understand microedit.py, study miniedit.py to learn -# about multiple windows and menus, cut and paste, etc. - - -import sys -import stdwin -from stdwinevents import * - - -# Main program -# -def main(): - # - # Get the filename argument and read its contents as one very - # large string. - # An exception will terminate the program if there is no argument - # or if the file could not be read... - # - filename = sys.argv[1] - fp = open(filename, 'r') - contents = fp.read() - del fp # Close the file - # - # Create the window, using the filename as window title - # - window = stdwin.open(filename) - # - # Add a simple File menu to the window with two items - # - filemenu = window.menucreate('File') - filemenu.additem('Save', 'S') # Item 0 (shortcut Meta-S) - filemenu.additem('Save As...') # Item 1 - # - # Create a text object occupying the entire window - # and fill it with the file's contents - # - corner = window.getwinsize() # (width, height) - area = (0, 0), corner # Rectangle as large as the window - text = window.textcreate(area) - text.settext(contents) - del contents # Get rid of contents object - fix_textsize(window, text) # Set document size accordingly - # - # Main event loop -- stop if a close request comes in. - # - # STDWIN applications should regularly call stdwin.getevent() - # otherwise the windows won't function as expected. - # - while 1: - # - # Get the next event - # - type, w, detail = e = stdwin.getevent() - # - # Event decoding switch - # - if type == WE_CLOSE: - break # Stop (no check for saved file!) - elif type == WE_SIZE: - # - # The window was resized -- - # let the text object recompute the line breaks - # and change the document size accordingly, - # so scroll bars will work - # - fix_textsize(window, text) - elif type == WE_MENU: - # - # Execute a file menu request (our only menu) - # - menu, item = detail - if item == 0: - # - # "Save": save to the current filename - # - dummy = save_file(window, text, filename) - elif item == 1: - # - # "Save As": ask a new filename, save to it, - # and make it the current filename - # - # NB: askfile raises KeyboardInterrupt - # if the user cancels the dialog, hence - # the try statement - # - try: - newfile = stdwin.askfile( \ - 'Save as:', filename, 1) - except KeyboardInterrupt: - newfile = '' - if newfile: - if save_file(window, text, newfile): - filename = newfile - window.settitle(filename) - elif text.event(e): - # - # The text object has handled the event. - # Fix the document size if necessary. - # Note: this sometimes fixes the size - # unnecessarily, e.g., for arrow keys. - # - if type in (WE_CHAR, WE_COMMAND): - fix_docsize(window, text) - - -# Save the window's contents to the filename. -# If the open() fails, put up a warning message and return 0; -# if the save succeeds, return 1. -# -def save_file(window, text, filename): - # - # Open the file for writing, handling exceptions - # - try: - fp = open(filename, 'w') - except RuntimeError: - stdwin.message('Cannot create ' + filename) - return 0 - # - # Get the contents of the text object as one very long string - # - contents = text.gettext() - # - # Write the contents to the file - # - fp.write(contents) - # - # The file is automatically closed when this routine returns - # - return 1 - - -# Change the size of the text object to fit in the window, -# and then fix the window's document size to fit around the text object. -# -def fix_textsize(window, text): - # - # Compute a rectangle as large as the window - # - corner = window.getwinsize() # (width, height) - area = (0, 0), (corner) - # - # Move the text object to this rectangle. - # Note: text.move() ignores the bottom coordinate! - # - text.move(area) - # - # Now fix the document size accordingly - # - fix_docsize(window, text) - - -# Fix the document size, after the text has changed -# -def fix_docsize(window, text): - # - # Get the actual rectangle occupied by the text object. - # This has the same left, top and right, but a different bottom. - # - area = text.getrect() - # - # Compute the true height of the text object - # - origin, corner = area - width, height = corner - # - # Set the document height to the text object's height. - # The width is zero since we don't want a horizontal scroll bar. - # - window.setdocsize(0, height) - - -# Once all functions are defined, call main() -# -main() diff --git a/Demo/stdwin/miniedit.py b/Demo/stdwin/miniedit.py deleted file mode 100755 index 9a11c2d..0000000 --- a/Demo/stdwin/miniedit.py +++ /dev/null @@ -1,356 +0,0 @@ -#! /usr/bin/env python - -# A miniature multi-window editor using STDWIN's text objects. -# -# Usage: miniedit [file] ... -# -# The user interface is similar to that of the miniedit demo application -# in C that comes with STDWIN. -# -# XXX need to comment the functions -# XXX Not yet implemented: -# disabling menu entries for inapplicable actions -# Find operations - - -import sys -import stdwin -from stdwinevents import * - - -# Constant: list of WE_COMMAND events that (may) change the text buffer -# so we can decide whether to set the 'changed' flag. -# Note that it is possible for such a command to fail (a backspace -# at the beginning of the buffer) but we'll set the changed flag anyway -# -- it's too complicated to check this condition right now. -# -changing = [WC_RETURN, WC_TAB, WC_BACKSPACE] - - -# The list of currently open windows; -# this is maintained so we can stop when there are no windows left -# -windows = [] - - -# A note on window data attributes (set by open_window): -# -# w.textobject the window's text object -# w.changed true when the window's text is changed -# w.filename filename connected to the window; '' if none - - -# Main program -# -def main(): - # - # Set a reasonable default window size. - # If we are using a fixed-width font this will open a 80x24 window; - # for variable-width fonts we approximate this based on an average - # - stdwin.setdefwinsize(40*stdwin.textwidth('in'), 24*stdwin.lineheight()) - # - # Create global menus (as local variables) - # - filemenu = make_file_menu(stdwin) - editmenu = make_edit_menu(stdwin) - findmenu = make_find_menu(stdwin) - # - # Get the list of files from the command line (maybe none) - # - files = sys.argv[1:] - # - # Open any files -- errors will be reported but do won't stop us - # - for filename in files: - open_file(filename) - # - # If there were no files, or none of them could be opened, - # put up a dialog asking for a filename - # - if not windows: - try: - open_dialog(None) - except KeyboardInterrupt: - pass # User cancelled - # - # If the dialog was cancelled, create an empty new window - # - if not windows: - new_window(None) - # - # Main event loop -- stop when we have no open windows left - # - while windows: - # - # Get the next event -- ignore interrupts - # - try: - type, window, detail = event = stdwin.getevent() - except KeyboardInterrupt: - type, window, detail = event = WE_NONE, None, None - # - # Event decoding switch - # - if not window: - pass # Ignore such events - elif type == WE_MENU: - # - # Execute menu operation - # - menu, item = detail - try: - menu.actions[item](window) - except KeyboardInterrupt: - pass # User cancelled - elif type == WE_CLOSE: - # - # Close a window - # - try: - close_dialog(window) - except KeyboardInterrupt: - pass # User cancelled - elif type == WE_SIZE: - # - # A window was resized -- - # let the text object recompute the line breaks - # and change the document size accordingly, - # so scroll bars will work - # - fix_textsize(window) - elif window.textobject.event(event): - # - # The event was eaten by the text object -- - # set the changed flag if not already set - # - if type == WE_CHAR or \ - type == WE_COMMAND and detail in changing: - window.changed = 1 - fix_docsize(window) - # - # Delete all objects that may still reference the window - # in the event -- this is needed otherwise the window - # won't actually be closed and may receive further - # events, which will confuse the event decoder - # - del type, window, detail, event - - -def make_file_menu(object): - menu = object.menucreate('File') - menu.actions = [] - additem(menu, 'New', 'N', new_window) - additem(menu, 'Open..', 'O', open_dialog) - additem(menu, '', '', None) - additem(menu, 'Save', 'S', save_dialog) - additem(menu, 'Save As..', '', save_as_dialog) - additem(menu, 'Save a Copy..', '', save_copy_dialog) - additem(menu, 'Revert', 'R', revert_dialog) - additem(menu, 'Quit', 'Q', quit_dialog) - return menu - - -def make_edit_menu(object): - menu = object.menucreate('Edit') - menu.actions = [] - additem(menu, 'Cut', 'X', do_cut) - additem(menu, 'Copy', 'C', do_copy) - additem(menu, 'Paste', 'V', do_paste) - additem(menu, 'Clear', 'B', do_clear) - additem(menu, 'Select All', 'A', do_select_all) - return menu - - -def make_find_menu(object): - menu = object.menucreate('Find') - menu.actions = [] - # XXX - return menu - - -def additem(menu, text, shortcut, function): - if shortcut: - menu.additem(text, shortcut) - else: - menu.additem(text) - menu.actions.append(function) - - -def open_dialog(current_ignored): - filename = stdwin.askfile('Open file:', '', 0) - open_file(filename) - - -def open_file(filename): - try: - fp = open(filename, 'r') - except RuntimeError: - stdwin.message(filename + ': cannot open') - return # Error, forget it - try: - contents = fp.read() - except RuntimeError: - stdwin.message(filename + ': read error') - return # Error, forget it - del fp # Close the file - open_window(filename, filename, contents) - - -def new_window(current_ignored): - open_window('', 'Untitled', '') - - -def open_window(filename, title, contents): - try: - window = stdwin.open(title) - except RuntimeError: - stdwin.message('cannot open new window') - return # Error, forget it - window.textobject = window.textcreate((0, 0), window.getwinsize()) - window.textobject.settext(contents) - window.changed = 0 - window.filename = filename - fix_textsize(window) - windows.append(window) - - -def quit_dialog(window): - for window in windows[:]: - close_dialog(window) - - -def close_dialog(window): - if window.changed: - prompt = 'Save changes to ' + window.gettitle() + ' ?' - if stdwin.askync(prompt, 1): - save_dialog(window) - if window.changed: - return # Save failed (not) cancelled - windows.remove(window) - del window.textobject - - -def save_dialog(window): - if not window.filename: - save_as_dialog(window) - return - if save_file(window, window.filename): - window.changed = 0 - - -def save_as_dialog(window): - prompt = 'Save ' + window.gettitle() + ' as:' - filename = stdwin.askfile(prompt, window.filename, 1) - if save_file(window, filename): - window.filename = filename - window.settitle(filename) - window.changed = 0 - - -def save_copy_dialog(window): - prompt = 'Save a copy of ' + window.gettitle() + ' as:' - filename = stdwin.askfile(prompt, window.filename, 1) - void = save_file(window, filename) - - -def save_file(window, filename): - try: - fp = open(filename, 'w') - except RuntimeError: - stdwin.message(filename + ': cannot create') - return 0 - contents = window.textobject.gettext() - try: - fp.write(contents) - except RuntimeError: - stdwin.message(filename + ': write error') - return 0 - return 1 - - -def revert_dialog(window): - if not window.filename: - stdwin.message('This window has no file to revert from') - return - if window.changed: - prompt = 'Really read ' + window.filename + ' back from file?' - if not stdwin.askync(prompt, 1): - return - try: - fp = open(window.filename, 'r') - except RuntimeError: - stdwin.message(filename + ': cannot open') - return - contents = fp.read() - del fp # Close the file - window.textobject.settext(contents) - window.changed = 0 - fix_docsize(window) - - -def fix_textsize(window): - corner = window.getwinsize() - area = (0, 0), (corner) - window.textobject.move(area) - fix_docsize(window) - - -def fix_docsize(window): - area = window.textobject.getrect() - origin, corner = area - width, height = corner - window.setdocsize(0, height) - - -def do_cut(window): - selection = window.textobject.getfocustext() - if not selection: - stdwin.fleep() # Nothing to cut - elif not window.setselection(WS_PRIMARY, selection): - stdwin.fleep() # Window manager glitch... - else: - stdwin.rotatecutbuffers(1) - stdwin.setcutbuffer(0, selection) - window.textobject.replace('') - window.changed = 1 - fix_docsize(window) - - -def do_copy(window): - selection = window.textobject.getfocustext() - if not selection: - stdwin.fleep() # Nothing to cut - elif not window.setselection(WS_PRIMARY, selection): - stdwin.fleep() # Window manager glitch... - else: - stdwin.rotatecutbuffers(1) - stdwin.setcutbuffer(0, selection) - - -def do_paste(window): - selection = stdwin.getselection(WS_PRIMARY) - if not selection: - selection = stdwin.getcutbuffer(0) - if not selection: - stdwin.fleep() # Nothing to paste - else: - window.textobject.replace(selection) - window.changed = 1 - fix_docsize(window) - -def do_clear(window): - first, last = window.textobject.getfocus() - if first == last: - stdwin.fleep() # Nothing to clear - else: - window.textobject.replace('') - window.changed = 1 - fix_docsize(window) - - -def do_select_all(window): - window.textobject.setfocus(0, 0x7fffffff) # XXX Smaller on the Mac! - - -main() diff --git a/Demo/stdwin/python.py b/Demo/stdwin/python.py deleted file mode 100755 index 8a3dfce..0000000 --- a/Demo/stdwin/python.py +++ /dev/null @@ -1,449 +0,0 @@ -#! /usr/bin/env python - -# A STDWIN-based front end for the Python interpreter. -# -# This is useful if you want to avoid console I/O and instead -# use text windows to issue commands to the interpreter. -# -# It supports multiple interpreter windows, each with its own context. -# -# BUGS AND CAVEATS: -# -# This was written long ago as a demonstration, and slightly hacked to -# keep it up-to-date, but never as an industry-strength alternative -# interface to Python. It should be rewritten using more classes, and -# merged with something like wdb. -# -# Although this supports multiple windows, the whole application -# is deaf and dumb when a command is running in one window. -# -# Interrupt is (ab)used to signal EOF on input requests. -# -# On UNIX (using X11), interrupts typed in the window will not be -# seen until the next input or output operation. When you are stuck -# in an infinite loop, try typing ^C in the shell window where you -# started this interpreter. (On the Mac, interrupts work normally.) - - -import sys -import stdwin -from stdwinevents import * -import rand -import mainloop -import os - - -# Stack of windows waiting for [raw_]input(). -# Element [0] is the top. -# If there are multiple windows waiting for input, only the -# one on top of the stack can accept input, because the way -# raw_input() is implemented (using recursive mainloop() calls). -# -inputwindows = [] - - -# Exception raised when input is available -# -InputAvailable = 'input available for raw_input (not an error)' - - -# Main program -- create the window and call the mainloop -# -def main(): - # Hack so 'import python' won't load another copy - # of this if we were loaded though 'python python.py'. - # (Should really look at sys.argv[0]...) - if 'inputwindows' in dir(sys.modules['__main__']) and \ - sys.modules['__main__'].inputwindows is inputwindows: - sys.modules['python'] = sys.modules['__main__'] - # - win = makewindow() - mainloop.mainloop() - - -# Create a new window -# -def makewindow(): - # stdwin.setdefscrollbars(0, 1) # Not in Python 0.9.1 - # stdwin.setfont('monaco') # Not on UNIX! and not Python 0.9.1 - # width, height = stdwin.textwidth('in')*40, stdwin.lineheight()*24 - # stdwin.setdefwinsize(width, height) - win = stdwin.open('Python interpreter ready') - win.editor = win.textcreate((0,0), win.getwinsize()) - win.globals = {} # Dictionary for user's globals - win.command = '' # Partially read command - win.busy = 0 # Ready to accept a command - win.auto = 1 # [CR] executes command - win.insertOutput = 1 # Insert output at focus - win.insertError = 1 # Insert error output at focus - win.setwincursor('ibeam') - win.filename = '' # Empty if no file for this window - makefilemenu(win) - makeeditmenu(win) - win.dispatch = pdispatch # Event dispatch function - mainloop.register(win) - return win - - -# Make a 'File' menu -# -def makefilemenu(win): - win.filemenu = mp = win.menucreate('File') - mp.callback = [] - additem(mp, 'New', 'N', do_new) - additem(mp, 'Open...', 'O', do_open) - additem(mp, '', '', None) - additem(mp, 'Close', 'W', do_close) - additem(mp, 'Save', 'S', do_save) - additem(mp, 'Save as...', '', do_saveas) - additem(mp, '', '', None) - additem(mp, 'Quit', 'Q', do_quit) - - -# Make an 'Edit' menu -# -def makeeditmenu(win): - win.editmenu = mp = win.menucreate('Edit') - mp.callback = [] - additem(mp, 'Cut', 'X', do_cut) - additem(mp, 'Copy', 'C', do_copy) - additem(mp, 'Paste', 'V', do_paste) - additem(mp, 'Clear', '', do_clear) - additem(mp, '', '', None) - win.iauto = len(mp.callback) - additem(mp, 'Autoexecute', '', do_auto) - mp.check(win.iauto, win.auto) - win.insertOutputNum = len(mp.callback) - additem(mp, 'Insert Output', '', do_insertOutputOption) - win.insertErrorNum = len(mp.callback) - additem(mp, 'Insert Error', '', do_insertErrorOption) - additem(mp, 'Exec', '\r', do_exec) - - -# Helper to add a menu item and callback function -# -def additem(mp, text, shortcut, handler): - if shortcut: - mp.additem(text, shortcut) - else: - mp.additem(text) - mp.callback.append(handler) - - -# Dispatch a single event to the interpreter. -# Resize events cause a resize of the editor. -# Some events are treated specially. -# Most other events are passed directly to the editor. -# -def pdispatch(event): - type, win, detail = event - if not win: - win = stdwin.getactive() - if not win: return - if type == WE_CLOSE: - do_close(win) - return - elif type == WE_SIZE: - win.editor.move((0, 0), win.getwinsize()) - elif type == WE_COMMAND and detail == WC_RETURN: - if win.auto: - do_exec(win) - else: - void = win.editor.event(event) - elif type == WE_COMMAND and detail == WC_CANCEL: - if win.busy: - raise KeyboardInterrupt - else: - win.command = '' - settitle(win) - elif type == WE_MENU: - mp, item = detail - mp.callback[item](win) - else: - void = win.editor.event(event) - if win in mainloop.windows: - # May have been deleted by close... - win.setdocsize(0, win.editor.getrect()[1][1]) - if type in (WE_CHAR, WE_COMMAND): - win.editor.setfocus(win.editor.getfocus()) - - -# Helper to set the title of the window -# -def settitle(win): - if win.filename == '': - win.settitle('Python interpreter ready') - else: - win.settitle(win.filename) - - -# Helper to replace the text of the focus -# -def replace(win, text): - win.editor.replace(text) - # Resize the window to display the text - win.setdocsize(0, win.editor.getrect()[1][1]) # update the size before - win.editor.setfocus(win.editor.getfocus()) # move focus to the change - - -# File menu handlers -# -def do_new(win): - win = makewindow() -# -def do_open(win): - try: - filename = stdwin.askfile('Open file', '', 0) - win = makewindow() - win.filename = filename - win.editor.replace(open(filename, 'r').read()) - win.editor.setfocus(0, 0) - win.settitle(win.filename) - # - except KeyboardInterrupt: - pass # Don't give an error on cancel -# -def do_save(win): - try: - if win.filename == '': - win.filename = stdwin.askfile('Open file', '', 1) - f = open(win.filename, 'w') - f.write(win.editor.gettext()) - # - except KeyboardInterrupt: - pass # Don't give an error on cancel - -def do_saveas(win): - currentFilename = win.filename - win.filename = '' - do_save(win) # Use do_save with empty filename - if win.filename == '': # Restore the name if do_save did not set it - win.filename = currentFilename -# -def do_close(win): - if win.busy: - stdwin.message('Can\'t close busy window') - return # need to fail if quitting?? - win.editor = None # Break circular reference - #del win.editmenu # What about the filemenu?? - mainloop.unregister(win) - win.close() -# -def do_quit(win): - # Call win.dispatch instead of do_close because there - # may be 'alien' windows in the list. - for win in mainloop.windows[:]: - mainloop.dispatch((WE_CLOSE, win, None)) - # need to catch failed close - - -# Edit menu handlers -# -def do_cut(win): - text = win.editor.getfocustext() - if not text: - stdwin.fleep() - return - stdwin.setcutbuffer(0, text) - replace(win, '') -# -def do_copy(win): - text = win.editor.getfocustext() - if not text: - stdwin.fleep() - return - stdwin.setcutbuffer(0, text) -# -def do_paste(win): - text = stdwin.getcutbuffer(0) - if not text: - stdwin.fleep() - return - replace(win, text) -# -def do_clear(win): - replace(win, '') - - -# These would be better in a preferences dialog: -# -def do_auto(win): - win.auto = (not win.auto) - win.editmenu.check(win.iauto, win.auto) -# -def do_insertOutputOption(win): - win.insertOutput = (not win.insertOutput) - title = ['Append Output', 'Insert Output'][win.insertOutput] - win.editmenu.setitem(win.insertOutputNum, title) -# -def do_insertErrorOption(win): - win.insertError = (not win.insertError) - title = ['Error Dialog', 'Insert Error'][win.insertError] - win.editmenu.setitem(win.insertErrorNum, title) - - -# Extract a command from the editor and execute it, or pass input to -# an interpreter waiting for it. -# Incomplete commands are merely placed in the window's command buffer. -# All exceptions occurring during the execution are caught and reported. -# (Tracebacks are currently not possible, as the interpreter does not -# save the traceback pointer until it reaches its outermost level.) -# -def do_exec(win): - if win.busy: - if win not in inputwindows: - stdwin.message('Can\'t run recursive commands') - return - if win <> inputwindows[0]: - stdwin.message('Please complete recursive input first') - return - # - # Set text to the string to execute. - a, b = win.editor.getfocus() - alltext = win.editor.gettext() - n = len(alltext) - if a == b: - # There is no selected text, just an insert point; - # so execute the current line. - while 0 < a and alltext[a-1] <> '\n': # Find beginning of line - a = a-1 - while b < n and alltext[b] <> '\n': # Find end of line after b - b = b+1 - text = alltext[a:b] + '\n' - else: - # Execute exactly the selected text. - text = win.editor.getfocustext() - if text[-1:] <> '\n': # Make sure text ends with \n - text = text + '\n' - while b < n and alltext[b] <> '\n': # Find end of line after b - b = b+1 - # - # Set the focus to expect the output, since there is always something. - # Output will be inserted at end of line after current focus, - # or appended to the end of the text. - b = [n, b][win.insertOutput] - win.editor.setfocus(b, b) - # - # Make sure there is a preceeding newline. - if alltext[b-1:b] <> '\n': - win.editor.replace('\n') - # - # - if win.busy: - # Send it to raw_input() below - raise InputAvailable, text - # - # Like the real Python interpreter, we want to execute - # single-line commands immediately, but save multi-line - # commands until they are terminated by a blank line. - # Unlike the real Python interpreter, we don't do any syntax - # checking while saving up parts of a multi-line command. - # - # The current heuristic to determine whether a command is - # the first line of a multi-line command simply checks whether - # the command ends in a colon (followed by a newline). - # This is not very robust (comments and continuations will - # confuse it), but it is usable, and simple to implement. - # (It even has the advantage that single-line loops etc. - # don't need te be terminated by a blank line.) - # - if win.command: - # Already continuing - win.command = win.command + text - if win.command[-2:] <> '\n\n': - win.settitle('Unfinished command...') - return # Need more... - else: - # New command - win.command = text - if text[-2:] == ':\n': - win.settitle('Unfinished command...') - return - command = win.command - win.command = '' - win.settitle('Executing command...') - # - # Some hacks: - # - The standard files are replaced by an IOWindow instance. - # - A 2nd argument to exec() is used to specify the directory - # holding the user's global variables. (If this wasn't done, - # the exec would be executed in the current local environment, - # and the user's assignments to globals would be lost...) - # - save_stdin = sys.stdin - save_stdout = sys.stdout - save_stderr = sys.stderr - try: - sys.stdin = sys.stdout = sys.stderr = IOWindow(win) - win.busy = 1 - try: - exec(command, win.globals) - except KeyboardInterrupt: - print '[Interrupt]' - except: - if type(sys.exc_type) == type(''): - msg = sys.exc_type - else: msg = sys.exc_type.__name__ - if sys.exc_value <> None: - msg = msg + ': ' + `sys.exc_value` - if win.insertError: - stdwin.fleep() - replace(win, msg + '\n') - else: - win.settitle('Unhandled exception') - stdwin.message(msg) - finally: - # Restore redirected I/O in *all* cases - win.busy = 0 - sys.stderr = save_stderr - sys.stdout = save_stdout - sys.stdin = save_stdin - settitle(win) - - -# Class emulating file I/O from/to a window -# -class IOWindow: - # - def __init__(self, win): - self.win = win - # - def readline(self, *unused_args): - n = len(inputwindows) - save_title = self.win.gettitle() - title = n*'(' + 'Requesting input...' + ')'*n - self.win.settitle(title) - inputwindows.insert(0, self.win) - try: - try: - mainloop.mainloop() - finally: - del inputwindows[0] - self.win.settitle(save_title) - except InputAvailable, val: # See do_exec above - return val - except KeyboardInterrupt: - raise EOFError # Until we have a "send EOF" key - # If we didn't catch InputAvailable, something's wrong... - raise EOFError - # - def write(self, text): - mainloop.check() - replace(self.win, text) - mainloop.check() - - -# Currently unused function to test a command's syntax without executing it -# -def testsyntax(s): - import string - lines = string.splitfields(s, '\n') - for i in range(len(lines)): lines[i] = '\t' + lines[i] - lines.insert(0, 'if 0:') - lines.append('') - exec(string.joinfields(lines, '\n')) - - -# Call the main program -# -main() diff --git a/Demo/stdwin/wdiff.py b/Demo/stdwin/wdiff.py deleted file mode 100755 index 50ca032..0000000 --- a/Demo/stdwin/wdiff.py +++ /dev/null @@ -1,484 +0,0 @@ -#! /usr/bin/env python - -# A window-oriented recursive diff utility. -# NB: This uses undocumented window classing modules. - -# TO DO: -# - faster update after moving/copying one file -# - diff flags (-b, etc.) should be global or maintained per window -# - use a few fixed windows instead of creating new ones all the time -# - ways to specify patterns to skip -# (best by pointing at a file and clicking a special menu entry!) -# - add rcsdiff menu commands -# - add a way to view status of selected files without opening them -# - add a way to diff two files with different names -# - add a way to rename files -# - keep backups of overwritten/deleted files -# - a way to mark specified files as uninteresting for dircmp - -import sys -import os -import rand -import commands -import dircache -import statcache -import cmp -import cmpcache -import stdwin -import gwin -import textwin -import filewin -import tablewin -import anywin - -mkarg = commands.mkarg -mk2arg = commands.mk2arg - -# List of names to ignore in dircmp() -# -skiplist = ['RCS', 'CVS', '.Amake', 'tags', 'TAGS', '.', '..'] - -# Function to determine whether a name should be ignored in dircmp(). -# -def skipthis(file): - return file[-1:] == '~' or file in skiplist - - -def anydiff(a, b, flags): # Display differences between any two objects - print 'diff', flags, a, b - if os.path.isdir(a) and os.path.isdir(b): - w = dirdiff(a, b, flags) - else: - w = filediff(a, b, flags) - addstatmenu(w, [a, b]) - w.original_close = w.close - w.close = close_dirwin - return w - -def close_dirwin(w): - close_subwindows(w, (), 0) - w.original_close(w) - -def filediff(a, b, flags): # Display differences between two text files - diffcmd = 'diff' - if flags: diffcmd = diffcmd + mkarg(flags) - diffcmd = diffcmd + mkarg(a) + mkarg(b) - difftext = commands.getoutput(diffcmd) - return textwin.open_readonly(mktitle(a, b), difftext) - -def dirdiff(a, b, flags): # Display differences between two directories - data = diffdata(a, b, flags) - w = tablewin.open(mktitle(a, b), data) - w.flags = flags - w.a = a - w.b = b - addviewmenu(w) - addactionmenu(w) - return w - -def diffdata(a, b, flags): # Compute directory differences. - # - a_only = [('A only:', header_action), ('', header_action)] - b_only = [('B only:', header_action), ('', header_action)] - ab_diff = [('A <> B:', header_action), ('', header_action)] - ab_same = [('A == B:', header_action), ('', header_action)] - data = [a_only, b_only, ab_diff, ab_same] - # - a_list = dircache.listdir(a)[:] - b_list = dircache.listdir(b)[:] - dircache.annotate(a, a_list) - dircache.annotate(b, b_list) - a_list.sort() - b_list.sort() - # - for x in a_list: - if x in ['./', '../']: - pass - elif x not in b_list: - a_only.append((x, a_only_action)) - else: - ax = os.path.join(a, x) - bx = os.path.join(b, x) - if os.path.isdir(ax) and os.path.isdir(bx): - if flags == '-r': - same = dircmp(ax, bx) - else: - same = 0 - else: - try: - same = cmp.cmp(ax, bx) - except (RuntimeError, os.error): - same = 0 - if same: - ab_same.append((x, ab_same_action)) - else: - ab_diff.append((x, ab_diff_action)) - # - for x in b_list: - if x in ['./', '../']: - pass - elif x not in a_list: - b_only.append((x, b_only_action)) - # - return data - -# Re-read the directory. -# Attempt to find the selected item back. - -def update(w): - setbusy(w) - icol, irow = w.selection - if 0 <= icol < len(w.data) and 2 <= irow < len(w.data[icol]): - selname = w.data[icol][irow][0] - else: - selname = '' - statcache.forget_dir(w.a) - statcache.forget_dir(w.b) - tablewin.select(w, (-1, -1)) - tablewin.update(w, diffdata(w.a, w.b, w.flags)) - if selname: - for icol in range(len(w.data)): - for irow in range(2, len(w.data[icol])): - if w.data[icol][irow][0] == selname: - tablewin.select(w, (icol, irow)) - break - -# Action functions for table items in directory diff windows - -def header_action(w, string, (icol, irow), (pos, clicks, button, mask)): - tablewin.select(w, (-1, -1)) - -def a_only_action(w, string, (icol, irow), (pos, clicks, button, mask)): - tablewin.select(w, (icol, irow)) - if clicks == 2: - w2 = anyopen(os.path.join(w.a, string)) - if w2: - w2.parent = w - -def b_only_action(w, string, (icol, irow), (pos, clicks, button, mask)): - tablewin.select(w, (icol, irow)) - if clicks == 2: - w2 = anyopen(os.path.join(w.b, string)) - if w2: - w2.parent = w - -def ab_diff_action(w, string, (icol, irow), (pos, clicks, button, mask)): - tablewin.select(w, (icol, irow)) - if clicks == 2: - w2 = anydiff(os.path.join(w.a, string), os.path.join(w.b, string),'') - w2.parent = w - -def ab_same_action(w, string, sel, detail): - ax = os.path.join(w.a, string) - if os.path.isdir(ax): - ab_diff_action(w, string, sel, detail) - else: - a_only_action(w, string, sel, detail) - -def anyopen(name): # Open any kind of document, ignore errors - try: - w = anywin.open(name) - except (RuntimeError, os.error): - stdwin.message('Can\'t open ' + name) - return 0 - addstatmenu(w, [name]) - return w - -def dircmp(a, b): # Compare whether two directories are the same - # To make this as fast as possible, it uses the statcache - print ' dircmp', a, b - a_list = dircache.listdir(a) - b_list = dircache.listdir(b) - for x in a_list: - if skipthis(x): - pass - elif x not in b_list: - return 0 - else: - ax = os.path.join(a, x) - bx = os.path.join(b, x) - if statcache.isdir(ax) and statcache.isdir(bx): - if not dircmp(ax, bx): return 0 - else: - try: - if not cmpcache.cmp(ax, bx): return 0 - except (RuntimeError, os.error): - return 0 - for x in b_list: - if skipthis(x): - pass - elif x not in a_list: - return 0 - return 1 - - -# View menu (for dir diff windows only) - -def addviewmenu(w): - w.viewmenu = m = w.menucreate('View') - m.action = [] - add(m, 'diff -r A B', diffr_ab) - add(m, 'diff A B', diff_ab) - add(m, 'diff -b A B', diffb_ab) - add(m, 'diff -c A B', diffc_ab) - add(m, 'gdiff A B', gdiff_ab) - add(m, ('Open A ', 'A'), open_a) - add(m, ('Open B ', 'B'), open_b) - add(m, 'Rescan', rescan) - add(m, 'Rescan -r', rescan_r) - -# Action menu (for dir diff windows only) - -def addactionmenu(w): - w.actionmenu = m = w.menucreate('Action') - m.action = [] - add(m, 'cp A B', cp_ab) - add(m, 'rm B', rm_b) - add(m, '', nop) - add(m, 'cp B A', cp_ba) - add(m, 'rm A', rm_a) - -# Main menu (global): - -def mainmenu(): - m = stdwin.menucreate('Wdiff') - m.action = [] - add(m, ('Quit wdiff', 'Q'), quit_wdiff) - add(m, 'Close subwindows', close_subwindows) - return m - -def add(m, text, action): - m.additem(text) - m.action.append(action) - -def quit_wdiff(w, m, item): - if askyesno('Really quit wdiff altogether?', 1): - sys.exit(0) - -def close_subwindows(w, m, item): - while 1: - for w2 in gwin.windows: - if w2.parent == w: - close_subwindows(w2, m, item) - w2.close(w2) - break # inner loop, continue outer loop - else: - break # outer loop - -def diffr_ab(w, m, item): - dodiff(w, '-r') - -def diff_ab(w, m, item): - dodiff(w, '') - -def diffb_ab(w, m, item): - dodiff(w, '-b') - -def diffc_ab(w, m, item): - dodiff(w, '-c') - -def gdiff_ab(w, m, item): # Call SGI's gdiff utility - x = getselection(w) - if x: - a, b = os.path.join(w.a, x), os.path.join(w.b, x) - if os.path.isdir(a) or os.path.isdir(b): - stdwin.fleep() # This is for files only - else: - diffcmd = 'gdiff' - diffcmd = diffcmd + mkarg(a) + mkarg(b) + ' &' - print diffcmd - sts = os.system(diffcmd) - if sts: print 'Exit status', sts - -def dodiff(w, flags): - x = getselection(w) - if x: - w2 = anydiff(os.path.join(w.a, x), os.path.join(w.b, x), flags) - w2.parent = w - -def open_a(w, m, item): - x = getselection(w) - if x: - w2 = anyopen(os.path.join(w.a, x)) - if w2: - w2.parent = w - -def open_b(w, m, item): - x = getselection(w) - if x: - w2 = anyopen(os.path.join(w.b, x)) - if w2: - w2.parent = w - -def rescan(w, m, item): - w.flags = '' - update(w) - -def rescan_r(w, m, item): - w.flags = '-r' - update(w) - -def rm_a(w, m, item): - x = getselection(w) - if x: - if x[-1:] == '/': x = x[:-1] - x = os.path.join(w.a, x) - if os.path.isdir(x): - if askyesno('Recursively remove A directory ' + x, 1): - runcmd('rm -rf' + mkarg(x)) - else: - runcmd('rm -f' + mkarg(x)) - update(w) - -def rm_b(w, m, item): - x = getselection(w) - if x: - if x[-1:] == '/': x = x[:-1] - x = os.path.join(w.b, x) - if os.path.isdir(x): - if askyesno('Recursively remove B directory ' + x, 1): - runcmd('rm -rf' + mkarg(x)) - else: - runcmd('rm -f' + mkarg(x)) - update(w) - -def cp_ab(w, m, item): - x = getselection(w) - if x: - if x[-1:] == '/': x = x[:-1] - ax = os.path.join(w.a, x) - bx = os.path.join(w.b, x) - if os.path.isdir(ax): - if os.path.exists(bx): - m = 'Can\'t copy directory to existing target' - stdwin.message(m) - return - runcmd('cp -r' + mkarg(ax) + mkarg(w.b)) - else: - runcmd('cp' + mkarg(ax) + mk2arg(w.b, x)) - update(w) - -def cp_ba(w, m, item): - x = getselection(w) - if x: - if x[-1:] == '/': x = x[:-1] - ax = os.path.join(w.a, x) - bx = os.path.join(w.b, x) - if os.path.isdir(bx): - if os.path.exists(ax): - m = 'Can\'t copy directory to existing target' - stdwin.message(m) - return - runcmd('cp -r' + mkarg(bx) + mkarg(w.a)) - else: - runcmd('cp' + mk2arg(w.b, x) + mkarg(ax)) - update(w) - -def nop(args): - pass - -def getselection(w): - icol, irow = w.selection - if 0 <= icol < len(w.data): - if 0 <= irow < len(w.data[icol]): - return w.data[icol][irow][0] - stdwin.message('no selection') - return '' - -def runcmd(cmd): - print cmd - sts, output = commands.getstatusoutput(cmd) - if sts or output: - if not output: - output = 'Exit status ' + `sts` - stdwin.message(output) - - -# Status menu (for all kinds of windows) - -def addstatmenu(w, files): - w.statmenu = m = w.menucreate('Stat') - m.files = files - m.action = [] - for file in files: - m.additem(commands.getstatus(file)) - m.action.append(stataction) - -def stataction(w, m, item): # Menu item action for stat menu - file = m.files[item] - try: - m.setitem(item, commands.getstatus(file)) - except os.error: - stdwin.message('Can\'t get status for ' + file) - - -# Compute a suitable window title from two paths - -def mktitle(a, b): - if a == b: return a - i = 1 - while a[-i:] == b[-i:]: i = i+1 - i = i-1 - if not i: - return a + ' ' + b - else: - return '{' + a[:-i] + ',' + b[:-i] + '}' + a[-i:] - - -# Ask a confirmation question - -def askyesno(prompt, default): - try: - return stdwin.askync(prompt, default) - except KeyboardInterrupt: - return 0 - - -# Display a message "busy" in a window, and mark it for updating - -def setbusy(w): - left, top = w.getorigin() - width, height = w.getwinsize() - right, bottom = left + width, top + height - d = w.begindrawing() - d.erase((0, 0), (10000, 10000)) - text = 'Busy...' - textwidth = d.textwidth(text) - textheight = d.lineheight() - h, v = left + (width-textwidth)/2, top + (height-textheight)/2 - d.text((h, v), text) - del d - w.change((0, 0), (10000, 10000)) - - -# Main function - -def main(): - print 'wdiff: warning: this program does NOT make backups' - argv = sys.argv - flags = '' - if len(argv) >= 2 and argv[1][:1] == '-': - flags = argv[1] - del argv[1] - stdwin.setdefscrollbars(0, 1) - m = mainmenu() # Create menu earlier than windows - if len(argv) == 2: # 1 argument - w = anyopen(argv[1]) - if not w: return - elif len(argv) == 3: # 2 arguments - w = anydiff(argv[1], argv[2], flags) - w.parent = () - else: - sys.stdout = sys.stderr - print 'usage:', argv[0], '[diff-flags] dir-1 [dir-2]' - sys.exit(2) - del w # It's preserved in gwin.windows - while 1: - try: - gwin.mainloop() - break - except KeyboardInterrupt: - pass # Just continue... - -# Start the main function (this is a script) -main() -- cgit v0.12