From c2587c76f1b416cdbecb979e54941933246bf856 Mon Sep 17 00:00:00 2001 From: Skip Montanaro Date: Tue, 16 Feb 2021 20:14:16 -0600 Subject: starting over --- lib/Abstract.py | 76 ++--- lib/Buttons.py | 590 +++++++++++++++++++------------------- lib/CSplit.py | 124 ++++---- lib/DEVICE.py | 794 +++++++++++++++++++++++++-------------------------- lib/GL.py | 176 ++++++------ lib/HVSplit.py | 84 +++--- lib/Histogram.py | 54 ++-- lib/Sliders.py | 270 +++++++++--------- lib/Soundogram.py | 54 ++-- lib/Split.py | 212 +++++++------- lib/StripChart.py | 118 ++++---- lib/Tcl.py | 712 ++++++++++++++++++++++----------------------- lib/TclShell.py | 434 ++++++++++++++-------------- lib/TclUtil.py | 386 ++++++++++++------------- lib/TestCSplit.py | 32 +-- lib/TransParent.py | 174 +++++------ lib/VUMeter.py | 76 ++--- lib/WindowParent.py | 180 ++++++------ lib/adv.py | 426 +++++++++++++-------------- lib/anywin.py | 12 +- lib/auds.py | 148 +++++----- lib/calendar.py | 216 +++++++------- lib/clock.py | 292 +++++++++---------- lib/cmp.py | 92 +++--- lib/cmpcache.py | 80 +++--- lib/commands.py | 64 ++--- lib/dircache.py | 40 +-- lib/dircmp.py | 318 ++++++++++----------- lib/dirwin.py | 32 +-- lib/dis.py | 172 +++++------ lib/dump.py | 60 ++-- lib/fact.py | 48 ++-- lib/filewin.py | 12 +- lib/fnmatch.py | 52 ++-- lib/getopt.py | 54 ++-- lib/glob.py | 66 ++--- lib/grep.py | 52 ++-- lib/gwin.py | 176 ++++++------ lib/lambda.py | 88 +++--- lib/listwin.py | 64 ++--- lib/localtime.py | 70 ++--- lib/maccache.py | 52 ++-- lib/macglob.py | 64 ++--- lib/macpath.py | 110 +++---- lib/macshell.py | 594 +++++++++++++++++++------------------- lib/packmail.py | 62 ++-- lib/panel.py | 344 +++++++++++----------- lib/panelparser.py | 122 ++++---- lib/path.py | 114 ++++---- lib/poly.py | 66 ++--- lib/rand.py | 6 +- lib/rect.py | 76 ++--- lib/selection.py | 78 ++--- lib/shutil.py | 78 ++--- lib/stat.py | 44 +-- lib/statcache.py | 72 ++--- lib/stdwinevents.py | 62 ++-- lib/stdwinsupport.py | 42 +-- lib/string.py | 140 ++++----- lib/sunaudio.py | 64 ++--- lib/tablewin.py | 382 ++++++++++++------------- lib/tb.py | 360 +++++++++++------------ lib/testall.py | 106 +++---- lib/textwin.py | 196 ++++++------- lib/util.py | 24 +- lib/whrandom.py | 82 +++--- lib/zmod.py | 92 +++--- 67 files changed, 5306 insertions(+), 5306 deletions(-) (limited to 'lib') diff --git a/lib/Abstract.py b/lib/Abstract.py index 385e6e5..9d9013b 100644 --- a/lib/Abstract.py +++ b/lib/Abstract.py @@ -11,45 +11,45 @@ # define() while split creation methods are called create(). class AbstractParent(): - # - # Upcalls from child to parent - # - def addchild(self, child): unimpl() - def delchild(self, child): unimpl() - # - def need_mouse(self, child): unimpl() - def no_mouse(self, child): unimpl() - # - def need_timer(self, child): unimpl() - def no_timer(self, child): unimpl() - # - # XXX need_kbd, no_kbd; focus??? - # - def begindrawing(self): return unimpl() - def beginmeasuring(self): return unimpl() - # - def change(self, area): unimpl() - def scroll(self, (area, (dh, dv))): unimpl() - def settimer(self, itimer): unimpl() + # + # Upcalls from child to parent + # + def addchild(self, child): unimpl() + def delchild(self, child): unimpl() + # + def need_mouse(self, child): unimpl() + def no_mouse(self, child): unimpl() + # + def need_timer(self, child): unimpl() + def no_timer(self, child): unimpl() + # + # XXX need_kbd, no_kbd; focus??? + # + def begindrawing(self): return unimpl() + def beginmeasuring(self): return unimpl() + # + def change(self, area): unimpl() + def scroll(self, (area, (dh, dv))): unimpl() + def settimer(self, itimer): unimpl() class AbstractChild(): - # - # Downcalls from parent to child - # - def destroy(self): unimpl() - # - def minsize(self, m): return unimpl() - def getbounds(self): return unimpl() - def setbounds(self, bounds): unimpl() - def draw(self, (d, area)): unimpl() - # - # Downcalls only made after certain upcalls - # - def mouse_down(self, detail): unimpl() - def mouse_move(self, detail): unimpl() - def mouse_up(self, detail): unimpl() - # - def timer(self): unimpl() + # + # Downcalls from parent to child + # + def destroy(self): unimpl() + # + def minsize(self, m): return unimpl() + def getbounds(self): return unimpl() + def setbounds(self, bounds): unimpl() + def draw(self, (d, area)): unimpl() + # + # Downcalls only made after certain upcalls + # + def mouse_down(self, detail): unimpl() + def mouse_move(self, detail): unimpl() + def mouse_up(self, detail): unimpl() + # + def timer(self): unimpl() # A "Split" is a child that manages one or more children. # (This terminology is due to DEC SRC, except for CSplits.) @@ -58,4 +58,4 @@ class AbstractChild(): # for others (e.g., all geometry related calls) this is not possible. class AbstractSplit() = AbstractChild(), AbstractParent(): - pass + pass diff --git a/lib/Buttons.py b/lib/Buttons.py index 7c36021..3ad5605 100644 --- a/lib/Buttons.py +++ b/lib/Buttons.py @@ -20,374 +20,374 @@ _MASK = 3 # LabelAppearance provides defaults for all appearance methods. # selected state not visible # disabled --> crossed out -# hilited --> inverted +# hilited --> inverted # class LabelAppearance(): - # - # Initialization - # - def init_appearance(self): - self.bounds = _rect.empty - self.enabled = 1 - self.hilited = 0 - self.selected = 0 - self.text = '' - # - # Size enquiry - # - def minsize(self, m): - try: - self.text = self.text - except NameError: - self.text = '' - return m.textwidth(self.text) + 6, m.lineheight() + 6 - # - def getbounds(self): - return self.bounds - # - # Changing the parameters - # - def settext(self, text): - self.text = text - if self.bounds <> _rect.empty: - self.recalctextpos() - self.redraw() - # - def setbounds(self, bounds): - if self.bounds <> _rect.empty: - self.parent.change(self.bounds) - self.bounds = bounds - if self.bounds <> _rect.empty: - self.recalc() - self.parent.change(bounds) - # - # Changing the state bits - # - def enable(self, flag): - if flag <> self.enabled: - self.enabled = flag - if self.bounds <> _rect.empty: - self.flipenable(self.parent.begindrawing()) - # - def hilite(self, flag): - if flag <> self.hilited: - self.hilited = flag - if self.bounds <> _rect.empty: - self.fliphilite(self.parent.begindrawing()) - # - def select(self, flag): - if flag <> self.selected: - self.selected = flag - if self.bounds <> _rect.empty: - self.redraw() - # - # Recalculate the box bounds and text position. - # This can be overridden by buttons that draw different boxes - # or want their text in a different position. - # - def recalc(self): - if self.bounds <> _rect.empty: - self.recalcbounds() - self.recalctextpos() - # - def recalcbounds(self): - self.hilitebounds = _rect.inset(self.bounds, (3, 3)) - self.crossbounds = self.bounds - # - def recalctextpos(self): - (left, top), (right, bottom) = self.bounds - m = self.parent.beginmeasuring() - h = (left + right - m.textwidth(self.text)) / 2 - v = (top + bottom - m.lineheight()) / 2 - self.textpos = h, v - # - # Generic drawing interface. - # Do not override redraw() or draw() methods; override drawit() c.s. - # - def redraw(self): - if self.bounds <> _rect.empty: - self.draw(self.parent.begindrawing(), self.bounds) - # - def draw(self, (d, area)): - area = _rect.intersect(area, self.bounds) - if area = _rect.empty: - return - d.cliprect(area) - d.erase(self.bounds) - self.drawit(d) - d.noclip() - # - # The drawit() method is fairly generic but may be overridden. - # - def drawit(self, d): - self.drawpict(d) - if self.text: - d.text(self.textpos, self.text) - if not self.enabled: - self.flipenable(d) - if self.hilited: - self.fliphilite(d) - # - # Default drawing detail functions. - # Overriding these is normally sufficient to get different - # appearances. - # - def drawpict(self, d): - pass - # - def flipenable(self, d): - _xorcross(d, self.crossbounds) - # - def fliphilite(self, d): - d.invert(self.hilitebounds) + # + # Initialization + # + def init_appearance(self): + self.bounds = _rect.empty + self.enabled = 1 + self.hilited = 0 + self.selected = 0 + self.text = '' + # + # Size enquiry + # + def minsize(self, m): + try: + self.text = self.text + except NameError: + self.text = '' + return m.textwidth(self.text) + 6, m.lineheight() + 6 + # + def getbounds(self): + return self.bounds + # + # Changing the parameters + # + def settext(self, text): + self.text = text + if self.bounds <> _rect.empty: + self.recalctextpos() + self.redraw() + # + def setbounds(self, bounds): + if self.bounds <> _rect.empty: + self.parent.change(self.bounds) + self.bounds = bounds + if self.bounds <> _rect.empty: + self.recalc() + self.parent.change(bounds) + # + # Changing the state bits + # + def enable(self, flag): + if flag <> self.enabled: + self.enabled = flag + if self.bounds <> _rect.empty: + self.flipenable(self.parent.begindrawing()) + # + def hilite(self, flag): + if flag <> self.hilited: + self.hilited = flag + if self.bounds <> _rect.empty: + self.fliphilite(self.parent.begindrawing()) + # + def select(self, flag): + if flag <> self.selected: + self.selected = flag + if self.bounds <> _rect.empty: + self.redraw() + # + # Recalculate the box bounds and text position. + # This can be overridden by buttons that draw different boxes + # or want their text in a different position. + # + def recalc(self): + if self.bounds <> _rect.empty: + self.recalcbounds() + self.recalctextpos() + # + def recalcbounds(self): + self.hilitebounds = _rect.inset(self.bounds, (3, 3)) + self.crossbounds = self.bounds + # + def recalctextpos(self): + (left, top), (right, bottom) = self.bounds + m = self.parent.beginmeasuring() + h = (left + right - m.textwidth(self.text)) / 2 + v = (top + bottom - m.lineheight()) / 2 + self.textpos = h, v + # + # Generic drawing interface. + # Do not override redraw() or draw() methods; override drawit() c.s. + # + def redraw(self): + if self.bounds <> _rect.empty: + self.draw(self.parent.begindrawing(), self.bounds) + # + def draw(self, (d, area)): + area = _rect.intersect(area, self.bounds) + if area = _rect.empty: + return + d.cliprect(area) + d.erase(self.bounds) + self.drawit(d) + d.noclip() + # + # The drawit() method is fairly generic but may be overridden. + # + def drawit(self, d): + self.drawpict(d) + if self.text: + d.text(self.textpos, self.text) + if not self.enabled: + self.flipenable(d) + if self.hilited: + self.fliphilite(d) + # + # Default drawing detail functions. + # Overriding these is normally sufficient to get different + # appearances. + # + def drawpict(self, d): + pass + # + def flipenable(self, d): + _xorcross(d, self.crossbounds) + # + def fliphilite(self, d): + d.invert(self.hilitebounds) # ButtonAppearance displays a centered string in a box. # selected --> bold border # disabled --> crossed out -# hilited --> inverted +# hilited --> inverted # class ButtonAppearance() = LabelAppearance(): - # - def drawpict(self, d): - d.box(_rect.inset(self.bounds, (1, 1))) - if self.selected: - # Make a thicker box - d.box(self.bounds) - d.box(_rect.inset(self.bounds, (2, 2))) - d.box(_rect.inset(self.bounds, (3, 3))) - # + # + def drawpict(self, d): + d.box(_rect.inset(self.bounds, (1, 1))) + if self.selected: + # Make a thicker box + d.box(self.bounds) + d.box(_rect.inset(self.bounds, (2, 2))) + d.box(_rect.inset(self.bounds, (3, 3))) + # # CheckAppearance displays a small square box and a left-justified string. # selected --> a cross appears in the box # disabled --> whole button crossed out -# hilited --> box is inverted +# hilited --> box is inverted # class CheckAppearance() = LabelAppearance(): - # - def minsize(self, m): - width, height = m.textwidth(self.text) + 6, m.lineheight() + 6 - return width + height + m.textwidth(' '), height - # - def drawpict(self, d): - d.box(self.boxbounds) - if self.selected: _xorcross(d, self.boxbounds) - # - def recalcbounds(self): - LabelAppearance.recalcbounds(self) - (left, top), (right, bottom) = self.bounds - self.size = bottom - top - 4 - self.boxbounds = (left+2, top+2), (left+2+self.size, bottom-2) - self.hilitebounds = self.boxbounds - # - def recalctextpos(self): - m = self.parent.beginmeasuring() - (left, top), (right, bottom) = self.boxbounds - h = right + m.textwidth(' ') - v = top + (self.size - m.lineheight()) / 2 - self.textpos = h, v - # + # + def minsize(self, m): + width, height = m.textwidth(self.text) + 6, m.lineheight() + 6 + return width + height + m.textwidth(' '), height + # + def drawpict(self, d): + d.box(self.boxbounds) + if self.selected: _xorcross(d, self.boxbounds) + # + def recalcbounds(self): + LabelAppearance.recalcbounds(self) + (left, top), (right, bottom) = self.bounds + self.size = bottom - top - 4 + self.boxbounds = (left+2, top+2), (left+2+self.size, bottom-2) + self.hilitebounds = self.boxbounds + # + def recalctextpos(self): + m = self.parent.beginmeasuring() + (left, top), (right, bottom) = self.boxbounds + h = right + m.textwidth(' ') + v = top + (self.size - m.lineheight()) / 2 + self.textpos = h, v + # # RadioAppearance displays a round indicator and a left-justified string. # selected --> a dot appears in the indicator # disabled --> whole button crossed out -# hilited --> indicator is inverted +# hilited --> indicator is inverted # class RadioAppearance() = CheckAppearance(): - # - def drawpict(self, d): - (left, top), (right, bottom) = self.boxbounds - radius = self.size / 2 - h, v = left + radius, top + radius - d.circle((h, v), radius) - if self.selected: - some = radius/3 - d.paint((h-some, v-some), (h+some, v+some)) - # + # + def drawpict(self, d): + (left, top), (right, bottom) = self.boxbounds + radius = self.size / 2 + h, v = left + radius, top + radius + d.circle((h, v), radius) + if self.selected: + some = radius/3 + d.paint((h-some, v-some), (h+some, v+some)) + # # NoReactivity ignores mouse events. # class NoReactivity(): - def init_reactivity(self): pass + def init_reactivity(self): pass # BaseReactivity defines hooks and asks for mouse events, # but provides only dummy mouse event handlers. # The trigger methods call the corresponding hooks set by the user. # Hooks (and triggers) mean the following: -# down_hook called on some mouse-down events -# move_hook called on some mouse-move events -# up_hook called on mouse-up events -# on_hook called for buttons with on/off state, when it goes on -# hook called when a button 'fires' or a radiobutton goes on +# down_hook called on some mouse-down events +# move_hook called on some mouse-move events +# up_hook called on mouse-up events +# on_hook called for buttons with on/off state, when it goes on +# hook called when a button 'fires' or a radiobutton goes on # There are usually extra conditions, e.g., hooks are only called # when the button is enabled, or active, or selected (on). # class BaseReactivity(): - # - def init_reactivity(self): - self.down_hook = self.move_hook = self.up_hook = \ - self.on_hook = self.off_hook = \ - self.hook = self.active = 0 - self.parent.need_mouse(self) - # - def mousetest(self, hv): - return _rect.pointinrect(hv, self.bounds) - # - def mouse_down(self, detail): - pass - # - def mouse_move(self, detail): - pass - # - def mouse_up(self, detail): - pass - # - def down_trigger(self): - if self.down_hook: self.down_hook(self) - # - def move_trigger(self): - if self.move_hook: self.move_hook(self) - # - def up_trigger(self): - if self.up_hook: self.up_hook(self) - # - def on_trigger(self): - if self.on_hook: self.on_hook(self) - # - def off_trigger(self): - if self.off_hook: self.off_hook(self) - # - def trigger(self): - if self.hook: self.hook(self) + # + def init_reactivity(self): + self.down_hook = self.move_hook = self.up_hook = \ + self.on_hook = self.off_hook = \ + self.hook = self.active = 0 + self.parent.need_mouse(self) + # + def mousetest(self, hv): + return _rect.pointinrect(hv, self.bounds) + # + def mouse_down(self, detail): + pass + # + def mouse_move(self, detail): + pass + # + def mouse_up(self, detail): + pass + # + def down_trigger(self): + if self.down_hook: self.down_hook(self) + # + def move_trigger(self): + if self.move_hook: self.move_hook(self) + # + def up_trigger(self): + if self.up_hook: self.up_hook(self) + # + def on_trigger(self): + if self.on_hook: self.on_hook(self) + # + def off_trigger(self): + if self.off_hook: self.off_hook(self) + # + def trigger(self): + if self.hook: self.hook(self) # ToggleReactivity acts like a simple pushbutton. # It toggles its hilite state on mouse down events. # class ToggleReactivity() = BaseReactivity(): - # - def mouse_down(self, detail): - if self.enabled and self.mousetest(detail[_HV]): - self.active = 1 - self.hilite(not self.hilited) - self.down_trigger() - # - def mouse_move(self, detail): - if self.active: - self.move_trigger() - # - def mouse_up(self, detail): - if self.active: - self.up_trigger() - self.active = 0 - # - def down_trigger(self): - if self.hilited: - self.on_trigger() - else: - self.off_trigger() - self.trigger() - # + # + def mouse_down(self, detail): + if self.enabled and self.mousetest(detail[_HV]): + self.active = 1 + self.hilite(not self.hilited) + self.down_trigger() + # + def mouse_move(self, detail): + if self.active: + self.move_trigger() + # + def mouse_up(self, detail): + if self.active: + self.up_trigger() + self.active = 0 + # + def down_trigger(self): + if self.hilited: + self.on_trigger() + else: + self.off_trigger() + self.trigger() + # # TriggerReactivity acts like a fancy pushbutton. # It hilites itself while the mouse is down within its bounds. # class TriggerReactivity() = BaseReactivity(): - # - def mouse_down(self, detail): - if self.enabled and self.mousetest(detail[_HV]): - self.active = 1 - self.hilite(1) - self.down_trigger() - # - def mouse_move(self, detail): - if self.active: - self.hilite(self.mousetest(detail[_HV])) - if self.hilited: - self.move_trigger() - # - def mouse_up(self, detail): - if self.active: - self.hilite(self.mousetest(detail[_HV])) - if self.hilited: - self.up_trigger() - self.trigger() - self.active = 0 - self.hilite(0) - # + # + def mouse_down(self, detail): + if self.enabled and self.mousetest(detail[_HV]): + self.active = 1 + self.hilite(1) + self.down_trigger() + # + def mouse_move(self, detail): + if self.active: + self.hilite(self.mousetest(detail[_HV])) + if self.hilited: + self.move_trigger() + # + def mouse_up(self, detail): + if self.active: + self.hilite(self.mousetest(detail[_HV])) + if self.hilited: + self.up_trigger() + self.trigger() + self.active = 0 + self.hilite(0) + # # CheckReactivity handles mouse events like TriggerReactivity, # It overrides the up_trigger method to flip its selected state. # class CheckReactivity() = TriggerReactivity(): - # - def up_trigger(self): - self.select(not self.selected) - if self.selected: - self.on_trigger() - else: - self.off_trigger() - self.trigger() + # + def up_trigger(self): + self.select(not self.selected) + if self.selected: + self.on_trigger() + else: + self.off_trigger() + self.trigger() # RadioReactivity turns itself on and the other buttons in its group # off when its up_trigger method is called. # class RadioReactivity() = TriggerReactivity(): - # - def init_reactivity(self): - TriggerReactivity.init_reactivity(self) - self.group = [] - # - def up_trigger(self): - for b in self.group: - if b <> self: - if b.selected: - b.select(0) - b.off_trigger() - self.select(1) - self.on_trigger() - self.trigger() + # + def init_reactivity(self): + TriggerReactivity.init_reactivity(self) + self.group = [] + # + def up_trigger(self): + for b in self.group: + if b <> self: + if b.selected: + b.select(0) + b.off_trigger() + self.select(1) + self.on_trigger() + self.trigger() # Auxiliary class for 'define' method. # Call the initializers in the right order. # class Define(): - # - def define(self, parent): - self.parent = parent - parent.addchild(self) - self.init_appearance() - self.init_reactivity() - return self - # - def destroy(self): - self.parent = 0 - # - def definetext(self, (parent, text)): - self = self.define(parent) - self.settext(text) - return self + # + def define(self, parent): + self.parent = parent + parent.addchild(self) + self.init_appearance() + self.init_reactivity() + return self + # + def destroy(self): + self.parent = 0 + # + def definetext(self, (parent, text)): + self = self.define(parent) + self.settext(text) + return self # Subroutine to cross out a rectangle. # def _xorcross(d, bounds): - ((left, top), (right, bottom)) = bounds - # This is s bit funny to make it look better - left = left + 2 - right = right - 2 - top = top + 2 - bottom = bottom - 3 - d.xorline(((left, top), (right, bottom))) - d.xorline((left, bottom), (right, top)) + ((left, top), (right, bottom)) = bounds + # This is s bit funny to make it look better + left = left + 2 + right = right - 2 + top = top + 2 + bottom = bottom - 3 + d.xorline(((left, top), (right, bottom))) + d.xorline((left, bottom), (right, top)) # Ready-made button classes. diff --git a/lib/CSplit.py b/lib/CSplit.py index a28b1c8..03559c1 100644 --- a/lib/CSplit.py +++ b/lib/CSplit.py @@ -1,70 +1,70 @@ # A CSplit is a Clock-shaped split: the children are grouped in a circle. # The numbering is a little different from a real clock: the 12 o'clock -# position is called 0, not 12. This is a little easier since Python -# usually counts from zero. (BTW, there needn't be exactly 12 children.) +# position is called 0, not 12. This is a little easier since Python +# usually counts from zero. (BTW, there needn't be exactly 12 children.) from math import pi, sin, cos from Split import Split class CSplit() = Split(): - # - def minsize(self, m): - # Since things look best if the children are spaced evenly - # along the circle (and often all children have the same - # size anyway) we compute the max child size and assume - # this is each child's size. - width, height = 0, 0 - for child in self.children: - wi, he = child.minsize(m) - width = max(width, wi) - height = max(height, he) - # In approximation, the diameter of the circle we need is - # (diameter of box) * (#children) / pi. - # We approximate pi by 3 (so we slightly overestimate - # our minimal size requirements -- not so bad). - # Because the boxes stick out of the circle we add the - # box size to each dimension. - # Because we really deal with ellipses, do everything - # separate in each dimension. - n = len(self.children) - return width + (width*n + 2)/3, height + (height*n + 2)/3 - # - def getbounds(self): - return self.bounds - # - def setbounds(self, bounds): - self.bounds = bounds - # Place the children. This involves some math. - # Compute center positions for children as if they were - # ellipses with a diameter about 1/N times the - # circumference of the big ellipse. - # (There is some rounding involved to make it look - # reasonable for small and large N alike.) - # XXX One day Python will have automatic conversions... - n = len(self.children) - fn = float(n) - if n = 0: return - (left, top), (right, bottom) = bounds - width, height = right-left, bottom-top - child_width, child_height = width*3/(n+4), height*3/(n+4) - half_width, half_height = \ - float(width-child_width)/2.0, \ - float(height-child_height)/2.0 - center_h, center_v = center = (left+right)/2, (top+bottom)/2 - fch, fcv = float(center_h), float(center_v) - alpha = 2.0 * pi / fn - for i in range(n): - child = self.children[i] - fi = float(i) - fh, fv = \ - fch + half_width*sin(fi*alpha), \ - fcv - half_height*cos(fi*alpha) - left, top = \ - int(fh) - child_width/2, \ - int(fv) - child_height/2 - right, bottom = \ - left + child_width, \ - top + child_height - child.setbounds((left, top), (right, bottom)) - # + # + def minsize(self, m): + # Since things look best if the children are spaced evenly + # along the circle (and often all children have the same + # size anyway) we compute the max child size and assume + # this is each child's size. + width, height = 0, 0 + for child in self.children: + wi, he = child.minsize(m) + width = max(width, wi) + height = max(height, he) + # In approximation, the diameter of the circle we need is + # (diameter of box) * (#children) / pi. + # We approximate pi by 3 (so we slightly overestimate + # our minimal size requirements -- not so bad). + # Because the boxes stick out of the circle we add the + # box size to each dimension. + # Because we really deal with ellipses, do everything + # separate in each dimension. + n = len(self.children) + return width + (width*n + 2)/3, height + (height*n + 2)/3 + # + def getbounds(self): + return self.bounds + # + def setbounds(self, bounds): + self.bounds = bounds + # Place the children. This involves some math. + # Compute center positions for children as if they were + # ellipses with a diameter about 1/N times the + # circumference of the big ellipse. + # (There is some rounding involved to make it look + # reasonable for small and large N alike.) + # XXX One day Python will have automatic conversions... + n = len(self.children) + fn = float(n) + if n = 0: return + (left, top), (right, bottom) = bounds + width, height = right-left, bottom-top + child_width, child_height = width*3/(n+4), height*3/(n+4) + half_width, half_height = \ + float(width-child_width)/2.0, \ + float(height-child_height)/2.0 + center_h, center_v = center = (left+right)/2, (top+bottom)/2 + fch, fcv = float(center_h), float(center_v) + alpha = 2.0 * pi / fn + for i in range(n): + child = self.children[i] + fi = float(i) + fh, fv = \ + fch + half_width*sin(fi*alpha), \ + fcv - half_height*cos(fi*alpha) + left, top = \ + int(fh) - child_width/2, \ + int(fv) - child_height/2 + right, bottom = \ + left + child_width, \ + top + child_height + child.setbounds((left, top), (right, bottom)) + # diff --git a/lib/DEVICE.py b/lib/DEVICE.py index 4f2fadc..00eddfc 100644 --- a/lib/DEVICE.py +++ b/lib/DEVICE.py @@ -1,17 +1,17 @@ #/************************************************************************** -# * * -# * Copyright (C) 1984, Silicon Graphics, Inc. * -# * * -# * These coded instructions, statements, and computer programs contain * -# * unpublished proprietary information of Silicon Graphics, Inc., and * -# * are protected by Federal copyright law. They may not be disclosed * -# * to third parties or copied or duplicated in any form, in whole or * -# * in part, without the prior written consent of Silicon Graphics, Inc. * -# * * +# * * +# * Copyright (C) 1984, Silicon Graphics, Inc. * +# * * +# * These coded instructions, statements, and computer programs contain * +# * unpublished proprietary information of Silicon Graphics, Inc., and * +# * are protected by Federal copyright law. They may not be disclosed * +# * to third parties or copied or duplicated in any form, in whole or * +# * in part, without the prior written consent of Silicon Graphics, Inc. * +# * * # **************************************************************************/ #/* file with device definitions (see /usr/include/device.h) */ -NULLDEV = 0 +NULLDEV = 0 BUTOFFSET = 1 VALOFFSET = 256 TIMOFFSET = 515 @@ -22,402 +22,402 @@ BUTCOUNT = 190 VALCOUNT = 27 TIMCOUNT = 4 XKBDCOUNT = 28 -INCOUNT = 8 +INCOUNT = 8 OUTCOUNT = 8 # # # # -BUT0 = 1 -BUT1 = 2 -BUT2 = 3 -BUT3 = 4 -BUT4 = 5 -BUT5 = 6 -BUT6 = 7 -BUT7 = 8 -BUT8 = 9 -BUT9 = 10 -BUT10 = 11 -BUT11 = 12 -BUT12 = 13 -BUT13 = 14 -BUT14 = 15 -BUT15 = 16 -BUT16 = 17 -BUT17 = 18 -BUT18 = 19 -BUT19 = 20 -BUT20 = 21 -BUT21 = 22 -BUT22 = 23 -BUT23 = 24 -BUT24 = 25 -BUT25 = 26 -BUT26 = 27 -BUT27 = 28 -BUT28 = 29 -BUT29 = 30 -BUT30 = 31 -BUT31 = 32 -BUT32 = 33 -BUT33 = 34 -BUT34 = 35 -BUT35 = 36 -BUT36 = 37 -BUT37 = 38 -BUT38 = 39 -BUT39 = 40 -BUT40 = 41 -BUT41 = 42 -BUT42 = 43 -BUT43 = 44 -BUT44 = 45 -BUT45 = 46 -BUT46 = 47 -BUT47 = 48 -BUT48 = 49 -BUT49 = 50 -BUT50 = 51 -BUT51 = 52 -BUT52 = 53 -BUT53 = 54 -BUT54 = 55 -BUT55 = 56 -BUT56 = 57 -BUT57 = 58 -BUT58 = 59 -BUT59 = 60 -BUT60 = 61 -BUT61 = 62 -BUT62 = 63 -BUT63 = 64 -BUT64 = 65 -BUT65 = 66 -BUT66 = 67 -BUT67 = 68 -BUT68 = 69 -BUT69 = 70 -BUT70 = 71 -BUT71 = 72 -BUT72 = 73 -BUT73 = 74 -BUT74 = 75 -BUT75 = 76 -BUT76 = 77 -BUT77 = 78 -BUT78 = 79 -BUT79 = 80 -BUT80 = 81 -BUT81 = 82 -BUT82 = 83 -MAXKBDBUT = 83 -BUT100 = 101 -BUT101 = 102 -BUT102 = 103 -BUT110 = 111 -BUT111 = 112 -BUT112 = 113 -BUT113 = 114 -BUT114 = 115 -BUT115 = 116 -BUT116 = 117 -BUT117 = 118 -BUT118 = 119 -BUT119 = 120 -BUT120 = 121 -BUT121 = 122 -BUT122 = 123 -BUT123 = 124 -BUT124 = 125 -BUT125 = 126 -BUT126 = 127 -BUT127 = 128 -BUT128 = 129 -BUT129 = 130 -BUT130 = 131 -BUT131 = 132 -BUT132 = 133 -BUT133 = 134 -BUT134 = 135 -BUT135 = 136 -BUT136 = 137 -BUT137 = 138 -BUT138 = 139 -BUT139 = 140 -BUT140 = 141 -BUT141 = 142 -BUT142 = 143 -BUT143 = 144 -BUT144 = 145 -BUT145 = 146 -BUT146 = 147 -BUT147 = 148 -BUT148 = 149 -BUT149 = 150 -BUT150 = 151 -BUT151 = 152 -BUT152 = 153 -BUT153 = 154 -BUT154 = 155 -BUT155 = 156 -BUT156 = 157 -BUT157 = 158 -BUT158 = 159 -BUT159 = 160 -BUT160 = 161 -BUT161 = 162 -BUT162 = 163 -BUT163 = 164 -BUT164 = 165 -BUT165 = 166 -BUT166 = 167 -BUT167 = 168 -BUT168 = 169 -BUT181 = 182 -BUT182 = 183 -BUT183 = 184 -BUT184 = 185 -BUT185 = 186 -BUT186 = 187 -BUT187 = 188 -BUT188 = 189 -BUT189 = 190 -MOUSE1 = 101 -MOUSE2 = 102 -MOUSE3 = 103 -LEFTMOUSE = 103 -MIDDLEMOUSE = 102 -RIGHTMOUSE = 101 -LPENBUT = 104 -BPAD0 = 105 -BPAD1 = 106 -BPAD2 = 107 -BPAD3 = 108 -LPENVALID = 109 -SWBASE = 111 -SW0 = 111 -SW1 = 112 -SW2 = 113 -SW3 = 114 -SW4 = 115 -SW5 = 116 -SW6 = 117 -SW7 = 118 -SW8 = 119 -SW9 = 120 -SW10 = 121 -SW11 = 122 -SW12 = 123 -SW13 = 124 -SW14 = 125 -SW15 = 126 -SW16 = 127 -SW17 = 128 -SW18 = 129 -SW19 = 130 -SW20 = 131 -SW21 = 132 -SW22 = 133 -SW23 = 134 -SW24 = 135 -SW25 = 136 -SW26 = 137 -SW27 = 138 -SW28 = 139 -SW29 = 140 -SW30 = 141 -SW31 = 142 -SBBASE = 182 -SBPICK = 182 -SBBUT1 = 183 -SBBUT2 = 184 -SBBUT3 = 185 -SBBUT4 = 186 -SBBUT5 = 187 -SBBUT6 = 188 -SBBUT7 = 189 -SBBUT8 = 190 -AKEY = 11 -BKEY = 36 -CKEY = 28 -DKEY = 18 -EKEY = 17 -FKEY = 19 -GKEY = 26 -HKEY = 27 -IKEY = 40 -JKEY = 34 -KKEY = 35 -LKEY = 42 -MKEY = 44 -NKEY = 37 -OKEY = 41 -PKEY = 48 -QKEY = 10 -RKEY = 24 -SKEY = 12 -TKEY = 25 -UKEY = 33 -VKEY = 29 -WKEY = 16 -XKEY = 21 -YKEY = 32 -ZKEY = 20 -ZEROKEY = 46 -ONEKEY = 8 -TWOKEY = 14 -THREEKEY = 15 -FOURKEY = 22 -FIVEKEY = 23 -SIXKEY = 30 -SEVENKEY = 31 -EIGHTKEY = 38 -NINEKEY = 39 -BREAKKEY = 1 -SETUPKEY = 2 -CTRLKEY = 3 -LEFTCTRLKEY = CTRLKEY -CAPSLOCKKEY = 4 -RIGHTSHIFTKEY = 5 -LEFTSHIFTKEY = 6 -NOSCRLKEY = 13 -ESCKEY = 7 -TABKEY = 9 -RETKEY = 51 -SPACEKEY = 83 -LINEFEEDKEY = 60 -BACKSPACEKEY = 61 -DELKEY = 62 -SEMICOLONKEY = 43 -PERIODKEY = 52 -COMMAKEY = 45 -QUOTEKEY = 50 -ACCENTGRAVEKEY = 55 -MINUSKEY = 47 -VIRGULEKEY = 53 -BACKSLASHKEY = 57 -EQUALKEY = 54 -LEFTBRACKETKEY = 49 -RIGHTBRACKETKEY = 56 -LEFTARROWKEY = 73 -DOWNARROWKEY = 74 -RIGHTARROWKEY = 80 -UPARROWKEY = 81 -PAD0 = 59 -PAD1 = 58 -PAD2 = 64 -PAD3 = 65 -PAD4 = 63 -PAD5 = 69 -PAD6 = 70 -PAD7 = 67 -PAD8 = 68 -PAD9 = 75 -PADPF1 = 72 -PADPF2 = 71 -PADPF3 = 79 -PADPF4 = 78 -PADPERIOD = 66 -PADMINUS = 76 -PADCOMMA = 77 -PADENTER = 82 -LEFTALTKEY = 143 -RIGHTALTKEY = 144 -RIGHTCTRLKEY = 145 -F1KEY = 146 -F2KEY = 147 -F3KEY = 148 -F4KEY = 149 -F5KEY = 150 -F6KEY = 151 -F7KEY = 152 -F8KEY = 153 -F9KEY = 154 -F10KEY = 155 -F11KEY = 156 -F12KEY = 157 +BUT0 = 1 +BUT1 = 2 +BUT2 = 3 +BUT3 = 4 +BUT4 = 5 +BUT5 = 6 +BUT6 = 7 +BUT7 = 8 +BUT8 = 9 +BUT9 = 10 +BUT10 = 11 +BUT11 = 12 +BUT12 = 13 +BUT13 = 14 +BUT14 = 15 +BUT15 = 16 +BUT16 = 17 +BUT17 = 18 +BUT18 = 19 +BUT19 = 20 +BUT20 = 21 +BUT21 = 22 +BUT22 = 23 +BUT23 = 24 +BUT24 = 25 +BUT25 = 26 +BUT26 = 27 +BUT27 = 28 +BUT28 = 29 +BUT29 = 30 +BUT30 = 31 +BUT31 = 32 +BUT32 = 33 +BUT33 = 34 +BUT34 = 35 +BUT35 = 36 +BUT36 = 37 +BUT37 = 38 +BUT38 = 39 +BUT39 = 40 +BUT40 = 41 +BUT41 = 42 +BUT42 = 43 +BUT43 = 44 +BUT44 = 45 +BUT45 = 46 +BUT46 = 47 +BUT47 = 48 +BUT48 = 49 +BUT49 = 50 +BUT50 = 51 +BUT51 = 52 +BUT52 = 53 +BUT53 = 54 +BUT54 = 55 +BUT55 = 56 +BUT56 = 57 +BUT57 = 58 +BUT58 = 59 +BUT59 = 60 +BUT60 = 61 +BUT61 = 62 +BUT62 = 63 +BUT63 = 64 +BUT64 = 65 +BUT65 = 66 +BUT66 = 67 +BUT67 = 68 +BUT68 = 69 +BUT69 = 70 +BUT70 = 71 +BUT71 = 72 +BUT72 = 73 +BUT73 = 74 +BUT74 = 75 +BUT75 = 76 +BUT76 = 77 +BUT77 = 78 +BUT78 = 79 +BUT79 = 80 +BUT80 = 81 +BUT81 = 82 +BUT82 = 83 +MAXKBDBUT = 83 +BUT100 = 101 +BUT101 = 102 +BUT102 = 103 +BUT110 = 111 +BUT111 = 112 +BUT112 = 113 +BUT113 = 114 +BUT114 = 115 +BUT115 = 116 +BUT116 = 117 +BUT117 = 118 +BUT118 = 119 +BUT119 = 120 +BUT120 = 121 +BUT121 = 122 +BUT122 = 123 +BUT123 = 124 +BUT124 = 125 +BUT125 = 126 +BUT126 = 127 +BUT127 = 128 +BUT128 = 129 +BUT129 = 130 +BUT130 = 131 +BUT131 = 132 +BUT132 = 133 +BUT133 = 134 +BUT134 = 135 +BUT135 = 136 +BUT136 = 137 +BUT137 = 138 +BUT138 = 139 +BUT139 = 140 +BUT140 = 141 +BUT141 = 142 +BUT142 = 143 +BUT143 = 144 +BUT144 = 145 +BUT145 = 146 +BUT146 = 147 +BUT147 = 148 +BUT148 = 149 +BUT149 = 150 +BUT150 = 151 +BUT151 = 152 +BUT152 = 153 +BUT153 = 154 +BUT154 = 155 +BUT155 = 156 +BUT156 = 157 +BUT157 = 158 +BUT158 = 159 +BUT159 = 160 +BUT160 = 161 +BUT161 = 162 +BUT162 = 163 +BUT163 = 164 +BUT164 = 165 +BUT165 = 166 +BUT166 = 167 +BUT167 = 168 +BUT168 = 169 +BUT181 = 182 +BUT182 = 183 +BUT183 = 184 +BUT184 = 185 +BUT185 = 186 +BUT186 = 187 +BUT187 = 188 +BUT188 = 189 +BUT189 = 190 +MOUSE1 = 101 +MOUSE2 = 102 +MOUSE3 = 103 +LEFTMOUSE = 103 +MIDDLEMOUSE = 102 +RIGHTMOUSE = 101 +LPENBUT = 104 +BPAD0 = 105 +BPAD1 = 106 +BPAD2 = 107 +BPAD3 = 108 +LPENVALID = 109 +SWBASE = 111 +SW0 = 111 +SW1 = 112 +SW2 = 113 +SW3 = 114 +SW4 = 115 +SW5 = 116 +SW6 = 117 +SW7 = 118 +SW8 = 119 +SW9 = 120 +SW10 = 121 +SW11 = 122 +SW12 = 123 +SW13 = 124 +SW14 = 125 +SW15 = 126 +SW16 = 127 +SW17 = 128 +SW18 = 129 +SW19 = 130 +SW20 = 131 +SW21 = 132 +SW22 = 133 +SW23 = 134 +SW24 = 135 +SW25 = 136 +SW26 = 137 +SW27 = 138 +SW28 = 139 +SW29 = 140 +SW30 = 141 +SW31 = 142 +SBBASE = 182 +SBPICK = 182 +SBBUT1 = 183 +SBBUT2 = 184 +SBBUT3 = 185 +SBBUT4 = 186 +SBBUT5 = 187 +SBBUT6 = 188 +SBBUT7 = 189 +SBBUT8 = 190 +AKEY = 11 +BKEY = 36 +CKEY = 28 +DKEY = 18 +EKEY = 17 +FKEY = 19 +GKEY = 26 +HKEY = 27 +IKEY = 40 +JKEY = 34 +KKEY = 35 +LKEY = 42 +MKEY = 44 +NKEY = 37 +OKEY = 41 +PKEY = 48 +QKEY = 10 +RKEY = 24 +SKEY = 12 +TKEY = 25 +UKEY = 33 +VKEY = 29 +WKEY = 16 +XKEY = 21 +YKEY = 32 +ZKEY = 20 +ZEROKEY = 46 +ONEKEY = 8 +TWOKEY = 14 +THREEKEY = 15 +FOURKEY = 22 +FIVEKEY = 23 +SIXKEY = 30 +SEVENKEY = 31 +EIGHTKEY = 38 +NINEKEY = 39 +BREAKKEY = 1 +SETUPKEY = 2 +CTRLKEY = 3 +LEFTCTRLKEY = CTRLKEY +CAPSLOCKKEY = 4 +RIGHTSHIFTKEY = 5 +LEFTSHIFTKEY = 6 +NOSCRLKEY = 13 +ESCKEY = 7 +TABKEY = 9 +RETKEY = 51 +SPACEKEY = 83 +LINEFEEDKEY = 60 +BACKSPACEKEY = 61 +DELKEY = 62 +SEMICOLONKEY = 43 +PERIODKEY = 52 +COMMAKEY = 45 +QUOTEKEY = 50 +ACCENTGRAVEKEY = 55 +MINUSKEY = 47 +VIRGULEKEY = 53 +BACKSLASHKEY = 57 +EQUALKEY = 54 +LEFTBRACKETKEY = 49 +RIGHTBRACKETKEY = 56 +LEFTARROWKEY = 73 +DOWNARROWKEY = 74 +RIGHTARROWKEY = 80 +UPARROWKEY = 81 +PAD0 = 59 +PAD1 = 58 +PAD2 = 64 +PAD3 = 65 +PAD4 = 63 +PAD5 = 69 +PAD6 = 70 +PAD7 = 67 +PAD8 = 68 +PAD9 = 75 +PADPF1 = 72 +PADPF2 = 71 +PADPF3 = 79 +PADPF4 = 78 +PADPERIOD = 66 +PADMINUS = 76 +PADCOMMA = 77 +PADENTER = 82 +LEFTALTKEY = 143 +RIGHTALTKEY = 144 +RIGHTCTRLKEY = 145 +F1KEY = 146 +F2KEY = 147 +F3KEY = 148 +F4KEY = 149 +F5KEY = 150 +F6KEY = 151 +F7KEY = 152 +F8KEY = 153 +F9KEY = 154 +F10KEY = 155 +F11KEY = 156 +F12KEY = 157 PRINTSCREENKEY = 158 SCROLLLOCKKEY = 159 PAUSEKEY = 160 INSERTKEY = 161 -HOMEKEY = 162 -PAGEUPKEY = 163 -ENDKEY = 164 +HOMEKEY = 162 +PAGEUPKEY = 163 +ENDKEY = 164 PAGEDOWNKEY = 165 NUMLOCKKEY = 166 -PADVIRGULEKEY = 167 -PADASTERKEY = 168 -PADPLUSKEY = 169 -SGIRESERVED = 256 -DIAL0 = 257 -DIAL1 = 258 -DIAL2 = 259 -DIAL3 = 260 -DIAL4 = 261 -DIAL5 = 262 -DIAL6 = 263 -DIAL7 = 264 -DIAL8 = 265 -MOUSEX = 266 -MOUSEY = 267 -LPENX = 268 -LPENY = 269 -BPADX = 270 -BPADY = 271 -CURSORX = 272 -CURSORY = 273 -GHOSTX = 274 -GHOSTY = 275 -SBTX = 276 -SBTY = 277 -SBTZ = 278 -SBRX = 279 -SBRY = 280 -SBRZ = 281 -SBPERIOD = 282 -TIMER0 = 515 -TIMER1 = 516 -TIMER2 = 517 -TIMER3 = 518 -KEYBD = 513 -RAWKEYBD = 514 -VALMARK = 523 -GERROR = 524 -REDRAW = 528 -WMSEND = 529 -WMREPLY = 530 -WMGFCLOSE = 531 -WMTXCLOSE = 532 -MODECHANGE = 533 -INPUTCHANGE = 534 -QFULL = 535 -PIECECHANGE = 536 -WINCLOSE = 537 -QREADERROR = 538 -WINFREEZE = 539 -WINTHAW = 540 -REDRAWICONIC = 541 -WINQUIT = 542 -DEPTHCHANGE = 543 -KEYBDFNAMES = 544 -KEYBDFSTRINGS = 545 -WINSHUT = 546 -INPUT0 = 1024 -INPUT1 = 1025 -INPUT2 = 1026 -INPUT3 = 1027 -INPUT4 = 1028 -INPUT5 = 1029 -INPUT6 = 1030 -INPUT7 = 1032 -OUTPUT0 = 1033 -OUTPUT1 = 1034 -OUTPUT2 = 1035 -OUTPUT3 = 1036 -OUTPUT4 = 1037 -OUTPUT5 = 1038 -OUTPUT6 = 1039 -OUTPUT7 = 1040 +PADVIRGULEKEY = 167 +PADASTERKEY = 168 +PADPLUSKEY = 169 +SGIRESERVED = 256 +DIAL0 = 257 +DIAL1 = 258 +DIAL2 = 259 +DIAL3 = 260 +DIAL4 = 261 +DIAL5 = 262 +DIAL6 = 263 +DIAL7 = 264 +DIAL8 = 265 +MOUSEX = 266 +MOUSEY = 267 +LPENX = 268 +LPENY = 269 +BPADX = 270 +BPADY = 271 +CURSORX = 272 +CURSORY = 273 +GHOSTX = 274 +GHOSTY = 275 +SBTX = 276 +SBTY = 277 +SBTZ = 278 +SBRX = 279 +SBRY = 280 +SBRZ = 281 +SBPERIOD = 282 +TIMER0 = 515 +TIMER1 = 516 +TIMER2 = 517 +TIMER3 = 518 +KEYBD = 513 +RAWKEYBD = 514 +VALMARK = 523 +GERROR = 524 +REDRAW = 528 +WMSEND = 529 +WMREPLY = 530 +WMGFCLOSE = 531 +WMTXCLOSE = 532 +MODECHANGE = 533 +INPUTCHANGE = 534 +QFULL = 535 +PIECECHANGE = 536 +WINCLOSE = 537 +QREADERROR = 538 +WINFREEZE = 539 +WINTHAW = 540 +REDRAWICONIC = 541 +WINQUIT = 542 +DEPTHCHANGE = 543 +KEYBDFNAMES = 544 +KEYBDFSTRINGS = 545 +WINSHUT = 546 +INPUT0 = 1024 +INPUT1 = 1025 +INPUT2 = 1026 +INPUT3 = 1027 +INPUT4 = 1028 +INPUT5 = 1029 +INPUT6 = 1030 +INPUT7 = 1032 +OUTPUT0 = 1033 +OUTPUT1 = 1034 +OUTPUT2 = 1035 +OUTPUT3 = 1036 +OUTPUT4 = 1037 +OUTPUT5 = 1038 +OUTPUT6 = 1039 +OUTPUT7 = 1040 MAXSGIDEVICE = 20000 -MENUBUTTON = RIGHTMOUSE +MENUBUTTON = RIGHTMOUSE diff --git a/lib/GL.py b/lib/GL.py index b733e51..35487a7 100644 --- a/lib/GL.py +++ b/lib/GL.py @@ -1,15 +1,15 @@ # Constants defined in #************************************************************************** -#* * -#* Copyright (C) 1984, Silicon Graphics, Inc. * -#* * -#* These coded instructions, statements, and computer programs contain * -#* unpublished proprietary information of Silicon Graphics, Inc., and * -#* are protected by Federal copyright law. They may not be disclosed * -#* to third parties or copied or duplicated in any form, in whole or * -#* in part, without the prior written consent of Silicon Graphics, Inc. * -#* * +#* * +#* Copyright (C) 1984, Silicon Graphics, Inc. * +#* * +#* These coded instructions, statements, and computer programs contain * +#* unpublished proprietary information of Silicon Graphics, Inc., and * +#* are protected by Federal copyright law. They may not be disclosed * +#* to third parties or copied or duplicated in any form, in whole or * +#* in part, without the prior written consent of Silicon Graphics, Inc. * +#* * #************************************************************************** # Graphics Libary constants @@ -18,17 +18,17 @@ TRUE = 1 FALSE = 0 -# maximum X and Y screen coordinates +# maximum X and Y screen coordinates XMAXSCREEN = 1279 YMAXSCREEN = 1023 -XMAXMEDIUM = 1023 # max for medium res monitor +XMAXMEDIUM = 1023 # max for medium res monitor YMAXMEDIUM = 767 -XMAX170 = 645 # max for RS-170 +XMAX170 = 645 # max for RS-170 YMAX170 = 484 -XMAXPAL = 779 # max for PAL +XMAXPAL = 779 # max for PAL YMAXPAL = 574 -# various hardware/software limits +# various hardware/software limits ATTRIBSTACKDEPTH = 10 VPSTACKDEPTH = 8 MATRIXSTACKDEPTH = 32 @@ -37,7 +37,7 @@ STARTTAG = -2 ENDTAG = -3 CPOSX_INVALID = -(2*XMAXSCREEN) -# names for colors in color map loaded by greset +# names for colors in color map loaded by greset BLACK = 0 RED = 1 GREEN = 2 @@ -47,20 +47,20 @@ MAGENTA = 5 CYAN = 6 WHITE = 7 -# popup colors +# popup colors PUP_CLEAR = 0 PUP_COLOR = 1 PUP_BLACK = 2 PUP_WHITE = 3 -# defines for drawmode +# defines for drawmode NORMALDRAW = 0 PUPDRAW = 1 OVERDRAW = 2 UNDERDRAW = 3 CURSORDRAW = 4 -# defines for defpattern +# defines for defpattern PATTERN_16 = 16 PATTERN_32 = 32 PATTERN_64 = 64 @@ -69,7 +69,7 @@ PATTERN_16_SIZE = 16 PATTERN_32_SIZE = 64 PATTERN_64_SIZE = 256 -# defines for readsource +# defines for readsource SRC_AUTO = 0 SRC_FRONT = 1 SRC_BACK = 2 @@ -79,7 +79,7 @@ SRC_OVER = 5 SRC_UNDER = 6 SRC_FRAMEGRABBER = 7 -# defines for blendfunction +# defines for blendfunction BF_ZERO = 0 BF_ONE = 1 BF_DC = 2 @@ -91,7 +91,7 @@ BF_MSA = 5 BF_DA = 6 BF_MDA = 7 -# defines for zfunction +# defines for zfunction ZF_NEVER = 0 ZF_LESS = 1 ZF_EQUAL = 2 @@ -101,38 +101,38 @@ ZF_NOTEQUAL = 5 ZF_GEQUAL = 6 ZF_ALWAYS = 7 -# defines for zsource +# defines for zsource ZSRC_DEPTH = 0 ZSRC_COLOR = 1 -# defines for pntsmooth +# defines for pntsmooth SMP_OFF = 0 SMP_ON = 1 -# defines for linesmooth +# defines for linesmooth SML_OFF = 0 SML_ON = 1 -# defines for setpup +# defines for setpup PUP_NONE = 0 PUP_GREY = 1 -# defines for glcompat +# defines for glcompat GLC_OLDPOLYGON = 0 GLC_ZRANGEMAP = 1 -# defines for curstype +# defines for curstype C16X1 = 0 C16X2 = 1 C32X1 = 2 C32X2 = 3 CCROSS = 4 -# defines for shademodel +# defines for shademodel FLAT = 0 GOURAUD = 1 -# defines for logicop +# defines for logicop ### LO_ZERO = 0x0 ### LO_AND = 0x1 ### LO_ANDR = 0x2 @@ -152,7 +152,7 @@ GOURAUD = 1 # -# START defines for getgdesc +# START defines for getgdesc # GD_XPMAX = 0 @@ -175,7 +175,7 @@ GD_BITS_NORM_ZBUFFER = 16 GD_BITS_OVER_SNG_CMODE = 17 GD_BITS_UNDR_SNG_CMODE = 18 GD_BITS_PUP_SNG_CMODE = 19 -GD_BITS_NORM_SNG_ALPHA = 21 +GD_BITS_NORM_SNG_ALPHA = 21 GD_BITS_NORM_DBL_ALPHA = 22 GD_BITS_CURSOR = 23 GD_OVERUNDER_SHARED = 24 @@ -234,16 +234,16 @@ GD_WSYS_4S = 1 GD_SCRNTYPE_WM = 0 GD_SCRNTYPE_NOWM = 1 -# -# END defines for getgdesc +# +# END defines for getgdesc # -# -# START NURBS interface definitions +# +# START NURBS interface definitions # -# NURBS Rendering Properties +# NURBS Rendering Properties N_PIXEL_TOLERANCE = 1 N_CULLING = 2 N_DISPLAY = 3 @@ -253,59 +253,59 @@ N_S_STEPS = 6 N_T_STEPS = 7 N_TILES = 8 -N_SHADED = 1.0 +N_SHADED = 1.0 # --------------------------------------------------------------------------- -# FLAGS FOR NURBS SURFACES AND CURVES -# -# Bit: 9876 5432 1 0 -# |tttt|nnnn|f|r| : r - 1 bit = 1 if rational coordinate exists -# : f - 1 bit = 1 if rational coordinate is before rest -# : = 0 if rational coordinate is after rest -# : nnnn - 4 bits for number of coordinates -# : tttt - 4 bits for type of data (color, position, etc.) -# +# FLAGS FOR NURBS SURFACES AND CURVES +# +# Bit: 9876 5432 1 0 +# |tttt|nnnn|f|r| : r - 1 bit = 1 if rational coordinate exists +# : f - 1 bit = 1 if rational coordinate is before rest +# : = 0 if rational coordinate is after rest +# : nnnn - 4 bits for number of coordinates +# : tttt - 4 bits for type of data (color, position, etc.) +# # NURBS data type -# N_T_ST 0 parametric space data -# N_T_XYZ 1 model space data -# -# rational or non-rational data and position in memory -# N_NONRATIONAL 0 non-rational data -# N_RATAFTER 1 rational data with rat coord after rest -# N_RATBEFORE 3 rational data with rat coord before rest -# +# N_T_ST 0 parametric space data +# N_T_XYZ 1 model space data +# +# rational or non-rational data and position in memory +# N_NONRATIONAL 0 non-rational data +# N_RATAFTER 1 rational data with rat coord after rest +# N_RATBEFORE 3 rational data with rat coord before rest +# # N_MKFLAG(a,b,c) ((a<<6) | (b<<2) | c) -# +# # --------------------------------------------------------------------------- -# -N_ST = 0x8 # N_MKFLAG( N_T_ST, 2, N_NONRATIONAL ) -N_STW = 0xd # N_MKFLAG( N_T_ST, 3, N_RATAFTER ) -N_WST = 0xf # N_MKFLAG( N_T_ST, 3, N_RATBEFORE ) -N_XYZ = 0x4c # N_MKFLAG( N_T_XYZ, 3, N_NONRATIONAL ) -N_XYZW = 0x51 # N_MKFLAG( N_T_XYZ, 4, N_RATAFTER ) -N_WXYZ = 0x53 # N_MKFLAG( N_T_XYZ, 4, N_RATBEFORE ) +# +N_ST = 0x8 # N_MKFLAG( N_T_ST, 2, N_NONRATIONAL ) +N_STW = 0xd # N_MKFLAG( N_T_ST, 3, N_RATAFTER ) +N_WST = 0xf # N_MKFLAG( N_T_ST, 3, N_RATBEFORE ) +N_XYZ = 0x4c # N_MKFLAG( N_T_XYZ, 3, N_NONRATIONAL ) +N_XYZW = 0x51 # N_MKFLAG( N_T_XYZ, 4, N_RATAFTER ) +N_WXYZ = 0x53 # N_MKFLAG( N_T_XYZ, 4, N_RATBEFORE ) -# -# END NURBS interface definitions -# +# +# END NURBS interface definitions +# -# -# START lighting model defines -# +# +# START lighting model defines +# LMNULL = 0.0 -# MATRIX modes +# MATRIX modes MSINGLE = 0 MPROJECTION = 1 MVIEWING = 2 -# LIGHT constants +# LIGHT constants MAXLIGHTS = 8 MAXRESTRICTIONS = 4 -# MATERIAL properties +# MATERIAL properties DEFMATERIAL = 0 EMISSION = 1 AMBIENT = 2 @@ -315,17 +315,17 @@ SHININESS = 5 COLORINDEXES = 6 ALPHA = 7 -# LIGHT properties +# LIGHT properties DEFLIGHT = 100 LCOLOR = 101 POSITION = 102 -# LIGHTINGMODEL properties +# LIGHTINGMODEL properties DEFLMODEL = 200 LOCALVIEWER = 201 ATTENUATION = 202 -# TARGET constants +# TARGET constants MATERIAL = 1000 LIGHT0 = 1100 LIGHT1 = 1101 @@ -337,7 +337,7 @@ LIGHT6 = 1106 LIGHT7 = 1107 LMODEL = 1200 -# lmcolor modes +# lmcolor modes LMC_COLOR = 0 LMC_EMISSION = 1 LMC_AMBIENT = 2 @@ -346,20 +346,20 @@ LMC_SPECULAR = 4 LMC_AD = 5 LMC_NULL = 6 -# -# END lighting model defines -# +# +# END lighting model defines +# -# -# START distributed graphics library defines -# +# +# START distributed graphics library defines +# -DGLSINK = 0 # sink connection -DGLLOCAL = 1 # local connection -DGLTSOCKET = 2 # tcp socket connection -DGL4DDN = 3 # 4DDN (DECnet) +DGLSINK = 0 # sink connection +DGLLOCAL = 1 # local connection +DGLTSOCKET = 2 # tcp socket connection +DGL4DDN = 3 # 4DDN (DECnet) -# -# END distributed graphics library defines -# +# +# END distributed graphics library defines +# diff --git a/lib/HVSplit.py b/lib/HVSplit.py index d52af8e..36192a7 100644 --- a/lib/HVSplit.py +++ b/lib/HVSplit.py @@ -8,49 +8,49 @@ from Split import Split class HVSplit() = Split(): - # - def create(self, (parent, hv)): - # hv is 0 or 1 for HSplit or VSplit - self = Split.create(self, parent) - self.hv = hv - return self - # - def minsize(self, m): - hv, vh = self.hv, 1 - self.hv - size = [0, 0] - for c in self.children: - csize = c.minsize(m) - if csize[vh] > size[vh]: size[vh] = csize[vh] - size[hv] = size[hv] + csize[hv] - return size[0], size[1] - # - def getbounds(self): - return self.bounds - # - def setbounds(self, bounds): - self.bounds = bounds - hv, vh = self.hv, 1 - self.hv - mf = self.parent.beginmeasuring - size = self.minsize(mf()) - # XXX not yet used! Later for stretching - maxsize_hv = bounds[1][hv] - bounds[0][hv] - origin = [self.bounds[0][0], self.bounds[0][1]] - for c in self.children: - size = c.minsize(mf()) - corner = [0, 0] - corner[vh] = bounds[1][vh] - corner[hv] = origin[hv] + size[hv] - c.setbounds((origin[0], origin[1]), \ - (corner[0], corner[1])) - origin[hv] = corner[hv] - # XXX stretch - # XXX too-small - # + # + def create(self, (parent, hv)): + # hv is 0 or 1 for HSplit or VSplit + self = Split.create(self, parent) + self.hv = hv + return self + # + def minsize(self, m): + hv, vh = self.hv, 1 - self.hv + size = [0, 0] + for c in self.children: + csize = c.minsize(m) + if csize[vh] > size[vh]: size[vh] = csize[vh] + size[hv] = size[hv] + csize[hv] + return size[0], size[1] + # + def getbounds(self): + return self.bounds + # + def setbounds(self, bounds): + self.bounds = bounds + hv, vh = self.hv, 1 - self.hv + mf = self.parent.beginmeasuring + size = self.minsize(mf()) + # XXX not yet used! Later for stretching + maxsize_hv = bounds[1][hv] - bounds[0][hv] + origin = [self.bounds[0][0], self.bounds[0][1]] + for c in self.children: + size = c.minsize(mf()) + corner = [0, 0] + corner[vh] = bounds[1][vh] + corner[hv] = origin[hv] + size[hv] + c.setbounds((origin[0], origin[1]), \ + (corner[0], corner[1])) + origin[hv] = corner[hv] + # XXX stretch + # XXX too-small + # class HSplit() = HVSplit(): - def create(self, parent): - return HVSplit.create(self, (parent, 0)) + def create(self, parent): + return HVSplit.create(self, (parent, 0)) class VSplit() = HVSplit(): - def create(self, parent): - return HVSplit.create(self, (parent, 1)) + def create(self, parent): + return HVSplit.create(self, (parent, 1)) diff --git a/lib/Histogram.py b/lib/Histogram.py index 3f6da76..505bbaf 100644 --- a/lib/Histogram.py +++ b/lib/Histogram.py @@ -5,32 +5,32 @@ from Buttons import * # A Histogram displays a histogram of numeric data. # class HistogramAppearance() = LabelAppearance(), Define(): - # - def define(self, parent): - Define.define(self, (parent, '')) - self.ydata = [] - self.scale = (0, 100) - return self - # - def setdata(self, (ydata, scale)): - self.ydata = ydata - self.scale = scale # (min, max) - self.parent.change(self.bounds) - # - def drawpict(self, d): - (left, top), (right, bottom) = self.bounds - min, max = self.scale - size = max-min - width, height = right-left, bottom-top - ydata = self.ydata - npoints = len(ydata) - v1 = top + height # constant - h1 = left # changed in loop - for i in range(npoints): - h0 = h1 - v0 = top + height - (ydata[i]-min)*height/size - h1 = left + (i+1) * width/npoints - d.paint((h0, v0), (h1, v1)) - # + # + def define(self, parent): + Define.define(self, (parent, '')) + self.ydata = [] + self.scale = (0, 100) + return self + # + def setdata(self, (ydata, scale)): + self.ydata = ydata + self.scale = scale # (min, max) + self.parent.change(self.bounds) + # + def drawpict(self, d): + (left, top), (right, bottom) = self.bounds + min, max = self.scale + size = max-min + width, height = right-left, bottom-top + ydata = self.ydata + npoints = len(ydata) + v1 = top + height # constant + h1 = left # changed in loop + for i in range(npoints): + h0 = h1 + v0 = top + height - (ydata[i]-min)*height/size + h1 = left + (i+1) * width/npoints + d.paint((h0, v0), (h1, v1)) + # class Histogram() = NoReactivity(), HistogramAppearance(): pass diff --git a/lib/Sliders.py b/lib/Sliders.py index e44b466..f655e77 100644 --- a/lib/Sliders.py +++ b/lib/Sliders.py @@ -23,153 +23,153 @@ _MASK = 3 # but defines its own setval_trigger and setval_hook. # class DragSliderReactivity() = BaseReactivity(): - # - def mouse_down(self, detail): - h, v = hv = detail[_HV] - if self.enabled and self.mousetest(hv): - self.anchor = h - self.oldval = self.val - self.active = 1 - # - def mouse_move(self, detail): - if self.active: - h, v = detail[_HV] - self.setval(self.oldval + (h - self.anchor)) - # - def mouse_up(self, detail): - if self.active: - h, v = detail[_HV] - self.setval(self.oldval + (h - self.anchor)) - self.active = 0 - # + # + def mouse_down(self, detail): + h, v = hv = detail[_HV] + if self.enabled and self.mousetest(hv): + self.anchor = h + self.oldval = self.val + self.active = 1 + # + def mouse_move(self, detail): + if self.active: + h, v = detail[_HV] + self.setval(self.oldval + (h - self.anchor)) + # + def mouse_up(self, detail): + if self.active: + h, v = detail[_HV] + self.setval(self.oldval + (h - self.anchor)) + self.active = 0 + # class DragSliderAppearance() = ButtonAppearance(): - # - # INVARIANTS maintained by the setval method: - # - # self.min <= self.val <= self.max - # self.text = self.pretext + `self.val` + self.postext - # - # (Notice that unlike Python ranges, the end point belongs - # to the range.) - # - def init_appearance(self): - ButtonAppearance.init_appearance(self) - self.min = 0 - self.val = 0 - self.max = 100 - self.hook = 0 - self.pretext = self.postext = '' - self.recalctext() - # - # The 'get*' and 'set*' methods belong to the generic slider interface - # - def getval(self): return self.val - # - def sethook(self, hook): - self.hook = hook - # - def setminvalmax(self, (min, val, max)): - self.min = min - self.max = max - self.setval(val) - # - def settexts(self, (pretext, postext)): - self.pretext = pretext - self.postext = postext - self.recalctext() - # - def setval(self, val): - val = min(self.max, max(self.min, val)) - if val <> self.val: - self.val = val - self.recalctext() - self.trigger() - # - def trigger(self): - if self.hook: - self.hook(self) - # - def recalctext(self): - self.settext(self.pretext + `self.val` + self.postext) - # + # + # INVARIANTS maintained by the setval method: + # + # self.min <= self.val <= self.max + # self.text = self.pretext + `self.val` + self.postext + # + # (Notice that unlike Python ranges, the end point belongs + # to the range.) + # + def init_appearance(self): + ButtonAppearance.init_appearance(self) + self.min = 0 + self.val = 0 + self.max = 100 + self.hook = 0 + self.pretext = self.postext = '' + self.recalctext() + # + # The 'get*' and 'set*' methods belong to the generic slider interface + # + def getval(self): return self.val + # + def sethook(self, hook): + self.hook = hook + # + def setminvalmax(self, (min, val, max)): + self.min = min + self.max = max + self.setval(val) + # + def settexts(self, (pretext, postext)): + self.pretext = pretext + self.postext = postext + self.recalctext() + # + def setval(self, val): + val = min(self.max, max(self.min, val)) + if val <> self.val: + self.val = val + self.recalctext() + self.trigger() + # + def trigger(self): + if self.hook: + self.hook(self) + # + def recalctext(self): + self.settext(self.pretext + `self.val` + self.postext) + # class DragSlider() = DragSliderReactivity(), DragSliderAppearance(), Define(): - def definetext(self, (parent, text)): - raise RuntimeError, 'DragSlider.definetext() not supported' + def definetext(self, (parent, text)): + raise RuntimeError, 'DragSlider.definetext() not supported' # Auxiliary class for PushButton incorporated in ComplexSlider # class _StepButton() = PushButton(): - def define(self, parent): - self = PushButton.define(self, parent) - self.step = 0 - return self - def setstep(self, step): - self.step = step - def definetextstep(self, (parent, text, step)): - self = self.definetext(parent, text) - self.setstep(step) - return self - def init_reactivity(self): - PushButton.init_reactivity(self) - self.parent.need_timer(self) - def step_trigger(self): - self.parent.setval(self.parent.getval() + self.step) - def down_trigger(self): - self.step_trigger() - self.parent.settimer(5) - def timer(self): - if self.hilited: - self.step_trigger() - if self.active: - self.parent.settimer(1) + def define(self, parent): + self = PushButton.define(self, parent) + self.step = 0 + return self + def setstep(self, step): + self.step = step + def definetextstep(self, (parent, text, step)): + self = self.definetext(parent, text) + self.setstep(step) + return self + def init_reactivity(self): + PushButton.init_reactivity(self) + self.parent.need_timer(self) + def step_trigger(self): + self.parent.setval(self.parent.getval() + self.step) + def down_trigger(self): + self.step_trigger() + self.parent.settimer(5) + def timer(self): + if self.hilited: + self.step_trigger() + if self.active: + self.parent.settimer(1) # A complex slider is an HSplit initialized to three buttons: # one to step down, a dragslider, and one to step up. # class ComplexSlider() = HSplit(): - # - # Override Slider define() method - # - def define(self, parent): - self = self.create(parent) # HSplit - # - self.downbutton = _StepButton().definetextstep(self, '-', -1) - self.dragbutton = DragSlider().define(self) - self.upbutton = _StepButton().definetextstep(self, '+', 1) - # - return self - # - # Override HSplit methods - # - def minsize(self, m): - w1, h1 = self.downbutton.minsize(m) - w2, h2 = self.dragbutton.minsize(m) - w3, h3 = self.upbutton.minsize(m) - height = max(h1, h2, h3) - w1 = max(w1, height) - w3 = max(w3, height) - return w1+w2+w3, height - # - def setbounds(self, bounds): - (left, top), (right, bottom) = self.bounds = bounds - size = bottom - top - self.downbutton.setbounds((left, top), (left+size, bottom)) - self.dragbutton.setbounds((left+size, top), \ - (right-size, bottom)) - self.upbutton.setbounds((right-size, top), (right, bottom)) - # - # Pass other Slider methods on to dragbutton - # - def getval(self): return self.dragbutton.getval() - def sethook(self, hook): self.dragbutton.sethook(hook) - def setminvalmax(self, args): self.dragbutton.setminvalmax(args) - def settexts(self, args): self.dragbutton.settexts(args) - def setval(self, val): self.dragbutton.setval(val) - def enable(self, flag): - self.downbutton.enable(flag) - self.dragbutton.enable(flag) - self.upbutton.enable(flag) + # + # Override Slider define() method + # + def define(self, parent): + self = self.create(parent) # HSplit + # + self.downbutton = _StepButton().definetextstep(self, '-', -1) + self.dragbutton = DragSlider().define(self) + self.upbutton = _StepButton().definetextstep(self, '+', 1) + # + return self + # + # Override HSplit methods + # + def minsize(self, m): + w1, h1 = self.downbutton.minsize(m) + w2, h2 = self.dragbutton.minsize(m) + w3, h3 = self.upbutton.minsize(m) + height = max(h1, h2, h3) + w1 = max(w1, height) + w3 = max(w3, height) + return w1+w2+w3, height + # + def setbounds(self, bounds): + (left, top), (right, bottom) = self.bounds = bounds + size = bottom - top + self.downbutton.setbounds((left, top), (left+size, bottom)) + self.dragbutton.setbounds((left+size, top), \ + (right-size, bottom)) + self.upbutton.setbounds((right-size, top), (right, bottom)) + # + # Pass other Slider methods on to dragbutton + # + def getval(self): return self.dragbutton.getval() + def sethook(self, hook): self.dragbutton.sethook(hook) + def setminvalmax(self, args): self.dragbutton.setminvalmax(args) + def settexts(self, args): self.dragbutton.settexts(args) + def setval(self, val): self.dragbutton.setval(val) + def enable(self, flag): + self.downbutton.enable(flag) + self.dragbutton.enable(flag) + self.upbutton.enable(flag) diff --git a/lib/Soundogram.py b/lib/Soundogram.py index 38dd5ef..aa2edd1 100644 --- a/lib/Soundogram.py +++ b/lib/Soundogram.py @@ -4,33 +4,33 @@ import audio from Histogram import Histogram class Soundogram() = Histogram(): - # - def define(self, (win, chunk)): - width, height = corner = win.getwinsize() - bounds = (0, 0), corner - self.chunk = chunk - self.step = (len(chunk)-1)/(width/2+1) + 1 - ydata = _make_ydata(chunk, self.step) - return Histogram.define(self, (win, bounds, ydata, (0, 128))) - # - def setchunk(self, chunk): - self.chunk = chunk - self.recompute() - # - def recompute(self): - (left, top), (right, bottom) = self.bounds - width = right - left - self.step = (len(chunk)-1)/width + 1 - ydata = _make_ydata(chunk, self.step) - self.setdata(ydata, (0, 128)) - # + # + def define(self, (win, chunk)): + width, height = corner = win.getwinsize() + bounds = (0, 0), corner + self.chunk = chunk + self.step = (len(chunk)-1)/(width/2+1) + 1 + ydata = _make_ydata(chunk, self.step) + return Histogram.define(self, (win, bounds, ydata, (0, 128))) + # + def setchunk(self, chunk): + self.chunk = chunk + self.recompute() + # + def recompute(self): + (left, top), (right, bottom) = self.bounds + width = right - left + self.step = (len(chunk)-1)/width + 1 + ydata = _make_ydata(chunk, self.step) + self.setdata(ydata, (0, 128)) + # def _make_ydata(chunk, step): - ydata = [] - for i in range(0, len(chunk), step): - piece = audio.chr2num(chunk[i:i+step]) - mi, ma = min(piece), max(piece) - y = max(abs(mi), abs(ma)) - ydata.append(y) - return ydata + ydata = [] + for i in range(0, len(chunk), step): + piece = audio.chr2num(chunk[i:i+step]) + mi, ma = min(piece), max(piece) + y = max(abs(mi), abs(ma)) + ydata.append(y) + return ydata diff --git a/lib/Split.py b/lib/Split.py index 8c0a8dc..63f5d5f 100644 --- a/lib/Split.py +++ b/lib/Split.py @@ -3,114 +3,114 @@ # Derived classes should at least implement the methods that call # unimpl() below: minsize(), getbounds() and setbounds(). -Error = 'Split.Error' # Exception +Error = 'Split.Error' # Exception import rect from util import remove class Split(): - # - # Calls from creator - # NB derived classes may add parameters to create() - # - def create(self, parent): - parent.addchild(self) - self.parent = parent - self.children = [] - self.mouse_interest = [] - self.timer_interest = [] - self.mouse_focus = 0 - return self - # - # Downcalls from parent to child - # - def destroy(self): - self.parent = None - for child in self.children: - child.destroy() - del self.children[:] - del self.mouse_interest[:] - del self.timer_interest[:] - self.mouse_focus = None - # - def minsize(self, m): return unimpl() - def getbounds(self): return unimpl() - def setbounds(self, bounds): unimpl() - # - def draw(self, d_detail): - # (Could avoid calls to children outside the area) - for child in self.children: - child.draw(d_detail) - # - # Downcalls only made after certain upcalls - # - def mouse_down(self, detail): - if self.mouse_focus: - self.mouse_focus.mouse_down(detail) - p = detail[0] - for child in self.mouse_interest: - if rect.pointinrect(p, child.getbounds()): - self.mouse_focus = child - child.mouse_down(detail) - def mouse_move(self, detail): - if self.mouse_focus: - self.mouse_focus.mouse_move(detail) - def mouse_up(self, detail): - if self.mouse_focus: - self.mouse_focus.mouse_up(detail) - self.mouse_focus = 0 - # - def timer(self): - for child in self.timer_interest: - child.timer() - # - # Upcalls from child to parent - # - def addchild(self, child): - if child in self.children: - raise Error, 'addchild: child already inlist' - self.children.append(child) - def delchild(self, child): - if child not in self.children: - raise Error, 'delchild: child not in list' - remove(child, self.children) - if child in self.mouse_interest: - remove(child, self.mouse_interest) - if child in self.timer_interest: - remove(child, self.timer_interest) - if child = self.mouse_focus: - self.mouse_focus = 0 - # - def need_mouse(self, child): - if child not in self.mouse_interest: - self.mouse_interest.append(child) - self.parent.need_mouse(self) - def no_mouse(self, child): - if child in self.mouse_interest: - remove(child, self.mouse_interest) - if not self.mouse_interest: - self.parent.no_mouse(self) - # - def need_timer(self, child): - if child not in self.timer_interest: - self.timer_interest.append(child) - self.parent.need_timer(self) - def no_timer(self, child): - if child in self.timer_interest: - remove(child, self.timer_interest) - if not self.timer_interest: - self.parent.no_timer(self) - # - # The rest are transparent: - # - def begindrawing(self): - return self.parent.begindrawing() - def beginmeasuring(self): - return self.parent.beginmeasuring() - # - def change(self, area): - self.parent.change(area) - def scroll(self, area_vector): - self.parent.scroll(area_vector) - def settimer(self, itimer): - self.parent.settimer(itimer) + # + # Calls from creator + # NB derived classes may add parameters to create() + # + def create(self, parent): + parent.addchild(self) + self.parent = parent + self.children = [] + self.mouse_interest = [] + self.timer_interest = [] + self.mouse_focus = 0 + return self + # + # Downcalls from parent to child + # + def destroy(self): + self.parent = None + for child in self.children: + child.destroy() + del self.children[:] + del self.mouse_interest[:] + del self.timer_interest[:] + self.mouse_focus = None + # + def minsize(self, m): return unimpl() + def getbounds(self): return unimpl() + def setbounds(self, bounds): unimpl() + # + def draw(self, d_detail): + # (Could avoid calls to children outside the area) + for child in self.children: + child.draw(d_detail) + # + # Downcalls only made after certain upcalls + # + def mouse_down(self, detail): + if self.mouse_focus: + self.mouse_focus.mouse_down(detail) + p = detail[0] + for child in self.mouse_interest: + if rect.pointinrect(p, child.getbounds()): + self.mouse_focus = child + child.mouse_down(detail) + def mouse_move(self, detail): + if self.mouse_focus: + self.mouse_focus.mouse_move(detail) + def mouse_up(self, detail): + if self.mouse_focus: + self.mouse_focus.mouse_up(detail) + self.mouse_focus = 0 + # + def timer(self): + for child in self.timer_interest: + child.timer() + # + # Upcalls from child to parent + # + def addchild(self, child): + if child in self.children: + raise Error, 'addchild: child already inlist' + self.children.append(child) + def delchild(self, child): + if child not in self.children: + raise Error, 'delchild: child not in list' + remove(child, self.children) + if child in self.mouse_interest: + remove(child, self.mouse_interest) + if child in self.timer_interest: + remove(child, self.timer_interest) + if child = self.mouse_focus: + self.mouse_focus = 0 + # + def need_mouse(self, child): + if child not in self.mouse_interest: + self.mouse_interest.append(child) + self.parent.need_mouse(self) + def no_mouse(self, child): + if child in self.mouse_interest: + remove(child, self.mouse_interest) + if not self.mouse_interest: + self.parent.no_mouse(self) + # + def need_timer(self, child): + if child not in self.timer_interest: + self.timer_interest.append(child) + self.parent.need_timer(self) + def no_timer(self, child): + if child in self.timer_interest: + remove(child, self.timer_interest) + if not self.timer_interest: + self.parent.no_timer(self) + # + # The rest are transparent: + # + def begindrawing(self): + return self.parent.begindrawing() + def beginmeasuring(self): + return self.parent.beginmeasuring() + # + def change(self, area): + self.parent.change(area) + def scroll(self, area_vector): + self.parent.scroll(area_vector) + def settimer(self, itimer): + self.parent.settimer(itimer) diff --git a/lib/StripChart.py b/lib/StripChart.py index fc707cb..ac767c3 100644 --- a/lib/StripChart.py +++ b/lib/StripChart.py @@ -7,62 +7,62 @@ from Buttons import LabelAppearance, NoReactivity # LabelAppearance allows it to be disabled and hilited. class StripChart() = LabelAppearance(), NoReactivity(): - # - def define(self, (parent, scale)): - self.parent = parent - parent.addchild(self) - self.init_appearance() - self.init_reactivity() - self.ydata = [] - self.scale = scale - self.resetbounds() - return self - # - def setbounds(self, bounds): - LabelAppearance.setbounds(self, bounds) - self.resetbounds() - # - def resetbounds(self): - (left, top), (right, bottom) = self.bounds - self.width = right-left - self.height = bottom-top - excess = len(self.ydata) - self.width - if excess > 0: - del self.ydata[:excess] - elif excess < 0: - while len(self.ydata) < self.width: - self.ydata.insert(0, 0) - # - def append(self, y): - self.ydata.append(y) - excess = len(self.ydata) - self.width - if excess > 0: - del self.ydata[:excess] - if self.bounds <> rect.empty: - self.parent.scroll(self.bounds, (-excess, 0)) - if self.bounds <> rect.empty: - (left, top), (right, bottom) = self.bounds - i = len(self.ydata) - area = (left+i-1, top), (left+i, bottom) - self.draw(self.parent.begindrawing(), area) - # - def draw(self, (d, area)): - area = rect.intersect(area, self.bounds) - if area = rect.empty: - print 'mt' - return - d.cliprect(area) - d.erase(self.bounds) - (a_left, a_top), (a_right, a_bottom) = area - (left, top), (right, bottom) = self.bounds - height = bottom - top - i1 = a_left - left - i2 = a_right - left - for i in range(max(0, i1), min(len(self.ydata), i2)): - split = bottom-self.ydata[i]*height/self.scale - d.paint((left+i, split), (left+i+1, bottom)) - if not self.enabled: - self.flipenable(d) - if self.hilited: - self.fliphilite(d) - d.noclip() + # + def define(self, (parent, scale)): + self.parent = parent + parent.addchild(self) + self.init_appearance() + self.init_reactivity() + self.ydata = [] + self.scale = scale + self.resetbounds() + return self + # + def setbounds(self, bounds): + LabelAppearance.setbounds(self, bounds) + self.resetbounds() + # + def resetbounds(self): + (left, top), (right, bottom) = self.bounds + self.width = right-left + self.height = bottom-top + excess = len(self.ydata) - self.width + if excess > 0: + del self.ydata[:excess] + elif excess < 0: + while len(self.ydata) < self.width: + self.ydata.insert(0, 0) + # + def append(self, y): + self.ydata.append(y) + excess = len(self.ydata) - self.width + if excess > 0: + del self.ydata[:excess] + if self.bounds <> rect.empty: + self.parent.scroll(self.bounds, (-excess, 0)) + if self.bounds <> rect.empty: + (left, top), (right, bottom) = self.bounds + i = len(self.ydata) + area = (left+i-1, top), (left+i, bottom) + self.draw(self.parent.begindrawing(), area) + # + def draw(self, (d, area)): + area = rect.intersect(area, self.bounds) + if area = rect.empty: + print 'mt' + return + d.cliprect(area) + d.erase(self.bounds) + (a_left, a_top), (a_right, a_bottom) = area + (left, top), (right, bottom) = self.bounds + height = bottom - top + i1 = a_left - left + i2 = a_right - left + for i in range(max(0, i1), min(len(self.ydata), i2)): + split = bottom-self.ydata[i]*height/self.scale + d.paint((left+i, split), (left+i+1, bottom)) + if not self.enabled: + self.flipenable(d) + if self.hilited: + self.fliphilite(d) + d.noclip() diff --git a/lib/Tcl.py b/lib/Tcl.py index 9d45e37..7f5c8c2 100644 --- a/lib/Tcl.py +++ b/lib/Tcl.py @@ -4,27 +4,27 @@ # Design choices: # # - Names used for functions are not exactly those used by C Tcl. -# In Python, names without 'Tcl_' prefix are acceptable because -# names are less global than in C (and often they are prefixed -# with a module name anyway). Parameter conventions also differ. +# In Python, names without 'Tcl_' prefix are acceptable because +# names are less global than in C (and often they are prefixed +# with a module name anyway). Parameter conventions also differ. # # - The Tcl Interpreter type is implemented using a Python class. -# Almost all functions with an Interpreter as first parameter are -# methods of this class. -# Applications can create derived classes to add additional commands -# or to override specific internal functions. +# Almost all functions with an Interpreter as first parameter are +# methods of this class. +# Applications can create derived classes to add additional commands +# or to override specific internal functions. # # - Tcl errors are mapped to Python exceptions. -# (I bet Ousterhout would have done the same in a language with -# a proper exception mechanism). +# (I bet Ousterhout would have done the same in a language with +# a proper exception mechanism). # # - Tcl expressions are evaluated by Python's built-in function eval(). -# This makes Python Tcl scripts incompatible with C Tcl scripts, -# but is the only sensible solution for a quick-and-dirty version. -# It also makes an escape to Python possible. +# This makes Python Tcl scripts incompatible with C Tcl scripts, +# but is the only sensible solution for a quick-and-dirty version. +# It also makes an escape to Python possible. # # - The Backslash function interprets \, since it -# can return a string instead of a character. +# can return a string instead of a character. from TclUtil import * @@ -38,59 +38,59 @@ TclReturn = 'TclReturn' class CmdBuf(): - # - def Create(buffer): - buffer.string = '' - return buffer - # - def Assemble(buffer, str): - buffer.string = buffer.string + str - if buffer.string[-1:] = '\n': - i, end = 0, len(buffer.string) - try: - while i < end: - list, i = FindNextCommand( \ - buffer.string, i, end, 0) - except TclMatchingError: - return '' - except TclSyntaxError: - pass # Let Eval() return the error - ret = buffer.string - buffer.string = '' - return ret - else: - return '' + # + def Create(buffer): + buffer.string = '' + return buffer + # + def Assemble(buffer, str): + buffer.string = buffer.string + str + if buffer.string[-1:] = '\n': + i, end = 0, len(buffer.string) + try: + while i < end: + list, i = FindNextCommand( \ + buffer.string, i, end, 0) + except TclMatchingError: + return '' + except TclSyntaxError: + pass # Let Eval() return the error + ret = buffer.string + buffer.string = '' + return ret + else: + return '' class _Frame(): - def Create(frame): - frame.locals = {} - return frame + def Create(frame): + frame.locals = {} + return frame class _Proc(): - # - def Create(proc, (interp, args, body)): - proc.interp = interp - proc.args = SplitList(args) # Do this once here - proc.body = body - return proc - # - def Call(proc, argv): - if len(argv) <> len(proc.args)+1: - raise TclRuntimeError, \ - 'wrong # args to proc "' + \ - argv[0] + '"' - # XXX No defaults or variable length 'args' yet - frame = _Frame().Create() - for i in range(len(proc.args)): - frame.locals[proc.args[i]] = argv[i+1] - proc.interp.stack.append(frame) - try: - value = proc.interp.Eval(proc.body) - except TclReturn, value: - pass - del proc.interp.stack[-1:] - return value + # + def Create(proc, (interp, args, body)): + proc.interp = interp + proc.args = SplitList(args) # Do this once here + proc.body = body + return proc + # + def Call(proc, argv): + if len(argv) <> len(proc.args)+1: + raise TclRuntimeError, \ + 'wrong # args to proc "' + \ + argv[0] + '"' + # XXX No defaults or variable length 'args' yet + frame = _Frame().Create() + for i in range(len(proc.args)): + frame.locals[proc.args[i]] = argv[i+1] + proc.interp.stack.append(frame) + try: + value = proc.interp.Eval(proc.body) + except TclReturn, value: + pass + del proc.interp.stack[-1:] + return value import regexp @@ -98,311 +98,311 @@ _expand_prog = regexp.compile('([^[$\\]+|\n)*') del regexp class Interpreter(): - # - def Create(interp): - interp.globals = {} - interp.commands = {} - interp.stack = [] - interp.commands['break'] = interp.BreakCmd - interp.commands['concat'] = interp.ConcatCmd - interp.commands['continue'] = interp.ContinueCmd - interp.commands['echo'] = interp.EchoCmd - interp.commands['eval'] = interp.EvalCmd - interp.commands['expr'] = interp.ExprCmd - interp.commands['for'] = interp.ForCmd - interp.commands['glob'] = interp.GlobCmd - interp.commands['global'] = interp.GlobalCmd - interp.commands['if'] = interp.IfCmd - interp.commands['index'] = interp.IndexCmd - interp.commands['list'] = interp.ListCmd - interp.commands['proc'] = interp.ProcCmd - interp.commands['rename'] = interp.RenameCmd - interp.commands['return'] = interp.ReturnCmd - interp.commands['set'] = interp.SetCmd - return interp - # - def Delete(interp): - # - # Only break circular references here; - # most things will be garbage-collected. - # - for name in interp.commands.keys(): - del interp.commands[name] - # - def CreateCommand(interp, (name, proc)): - interp.commands[name] = proc - # - def DeleteCommand(interp, (name)): - del interp.commands[name] - # - # Local variables are maintained on the stack. - # A local variable with value "None" is a dummy - # meaning that the corresponding global variable - # should be used. - # - def GetVar(interp, varName): - dict = interp.globals - if interp.stack: - d = interp.stack[-1:][0].locals - if d.has_key(varName) and d[varName] = None: - pass - else: - dict = d - if not dict.has_key(varName): - raise TclRuntimeError, \ - 'Variable "' + varName + '" not found' - return dict[varName] - # - def SetVar(interp, (varName, newValue)): - dict = interp.globals - if interp.stack: - d = interp.stack[-1:][0].locals - if d.has_key(varName) and d[varName] = None: - pass - else: - dict = d - dict[varName] = newValue - # - def Expand(interp, (str, i, end)): - if end <= i: return '' - if str[i] = '{' and str[end-1] = '}': - return str[i+1:end-1] - if str[i] = '"' and str[end-1] = '"': - i, end = i+1, end-1 - result = '' - while i < end: - c = str[i] - if c = '\\': - x, i = Backslash(str, i, end) - result = result + x - elif c = '[': - j = BalanceBrackets(str, i, end) - x = interp.EvalBasic(str, i+1, j-1, 1) - result = result + x - i = j - elif c = '$': - i = i+1 - j = FindVarName(str, i, end) - name = str[i:j] - i = j - if not name: - result = result + '$' - else: - if name[:1] = '{' and name[-1:] = '}': - name = name[1:-1] - result = result + interp.GetVar(name) - else: - j = _expand_prog.exec(str, i) - j = min(j, end) - result = result + str[i:j] - i = j - return result - # - def EvalBasic(interp, (str, i, end, bracketed)): - result = '' - while i < end: - indexargv, i = FindNextCommand( \ - str, i, end, bracketed) - if indexargv: - argv = [] - for x, y in indexargv: - arg = interp.Expand(str, x, y) - argv.append(arg) - name = argv[0] - if not interp.commands.has_key(name): - raise TclRuntimeError, \ - 'Command "' + name + \ - '" not found' - result = interp.commands[name](argv) - return result - # - def Eval(interp, str): - return interp.EvalBasic(str, 0, len(str), 0) - # - def ExprBasic(interp, (str, begin, end)): - expr = interp.Expand(str, begin, end) - i = SkipSpaces(expr, 0, len(expr)) - expr = expr[i:] - try: - return eval(expr, {}) - except (NameError, TypeError, RuntimeError, EOFError), msg: - import sys - raise TclRuntimeError, sys.exc_type + ': ' + msg - # - def Expr(interp, str): - return interp.ExprBasic(str, 0, len(str)) - # - # The rest are command implementations - # - def BreakCmd(interp, argv): - if len(argv) <> 1: - raise TclRuntimeError, 'usage: break' - raise TclBreak - # - def ConcatCmd(interp, argv): - if len(argv) < 2: - raise TclRuntimeError, 'usage: concat arg ...' - return Concat(argv[1:]) - # - def ContinueCmd(interp, argv): - if len(argv) <> 1: - raise TclRuntimeError, 'usage: continue' - raise TclContinue - # - def EchoCmd(interp, argv): - for arg in argv[1:]: print arg, - print - return '' - # - def EvalCmd(interp, argv): - if len(argv) < 2: - raise TclRuntimeError, 'usage: eval arg [arg ...]' - str = Concat(argv[1:]) - return interp.Eval(str) - # - def ExprCmd(interp, argv): - if len(argv) <> 2: - raise TclRuntimeError, 'usage: expr expression' - expr = argv[1] - result = interp.Expr(expr) - if type(result) <> type(''): result = `result` - return result - # - def ForCmd(interp, argv): - if len(argv) <> 5: - raise TclRuntimeError, \ - 'usage: for start test next body' - x = interp.Eval(argv[1]) - while interp.Expr(argv[2]): - try: - x = interp.Eval(argv[4]) - except TclBreak: - break - except TclContinue: - pass - x = interp.Eval(argv[3]) - return '' - # - def GlobCmd(interp, argv): - import macglob - if len(argv) < 2: - raise TclRuntimeError, 'usage: glob pattern ...' - list = [] - for pat in argv[1:]: - list = list + macglob.glob(pat) - if not list: - raise TclRuntimeError, 'no match for glob pattern(s)' - return BuildList(list) - # - def GlobalCmd(interp, argv): - if len(argv) < 2: - raise TclRuntimeError, 'usage: global varname ...' - if not interp.stack: - raise TclRuntimeError, 'global used outside proc' - dict = interp.stack[-1:][0].locals - for name in argv[1:]: - dict[name] = None - return '' - # - def IfCmd(interp, argv): - argv = argv[:] - if len(argv) > 2 and argv[2] = 'then': del argv[2] - if len(argv) > 3 and argv[3] = 'else': del argv[3] - if not 3 <= len(argv) <= 4: - raise TclRuntimeError, \ - 'usage: if test [then] trueBody [else] falseBody' - if interp.Expr(argv[1]): - return interp.Eval(argv[2]) - if len(argv) > 3: - return interp.Eval(argv[3]) - return '' - # - def IndexCmd(interp, argv): - if len(argv) <> 3: - raise TclRuntimeError, 'usage: index value index' - import string - try: - index = string.atoi(argv[2]) - if index < 0: raise string.atoi_error - except string.atoi_error: - raise TclRuntimeError, 'bad index: ' + argv[2] - list = SplitList(argv[1]) - if index >= len(list): return '' - return list[index] - # - def ListCmd(interp, argv): - if len(argv) < 2: - raise TclRuntimeError, 'usage: list arg ...' - return BuildList(argv[1:]) - # - def ProcCmd(interp, argv): - if len(argv) <> 4: - raise TclRuntimeError, 'usage: proc name args body' - x = _Proc().Create(interp, argv[2], argv[3]) - interp.CreateCommand(argv[1], x.Call) - return '' - # - def RenameCmd(interp, argv): - if len(argv) <> 3: - raise TclRuntimeError, 'usage: rename oldName newName' - oldName, newName = argv[1], argv[2] - if not interp.commands.has_key(oldName): - raise TclRuntimeError, \ - 'command "' + oldName + '" not found' - if newName: interp.commands[newName] = interp.commands[oldName] - del interp.commands[oldName] - return '' - # - def ReturnCmd(interp, argv): - if not 1 <= len(argv) <= 2: - raise TclRuntimeError, 'usage: return [arg]' - if len(argv) = 1: raise TclReturn, '' - raise TclReturn, argv[1] - # - def SetCmd(interp, argv): - n = len(argv) - if not 2 <= n <= 3: - raise TclRuntimeError, 'usage: set varname [newvalue]' - if n = 2: return interp.GetVar(argv[1]) - interp.SetVar(argv[1], argv[2]) - return '' + # + def Create(interp): + interp.globals = {} + interp.commands = {} + interp.stack = [] + interp.commands['break'] = interp.BreakCmd + interp.commands['concat'] = interp.ConcatCmd + interp.commands['continue'] = interp.ContinueCmd + interp.commands['echo'] = interp.EchoCmd + interp.commands['eval'] = interp.EvalCmd + interp.commands['expr'] = interp.ExprCmd + interp.commands['for'] = interp.ForCmd + interp.commands['glob'] = interp.GlobCmd + interp.commands['global'] = interp.GlobalCmd + interp.commands['if'] = interp.IfCmd + interp.commands['index'] = interp.IndexCmd + interp.commands['list'] = interp.ListCmd + interp.commands['proc'] = interp.ProcCmd + interp.commands['rename'] = interp.RenameCmd + interp.commands['return'] = interp.ReturnCmd + interp.commands['set'] = interp.SetCmd + return interp + # + def Delete(interp): + # + # Only break circular references here; + # most things will be garbage-collected. + # + for name in interp.commands.keys(): + del interp.commands[name] + # + def CreateCommand(interp, (name, proc)): + interp.commands[name] = proc + # + def DeleteCommand(interp, (name)): + del interp.commands[name] + # + # Local variables are maintained on the stack. + # A local variable with value "None" is a dummy + # meaning that the corresponding global variable + # should be used. + # + def GetVar(interp, varName): + dict = interp.globals + if interp.stack: + d = interp.stack[-1:][0].locals + if d.has_key(varName) and d[varName] = None: + pass + else: + dict = d + if not dict.has_key(varName): + raise TclRuntimeError, \ + 'Variable "' + varName + '" not found' + return dict[varName] + # + def SetVar(interp, (varName, newValue)): + dict = interp.globals + if interp.stack: + d = interp.stack[-1:][0].locals + if d.has_key(varName) and d[varName] = None: + pass + else: + dict = d + dict[varName] = newValue + # + def Expand(interp, (str, i, end)): + if end <= i: return '' + if str[i] = '{' and str[end-1] = '}': + return str[i+1:end-1] + if str[i] = '"' and str[end-1] = '"': + i, end = i+1, end-1 + result = '' + while i < end: + c = str[i] + if c = '\\': + x, i = Backslash(str, i, end) + result = result + x + elif c = '[': + j = BalanceBrackets(str, i, end) + x = interp.EvalBasic(str, i+1, j-1, 1) + result = result + x + i = j + elif c = '$': + i = i+1 + j = FindVarName(str, i, end) + name = str[i:j] + i = j + if not name: + result = result + '$' + else: + if name[:1] = '{' and name[-1:] = '}': + name = name[1:-1] + result = result + interp.GetVar(name) + else: + j = _expand_prog.exec(str, i) + j = min(j, end) + result = result + str[i:j] + i = j + return result + # + def EvalBasic(interp, (str, i, end, bracketed)): + result = '' + while i < end: + indexargv, i = FindNextCommand( \ + str, i, end, bracketed) + if indexargv: + argv = [] + for x, y in indexargv: + arg = interp.Expand(str, x, y) + argv.append(arg) + name = argv[0] + if not interp.commands.has_key(name): + raise TclRuntimeError, \ + 'Command "' + name + \ + '" not found' + result = interp.commands[name](argv) + return result + # + def Eval(interp, str): + return interp.EvalBasic(str, 0, len(str), 0) + # + def ExprBasic(interp, (str, begin, end)): + expr = interp.Expand(str, begin, end) + i = SkipSpaces(expr, 0, len(expr)) + expr = expr[i:] + try: + return eval(expr, {}) + except (NameError, TypeError, RuntimeError, EOFError), msg: + import sys + raise TclRuntimeError, sys.exc_type + ': ' + msg + # + def Expr(interp, str): + return interp.ExprBasic(str, 0, len(str)) + # + # The rest are command implementations + # + def BreakCmd(interp, argv): + if len(argv) <> 1: + raise TclRuntimeError, 'usage: break' + raise TclBreak + # + def ConcatCmd(interp, argv): + if len(argv) < 2: + raise TclRuntimeError, 'usage: concat arg ...' + return Concat(argv[1:]) + # + def ContinueCmd(interp, argv): + if len(argv) <> 1: + raise TclRuntimeError, 'usage: continue' + raise TclContinue + # + def EchoCmd(interp, argv): + for arg in argv[1:]: print arg, + print + return '' + # + def EvalCmd(interp, argv): + if len(argv) < 2: + raise TclRuntimeError, 'usage: eval arg [arg ...]' + str = Concat(argv[1:]) + return interp.Eval(str) + # + def ExprCmd(interp, argv): + if len(argv) <> 2: + raise TclRuntimeError, 'usage: expr expression' + expr = argv[1] + result = interp.Expr(expr) + if type(result) <> type(''): result = `result` + return result + # + def ForCmd(interp, argv): + if len(argv) <> 5: + raise TclRuntimeError, \ + 'usage: for start test next body' + x = interp.Eval(argv[1]) + while interp.Expr(argv[2]): + try: + x = interp.Eval(argv[4]) + except TclBreak: + break + except TclContinue: + pass + x = interp.Eval(argv[3]) + return '' + # + def GlobCmd(interp, argv): + import macglob + if len(argv) < 2: + raise TclRuntimeError, 'usage: glob pattern ...' + list = [] + for pat in argv[1:]: + list = list + macglob.glob(pat) + if not list: + raise TclRuntimeError, 'no match for glob pattern(s)' + return BuildList(list) + # + def GlobalCmd(interp, argv): + if len(argv) < 2: + raise TclRuntimeError, 'usage: global varname ...' + if not interp.stack: + raise TclRuntimeError, 'global used outside proc' + dict = interp.stack[-1:][0].locals + for name in argv[1:]: + dict[name] = None + return '' + # + def IfCmd(interp, argv): + argv = argv[:] + if len(argv) > 2 and argv[2] = 'then': del argv[2] + if len(argv) > 3 and argv[3] = 'else': del argv[3] + if not 3 <= len(argv) <= 4: + raise TclRuntimeError, \ + 'usage: if test [then] trueBody [else] falseBody' + if interp.Expr(argv[1]): + return interp.Eval(argv[2]) + if len(argv) > 3: + return interp.Eval(argv[3]) + return '' + # + def IndexCmd(interp, argv): + if len(argv) <> 3: + raise TclRuntimeError, 'usage: index value index' + import string + try: + index = string.atoi(argv[2]) + if index < 0: raise string.atoi_error + except string.atoi_error: + raise TclRuntimeError, 'bad index: ' + argv[2] + list = SplitList(argv[1]) + if index >= len(list): return '' + return list[index] + # + def ListCmd(interp, argv): + if len(argv) < 2: + raise TclRuntimeError, 'usage: list arg ...' + return BuildList(argv[1:]) + # + def ProcCmd(interp, argv): + if len(argv) <> 4: + raise TclRuntimeError, 'usage: proc name args body' + x = _Proc().Create(interp, argv[2], argv[3]) + interp.CreateCommand(argv[1], x.Call) + return '' + # + def RenameCmd(interp, argv): + if len(argv) <> 3: + raise TclRuntimeError, 'usage: rename oldName newName' + oldName, newName = argv[1], argv[2] + if not interp.commands.has_key(oldName): + raise TclRuntimeError, \ + 'command "' + oldName + '" not found' + if newName: interp.commands[newName] = interp.commands[oldName] + del interp.commands[oldName] + return '' + # + def ReturnCmd(interp, argv): + if not 1 <= len(argv) <= 2: + raise TclRuntimeError, 'usage: return [arg]' + if len(argv) = 1: raise TclReturn, '' + raise TclReturn, argv[1] + # + def SetCmd(interp, argv): + n = len(argv) + if not 2 <= n <= 3: + raise TclRuntimeError, 'usage: set varname [newvalue]' + if n = 2: return interp.GetVar(argv[1]) + interp.SetVar(argv[1], argv[2]) + return '' # The rest are just demos: def MainLoop(interp): - buffer = CmdBuf().Create() - if not interp.globals.has_key('ps1'): interp.globals['ps1'] = '% ' - if not interp.globals.has_key('ps2'): interp.globals['ps2'] = '' - psname = 'ps1' - while 1: - try: - line = raw_input(interp.globals[psname]) - except (EOFError, KeyboardInterrupt): - print - break - line = buffer.Assemble(line + '\n') - if not line: - psname = 'ps2' - else: - psname = 'ps1' - try: - x = interp.Eval(line) - if x <> '': print 'Result:', `x` - except (TclRuntimeError, TclSyntaxError, \ - TclMatchingError), msg: - print 'Error:', msg - except (TclBreak, TclContinue): - print 'Error: break or continue outside loop' - except TclReturn, value: - # Return outside proc returns to main loop - if value: print value + buffer = CmdBuf().Create() + if not interp.globals.has_key('ps1'): interp.globals['ps1'] = '% ' + if not interp.globals.has_key('ps2'): interp.globals['ps2'] = '' + psname = 'ps1' + while 1: + try: + line = raw_input(interp.globals[psname]) + except (EOFError, KeyboardInterrupt): + print + break + line = buffer.Assemble(line + '\n') + if not line: + psname = 'ps2' + else: + psname = 'ps1' + try: + x = interp.Eval(line) + if x <> '': print 'Result:', `x` + except (TclRuntimeError, TclSyntaxError, \ + TclMatchingError), msg: + print 'Error:', msg + except (TclBreak, TclContinue): + print 'Error: break or continue outside loop' + except TclReturn, value: + # Return outside proc returns to main loop + if value: print value the_interpreter = Interpreter().Create() def main(): - MainLoop(the_interpreter) + MainLoop(the_interpreter) # XXX To do: diff --git a/lib/TclShell.py b/lib/TclShell.py index 78d8dc4..8d0ef19 100644 --- a/lib/TclShell.py +++ b/lib/TclShell.py @@ -10,246 +10,246 @@ from macpath import isfile, isdir, exists UsageError = TclRuntimeError class ShellInterpreter() = Interpreter(): - # - def ResetVariables(interp): - interp.globals['ps1'] = '$ ' - interp.globals['ps2'] = '> ' - interp.globals['home'] = mac.getcwd() - # - def DefineCommands(interp): - interp.commands['cd'] = interp.CdCmd - interp.commands['grep'] = interp.GrepCmd - interp.commands['ls'] = interp.LsCmd - interp.commands['mkdir'] = interp.MkdirCmd - interp.commands['mv'] = interp.MvCmd - interp.commands['pg'] = interp.PgCmd - interp.commands['pwd'] = interp.PwdCmd - interp.commands['rm'] = interp.RmCmd - interp.commands['rmdir'] = interp.RmdirCmd - interp.commands['sync'] = interp.SyncCmd - # - def Reset(interp): - interp.ResetVariables() - interp.DefineCommands() - # - def Create(interp): - interp = Interpreter.Create(interp) # initialize base class - interp.Reset() - return interp - # - # Command-implementing functions - # - def CdCmd(interp, argv): - if len(argv) > 2: - raise UsageError, 'usage: cd [dirname]' - if len(argv) = 2: - chdirto(argv[1]) - else: - chdirto(interp.globals['home']) - return '' - # - def GrepCmd(interp, argv): - if len(argv) < 3: - raise UsageError, 'usage: grep regexp file ...' - import regexp - try: - prog = regexp.compile(argv[1]) - except regexp.error, msg: - raise TclRuntimeError, \ - ('grep', argv[1], ': bad regexp :', msg) - for file in argv[2:]: - grepfile(prog, file) - return '' - # - def LsCmd(interp, argv): - if len(argv) < 2: - lsdir(':') - else: - for dirname in argv[1:]: - lsdir(dirname) - return '' - # - def MkdirCmd(interp, argv): - if len(argv) < 2: - raise UsageError, 'usage: mkdir name ...' - for name in argv[1:]: - makedir(name) - return '' - # - def MvCmd(interp, argv): - if len(argv) <> 3: - raise UsageError, 'usage: mv src dst' - src, dst = argv[1], argv[2] - if not exists(src): - raise TclRuntimeError, \ - ('mv', src, dst, ': source does not exist') - if exists(dst): - raise TclRuntimeError, \ - ('mv', src, dst, ': destination already exists') - try: - mac.rename(src, dst) - except mac.error, msg: - raise TclRuntimeError, \ - (src, dst, ': rename failed :', msg) - return '' - # - def PgCmd(interp, argv): - if len(argv) < 2: - raise UsageError, 'usage: page file ...' - for name in argv[1:]: - pagefile(name) - return '' - # - def PwdCmd(interp, argv): - if len(argv) > 1: - raise UsageError, 'usage: pwd' - else: - return mac.getcwd() - # - def RmCmd(interp, argv): - if len(argv) < 2: - raise UsageError, 'usage: rm file ...' - for name in argv[1:]: - remove(name) - return '' - # - def RmdirCmd(interp, argv): - if len(argv) < 2: - raise UsageError, 'usage: rmdir dir ...' - for name in argv[1:]: - rmdir(name) - return '' - # - def SyncCmd(interp, argv): - if len(argv) > 1: - raise UsageError, 'usage: sync' - try: - mac.sync() - except mac.error, msg: - raise TclRuntimeError, ('sync failed :', msg) - # + # + def ResetVariables(interp): + interp.globals['ps1'] = '$ ' + interp.globals['ps2'] = '> ' + interp.globals['home'] = mac.getcwd() + # + def DefineCommands(interp): + interp.commands['cd'] = interp.CdCmd + interp.commands['grep'] = interp.GrepCmd + interp.commands['ls'] = interp.LsCmd + interp.commands['mkdir'] = interp.MkdirCmd + interp.commands['mv'] = interp.MvCmd + interp.commands['pg'] = interp.PgCmd + interp.commands['pwd'] = interp.PwdCmd + interp.commands['rm'] = interp.RmCmd + interp.commands['rmdir'] = interp.RmdirCmd + interp.commands['sync'] = interp.SyncCmd + # + def Reset(interp): + interp.ResetVariables() + interp.DefineCommands() + # + def Create(interp): + interp = Interpreter.Create(interp) # initialize base class + interp.Reset() + return interp + # + # Command-implementing functions + # + def CdCmd(interp, argv): + if len(argv) > 2: + raise UsageError, 'usage: cd [dirname]' + if len(argv) = 2: + chdirto(argv[1]) + else: + chdirto(interp.globals['home']) + return '' + # + def GrepCmd(interp, argv): + if len(argv) < 3: + raise UsageError, 'usage: grep regexp file ...' + import regexp + try: + prog = regexp.compile(argv[1]) + except regexp.error, msg: + raise TclRuntimeError, \ + ('grep', argv[1], ': bad regexp :', msg) + for file in argv[2:]: + grepfile(prog, file) + return '' + # + def LsCmd(interp, argv): + if len(argv) < 2: + lsdir(':') + else: + for dirname in argv[1:]: + lsdir(dirname) + return '' + # + def MkdirCmd(interp, argv): + if len(argv) < 2: + raise UsageError, 'usage: mkdir name ...' + for name in argv[1:]: + makedir(name) + return '' + # + def MvCmd(interp, argv): + if len(argv) <> 3: + raise UsageError, 'usage: mv src dst' + src, dst = argv[1], argv[2] + if not exists(src): + raise TclRuntimeError, \ + ('mv', src, dst, ': source does not exist') + if exists(dst): + raise TclRuntimeError, \ + ('mv', src, dst, ': destination already exists') + try: + mac.rename(src, dst) + except mac.error, msg: + raise TclRuntimeError, \ + (src, dst, ': rename failed :', msg) + return '' + # + def PgCmd(interp, argv): + if len(argv) < 2: + raise UsageError, 'usage: page file ...' + for name in argv[1:]: + pagefile(name) + return '' + # + def PwdCmd(interp, argv): + if len(argv) > 1: + raise UsageError, 'usage: pwd' + else: + return mac.getcwd() + # + def RmCmd(interp, argv): + if len(argv) < 2: + raise UsageError, 'usage: rm file ...' + for name in argv[1:]: + remove(name) + return '' + # + def RmdirCmd(interp, argv): + if len(argv) < 2: + raise UsageError, 'usage: rmdir dir ...' + for name in argv[1:]: + rmdir(name) + return '' + # + def SyncCmd(interp, argv): + if len(argv) > 1: + raise UsageError, 'usage: sync' + try: + mac.sync() + except mac.error, msg: + raise TclRuntimeError, ('sync failed :', msg) + # def chdirto(dirname): - try: - mac.chdir(dirname) - except mac.error, msg: - raise TclRuntimeError, (dirname, ': chdir failed :', msg) + try: + mac.chdir(dirname) + except mac.error, msg: + raise TclRuntimeError, (dirname, ': chdir failed :', msg) def grepfile(prog, file): - try: - fp = open(file, 'r') - except RuntimeError, msg: - raise TclRuntimeError, (file, ': open failed :', msg) - lineno = 0 - while 1: - line = fp.readline() - if not line: break - lineno = lineno+1 - if prog.exec(line): - print file+'('+`lineno`+'):', line, + try: + fp = open(file, 'r') + except RuntimeError, msg: + raise TclRuntimeError, (file, ': open failed :', msg) + lineno = 0 + while 1: + line = fp.readline() + if not line: break + lineno = lineno+1 + if prog.exec(line): + print file+'('+`lineno`+'):', line, def lsdir(dirname): - if not isdir(dirname): - print dirname, ': no such directory' - return - names = mac.listdir(dirname) - lsfiles(names, dirname) + if not isdir(dirname): + print dirname, ': no such directory' + return + names = mac.listdir(dirname) + lsfiles(names, dirname) def lsfiles(names, dirname): - names = names[:] # Make a copy so we can modify it - for i in range(len(names)): - name = names[i] - if isdir(macpath.cat(dirname, name)): - names[i] = ':' + name + ':' - columnize(names) + names = names[:] # Make a copy so we can modify it + for i in range(len(names)): + name = names[i] + if isdir(macpath.cat(dirname, name)): + names[i] = ':' + name + ':' + columnize(names) def makedir(name): - if exists(name): - print name, ': already exists' - return - try: - mac.mkdir(name, 0777) - except mac.error, msg: - raise TclRuntimeError, (name, ': mkdir failed :', msg) + if exists(name): + print name, ': already exists' + return + try: + mac.mkdir(name, 0777) + except mac.error, msg: + raise TclRuntimeError, (name, ': mkdir failed :', msg) def pagefile(name): - import string - if not isfile(name): - print name, ': no such file' - return - LINES = 24 - 1 - # For THINK C 3.0, make the path absolute: - # if not macpath.isabs(name): - # name = macpath.cat(mac.getcwd(), name) - try: - fp = open(name, 'r') - except RuntimeError, msg: - raise TclRuntimeError, (name, ': open failed :', msg) - line = fp.readline() - while line: - for i in range(LINES): - print line, - line = fp.readline() - if not line: break - if line: - try: - more = raw_input('[more]') - except (EOFError, KeyboardInterrupt): - print - break - if string.strip(more)[:1] in ('q', 'Q'): - break + import string + if not isfile(name): + print name, ': no such file' + return + LINES = 24 - 1 + # For THINK C 3.0, make the path absolute: + # if not macpath.isabs(name): + # name = macpath.cat(mac.getcwd(), name) + try: + fp = open(name, 'r') + except RuntimeError, msg: + raise TclRuntimeError, (name, ': open failed :', msg) + line = fp.readline() + while line: + for i in range(LINES): + print line, + line = fp.readline() + if not line: break + if line: + try: + more = raw_input('[more]') + except (EOFError, KeyboardInterrupt): + print + break + if string.strip(more)[:1] in ('q', 'Q'): + break def remove(name): - if not isfile(name): - print name, ': no such file' - return - try: - mac.unlink(name) - except mac.error, msg: - raise TclRuntimeError, (name, ': unlink failed :', msg) + if not isfile(name): + print name, ': no such file' + return + try: + mac.unlink(name) + except mac.error, msg: + raise TclRuntimeError, (name, ': unlink failed :', msg) def rmdir(name): - if not isdir(name): - raise TclRuntimeError, (name, ': no such directory') - try: - mac.rmdir(name) - except mac.error, msg: - raise TclRuntimeError, (name, ': rmdir failed :', msg) + if not isdir(name): + raise TclRuntimeError, (name, ': no such directory') + try: + mac.rmdir(name) + except mac.error, msg: + raise TclRuntimeError, (name, ': rmdir failed :', msg) def printlist(list): - for word in list: - print word, + for word in list: + print word, def columnize(list): - import string - COLUMNS = 80-1 - n = len(list) - colwidth = maxwidth(list) - ncols = (COLUMNS + 1) / (colwidth + 1) - if ncols < 1: ncols = 1 - nrows = (n + ncols - 1) / ncols - for irow in range(nrows): - line = '' - for icol in range(ncols): - i = irow + nrows*icol - if 0 <= i < n: - word = list[i] - if i+nrows < n: - word = string.ljust(word, colwidth) - if icol > 0: - word = ' ' + word - line = line + word - print line + import string + COLUMNS = 80-1 + n = len(list) + colwidth = maxwidth(list) + ncols = (COLUMNS + 1) / (colwidth + 1) + if ncols < 1: ncols = 1 + nrows = (n + ncols - 1) / ncols + for irow in range(nrows): + line = '' + for icol in range(ncols): + i = irow + nrows*icol + if 0 <= i < n: + word = list[i] + if i+nrows < n: + word = string.ljust(word, colwidth) + if icol > 0: + word = ' ' + word + line = line + word + print line def maxwidth(list): - width = 0 - for word in list: - if len(word) > width: - width = len(word) - return width + width = 0 + for word in list: + if len(word) > width: + width = len(word) + return width the_interpreter = ShellInterpreter().Create() def main(): - Tcl.MainLoop(the_interpreter) + Tcl.MainLoop(the_interpreter) diff --git a/lib/TclUtil.py b/lib/TclUtil.py index 0990530..fb7b530 100644 --- a/lib/TclUtil.py +++ b/lib/TclUtil.py @@ -12,7 +12,7 @@ # For efficiency, the Tcl "tokenizing" routines used pre-compiled -# regular expressions. This is less readable but should be much faster +# regular expressions. This is less readable but should be much faster # than scanning the string a character at a time. # # The global variables @@ -21,9 +21,9 @@ # # The patterns always # have the form * so they always match at the start of the -# search buffer---maybe with the empty string. This makes it possible +# search buffer---maybe with the empty string. This makes it possible # to use the expression "_foo_prog.exec(str, i)[0][1]" to find the first -# character beyond the matched string. Note that this may be beyond the +# character beyond the matched string. Note that this may be beyond the # end variable -- where this matters, "min(i, end)" is used. # Constructs that cannot @@ -33,19 +33,19 @@ # # Many regular expressions contain an expression that matches # a Tcl backslash sequence as a subpart: -# \\\\C?M?(.|\n) +# \\\\C?M?(.|\n) # # This is a bit hard to # read because the backslash contained in it must be doubled twice: # once to get past Python's backslash mechanism, once to get past that -# of regular expressions. It uses (.|\n) to match absolutely +# of regular expressions. It uses (.|\n) to match absolutely # *every character*, becase the MULTILINE regular expression package does # not accept '\n' as a match for '.'. # # There is also a simplification in the pattern for backslashes: # *any* single character following a backslash is escaped, # so hex and octal -# excapes are not scanned fully. The forms \Cx, \Mx and \CMx are +# excapes are not scanned fully. The forms \Cx, \Mx and \CMx are # scanned correctly, as these may hide a special character. # (This does not invalidate the recognition of strings, although the # match is effectuated in a different way than by the Backslash function.) @@ -69,28 +69,28 @@ TclMatchingError = 'Tcl matching error' _varname_prog = regexp.compile('[a-zA-Z0-9_]*') def FindVarName(str, i, end): - if i < end and str[i] = '{': return BalanceBraces(str, i, end) - i = _varname_prog.exec(str, i)[0][1] - return min(i, end) + if i < end and str[i] = '{': return BalanceBraces(str, i, end) + i = _varname_prog.exec(str, i)[0][1] + return min(i, end) # Split a list into its elements. # Return a list of elements (strings). def SplitList(str): - i, end = 0, len(str) - list = [] - while 1: - i = SkipSpaces(str, i, end) - if i >= end: break - j = i - i = FindNextElement(str, i, end) - if str[j] = '{' and str[i-1] = '}': - element = str[j+1:i-1] - else: - element = Collapse(str[j:i]) - list.append(element) - return list + i, end = 0, len(str) + list = [] + while 1: + i = SkipSpaces(str, i, end) + if i >= end: break + j = i + i = FindNextElement(str, i, end) + if str[j] = '{' and str[i-1] = '}': + element = str[j+1:i-1] + else: + element = Collapse(str[j:i]) + list.append(element) + return list # Find the next element from a list. @@ -98,13 +98,13 @@ def SplitList(str): _element_prog = regexp.compile('([^ \t\n\\]+|\\\\C?M?(.|\n))*') def FindNextElement(str, i, end): - if i < end and str[i] = '{': - i = BalanceBraces(str, i, end) - if i < end and str[i] not in ' \t\n': - raise TclSyntaxError, 'Garbage after } in list' - return i - i = _element_prog.exec(str, i)[0][1] - return min(i, end) + if i < end and str[i] = '{': + i = BalanceBraces(str, i, end) + if i < end and str[i] not in ' \t\n': + raise TclSyntaxError, 'Garbage after } in list' + return i + i = _element_prog.exec(str, i)[0][1] + return min(i, end) # Copy a string, expanding all backslash sequences. @@ -112,19 +112,19 @@ def FindNextElement(str, i, end): _collapse_prog = regexp.compile('(\n|[^\\]+)*') def Collapse(str): - if '\\' not in str: return str - i, end = 0, len(str) - result = '' - while i < end: - j = _collapse_prog.exec(str, i)[0][1] - j = min(j, end) - result = result + str[i:j] - if j >= end: break - c = str[j] - if c <> '\\': raise TclAssertError, 'collapse error' - x, i = Backslash(str, j, end) - result = result + x - return result + if '\\' not in str: return str + i, end = 0, len(str) + result = '' + while i < end: + j = _collapse_prog.exec(str, i)[0][1] + j = min(j, end) + result = result + str[i:j] + if j >= end: break + c = str[j] + if c <> '\\': raise TclAssertError, 'collapse error' + x, i = Backslash(str, j, end) + result = result + x + return result # Find the next full command. @@ -138,25 +138,25 @@ def Collapse(str): _eol_prog = regexp.compile('[^\n]*') def FindNextCommand(str, i, end, bracketed): - i = SkipSpaces(str, i, end) - if i >= end: return [], end - if str[i] = '#': - i = _eol_prog.exec(str, i) - i = min(i, end) - if i < end and str[i] = '\n': i = i+1 - return [], i - if bracketed: terminators = [';'] - else: terminators = [';', '\n'] - list = [] - while i < end: - j = FindNextWord(str, i, end) - word = str[i:j] - if word in terminators: - i = j - break - if word <> '\n': list.append(i, j) - i = SkipSpaces(str, j, end) - return list, i + i = SkipSpaces(str, i, end) + if i >= end: return [], end + if str[i] = '#': + i = _eol_prog.exec(str, i) + i = min(i, end) + if i < end and str[i] = '\n': i = i+1 + return [], i + if bracketed: terminators = [';'] + else: terminators = [';', '\n'] + list = [] + while i < end: + j = FindNextWord(str, i, end) + word = str[i:j] + if word in terminators: + i = j + break + if word <> '\n': list.append(i, j) + i = SkipSpaces(str, j, end) + return list, i # Find the next word of a command. @@ -167,26 +167,26 @@ def FindNextCommand(str, i, end, bracketed): _word_prog = regexp.compile('([^ \t\n;[\\]+|\\\\C?M?(.|\n))*') def FindNextWord(str, i, end): - if i >= end: return end - if str[i] in '{"': - if str[i] = '{': i = BalanceBraces(str, i, end) - else: i = BalanceQuotes(str, i, end) - if i >= end or str[i] in ' \t\n;': return min(i, end) - raise TclSyntaxError, 'Garbage after } or "' - begin = i - while i < end: - i = _word_prog.exec(str, i)[0][1] - if i >= end: - i = end - break - c = str[i] - if c in ' \t': break - if c in ';\n': - if i = begin: i = i+1 - break - if c = '[': i = BalanceBrackets(str, i, end) - else: raise TclAssertError, 'word error' - return i + if i >= end: return end + if str[i] in '{"': + if str[i] = '{': i = BalanceBraces(str, i, end) + else: i = BalanceQuotes(str, i, end) + if i >= end or str[i] in ' \t\n;': return min(i, end) + raise TclSyntaxError, 'Garbage after } or "' + begin = i + while i < end: + i = _word_prog.exec(str, i)[0][1] + if i >= end: + i = end + break + c = str[i] + if c in ' \t': break + if c in ';\n': + if i = begin: i = i+1 + break + if c = '[': i = BalanceBrackets(str, i, end) + else: raise TclAssertError, 'word error' + return i # Parse balanced brackets from str[i:end]. @@ -197,22 +197,22 @@ def FindNextWord(str, i, end): _brackets_prog = regexp.compile('([^][{\\]+|\n|\\\\C?M?(.|\n))*') def BalanceBrackets(str, i, end): - if i >= end or str[i] <> '[': - raise TclAssertError, 'BalanceBrackets' - nesting = 0 - while i < end: - i = _brackets_prog.exec(str, i)[0][1] - if i >= end: break - c = str[i] - if c = '{': i = BalanceBraces(str, i, end) - else: - i = i+1 - if c = '[': nesting = nesting + 1 - elif c = ']': - nesting = nesting - 1 - if nesting = 0: return i - else: raise TclAssertError, 'brackets error' - raise TclMatchingError, 'Unmatched bracket ([)' + if i >= end or str[i] <> '[': + raise TclAssertError, 'BalanceBrackets' + nesting = 0 + while i < end: + i = _brackets_prog.exec(str, i)[0][1] + if i >= end: break + c = str[i] + if c = '{': i = BalanceBraces(str, i, end) + else: + i = i+1 + if c = '[': nesting = nesting + 1 + elif c = ']': + nesting = nesting - 1 + if nesting = 0: return i + else: raise TclAssertError, 'brackets error' + raise TclMatchingError, 'Unmatched bracket ([)' # Parse balanced braces from str[i:end]. @@ -223,20 +223,20 @@ def BalanceBrackets(str, i, end): _braces_prog = regexp.compile('([^{}\\]+|\n|\\\\C?M?(.|\n))*') def BalanceBraces(str, i, end): - if i >= end or str[i] <> '{': - raise TclAssertError, 'BalanceBraces' - nesting = 0 - while i < end: - i = _braces_prog.exec(str, i)[0][1] - if i >= end: break - c = str[i] - i = i+1 - if c = '{': nesting = nesting + 1 - elif c = '}': - nesting = nesting - 1 - if nesting = 0: return i - else: raise TclAssertError, 'braces error' - raise TclMatchingError, 'Unmatched brace ({)' + if i >= end or str[i] <> '{': + raise TclAssertError, 'BalanceBraces' + nesting = 0 + while i < end: + i = _braces_prog.exec(str, i)[0][1] + if i >= end: break + c = str[i] + i = i+1 + if c = '{': nesting = nesting + 1 + elif c = '}': + nesting = nesting - 1 + if nesting = 0: return i + else: raise TclAssertError, 'braces error' + raise TclMatchingError, 'Unmatched brace ({)' # Parse double quotes from str[i:end]. @@ -246,11 +246,11 @@ def BalanceBraces(str, i, end): _quotes_prog = regexp.compile('([^"\\]+|\n|\\\\C?M?(.|\n))*') def BalanceQuotes(str, i, end): - if i >= end or str[i] <> '"': - raise TclAssertError, 'BalanceQuotes' - i = _quotes_prog.exec(str, i+1)[0][1] - if i < end and str[i] = '"': return i+1 - raise TclMatchingError, 'Unmatched quote (")' + if i >= end or str[i] <> '"': + raise TclAssertError, 'BalanceQuotes' + i = _quotes_prog.exec(str, i+1)[0][1] + if i < end and str[i] = '"': return i+1 + raise TclMatchingError, 'Unmatched quote (")' # Static data used by Backslash() @@ -272,44 +272,44 @@ del c # this takes only the backslash itself off the string. def Backslash(str, i, end): - if i >= end or str[i] <> '\\': - raise TclAssertError, 'Backslash' - i = i+1 - if i = end: return '\\', i - c = str[i] - i = i+1 - if _bstab.has_key(c): return _bstab[c], i - if c = 'C': - if i = end: return '\\', i-1 - c = str[i] - i = i+1 - if c = 'M': - if i = end: return '\\', i-2 - c = str[i] - i = i+1 - x = ord(c) % 040 + 0200 - else: - x = ord(c) % 040 - return chr(x), i - elif c = 'M': - if i = end: return '\\', i-1 - c = str[i] - i = i+1 - x = ord(c) - if x < 0200: x = x + 0200 - return chr(x), i - elif c and c in '0123456789': - x = ord(c) - ord('0') - end = min(end, i+2) - while i < end: - c = str[i] - if c not in '0123456789': break - i = i+1 - x = x*8 + ord(c) - ord('0') - return ord(x), i - else: - # Not something that we recognize - return '\\', i-1 + if i >= end or str[i] <> '\\': + raise TclAssertError, 'Backslash' + i = i+1 + if i = end: return '\\', i + c = str[i] + i = i+1 + if _bstab.has_key(c): return _bstab[c], i + if c = 'C': + if i = end: return '\\', i-1 + c = str[i] + i = i+1 + if c = 'M': + if i = end: return '\\', i-2 + c = str[i] + i = i+1 + x = ord(c) % 040 + 0200 + else: + x = ord(c) % 040 + return chr(x), i + elif c = 'M': + if i = end: return '\\', i-1 + c = str[i] + i = i+1 + x = ord(c) + if x < 0200: x = x + 0200 + return chr(x), i + elif c and c in '0123456789': + x = ord(c) - ord('0') + end = min(end, i+2) + while i < end: + c = str[i] + if c not in '0123456789': break + i = i+1 + x = x*8 + ord(c) - ord('0') + return ord(x), i + else: + # Not something that we recognize + return '\\', i-1 # Skip over spaces and tabs (but not newlines). @@ -317,61 +317,61 @@ def Backslash(str, i, end): _spaces_prog = regexp.compile('[ \t]*') def SkipSpaces(str, i, end): - i = _spaces_prog.exec(str, i)[0][1] - return min(i, end) + i = _spaces_prog.exec(str, i)[0][1] + return min(i, end) # Concatenate the elements of a list with intervening spaces. def Concat(argv): - result = '' - sep = '' - for arg in argv: - result = result + (sep + arg) - sep = ' ' - return result + result = '' + sep = '' + for arg in argv: + result = result + (sep + arg) + sep = ' ' + return result # Concatenate list elements, adding braces etc. to make them parseable # again with SplitList. def BuildList(argv): - result = '' - sep = '' - for arg in argv: - arg = AddBraces(arg) - result = result + (sep + arg) - sep = ' ' - return result + result = '' + sep = '' + for arg in argv: + arg = AddBraces(arg) + result = result + (sep + arg) + sep = ' ' + return result # Add braces around a string if necessary to make it parseable by SplitList. def AddBraces(str): - # Special case for empty string - if str = '': return '{}' - # See if it contains balanced braces - res = '{' + str + '}' - if TryNextElement(res): - # See if it would survive unquoted - # XXX should escape [] and $ as well??? - if TryNextElement(str) and Collapse(str) = str: return str - # No -- return with added braces - return res - # Unbalanced braces. Add backslashes before suspect characters - res = '' - for c in str: - if c in '$\\[]{} ;': c = '\\' + c - elif c = '\n': c = '\\n' - elif c = '\t': c = '\\t' - res = res + c - return res + # Special case for empty string + if str = '': return '{}' + # See if it contains balanced braces + res = '{' + str + '}' + if TryNextElement(res): + # See if it would survive unquoted + # XXX should escape [] and $ as well??? + if TryNextElement(str) and Collapse(str) = str: return str + # No -- return with added braces + return res + # Unbalanced braces. Add backslashes before suspect characters + res = '' + for c in str: + if c in '$\\[]{} ;': c = '\\' + c + elif c = '\n': c = '\\n' + elif c = '\t': c = '\\t' + res = res + c + return res def TryNextElement(str): - end = len(str) - try: - i = FindNextElement(str, 0, end) - return i = end - except (TclSyntaxError, TclMatchingError): - return 0 + end = len(str) + try: + i = FindNextElement(str, 0, end) + return i = end + except (TclSyntaxError, TclMatchingError): + return 0 diff --git a/lib/TestCSplit.py b/lib/TestCSplit.py index b638f81..5da55c4 100644 --- a/lib/TestCSplit.py +++ b/lib/TestCSplit.py @@ -6,21 +6,21 @@ from WindowParent import WindowParent from Buttons import PushButton def main(n): - from CSplit import CSplit - - 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() - - while 1: - the_event = stdwin.getevent() - if the_event[0] = WE_CLOSE: break - the_window.dispatch(the_event) - the_window.destroy() + from CSplit import CSplit + + 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() + + while 1: + the_event = stdwin.getevent() + if the_event[0] = WE_CLOSE: break + the_window.dispatch(the_event) + the_window.destroy() main(12) diff --git a/lib/TransParent.py b/lib/TransParent.py index a07b4c4..8cee283 100644 --- a/lib/TransParent.py +++ b/lib/TransParent.py @@ -3,94 +3,94 @@ # Use this as a base class for objects that are almost transparent. # Don't use as a base class for parents with multiple children. -Error = 'TransParent.Error' # Exception +Error = 'TransParent.Error' # Exception class ManageOneChild(): - # - # Upcalls shared with other single-child parents - # - def addchild(self, child): - if self.child: - raise Error, 'addchild: one child only' - if not child: - raise Error, 'addchild: bad child' - self.child = child - # - def delchild(self, child): - if not self.child: - raise Error, 'delchild: no child' - if child <> self.child: - raise Error, 'delchild: not my child' - self.child = 0 + # + # Upcalls shared with other single-child parents + # + def addchild(self, child): + if self.child: + raise Error, 'addchild: one child only' + if not child: + raise Error, 'addchild: bad child' + self.child = child + # + def delchild(self, child): + if not self.child: + raise Error, 'delchild: no child' + if child <> self.child: + raise Error, 'delchild: not my child' + self.child = 0 class TransParent() = ManageOneChild(): - # - # Calls from creator - # NB derived classes may add parameters to create() - # - def create(self, parent): - parent.addchild(self) - self.parent = parent - self.child = 0 # No child yet - # - # Downcalls from parent to child - # - def destroy(self): - del self.parent - if self.child: self.child.destroy() - del self.child - # - def minsize(self, m): - if not self.child: - return 0, 0 - else: - return self.child.minsize(m) - def getbounds(self, bounds): - if not self.child: - raise Error, 'getbounds w/o child' - else: - return self.child.getbounds() - def setbounds(self, bounds): - if not self.child: - raise Error, 'setbounds w/o child' - else: - self.child.setbounds(bounds) - def draw(self, args): - if self.child: - self.child.draw(args) - # - # Downcalls only made after certain upcalls - # - def mouse_down(self, detail): - if self.child: self.child.mouse_down(detail) - def mouse_move(self, detail): - if self.child: self.child.mouse_move(detail) - def mouse_up(self, detail): - if self.child: self.child.mouse_up(detail) - # - def timer(self): - if self.child: self.child.timer() - # - # Upcalls from child to parent - # - def need_mouse(self, child): - self.parent.need_mouse(self) - def no_mouse(self, child): - self.parent.no_mouse(self) - # - def need_timer(self, child): - self.parent.need_timer(self) - def no_timer(self, child): - self.parent.no_timer(self) - # - def begindrawing(self): - return self.parent.begindrawing() - def beginmeasuring(self): - return self.parent.beginmeasuring() - # - def change(self, area): - self.parent.change(area) - def scroll(self, args): - self.parent.scroll(args) - def settimer(self, itimer): - self.parent.settimer(itimer) + # + # Calls from creator + # NB derived classes may add parameters to create() + # + def create(self, parent): + parent.addchild(self) + self.parent = parent + self.child = 0 # No child yet + # + # Downcalls from parent to child + # + def destroy(self): + del self.parent + if self.child: self.child.destroy() + del self.child + # + def minsize(self, m): + if not self.child: + return 0, 0 + else: + return self.child.minsize(m) + def getbounds(self, bounds): + if not self.child: + raise Error, 'getbounds w/o child' + else: + return self.child.getbounds() + def setbounds(self, bounds): + if not self.child: + raise Error, 'setbounds w/o child' + else: + self.child.setbounds(bounds) + def draw(self, args): + if self.child: + self.child.draw(args) + # + # Downcalls only made after certain upcalls + # + def mouse_down(self, detail): + if self.child: self.child.mouse_down(detail) + def mouse_move(self, detail): + if self.child: self.child.mouse_move(detail) + def mouse_up(self, detail): + if self.child: self.child.mouse_up(detail) + # + def timer(self): + if self.child: self.child.timer() + # + # Upcalls from child to parent + # + def need_mouse(self, child): + self.parent.need_mouse(self) + def no_mouse(self, child): + self.parent.no_mouse(self) + # + def need_timer(self, child): + self.parent.need_timer(self) + def no_timer(self, child): + self.parent.no_timer(self) + # + def begindrawing(self): + return self.parent.begindrawing() + def beginmeasuring(self): + return self.parent.beginmeasuring() + # + def change(self, area): + self.parent.change(area) + def scroll(self, args): + self.parent.scroll(args) + def settimer(self, itimer): + self.parent.settimer(itimer) diff --git a/lib/VUMeter.py b/lib/VUMeter.py index c862452..31fe155 100644 --- a/lib/VUMeter.py +++ b/lib/VUMeter.py @@ -7,41 +7,41 @@ K = 1024 Rates = [0, 32*K, 16*K, 8*K] class VUMeter() = StripChart(): - # - # Override define() and timer() methods - # - def define(self, parent): - self = StripChart.define(self, (parent, 128)) - self.parent.need_timer(self) - self.sampling = 0 - self.rate = 3 - self.enable(0) - return self - # - def timer(self): - if self.sampling: - chunk = audio.wait_recording() - self.sampling = 0 - nums = audio.chr2num(chunk) - ampl = max(abs(min(nums)), abs(max(nums))) - self.append(ampl) - if self.enabled and not self.sampling: - audio.setrate(self.rate) - size = Rates[self.rate]/10 - size = size/48*48 - audio.start_recording(size) - self.sampling = 1 - if self.sampling: - self.parent.settimer(1) - # - # New methods: start() and stop() - # - def stop(self): - if self.sampling: - chunk = audio.stop_recording() - self.sampling = 0 - self.enable(0) - # - def start(self): - self.enable(1) - self.timer() + # + # Override define() and timer() methods + # + def define(self, parent): + self = StripChart.define(self, (parent, 128)) + self.parent.need_timer(self) + self.sampling = 0 + self.rate = 3 + self.enable(0) + return self + # + def timer(self): + if self.sampling: + chunk = audio.wait_recording() + self.sampling = 0 + nums = audio.chr2num(chunk) + ampl = max(abs(min(nums)), abs(max(nums))) + self.append(ampl) + if self.enabled and not self.sampling: + audio.setrate(self.rate) + size = Rates[self.rate]/10 + size = size/48*48 + audio.start_recording(size) + self.sampling = 1 + if self.sampling: + self.parent.settimer(1) + # + # New methods: start() and stop() + # + def stop(self): + if self.sampling: + chunk = audio.stop_recording() + self.sampling = 0 + self.enable(0) + # + def start(self): + self.enable(1) + self.timer() diff --git a/lib/WindowParent.py b/lib/WindowParent.py index 1e18930..5c72984 100644 --- a/lib/WindowParent.py +++ b/lib/WindowParent.py @@ -7,95 +7,95 @@ from stdwinevents import * from TransParent import ManageOneChild -Error = 'WindowParent.Error' # Exception +Error = 'WindowParent.Error' # Exception class WindowParent() = ManageOneChild(): - # - def create(self, (title, size)): - self.title = title - self.size = size # (width, height) - self._reset() - return self - # - def _reset(self): - self.child = 0 - self.win = 0 - self.itimer = 0 - self.do_mouse = 0 - self.do_timer = 0 - # - def destroy(self): - if self.child: self.child.destroy() - self._reset() - # - def need_mouse(self, child): self.do_mouse = 1 - def no_mouse(self, child): self.do_mouse = 0 - # - def need_timer(self, child): self.do_timer = 1 - def no_timer(self, child): self.do_timer = 0 - # - def realize(self): - if self.win: - raise Error, 'realize(): called twice' - if not self.child: - raise Error, 'realize(): no child' - size = self.child.minsize(self.beginmeasuring()) - self.size = max(self.size[0], size[0]), \ - max(self.size[1], size[1]) - #stdwin.setdefwinsize(self.size) - # XXX Compensate stdwin bug: - stdwin.setdefwinsize(self.size[0]+4, self.size[1]+2) - self.win = stdwin.open(self.title) - if self.itimer: - self.win.settimer(self.itimer) - bounds = (0, 0), self.win.getwinsize() - self.child.setbounds(bounds) - # - def beginmeasuring(self): - # Return something with which a child can measure text - if self.win: - return self.win.begindrawing() - else: - return stdwin - # - def begindrawing(self): - if self.win: - return self.win.begindrawing() - else: - raise Error, 'begindrawing(): not realized yet' - # - def change(self, area): - if self.win: - self.win.change(area) - # - def scroll(self, args): - if self.win: - self.win.scroll(args) - # - def settimer(self, itimer): - if self.win: - self.win.settimer(itimer) - else: - self.itimer = itimer - # - # Only call dispatch if we have a child - # - def dispatch(self, (type, win, detail)): - if win <> self.win: - return - elif type = WE_DRAW: - d = self.win.begindrawing() - self.child.draw(d, detail) - elif type = WE_MOUSE_DOWN: - if self.do_mouse: self.child.mouse_down(detail) - elif type = WE_MOUSE_MOVE: - if self.do_mouse: self.child.mouse_move(detail) - elif type = WE_MOUSE_UP: - if self.do_mouse: self.child.mouse_up(detail) - elif type = WE_TIMER: - if self.do_timer: self.child.timer() - elif type = WE_SIZE: - self.win.change((0, 0), (10000, 10000)) # XXX - bounds = (0, 0), self.win.getwinsize() - self.child.setbounds(bounds) - # + # + def create(self, (title, size)): + self.title = title + self.size = size # (width, height) + self._reset() + return self + # + def _reset(self): + self.child = 0 + self.win = 0 + self.itimer = 0 + self.do_mouse = 0 + self.do_timer = 0 + # + def destroy(self): + if self.child: self.child.destroy() + self._reset() + # + def need_mouse(self, child): self.do_mouse = 1 + def no_mouse(self, child): self.do_mouse = 0 + # + def need_timer(self, child): self.do_timer = 1 + def no_timer(self, child): self.do_timer = 0 + # + def realize(self): + if self.win: + raise Error, 'realize(): called twice' + if not self.child: + raise Error, 'realize(): no child' + size = self.child.minsize(self.beginmeasuring()) + self.size = max(self.size[0], size[0]), \ + max(self.size[1], size[1]) + #stdwin.setdefwinsize(self.size) + # XXX Compensate stdwin bug: + stdwin.setdefwinsize(self.size[0]+4, self.size[1]+2) + self.win = stdwin.open(self.title) + if self.itimer: + self.win.settimer(self.itimer) + bounds = (0, 0), self.win.getwinsize() + self.child.setbounds(bounds) + # + def beginmeasuring(self): + # Return something with which a child can measure text + if self.win: + return self.win.begindrawing() + else: + return stdwin + # + def begindrawing(self): + if self.win: + return self.win.begindrawing() + else: + raise Error, 'begindrawing(): not realized yet' + # + def change(self, area): + if self.win: + self.win.change(area) + # + def scroll(self, args): + if self.win: + self.win.scroll(args) + # + def settimer(self, itimer): + if self.win: + self.win.settimer(itimer) + else: + self.itimer = itimer + # + # Only call dispatch if we have a child + # + def dispatch(self, (type, win, detail)): + if win <> self.win: + return + elif type = WE_DRAW: + d = self.win.begindrawing() + self.child.draw(d, detail) + elif type = WE_MOUSE_DOWN: + if self.do_mouse: self.child.mouse_down(detail) + elif type = WE_MOUSE_MOVE: + if self.do_mouse: self.child.mouse_move(detail) + elif type = WE_MOUSE_UP: + if self.do_mouse: self.child.mouse_up(detail) + elif type = WE_TIMER: + if self.do_timer: self.child.timer() + elif type = WE_SIZE: + self.win.change((0, 0), (10000, 10000)) # XXX + bounds = (0, 0), self.win.getwinsize() + self.child.setbounds(bounds) + # diff --git a/lib/adv.py b/lib/adv.py index f32f91b..fd857b9 100644 --- a/lib/adv.py +++ b/lib/adv.py @@ -13,16 +13,16 @@ nil = return_nil() whitespace = ' \t\n' def split(s): - res = [] - i, n = 0, len(s) - while i < n: - while i < n and s[i] in whitespace: i = i+1 - if i = n: break - j = i - while j < n and s[j] not in whitespace: j = j+1 - res.append(s[i:j]) - i = j - return res + res = [] + i, n = 0, len(s) + while i < n: + while i < n and s[i] in whitespace: i = i+1 + if i = n: break + j = i + while j < n and s[j] not in whitespace: j = j+1 + res.append(s[i:j]) + i = j + return res # Constants to name directions @@ -68,76 +68,76 @@ alias['drop'] = PUT # Normalize a command, in place: truncate words to 6 chars, and expand aliases. def normalize(cmd): - for i in range(len(cmd)): - word = cmd[i][:6] - if alias.has_key(word): - word = alias[word] - cmd[i] = word + for i in range(len(cmd)): + word = cmd[i][:6] + if alias.has_key(word): + word = alias[word] + cmd[i] = word # The Object class describes objects that the player can carry around. class Object(): - def init(this, name): - this.name = name - return this - def describe(this): - print 'A', this.name + '.' - def get(this, (player, room)): - del room.objects[this.name] - player.objects[this.name] = this - def put(this, (player, room)): - del player.objects[this.name] - room.objects[this.name] = this + def init(this, name): + this.name = name + return this + def describe(this): + print 'A', this.name + '.' + def get(this, (player, room)): + del room.objects[this.name] + player.objects[this.name] = this + def put(this, (player, room)): + del player.objects[this.name] + room.objects[this.name] = this # The Player class embodies first person control. class Player(): - # Set initial state, except current room. - def init(self, initial_room): - self.blind = 0 - self.here = initial_room - self.prev = nil - self.objects = {} - return self - # Read and execute commands forever. - def play(self): - self.here.casualdescribe() - while 1: - self.move() - # Read and execute one command. - def move(self): - next = self.here.parser() - if next and next <> self.here: - self.prev = self.here - self.here = next - if not self.blind: - self.here.casualdescribe() - # Print inventory. - def inventory(self): - if not self.objects: - print 'You aren\'t carrying anything.' - return - print 'You are carrying:' - for key in self.objects.keys(): - self.objects[key].describe() - # Go back to previous room. - def back(self): - if self.prev: return self.prev - print 'You can\'t go back now.' - # Get an object from the room. - def get(self, name): - if self.here.objects.has_key(name): - self.here.objects[name].get(self, self.here) - else: - print 'I see no', name, 'here.' - # Put an object in the room. - def put(self, name): - if self.objects.has_key(name): - self.objects[name].put(self, self.here) - else: - print 'You have no', name, 'with you.' + # Set initial state, except current room. + def init(self, initial_room): + self.blind = 0 + self.here = initial_room + self.prev = nil + self.objects = {} + return self + # Read and execute commands forever. + def play(self): + self.here.casualdescribe() + while 1: + self.move() + # Read and execute one command. + def move(self): + next = self.here.parser() + if next and next <> self.here: + self.prev = self.here + self.here = next + if not self.blind: + self.here.casualdescribe() + # Print inventory. + def inventory(self): + if not self.objects: + print 'You aren\'t carrying anything.' + return + print 'You are carrying:' + for key in self.objects.keys(): + self.objects[key].describe() + # Go back to previous room. + def back(self): + if self.prev: return self.prev + print 'You can\'t go back now.' + # Get an object from the room. + def get(self, name): + if self.here.objects.has_key(name): + self.here.objects[name].get(self, self.here) + else: + print 'I see no', name, 'here.' + # Put an object in the room. + def put(self, name): + if self.objects.has_key(name): + self.objects[name].put(self, self.here) + else: + print 'You have no', name, 'with you.' # The Room class describes a generic room. @@ -145,120 +145,120 @@ class Player(): # that override certain operations. class Room(): - # Initialize a featureless room. - def init(here, name): - here.seen = 0 - here.name = name - here.exits = {} - here.objects = {} - here.description = [] - return here - # Add an object to the room. Used during initialization. - def add(here, obj): - here.objects[obj.name] = obj - # Print a casual description. - def casualdescribe(here): - if here.seen: - print here.name + '.' - here.listobjects() - return - here.seen = 1 - here.describe() - # Print a full description, including all exits and objects seen. - def describe(here): - if not here.description: - print here.name + '.' - here.listexits() - else: - for line in here.description: print line - here.listobjects() - # List exits. - def listexits(here): - there = here.exits.keys() - if there: - if len(there) = 1: - print 'There is an exit leading', - else: - print 'There are exits leading', - for name in there[:-2]: - print name + ',', - print there[len(there)-2], 'and', - print there[len(there)-1] + '.' - # List objects - def listobjects(here): - if here.objects: - print 'I see:' - for key in here.objects.keys(): - here.objects[key].describe() - # Default parser. Returns next room (possibly the same) or nil. - def parser(here): - cmd = here.getcmd(here.prompt()) - return here.decide(cmd) - # Return default prompt string. - def prompt(here): return '> ' - # Default input routine. Returns a non-empty list of words. - def getcmd(here, prompt): - # Loop until non-empty command gotten - # EOFError and KeyboardInterrupt may be caught elsewhere - while 1: - line = raw_input(prompt) - cmd = split(line) - if cmd: - normalize(cmd) - return cmd - # Default decision routine. Override for room-specific commands. - def decide(here, cmd): - key, args = cmd[0], cmd[1:] - if not args: - if key = N: return here.north() - if key = S: return here.south() - if key = E: return here.east() - if key = W: return here.west() - if key = U: return here.up() - if key = D: return here.down() - if key = NW: return here.nw() - if key = NE: return here.ne() - if key = SW: return here.sw() - if key = SE: return here.se() - if key = LOOK: return here.look() - if key = INVENT: return here.inventory() - if key = BACK: return here.back() - if here.objects.has_key(key): - print 'What do you want to do with the', key+'?' - else: - print 'Huh?' - return - if key = GET: - for arg in args: - player.get(arg) - return - if key = PUT: - for arg in args: - player.put(arg) - # Standard commands. - def look(here): - here.describe() - def inventory(here): - player.inventory() - def back(here): - return player.back() - # Standard exits. - def north(here): return here.take_exit(N) - def south(here): return here.take_exit(S) - def west(here): return here.take_exit(W) - def east(here): return here.take_exit(E) - def up(here): return here.take_exit(U) - def down(here): return here.take_exit(D) - def nw(here): return here.take_exit(NW) - def ne(here): return here.take_exit(NE) - def sw(here): return here.take_exit(SW) - def se(here): return here.take_exit(SE) - # Subroutine for standard exits. - def take_exit(here, key): - if here.exits.has_key(key): - return here.exits[key] - print 'You cannot go in that direction.' - return here + # Initialize a featureless room. + def init(here, name): + here.seen = 0 + here.name = name + here.exits = {} + here.objects = {} + here.description = [] + return here + # Add an object to the room. Used during initialization. + def add(here, obj): + here.objects[obj.name] = obj + # Print a casual description. + def casualdescribe(here): + if here.seen: + print here.name + '.' + here.listobjects() + return + here.seen = 1 + here.describe() + # Print a full description, including all exits and objects seen. + def describe(here): + if not here.description: + print here.name + '.' + here.listexits() + else: + for line in here.description: print line + here.listobjects() + # List exits. + def listexits(here): + there = here.exits.keys() + if there: + if len(there) = 1: + print 'There is an exit leading', + else: + print 'There are exits leading', + for name in there[:-2]: + print name + ',', + print there[len(there)-2], 'and', + print there[len(there)-1] + '.' + # List objects + def listobjects(here): + if here.objects: + print 'I see:' + for key in here.objects.keys(): + here.objects[key].describe() + # Default parser. Returns next room (possibly the same) or nil. + def parser(here): + cmd = here.getcmd(here.prompt()) + return here.decide(cmd) + # Return default prompt string. + def prompt(here): return '> ' + # Default input routine. Returns a non-empty list of words. + def getcmd(here, prompt): + # Loop until non-empty command gotten + # EOFError and KeyboardInterrupt may be caught elsewhere + while 1: + line = raw_input(prompt) + cmd = split(line) + if cmd: + normalize(cmd) + return cmd + # Default decision routine. Override for room-specific commands. + def decide(here, cmd): + key, args = cmd[0], cmd[1:] + if not args: + if key = N: return here.north() + if key = S: return here.south() + if key = E: return here.east() + if key = W: return here.west() + if key = U: return here.up() + if key = D: return here.down() + if key = NW: return here.nw() + if key = NE: return here.ne() + if key = SW: return here.sw() + if key = SE: return here.se() + if key = LOOK: return here.look() + if key = INVENT: return here.inventory() + if key = BACK: return here.back() + if here.objects.has_key(key): + print 'What do you want to do with the', key+'?' + else: + print 'Huh?' + return + if key = GET: + for arg in args: + player.get(arg) + return + if key = PUT: + for arg in args: + player.put(arg) + # Standard commands. + def look(here): + here.describe() + def inventory(here): + player.inventory() + def back(here): + return player.back() + # Standard exits. + def north(here): return here.take_exit(N) + def south(here): return here.take_exit(S) + def west(here): return here.take_exit(W) + def east(here): return here.take_exit(E) + def up(here): return here.take_exit(U) + def down(here): return here.take_exit(D) + def nw(here): return here.take_exit(NW) + def ne(here): return here.take_exit(NE) + def sw(here): return here.take_exit(SW) + def se(here): return here.take_exit(SE) + # Subroutine for standard exits. + def take_exit(here, key): + if here.exits.has_key(key): + return here.exits[key] + print 'You cannot go in that direction.' + return here # Create the objects we know about. @@ -271,10 +271,10 @@ o_python = Object().init('python') # Subroutine to connect two rooms. def connect(rm1, rm2, dir1, dir2): - if dir1: - rm1.exits[dir1] = rm2 - if dir2: - rm2.exits[dir2] = rm1 + if dir1: + rm1.exits[dir1] = rm2 + if dir2: + rm2.exits[dir2] = rm1 # Create the rooms and connect them together. @@ -283,34 +283,34 @@ def connect(rm1, rm2, dir1, dir2): r_front = Room().init('Front of building') r_initial = r_front r_front.description = [ \ - 'You are standing in front of a large, desolate building.', \ - 'Huge neon letters spell "CWI". The "I" is blinking.', \ - 'There are entrances north and west from where you are standing.', \ - ] + 'You are standing in front of a large, desolate building.', \ + 'Huge neon letters spell "CWI". The "I" is blinking.', \ + 'There are entrances north and west from where you are standing.', \ + ] r_entrance = Room().init('Entrance') r_entrance.description = [ \ - 'You are standing in a small entrance room.', \ - 'On the east side is a window to a reception room.', \ - 'South is a door leading outside the building.', \ - 'North is a large hall.' \ - ] + 'You are standing in a small entrance room.', \ + 'On the east side is a window to a reception room.', \ + 'South is a door leading outside the building.', \ + 'North is a large hall.' \ + ] r_hall_s = Room().init('South of hall') r_hall_s.description = [ \ - 'You are standing at the south side of a very large hall.', \ - 'There are doors leading west, southwest, south and southeast,', \ - 'and a corridor leads east.', \ - 'The hall continues to the north.' \ - ] + 'You are standing at the south side of a very large hall.', \ + 'There are doors leading west, southwest, south and southeast,', \ + 'and a corridor leads east.', \ + 'The hall continues to the north.' \ + ] r_hall_n = Room().init('North of hall') r_hall_n.description = [ \ - 'You are stanting at the north side of a very large hall.', \ - 'There are corridors leading west, northwest, northeast,', \ - 'an elevator door north, and a door leading outside east.', \ - 'There are stairs leading up, and the hall continues to the south.' \ - ] + 'You are stanting at the north side of a very large hall.', \ + 'There are corridors leading west, northwest, northeast,', \ + 'an elevator door north, and a door leading outside east.', \ + 'There are stairs leading up, and the hall continues to the south.' \ + ] r_reception = Room().init('Reception') @@ -349,7 +349,7 @@ r_reception.add(o_lamp) # Create an uninitialized player object. # It is initialized by main(), but must be created here (as global) -# since some Room methods reference it. (Though maybe they shouldn't?) +# since some Room methods reference it. (Though maybe they shouldn't?) player = Player() @@ -357,10 +357,10 @@ player = Player() # Play the game from the beginning. def main(): - x = player.init(r_initial) - try: - player.play() - except (EOFError, KeyboardInterrupt): - pass + x = player.init(r_initial) + try: + player.play() + except (EOFError, KeyboardInterrupt): + pass main() diff --git a/lib/anywin.py b/lib/anywin.py index 6de3605..bb7e865 100644 --- a/lib/anywin.py +++ b/lib/anywin.py @@ -6,9 +6,9 @@ import filewin import path def open(name): - print 'opening', name, '...' - if path.isdir(name): - w = dirwin.open(name) - else: - w = filewin.open(name) - return w + print 'opening', name, '...' + if path.isdir(name): + w = dirwin.open(name) + else: + w = filewin.open(name) + return w diff --git a/lib/auds.py b/lib/auds.py index 53db6aa..549c0a7 100644 --- a/lib/auds.py +++ b/lib/auds.py @@ -4,103 +4,103 @@ RATE = 8192 # Initialize the audio stuff audio.setrate(3) -audio.setoutgain(100) # for speaker +audio.setoutgain(100) # for speaker play = audio.write def samp(n): - savegain = audio.getoutgain() - try: - audio.setoutgain(0) - x = raw_input('Hit Enter to sample ' + `n` + ' seconds: ') - return audio.read(n*RATE) - finally: - audio.setoutgain(savegain) + savegain = audio.getoutgain() + try: + audio.setoutgain(0) + x = raw_input('Hit Enter to sample ' + `n` + ' seconds: ') + return audio.read(n*RATE) + finally: + audio.setoutgain(savegain) def echo(s, delay, gain): - return s[:delay] + audio.add(s[delay:], audio.amplify(s, gain, gain)) + return s[:delay] + audio.add(s[delay:], audio.amplify(s, gain, gain)) def save(s, file): - f = open(file, 'w') - f.write(s) + f = open(file, 'w') + f.write(s) def load(file): - return loadfp(open(file, 'r')) + return loadfp(open(file, 'r')) def loadfp(fp): - s = '' - while 1: - buf = fp.read(16*1024) - if not buf: break - s = s + buf - return s + s = '' + while 1: + buf = fp.read(16*1024) + if not buf: break + s = s + buf + return s def unbias(s): - if not s: return s - a = audio.chr2num(s) - sum = 0 - for i in a: sum = sum + i - bias = (sum + len(a)/2) / len(a) - print 'Bias value:', bias - if bias: - for i in range(len(a)): - a[i] = a[i] - bias - s = audio.num2chr(a) - return s + if not s: return s + a = audio.chr2num(s) + sum = 0 + for i in a: sum = sum + i + bias = (sum + len(a)/2) / len(a) + print 'Bias value:', bias + if bias: + for i in range(len(a)): + a[i] = a[i] - bias + s = audio.num2chr(a) + return s # Stretch by a/b. # Think of this as converting the sampling rate from a samples/sec -# to b samples/sec. Or, if the input is a bytes long, the output +# to b samples/sec. Or, if the input is a bytes long, the output # will be b bytes long. # def stretch(s, a, b): - y = audio.chr2num(s) - m = len(y) - out = [] - n = m * b / a - # i, j will walk through y and out (step 1) - # ib, ja are i*b, j*a and are kept as close together as possible - i, ib = 0, 0 - j, ja = 0, 0 - for j in range(n): - ja = ja+a - while ib < ja: - i = i+1 - ib = ib+b - if i >= m: - break - if ib = ja: - out.append(y[i]) - else: - out.append((y[i]*(ja-(ib-b)) + y[i-1]*(ib-ja)) / b) - return audio.num2chr(out) + y = audio.chr2num(s) + m = len(y) + out = [] + n = m * b / a + # i, j will walk through y and out (step 1) + # ib, ja are i*b, j*a and are kept as close together as possible + i, ib = 0, 0 + j, ja = 0, 0 + for j in range(n): + ja = ja+a + while ib < ja: + i = i+1 + ib = ib+b + if i >= m: + break + if ib = ja: + out.append(y[i]) + else: + out.append((y[i]*(ja-(ib-b)) + y[i-1]*(ib-ja)) / b) + return audio.num2chr(out) def sinus(freq): # return a 1-second sine wave - from math import sin, pi - factor = 2.0*pi*float(freq)/float(RATE) - list = range(RATE) - for i in list: - list[i] = int(sin(float(i) * factor) * 127.0) - return audio.num2chr(list) + from math import sin, pi + factor = 2.0*pi*float(freq)/float(RATE) + list = range(RATE) + for i in list: + list[i] = int(sin(float(i) * factor) * 127.0) + return audio.num2chr(list) def softclip(s): - if '\177' not in s and '\200' not in s: - return s - num = audio.chr2num(s) - extremes = (-128, 127) - for i in range(1, len(num)-1): - if num[i] in extremes: - num[i] = (num[i-1] + num[i+1]) / 2 - return audio.num2chr(num) + if '\177' not in s and '\200' not in s: + return s + num = audio.chr2num(s) + extremes = (-128, 127) + for i in range(1, len(num)-1): + if num[i] in extremes: + num[i] = (num[i-1] + num[i+1]) / 2 + return audio.num2chr(num) def demo(): - gday = load('gday')[1000:6000] - save(gday, 'gday0') - gg = [gday] - for i in range(1, 10): - for g in gg: play(g) - g = stretch(gday, 10, 10-i) - save(g, 'gday' + `i`) - gg.append(g) - while 1: - for g in gg: play(g) + gday = load('gday')[1000:6000] + save(gday, 'gday0') + gg = [gday] + for i in range(1, 10): + for g in gg: play(g) + g = stretch(gday, 10, 10-i) + save(g, 'gday' + `i`) + gg.append(g) + while 1: + for g in gg: play(g) diff --git a/lib/calendar.py b/lib/calendar.py index 97ca86f..49e8e63 100644 --- a/lib/calendar.py +++ b/lib/calendar.py @@ -11,12 +11,12 @@ # - Monday is the first day of the week (numbered 0) # These are really parameters of the 'time' module: -epoch = 1970 # Time began on January 1 of this year (00:00:00 UCT) -day_0 = 3 # The epoch begins on a Thursday (Monday = 0) +epoch = 1970 # Time began on January 1 of this year (00:00:00 UCT) +day_0 = 3 # The epoch begins on a Thursday (Monday = 0) # Return 1 for leap years, 0 for non-leap years def isleap(year): - return year % 4 = 0 and (year % 100 <> 0 or year % 400 = 0) + return year % 4 = 0 and (year % 100 <> 0 or year % 400 = 0) # Constants for months referenced later January = 1 @@ -30,41 +30,41 @@ error = 'calendar error' # Turn seconds since epoch into calendar time def gmtime(secs): - if secs < 0: raise error, 'negative input to gmtime()' - mins, secs = divmod(secs, 60) - hours, mins = divmod(mins, 60) - days, hours = divmod(hours, 24) - wday = (days + day_0) % 7 - year = epoch - # XXX Most of the following loop can be replaced by one division - while 1: - yd = 365 + isleap(year) - if days < yd: break - days = days - yd - year = year + 1 - yday = days - month = January - while 1: - md = mdays[month] + (month = February and isleap(year)) - if days < md: break - days = days - md - month = month + 1 - return year, month, days + 1, hours, mins, secs, yday, wday - # XXX Week number also? + if secs < 0: raise error, 'negative input to gmtime()' + mins, secs = divmod(secs, 60) + hours, mins = divmod(mins, 60) + days, hours = divmod(hours, 24) + wday = (days + day_0) % 7 + year = epoch + # XXX Most of the following loop can be replaced by one division + while 1: + yd = 365 + isleap(year) + if days < yd: break + days = days - yd + year = year + 1 + yday = days + month = January + while 1: + md = mdays[month] + (month = February and isleap(year)) + if days < md: break + days = days - md + month = month + 1 + return year, month, days + 1, hours, mins, secs, yday, wday + # XXX Week number also? # Return number of leap years in range [y1, y2) # Assume y1 <= y2 and no funny (non-leap century) years def leapdays(y1, y2): - return (y2+3)/4 - (y1+3)/4 + return (y2+3)/4 - (y1+3)/4 # Inverse of gmtime(): # Turn UCT calendar time (less yday, wday) into seconds since epoch def mktime(year, month, day, hours, mins, secs): - days = day - 1 - for m in range(January, month): days = days + mdays[m] - if isleap(year) and month > February: days = days+1 - days = days + (year-epoch)*365 + leapdays(epoch, year) - return ((days*24 + hours)*60 + mins)*60 + secs + days = day - 1 + for m in range(January, month): days = days + mdays[m] + if isleap(year) and month > February: days = days+1 + days = days + (year-epoch)*365 + leapdays(epoch, year) + return ((days*24 + hours)*60 + mins)*60 + secs # Full and abbreviated names of weekdays day_name = ('Monday', 'Tuesday', 'Wednesday', 'Thursday') @@ -72,40 +72,40 @@ day_name = day_name + ('Friday', 'Saturday', 'Sunday') day_abbr = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun') # Full and abbreviated of months (1-based arrays!!!) -month_name = ('', 'January', 'February', 'March', 'April') -month_name = month_name + ('May', 'June', 'July', 'August') -month_name = month_name + ('September', 'October', 'November', 'December') -month_abbr = (' ', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun') +month_name = ('', 'January', 'February', 'March', 'April') +month_name = month_name + ('May', 'June', 'July', 'August') +month_name = month_name + ('September', 'October', 'November', 'December') +month_abbr = (' ', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun') month_abbr = month_abbr + ('Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec') # Zero-fill string to two positions (helper for asctime()) def dd(s): - while len(s) < 2: s = '0' + s - return s + while len(s) < 2: s = '0' + s + return s # Blank-fill string to two positions (helper for asctime()) def zd(s): - while len(s) < 2: s = ' ' + s - return s + while len(s) < 2: s = ' ' + s + return s # Turn calendar time as returned by gmtime() into a string # (the yday parameter is for compatibility with gmtime()) def asctime(year, month, day, hours, mins, secs, yday, wday): - s = day_abbr[wday] + ' ' + month_abbr[month] + ' ' + zd(`day`) - s = s + ' ' + dd(`hours`) + ':' + dd(`mins`) + ':' + dd(`secs`) - return s + ' ' + `year` + s = day_abbr[wday] + ' ' + month_abbr[month] + ' ' + zd(`day`) + s = s + ' ' + dd(`hours`) + ':' + dd(`mins`) + ':' + dd(`secs`) + return s + ' ' + `year` # Localization: Minutes West from Greenwich -# timezone = -2*60 # Middle-European time with DST on -timezone = 5*60 # EST (sigh -- THINK time() doesn't return UCT) +# timezone = -2*60 # Middle-European time with DST on +timezone = 5*60 # EST (sigh -- THINK time() doesn't return UCT) # Local time ignores DST issues for now -- adjust 'timezone' to fake it def localtime(secs): - return gmtime(secs - timezone*60) + return gmtime(secs - timezone*60) # UNIX-style ctime (except it doesn't append '\n'!) def ctime(secs): - return asctime(localtime(secs)) + return asctime(localtime(secs)) ###################### # Non-UNIX additions # @@ -115,99 +115,99 @@ def ctime(secs): # Return weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12), day (1-31) def weekday(year, month, day): - secs = mktime(year, month, day, 0, 0, 0) - days = secs / (24*60*60) - return (days + day_0) % 7 + secs = mktime(year, month, day, 0, 0, 0) + days = secs / (24*60*60) + return (days + day_0) % 7 # Return weekday (0-6 ~ Mon-Sun) and number of days (28-31) for year, month def monthrange(year, month): - day1 = weekday(year, month, 1) - ndays = mdays[month] + (month = February and isleap(year)) - return day1, ndays + day1 = weekday(year, month, 1) + ndays = mdays[month] + (month = February and isleap(year)) + return day1, ndays # Return a matrix representing a month's calendar # Each row represents a week; days outside this month are zero def _monthcalendar(year, month): - day1, ndays = monthrange(year, month) - rows = [] - r7 = range(7) - day = 1 - day1 - while day <= ndays: - row = [0, 0, 0, 0, 0, 0, 0] - for i in r7: - if 1 <= day <= ndays: row[i] = day - day = day + 1 - rows.append(row) - return rows + day1, ndays = monthrange(year, month) + rows = [] + r7 = range(7) + day = 1 - day1 + while day <= ndays: + row = [0, 0, 0, 0, 0, 0, 0] + for i in r7: + if 1 <= day <= ndays: row[i] = day + day = day + 1 + rows.append(row) + return rows # Caching interface to _monthcalendar mc_cache = {} def monthcalendar(year, month): - key = `year` + month_abbr[month] - try: - return mc_cache[key] - except RuntimeError: - mc_cache[key] = ret = _monthcalendar(year, month) - return ret + key = `year` + month_abbr[month] + try: + return mc_cache[key] + except RuntimeError: + mc_cache[key] = ret = _monthcalendar(year, month) + return ret # Center a string in a field def center(str, width): - n = width - len(str) - if n < 0: return str - return ' '*(n/2) + str + ' '*(n-n/2) + n = width - len(str) + if n < 0: return str + return ' '*(n/2) + str + ' '*(n-n/2) # XXX The following code knows that print separates items with space! # Print a single week (no newline) def prweek(week, width): - for day in week: - if day = 0: print ' '*width, - else: - if width > 2: print ' '*(width-3), - if day < 10: print '', - print day, + for day in week: + if day = 0: print ' '*width, + else: + if width > 2: print ' '*(width-3), + if day < 10: print '', + print day, # Return a header for a week def weekheader(width): - str = '' - for i in range(7): - if str: str = str + ' ' - str = str + day_abbr[i%7][:width] - return str + str = '' + for i in range(7): + if str: str = str + ' ' + str = str + day_abbr[i%7][:width] + return str # Print a month's calendar def prmonth(year, month): - print weekheader(3) - for week in monthcalendar(year, month): - prweek(week, 3) - print + print weekheader(3) + for week in monthcalendar(year, month): + prweek(week, 3) + print # Spacing between month columns -spacing = ' ' +spacing = ' ' # 3-column formatting for year calendars def format3c(a, b, c): - print center(a, 20), spacing, center(b, 20), spacing, center(c, 20) + print center(a, 20), spacing, center(b, 20), spacing, center(c, 20) # Print a year's calendar def prcal(year): - header = weekheader(2) - format3c('', `year`, '') - for q in range(January, January+12, 3): - print - format3c(month_name[q], month_name[q+1], month_name[q+2]) - format3c(header, header, header) - data = [] - height = 0 - for month in range(q, q+3): - cal = monthcalendar(year, month) - if len(cal) > height: height = len(cal) - data.append(cal) - for i in range(height): - for cal in data: - if i >= len(cal): - print ' '*20, - else: - prweek(cal[i], 2) - print spacing, - print + header = weekheader(2) + format3c('', `year`, '') + for q in range(January, January+12, 3): + print + format3c(month_name[q], month_name[q+1], month_name[q+2]) + format3c(header, header, header) + data = [] + height = 0 + for month in range(q, q+3): + cal = monthcalendar(year, month) + if len(cal) > height: height = len(cal) + data.append(cal) + for i in range(height): + for cal in data: + if i >= len(cal): + print ' '*20, + else: + prweek(cal[i], 2) + print spacing, + print diff --git a/lib/clock.py b/lib/clock.py index ec5301e..572018e 100644 --- a/lib/clock.py +++ b/lib/clock.py @@ -14,7 +14,7 @@ import stdwin from stdwinevents import WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP, \ - WE_TIMER, WE_DRAW, WE_SIZE, WE_CLOSE, WE_ACTIVATE + WE_TIMER, WE_DRAW, WE_SIZE, WE_CLOSE, WE_ACTIVATE import time from math import sin, cos, atan2, pi, sqrt @@ -25,178 +25,178 @@ origin = 0, 0 faraway = 2000, 2000 everywhere = origin, faraway -class struct(): pass # A class to declare featureless objects +class struct(): pass # A class to declare featureless objects -G = struct() # Global variables (most set in setdimensions()) -G.tzdiff = 5*3600 # THINK computes UCT from local time assuming EST! +G = struct() # Global variables (most set in setdimensions()) +G.tzdiff = 5*3600 # THINK computes UCT from local time assuming EST! -A = struct() # Globals used by the alarm -A.set = 1 # True when alarm is set -A.time = 11*60 + 40 # Time when alarm must go off -A.ring = 0 # True when alarm is ringing +A = struct() # Globals used by the alarm +A.set = 1 # True when alarm is set +A.time = 11*60 + 40 # Time when alarm must go off +A.ring = 0 # True when alarm is ringing def main(): - try: - realmain() - except KeyboardInterrupt: - print 'KeyboardInterrupt' - finally: - G.w = 0 + try: + realmain() + except KeyboardInterrupt: + print 'KeyboardInterrupt' + finally: + G.w = 0 def realmain(): - setdimensions(DEFWIDTH, DEFHEIGHT) - stdwin.setdefwinsize(G.farcorner) - G.w = stdwin.open('klok') - settimer() - while 1: - type, window, detail = stdwin.getevent() - if type = WE_DRAW: - drawproc(detail) - elif type = WE_TIMER: - settimer() - drawproc(everywhere) - elif type in mouse_events: - mouseclick(type, detail) - elif type = WE_ACTIVATE: - if A.ring: - # Turn the ringing off - A.ring = 0 - G.w.begindrawing().invert(G.mainarea) - elif type = WE_SIZE: - G.w.change(everywhere) - width, height = G.w.getwinsize() - height = height - stdwin.lineheight() - setdimensions(width, height) - elif type = WE_CLOSE: - break + setdimensions(DEFWIDTH, DEFHEIGHT) + stdwin.setdefwinsize(G.farcorner) + G.w = stdwin.open('klok') + settimer() + while 1: + type, window, detail = stdwin.getevent() + if type = WE_DRAW: + drawproc(detail) + elif type = WE_TIMER: + settimer() + drawproc(everywhere) + elif type in mouse_events: + mouseclick(type, detail) + elif type = WE_ACTIVATE: + if A.ring: + # Turn the ringing off + A.ring = 0 + G.w.begindrawing().invert(G.mainarea) + elif type = WE_SIZE: + G.w.change(everywhere) + width, height = G.w.getwinsize() + height = height - stdwin.lineheight() + setdimensions(width, height) + elif type = WE_CLOSE: + break def setdimensions(width, height): - if width < height: size = width - else: size = height - halfwidth = width/2 - halfheight = height/2 - G.center = halfwidth, halfheight - G.radius = size*45/100 - G.width = width - G.height = height - G.corner = width, height - G.mainarea = origin, G.corner - G.lineheight = stdwin.lineheight() - G.farcorner = width, height + G.lineheight - G.statusarea = (0, height), G.farcorner - G.fullarea = origin, G.farcorner + if width < height: size = width + else: size = height + halfwidth = width/2 + halfheight = height/2 + G.center = halfwidth, halfheight + G.radius = size*45/100 + G.width = width + G.height = height + G.corner = width, height + G.mainarea = origin, G.corner + G.lineheight = stdwin.lineheight() + G.farcorner = width, height + G.lineheight + G.statusarea = (0, height), G.farcorner + G.fullarea = origin, G.farcorner def settimer(): - now = getlocaltime() - G.times = calctime(now) - delay = 61 - now % 60 - G.w.settimer(10 * delay) - minutes = (now/60) % 720 - if A.ring: - # Is it time to stop the alarm ringing? - since = (minutes - A.time + 720) % 720 - if since >= 5: - # Stop it now - A.ring = 0 - else: - # Ring again, once every minute - stdwin.fleep() - elif A.set and minutes = A.time: - # Start the alarm ringing - A.ring = 1 - stdwin.fleep() + now = getlocaltime() + G.times = calctime(now) + delay = 61 - now % 60 + G.w.settimer(10 * delay) + minutes = (now/60) % 720 + if A.ring: + # Is it time to stop the alarm ringing? + since = (minutes - A.time + 720) % 720 + if since >= 5: + # Stop it now + A.ring = 0 + else: + # Ring again, once every minute + stdwin.fleep() + elif A.set and minutes = A.time: + # Start the alarm ringing + A.ring = 1 + stdwin.fleep() def drawproc(area): - hours, minutes, seconds = G.times - d = G.w.begindrawing() - d.cliprect(area) - d.erase(everywhere) - d.circle(G.center, G.radius) - d.line(G.center, calcpoint(hours*30 + minutes/2, 0.6)) - d.line(G.center, calcpoint(minutes*6, 1.0)) - str = dd(hours) + ':' + dd(minutes) - p = (G.width - d.textwidth(str))/2, G.height * 3 / 4 - d.text(p, str) - if A.set: - drawalarm(d) - drawalarmtime(d) - if A.ring: - d.invert(G.mainarea) + hours, minutes, seconds = G.times + d = G.w.begindrawing() + d.cliprect(area) + d.erase(everywhere) + d.circle(G.center, G.radius) + d.line(G.center, calcpoint(hours*30 + minutes/2, 0.6)) + d.line(G.center, calcpoint(minutes*6, 1.0)) + str = dd(hours) + ':' + dd(minutes) + p = (G.width - d.textwidth(str))/2, G.height * 3 / 4 + d.text(p, str) + if A.set: + drawalarm(d) + drawalarmtime(d) + if A.ring: + d.invert(G.mainarea) def mouseclick(type, detail): - d = G.w.begindrawing() - if A.ring: - # First turn the ringing off - A.ring = 0 - d.invert(G.mainarea) - h, v = detail[0] - ch, cv = G.center - x, y = h-ch, cv-v - dist = sqrt(x*x + y*y) / float(G.radius) - if dist > 1.2: - if A.set: - drawalarm(d) - erasealarmtime(d) - A.set = 0 - elif dist < 0.8: - if not A.set: - A.set = 1 - drawalarm(d) - drawalarmtime(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 <> A.time or not A.set: - if A.set: - drawalarm(d) - erasealarmtime(d) - A.set = 1 - A.time = atime - drawalarm(d) - drawalarmtime(d) + d = G.w.begindrawing() + if A.ring: + # First turn the ringing off + A.ring = 0 + d.invert(G.mainarea) + h, v = detail[0] + ch, cv = G.center + x, y = h-ch, cv-v + dist = sqrt(x*x + y*y) / float(G.radius) + if dist > 1.2: + if A.set: + drawalarm(d) + erasealarmtime(d) + A.set = 0 + elif dist < 0.8: + if not A.set: + A.set = 1 + drawalarm(d) + drawalarmtime(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 <> A.time or not A.set: + if A.set: + drawalarm(d) + erasealarmtime(d) + A.set = 1 + A.time = atime + drawalarm(d) + drawalarmtime(d) def drawalarm(d): - p1 = calcpoint(float(A.time)/2.0, 1.02) - p2 = calcpoint(float(A.time)/2.0 - 4.0, 1.1) - p3 = calcpoint(float(A.time)/2.0 + 4.0, 1.1) - d.xorline(p1, p2) - d.xorline(p2, p3) - d.xorline(p3, p1) + p1 = calcpoint(float(A.time)/2.0, 1.02) + p2 = calcpoint(float(A.time)/2.0 - 4.0, 1.1) + p3 = calcpoint(float(A.time)/2.0 + 4.0, 1.1) + d.xorline(p1, p2) + d.xorline(p2, p3) + d.xorline(p3, p1) def erasealarmtime(d): - d.erase(G.statusarea) + d.erase(G.statusarea) def drawalarmtime(d): - # A.time is in the range 0..720 with origin at 12 o'clock - # Convert to hours (0..12) and minutes (12*(0..60)) - hh = A.time/60 - mm = A.time%60 - str = 'Alarm@' + dd(hh) + ':' + dd(mm) - p1 = (G.width - d.textwidth(str))/2, G.height - d.text(p1, str) + # A.time is in the range 0..720 with origin at 12 o'clock + # Convert to hours (0..12) and minutes (12*(0..60)) + hh = A.time/60 + mm = A.time%60 + str = 'Alarm@' + dd(hh) + ':' + dd(mm) + p1 = (G.width - d.textwidth(str))/2, G.height + d.text(p1, str) def calctime(now): - seconds = now % 60 - minutes = (now/60) % 60 - hours = (now/3600) % 12 - return hours, minutes, seconds + seconds = now % 60 + minutes = (now/60) % 60 + hours = (now/3600) % 12 + return hours, minutes, seconds def calcpoint(degrees, size): - alpha = pi/2.0 - float(degrees) * pi/180.0 - x, y = cos(alpha), sin(alpha) - h, v = G.center - r = float(G.radius) - return h + int(x*size*r), v - int(y*size*r) + alpha = pi/2.0 - float(degrees) * pi/180.0 + x, y = cos(alpha), sin(alpha) + h, v = G.center + r = float(G.radius) + return h + int(x*size*r), v - int(y*size*r) def dd(n): - s = `n` - return '0'*(2-len(s)) + s + s = `n` + return '0'*(2-len(s)) + s def getlocaltime(): - return time.time() - G.tzdiff + return time.time() - G.tzdiff #main() diff --git a/lib/cmp.py b/lib/cmp.py index 8dc315e..434caee 100644 --- a/lib/cmp.py +++ b/lib/cmp.py @@ -3,59 +3,59 @@ # Efficiently compare files, boolean outcome only (equal / not equal). # Tricks (used in this order): -# - Files with identical type, size & mtime are assumed to be clones -# - Files with different type or size cannot be identical -# - We keep a cache of outcomes of earlier comparisons -# - We don't fork a process to run 'cmp' but read the files ourselves +# - Files with identical type, size & mtime are assumed to be clones +# - Files with different type or size cannot be identical +# - We keep a cache of outcomes of earlier comparisons +# - We don't fork a process to run 'cmp' but read the files ourselves import posix cache = {} def cmp(f1, f2): # Compare two files, use the cache if possible. - # Return 1 for identical files, 0 for different. - # Raise exceptions if either file could not be statted, read, etc. - s1, s2 = sig(posix.stat(f1)), sig(posix.stat(f2)) - if s1[0] <> 8 or s2[0] <> 8: - # Either is a not a plain file -- always report as different - return 0 - if s1 = s2: - # type, size & mtime match -- report same - return 1 - if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother - # types or sizes differ -- report different - return 0 - # same type and size -- look in the cache - key = f1 + ' ' + f2 - try: - cs1, cs2, outcome = cache[key] - # cache hit - if s1 = cs1 and s2 = cs2: - # cached signatures match - return outcome - # stale cached signature(s) - except RuntimeError: - # cache miss - pass - # really compare - outcome = do_cmp(f1, f2) - cache[key] = s1, s2, outcome - return outcome + # Return 1 for identical files, 0 for different. + # Raise exceptions if either file could not be statted, read, etc. + s1, s2 = sig(posix.stat(f1)), sig(posix.stat(f2)) + if s1[0] <> 8 or s2[0] <> 8: + # Either is a not a plain file -- always report as different + return 0 + if s1 = s2: + # type, size & mtime match -- report same + return 1 + if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother + # types or sizes differ -- report different + return 0 + # same type and size -- look in the cache + key = f1 + ' ' + f2 + try: + cs1, cs2, outcome = cache[key] + # cache hit + if s1 = cs1 and s2 = cs2: + # cached signatures match + return outcome + # stale cached signature(s) + except RuntimeError: + # cache miss + pass + # really compare + outcome = do_cmp(f1, f2) + cache[key] = s1, s2, outcome + return outcome def sig(st): # Return signature (i.e., type, size, mtime) from raw stat data - # 0-5: st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid - # 6-9: st_size, st_atime, st_mtime, st_ctime - type = st[0] / 4096 - size = st[6] - mtime = st[8] - return type, size, mtime + # 0-5: st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid + # 6-9: st_size, st_atime, st_mtime, st_ctime + type = st[0] / 4096 + size = st[6] + mtime = st[8] + return type, size, mtime def do_cmp(f1, f2): # Compare two files, really - bufsize = 8096 # Could be tuned - fp1 = open(f1, 'r') - fp2 = open(f2, 'r') - while 1: - b1 = fp1.read(bufsize) - b2 = fp2.read(bufsize) - if b1 <> b2: return 0 - if not b1: return 1 + bufsize = 8096 # Could be tuned + fp1 = open(f1, 'r') + fp2 = open(f2, 'r') + while 1: + b1 = fp1.read(bufsize) + b2 = fp2.read(bufsize) + if b1 <> b2: return 0 + if not b1: return 1 diff --git a/lib/cmpcache.py b/lib/cmpcache.py index 4aea356..e846f58 100644 --- a/lib/cmpcache.py +++ b/lib/cmpcache.py @@ -3,11 +3,11 @@ # Efficiently compare files, boolean outcome only (equal / not equal). # # Tricks (used in this order): -# - Use the statcache module to avoid statting files more than once -# - Files with identical type, size & mtime are assumed to be clones -# - Files with different type or size cannot be identical -# - We keep a cache of outcomes of earlier comparisons -# - We don't fork a process to run 'cmp' but read the files ourselves +# - Use the statcache module to avoid statting files more than once +# - Files with identical type, size & mtime are assumed to be clones +# - Files with different type or size cannot be identical +# - We keep a cache of outcomes of earlier comparisons +# - We don't fork a process to run 'cmp' but read the files ourselves import posix from stat import * @@ -23,46 +23,46 @@ cache = {} # May raise posix.error if a stat or open of either fails. # def cmp(f1, f2): - # Return 1 for identical files, 0 for different. - # Raise exceptions if either file could not be statted, read, etc. - s1, s2 = sig(statcache.stat(f1)), sig(statcache.stat(f2)) - if not S_ISREG(s1[0]) or not S_ISREG(s2[0]): - # Either is a not a plain file -- always report as different - return 0 - if s1 = s2: - # type, size & mtime match -- report same - return 1 - if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother - # types or sizes differ -- report different - return 0 - # same type and size -- look in the cache - key = f1 + ' ' + f2 - if cache.has_key(key): - cs1, cs2, outcome = cache[key] - # cache hit - if s1 = cs1 and s2 = cs2: - # cached signatures match - return outcome - # stale cached signature(s) - # really compare - outcome = do_cmp(f1, f2) - cache[key] = s1, s2, outcome - return outcome + # Return 1 for identical files, 0 for different. + # Raise exceptions if either file could not be statted, read, etc. + s1, s2 = sig(statcache.stat(f1)), sig(statcache.stat(f2)) + if not S_ISREG(s1[0]) or not S_ISREG(s2[0]): + # Either is a not a plain file -- always report as different + return 0 + if s1 = s2: + # type, size & mtime match -- report same + return 1 + if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother + # types or sizes differ -- report different + return 0 + # same type and size -- look in the cache + key = f1 + ' ' + f2 + if cache.has_key(key): + cs1, cs2, outcome = cache[key] + # cache hit + if s1 = cs1 and s2 = cs2: + # cached signatures match + return outcome + # stale cached signature(s) + # really compare + outcome = do_cmp(f1, f2) + cache[key] = s1, s2, outcome + return outcome # Return signature (i.e., type, size, mtime) from raw stat data. # def sig(st): - return S_IFMT(st[ST_MODE]), st[ST_SIZE], st[ST_MTIME] + return S_IFMT(st[ST_MODE]), st[ST_SIZE], st[ST_MTIME] # Compare two files, really. # def do_cmp(f1, f2): - #print ' cmp', f1, f2 # XXX remove when debugged - bufsize = 8096 # Could be tuned - fp1 = open(f1, 'r') - fp2 = open(f2, 'r') - while 1: - b1 = fp1.read(bufsize) - b2 = fp2.read(bufsize) - if b1 <> b2: return 0 - if not b1: return 1 + #print ' cmp', f1, f2 # XXX remove when debugged + bufsize = 8096 # Could be tuned + fp1 = open(f1, 'r') + fp2 = open(f2, 'r') + while 1: + b1 = fp1.read(bufsize) + b2 = fp2.read(bufsize) + if b1 <> b2: return 0 + if not b1: return 1 diff --git a/lib/commands.py b/lib/commands.py index 3cb6e69..dc46740 100644 --- a/lib/commands.py +++ b/lib/commands.py @@ -11,7 +11,7 @@ import path # Get 'ls -l' status for an object into a string # def getstatus(file): - return getoutput('ls -ld' + mkarg(file)) + return getoutput('ls -ld' + mkarg(file)) # Get the output from a shell command into a string. @@ -20,44 +20,44 @@ def getstatus(file): # XXX This should use posix.popen() instead, should it exist. # def getoutput(cmd): - return getstatusoutput(cmd)[1] + return getstatusoutput(cmd)[1] # Ditto but preserving the exit status. # Returns a pair (sts, output) # def getstatusoutput(cmd): - tmp = '/usr/tmp/wdiff' + `rand.rand()` - sts = -1 - try: - sts = posix.system(cmd + ' >' + tmp + ' 2>&1') - text = readfile(tmp) - finally: - altsts = posix.system('rm -f ' + tmp) - if text[-1:] = '\n': text = text[:-1] - return sts, text + tmp = '/usr/tmp/wdiff' + `rand.rand()` + sts = -1 + try: + sts = posix.system(cmd + ' >' + tmp + ' 2>&1') + text = readfile(tmp) + finally: + altsts = posix.system('rm -f ' + tmp) + if text[-1:] = '\n': text = text[:-1] + return sts, text # Return a string containing a file's contents. # def readfile(fn): - st = posix.stat(fn) - size = st[stat.ST_SIZE] - if not size: return '' - try: - fp = open(fn, 'r') - except: - raise posix.error, 'readfile(' + fn + '): open failed' - try: - return fp.read(size) - except: - raise posix.error, 'readfile(' + fn + '): read failed' + st = posix.stat(fn) + size = st[stat.ST_SIZE] + if not size: return '' + try: + fp = open(fn, 'r') + except: + raise posix.error, 'readfile(' + fn + '): open failed' + try: + return fp.read(size) + except: + raise posix.error, 'readfile(' + fn + '): read failed' # Make command argument from directory and pathname (prefix space, add quotes). # def mk2arg(head, x): - return mkarg(path.cat(head, x)) + return mkarg(path.cat(head, x)) # Make a shell command argument from a string. @@ -66,12 +66,12 @@ def mk2arg(head, x): # with backslash. # def mkarg(x): - if '\'' not in x: - return ' \'' + x + '\'' - s = ' "' - for c in x: - if c in '\\$"': - s = s + '\\' - s = s + c - s = s + '"' - return s + if '\'' not in x: + return ' \'' + x + '\'' + s = ' "' + for c in x: + if c in '\\$"': + s = s + '\\' + s = s + c + s = s + '"' + return s diff --git a/lib/dircache.py b/lib/dircache.py index c14db3e..b40f76e 100644 --- a/lib/dircache.py +++ b/lib/dircache.py @@ -10,27 +10,27 @@ import path cache = {} def listdir(path): # List directory contents, using cache - try: - cached_mtime, list = cache[path] - del cache[path] - except RuntimeError: - cached_mtime, list = -1, [] - try: - mtime = posix.stat(path)[8] - except posix.error: - return [] - if mtime <> cached_mtime: - try: - list = posix.listdir(path) - except posix.error: - return [] - list.sort() - cache[path] = mtime, list - return list + try: + cached_mtime, list = cache[path] + del cache[path] + except RuntimeError: + cached_mtime, list = -1, [] + try: + mtime = posix.stat(path)[8] + except posix.error: + return [] + if mtime <> cached_mtime: + try: + list = posix.listdir(path) + except posix.error: + return [] + list.sort() + cache[path] = mtime, list + return list opendir = listdir # XXX backward compatibility def annotate(head, list): # Add '/' suffixes to directories - for i in range(len(list)): - if path.isdir(path.cat(head, list[i])): - list[i] = list[i] + '/' + for i in range(len(list)): + if path.isdir(path.cat(head, list[i])): + list[i] = list[i] + '/' diff --git a/lib/dircmp.py b/lib/dircmp.py index 31e712c..819f0bd 100644 --- a/lib/dircmp.py +++ b/lib/dircmp.py @@ -14,192 +14,192 @@ from stat import * # Directory comparison class. # class dircmp(): - # - def new(dd, (a, b)): # Initialize - dd.a = a - dd.b = b - # Properties that caller may change before callingdd. run(): - dd.hide = ['.', '..'] # Names never to be shown - dd.ignore = ['RCS', 'tags'] # Names ignored in comparison - # - return dd - # - def run(dd): # Compare everything except common subdirectories - dd.a_list = filter(dircache.listdir(dd.a), dd.hide) - dd.b_list = filter(dircache.listdir(dd.b), dd.hide) - dd.a_list.sort() - dd.b_list.sort() - dd.phase1() - dd.phase2() - dd.phase3() - # - def phase1(dd): # Compute common names - dd.a_only = [] - dd.common = [] - for x in dd.a_list: - if x in dd.b_list: - dd.common.append(x) - else: - dd.a_only.append(x) - # - dd.b_only = [] - for x in dd.b_list: - if x not in dd.common: - dd.b_only.append(x) - # - def phase2(dd): # Distinguish files, directories, funnies - dd.common_dirs = [] - dd.common_files = [] - dd.common_funny = [] - # - for x in dd.common: - a_path = path.cat(dd.a, x) - b_path = path.cat(dd.b, x) - # - ok = 1 - try: - a_stat = statcache.stat(a_path) - except posix.error, why: - # print 'Can\'t stat', a_path, ':', why[1] - ok = 0 - try: - b_stat = statcache.stat(b_path) - except posix.error, why: - # print 'Can\'t stat', b_path, ':', why[1] - ok = 0 - # - if ok: - a_type = S_IFMT(a_stat[ST_MODE]) - b_type = S_IFMT(b_stat[ST_MODE]) - if a_type <> b_type: - dd.common_funny.append(x) - elif S_ISDIR(a_type): - dd.common_dirs.append(x) - elif S_ISREG(a_type): - dd.common_files.append(x) - else: - dd.common_funny.append(x) - else: - dd.common_funny.append(x) - # - def phase3(dd): # Find out differences between common files - xx = cmpfiles(dd.a, dd.b, dd.common_files) - dd.same_files, dd.diff_files, dd.funny_files = xx - # - def phase4(dd): # Find out differences between common subdirectories - # A new dircmp object is created for each common subdirectory, - # these are stored in a dictionary indexed by filename. - # The hide and ignore properties are inherited from the parent - dd.subdirs = {} - for x in dd.common_dirs: - a_x = path.cat(dd.a, x) - b_x = path.cat(dd.b, x) - dd.subdirs[x] = newdd = dircmp().new(a_x, b_x) - newdd.hide = dd.hide - newdd.ignore = dd.ignore - newdd.run() - # - def phase4_closure(dd): # Recursively call phase4() on subdirectories - dd.phase4() - for x in dd.subdirs.keys(): - dd.subdirs[x].phase4_closure() - # - def report(dd): # Print a report on the differences between a and b - # Assume that phases 1 to 3 have been executed - # Output format is purposely lousy - print 'diff', dd.a, dd.b - if dd.a_only: - print 'Only in', dd.a, ':', dd.a_only - if dd.b_only: - print 'Only in', dd.b, ':', dd.b_only - if dd.same_files: - print 'Identical files :', dd.same_files - if dd.diff_files: - print 'Differing files :', dd.diff_files - if dd.funny_files: - print 'Trouble with common files :', dd.funny_files - if dd.common_dirs: - print 'Common subdirectories :', dd.common_dirs - if dd.common_funny: - print 'Common funny cases :', dd.common_funny - # - def report_closure(dd): # Print reports on dd and on subdirs - # If phase 4 hasn't been done, no subdir reports are printed - dd.report() - try: - x = dd.subdirs - except NameError: - return # No subdirectories computed - for x in dd.subdirs.keys(): - print - dd.subdirs[x].report_closure() - # - def report_phase4_closure(dd): # Report and do phase 4 recursively - dd.report() - dd.phase4() - for x in dd.subdirs.keys(): - print - dd.subdirs[x].report_phase4_closure() + # + def new(dd, (a, b)): # Initialize + dd.a = a + dd.b = b + # Properties that caller may change before callingdd. run(): + dd.hide = ['.', '..'] # Names never to be shown + dd.ignore = ['RCS', 'tags'] # Names ignored in comparison + # + return dd + # + def run(dd): # Compare everything except common subdirectories + dd.a_list = filter(dircache.listdir(dd.a), dd.hide) + dd.b_list = filter(dircache.listdir(dd.b), dd.hide) + dd.a_list.sort() + dd.b_list.sort() + dd.phase1() + dd.phase2() + dd.phase3() + # + def phase1(dd): # Compute common names + dd.a_only = [] + dd.common = [] + for x in dd.a_list: + if x in dd.b_list: + dd.common.append(x) + else: + dd.a_only.append(x) + # + dd.b_only = [] + for x in dd.b_list: + if x not in dd.common: + dd.b_only.append(x) + # + def phase2(dd): # Distinguish files, directories, funnies + dd.common_dirs = [] + dd.common_files = [] + dd.common_funny = [] + # + for x in dd.common: + a_path = path.cat(dd.a, x) + b_path = path.cat(dd.b, x) + # + ok = 1 + try: + a_stat = statcache.stat(a_path) + except posix.error, why: + # print 'Can\'t stat', a_path, ':', why[1] + ok = 0 + try: + b_stat = statcache.stat(b_path) + except posix.error, why: + # print 'Can\'t stat', b_path, ':', why[1] + ok = 0 + # + if ok: + a_type = S_IFMT(a_stat[ST_MODE]) + b_type = S_IFMT(b_stat[ST_MODE]) + if a_type <> b_type: + dd.common_funny.append(x) + elif S_ISDIR(a_type): + dd.common_dirs.append(x) + elif S_ISREG(a_type): + dd.common_files.append(x) + else: + dd.common_funny.append(x) + else: + dd.common_funny.append(x) + # + def phase3(dd): # Find out differences between common files + xx = cmpfiles(dd.a, dd.b, dd.common_files) + dd.same_files, dd.diff_files, dd.funny_files = xx + # + def phase4(dd): # Find out differences between common subdirectories + # A new dircmp object is created for each common subdirectory, + # these are stored in a dictionary indexed by filename. + # The hide and ignore properties are inherited from the parent + dd.subdirs = {} + for x in dd.common_dirs: + a_x = path.cat(dd.a, x) + b_x = path.cat(dd.b, x) + dd.subdirs[x] = newdd = dircmp().new(a_x, b_x) + newdd.hide = dd.hide + newdd.ignore = dd.ignore + newdd.run() + # + def phase4_closure(dd): # Recursively call phase4() on subdirectories + dd.phase4() + for x in dd.subdirs.keys(): + dd.subdirs[x].phase4_closure() + # + def report(dd): # Print a report on the differences between a and b + # Assume that phases 1 to 3 have been executed + # Output format is purposely lousy + print 'diff', dd.a, dd.b + if dd.a_only: + print 'Only in', dd.a, ':', dd.a_only + if dd.b_only: + print 'Only in', dd.b, ':', dd.b_only + if dd.same_files: + print 'Identical files :', dd.same_files + if dd.diff_files: + print 'Differing files :', dd.diff_files + if dd.funny_files: + print 'Trouble with common files :', dd.funny_files + if dd.common_dirs: + print 'Common subdirectories :', dd.common_dirs + if dd.common_funny: + print 'Common funny cases :', dd.common_funny + # + def report_closure(dd): # Print reports on dd and on subdirs + # If phase 4 hasn't been done, no subdir reports are printed + dd.report() + try: + x = dd.subdirs + except NameError: + return # No subdirectories computed + for x in dd.subdirs.keys(): + print + dd.subdirs[x].report_closure() + # + def report_phase4_closure(dd): # Report and do phase 4 recursively + dd.report() + dd.phase4() + for x in dd.subdirs.keys(): + print + dd.subdirs[x].report_phase4_closure() # Compare common files in two directories. # Return: -# - files that compare equal -# - files that compare different -# - funny cases (can't stat etc.) +# - files that compare equal +# - files that compare different +# - funny cases (can't stat etc.) # def cmpfiles(a, b, common): - res = ([], [], []) - for x in common: - res[cmp(path.cat(a, x), path.cat(b, x))].append(x) - return res + res = ([], [], []) + for x in common: + res[cmp(path.cat(a, x), path.cat(b, x))].append(x) + return res # Compare two files. # Return: -# 0 for equal -# 1 for different -# 2 for funny cases (can't stat, etc.) +# 0 for equal +# 1 for different +# 2 for funny cases (can't stat, etc.) # def cmp(a, b): - try: - if cmpcache.cmp(a, b): return 0 - return 1 - except posix.error: - return 2 + try: + if cmpcache.cmp(a, b): return 0 + return 1 + except posix.error: + return 2 # Remove a list item. # NB: This modifies the list argument. # def remove(list, item): - for i in range(len(list)): - if list[i] = item: - del list[i] - break + for i in range(len(list)): + if list[i] = item: + del list[i] + break # Return a copy with items that occur in skip removed. # def filter(list, skip): - result = [] - for item in list: - if item not in skip: result.append(item) - return result + result = [] + for item in list: + if item not in skip: result.append(item) + return result # Demonstration and testing. # def demo(): - import sys - import getopt - options, args = getopt.getopt(sys.argv[1:], 'r') - if len(args) <> 2: raise getopt.error, 'need exactly two args' - dd = dircmp().new(args[0], args[1]) - dd.run() - if ('-r', '') in options: - dd.report_phase4_closure() - else: - dd.report() + import sys + import getopt + options, args = getopt.getopt(sys.argv[1:], 'r') + if len(args) <> 2: raise getopt.error, 'need exactly two args' + dd = dircmp().new(args[0], args[1]) + dd.run() + if ('-r', '') in options: + dd.report_phase4_closure() + else: + dd.report() # demo() diff --git a/lib/dirwin.py b/lib/dirwin.py index 76e0b5e..0b3b5db 100644 --- a/lib/dirwin.py +++ b/lib/dirwin.py @@ -9,21 +9,21 @@ import path import dircache def action(w, string, i, detail): - (h, v), clicks, button, mask = detail - if clicks = 2: - name = path.cat(w.name, string) - try: - w2 = anywin.open(name) - w2.parent = w - except posix.error, why: - stdwin.message('Can\'t open ' + name + ': ' + why[1]) + (h, v), clicks, button, mask = detail + if clicks = 2: + name = path.cat(w.name, string) + try: + w2 = anywin.open(name) + w2.parent = w + except posix.error, why: + stdwin.message('Can\'t open ' + name + ': ' + why[1]) def open(name): - name = path.cat(name, '') - list = dircache.opendir(name)[:] - list.sort() - dircache.annotate(name, list) - w = listwin.open(name, list) - w.name = name - w.action = action - return w + name = path.cat(name, '') + list = dircache.opendir(name)[:] + list.sort() + dircache.annotate(name, list) + w = listwin.open(name, list) + w.name = name + w.action = action + return w diff --git a/lib/dis.py b/lib/dis.py index d13b08f..fe57fb9 100644 --- a/lib/dis.py +++ b/lib/dis.py @@ -4,64 +4,64 @@ import sys import string def dis(): - tb = sys.last_traceback - while tb.tb_next: tb = tb.tb_next - distb(tb) + tb = sys.last_traceback + while tb.tb_next: tb = tb.tb_next + distb(tb) def distb(tb): - disassemble(tb.tb_frame.f_code, tb.tb_lasti) + disassemble(tb.tb_frame.f_code, tb.tb_lasti) def disco(co): - disassemble(co, -1) + disassemble(co, -1) def disassemble(co, lasti): - code = co.co_code - labels = findlabels(code) - n = len(code) - i = 0 - while i < n: - c = code[i] - op = ord(c) - if op = SET_LINENO and i > 0: print # Extra blank line - if i = lasti: print '-->', - else: print ' ', - if i in labels: print '>>', - else: print ' ', - print string.rjust(`i`, 4), - print string.ljust(opname[op], 15), - i = i+1 - if op >= HAVE_ARGUMENT: - oparg = ord(code[i]) + ord(code[i+1])*256 - i = i+2 - print string.rjust(`oparg`, 5), - if op in hasconst: - print '(' + `co.co_consts[oparg]` + ')', - elif op in hasname: - print '(' + co.co_names[oparg] + ')', - elif op in hasjrel: - print '(to ' + `i + oparg` + ')', - print + code = co.co_code + labels = findlabels(code) + n = len(code) + i = 0 + while i < n: + c = code[i] + op = ord(c) + if op = SET_LINENO and i > 0: print # Extra blank line + if i = lasti: print '-->', + else: print ' ', + if i in labels: print '>>', + else: print ' ', + print string.rjust(`i`, 4), + print string.ljust(opname[op], 15), + i = i+1 + if op >= HAVE_ARGUMENT: + oparg = ord(code[i]) + ord(code[i+1])*256 + i = i+2 + print string.rjust(`oparg`, 5), + if op in hasconst: + print '(' + `co.co_consts[oparg]` + ')', + elif op in hasname: + print '(' + co.co_names[oparg] + ')', + elif op in hasjrel: + print '(to ' + `i + oparg` + ')', + print def findlabels(code): - labels = [] - n = len(code) - i = 0 - while i < n: - c = code[i] - op = ord(c) - i = i+1 - if op >= HAVE_ARGUMENT: - oparg = ord(code[i]) + ord(code[i+1])*256 - i = i+2 - label = -1 - if op in hasjrel: - label = i+oparg - elif op in hasjabs: - label = oparg - if label >= 0: - if label not in labels: - labels.append(label) - return labels + labels = [] + n = len(code) + i = 0 + while i < n: + c = code[i] + op = ord(c) + i = i+1 + if op >= HAVE_ARGUMENT: + oparg = ord(code[i]) + ord(code[i+1])*256 + i = i+2 + label = -1 + if op in hasjrel: + label = i+oparg + elif op in hasjabs: + label = oparg + if label >= 0: + if label not in labels: + labels.append(label) + return labels hasconst = [] hasname = [] @@ -72,19 +72,19 @@ opname = range(256) for op in opname: opname[op] = '<' + `op` + '>' def def_op(name, op): - opname[op] = name + opname[op] = name def name_op(name, op): - opname[op] = name - hasname.append(op) + opname[op] = name + hasname.append(op) def jrel_op(name, op): - opname[op] = name - hasjrel.append(op) + opname[op] = name + hasjrel.append(op) def jabs_op(name, op): - opname[op] = name - hasjabs.append(op) + opname[op] = name + hasjabs.append(op) # Instruction opcodes for compiled code @@ -141,36 +141,36 @@ def_op('POP_BLOCK', 87) def_op('END_FINALLY', 88) def_op('BUILD_CLASS', 89) -HAVE_ARGUMENT = 90 # Opcodes from here have an argument: +HAVE_ARGUMENT = 90 # Opcodes from here have an argument: -name_op('STORE_NAME', 90) # Index in name list -name_op('DELETE_NAME', 91) # "" -def_op('UNPACK_TUPLE', 92) # Number of tuple items -def_op('UNPACK_LIST', 93) # Number of list items -# unused: 94 -name_op('STORE_ATTR', 95) # Index in name list -name_op('DELETE_ATTR', 96) # "" +name_op('STORE_NAME', 90) # Index in name list +name_op('DELETE_NAME', 91) # "" +def_op('UNPACK_TUPLE', 92) # Number of tuple items +def_op('UNPACK_LIST', 93) # Number of list items +# unused: 94 +name_op('STORE_ATTR', 95) # Index in name list +name_op('DELETE_ATTR', 96) # "" -def_op('LOAD_CONST', 100) # Index in const list +def_op('LOAD_CONST', 100) # Index in const list hasconst.append(100) -name_op('LOAD_NAME', 101) # Index in name list -def_op('BUILD_TUPLE', 102) # Number of tuple items -def_op('BUILD_LIST', 103) # Number of list items -def_op('BUILD_MAP', 104) # Always zero for now -name_op('LOAD_ATTR', 105) # Index in name list -def_op('COMPARE_OP', 106) # Comparison operator -name_op('IMPORT_NAME', 107) # Index in name list -name_op('IMPORT_FROM', 108) # Index in name list - -jrel_op('JUMP_FORWARD', 110) # Number of bytes to skip -jrel_op('JUMP_IF_FALSE', 111) # "" -jrel_op('JUMP_IF_TRUE', 112) # "" -jabs_op('JUMP_ABSOLUTE', 113) # Target byte offset from beginning of code -jrel_op('FOR_LOOP', 114) # Number of bytes to skip - -jrel_op('SETUP_LOOP', 120) # Distance to target address -jrel_op('SETUP_EXCEPT', 121) # "" -jrel_op('SETUP_FINALLY', 122) # "" - -def_op('SET_LINENO', 127) # Current line number +name_op('LOAD_NAME', 101) # Index in name list +def_op('BUILD_TUPLE', 102) # Number of tuple items +def_op('BUILD_LIST', 103) # Number of list items +def_op('BUILD_MAP', 104) # Always zero for now +name_op('LOAD_ATTR', 105) # Index in name list +def_op('COMPARE_OP', 106) # Comparison operator +name_op('IMPORT_NAME', 107) # Index in name list +name_op('IMPORT_FROM', 108) # Index in name list + +jrel_op('JUMP_FORWARD', 110) # Number of bytes to skip +jrel_op('JUMP_IF_FALSE', 111) # "" +jrel_op('JUMP_IF_TRUE', 112) # "" +jabs_op('JUMP_ABSOLUTE', 113) # Target byte offset from beginning of code +jrel_op('FOR_LOOP', 114) # Number of bytes to skip + +jrel_op('SETUP_LOOP', 120) # Distance to target address +jrel_op('SETUP_EXCEPT', 121) # "" +jrel_op('SETUP_FINALLY', 122) # "" + +def_op('SET_LINENO', 127) # Current line number SET_LINENO = 127 diff --git a/lib/dump.py b/lib/dump.py index 0510092..cecc275 100644 --- a/lib/dump.py +++ b/lib/dump.py @@ -23,41 +23,41 @@ # Dump a whole symbol table # def dumpsymtab(dict): - for key in dict.keys(): - dumpvar(key, dict[key]) + for key in dict.keys(): + dumpvar(key, dict[key]) # Dump a single variable # def dumpvar(name, x): - import sys - t = type(x) - if t = type({}): - print name, '= {}' - for key in x.keys(): - item = x[key] - if not printable(item): - print '#', - print name, '[', `key`, '] =', `item` - elif t in (type(''), type(0), type(0.0), type([]), type(())): - if not printable(x): - print '#', - print name, '=', `x` - elif t = type(sys): - print 'import', name, '#', x - else: - print '#', name, '=', x + import sys + t = type(x) + if t = type({}): + print name, '= {}' + for key in x.keys(): + item = x[key] + if not printable(item): + print '#', + print name, '[', `key`, '] =', `item` + elif t in (type(''), type(0), type(0.0), type([]), type(())): + if not printable(x): + print '#', + print name, '=', `x` + elif t = type(sys): + print 'import', name, '#', x + else: + print '#', name, '=', x # check if a value is printable in a way that can be read back with input() # def printable(x): - t = type(x) - if t in (type(''), type(0), type(0.0)): - return 1 - if t in (type([]), type(())): - for item in x: - if not printable(item): - return 0 - return 1 - if x = {}: - return 1 - return 0 + t = type(x) + if t in (type(''), type(0), type(0.0)): + return 1 + if t in (type([]), type(())): + for item in x: + if not printable(item): + return 0 + return 1 + if x = {}: + return 1 + return 0 diff --git a/lib/fact.py b/lib/fact.py index ba961c4..2beb0cb 100644 --- a/lib/fact.py +++ b/lib/fact.py @@ -3,35 +3,35 @@ import sys import math -error = 'fact.error' # exception +error = 'fact.error' # exception def fact(n): - if n < 1: raise error # fact() argument should be >= 1 - if n = 1: return [] # special case - res = [] - _fact(n, 2, res) - return res + if n < 1: raise error # fact() argument should be >= 1 + if n = 1: return [] # special case + res = [] + _fact(n, 2, res) + return res def _fact(n, lowest, res): - highest = int(math.sqrt(float(n+1))) - for i in range(lowest, highest+1): - if n%i = 0: - res.append(i) - _fact(n/i, i, res) - break - else: - res.append(n) + highest = int(math.sqrt(float(n+1))) + for i in range(lowest, highest+1): + if n%i = 0: + res.append(i) + _fact(n/i, i, res) + break + else: + res.append(n) def main(): - if len(sys.argv) > 1: - for arg in sys.argv[1:]: - n = eval(arg) - print n, fact(n) - else: - try: - while 1: - print fact(input()) - except EOFError: - pass + if len(sys.argv) > 1: + for arg in sys.argv[1:]: + n = eval(arg) + print n, fact(n) + else: + try: + while 1: + print fact(input()) + except EOFError: + pass main() diff --git a/lib/filewin.py b/lib/filewin.py index ad35ea4..6a224e7 100644 --- a/lib/filewin.py +++ b/lib/filewin.py @@ -8,11 +8,11 @@ from util import readfile # FILE WINDOW def open_readonly(fn): # Open a file window - w = textwin.open_readonly(fn, readfile(fn)) - w.fn = fn - return w + w = textwin.open_readonly(fn, readfile(fn)) + w.fn = fn + return w def open(fn): # Open a file window - w = textwin.open(fn, readfile(fn)) - w.fn = fn - return w + w = textwin.open(fn, readfile(fn)) + w.fn = fn + return w diff --git a/lib/fnmatch.py b/lib/fnmatch.py index 8f9e318..c7caef6 100644 --- a/lib/fnmatch.py +++ b/lib/fnmatch.py @@ -3,33 +3,33 @@ # XXX [] patterns are not supported (but recognized) def fnmatch(name, pat): - if '*' in pat or '?' in pat or '[' in pat: - return fnmatch1(name, pat) - return name = pat + if '*' in pat or '?' in pat or '[' in pat: + return fnmatch1(name, pat) + return name = pat def fnmatch1(name, pat): - for i in range(len(pat)): - c = pat[i] - if c = '*': - restpat = pat[i+1:] - if '*' in restpat or '?' in restpat or '[' in restpat: - for i in range(i, len(name)): - if fnmatch1(name[i:], restpat): - return 1 - return 0 - else: - return name[len(name)-len(restpat):] = restpat - elif c = '?': - if len(name) <= i : return 0 - elif c = '[': - return 0 # XXX - else: - if name[i:i+1] <> c: - return 0 - return 1 + for i in range(len(pat)): + c = pat[i] + if c = '*': + restpat = pat[i+1:] + if '*' in restpat or '?' in restpat or '[' in restpat: + for i in range(i, len(name)): + if fnmatch1(name[i:], restpat): + return 1 + return 0 + else: + return name[len(name)-len(restpat):] = restpat + elif c = '?': + if len(name) <= i : return 0 + elif c = '[': + return 0 # XXX + else: + if name[i:i+1] <> c: + return 0 + return 1 def fnmatchlist(names, pat): - res = [] - for name in names: - if fnmatch(name, pat): res.append(name) - return res + res = [] + for name in names: + if fnmatch(name, pat): res.append(name) + return res diff --git a/lib/getopt.py b/lib/getopt.py index f343c22..ef72fbc 100644 --- a/lib/getopt.py +++ b/lib/getopt.py @@ -12,36 +12,36 @@ # detects an error. # It returns two items: -# (1) a list of pairs (option, option_argument) giving the options in -# the order in which they were specified. (I'd use a dictionary -# but applications may depend on option order or multiple -# occurrences.) Boolean options have '' as option_argument. -# (2) the list of remaining arguments (may be empty). +# (1) a list of pairs (option, option_argument) giving the options in +# the order in which they were specified. (I'd use a dictionary +# but applications may depend on option order or multiple +# occurrences.) Boolean options have '' as option_argument. +# (2) the list of remaining arguments (may be empty). error = 'getopt error' def getopt(args, options): - list = [] - while args and args[0][0] = '-' and args[0] <> '-': - if args[0] = '--': - args = args[1:] - break - optstring, args = args[0][1:], args[1:] - while optstring <> '': - opt, optstring = optstring[0], optstring[1:] - if classify(opt, options): # May raise exception as well - if optstring = '': - if not args: - raise error, 'option -' + opt + ' requires argument' - optstring, args = args[0], args[1:] - optarg, optstring = optstring, '' - else: - optarg = '' - list.append('-' + opt, optarg) - return list, args + list = [] + while args and args[0][0] = '-' and args[0] <> '-': + if args[0] = '--': + args = args[1:] + break + optstring, args = args[0][1:], args[1:] + while optstring <> '': + opt, optstring = optstring[0], optstring[1:] + if classify(opt, options): # May raise exception as well + if optstring = '': + if not args: + raise error, 'option -' + opt + ' requires argument' + optstring, args = args[0], args[1:] + optarg, optstring = optstring, '' + else: + optarg = '' + list.append('-' + opt, optarg) + return list, args def classify(opt, options): # Helper to check type of option - for i in range(len(options)): - if opt = options[i] <> ':': - return options[i+1:i+2] = ':' - raise error, 'option -' + opt + ' not recognized' + for i in range(len(options)): + if opt = options[i] <> ':': + return options[i+1:i+2] = ':' + raise error, 'option -' + opt + ' not recognized' diff --git a/lib/glob.py b/lib/glob.py index b711094..8a70f0e 100644 --- a/lib/glob.py +++ b/lib/glob.py @@ -5,40 +5,40 @@ import path import fnmatch def glob(pathname): - if not has_magic(pathname): return [pathname] - dirname, basename = path.split(pathname) - if dirname[-1:] = '/' and dirname <> '/': - dirname = dirname[:-1] - if has_magic(dirname): - list = glob(dirname) - else: - list = [dirname] - if not has_magic(basename): - result = [] - for dirname in list: - if basename or path.isdir(dirname): - name = path.cat(dirname, basename) - if path.exists(name): - result.append(name) - else: - result = [] - for dirname in list: - sublist = glob1(dirname, basename) - for name in sublist: - result.append(path.cat(dirname, name)) - return result + if not has_magic(pathname): return [pathname] + dirname, basename = path.split(pathname) + if dirname[-1:] = '/' and dirname <> '/': + dirname = dirname[:-1] + if has_magic(dirname): + list = glob(dirname) + else: + list = [dirname] + if not has_magic(basename): + result = [] + for dirname in list: + if basename or path.isdir(dirname): + name = path.cat(dirname, basename) + if path.exists(name): + result.append(name) + else: + result = [] + for dirname in list: + sublist = glob1(dirname, basename) + for name in sublist: + result.append(path.cat(dirname, name)) + return result def glob1(dirname, pattern): - if not dirname: dirname = '.' - try: - names = posix.listdir(dirname) - except posix.error: - return [] - result = [] - for name in names: - if name[0] <> '.' or pattern[0] = '.': - if fnmatch.fnmatch(name, pattern): result.append(name) - return result + if not dirname: dirname = '.' + try: + names = posix.listdir(dirname) + except posix.error: + return [] + result = [] + for name in names: + if name[0] <> '.' or pattern[0] = '.': + if fnmatch.fnmatch(name, pattern): result.append(name) + return result def has_magic(s): - return '*' in s or '?' in s or '[' in s + return '*' in s or '?' in s or '[' in s diff --git a/lib/grep.py b/lib/grep.py index 66eb08d..210f9f0 100644 --- a/lib/grep.py +++ b/lib/grep.py @@ -4,29 +4,29 @@ import regexp import string def grep(expr, filename): - prog = regexp.compile(expr) - fp = open(filename, 'r') - lineno = 0 - while 1: - line = fp.readline() - if not line: break - lineno = lineno + 1 - res = prog.exec(line) - if res: - #print res - start, end = res[0] - if line[-1:] = '\n': line = line[:-1] - prefix = string.rjust(`lineno`, 3) + ': ' - print prefix + line - if 0: - line = line[:start] - if '\t' not in line: - prefix = ' ' * (len(prefix) + start) - else: - prefix = ' ' * len(prefix) - for c in line: - if c <> '\t': c = ' ' - prefix = prefix + c - if start = end: prefix = prefix + '\\' - else: prefix = prefix + '^'*(end-start) - print prefix + prog = regexp.compile(expr) + fp = open(filename, 'r') + lineno = 0 + while 1: + line = fp.readline() + if not line: break + lineno = lineno + 1 + res = prog.exec(line) + if res: + #print res + start, end = res[0] + if line[-1:] = '\n': line = line[:-1] + prefix = string.rjust(`lineno`, 3) + ': ' + print prefix + line + if 0: + line = line[:start] + if '\t' not in line: + prefix = ' ' * (len(prefix) + start) + else: + prefix = ' ' * len(prefix) + for c in line: + if c <> '\t': c = ' ' + prefix = prefix + c + if start = end: prefix = prefix + '\\' + else: prefix = prefix + '^'*(end-start) + print prefix diff --git a/lib/gwin.py b/lib/gwin.py index f6291e1..a53f69c 100644 --- a/lib/gwin.py +++ b/lib/gwin.py @@ -9,113 +9,113 @@ from stdwinevents import * # XXX Old version of stdwinevents, should go import stdwinsupport -S = stdwinsupport # Shorthand +S = stdwinsupport # Shorthand -windows = [] # List of open windows +windows = [] # List of open windows # Open a window -def open(title): # Open a generic window - w = stdwin.open(title) - stdwin.setdefwinsize(0, 0) - # Set default event handlers - w.draw = nop - w.char = nop - w.mdown = nop - w.mmove = nop - w.mup = nop - w.m2down = m2down - w.m2up = m2up - w.size = nop - w.move = nop - w.activate = w.deactivate = nop - w.timer = nop - # default command handlers - w.close = close - w.tab = tab - w.enter = enter - w.backspace = backspace - w.arrow = arrow - w.kleft = w.kup = w.kright = w.kdown = nop - windows.append(w) - return w +def open(title): # Open a generic window + w = stdwin.open(title) + stdwin.setdefwinsize(0, 0) + # Set default event handlers + w.draw = nop + w.char = nop + w.mdown = nop + w.mmove = nop + w.mup = nop + w.m2down = m2down + w.m2up = m2up + w.size = nop + w.move = nop + w.activate = w.deactivate = nop + w.timer = nop + # default command handlers + w.close = close + w.tab = tab + w.enter = enter + w.backspace = backspace + w.arrow = arrow + w.kleft = w.kup = w.kright = w.kdown = nop + windows.append(w) + return w # Generic event dispatching -def mainloop(): # Handle events until no windows left - while windows: - treatevent(stdwin.getevent()) - -def treatevent(e): # Handle a stdwin event - type, w, detail = e - if type = S.we_draw: - w.draw(w, detail) - elif type = S.we_menu: - m, item = detail - m.action[item](w, m, item) - elif type = S.we_command: - treatcommand(w, detail) - elif type = S.we_char: - w.char(w, detail) - elif type = S.we_mouse_down: - if detail[1] > 1: w.m2down(w, detail) - else: w.mdown(w, detail) - elif type = S.we_mouse_move: - w.mmove(w, detail) - elif type = S.we_mouse_up: - if detail[1] > 1: w.m2up(w, detail) - else: w.mup(w, detail) - elif type = S.we_size: - w.size(w, w.getwinsize()) - elif type = S.we_activate: - w.activate(w) - elif type = S.we_deactivate: - w.deactivate(w) - elif type = S.we_move: - w.move(w) - elif type = S.we_timer: - w.timer(w) - elif type = WE_CLOSE: - w.close(w) - -def treatcommand(w, type): # Handle a we_command event - if type = S.wc_close: - w.close(w) - elif type = S.wc_return: - w.enter(w) - elif type = S.wc_tab: - w.tab(w) - elif type = S.wc_backspace: - w.backspace(w) - elif type in (S.wc_left, S.wc_up, S.wc_right, S.wc_down): - w.arrow(w, type) +def mainloop(): # Handle events until no windows left + while windows: + treatevent(stdwin.getevent()) + +def treatevent(e): # Handle a stdwin event + type, w, detail = e + if type = S.we_draw: + w.draw(w, detail) + elif type = S.we_menu: + m, item = detail + m.action[item](w, m, item) + elif type = S.we_command: + treatcommand(w, detail) + elif type = S.we_char: + w.char(w, detail) + elif type = S.we_mouse_down: + if detail[1] > 1: w.m2down(w, detail) + else: w.mdown(w, detail) + elif type = S.we_mouse_move: + w.mmove(w, detail) + elif type = S.we_mouse_up: + if detail[1] > 1: w.m2up(w, detail) + else: w.mup(w, detail) + elif type = S.we_size: + w.size(w, w.getwinsize()) + elif type = S.we_activate: + w.activate(w) + elif type = S.we_deactivate: + w.deactivate(w) + elif type = S.we_move: + w.move(w) + elif type = S.we_timer: + w.timer(w) + elif type = WE_CLOSE: + w.close(w) + +def treatcommand(w, type): # Handle a we_command event + if type = S.wc_close: + w.close(w) + elif type = S.wc_return: + w.enter(w) + elif type = S.wc_tab: + w.tab(w) + elif type = S.wc_backspace: + w.backspace(w) + elif type in (S.wc_left, S.wc_up, S.wc_right, S.wc_down): + w.arrow(w, type) # Methods -def close(w): # Close method - for i in range(len(windows)): - if windows[i] is w: - del windows[i] - break +def close(w): # Close method + for i in range(len(windows)): + if windows[i] is w: + del windows[i] + break -def arrow(w, detail): # Arrow key method - if detail = S.wc_left: - w.kleft(w) - elif detail = S.wc_up: - w.kup(w) - elif detail = S.wc_right: - w.kright(w) - elif detail = S.wc_down: - w.kdown(w) +def arrow(w, detail): # Arrow key method + if detail = S.wc_left: + w.kleft(w) + elif detail = S.wc_up: + w.kup(w) + elif detail = S.wc_right: + w.kright(w) + elif detail = S.wc_down: + w.kdown(w) # Trivial methods def tab(w): w.char(w, '\t') -def enter(w): w.char(w, '\n') # 'return' is a Python reserved word +def enter(w): w.char(w, '\n') # 'return' is a Python reserved word def backspace(w): w.char(w, '\b') def m2down(w, detail): w.mdown(w, detail) def m2up(w, detail): w.mup(w, detail) diff --git a/lib/lambda.py b/lib/lambda.py index 7d62b83..10fe8e0 100644 --- a/lib/lambda.py +++ b/lib/lambda.py @@ -13,16 +13,16 @@ # f and x are stored as data attributes of the member. class _CurryClass(): - def new(self, (f, x)): - self.f = f - self.x = x - return self - def fx(self, y): - return self.f(self.x, y) + def new(self, (f, x)): + self.f = f + self.x = x + return self + def fx(self, y): + return self.f(self.x, y) def CURRY(f, x): - # NB: f is not "simple": it has 2 arguments - return _CurryClass().new(f, x).fx + # NB: f is not "simple": it has 2 arguments + return _CurryClass().new(f, x).fx # Numbers in Lambda Calculus @@ -32,9 +32,9 @@ def CURRY(f, x): # times to x, e.g., Twice(f, x) = f(f(x)). # As far as I understand, there is no difference in real lambda # calculus between -# lambda f x : f(f(x)) +# lambda f x : f(f(x)) # and -# lambda f : f o f # 'o' means function composition +# lambda f : f o f # 'o' means function composition # but in Python we have to write the first as Twice(f, x) and # the second as twice(f). @@ -55,9 +55,9 @@ def fourfold(f): return CURRY(Fourfold, f) # NB: actually 'ntimes' is less concrete than 'Ntimes', as # 'ntimes' returns a function, while 'Ntimes' returns a value -# similar to what f(x) returns. 'Ntimes' can be derived +# similar to what f(x) returns. 'Ntimes' can be derived # from 'ntimes', as follows: -# def Ntimes(f, x): return ntimes(f)(x) +# def Ntimes(f, x): return ntimes(f)(x) # but this doesn't help us since 'ntimes' can only be defined # using Ntimes (or a trick like the one used by CURRY). @@ -65,21 +65,21 @@ def fourfold(f): return CURRY(Fourfold, f) # Arithmetic in Lambda Calculus # # We can perform simple arithmetic on the un-curried versions, e.g., -# Successor(Twice) = Thrice (2+1) -# Sum(Thrice, Twice) = Fivefold (3+2) -# Product(Thrice, Twice) = Sixfold (3*2) -# Power(Thrice, Twice) = Ninefold (3**2) +# Successor(Twice) = Thrice (2+1) +# Sum(Thrice, Twice) = Fivefold (3+2) +# Product(Thrice, Twice) = Sixfold (3*2) +# Power(Thrice, Twice) = Ninefold (3**2) # # First we define versions that need f and x arguments. # They have funny argument forms so the final functions can # use CURRY, which only works on functions of exactly 2 arguments. def SUCCESSOR(Ntimes, (f, x)): return f(Ntimes(f, x)) -def SUCCESSOR(Ntimes, (f, x)): return Ntimes(f, f(x)) # Same effect +def SUCCESSOR(Ntimes, (f, x)): return Ntimes(f, f(x)) # Same effect def SUM(Ntimes, (Mtimes, (f, x))): return Ntimes(f, Mtimes(f, x)) def PRODUCT(Ntimes, (Mtimes, (f, x))): return Ntimes(CURRY(Mtimes, f), x) def POWER(Ntimes, (Mtimes, (f, x))): - return Mtimes(CURRY(CURRY, Ntimes), f)(x) + return Mtimes(CURRY(CURRY, Ntimes), f)(x) def Successor(Ntimes): return CURRY(SUCCESSOR, Ntimes) def Sum(Ntimes, Mtimes): return CURRY(CURRY(SUM, Ntimes), Mtimes) @@ -98,54 +98,54 @@ def Power(Ntimes, Mtimes): return CURRY(CURRY(POWER, Ntimes), Mtimes) # P.S.: Here is a Lambda function in Python. # It uses 'exec' and expects two strings to describe the arguments -# and the function expression. Example: -# lambda('x', 'x+1') +# and the function expression. Example: +# lambda('x', 'x+1') # defines the successor function. def lambda(args, expr): - if '\n' in args or '\n' in expr: - raise RuntimeError, 'lambda: no cheating!' - stmt = 'def func(' + args + '): return ' + expr + '\n' - print 'lambda:', stmt, - exec(stmt) - return func + if '\n' in args or '\n' in expr: + raise RuntimeError, 'lambda: no cheating!' + stmt = 'def func(' + args + '): return ' + expr + '\n' + print 'lambda:', stmt, + exec(stmt) + return func # P.P.S.S.: Here is a way to construct Ntimes and ntimes directly. # Example: -# GenericNtimes(4) +# GenericNtimes(4) # is equivalent to Fourfold. class _GenericNtimesClass(): - def new(self, n): - self.n = n - return self - def Ntimes(self, (f, x)): - n = self.n - while n > 0: x, n = f(x), n-1 - return x + def new(self, n): + self.n = n + return self + def Ntimes(self, (f, x)): + n = self.n + while n > 0: x, n = f(x), n-1 + return x def GenericNtimes(n): - return _GenericNtimesClass().new(n).Ntimes + return _GenericNtimesClass().new(n).Ntimes # To construct any 'ntimes' function from the corresponding 'Ntimes', -# we use a trick as used by CURRY. For example, -# Ntimes2ntimes(Fourfold) +# we use a trick as used by CURRY. For example, +# Ntimes2ntimes(Fourfold) # yields a function equivalent to fourfold. class _Ntimes2ntimesClass(): - def new(self, Ntimes): - self.Ntimes = Ntimes - return self - def ntimes(self, f): - return CURRY(self.Ntimes, f) + def new(self, Ntimes): + self.Ntimes = Ntimes + return self + def ntimes(self, f): + return CURRY(self.Ntimes, f) def Ntimes2ntimes(Ntimes): return _Ntimes2ntimesClass().new(Ntimes).ntimes -# This allows us to construct generic 'ntimes' functions. Example: -# generic_ntimes(3) +# This allows us to construct generic 'ntimes' functions. Example: +# generic_ntimes(3) # is the same as thrice. def generic_ntimes(n): return Ntimes2ntimes(GenericNtimes(n)) diff --git a/lib/listwin.py b/lib/listwin.py index aac127c..9480a81 100644 --- a/lib/listwin.py +++ b/lib/listwin.py @@ -5,43 +5,43 @@ import gwin import stdwin def maxlinewidth(a): # Compute maximum textwidth of lines in a sequence - max = 0 - for line in a: - width = stdwin.textwidth(line) - if width > max: max = width - return max + max = 0 + for line in a: + width = stdwin.textwidth(line) + if width > max: max = width + return max def action(w, string, i, detail): # Default item selection method - pass + pass def mup(w, detail): # Mouse up method - (h, v), clicks, button, mask = detail - i = divmod(v, w.lineheight)[0] - if 0 <= i < len(w.data): - w.action(w, w.data[i], i, detail) + (h, v), clicks, button, mask = detail + i = divmod(v, w.lineheight)[0] + if 0 <= i < len(w.data): + w.action(w, w.data[i], i, detail) def draw(w, ((left, top), (right, bottom))): # Text window draw method - data = w.data - d = w.begindrawing() - lh = w.lineheight - itop = top/lh - ibot = (bottom-1)/lh + 1 - if itop < 0: itop = 0 - if ibot > len(data): ibot = len(data) - for i in range(itop, ibot): d.text((0, i*lh), data[i]) + data = w.data + d = w.begindrawing() + lh = w.lineheight + itop = top/lh + ibot = (bottom-1)/lh + 1 + if itop < 0: itop = 0 + if ibot > len(data): ibot = len(data) + for i in range(itop, ibot): d.text((0, i*lh), data[i]) def open(title, data): # Display a list of texts in a window - lineheight = stdwin.lineheight() - h, v = maxlinewidth(data), len(data)*lineheight - h0, v0 = h + stdwin.textwidth(' '), v + lineheight - if h0 > stdwin.textwidth(' ')*80: h0 = 0 - if v0 > stdwin.lineheight()*24: v0 = 0 - stdwin.setdefwinsize(h0, v0) - w = gwin.open(title) - w.setdocsize(h, v) - w.lineheight = lineheight - w.data = data - w.draw = draw - w.action = action - w.mup = mup - return w + lineheight = stdwin.lineheight() + h, v = maxlinewidth(data), len(data)*lineheight + h0, v0 = h + stdwin.textwidth(' '), v + lineheight + if h0 > stdwin.textwidth(' ')*80: h0 = 0 + if v0 > stdwin.lineheight()*24: v0 = 0 + stdwin.setdefwinsize(h0, v0) + w = gwin.open(title) + w.setdocsize(h, v) + w.lineheight = lineheight + w.data = data + w.draw = draw + w.action = action + w.mup = mup + return w diff --git a/lib/localtime.py b/lib/localtime.py index 5ce6529..1b662e9 100644 --- a/lib/localtime.py +++ b/lib/localtime.py @@ -2,52 +2,52 @@ import posix -epoch = 1970 # 1 jan 00:00:00, UCT -day0 = 4 # day 0 was a thursday +epoch = 1970 # 1 jan 00:00:00, UCT +day0 = 4 # day 0 was a thursday day_names = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat') -month_names = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun') +month_names = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun') month_names = month_names + ('Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec') month_sizes = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) def isleap(year): - return year % 4 = 0 and (year % 100 <> 0 or year % 400 = 0) - -def gmtime(secs): # decode time into UCT - mins, secs = divmod(secs, 60) - hours, mins = divmod(mins, 60) - days, hours = divmod(hours, 24) - wday = (day0 + days) % 7 - year = epoch - lp = isleap(year) - dpy = 365 + lp - while days >= dpy: - days = days - dpy - year = year + 1 - lp = isleap(year) - dpy = 365 + lp - yday = days - month = 0 - dpm = month_sizes[month] + (lp and month = 1) - while days >= dpm: - days = days - dpm - month = month + 1 - dpm = month_sizes[month] + (lp and month = 1) - return (year, month, days+1, hours, mins, secs, yday, wday) + return year % 4 = 0 and (year % 100 <> 0 or year % 400 = 0) + +def gmtime(secs): # decode time into UCT + mins, secs = divmod(secs, 60) + hours, mins = divmod(mins, 60) + days, hours = divmod(hours, 24) + wday = (day0 + days) % 7 + year = epoch + lp = isleap(year) + dpy = 365 + lp + while days >= dpy: + days = days - dpy + year = year + 1 + lp = isleap(year) + dpy = 365 + lp + yday = days + month = 0 + dpm = month_sizes[month] + (lp and month = 1) + while days >= dpm: + days = days - dpm + month = month + 1 + dpm = month_sizes[month] + (lp and month = 1) + return (year, month, days+1, hours, mins, secs, yday, wday) def dd(x): - s = `x` - while len(s) < 2: s = '0' + s - return s + s = `x` + while len(s) < 2: s = '0' + s + return s def zd(x): - s = `x` - while len(s) < 2: s = ' ' + s - return s + s = `x` + while len(s) < 2: s = ' ' + s + return s def format(year, month, days, hours, mins, secs, yday, wday): - s = day_names[wday] + ' ' + zd(days) + ' ' + month_names[month] + ' ' - s = s + dd(hours) + ':' + dd(mins) + ':' + dd(secs) - return s + s = day_names[wday] + ' ' + zd(days) + ' ' + month_names[month] + ' ' + s = s + dd(hours) + ':' + dd(mins) + ':' + dd(secs) + return s diff --git a/lib/maccache.py b/lib/maccache.py index 329e514..dc6502b 100644 --- a/lib/maccache.py +++ b/lib/maccache.py @@ -25,37 +25,37 @@ FILE = 1 LISTTYPE = type([]) def _stat(name): - name = macpath.cat(cwd, name) - if cache.has_key(name): - return cache[name] - if macpath.isfile(name): - cache[name] = FILE - return FILE - try: - list = mac.listdir(name) - except: - cache[name] = NONE - return NONE - cache[name] = list - if name[-1:] = ':': cache[name[:-1]] = list - else: cache[name+':'] = list - return list + name = macpath.cat(cwd, name) + if cache.has_key(name): + return cache[name] + if macpath.isfile(name): + cache[name] = FILE + return FILE + try: + list = mac.listdir(name) + except: + cache[name] = NONE + return NONE + cache[name] = list + if name[-1:] = ':': cache[name[:-1]] = list + else: cache[name+':'] = list + return list def isdir(name): - st = _stat(name) - return type(st) = LISTTYPE + st = _stat(name) + return type(st) = LISTTYPE def isfile(name): - st = _stat(name) - return st = FILE + st = _stat(name) + return st = FILE def exists(name): - st = _stat(name) - return st <> NONE + st = _stat(name) + return st <> NONE def listdir(name): - st = _stat(name) - if type(st) = LISTTYPE: - return st - else: - raise RuntimeError, 'list non-directory' + st = _stat(name) + if type(st) = LISTTYPE: + return st + else: + raise RuntimeError, 'list non-directory' diff --git a/lib/macglob.py b/lib/macglob.py index cad2c79..f18c396 100644 --- a/lib/macglob.py +++ b/lib/macglob.py @@ -8,39 +8,39 @@ import macpath import fnmatch def glob(pathname): - if not has_magic(pathname): return [pathname] - dirname, basename = macpath.split(pathname) - if has_magic(dirname): - if dirname[-1:] = ':': dirname = dirname[:-1] - list = glob(dirname) - else: - list = [dirname] - if not has_magic(basename): - result = [] - for dirname in list: - if basename or macpath.isdir(dirname): - name = macpath.cat(dirname, basename) - if macpath.exists(name): - result.append(name) - else: - result = [] - for dirname in list: - sublist = glob1(dirname, basename) - for name in sublist: - result.append(macpath.cat(dirname, name)) - return result + if not has_magic(pathname): return [pathname] + dirname, basename = macpath.split(pathname) + if has_magic(dirname): + if dirname[-1:] = ':': dirname = dirname[:-1] + list = glob(dirname) + else: + list = [dirname] + if not has_magic(basename): + result = [] + for dirname in list: + if basename or macpath.isdir(dirname): + name = macpath.cat(dirname, basename) + if macpath.exists(name): + result.append(name) + else: + result = [] + for dirname in list: + sublist = glob1(dirname, basename) + for name in sublist: + result.append(macpath.cat(dirname, name)) + return result def glob1(dirname, pattern): - if not dirname: dirname = ':' - try: - names = mac.listdir(dirname) - except mac.error: - return [] - result = [] - for name in names: - if name[0] <> '.' or pattern[0] = '.': - if fnmatch.fnmatch(name, pattern): result.append(name) - return result + if not dirname: dirname = ':' + try: + names = mac.listdir(dirname) + except mac.error: + return [] + result = [] + for name in names: + if name[0] <> '.' or pattern[0] = '.': + if fnmatch.fnmatch(name, pattern): result.append(name) + return result def has_magic(s): - return '*' in s or '?' in s or '[' in s + return '*' in s or '?' in s or '[' in s diff --git a/lib/macpath.py b/lib/macpath.py index 99ba6b8..99254ab 100644 --- a/lib/macpath.py +++ b/lib/macpath.py @@ -12,7 +12,7 @@ from stat import * # volume name). def isabs(s): - return ':' in s and s[0] <> ':' + return ':' in s and s[0] <> ':' # Concatenate two pathnames. @@ -20,13 +20,13 @@ def isabs(s): # if the first pathname were the current directory. def cat(s, t): - if (not s) or isabs(t): return t - if t[:1] = ':': t = t[1:] - if ':' not in s: - s = ':' + s - if s[-1:] <> ':': - s = s + ':' - return s + t + if (not s) or isabs(t): return t + if t[:1] = ':': t = t[1:] + if ':' not in s: + s = ':' + s + if s[-1:] <> ':': + s = s + ':' + return s + t # Split a pathname in two parts: the directory leading up to the final bit, @@ -34,11 +34,11 @@ def cat(s, t): # The result (s, t) is such that cat(s, t) yields the original argument. def split(s): - if ':' not in s: return '', s - colon = 0 - for i in range(len(s)): - if s[i] = ':': colon = i+1 - return s[:colon], s[colon:] + if ':' not in s: return '', s + colon = 0 + for i in range(len(s)): + if s[i] = ':': colon = i+1 + return s[:colon], s[colon:] # Normalize a pathname: get rid of '::' sequences by backing up, @@ -49,60 +49,60 @@ def split(s): norm_error = 'macpath.norm_error: path cannot be normalized' def norm(s): - import string - if ':' not in s: - return ':' + s - f = string.splitfields(s, ':') - pre = [] - post = [] - if not f[0]: - pre = f[:1] - f = f[1:] - if not f[len(f)-1]: - post = f[-1:] - f = f[:-1] - res = [] - for seg in f: - if seg: - res.append(seg) - else: - if not res: raise norm_error, 'path starts with ::' - del res[len(res)-1] - if not (pre or res): - raise norm_error, 'path starts with volume::' - if pre: res = pre + res - if post: res = res + post - s = res[0] - for seg in res[1:]: - s = s + ':' + seg - return s + import string + if ':' not in s: + return ':' + s + f = string.splitfields(s, ':') + pre = [] + post = [] + if not f[0]: + pre = f[:1] + f = f[1:] + if not f[len(f)-1]: + post = f[-1:] + f = f[:-1] + res = [] + for seg in f: + if seg: + res.append(seg) + else: + if not res: raise norm_error, 'path starts with ::' + del res[len(res)-1] + if not (pre or res): + raise norm_error, 'path starts with volume::' + if pre: res = pre + res + if post: res = res + post + s = res[0] + for seg in res[1:]: + s = s + ':' + seg + return s # Return true if the pathname refers to an existing directory. def isdir(s): - try: - st = mac.stat(s) - except mac.error: - return 0 - return S_ISDIR(st[ST_MODE]) + try: + st = mac.stat(s) + except mac.error: + return 0 + return S_ISDIR(st[ST_MODE]) # Return true if the pathname refers to an existing regular file. def isfile(s): - try: - st = mac.stat(s) - except mac.error: - return 0 - return S_ISREG(st[ST_MODE]) + try: + st = mac.stat(s) + except mac.error: + return 0 + return S_ISREG(st[ST_MODE]) # Return true if the pathname refers to an existing file or directory. def exists(s): - try: - st = mac.stat(s) - except mac.error: - return 0 - return 1 + try: + st = mac.stat(s) + except mac.error: + return 0 + return 1 diff --git a/lib/macshell.py b/lib/macshell.py index c96d65b..884c89c 100644 --- a/lib/macshell.py +++ b/lib/macshell.py @@ -21,379 +21,379 @@ class Struct(): pass G = Struct() def reset(): - G.debug = 0 - G.ps1 = '$ ' - G.homedir = mac.getcwd() - G.commands = mkcmdtab() - G.aliases = {} + G.debug = 0 + G.ps1 = '$ ' + G.homedir = mac.getcwd() + G.commands = mkcmdtab() + G.aliases = {} def mkcmdtab(): - tab = {} - tab['alias'] = do_alias - tab['cd'] = do_cd - tab['debug'] = do_debug - tab['grep'] = do_grep - tab['help'] = do_help - tab['ls'] = do_ls - tab['mkdir'] = do_mkdir - tab['mv'] = do_mv - tab['page'] = do_page - tab['pwd'] = do_pwd - tab['reset'] = do_reset - tab['rm'] = do_rm - tab['rmdir'] = do_rmdir - tab['sync'] = do_sync - tab['unalias'] = do_unalias - return tab + tab = {} + tab['alias'] = do_alias + tab['cd'] = do_cd + tab['debug'] = do_debug + tab['grep'] = do_grep + tab['help'] = do_help + tab['ls'] = do_ls + tab['mkdir'] = do_mkdir + tab['mv'] = do_mv + tab['page'] = do_page + tab['pwd'] = do_pwd + tab['reset'] = do_reset + tab['rm'] = do_rm + tab['rmdir'] = do_rmdir + tab['sync'] = do_sync + tab['unalias'] = do_unalias + return tab def main(): - while 1: - try: - line = raw_input(G.ps1) - except EOFError: - print '[EOF]' - break - except KeyboardInterrupt: - print '[Intr]' - line = '' - if G.debug: - print 'line:', `line` - words = TclUtil.SplitList(line) - if G.debug: - print 'words:', words - if words and words[0][0] <> '#': - run(words) + while 1: + try: + line = raw_input(G.ps1) + except EOFError: + print '[EOF]' + break + except KeyboardInterrupt: + print '[Intr]' + line = '' + if G.debug: + print 'line:', `line` + words = TclUtil.SplitList(line) + if G.debug: + print 'words:', words + if words and words[0][0] <> '#': + run(words) def run(words): - expandaliases(words) - cmd = words[0] - args = words[1:] - if G.commands.has_key(cmd): - if args: - try: - args = expandgloblist(args) - except glob_error, msg: - print cmd, ': glob error :', msg - return - G.commands[cmd](args) - return - if hasglobchar(cmd): - if args: - print cmd, ': cannot glob pattern with arguments' - return - try: - words = expandglobword(cmd) - except glob_error, msg: - print cmd, ': glob error :', msg - return - if len(words) > 1: - columnize(words) - return - cmd = words[0] - print cmd - if isfile(cmd): - if args: - print cmd, ': file command expects no arguments' - return - do_page([cmd]) - elif isdir(cmd): - if args: - print cmd, ': directory command expects no arguments' - return - do_cd([cmd]) - else: - print cmd, ': no such command, file or directory' + expandaliases(words) + cmd = words[0] + args = words[1:] + if G.commands.has_key(cmd): + if args: + try: + args = expandgloblist(args) + except glob_error, msg: + print cmd, ': glob error :', msg + return + G.commands[cmd](args) + return + if hasglobchar(cmd): + if args: + print cmd, ': cannot glob pattern with arguments' + return + try: + words = expandglobword(cmd) + except glob_error, msg: + print cmd, ': glob error :', msg + return + if len(words) > 1: + columnize(words) + return + cmd = words[0] + print cmd + if isfile(cmd): + if args: + print cmd, ': file command expects no arguments' + return + do_page([cmd]) + elif isdir(cmd): + if args: + print cmd, ': directory command expects no arguments' + return + do_cd([cmd]) + else: + print cmd, ': no such command, file or directory' glob_error = 'glob error' def expandgloblist(words): - res = [] - for word in words: - if hasglobchar(word): - res = res + expandglobword(word) - else: - res.append(word) - return res + res = [] + for word in words: + if hasglobchar(word): + res = res + expandglobword(word) + else: + res.append(word) + return res def expandglobword(word): - names = glob.globlist(mac.listdir(':'), word) - if not names: raise glob_error, 'no match for pattern ' + word - return names + names = glob.globlist(mac.listdir(':'), word) + if not names: raise glob_error, 'no match for pattern ' + word + return names def hasglobchar(word): - return '*' in word or '?' in word + return '*' in word or '?' in word def expandaliases(words): - seen = [] - cmd = words[0] - while cmd not in seen and G.aliases.has_key(cmd): - seen.append(cmd) - words[:1] = G.aliases[cmd] - cmd = words[0] + seen = [] + cmd = words[0] + while cmd not in seen and G.aliases.has_key(cmd): + seen.append(cmd) + words[:1] = G.aliases[cmd] + cmd = words[0] def do_alias(args): - if not args: - listaliases() - elif len(args) = 1: - listalias(args[0]) - else: - defalias(args[0], args[1:]) + if not args: + listaliases() + elif len(args) = 1: + listalias(args[0]) + else: + defalias(args[0], args[1:]) def listaliases(): - names = G.aliases.keys() - names.sort() - for name in names: listalias(name) + names = G.aliases.keys() + names.sort() + for name in names: listalias(name) def listalias(name): - if not G.aliases.has_key(name): - print name, ': no such alias' - return - print 'alias', name, - printlist(G.aliases[name]) - print + if not G.aliases.has_key(name): + print name, ': no such alias' + return + print 'alias', name, + printlist(G.aliases[name]) + print def defalias(name, expansion): - G.aliases[name] = expansion + G.aliases[name] = expansion def do_cd(args): - if len(args) > 1: - print 'usage: cd [dirname]' - elif args: - chdirto(args[0]) - else: - chdirto(G.homedir) + if len(args) > 1: + print 'usage: cd [dirname]' + elif args: + chdirto(args[0]) + else: + chdirto(G.homedir) def chdirto(dirname): - try: - mac.chdir(dirname) - except mac.error, msg: - print dirname, ':', msg - return + try: + mac.chdir(dirname) + except mac.error, msg: + print dirname, ':', msg + return def do_debug(args): - G.debug = (not G.debug) + G.debug = (not G.debug) def do_grep(args): - if len(args) < 2: - print 'usage: grep regexp file ...' - return - import regexp - try: - prog = regexp.compile(args[0]) - except regexp.error, msg: - print 'regexp.compile error for', args[0], ':', msg - return - for file in args[1:]: - grepfile(prog, file) + if len(args) < 2: + print 'usage: grep regexp file ...' + return + import regexp + try: + prog = regexp.compile(args[0]) + except regexp.error, msg: + print 'regexp.compile error for', args[0], ':', msg + return + for file in args[1:]: + grepfile(prog, file) def grepfile(prog, file): - try: - fp = open(file, 'r') - except RuntimeError, msg: - print file, ': cannot open :', msg - return - lineno = 0 - while 1: - line = fp.readline() - if not line: break - lineno = lineno+1 - if prog.exec(line): - print file+'('+`lineno`+'):', line, + try: + fp = open(file, 'r') + except RuntimeError, msg: + print file, ': cannot open :', msg + return + lineno = 0 + while 1: + line = fp.readline() + if not line: break + lineno = lineno+1 + if prog.exec(line): + print file+'('+`lineno`+'):', line, def do_help(args): - if args: - print 'usage: help' - return - names = G.commands.keys() - names.sort() - columnize(names) + if args: + print 'usage: help' + return + names = G.commands.keys() + names.sort() + columnize(names) def do_ls(args): - if not args: - lsdir(':') - else: - for dirname in args: - lsdir(dirname) + if not args: + lsdir(':') + else: + for dirname in args: + lsdir(dirname) def lsdir(dirname): - if not isdir(dirname): - print dirname, ': no such directory' - return - names = mac.listdir(dirname) - lsfiles(names, dirname) + if not isdir(dirname): + print dirname, ': no such directory' + return + names = mac.listdir(dirname) + lsfiles(names, dirname) def lsfiles(names, dirname): - names = names[:] # Make a copy so we can modify it - for i in range(len(names)): - name = names[i] - if G.debug: print i, name - if isdir(macpath.cat(dirname, name)): - names[i] = ':' + name + ':' - columnize(names) + names = names[:] # Make a copy so we can modify it + for i in range(len(names)): + name = names[i] + if G.debug: print i, name + if isdir(macpath.cat(dirname, name)): + names[i] = ':' + name + ':' + columnize(names) def columnize(list): - COLUMNS = 80-1 - n = len(list) - colwidth = maxwidth(list) - ncols = (COLUMNS + 1) / (colwidth + 1) - if ncols < 1: ncols = 1 - nrows = (n + ncols - 1) / ncols - for irow in range(nrows): - line = '' - for icol in range(ncols): - i = irow + nrows*icol - if 0 <= i < n: - word = list[i] - if i+nrows < n: - word = string.ljust(word, colwidth) - if icol > 0: - word = ' ' + word - line = line + word - print line + COLUMNS = 80-1 + n = len(list) + colwidth = maxwidth(list) + ncols = (COLUMNS + 1) / (colwidth + 1) + if ncols < 1: ncols = 1 + nrows = (n + ncols - 1) / ncols + for irow in range(nrows): + line = '' + for icol in range(ncols): + i = irow + nrows*icol + if 0 <= i < n: + word = list[i] + if i+nrows < n: + word = string.ljust(word, colwidth) + if icol > 0: + word = ' ' + word + line = line + word + print line def maxwidth(list): - width = 0 - for word in list: - if len(word) > width: - width = len(word) - return width + width = 0 + for word in list: + if len(word) > width: + width = len(word) + return width def do_mv(args): - if len(args) <> 2: - print 'usage: mv src dst' - return - src, dst = args[0], args[1] - if not exists(src): - print src, ': source does not exist' - return - if exists(dst): - print src, ': destination already exists' - return - try: - mac.rename(src, dst) - except mac.error, msg: - print src, dst, ': rename failed:', msg + if len(args) <> 2: + print 'usage: mv src dst' + return + src, dst = args[0], args[1] + if not exists(src): + print src, ': source does not exist' + return + if exists(dst): + print src, ': destination already exists' + return + try: + mac.rename(src, dst) + except mac.error, msg: + print src, dst, ': rename failed:', msg def do_mkdir(args): - if not args: - print 'usage: mkdir name ...' - return - for name in args: - makedir(name) + if not args: + print 'usage: mkdir name ...' + return + for name in args: + makedir(name) def makedir(name): - if exists(name): - print name, ': already exists' - return - try: - mac.mkdir(name, 0777) - except mac.error, msg: - print name, ': mkdir failed:', msg + if exists(name): + print name, ': already exists' + return + try: + mac.mkdir(name, 0777) + except mac.error, msg: + print name, ': mkdir failed:', msg def do_page(args): - if not args: - print 'usage: page file ...' - return - for name in args: - pagefile(name) + if not args: + print 'usage: page file ...' + return + for name in args: + pagefile(name) def pagefile(name): - if not isfile(name): - print name, ': no such file' - return - LINES = 24 - 1 - # For THINK C 3.0, make the path absolute: - # if not macpath.isabs(name): - # name = macpath.cat(mac.getcwd(), name) - try: - fp = open(name, 'r') - except: - print name, ': cannot open' - return - line = fp.readline() - while line: - for i in range(LINES): - print line, - line = fp.readline() - if not line: break - if line: - try: - more = raw_input('[more]') - except (EOFError, KeyboardInterrupt): - print - break - if string.strip(more)[:1] in ('q', 'Q'): - break + if not isfile(name): + print name, ': no such file' + return + LINES = 24 - 1 + # For THINK C 3.0, make the path absolute: + # if not macpath.isabs(name): + # name = macpath.cat(mac.getcwd(), name) + try: + fp = open(name, 'r') + except: + print name, ': cannot open' + return + line = fp.readline() + while line: + for i in range(LINES): + print line, + line = fp.readline() + if not line: break + if line: + try: + more = raw_input('[more]') + except (EOFError, KeyboardInterrupt): + print + break + if string.strip(more)[:1] in ('q', 'Q'): + break def do_pwd(args): - if args: - print 'usage: pwd' - else: - print mac.getcwd() + if args: + print 'usage: pwd' + else: + print mac.getcwd() def do_reset(args): - if args: - print 'usage: reset' - else: - reset() + if args: + print 'usage: reset' + else: + reset() def do_rm(args): - if not args: - print 'usage: rm file ...' - return - for name in args: - remove(name) + if not args: + print 'usage: rm file ...' + return + for name in args: + remove(name) def remove(name): - if not isfile(name): - print name, ': no such file' - return - try: - mac.unlink(name) - except mac.error, msg: - print name, ': unlink failed:', msg + if not isfile(name): + print name, ': no such file' + return + try: + mac.unlink(name) + except mac.error, msg: + print name, ': unlink failed:', msg def do_rmdir(args): - if not args: - print 'usage: rmdir dir ...' - return - for name in args: - rmdir(name) + if not args: + print 'usage: rmdir dir ...' + return + for name in args: + rmdir(name) def rmdir(name): - if not isdir(name): - print name, ': no such directory' - return - try: - mac.rmdir(name) - except mac.error, msg: - print name, ': rmdir failed:', msg + if not isdir(name): + print name, ': no such directory' + return + try: + mac.rmdir(name) + except mac.error, msg: + print name, ': rmdir failed:', msg def do_sync(args): - if args: - print 'usage: sync' - return - try: - mac.sync() - except mac.error, msg: - print 'sync failed:', msg + if args: + print 'usage: sync' + return + try: + mac.sync() + except mac.error, msg: + print 'sync failed:', msg def do_unalias(args): - if not args: - print 'usage: unalias name ...' - return - for name in args: - unalias(name) + if not args: + print 'usage: unalias name ...' + return + for name in args: + unalias(name) def unalias(name): - if not G.aliases.has_key(name): - print name, ': no such alias' - return - del G.aliases[name] + if not G.aliases.has_key(name): + print name, ': no such alias' + return + del G.aliases[name] def printlist(list): - for word in list: - print word, + for word in list: + print word, reset() main() diff --git a/lib/packmail.py b/lib/packmail.py index 40b5b7a..c7bebe8 100644 --- a/lib/packmail.py +++ b/lib/packmail.py @@ -6,43 +6,43 @@ from stat import ST_MTIME # Pack one file def pack(outfp, file, name): - fp = open(file, 'r') - outfp.write('sed "s/^X//" >' + name + ' <<"!"\n') - while 1: - line = fp.readline() - if not line: break - if line[-1:] <> '\n': - line = line + '\n' - outfp.write('X' + line) - outfp.write('!\n') + fp = open(file, 'r') + outfp.write('sed "s/^X//" >' + name + ' <<"!"\n') + while 1: + line = fp.readline() + if not line: break + if line[-1:] <> '\n': + line = line + '\n' + outfp.write('X' + line) + outfp.write('!\n') # Pack some files from a directory def packsome(outfp, dirname, names): - for name in names: - print name - file = macpath.cat(dirname, name) - pack(outfp, file, name) + for name in names: + print name + file = macpath.cat(dirname, name) + pack(outfp, file, name) # Pack all files from a directory def packall(outfp, dirname): - names = mac.listdir(dirname) - names.sort() - packsome(outfp, dirname, names) + names = mac.listdir(dirname) + names.sort() + packsome(outfp, dirname, names) # Pack all files from a directory that are not older than a give one def packnotolder(outfp, dirname, oldest): - names = mac.listdir(dirname) - oldest = macpath.cat(dirname, oldest) - st = mac.stat(oldest) - mtime = st[ST_MTIME] - todo = [] - for name in names: - print name, '...', - st = mac.stat(macpath.cat(dirname, name)) - if st[ST_MTIME] >= mtime: - print 'Yes.' - todo.append(name) - else: - print 'No.' - todo.sort() - packsome(outfp, dirname, todo) + names = mac.listdir(dirname) + oldest = macpath.cat(dirname, oldest) + st = mac.stat(oldest) + mtime = st[ST_MTIME] + todo = [] + for name in names: + print name, '...', + st = mac.stat(macpath.cat(dirname, name)) + if st[ST_MTIME] >= mtime: + print 'Yes.' + todo.append(name) + else: + print 'No.' + todo.sort() + packsome(outfp, dirname, todo) diff --git a/lib/panel.py b/lib/panel.py index 8b0b45c..9fda1c6 100644 --- a/lib/panel.py +++ b/lib/panel.py @@ -17,82 +17,82 @@ debug = 0 # Test if an object is a list. # def is_list(x): - return type(x) = type([]) + return type(x) = type([]) # Reverse a list. # def reverse(list): - res = [] - for item in list: - res.insert(0, item) - return res + res = [] + for item in list: + res.insert(0, item) + return res # Get an attribute of a list, which may itself be another list. # Don't use 'prop' for name. # def getattrlist(list, name): - for item in list: - if item and is_list(item) and item[0] = name: - return item[1:] - return [] + for item in list: + if item and is_list(item) and item[0] = name: + return item[1:] + return [] # Get a property of a list, which may itself be another list. # def getproplist(list, name): - for item in list: - if item and is_list(item) and item[0] = 'prop': - if len(item) > 1 and item[1] = name: - return item[2:] - return [] + for item in list: + if item and is_list(item) and item[0] = 'prop': + if len(item) > 1 and item[1] = name: + return item[2:] + return [] # Test if an actuator description contains the property 'end-of-group' # def is_endgroup(list): - x = getproplist(list, 'end-of-group') - return (x and x[0] = '#t') + x = getproplist(list, 'end-of-group') + return (x and x[0] = '#t') # Neatly display an actuator definition given as S-expression # the prefix string is printed before each line. # def show_actuator(prefix, a): - for item in a: - if not is_list(item): - print prefix, item - elif item and item[0] = 'al': - print prefix, 'Subactuator list:' - for a in item[1:]: - show_actuator(prefix + ' ', a) - elif len(item) = 2: - print prefix, item[0], '=>', item[1] - elif len(item) = 3 and item[0] = 'prop': - print prefix, 'Prop', item[1], '=>', - print item[2] - else: - print prefix, '?', item + for item in a: + if not is_list(item): + print prefix, item + elif item and item[0] = 'al': + print prefix, 'Subactuator list:' + for a in item[1:]: + show_actuator(prefix + ' ', a) + elif len(item) = 2: + print prefix, item[0], '=>', item[1] + elif len(item) = 3 and item[0] = 'prop': + print prefix, 'Prop', item[1], '=>', + print item[2] + else: + print prefix, '?', item # Neatly display a panel. # def show_panel(prefix, p): - for item in p: - if not is_list(item): - print prefix, item - elif item and item[0] = 'al': - print prefix, 'Actuator list:' - for a in item[1:]: - show_actuator(prefix + ' ', a) - elif len(item) = 2: - print prefix, item[0], '=>', item[1] - elif len(item) = 3 and item[0] = 'prop': - print prefix, 'Prop', item[1], '=>', - print item[2] - else: - print prefix, '?', item + for item in p: + if not is_list(item): + print prefix, item + elif item and item[0] = 'al': + print prefix, 'Actuator list:' + for a in item[1:]: + show_actuator(prefix + ' ', a) + elif len(item) = 2: + print prefix, item[0], '=>', item[1] + elif len(item) = 3 and item[0] = 'prop': + print prefix, 'Prop', item[1], '=>', + print item[2] + else: + print prefix, '?', item # Exception raised by build_actuator or build_panel. @@ -103,7 +103,7 @@ panel_error = 'panel error' # Dummy callback used to initialize the callbacks. # def dummy_callback(arg): - pass + pass # Assign attributes to members of the target. @@ -111,60 +111,60 @@ def dummy_callback(arg): # The member name is the attribute name prefixed with the prefix. # def assign_members(target, attrlist, exclist, prefix): - for item in attrlist: - if is_list(item) and len(item) = 2 and item[0] not in exclist: - name, value = item[0], item[1] - ok = 1 - if value[0] in '-0123456789': - value = eval(value) - elif value[0] = '"': - value = value[1:-1] - elif value = 'move-then-resize': - # Strange default set by Panel Editor... - ok = 0 - else: - print 'unknown value', value, 'for', name - ok = 0 - if ok: - lhs = 'target.' + prefix + name - stmt = lhs + '=' + `value` - if debug: print 'exec', stmt - try: - exec(stmt + '\n') - except KeyboardInterrupt: # Don't catch this! - raise KeyboardInterrupt - except: - print 'assign failed:', stmt + for item in attrlist: + if is_list(item) and len(item) = 2 and item[0] not in exclist: + name, value = item[0], item[1] + ok = 1 + if value[0] in '-0123456789': + value = eval(value) + elif value[0] = '"': + value = value[1:-1] + elif value = 'move-then-resize': + # Strange default set by Panel Editor... + ok = 0 + else: + print 'unknown value', value, 'for', name + ok = 0 + if ok: + lhs = 'target.' + prefix + name + stmt = lhs + '=' + `value` + if debug: print 'exec', stmt + try: + exec(stmt + '\n') + except KeyboardInterrupt: # Don't catch this! + raise KeyboardInterrupt + except: + print 'assign failed:', stmt # Build a real actuator from an actuator descriptior. # Return a pair (actuator, name). # def build_actuator(descr): - namelist = getattrlist(descr, 'name') - if namelist: - # Assume it is a string - actuatorname = namelist[0][1:-1] - else: - actuatorname = '' - type = descr[0] - if type[:4] = 'pnl_': type = type[4:] - act = pnl.mkact(type) - act.downfunc = act.activefunc = act.upfunc = dummy_callback - # - assign_members(act, descr[1:], ['al', 'data', 'name'], '') - # - # Treat actuator-specific data - # - datalist = getattrlist(descr, 'data') - prefix = '' - if type[-4:] = 'puck': - prefix = 'puck_' - elif type = 'mouse': - prefix = 'mouse_' - assign_members(act, datalist, [], prefix) - # - return act, actuatorname + namelist = getattrlist(descr, 'name') + if namelist: + # Assume it is a string + actuatorname = namelist[0][1:-1] + else: + actuatorname = '' + type = descr[0] + if type[:4] = 'pnl_': type = type[4:] + act = pnl.mkact(type) + act.downfunc = act.activefunc = act.upfunc = dummy_callback + # + assign_members(act, descr[1:], ['al', 'data', 'name'], '') + # + # Treat actuator-specific data + # + datalist = getattrlist(descr, 'data') + prefix = '' + if type[-4:] = 'puck': + prefix = 'puck_' + elif type = 'mouse': + prefix = 'mouse_' + assign_members(act, datalist, [], prefix) + # + return act, actuatorname # Build all sub-actuators and add them to the super-actuator. @@ -176,27 +176,27 @@ def build_actuator(descr): # to a sub-actuator. # def build_subactuators(panel, super_act, al): - # - # This is nearly the same loop as below in build_panel(), - # except a call is made to addsubact() instead of addact(). - # - for a in al: - act, name = build_actuator(a) - act.addsubact(super_act) - if name: - stmt = 'panel.' + name + ' = act' - if debug: print 'exec', stmt - exec(stmt + '\n') - if is_endgroup(a): - panel.endgroup() - sub_al = getattrlist(a, 'al') - if sub_al: - build_subactuators(panel, act, sub_al) - # - # Fix the actuator to which whe just added subactuators. - # This can't hurt (I hope) and is needed for the scroll actuator. - # - super_act.fixact() + # + # This is nearly the same loop as below in build_panel(), + # except a call is made to addsubact() instead of addact(). + # + for a in al: + act, name = build_actuator(a) + act.addsubact(super_act) + if name: + stmt = 'panel.' + name + ' = act' + if debug: print 'exec', stmt + exec(stmt + '\n') + if is_endgroup(a): + panel.endgroup() + sub_al = getattrlist(a, 'al') + if sub_al: + build_subactuators(panel, act, sub_al) + # + # Fix the actuator to which whe just added subactuators. + # This can't hurt (I hope) and is needed for the scroll actuator. + # + super_act.fixact() # Build a real panel from a panel definition. @@ -204,78 +204,78 @@ def build_subactuators(panel, super_act, al): # reference to a. # def build_panel(descr): - # - # Sanity check - # - if (not descr) or descr[0] <> 'panel': - raise panel_error, 'panel description must start with "panel"' - # - if debug: show_panel('', descr) - # - # Create an empty panel - # - panel = pnl.mkpanel() - # - # Assign panel attributes - # - assign_members(panel, descr[1:], ['al'], '') - # - # Look for actuator list - # - al = getattrlist(descr, 'al') - # - # The order in which actuators are created is important - # because of the endgroup() operator. - # Unfortunately the Panel Editor outputs the actuator list - # in reverse order, so we reverse it here. - # - al = reverse(al) - # - for a in al: - act, name = build_actuator(a) - act.addact(panel) - if name: - stmt = 'panel.' + name + ' = act' - exec(stmt + '\n') - if is_endgroup(a): - panel.endgroup() - sub_al = getattrlist(a, 'al') - if sub_al: - build_subactuators(panel, act, sub_al) - # - return panel + # + # Sanity check + # + if (not descr) or descr[0] <> 'panel': + raise panel_error, 'panel description must start with "panel"' + # + if debug: show_panel('', descr) + # + # Create an empty panel + # + panel = pnl.mkpanel() + # + # Assign panel attributes + # + assign_members(panel, descr[1:], ['al'], '') + # + # Look for actuator list + # + al = getattrlist(descr, 'al') + # + # The order in which actuators are created is important + # because of the endgroup() operator. + # Unfortunately the Panel Editor outputs the actuator list + # in reverse order, so we reverse it here. + # + al = reverse(al) + # + for a in al: + act, name = build_actuator(a) + act.addact(panel) + if name: + stmt = 'panel.' + name + ' = act' + exec(stmt + '\n') + if is_endgroup(a): + panel.endgroup() + sub_al = getattrlist(a, 'al') + if sub_al: + build_subactuators(panel, act, sub_al) + # + return panel # Wrapper around pnl.dopanel() which calls call-back functions. # def my_dopanel(): - # Extract only the first 4 elements to allow for future expansion - a, down, active, up = pnl.dopanel()[:4] - if down: - down.downfunc(down) - if active: - active.activefunc(active) - if up: - up.upfunc(up) - return a + # Extract only the first 4 elements to allow for future expansion + a, down, active, up = pnl.dopanel()[:4] + if down: + down.downfunc(down) + if active: + active.activefunc(active) + if up: + up.upfunc(up) + return a # Create one or more panels from a description file (S-expressions) # generated by the Panel Editor. -# +# def defpanellist(file): - import panelparser - descrlist = panelparser.parse_file(open(file, 'r')) - panellist = [] - for descr in descrlist: - panellist.append(build_panel(descr)) - return panellist + import panelparser + descrlist = panelparser.parse_file(open(file, 'r')) + panellist = [] + for descr in descrlist: + panellist.append(build_panel(descr)) + return panellist # Import everything from built-in method pnl, so the user can always # use panel.foo() instead of pnl.foo(). # This gives *no* performance penalty once this module is imported. # -from pnl import * # for export +from pnl import * # for export -dopanel = my_dopanel # override pnl.dopanel +dopanel = my_dopanel # override pnl.dopanel diff --git a/lib/panelparser.py b/lib/panelparser.py index 5eb2f2b..9c9ee02 100644 --- a/lib/panelparser.py +++ b/lib/panelparser.py @@ -15,47 +15,47 @@ separators = operators + whitespace + ';' + '"' # Return a list of tokens (strings). # def tokenize_string(s): - tokens = [] - while s: - c = s[:1] - if c in whitespace: - s = s[1:] - elif c = ';': - s = '' - elif c = '"': - n = len(s) - i = 1 - while i < n: - c = s[i] - i = i+1 - if c = '"': break - if c = '\\': i = i+1 - tokens.append(s[:i]) - s = s[i:] - elif c in operators: - tokens.append(c) - s = s[1:] - else: - n = len(s) - i = 1 - while i < n: - if s[i] in separators: break - i = i+1 - tokens.append(s[:i]) - s = s[i:] - return tokens + tokens = [] + while s: + c = s[:1] + if c in whitespace: + s = s[1:] + elif c = ';': + s = '' + elif c = '"': + n = len(s) + i = 1 + while i < n: + c = s[i] + i = i+1 + if c = '"': break + if c = '\\': i = i+1 + tokens.append(s[:i]) + s = s[i:] + elif c in operators: + tokens.append(c) + s = s[1:] + else: + n = len(s) + i = 1 + while i < n: + if s[i] in separators: break + i = i+1 + tokens.append(s[:i]) + s = s[i:] + return tokens # Tokenize a whole file (given as file object, not as file name). # Return a list of tokens (strings). # def tokenize_file(fp): - tokens = [] - while 1: - line = fp.readline() - if not line: break - tokens = tokens + tokenize_string(line) - return tokens + tokens = [] + while 1: + line = fp.readline() + if not line: break + tokens = tokens + tokenize_string(line) + return tokens # Exception raised by parse_exr. @@ -71,50 +71,50 @@ syntax_error = 'syntax error' # May raise syntax_error. # def parse_expr(tokens): - if (not tokens) or tokens[0] <> '(': - raise syntax_error, 'expected "("' - tokens = tokens[1:] - expr = [] - while 1: - if not tokens: - raise syntax_error, 'missing ")"' - if tokens[0] = ')': - return expr, tokens[1:] - elif tokens[0] = '(': - subexpr, tokens = parse_expr(tokens) - expr.append(subexpr) - else: - expr.append(tokens[0]) - tokens = tokens[1:] + if (not tokens) or tokens[0] <> '(': + raise syntax_error, 'expected "("' + tokens = tokens[1:] + expr = [] + while 1: + if not tokens: + raise syntax_error, 'missing ")"' + if tokens[0] = ')': + return expr, tokens[1:] + elif tokens[0] = '(': + subexpr, tokens = parse_expr(tokens) + expr.append(subexpr) + else: + expr.append(tokens[0]) + tokens = tokens[1:] # Parse a file (given as file object, not as file name). # Return a list of parsed S-expressions found at the top level. # def parse_file(fp): - tokens = tokenize_file(fp) - exprlist = [] - while tokens: - expr, tokens = parse_expr(tokens) - exprlist.append(expr) - return exprlist + tokens = tokenize_file(fp) + exprlist = [] + while tokens: + expr, tokens = parse_expr(tokens) + exprlist.append(expr) + return exprlist # EXAMPLE: # # The input -# '(hip (hop hur-ray))' +# '(hip (hop hur-ray))' # # passed to tokenize_string() returns the token list -# ['(', 'hip', '(', 'hop', 'hur-ray', ')', ')'] +# ['(', 'hip', '(', 'hop', 'hur-ray', ')', ')'] # # When this is passed to parse_expr() it returns the expression -# ['hip', ['hop', 'hur-ray']] +# ['hip', ['hop', 'hur-ray']] # plus an empty token list (because there are no tokens left. # # When a file containing the example is passed to parse_file() it returns # a list whose only element is the output of parse_expr() above: -# [['hip', ['hop', 'hur-ray']]] +# [['hip', ['hop', 'hur-ray']]] # TOKENIZING: @@ -123,6 +123,6 @@ def parse_file(fp): # # Tokens are separated by whitespace, except the following characters # always form a separate token (outside strings): -# ( ) ' +# ( ) ' # Strings are enclosed in double quotes (") and backslash (\) is used # as escape character in strings. diff --git a/lib/path.py b/lib/path.py index be2340f..0c0d09f 100644 --- a/lib/path.py +++ b/lib/path.py @@ -10,86 +10,86 @@ import stat # (begins with '/'). # def cat(a, b): - if b[:1] = '/': return b - if a = '' or a[-1:] = '/': return a + b - return a + '/' + b + if b[:1] = '/': return b + if a = '' or a[-1:] = '/': return a + b + return a + '/' + b # Split a path in head (empty or ending in '/') and tail (no '/'). # The tail will be empty if the path ends in '/'. # def split(p): - head, tail = '', '' - for c in p: - tail = tail + c - if c = '/': - head, tail = head + tail, '' - return head, tail + head, tail = '', '' + for c in p: + tail = tail + c + if c = '/': + head, tail = head + tail, '' + return head, tail # Return the tail (basename) part of a path. # def basename(p): - return split(p)[1] + return split(p)[1] # Return the longest prefix of all list elements. # def commonprefix(m): - if not m: return '' - prefix = m[0] - for item in m: - for i in range(len(prefix)): - if prefix[:i+1] <> item[:i+1]: - prefix = prefix[:i] - if i = 0: return '' - break - return prefix + if not m: return '' + prefix = m[0] + for item in m: + for i in range(len(prefix)): + if prefix[:i+1] <> item[:i+1]: + prefix = prefix[:i] + if i = 0: return '' + break + return prefix # Does a file/directory exist? # def exists(path): - try: - st = posix.stat(path) - except posix.error: - return 0 - return 1 + try: + st = posix.stat(path) + except posix.error: + return 0 + return 1 # Is a path a posix directory? # def isdir(path): - try: - st = posix.stat(path) - except posix.error: - return 0 - return stat.S_ISDIR(st[stat.ST_MODE]) + try: + st = posix.stat(path) + except posix.error: + return 0 + return stat.S_ISDIR(st[stat.ST_MODE]) # Is a path a symbolic link? # This will always return false on systems where posix.lstat doesn't exist. # def islink(path): - try: - st = posix.lstat(path) - except (posix.error, NameError): - return 0 - return stat.S_ISLNK(st[stat.ST_MODE]) + try: + st = posix.lstat(path) + except (posix.error, NameError): + return 0 + return stat.S_ISLNK(st[stat.ST_MODE]) _mounts = [] def _getmounts(): - import commands, string - mounts = [] - data = commands.getoutput('/etc/mount') - lines = string.splitfields(data, '\n') - for line in lines: - words = string.split(line) - if len(words) >= 3 and words[1] = 'on': - mounts.append(words[2]) - return mounts + import commands, string + mounts = [] + data = commands.getoutput('/etc/mount') + lines = string.splitfields(data, '\n') + for line in lines: + words = string.split(line) + if len(words) >= 3 and words[1] = 'on': + mounts.append(words[2]) + return mounts # Is a path a mount point? @@ -98,9 +98,9 @@ def _getmounts(): # Sorry. # def ismount(path): - if not _mounts: - _mounts[:] = _getmounts() - return path in _mounts + if not _mounts: + _mounts[:] = _getmounts() + return path in _mounts # Directory tree walk. @@ -112,14 +112,14 @@ def ismount(path): # or to impose a different order of visiting. # def walk(top, func, arg): - try: - names = posix.listdir(top) - except posix.error: - return - func(arg, top, names) - exceptions = ('.', '..') - for name in names: - if name not in exceptions: - name = cat(top, name) - if isdir(name): - walk(name, func, arg) + try: + names = posix.listdir(top) + except posix.error: + return + func(arg, top, names) + exceptions = ('.', '..') + for name in names: + if name not in exceptions: + name = cat(top, name) + if isdir(name): + walk(name, func, arg) diff --git a/lib/poly.py b/lib/poly.py index a7c24ec..abac4c8 100644 --- a/lib/poly.py +++ b/lib/poly.py @@ -6,50 +6,50 @@ # taken out by normalize(). def normalize(p): # Strip unnecessary zero coefficients - n = len(p) - while p: - if p[n-1]: return p[:n] - n = n-1 - return [] + n = len(p) + while p: + if p[n-1]: return p[:n] + n = n-1 + return [] def plus(a, b): - if len(a) < len(b): a, b = b, a # make sure a is the longest - res = a[:] # make a copy - for i in range(len(b)): - res[i] = res[i] + b[i] - return normalize(res) + if len(a) < len(b): a, b = b, a # make sure a is the longest + res = a[:] # make a copy + for i in range(len(b)): + res[i] = res[i] + b[i] + return normalize(res) def minus(a, b): - if len(a) < len(b): a, b = b, a # make sure a is the longest - res = a[:] # make a copy - for i in range(len(b)): - res[i] = res[i] - b[i] - return normalize(res) + if len(a) < len(b): a, b = b, a # make sure a is the longest + res = a[:] # make a copy + for i in range(len(b)): + res[i] = res[i] - b[i] + return normalize(res) def one(power, coeff): # Representation of coeff * x**power - res = [] - for i in range(power): res.append(0) - return res + [coeff] + res = [] + for i in range(power): res.append(0) + return res + [coeff] def times(a, b): - res = [] - for i in range(len(a)): - for j in range(len(b)): - res = plus(res, one(i+j, a[i]*b[j])) - return res + res = [] + for i in range(len(a)): + for j in range(len(b)): + res = plus(res, one(i+j, a[i]*b[j])) + return res def power(a, n): # Raise polynomial a to the positive integral power n - if n = 0: return [1] - if n = 1: return a - if n/2*2 = n: - b = power(a, n/2) - return times(b, b) - return times(power(a, n-1), a) + if n = 0: return [1] + if n = 1: return a + if n/2*2 = n: + b = power(a, n/2) + return times(b, b) + return times(power(a, n-1), a) def der(a): # First derivative - res = a[1:] - for i in range(len(res)): - res[i] = res[i] * (i+1) - return res + res = a[1:] + for i in range(len(res)): + res[i] = res[i] * (i+1) + return res # Computing a primitive function would require rational arithmetic... diff --git a/lib/rand.py b/lib/rand.py index 0ca1a53..0616483 100644 --- a/lib/rand.py +++ b/lib/rand.py @@ -3,10 +3,10 @@ import whrandom def srand(seed): - whrandom.seed(seed%256, seed/256%256, seed/6