From a19a216bc60160c162e616145ef091dd18ce4e61 Mon Sep 17 00:00:00 2001 From: Skip Montanaro Date: Tue, 16 Feb 2021 14:40:46 -0600 Subject: Python 0.9.1 as posted in alt.sources --- README | 71 + demo/README | 22 + demo/scripts/findlinksto.py | 29 + demo/scripts/mkreal.py | 65 + demo/scripts/ptags.py | 66 + demo/scripts/suff.py | 29 + demo/scripts/xxci.py | 77 + demo/sgi/README | 15 + demo/sgi/audio/README | 5 + demo/sgi/audio/play.py | 75 + demo/sgi/audio_stdwin/README | 16 + demo/sgi/audio_stdwin/jukebox.py | 321 ++++ demo/sgi/audio_stdwin/rec.py | 271 +++ demo/sgi/audio_stdwin/vumeter.py | 35 + demo/sgi/gl/README | 22 + demo/sgi/gl/backface.py | 140 ++ demo/sgi/gl/kites.py | 194 +++ demo/sgi/gl/mclock.doc | 60 + demo/sgi/gl/mclock.py | 729 ++++++++ demo/sgi/gl/mixing.py | 116 ++ demo/sgi/gl/nurbs.py | 171 ++ demo/sgi/gl/zrgb.py | 169 ++ demo/sgi/gl_panel/README | 23 + demo/sgi/gl_panel/apanel/apanel.py | 63 + demo/sgi/gl_panel/apanel/apanel.s | 76 + demo/sgi/gl_panel/flying/data.py | 42 + demo/sgi/gl_panel/flying/flying.py | 375 +++++ demo/sgi/gl_panel/flying/flying.s | 140 ++ demo/sgi/gl_panel/flying/freeze.s | 31 + demo/sgi/gl_panel/flying/light.py | 46 + demo/sgi/gl_panel/flying/light.s | 94 ++ demo/sgi/gl_panel/flying/material.py | 26 + demo/sgi/gl_panel/flying/materials.s | 161 ++ demo/sgi/gl_panel/flying/objdict.py | 41 + demo/sgi/gl_panel/flying/objectdef.py | 147 ++ demo/sgi/gl_panel/flying/panel.s | 76 + demo/sgi/gl_panel/nurbs/nurbs.py | 196 +++ demo/sgi/gl_panel/nurbs/nurbs.s | 81 + demo/sgi/gl_panel/nurbs/nurbsdata.py | 82 + demo/sgi/gl_panel/twoview/block.py | 73 + demo/sgi/gl_panel/twoview/camera.s | 55 + demo/sgi/gl_panel/twoview/observer.s | 98 ++ demo/sgi/gl_panel/twoview/topview.s | 47 + demo/sgi/gl_panel/twoview/twoview.py | 395 +++++ demo/stdwin/wdiff.py | 480 ++++++ doc/Makefile | 47 + doc/README | 24 + doc/SetClass.py | 17 + doc/fibo.py | 15 + doc/mod.tex | 62 + doc/mod1.tex | 521 ++++++ doc/mod2.tex | 1083 ++++++++++++ doc/mod3.tex | 484 ++++++ doc/myformat.sty | 34 + doc/pytry | 20 + doc/tut.tex | 1550 +++++++++++++++++ lib/Abstract.py | 61 + lib/Buttons.py | 399 +++++ lib/CSplit.py | 70 + lib/DEVICE.py | 423 +++++ lib/GL.py | 365 ++++ lib/HVSplit.py | 56 + lib/Histogram.py | 36 + lib/Sliders.py | 175 ++ lib/Soundogram.py | 36 + lib/Split.py | 116 ++ lib/StripChart.py | 68 + lib/Tcl.py | 421 +++++ lib/TclShell.py | 255 +++ lib/TclUtil.py | 377 +++++ lib/TestCSplit.py | 26 + lib/TransParent.py | 96 ++ lib/VUMeter.py | 47 + lib/WindowParent.py | 101 ++ lib/adv.py | 366 ++++ lib/anywin.py | 14 + lib/auds.py | 106 ++ lib/calendar.py | 213 +++ lib/clock.py | 202 +++ lib/cmp.py | 61 + lib/cmpcache.py | 68 + lib/commands.py | 77 + lib/dircache.py | 36 + lib/dircmp.py | 205 +++ lib/dirwin.py | 29 + lib/dis.py | 176 ++ lib/dump.py | 63 + lib/fact.py | 37 + lib/filewin.py | 18 + lib/fnmatch.py | 35 + lib/getopt.py | 47 + lib/glob.py | 44 + lib/grep.py | 32 + lib/gwin.py | 122 ++ lib/lambda.py | 151 ++ lib/listwin.py | 47 + lib/localtime.py | 53 + lib/maccache.py | 61 + lib/macglob.py | 46 + lib/macpath.py | 108 ++ lib/macshell.py | 399 +++++ lib/minmax.py | 6 + lib/packmail.py | 48 + lib/panel.py | 281 ++++ lib/panelparser.py | 128 ++ lib/path.py | 125 ++ lib/poly.py | 55 + lib/rand.py | 12 + lib/rect.py | 88 + lib/selection.py | 72 + lib/shutil.py | 70 + lib/stat.py | 57 + lib/statcache.py | 86 + lib/stdwinevents.py | 46 + lib/stdwinsupport.py | 34 + lib/string.py | 129 ++ lib/sunaudio.py | 54 + lib/tablewin.py | 237 +++ lib/tb.py | 220 +++ lib/testall.py | 416 +++++ lib/textwin.py | 119 ++ lib/util.py | 30 + lib/whrandom.py | 74 + lib/zmod.py | 94 ++ python.man | 79 + shar/python-0.9.1-01-21.shar | 1952 ++++++++++++++++++++++ shar/python-0.9.1-01.patch | 163 ++ shar/python-0.9.1-03-21.shar | 2944 +++++++++++++++++++++++++++++++++ shar/python-0.9.1-04-21.shar | 2755 ++++++++++++++++++++++++++++++ shar/python-0.9.1-05-21.shar | 2528 ++++++++++++++++++++++++++++ shar/python-0.9.1-06-21.shar | 2510 ++++++++++++++++++++++++++++ shar/python-0.9.1-07-21.shar | 2518 ++++++++++++++++++++++++++++ shar/python-0.9.1-08-21.shar | 2349 ++++++++++++++++++++++++++ shar/python-0.9.1-09-21.shar | 2688 ++++++++++++++++++++++++++++++ shar/python-0.9.1-10-21.shar | 2508 ++++++++++++++++++++++++++++ shar/python-0.9.1-11-21.shar | 2618 +++++++++++++++++++++++++++++ shar/python-0.9.1-12-21.shar | 2833 +++++++++++++++++++++++++++++++ shar/python-0.9.1-13-21.shar | 2811 +++++++++++++++++++++++++++++++ shar/python-0.9.1-14-21.shar | 2720 ++++++++++++++++++++++++++++++ shar/python-0.9.1-15-21.shar | 2539 ++++++++++++++++++++++++++++ shar/python-0.9.1-16-21.shar | 2495 ++++++++++++++++++++++++++++ shar/python-0.9.1-17-21.shar | 2464 +++++++++++++++++++++++++++ shar/python-0.9.1-18-21.shar | 2268 +++++++++++++++++++++++++ shar/python-0.9.1-19-21.shar | 1997 ++++++++++++++++++++++ shar/python-0.9.1-20-21.shar | 1941 ++++++++++++++++++++++ shar/python-0.9.1-21-21.shar | 1675 +++++++++++++++++++ src/Grammar | 72 + src/Makefile | 508 ++++++ src/PROTO.h | 79 + src/README | 11 + src/To.do | 11 + src/acceler.c | 136 ++ src/allobjects.h | 50 + src/amoebamodule.c | 774 +++++++++ src/asa.c | 494 ++++++ src/asa.h | 33 + src/assert.h | 25 + src/audiomodule.c | 615 +++++++ src/bitset.c | 99 ++ src/bitset.h | 46 + src/bltinmodule.c | 559 +++++++ src/bltinmodule.h | 27 + src/ceval.c | 1436 ++++++++++++++++ src/ceval.h | 33 + src/cgen | 458 +++++ src/cgensupport.c | 393 +++++ src/cgensupport.h | 39 + src/classobject.c | 298 ++++ src/classobject.h | 44 + src/compile.c | 1772 ++++++++++++++++++++ src/compile.h | 47 + src/config.c | 180 ++ src/configmac.c | 109 ++ src/cstubs | 999 +++++++++++ src/dictobject.c | 605 +++++++ src/dictobject.h | 44 + src/errcode.h | 36 + src/errors.c | 196 +++ src/errors.h | 58 + src/fgetsintr.c | 94 ++ src/fgetsintr.h | 25 + src/fileobject.c | 293 ++++ src/fileobject.h | 33 + src/firstsets.c | 133 ++ src/floatobject.c | 271 +++ src/floatobject.h | 44 + src/fmod.c | 51 + src/frameobject.c | 156 ++ src/frameobject.h | 80 + src/funcobject.c | 113 ++ src/funcobject.h | 33 + src/getcwd.c | 102 ++ src/graminit.c | 1094 ++++++++++++ src/graminit.h | 66 + src/grammar.c | 233 +++ src/grammar.h | 105 ++ src/grammar1.c | 75 + src/import.c | 259 +++ src/import.h | 31 + src/intobject.c | 307 ++++ src/intobject.h | 72 + src/intrcheck.c | 144 ++ src/listnode.c | 93 ++ src/listobject.c | 519 ++++++ src/listobject.h | 59 + src/macmodule.c | 246 +++ src/malloc.h | 63 + src/mathmodule.c | 180 ++ src/metagrammar.c | 176 ++ src/metagrammar.h | 30 + src/methodobject.c | 147 ++ src/methodobject.h | 42 + src/modsupport.c | 381 +++++ src/modsupport.h | 27 + src/moduleobject.c | 154 ++ src/moduleobject.h | 33 + src/node.c | 100 ++ src/node.h | 58 + src/object.c | 290 ++++ src/object.h | 324 ++++ src/objimpl.h | 50 + src/opcode.h | 109 ++ src/panelmodule.c | 1090 ++++++++++++ src/parser.c | 423 +++++ src/parser.h | 50 + src/parsetok.c | 158 ++ src/parsetok.h | 29 + src/patchlevel.h | 1 + src/pgen.c | 751 +++++++++ src/pgen.h | 30 + src/pgenheaders.h | 50 + src/pgenmain.c | 148 ++ src/posixmodule.c | 427 +++++ src/printgrammar.c | 149 ++ src/profmain.c | 133 ++ src/pythonmain.c | 440 +++++ src/pythonrun.h | 47 + src/regexp.c | 1394 ++++++++++++++++ src/regexp.h | 51 + src/regexpmodule.c | 191 +++ src/regmagic.h | 29 + src/regsub.c | 115 ++ src/rltokenizer.c | 26 + src/sc_errors.c | 145 ++ src/sc_errors.h | 41 + src/sc_global.h | 137 ++ src/sc_interpr.c | 1352 +++++++++++++++ src/scdbg.c | 152 ++ src/sigtype.h | 51 + src/stdwinmodule.c | 1697 +++++++++++++++++++ src/stdwinobject.h | 31 + src/strdup.c | 39 + src/strerror.c | 47 + src/stringobject.c | 347 ++++ src/stringobject.h | 63 + src/strtol.c | 122 ++ src/structmember.c | 158 ++ src/structmember.h | 64 + src/stubcode.h | 28 + src/sysmodule.c | 214 +++ src/sysmodule.h | 30 + src/timemodule.c | 229 +++ src/token.h | 69 + src/tokenizer.c | 523 ++++++ src/tokenizer.h | 53 + src/traceback.c | 217 +++ src/traceback.h | 30 + src/tupleobject.c | 287 ++++ src/tupleobject.h | 56 + src/typeobject.c | 61 + src/xxobject.c | 131 ++ 271 files changed, 96470 insertions(+) create mode 100644 README create mode 100644 demo/README create mode 100755 demo/scripts/findlinksto.py create mode 100755 demo/scripts/mkreal.py create mode 100755 demo/scripts/ptags.py create mode 100755 demo/scripts/suff.py create mode 100755 demo/scripts/xxci.py create mode 100644 demo/sgi/README create mode 100644 demo/sgi/audio/README create mode 100755 demo/sgi/audio/play.py create mode 100644 demo/sgi/audio_stdwin/README create mode 100755 demo/sgi/audio_stdwin/jukebox.py create mode 100755 demo/sgi/audio_stdwin/rec.py create mode 100755 demo/sgi/audio_stdwin/vumeter.py create mode 100644 demo/sgi/gl/README create mode 100755 demo/sgi/gl/backface.py create mode 100755 demo/sgi/gl/kites.py create mode 100644 demo/sgi/gl/mclock.doc create mode 100755 demo/sgi/gl/mclock.py create mode 100755 demo/sgi/gl/mixing.py create mode 100755 demo/sgi/gl/nurbs.py create mode 100755 demo/sgi/gl/zrgb.py create mode 100644 demo/sgi/gl_panel/README create mode 100755 demo/sgi/gl_panel/apanel/apanel.py create mode 100644 demo/sgi/gl_panel/apanel/apanel.s create mode 100644 demo/sgi/gl_panel/flying/data.py create mode 100755 demo/sgi/gl_panel/flying/flying.py create mode 100644 demo/sgi/gl_panel/flying/flying.s create mode 100644 demo/sgi/gl_panel/flying/freeze.s create mode 100644 demo/sgi/gl_panel/flying/light.py create mode 100644 demo/sgi/gl_panel/flying/light.s create mode 100644 demo/sgi/gl_panel/flying/material.py create mode 100644 demo/sgi/gl_panel/flying/materials.s create mode 100644 demo/sgi/gl_panel/flying/objdict.py create mode 100644 demo/sgi/gl_panel/flying/objectdef.py create mode 100644 demo/sgi/gl_panel/flying/panel.s create mode 100755 demo/sgi/gl_panel/nurbs/nurbs.py create mode 100644 demo/sgi/gl_panel/nurbs/nurbs.s create mode 100644 demo/sgi/gl_panel/nurbs/nurbsdata.py create mode 100644 demo/sgi/gl_panel/twoview/block.py create mode 100644 demo/sgi/gl_panel/twoview/camera.s create mode 100644 demo/sgi/gl_panel/twoview/observer.s create mode 100644 demo/sgi/gl_panel/twoview/topview.s create mode 100755 demo/sgi/gl_panel/twoview/twoview.py create mode 100755 demo/stdwin/wdiff.py create mode 100644 doc/Makefile create mode 100644 doc/README create mode 100644 doc/SetClass.py create mode 100644 doc/fibo.py create mode 100644 doc/mod.tex create mode 100644 doc/mod1.tex create mode 100644 doc/mod2.tex create mode 100644 doc/mod3.tex create mode 100644 doc/myformat.sty create mode 100755 doc/pytry create mode 100644 doc/tut.tex create mode 100644 lib/Abstract.py create mode 100644 lib/Buttons.py create mode 100644 lib/CSplit.py create mode 100644 lib/DEVICE.py create mode 100644 lib/GL.py create mode 100644 lib/HVSplit.py create mode 100644 lib/Histogram.py create mode 100644 lib/Sliders.py create mode 100644 lib/Soundogram.py create mode 100644 lib/Split.py create mode 100644 lib/StripChart.py create mode 100644 lib/Tcl.py create mode 100644 lib/TclShell.py create mode 100644 lib/TclUtil.py create mode 100644 lib/TestCSplit.py create mode 100644 lib/TransParent.py create mode 100644 lib/VUMeter.py create mode 100644 lib/WindowParent.py create mode 100644 lib/adv.py create mode 100644 lib/anywin.py create mode 100644 lib/auds.py create mode 100644 lib/calendar.py create mode 100644 lib/clock.py create mode 100644 lib/cmp.py create mode 100644 lib/cmpcache.py create mode 100644 lib/commands.py create mode 100644 lib/dircache.py create mode 100644 lib/dircmp.py create mode 100644 lib/dirwin.py create mode 100644 lib/dis.py create mode 100644 lib/dump.py create mode 100644 lib/fact.py create mode 100644 lib/filewin.py create mode 100644 lib/fnmatch.py create mode 100644 lib/getopt.py create mode 100644 lib/glob.py create mode 100644 lib/grep.py create mode 100644 lib/gwin.py create mode 100644 lib/lambda.py create mode 100644 lib/listwin.py create mode 100644 lib/localtime.py create mode 100644 lib/maccache.py create mode 100644 lib/macglob.py create mode 100644 lib/macpath.py create mode 100644 lib/macshell.py create mode 100644 lib/minmax.py create mode 100644 lib/packmail.py create mode 100644 lib/panel.py create mode 100644 lib/panelparser.py create mode 100644 lib/path.py create mode 100644 lib/poly.py create mode 100644 lib/rand.py create mode 100644 lib/rect.py create mode 100644 lib/selection.py create mode 100644 lib/shutil.py create mode 100644 lib/stat.py create mode 100644 lib/statcache.py create mode 100644 lib/stdwinevents.py create mode 100644 lib/stdwinsupport.py create mode 100644 lib/string.py create mode 100644 lib/sunaudio.py create mode 100644 lib/tablewin.py create mode 100644 lib/tb.py create mode 100644 lib/testall.py create mode 100644 lib/textwin.py create mode 100644 lib/util.py create mode 100644 lib/whrandom.py create mode 100644 lib/zmod.py create mode 100644 python.man create mode 100644 shar/python-0.9.1-01-21.shar create mode 100644 shar/python-0.9.1-01.patch create mode 100644 shar/python-0.9.1-03-21.shar create mode 100644 shar/python-0.9.1-04-21.shar create mode 100644 shar/python-0.9.1-05-21.shar create mode 100644 shar/python-0.9.1-06-21.shar create mode 100644 shar/python-0.9.1-07-21.shar create mode 100644 shar/python-0.9.1-08-21.shar create mode 100644 shar/python-0.9.1-09-21.shar create mode 100644 shar/python-0.9.1-10-21.shar create mode 100644 shar/python-0.9.1-11-21.shar create mode 100644 shar/python-0.9.1-12-21.shar create mode 100644 shar/python-0.9.1-13-21.shar create mode 100644 shar/python-0.9.1-14-21.shar create mode 100644 shar/python-0.9.1-15-21.shar create mode 100644 shar/python-0.9.1-16-21.shar create mode 100644 shar/python-0.9.1-17-21.shar create mode 100644 shar/python-0.9.1-18-21.shar create mode 100644 shar/python-0.9.1-19-21.shar create mode 100644 shar/python-0.9.1-20-21.shar create mode 100644 shar/python-0.9.1-21-21.shar create mode 100644 src/Grammar create mode 100644 src/Makefile create mode 100644 src/PROTO.h create mode 100644 src/README create mode 100644 src/To.do create mode 100644 src/acceler.c create mode 100644 src/allobjects.h create mode 100644 src/amoebamodule.c create mode 100644 src/asa.c create mode 100644 src/asa.h create mode 100644 src/assert.h create mode 100644 src/audiomodule.c create mode 100644 src/bitset.c create mode 100644 src/bitset.h create mode 100644 src/bltinmodule.c create mode 100644 src/bltinmodule.h create mode 100644 src/ceval.c create mode 100644 src/ceval.h create mode 100644 src/cgen create mode 100644 src/cgensupport.c create mode 100644 src/cgensupport.h create mode 100644 src/classobject.c create mode 100644 src/classobject.h create mode 100644 src/compile.c create mode 100644 src/compile.h create mode 100644 src/config.c create mode 100644 src/configmac.c create mode 100644 src/cstubs create mode 100644 src/dictobject.c create mode 100644 src/dictobject.h create mode 100644 src/errcode.h create mode 100644 src/errors.c create mode 100644 src/errors.h create mode 100644 src/fgetsintr.c create mode 100644 src/fgetsintr.h create mode 100644 src/fileobject.c create mode 100644 src/fileobject.h create mode 100644 src/firstsets.c create mode 100644 src/floatobject.c create mode 100644 src/floatobject.h create mode 100644 src/fmod.c create mode 100644 src/frameobject.c create mode 100644 src/frameobject.h create mode 100644 src/funcobject.c create mode 100644 src/funcobject.h create mode 100644 src/getcwd.c create mode 100644 src/graminit.c create mode 100644 src/graminit.h create mode 100644 src/grammar.c create mode 100644 src/grammar.h create mode 100644 src/grammar1.c create mode 100644 src/import.c create mode 100644 src/import.h create mode 100644 src/intobject.c create mode 100644 src/intobject.h create mode 100644 src/intrcheck.c create mode 100644 src/listnode.c create mode 100644 src/listobject.c create mode 100644 src/listobject.h create mode 100644 src/macmodule.c create mode 100644 src/malloc.h create mode 100644 src/mathmodule.c create mode 100644 src/metagrammar.c create mode 100644 src/metagrammar.h create mode 100644 src/methodobject.c create mode 100644 src/methodobject.h create mode 100644 src/modsupport.c create mode 100644 src/modsupport.h create mode 100644 src/moduleobject.c create mode 100644 src/moduleobject.h create mode 100644 src/node.c create mode 100644 src/node.h create mode 100644 src/object.c create mode 100644 src/object.h create mode 100644 src/objimpl.h create mode 100644 src/opcode.h create mode 100644 src/panelmodule.c create mode 100644 src/parser.c create mode 100644 src/parser.h create mode 100644 src/parsetok.c create mode 100644 src/parsetok.h create mode 100644 src/patchlevel.h create mode 100644 src/pgen.c create mode 100644 src/pgen.h create mode 100644 src/pgenheaders.h create mode 100644 src/pgenmain.c create mode 100644 src/posixmodule.c create mode 100644 src/printgrammar.c create mode 100644 src/profmain.c create mode 100644 src/pythonmain.c create mode 100644 src/pythonrun.h create mode 100644 src/regexp.c create mode 100644 src/regexp.h create mode 100644 src/regexpmodule.c create mode 100644 src/regmagic.h create mode 100644 src/regsub.c create mode 100644 src/rltokenizer.c create mode 100644 src/sc_errors.c create mode 100644 src/sc_errors.h create mode 100644 src/sc_global.h create mode 100644 src/sc_interpr.c create mode 100644 src/scdbg.c create mode 100644 src/sigtype.h create mode 100644 src/stdwinmodule.c create mode 100644 src/stdwinobject.h create mode 100644 src/strdup.c create mode 100644 src/strerror.c create mode 100644 src/stringobject.c create mode 100644 src/stringobject.h create mode 100644 src/strtol.c create mode 100644 src/structmember.c create mode 100644 src/structmember.h create mode 100644 src/stubcode.h create mode 100644 src/sysmodule.c create mode 100644 src/sysmodule.h create mode 100644 src/timemodule.c create mode 100644 src/token.h create mode 100644 src/tokenizer.c create mode 100644 src/tokenizer.h create mode 100644 src/traceback.c create mode 100644 src/traceback.h create mode 100644 src/tupleobject.c create mode 100644 src/tupleobject.h create mode 100644 src/typeobject.c create mode 100644 src/xxobject.c diff --git a/README b/README new file mode 100644 index 0000000..5fe1ff7 --- /dev/null +++ b/README @@ -0,0 +1,71 @@ +This is Python, an extensible interpreted programming language that +combines remarkable power with very clear syntax. + +This is version 0.9 (the first beta release), patchlevel 1. + +Python can be used instead of shell, Awk or Perl scripts, to write +prototypes of real applications, or as an extension language of large +systems, you name it. There are built-in modules that interface to +the operating system and to various window systems: X11, the Mac +window system (you need STDWIN for these two), and Silicon Graphics' +GL library. It runs on most modern versions of UNIX, on the Mac, and +I wouldn't be surprised if it ran on MS-DOS unchanged. I developed it +mostly on an SGI IRIS workstation (using IRIX 3.1 and 3.2) and on the +Mac, but have tested it also on SunOS (4.1) and BSD 4.3 (tahoe). + +Building and installing Python is easy (but do read the Makefile). +A UNIX style manual page and extensive documentation (in LaTeX format) +are provided. (In the beta release, the documentation is still under +development.) + +Please try it out and send me your comments (on anything -- the +language design, implementation, portability, installation, +documentation) and the modules you wrote for it, to make the first +real release better. If you needed to hack the source to get it to +compile and run on a particular machine, send me the fixes -- I'll try +to incorporate them into the next patch. If you can't get it to work +at all, send me a *detailed* description of the problem and I may look +into it. + +If you want to profit of the X11 or Mac window interface, you'll need +STDWIN. This is a portable window system interface by the same +author. The versions of STDWIN floating around on some archives are +not sufficiently up-to-date for use with Python. I will distribute +the latest and greatest STDWIN version at about the same time as Python. + +I am the author of Python: + + Guido van Rossum + CWI, dept. CST + Kruislaan 413 + 1098 SJ Amsterdam + The Netherlands + + E-mail: gu...@cwi.nl + +The Python source is copyrighted, but you can freely use and copy it +as long as you don't change or remove the copyright: + +/*********************************************************** +Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The +Netherlands. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +******************************************************************/ diff --git a/demo/README b/demo/README new file mode 100644 index 0000000..a9ff224 --- /dev/null +++ b/demo/README @@ -0,0 +1,22 @@ +This directory contains various demonstrations of what you can do with +Python. The demos are grouped sub(sub*)directories according to +required optional built-in modules. + +scripts Some useful Python scripts that I put in my bin + directory. No optional built-in modules meeded. + +sgi Demos that only run on Silicon Graphics machines. + Require the built-in modules 'audio' and/or 'gl'. + +stdwin Demos that use the STDWIN library. Require the 'stdwin' + built-in module. + +WARNING: some scripts are executable and have a first line saying + + #! /ufs/guido/bin/sgi/python + +This is unlikely to give good results anywhere else except in my +office. Edit the first line before installing such scripts; to try +them out, you can just say "python file.py". (The .py suffix is not +necessary in this case, but makes it possible to debug the modules +interactively by importing them.) diff --git a/demo/scripts/findlinksto.py b/demo/scripts/findlinksto.py new file mode 100755 index 0000000..210441e --- /dev/null +++ b/demo/scripts/findlinksto.py @@ -0,0 +1,29 @@ +#! /ufs/guido/bin/sgi/python + +# findlinksto +# +# find symbolic links to a given path + +import posix, path, sys + +def visit(pattern, dirname, names): + if path.islink(dirname): + names[:] = [] + return + if path.ismount(dirname): + print 'descend into', dirname + n = len(pattern) + for name in names: + name = path.cat(dirname, name) + try: + linkto = posix.readlink(name) + if linkto[:n] = pattern: + print name, '->', linkto + except posix.error: + pass + +def main(pattern, args): + for dirname in args: + path.walk(dirname, visit, pattern) + +main(sys.argv[1], sys.argv[2:]) diff --git a/demo/scripts/mkreal.py b/demo/scripts/mkreal.py new file mode 100755 index 0000000..19fef28 --- /dev/null +++ b/demo/scripts/mkreal.py @@ -0,0 +1,65 @@ +#! /ufs/guido/bin/sgi/python + +# mkreal +# +# turn a symlink to a directory into a real directory + +import sys +import posix +import path +from stat import * + +cat = path.cat + +error = 'mkreal error' + +BUFSIZE = 32*1024 + +def mkrealfile(name): + st = posix.stat(name) # Get the mode + mode = S_IMODE(st[ST_MODE]) + linkto = posix.readlink(name) # Make sure again it's a symlink + f_in = open(name, 'r') # This ensures it's a file + posix.unlink(name) + f_out = open(name, 'w') + while 1: + buf = f_in.read(BUFSIZE) + if not buf: break + f_out.write(buf) + del f_out # Flush data to disk before changing mode + posix.chmod(name, mode) + +def mkrealdir(name): + st = posix.stat(name) # Get the mode + mode = S_IMODE(st[ST_MODE]) + linkto = posix.readlink(name) + files = posix.listdir(name) + posix.unlink(name) + posix.mkdir(name, mode) + posix.chmod(name, mode) + linkto = cat('..', linkto) + # + for file in files: + if file not in ('.', '..'): + posix.symlink(cat(linkto, file), cat(name, file)) + +def main(): + sys.stdout = sys.stderr + progname = path.basename(sys.argv[0]) + args = sys.argv[1:] + if not args: + print 'usage:', progname, 'path ...' + sys.exit(2) + status = 0 + for name in args: + if not path.islink(name): + print progname+':', name+':', 'not a symlink' + status = 1 + else: + if path.isdir(name): + mkrealdir(name) + else: + mkrealfile(name) + sys.exit(status) + +main() diff --git a/demo/scripts/ptags.py b/demo/scripts/ptags.py new file mode 100755 index 0000000..0f99650 --- /dev/null +++ b/demo/scripts/ptags.py @@ -0,0 +1,66 @@ +#! /ufs/guido/bin/sgi/python + +# ptags +# +Create a tags file for Python programs +# Tagged are: +# - functions (even inside other defs or classes) +# - classes +# - filenames +# Warns about files it cannot open. +# No warnings about duplicate tags. + +import sys +import posix +import path +import string + +keywords = ['def', 'class'] # If you add keywords, update starts!!! +starts = 'dc' # Starting characters of keywords + +whitespace = string.whitespace +identchars = string.letters + string.digits + '_' + +tags = [] # Modified! + +def main(): + args = sys.argv[1:] + for file in args: treat_file(file) + if tags: + fp = open('tags', 'w') + tags.sort() + for s in tags: fp.write(s) + +def treat_file(file): + try: + fp = open(file, 'r') + except: + print 'Cannot open', file + return + base = path.basename(file) + if base[-3:] = '.py': base = base[:-3] + s = base + '\t' + file + '\t' + '1\n' + tags.append(s) + while 1: + line = fp.readline() + if not line: break + maketag(line, file) + +def maketag(line, file): + i = 0 + while line[i:i+1] in whitespace: i = i+1 + if line[i:i+1] not in starts: return + n = len(line) + j = i + while i < n and line[i] not in whitespace: i = i+1 + if line[j:i] not in keywords: return + while i < n and line[i] in whitespace: i = i+1 + j = i + while i < n and line[i] in identchars: i = i+1 + name = line[j:i] + while i < n and line[i] in whitespace: i = i+1 + if i < n and line[i] = '(': i = i+1 + s = name + '\t' + file + '\t' + '/^' + line[:i] + '/\n' + tags.append(s) + +main() diff --git a/demo/scripts/suff.py b/demo/scripts/suff.py new file mode 100755 index 0000000..f6bd6bf --- /dev/null +++ b/demo/scripts/suff.py @@ -0,0 +1,29 @@ +#! /ufs/guido/bin/sgi/python + +# suff +# +# show different suffixes amongst arguments + +import sys + +def main(): + files = sys.argv[1:] + suffixes = {} + for file in files: + suff = getsuffix(file) + if not suffixes.has_key(suff): + suffixes[suff] = [] + suffixes[suff].append(file) + keys = suffixes.keys() + keys.sort() + for suff in keys: + print `suff`, len(suffixes[suff]) + +def getsuffix(file): + suff = '' + for i in range(len(file)): + if file[i] = '.': + suff = file[i:] + return suff + +main() diff --git a/demo/scripts/xxci.py b/demo/scripts/xxci.py new file mode 100755 index 0000000..43ea316 --- /dev/null +++ b/demo/scripts/xxci.py @@ -0,0 +1,77 @@ +#! /ufs/guido/bin/sgi/python + +# xxci +# +# check in files for which rcsdiff returns nonzero exit status + +import sys +import posix +import stat +import path +import commands + +MAXSIZE = 200*1024 # Files this big must be binaries and are skipped. + +def getargs(): + args = sys.argv[1:] + if args: + return args + print 'No arguments, checking almost *' + for file in posix.listdir('.'): + if not skipfile(file): + args.append(file) + if not args: + print 'Nothing to do -- exit 1' + sys.exit(1) + args.sort() + return args + +badnames = ['tags', 'xyzzy'] +badprefixes = ['.', ',', '@', '#', 'o.'] +badsuffixes = \ + ['~', '.a', '.o', '.old', '.bak', '.orig', '.new', '.prev', '.not'] +# XXX Should generalize even more to use fnmatch! + +def skipfile(file): + if file in badnames or \ + badprefix(file) or badsuffix(file) or \ + path.islink(file) or path.isdir(file): + return 1 + # Skip huge files -- probably binaries. + try: + st = posix.stat(file) + except posix.error: + return 1 # Doesn't exist -- skip it + return st[stat.ST_SIZE] >= MAXSIZE + +def badprefix(file): + for bad in badprefixes: + if file[:len(bad)] = bad: return 1 + return 0 + +def badsuffix(file): + for bad in badsuffixes: + if file[-len(bad):] = bad: return 1 + return 0 + +def go(args): + for file in args: + print file + ':' + if run('rcsdiff -c', file): + if askyesno('Check in ' + file + ' ? '): + sts = run('rcs -l', file) # ignored + # can't use run() here because it's interactive + sts = posix.system('ci -l ' + file) + +def run(cmd, file): + sts, output = commands.getstatusoutput(cmd + commands.mkarg(file)) + if sts: + print output + print 'Exit status', sts + return sts + +def askyesno(prompt): + s = raw_input(prompt) + return s in ['y', 'yes'] + +go(getargs()) diff --git a/demo/sgi/README b/demo/sgi/README new file mode 100644 index 0000000..5740c22 --- /dev/null +++ b/demo/sgi/README @@ -0,0 +1,15 @@ +Demonstrations of Python that use various features of the Silicon +Graphics IRIS machines. + +audio Demonstrations of the audio capabilities of the 4D/25. + Require the built-in module 'audio'. + +audio_stdwin Window-based demonstrations the audio capabilities of + the 4D/25. Require the built-in modules 'stdwin' and + 'audio'. + +gl Demonstrations of the Graphics Library (GL). + Require the built-in module 'gl'. + +gl_panel Demonstrations of the Panel Library by NASA Ames. + Require the built-in modules 'gl' and 'pnl'. diff --git a/demo/sgi/audio/README b/demo/sgi/audio/README new file mode 100644 index 0000000..17dc9b2 --- /dev/null +++ b/demo/sgi/audio/README @@ -0,0 +1,5 @@ +Programs that demonstrate the use of the audio device on the SGI 4D/25. +These require the built-in module 'audio'. + +play Read a sound sample from a file and play it through the + speaker. Options to set volume, sampling rate etc. diff --git a/demo/sgi/audio/play.py b/demo/sgi/audio/play.py new file mode 100755 index 0000000..8f6a802 --- /dev/null +++ b/demo/sgi/audio/play.py @@ -0,0 +1,75 @@ +#!/ufs/guido/bin/sgi/python + +import sys +import audio + +import string +import getopt +import auds + +debug = [] + +DEF_RATE = 3 + +def main(): + # + gain = 100 + rate = 0 + starter = audio.write + stopper = 0 + # + optlist, args = getopt.getopt(sys.argv[1:], 'adg:r:') + # + for optname, optarg in optlist: + if 0: + pass + elif optname = '-d': + debug.append(1) + elif optname = '-g': + gain = string.atoi(optarg) + if not (0 < gain < 256): + raise optarg.error, '-g gain out of range' + elif optname = '-r': + rate = string.atoi(optarg) + if not (1 <= rate <= 3): + raise optarg.error, '-r rate out of range' + elif optname = '-a': + starter = audio.start_playing + stopper = audio.wait_playing + # + audio.setoutgain(gain) + audio.setrate(rate) + # + if not args: + play(starter, rate, auds.loadfp(sys.stdin)) + else: + real_stopper = 0 + for file in args: + if real_stopper: + real_stopper() + play(starter, rate, auds.load(file)) + real_stopper = stopper + +def play(starter, rate, data): + magic = data[:4] + if magic = '0008': + mrate = 3 + elif magic = '0016': + mrate = 2 + elif magic = '0032': + mrate = 1 + else: + mrate = 0 + if mrate: + data = data[4:] + else: + mrate = DEF_RATE + if not rate: rate = mrate + audio.setrate(rate) + starter(data) + +try: + main() +finally: + audio.setoutgain(0) + audio.done() diff --git a/demo/sgi/audio_stdwin/README b/demo/sgi/audio_stdwin/README new file mode 100644 index 0000000..3074715 --- /dev/null +++ b/demo/sgi/audio_stdwin/README @@ -0,0 +1,16 @@ +Three programs that provide a user interface based upon STDWIN to the +audio device of the SGI 4D/25. These scripts also demonstrate the power +of a set of window interface classes implemented in Python that simplify +the construction of all sorts of buttons, etc. + +jukebox Browses a directory full of sound samples and lets you + play selected ones. (Probably not fully functional, it + requires a conversion program.) + +rec A tape recorder that lets you record a sound sample, + play it back, and save it to a file. Various options to + set sampling rate, volume etc. When idle it doubles + as a VU meter. + +vumeter A VU meter that displays a history of the volume of + sound recently sampled from the microphone. diff --git a/demo/sgi/audio_stdwin/jukebox.py b/demo/sgi/audio_stdwin/jukebox.py new file mode 100755 index 0000000..5267d73 --- /dev/null +++ b/demo/sgi/audio_stdwin/jukebox.py @@ -0,0 +1,321 @@ +#! /ufs/guido/bin/sgi/python + +# JUKEBOX: browse directories full of sampled sound files. +# +# One or more "list windows" display the files and subdirectories of +# the arguments. Double-clicking on a subdirectory opens a new window +# displaying its contents (and so on recursively). Double clicking +# on a file plays it as a sound file (assuming it is one). +# +# Playing is asynchronous: the application keeps listening to events +# while the sample is playing, so you can change the volume (gain) +# during playing, cancel playing or start a new sample right away. +# +# The control window displays the current output gain and a primitive +# "stop button" to cancel the current play request. +# +# Sound files must currently be in Dik Winter's compressed Mac format. +# Since decompression is costly, decompressed samples are saved in +# /usr/tmp/@j* until the application is left. The files are read +# afresh each time, though. + +import audio +import sunaudio +import commands +import getopt +import path +import posix +import rand +import stdwin +from stdwinevents import * +import string +import sys + +from WindowParent import WindowParent +from HVSplit import VSplit +from Buttons import PushButton +from Sliders import ComplexSlider + +# Pathnames + +HOME_BIN_SGI = '/ufs/guido/bin/sgi/' # Directory where macsound2sgi lives +DEF_DB = '/ufs/dik/sounds/Mac/HCOM' # Default directory of sounds + + +# Global variables + +class struct(): pass # Class to define featureless structures + +G = struct() # Holds writable global variables + + +# Main program + +def main(): + G.synchronous = 0 # If set, use synchronous audio.write() + G.debug = 0 # If set, print debug messages + G.gain = 75 # Output gain + G.rate = 3 # Sampling rate + G.busy = 0 # Set while asynchronous playing is active + G.windows = [] # List of open windows (except control) + G.mode = 'mac' # Macintosh mode + G.tempprefix = '/usr/tmp/@j' + `rand.rand()` + '-' + # + optlist, args = getopt.getopt(sys.argv[1:], 'dg:r:sSa') + for optname, optarg in optlist: + if optname = '-d': + G.debug = 1 + elif optname = '-g': + G.gain = string.atoi(optarg) + if not (0 < G.gain < 256): + raise optarg.error, '-g gain out of range' + elif optname = '-r': + G.rate = string.atoi(optarg) + if not (1 <= G.rate <= 3): + raise optarg.error, '-r rate out of range' + elif optname = '-s': + G.synchronous = 1 + elif optname = '-S': + G.mode = 'sgi' + elif optname = '-a': + G.mode = 'sun' + # + if not args: + args = [DEF_DB] + # + G.cw = opencontrolwindow() + for dirname in args: + G.windows.append(openlistwindow(dirname)) + # + # + savegain = audio.getoutgain() + try: + # Initialize stdaudio + audio.setoutgain(0) + audio.start_playing('') + dummy = audio.wait_playing() + audio.setoutgain(0) + maineventloop() + finally: + audio.setoutgain(savegain) + audio.done() + clearcache() + +def maineventloop(): + mouse_events = WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP + while G.windows: + type, w, detail = event = stdwin.getevent() + if w = G.cw.win: + if type = WE_CLOSE: + return + G.cw.dispatch(event) + else: + if type = WE_DRAW: + w.drawproc(w, detail) + elif type in mouse_events: + w.mouse(w, type, detail) + elif type = WE_CLOSE: + w.close(w) + del w, event + else: + if G.debug: print type, w, detail + +# Control window -- to set gain and cancel play operations in progress + +def opencontrolwindow(): + cw = WindowParent().create('Jukebox', (0, 0)) + v = VSplit().create(cw) + # + gain = ComplexSlider().define(v) + gain.setminvalmax(0, G.gain, 255) + gain.settexts(' ', ' ') + gain.sethook(gain_setval_hook) + # + stop = PushButton().definetext(v, 'Stop') + stop.hook = stop_hook + # + cw.realize() + return cw + +def gain_setval_hook(self): + G.gain = self.val + if G.busy: audio.setoutgain(G.gain) + +def stop_hook(self): + if G.busy: + audio.setoutgain(0) + dummy = audio.stop_playing() + G.busy = 0 + + +# List windows -- to display list of files and subdirectories + +def openlistwindow(dirname): + list = posix.listdir(dirname) + list.sort() + i = 0 + while i < len(list): + if list[i] = '.' or list[i] = '..': + del list[i] + else: + i = i+1 + for i in range(len(list)): + name = list[i] + if path.isdir(path.cat(dirname, name)): + list[i] = list[i] + '/' + width = maxwidth(list) + width = width + stdwin.textwidth(' ') # XXX X11 stdwin bug workaround + height = len(list) * stdwin.lineheight() + stdwin.setdefwinsize(width, min(height, 500)) + w = stdwin.open(dirname) + stdwin.setdefwinsize(0, 0) + w.setdocsize(width, height) + w.drawproc = drawlistwindow + w.mouse = mouselistwindow + w.close = closelistwindow + w.dirname = dirname + w.list = list + w.selected = -1 + return w + +def maxwidth(list): + width = 1 + for name in list: + w = stdwin.textwidth(name) + if w > width: width = w + return width + +def drawlistwindow(w, area): + d = w.begindrawing() + d.erase((0, 0), (1000, 10000)) + lh = d.lineheight() + h, v = 0, 0 + for name in w.list: + d.text((h, v), name) + v = v + lh + showselection(w, d) + +def hideselection(w, d): + if w.selected >= 0: + invertselection(w, d) + +def showselection(w, d): + if w.selected >= 0: + invertselection(w, d) + +def invertselection(w, d): + lh = d.lineheight() + h1, v1 = p1 = 0, w.selected*lh + h2, v2 = p2 = 1000, v1 + lh + d.invert(p1, p2) + +def mouselistwindow(w, type, detail): + (h, v), clicks, button = detail[:3] + d = w.begindrawing() + lh = d.lineheight() + if 0 <= v < lh*len(w.list): + i = v / lh + else: + i = -1 + if w.selected <> i: + hideselection(w, d) + w.selected = i + showselection(w, d) + if type = WE_MOUSE_DOWN and clicks >= 2 and i >= 0: + name = path.cat(w.dirname, w.list[i]) + if name[-1:] = '/': + if clicks = 2: + G.windows.append(openlistwindow(name[:-1])) + else: + playfile(name) + +def closelistwindow(w): + remove(G.windows, w) + +def remove(list, item): + for i in range(len(list)): + if list[i] = item: + del list[i] + break + + +# Playing tools + +cache = {} + +def clearcache(): + for x in cache.keys(): + try: + sts = posix.system('rm -f ' + cache[x]) + if sts: + print cmd + print 'Exit status', sts + except: + print cmd + print 'Exception?!' + del cache[x] + +def playfile(name): + if G.mode <> 'mac': + tempname = name + elif cache.has_key(name): + tempname = cache[name] + else: + tempname = G.tempprefix + `rand.rand()` + cmd = HOME_BIN_SGI + 'macsound2sgi' + cmd = cmd + ' ' + commands.mkarg(name) + cmd = cmd + ' >' + tempname + if G.debug: print cmd + sts = posix.system(cmd) + if sts: + print cmd + print 'Exit status', sts + stdwin.fleep() + return + cache[name] = tempname + fp = open(tempname, 'r') + try: + hdr = sunaudio.gethdr(fp) + except sunaudio.error, msg: + hdr = () + if hdr: + data_size = hdr[0] + data = fp.read(data_size) + # XXX this doesn't work yet, need to convert from uLAW!!! + del fp + else: + del fp + data = readfile(tempname) + if G.debug: print len(data), 'bytes read from', tempname + if G.busy: + G.busy = 0 + dummy = audio.stop_playing() + # + # Completely reset the audio device + audio.setrate(G.rate) + audio.setduration(0) + audio.setoutgain(G.gain) + # + if G.synchronous: + audio.write(data) + audio.setoutgain(0) + else: + try: + audio.start_playing(data) + G.busy = 1 + except: + stdwin.fleep() + del data + +def readfile(filename): + return readfp(open(filename, 'r')) + +def readfp(fp): + data = '' + while 1: + buf = fp.read(102400) # Reads most samples in one fell swoop + if not buf: + return data + data = data + buf + +main() diff --git a/demo/sgi/audio_stdwin/rec.py b/demo/sgi/audio_stdwin/rec.py new file mode 100755 index 0000000..3ab3aea --- /dev/null +++ b/demo/sgi/audio_stdwin/rec.py @@ -0,0 +1,271 @@ +#! /ufs/guido/bin/sgi/python + +import sys +import audio +import stdwin + +import string +import getopt + +from stdwinevents import * +from Buttons import * +from Sliders import * +#from Soundogram import Soundogram +from VUMeter import VUMeter +from WindowParent import WindowParent +from HVSplit import HSplit, VSplit + +class TimeOutToggleButton() = ToggleButton(): + def define(self, parent): + self = ToggleButton.define(self, parent) + self.parent.need_timer(self) + self.timer_hook = 0 + return self + def timer(self): + if self.timer_hook: + self.timer_hook(self) + +K = 1024 +BUFSIZE = 30*8*K +Rates = [0, 32*K, 16*K, 8*K] +Magics = ['', '0032', '0016', '0008'] + +class Struct(): pass +G = Struct() + +def main(): + # + # Set default state + # + G.gain = 60 + G.rate = 3 + G.nomuting = 0 + G.savefile = '@rec' + # + # Set default values + # + G.data = '' + G.playing = 0 + G.recording = 0 + G.sogram = 0 + # + # Parse options + # + optlist, args = getopt.getopt(sys.argv[1:], 'mdg:r:') + # + for optname, optarg in optlist: + if 0: # (So all cases start with elif) + pass + elif optname = '-d': + G.debug = 1 + elif optname = '-g': + G.gain = string.atoi(optarg) + if not (0 < G.gain < 256): + raise optarg.error, '-g gain out of range' + elif optname = '-m': + G.nomuting = (not G.nomuting) + elif optname = '-r': + G.rate = string.atoi(optarg) + if not (1 <= G.rate <= 3): + raise optarg.error, '-r rate out of range' + # + if args: + G.savefile = args[0] + # + # Initialize the sound package + # + audio.setoutgain(G.nomuting * G.gain) # Silence the speaker + audio.setrate(G.rate) + # + # Create the WindowParent and VSplit + # + G.window = WindowParent().create('Recorder', (0, 0)) + w = G.vsplit = VSplit().create(G.window) + # + # VU-meter + # + G.vubtn = VUMeter().define(w) + # + # Radiobuttons for rates + # + r1btn = RadioButton().definetext(w, '32 K/sec') + r1btn.on_hook = rate_hook + r1btn.rate = 1 + # + r2btn = RadioButton().definetext(w, '16 K/sec') + r2btn.on_hook = rate_hook + r2btn.rate = 2 + # + r3btn = RadioButton().definetext(w, '8 K/sec') + r3btn.on_hook = rate_hook + r3btn.rate = 3 + # + radios = [r1btn, r2btn, r3btn] + r1btn.group = r2btn.group = r3btn.group = radios + for r in radios: + if r.rate = G.rate: r.select(1) + # + # Other controls + # + G.recbtn = TimeOutToggleButton().definetext(w, 'Record') + G.recbtn.on_hook = record_on_hook + G.recbtn.timer_hook = record_timer_hook + G.recbtn.off_hook = record_off_hook + # + G.mutebtn = CheckButton().definetext(w, 'Mute') + G.mutebtn.select(not G.nomuting) + G.mutebtn.hook = mute_hook + # + G.playbtn = TimeOutToggleButton().definetext(w, 'Playback') + G.playbtn.on_hook = play_on_hook + G.playbtn.timer_hook = play_timer_hook + G.playbtn.off_hook = play_off_hook + # + G.gainbtn = ComplexSlider().define(w) + G.gainbtn.settexts(' Volume: ', ' ') + G.gainbtn.setminvalmax(0, G.gain, 255) + G.gainbtn.sethook(gain_hook) + # + G.sizebtn = Label().definetext(w, `len(G.data)` + ' bytes') + # + #G.showbtn = PushButton().definetext(w, 'Sound-o-gram...') + #G.showbtn.hook = show_hook + # + G.savebtn = PushButton().definetext(w, 'Save...') + G.savebtn.hook = save_hook + # + G.quitbtn = PushButton().definetext(w, 'Quit') + G.quitbtn.hook = quit_hook + G.playbtn.enable(0) + G.savebtn.enable(0) + #G.showbtn.enable(0) + start_vu() + G.window.realize() + # + # Event loop + # + while 1: + e = stdwin.getevent() + G.window.dispatch(e) + +# XXX Disabled... +def show_hook(self): + savetext = self.text + self.settext('Be patient...') + close_sogram() + stdwin.setdefwinsize(400, 300) + win = stdwin.open('Sound-o-gram') + G.sogram = Soundogram().define(win, G.data) + win.buttons = [G.sogram] + self.settext(savetext) + +def close_sogram(): + if G.sogram: + # Break circular references + G.sogram.win.buttons[:] = [] + del G.sogram.win + G.sogram = 0 + +def mute_hook(self): + G.nomuting = (not self.selected) + audio.setoutgain(G.nomuting * G.gain) + +def rate_hook(self): + G.rate = self.rate + audio.setrate(G.rate) + +def record_on_hook(self): + stop_vu() + close_sogram() + audio.setrate(G.rate) + audio.setoutgain(G.nomuting * G.gain) + audio.start_recording(BUFSIZE) + G.recording = 1 + G.playbtn.enable(0) + G.window.settimer(10 * BUFSIZE / Rates[G.rate]) + +def record_timer_hook(self): + if G.recording: + if audio.poll_recording(): + self.hilite(0) + record_off_hook(self) + else: + self.parent.settimer(5) + +def record_off_hook(self): + if not G.recording: + return + G.data = audio.stop_recording() + G.recording = 0 + G.sizebtn.settext(`len(G.data)` + ' bytes') + audio.setoutgain(G.nomuting * G.gain) + G.playbtn.enable((len(G.data) > 0)) + G.savebtn.enable((len(G.data) > 0)) + #G.showbtn.enable((len(G.data) > 0)) + G.window.settimer(0) + start_vu() + +def play_on_hook(self): + stop_vu() + audio.setrate(G.rate) + audio.setoutgain(G.gain) + audio.start_playing(G.data) + G.playing = 1 + G.recbtn.enable(0) + G.window.settimer(max(10 * len(G.data) / Rates[G.rate], 1)) + +def play_timer_hook(self): + if G.playing: + if audio.poll_playing(): + self.hilite(0) + play_off_hook(self) + else: + self.parent.settimer(5) + +def play_off_hook(self): + if not G.playing: + return + x = audio.stop_playing() + G.playing = 0 + audio.setoutgain(G.nomuting * G.gain) + G.recbtn.enable(1) + G.window.settimer(0) + start_vu() + +def gain_hook(self): + G.gain = self.val + if G.playing or G.nomuting: audio.setoutgain(G.gain) + +def save_hook(self): + if not G.data: + stdwin.fleep() + else: + prompt = 'Store sampled data on file: ' + try: + G.savefile = stdwin.askfile(prompt, G.savefile, 1) + except KeyboardInterrupt: + return + try: + fp = open(G.savefile, 'w') + fp.write(Magics[G.rate] + G.data) + except: + stdwin.message('Cannot create ' + file) + +def stop_vu(): + G.vubtn.stop() + +def start_vu(): + G.vubtn.start() + +Exit = 'exit' # exception + +def quit_hook(self): + raise Exit, 0 + +try: + try: + main() + finally: + audio.setoutgain(0) +except Exit, sts: + sys.exit(sts) diff --git a/demo/sgi/audio_stdwin/vumeter.py b/demo/sgi/audio_stdwin/vumeter.py new file mode 100755 index 0000000..1685ba2 --- /dev/null +++ b/demo/sgi/audio_stdwin/vumeter.py @@ -0,0 +1,35 @@ +#! /ufs/guido/bin/sgi/python + +import audio +import stdwin + +from VUMeter import VUMeter +from WindowParent import WindowParent +import MainLoop + +NBUFS=20 +BUFSIZE = NBUFS*48 +SCALE=128 + +class MyVUMeter() = VUMeter(): + def init_reactivity(self): + self.parent.need_mouse(self) + def mouse_down(self, detail): + if self.enabled: + self.stop() + else: + self.start() + def mouse_move(self, detail): pass + def mouse_up(self, detail): pass + +def main(): + audio.setrate(3) + audio.setoutgain(0) + w = WindowParent().create('VU Meter', (200, 100)) + v = MyVUMeter().define(w) + v.start() + w.realize() + while 1: + w.dispatch(stdwin.getevent()) + +main() diff --git a/demo/sgi/gl/README b/demo/sgi/gl/README new file mode 100644 index 0000000..f191cf5 --- /dev/null +++ b/demo/sgi/gl/README @@ -0,0 +1,22 @@ +These demos run only on SGI machines and require the 'gl' built-in module. +The demonstrate the abilities of SGI's GL library as well as the ease of +GL programming in Python. Most demos require the Z-buffer (aka +24-bitplane) option. + +backface Demonstrates the 'backface' GL function. + +kites Show 3 flying kites. Demonstrates the rendering speed + obtainable by Python programs. + +mclock A colorful clock with more options than you can + remember. Works on 8-bit machines (but allows more + colors on 24-bit machines). + +mixing Demonstrates the effect of color mixing: through + frequent color switching it gives the effect of white + light. + +nurbs A simple demonstration of the 'nurbs' GL functions. + +zrgb Displays a 3-D Gouraud-shaded figure which can be moved + around with the mouse. diff --git a/demo/sgi/gl/backface.py b/demo/sgi/gl/backface.py new file mode 100755 index 0000000..5936f75 --- /dev/null +++ b/demo/sgi/gl/backface.py @@ -0,0 +1,140 @@ +#! /ufs/guido/bin/sgi/python + +# backface +# +# draw a cube that can run with backface() turned on or off. +# cube is moved when LEFTMOUSE is pressed and mouse itself is moved. + +from gl import * +from DEVICE import * +from GL import * + +CUBE_SIZE = 200.0 +CUBE_OBJ = 1 + +def main () : + # + x = 0 + y = 0 + moveit = 0 + # + initialize() + # + while (1) : + # + while (qtest()) : + dev, val = qread() + # + if dev = ESCKEY : + backface(0) + return + # + elif dev = REDRAW : + reshapeviewport() + drawcube(x,y) + # + elif dev = LEFTMOUSE : + # + # LEFTMOUSE down + moveit = val + # + elif dev = BKEY : + backface(1) + drawcube(x,y) + # + elif dev = FKEY : + backface(0) + drawcube(x,y) + # + if moveit : + x = getvaluator(MOUSEX) + y = getvaluator(MOUSEY) + drawcube(x,y) + + +def initialize () : + foreground () + keepaspect (1, 1) + gid = winopen('backface') + winset(gid) + winconstraints() + # + doublebuffer() + gconfig() + shademodel(FLAT) + # + ortho(-1024.0, 1024.0, -1024.0, 1024.0, -1024.0, 1024.0) + # + qdevice(ESCKEY) + qdevice(REDRAW) + qdevice(LEFTMOUSE) + qdevice(BKEY) + qdevice(FKEY) + qenter(REDRAW,gid) + # + backface(1) + +# +# define a cube +def cube () : + # + # front face + pushmatrix() + translate(0.0,0.0,CUBE_SIZE) + color(RED) + rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE) + popmatrix() + # + # right face + pushmatrix() + translate(CUBE_SIZE, 0.0, 0.0) + rotate(900, 'y') + color(GREEN) + rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE) + popmatrix() + # + # back face + pushmatrix() + translate(0.0, 0.0, -CUBE_SIZE) + rotate(1800, 'y') + color(BLUE) + rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE) + popmatrix() + # + # left face + pushmatrix() + translate(-CUBE_SIZE, 0.0, 0.0) + rotate(-900, 'y') + color(CYAN) + rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE) + popmatrix() + # + # top face + pushmatrix() + translate(0.0, CUBE_SIZE, 0.0) + rotate(-900, 'x') + color(MAGENTA) + rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE) + popmatrix() + # + # bottom face + pushmatrix() + translate(0.0, -CUBE_SIZE, 0.0) + rotate(900, 'x') + color(YELLOW) + rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE) + popmatrix() + +def drawcube(x,y) : + # + pushmatrix() + rotate(2*x, 'x') + rotate(2*y, 'y') + color(BLACK) + clear() + cube() + popmatrix() + swapbuffers() + + +main () diff --git a/demo/sgi/gl/kites.py b/demo/sgi/gl/kites.py new file mode 100755 index 0000000..764ad2c --- /dev/null +++ b/demo/sgi/gl/kites.py @@ -0,0 +1,194 @@ +#! /ufs/guido/bin/sgi/python + +# *** This only works correctly on a 24 bit-plane machine. *** +# +# A simple Python program that tests the some parts of the +# GL library. It shows the speed that can be obtained when +# doing simple graphics. +# +# The bottleneck in this program is NOT Python but the graphics +# engine; i.e Python can feed the graphics pipeline fast enough +# on the 4D/25G. +# +# This program show 3 kites flying around the screen. It uses +# +# * bgnpolygon, endpolygon +# * v3, n3 +# * lmdef, lmbind +# +# Usage : +# +# ESC -> exit program +# MOUSE3 -> freeze toggle +# MOUSE2 -> one step (use this in freeze state) + +from GL import * +from gl import * +import DEVICE +from math import * + +# +# viewobj : sets the rotation, translation and scaling +# set appropiate material, call drawobject() +# +def viewobj (r, s, t, mat) : + pushmatrix() + rot (r * 10.0, 'X') + rot (r * 10.0, 'Y') + rot (r * 10.0, 'Z') + scale (s[0], s[1], s[2]) + translate (t[0], t[1], t[2]) + lmbind(MATERIAL, mat) + drawobject() + popmatrix() + +# +# makeobj : the contructor of the object +# +def mkobj () : + v0 = (-5.0 ,0.0, 0.0) + v1 = (0.0 ,5.0, 0.0) + v2 = (5.0 ,0.0, 0.0) + v3 = (0.0 ,2.0, 0.0) + n0 = (sqrt(2.0)/2.0, sqrt(2.0)/2.0, 0.0) + vn = ((v0, n0), (v1, n0), (v2, n0), (v3, n0)) + # + return vn + +# +# the object itself as an array of vertices and normals +# +kite = mkobj () + +# +# drawobject : draw a triangle. with bgnpolygon +# +def drawobject () : + # + bgnpolygon() + vnarray (kite) + endpolygon() + +# +# identity matrix +# +idmat=[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0] + +# +# the rgb-value of light-blue +# +LightBlue = (43,169,255) + +# +# the different materials. +# +m1=[SPECULAR,0.0,0.0,0.6,DIFFUSE,0.0,0.0,0.8,SHININESS,20.0,LMNULL] +m2=[SPECULAR,0.8,0.0,0.1,DIFFUSE,0.8,0.0,0.3,SHININESS,120.0,LMNULL] +m3=[SPECULAR,0.0,1.0,0.0,DIFFUSE,0.0,0.6,0.0,SHININESS,120.0,LMNULL] + +# +# lightsources +# +light1 = [LCOLOR,1.0,1.0,1.0,POSITION,15.0,15.0,0.0,1.0,LMNULL] +light2 = [LCOLOR,1.0,1.0,1.0,POSITION,-15.0,15.0,0.0,1.0,LMNULL] + +# +# the lightmodel +# +model = [AMBIENT,0.2,0.2,0.2,LMNULL] + +# +# initgl : opens the window, configures the pipeline to 2buf and zbuf, +# sets the viewing, defines and binds the materials +# +def initgl () : + # + # open window + # + foreground () + keepaspect (1, 1) + prefposition (100, 500, 100, 500) + w = winopen ('PYTHON lights') + keepaspect (1, 1) + winconstraints() + # + # configure pipeline (zbuf, 2buf, GOURAUD and RGBmode) + # + zbuffer (1) + doublebuffer () + shademodel (GOURAUD) + RGBmode () + gconfig () + # + # define and bind materials (set perspective BEFORE loadmat !) + # + mmode(MVIEWING) + perspective (900, 1.0, 1.0, 20.0) + loadmatrix(idmat) + lmdef(DEFMATERIAL, 1, m1) + lmdef(DEFMATERIAL, 2, m2) + lmdef(DEFMATERIAL, 3, m3) + lmdef(DEFLIGHT, 1, light1) + lmdef(DEFLIGHT, 2, light2) + lmdef(DEFLMODEL, 1, model) + lmbind(LIGHT0,1) + lmbind(LIGHT1,2) + lmbind(LMODEL,1) + # + # set viewing + # + lookat (0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0) + # + # ask for the REDRAW and ESCKEY events + # + qdevice(DEVICE.MOUSE3) + qdevice(DEVICE.MOUSE2) + qdevice(DEVICE.REDRAW) + qdevice(DEVICE.ESCKEY) + +# +# GoForIT : use 2buf to redraw the object 2n times. index i is used as +# the (smoothly changing) rotation angle +# +def GoForIt(i) : + freeze = 1 + while 1 : + if freeze <> 0 : + i = i + 1 + # + # clear z-buffer and clear background to light-blue + # + zclear() + c3i (LightBlue) + clear() + # + # draw the 3 traiangles scaled above each other. + # + viewobj(float(i),[1.0,1.0,1.0],[1.0,1.0,1.0],1) + viewobj(float(i),[0.75,0.75,0.75],[0.0,2.0,2.0],2) + viewobj(float(i),[0.5,0.5,0.5],[0.0,4.0,4.0],3) + # + swapbuffers() + # + if qtest() <> 0 : + dev, val = qread() + if dev = DEVICE.ESCKEY : + break + elif dev = DEVICE.REDRAW : + reshapeviewport () + elif dev = DEVICE.MOUSE3 and val <> 0 : + freeze = 1 - freeze + elif dev = DEVICE.MOUSE2 and val <> 0 : + i = i + 1 + + +# the main program +# +def main () : + initgl () + GoForIt (0) + +# +# exec main +# +main () diff --git a/demo/sgi/gl/mclock.doc b/demo/sgi/gl/mclock.doc new file mode 100644 index 0000000..610e9ab --- /dev/null +++ b/demo/sgi/gl/mclock.doc @@ -0,0 +1,60 @@ +Newsgroups: cwi.sgi +Subject: Re: new clock +Distribution: cwi.sgi +References: <22...@charon.cwi.nl> + +Last week I wrote: + +>For your enjoyment I have implemented a colorful clock. + +The clock has now been extended with some new facilities: a menu, an +alarm and a gong. These may require some explanation beyond what's in +the usage message. + +Menu +---- +The right mouse button now pops up a menu that allows you to turn the +seconds hand on or off and to switch the alarm off. + +Alarm +----- + +The left and middle buttons set the alarm. When it is on, the alarm +time is displayed as a time on a 24 hour clock in the bottom left +corner. It is also indicated by two red triangles, corresponding to the +little (hours) and big (minutes) hand. These hands can be moved around: +the left mouse button moves the minutes hand, the middle button moves +the hourds hand. Watch out for differences of twelve hours (always +check the digital display); these can be corrected by dragging the hours +hand once around the dial. + +When the alarm goes off, two things happen: a shell command specified on +the command line with the -a option is executed (in the background), and +the clock's colors change every two seconds, for five minutes. You can +also turn the alarm off by using the menu accessible through the right +mouse button. + +There is no default command for the -a option; if it is not specified, +only the changing of the colors happens. If you have an 8 ohm speaker +connected to the audio output of your Personal Iris, a suitable command +would be: + + mclock -a '/ufs/guido/bin/sgi/play /ufs/guido/lib/sounds/alarm' + +Gong +---- + +Some people like a clock that makes noises every hour, or even more +often. This is supported by the -g and -G options. With -g you specify +a shell command to be executed to sound the gong; with -G you can +specify the interval between gong calls, in seconds (default is one hour). +The shell command is executed in the background. It is given two +arguments: the hours (on a 24 hour clock!) and the minutes. The +executable Python script /ufs/guido/bin/sgi/chime is a suitable example. +Again, this only works if you have installed a speaker (I bet 8 ohm +speakers are going to be in demand!) + +-- +Guido van Rossum, Centre for Mathematics and Computer Science (CWI), Amsterdam +gu...@cwi.nl or ..!hp4nl!cwi.nl!guido or guido%cwi...@uunet.uu.net +"A thing of beauty is a joy till sunrise" diff --git a/demo/sgi/gl/mclock.py b/demo/sgi/gl/mclock.py new file mode 100755 index 0000000..806511c --- /dev/null +++ b/demo/sgi/gl/mclock.py @@ -0,0 +1,729 @@ +#! /ufs/guido/bin/sgi/python + +############################################################################# +# NOTA BENE: Before installing, fix TZDIFF to reflect your local time zone! # +############################################################################# + +# "M Clock" +# +# An implementation in software of an original design by Rob Juda. +# Clock implementation: Guido van Rossum. +# Alarm and Gong features: Sape Mullender. +# +# XXX TO DO: +# find out local time zone difference automatically +# add a date indicator +# allow multiple alarms +# allow the menu to change more parameters + +import sys + +from gl import * +from GL import * +from DEVICE import * +import time +import getopt +import string +import path +from math import pi +import math +import posix + +FULLC = 3600 # Full circle in 1/10-ths of a degree +MIDN = 900 # Angle of the 12 o'clock position +R, G, B = 0, 1, 2 # Indices of colors in RGB list + +HOUR = 3600 # Number of seconds per hour +MINUTE = 60 # Number of seconds per minute + +class struct(): pass # Class to define featureless structures +Gl = struct() # Object to hold writable global variables + +# Default constants (used in multiple places) + +SCREENBG = 127, 156, 191 +NPARTS = 9 +TITLE = 'M Clock' +TZDIFF = -1*HOUR # <--- change this to reflect your local time zone + +# Default parameters + +Gl.foreground = 0 # If set, run in the foreground +Gl.fullscreen = 0 # If set, run on full screen +Gl.tzdiff = TZDIFF # Seconds west of Greenwich (winter time) +Gl.nparts = NPARTS # Number of parts each circle is divided in (>= 2) +Gl.debug = 0 # If set, print debug output +Gl.doublebuffer = 1 # If set, use double buffering +Gl.update = 0 # Update interval; seconds hand is suppressed if > 1 +Gl.colorsubset = 0 # If set, display only a subset of the colors +Gl.cyan = 0 # If set, display cyan overlay (big hand) +Gl.magenta = 0 # If set, display magenta overlay (little hand) +Gl.yellow = 0 # If set, display yellow overlay (fixed background) +Gl.black = 0 # If set, display black overlay (hands) +Gl.colormap = 0 # If set, use colormap mode instead of RGB mode +Gl.warnings = 0 # If set, print warnings +Gl.title = '- - ' # Window title (default set later) +Gl.border = 1 # If set, use a window border (and title) +Gl.bg = 0, 0, 0 # Background color R, G, B value +Gl.iconic = 0 # Set in iconic state +Gl.fg = 255, 0, 0 # Alarm background RGB (either normal or alarm) +Gl.ox,Gl.oy = 0,0 # Window origin +Gl.cx,Gl.cy = 0,0 # Window size +Gl.alarm_set = 0 # Alarm on or off +Gl.alarm_on = 0 # Alarm is ringing +Gl.alarm_time = 0 # Alarm time in seconds after midnight +Gl.alarm_hours = 0 # Alarm hour setting, 24 hour clock +Gl.alarm_minutes = 0 # Alarm minutes setting +Gl.alarm_rgb = 0,0,0 # Alarm display RGB colors +Gl.alarm_cmd = '' # Command to execute when alarm goes off +Gl.mouse2down = 0 # Mouse button state +Gl.mouse3down = 0 # Mouse button state +Gl.gong_cmd = '' # Command to execute when chimes go off +Gl.gong_int = 3600 # Gong interval +Gl.indices = R, G, B # Colors (permuted when alarm is on) + +def main(): + # + sys.stdout = sys.stderr # All output is errors/warnings etc. + # + try: + args = getoptions() + except string.atoi_error, value: + usage(string.atoi_error, value) + except getopt.error, msg: + usage(getopt.error, msg) + # + if args: + realtime = 0 + hours = string.atoi(args[0]) + minutes = seconds = 0 + if args[1:]: minutes = string.atoi(args[1]) + if args[2:]: seconds = string.atoi(args[2]) + localtime = ((hours*60)+minutes)*60+seconds + else: + realtime = 1 + # + if Gl.title = '- - ': + if realtime: + Gl.title = TITLE + else: + title = '' + for arg in args: title = title + ' ' + arg + Gl.title = title[1:] + del title + # + wid = makewindow() + Gl.ox,Gl.oy = getorigin() + Gl.cx,Gl.cy = getsize() + initmenu() + clearall() + # + if not Gl.update: + Gl.update = 60 + # + if Gl.update <= 1: + Gl.timernoise = 6 + else: + Gl.timernoise = 60 + noise(TIMER0, Gl.timernoise) + # + qdevice(WINSHUT) + qdevice(WINQUIT) + qdevice(ESCKEY) + if realtime: + qdevice(TIMER0) + qdevice(REDRAW) + qdevice(WINFREEZE) + qdevice(WINTHAW) + qdevice(MENUBUTTON) # MOUSE1 + qdevice(MOUSE3) # Left button + qdevice(MOUSE2) # Middle button + unqdevice(INPUTCHANGE) + # + lasttime = 0 + Gl.change = 1 + while 1: + if realtime: + localtime = time.time() - Gl.tzdiff + if Gl.alarm_set: + if localtime%(24*HOUR) = Gl.alarm_time: + # Ring the alarm! + if Gl.debug: + print 'Rrrringg!' + Gl.alarm_on = 1 + if Gl.alarm_cmd <> '': + d = posix.system(Gl.alarm_cmd+' '+`Gl.alarm_time/3600`+' '+`(Gl.alarm_time/60)%60` + ' &') + Gl.change = 1 + clearall() + if Gl.alarm_on: + if (localtime - Gl.alarm_time) % (24*HOUR) > 300: + # More than 5 minutes away from alarm + Gl.alarm_on = 0 + if Gl.debug: + print 'Alarm turned off' + Gl.change = 1 + clearall() + Gl.indices = R, G, B + else: + if localtime % 2 = 0: + # Permute color indices + Gl.indices = Gl.indices[2:] + Gl.indices[:2] + Gl.change = 1 + if Gl.gong_cmd <> '' and localtime%Gl.gong_int = 0: + d = posix.system(Gl.gong_cmd+' '+`(localtime/3600)%24`+' '+`(localtime/60)%60` + ' &') + if localtime/Gl.update <> lasttime/Gl.update: + if Gl.debug: print 'new time' + Gl.change = 1 + if Gl.change: + if Gl.debug: print 'drawing' + doit(localtime) + lasttime = localtime + Gl.change = 0 + dev, data = qread() + if Gl.debug and dev <> TIMER0: + print dev, data + if dev = TIMER0: + if Gl.debug > 1: + print dev, data + elif dev = MOUSE3: + mousex = getvaluator(MOUSEX) + mousey = getvaluator(MOUSEY) + if mouseclick(3, data, mousex, mousey): + Gl.change = 1 + elif dev = MOUSE2: + mousex = getvaluator(MOUSEX) + mousey = getvaluator(MOUSEY) + if mouseclick(2, data, mousex, mousey): + Gl.change = 1 + elif dev = MOUSEX: + mousex = data + if Gl.mouse2down: + mouse2track(mousex, mousey) + if Gl.mouse3down: + mouse3track(mousex, mousey) + elif dev = MOUSEY: + mousey = data + if Gl.mouse2down: + mouse2track(mousex, mousey) + if Gl.mouse3down: + mouse3track(mousex, mousey) + elif dev = REDRAW or dev = REDRAWICONIC: + if Gl.debug: + if dev = REDRAW: print 'REDRAW' + else: print 'REDRAWICONIC' + reshapeviewport() + Gl.ox,Gl.oy = getorigin() + Gl.cx,Gl.cy = getsize() + Gl.change = 1 + clearall() + elif dev = MENUBUTTON: + if Gl.debug: print 'MENUBUTTON' + handlemenu() + elif dev = WINFREEZE: + if Gl.debug: print 'WINFREEZE' + Gl.iconic = 1 + noise(TIMER0, 60*60) # Redraw every 60 seconds only + elif dev = WINTHAW: + if Gl.debug: print 'WINTHAW' + Gl.iconic = 0 + noise(TIMER0, Gl.timernoise) + Gl.change = 1 + elif dev = ESCKEY or dev = WINSHUT or dev = WINQUIT: + if Gl.debug: print 'Exit' + sys.exit(0) + +def getoptions(): + optlist, args = getopt.getopt(sys.argv[1:], 'A:a:B:bc:dFfG:g:n:sT:t:u:wCMYK') + for optname, optarg in optlist: + if optname = '-A': + Gl.fg = eval(optarg) # Should be (r,g,b) + elif optname = '-a': + Gl.alarm_cmd = optarg + elif optname = '-B': + Gl.bg = eval(optarg) # Should be (r,g,b) + elif optname = '-b': + Gl.border = 0 + elif optname = '-c': + Gl.colormap = string.atoi(optarg) + elif optname = '-d': + Gl.debug = Gl.debug + 1 + Gl.warnings = 1 + elif optname = '-F': + Gl.foreground = 1 + elif optname = '-f': + Gl.fullscreen = 1 + elif optname = '-G': + Gl.gong_int = 60*string.atoi(optarg) + elif optname = '-g': + Gl.gong_cmd = optarg + elif optname = '-n': + Gl.nparts = string.atoi(optarg) + elif optname = '-s': + Gl.doublebuffer = 0 + elif optname = '-T': + Gl.title = optarg + elif optname = '-t': + Gl.tzdiff = string.atoi(optarg) + elif optname = '-u': + Gl.update = string.atoi(optarg) + elif optname = '-w': + Gl.warnings = 1 + elif optname = '-C': + Gl.cyan = Gl.colorsubset = 1 + elif optname = '-M': + Gl.magenta = Gl.colorsubset = 1 + elif optname = '-Y': + Gl.yellow = Gl.colorsubset = 1 + elif optname = '-K': + Gl.black = Gl.colorsubset = 1 + else: + print 'Unsupported option', optname + return args + +def usage(exc, msg): + if sys.argv: + progname = path.basename(sys.argv[0]) + else: + progname = 'mclock' + # + print progname + ':', + if exc = string.atoi_error: + print 'non-numeric argument:', + print msg + # + print 'usage:', progname, '[options] [hh [mm [ss]]]' + # + print '-A r,g,b : alarm background red,green,blue [255,0,0]' + print '-a cmd : shell command executed when alarm goes off' + print '-B r,g,b : background red,green,blue [0,0,0]' + print ' (-B SCREENBG uses the default screen background)' + print '-b : suppress window border and title' + print '-c cmapid : select explicit colormap' + print '-d : more debug output (implies -F, -w)' + print '-F : run in foreground' + print '-f : use full screen' + print '-G intrvl : interval between chimes in minutes [60]' + print '-g cmd : shell command executed when chimes go off' + print '-s : single buffer mode' + print '-w : print various warnings' + print '-n nparts : number of parts [' + `NPARTS` + ']' + print '-T title : alternate window title [\'' + TITLE + '\']' + print '-t tzdiff : time zone difference [' + `TZDIFF` + ']' + print '-u update : update interval [60]' + print '-CMYK : Cyan, Magenta, Yellow or blacK overlay only' + print 'if hh [mm [ss]] is specified, display that time statically' + print 'on machines with < 12 bitplanes, -c and -s are forced on' + # + sys.exit(2) + +def doit(localtime): + hands = makehands(localtime) + list = makelist(hands) + render(list, hands) + +def makehands(localtime): + localtime = localtime % (12*HOUR) + seconds_hand = MIDN + FULLC - (localtime*60) % FULLC + big_hand = (MIDN + FULLC - (localtime%HOUR)) % FULLC + little_hand = (MIDN + FULLC - ((localtime/12) % HOUR)) % FULLC + return little_hand, big_hand, seconds_hand + +def makelist(little_hand, big_hand, seconds_hand): + total = [] + if Gl.cyan or not Gl.colorsubset: + total = total + makesublist(big_hand, Gl.indices[0]) + if Gl.magenta or not Gl.colorsubset: + total = total + makesublist(little_hand, Gl.indices[1]) + if Gl.yellow or not Gl.colorsubset: + total = total + makesublist(MIDN, Gl.indices[2]) + total.sort() + return total + +def makesublist(first, icolor): + list = [] + alpha = FULLC/Gl.nparts + a = first - alpha/2 + for i in range(Gl.nparts): + angle = (a + i*alpha + FULLC) % FULLC + value = 255*(Gl.nparts-1-i)/(Gl.nparts-1) + list.append(angle, icolor, value) + list.sort() + a, icolor, value = list[0] + if a <> 0: + a, icolor, value = list[len(list)-1] + t = 0, icolor, value + list.insert(0, t) + return list + +def rgb_fg(): + return Gl.fg + # Obsolete code: + if Gl.alarm_on: + return Gl.bg + else: + return Gl.fg + +def rgb_bg(): + return Gl.bg + # Obsolete code: + if Gl.alarm_on: + return Gl.fg + else: + return Gl.bg + +def clearall(): + Gl.c3i(rgb_bg()) + clear() + if Gl.doublebuffer: + swapbuffers() + clear() + +def draw_alarm(color): + frontbuffer(TRUE) + Gl.c3i(color) + pushmatrix() + rotate(-((Gl.alarm_time/12)%3600), 'z') + bgnpolygon() + v2f( 0.00,1.00) + v2f( 0.04,1.05) + v2f(-0.04,1.05) + endpolygon() + popmatrix() + # + pushmatrix() + rotate(-((Gl.alarm_time)%3600), 'z') + bgnpolygon() + v2f( 0.00,1.05) + v2f( 0.07,1.10) + v2f(-0.07,1.10) + endpolygon() + popmatrix() + # + cmov2(-1.06, -1.06) + charstr(string.rjust(`Gl.alarm_time/3600`,2)) + charstr(':') + charstr(string.zfill((Gl.alarm_time/60)%60,2)) + frontbuffer(FALSE) + +def render(list, (little_hand, big_hand, seconds_hand)): + # + if Gl.colormap: + resetindex() + # + if not list: + Gl.c3i(255, 255, 255) # White + circf(0.0, 0.0, 1.0) + else: + list.append(3600, 0, 255) # Sentinel + # + rgb = [255, 255, 255] + a_prev = 0 + for a, icolor, value in list: + if a <> a_prev: + [r, g, b] = rgb + if Gl.debug > 1: + print rgb, a_prev, a + Gl.c3i(r, g, b) + arcf(0.0, 0.0, 1.0, a_prev, a) + rgb[icolor] = value + a_prev = a + # + if Gl.black or not Gl.colorsubset: + # + # Draw the hands -- in black + # + Gl.c3i(0, 0, 0) + # + if Gl.update = 1 and not Gl.iconic: + # Seconds hand is only drawn if we update every second + pushmatrix() + rotate(seconds_hand, 'z') + bgnline() + v2f(0.0, 0.0) + v2f(1.0, 0.0) + endline() + popmatrix() + # + pushmatrix() + rotate(big_hand, 'z') + rectf(0.0, -0.01, 0.97, 0.01) + circf(0.0, 0.0, 0.01) + circf(0.97, 0.0, 0.01) + popmatrix() + # + pushmatrix() + rotate(little_hand, 'z') + rectf(0.04, -0.02, 0.63, 0.02) + circf(0.04, 0.0, 0.02) + circf(0.63, 0.0, 0.02) + popmatrix() + # + # Draw the alarm time, if set or being set + # + if Gl.alarm_set: + draw_alarm(rgb_fg()) + # + if Gl.doublebuffer: swapbuffers() + +def makewindow(): + # + if Gl.debug or Gl.foreground: + foreground() + # + if Gl.fullscreen: + # XXX Should find out true screen size using getgdesc() + prefposition(0, 1279, 0, 1023) + else: + keepaspect(1, 1) + minsize(64, 64) + # + if not Gl.border: + noborder() + wid = winopen(Gl.title) + # + if not Gl.fullscreen: + keepaspect(1, 1) + minsize(10, 10) + maxsize(2000, 2000) + iconsize(66, 66) + winconstraints() + # + nplanes = getplanes() + nmaps = getgdesc(GD_NMMAPS) + if Gl.warnings: + print nplanes, 'color planes,', nmaps, 'color maps' + # + if nplanes < 12 or Gl.colormap: + if not Gl.colormap: + Gl.colormap = nmaps - 1 + if Gl.warnings: + print 'not enough color planes available', + print 'for RGB mode; forcing colormap mode' + print 'using color map number', Gl.colormap + if not Gl.colorsubset: + needed = 3 + else: + needed = Gl.cyan + Gl.magenta + Gl.yellow + needed = needed*Gl.nparts + if Gl.bg <> (0, 0, 0): + needed = needed+1 + if Gl.fg <> (0, 0, 0): + needed = needed+1 + if Gl.doublebuffer: + if needed > available(nplanes/2): + Gl.doublebuffer = 0 + if Gl.warnings: + print 'not enough colors available', + print 'for double buffer mode;', + print 'forcing single buffer mode' + else: + nplanes = nplanes/2 + if needed > available(nplanes): + # Do this warning always + print 'still not enough colors available;', + print 'parts will be left white' + print '(needed', needed, 'but have only', + print available(nplanes), 'colors available)' + # + if Gl.doublebuffer: + doublebuffer() + gconfig() + # + if Gl.colormap: + Gl.c3i = pseudo_c3i + fixcolormap() + else: + Gl.c3i = c3i + RGBmode() + gconfig() + # + if Gl.fullscreen: + # XXX Should find out true screen size using getgdesc() + ortho2(-1.1*1.280, 1.1*1.280, -1.1*1.024, 1.1*1.024) + else: + ortho2(-1.1, 1.1, -1.1, 1.1) + # + return wid + +def available(nplanes): + return pow(2, nplanes) - 1 # Reserve one pixel for black + +def fixcolormap(): + multimap() + gconfig() + nplanes = getplanes() + if Gl.warnings: + print 'multimap mode has', nplanes, 'color planes' + imap = Gl.colormap + Gl.startindex = pow(2, nplanes) - 1 + Gl.stopindex = 1 + setmap(imap) + mapcolor(0, 0, 0, 0) # Fixed entry for black + if Gl.bg <> (0, 0, 0): + r, g, b = Gl.bg + mapcolor(1, r, g, b) # Fixed entry for Gl.bg + Gl.stopindex = 2 + if Gl.fg <> (0, 0, 0): + r, g, b = Gl.fg + mapcolor(2, r, g, b) # Fixed entry for Gl.fg + Gl.stopindex = 3 + Gl.overflow_seen = 0 + resetindex() + +def resetindex(): + Gl.index = Gl.startindex + +r0g0b0 = (0, 0, 0) + +def pseudo_c3i(rgb): + if rgb = r0g0b0: + index = 0 + elif rgb = Gl.bg: + index = 1 + elif rgb = Gl.fg: + index = 2 + else: + index = definecolor(rgb) + color(index) + +def definecolor(rgb): + index = Gl.index + if index < Gl.stopindex: + if Gl.debug: print 'definecolor hard case', rgb + # First see if we already have this one... + for index in range(Gl.stopindex, Gl.startindex+1): + if rgb = getmcolor(index): + if Gl.debug: print 'return', index + return index + # Don't clobber reserverd colormap entries + if not Gl.overflow_seen: + # Shouldn't happen any more, hence no Gl.warnings test + print 'mclock: out of colormap entries' + Gl.overflow_seen = 1 + return Gl.stopindex + r, g, b = rgb + if Gl.debug > 1: print 'mapcolor', (index, r, g, b) + mapcolor(index, r, g, b) + Gl.index = index - 1 + return index + +# Compute n**i +def pow(n, i): + x = 1 + for j in range(i): x = x*n + return x + +def mouseclick(mouse, updown, x, y): + if updown = 1: + # mouse button came down, start tracking + if Gl.debug: + print 'mouse', mouse, 'down at', x, y + if mouse = 2: + Gl.mouse2down = 1 + mouse2track(x, y) + elif mouse = 3: + Gl.mouse3down = 1 + mouse3track(x, y) + else: + print 'fatal error' + qdevice(MOUSEX) + qdevice(MOUSEY) + return 0 + else: + # mouse button came up, stop tracking + if Gl.debug: + print 'mouse', mouse, 'up at', x, y + unqdevice(MOUSEX) + unqdevice(MOUSEY) + if mouse = 2: + mouse2track(x, y) + Gl.mouse2down = 0 + elif mouse = 3: + mouse3track(x, y) + Gl.mouse3down = 0 + else: + print 'fatal error' + Gl.alarm_set = 1 + return 1 + +def mouse3track(x, y): + # first compute polar coordinates from x and y + cx, cy = Gl.ox + Gl.cx/2, Gl.oy + Gl.cy/2 + x, y = x - cx, y - cy + if (x, y) = (0, 0): return # would cause an exception + minutes = int(30.5 + 30.0*math.atan2(float(-x), float(-y))/pi) + if minutes = 60: minutes = 0 + a,b = Gl.alarm_minutes/15, minutes/15 + if (a,b) = (0,3): + # Moved backward through 12 o'clock: + Gl.alarm_hours = Gl.alarm_hours - 1 + if Gl.alarm_hours < 0: Gl.alarm_hours = Gl.alarm_hours + 24 + if (a,b) = (3,0): + # Moved forward through 12 o'clock: + Gl.alarm_hours = Gl.alarm_hours + 1 + if Gl.alarm_hours >= 24: Gl.alarm_hours = Gl.alarm_hours - 24 + Gl.alarm_minutes = minutes + seconds = Gl.alarm_hours * HOUR + Gl.alarm_minutes * MINUTE + if seconds <> Gl.alarm_time: + draw_alarm(rgb_bg()) + Gl.alarm_time = seconds + draw_alarm(rgb_fg()) + +def mouse2track(x, y): + # first compute polar coordinates from x and y + cx, cy = Gl.ox + Gl.cx/2, Gl.oy + Gl.cy/2 + x, y = x - cx, y - cy + if (x, y) = (0, 0): return # would cause an exception + hours = int(6.5 - float(Gl.alarm_minutes)/60.0 + 6.0*math.atan2(float(-x), float(-y))/pi) + if hours = 12: hours = 0 + if (Gl.alarm_hours,hours) = (0,11): + # Moved backward through midnight: + Gl.alarm_hours = 23 + elif (Gl.alarm_hours,hours) = (12,11): + # Moved backward through noon: + Gl.alarm_hours = 11 + elif (Gl.alarm_hours,hours) = (11,0): + # Moved forward through noon: + Gl.alarm_hours = 12 + elif (Gl.alarm_hours,hours) = (23,0): + # Moved forward through midnight: + Gl.alarm_hours = 0 + elif Gl.alarm_hours < 12: + Gl.alarm_hours = hours + else: + Gl.alarm_hours = hours + 12 + seconds = Gl.alarm_hours * HOUR + Gl.alarm_minutes * MINUTE + if seconds <> Gl.alarm_time: + draw_alarm(rgb_bg()) + Gl.alarm_time = seconds + draw_alarm(rgb_fg()) + +def initmenu(): + Gl.pup = pup = newpup() + addtopup(pup, 'M Clock%t|Alarm On/Off|Seconds Hand On/Off|Quit', 0) + +def handlemenu(): + item = dopup(Gl.pup) + if item = 1: + # Toggle alarm + if Gl.alarm_set: + Gl.alarm_set = 0 + Gl.alarm_on = 0 + else: + Gl.alarm_set = 1 + Gl.change = 1 + clearall() + elif item = 2: + # Toggle Seconds Hand + if Gl.update = 1: + Gl.update = 60 + Gl.timernoise = 60 + else: + Gl.update = 1 + Gl.timernoise = 6 + Gl.change = 1 + elif item = 3: + if Gl.debug: print 'Exit' + sys.exit(0) + +main() diff --git a/demo/sgi/gl/mixing.py b/demo/sgi/gl/mixing.py new file mode 100755 index 0000000..294e65f --- /dev/null +++ b/demo/sgi/gl/mixing.py @@ -0,0 +1,116 @@ +#! /ufs/guido/bin/sgi/python + +# Use Gouraud shading to mix colors. Requires Z-buffer. +# It changes the color assignments so fast that you see white. +# Left button pauses, middle rotates the square. ESC to quit. +# Experiment with a larger window (too slow) or smaller window (really white). + +from GL import * +from gl import * +import DEVICE +from math import * + +# +# tekenvlak : draw a square. with bgnpolygon +# +def tekenvlak (vc) : + bgnpolygon() + #vcarray (vc) + for i in vc : + c3f (i[1]) + v3f (i[0]) + endpolygon() + +# +# tekendoos : draw a box +# +def tekendoos (col) : + v = [(-5.0,0.0,0.0),(0.0,5.0,0.0),(5.0,0.0,0.0),(0.0,-5.0,0.0)] + vc = [(v[0],col[0]),(v[1],col[1]),(v[2],col[2]),(v[3],col[1])] + tekenvlak (vc) + +# +# initialize gl +# +def initgl () : + # + # open window + # + foreground () + keepaspect (1, 1) + prefposition (100, 500, 100, 500) + w = winopen ('PYTHON RGB') + keepaspect (1, 1) + winconstraints() + # + # configure pipeline (2buf, GOURAUD and RGBmode) + # + doublebuffer () + zbuffer (1) + shademodel (GOURAUD) + RGBmode () + gconfig () + # + # set viewing + # + perspective (900, 1, 1.0, 10.0) + polarview (10.0, 0, 0, 0) + # + # ask for the REDRAW and ESCKEY events + # + qdevice(DEVICE.MOUSE2) + qdevice(DEVICE.MOUSE3) + qdevice(DEVICE.REDRAW) + qdevice(DEVICE.ESCKEY) + + +# +# the color black +# +black = 0 +# +# GoForIT : use 2buf to redraw the object 2n times. index i is used as +# the (smoothly changing) rotation angle +# +def GoForIt(i) : + col = [(255.0,0.0,0.0), (0.0,255.0,0.0), (0.0,0.0,255.0)] + twist = 0 + freeze = 1 + while 1 : + if freeze <> 0 : + col[0],col[1],col[2] = col[1],col[2],col[0] + # + # clear z-buffer and clear background to light-blue + # + zclear() + cpack (black) + clear() + # + tekendoos (col) + # + swapbuffers() + # + if qtest() <> 0 : + dev, val = qread() + if dev = DEVICE.ESCKEY : + break + elif dev = DEVICE.REDRAW : + reshapeviewport () + elif dev = DEVICE.MOUSE2 and val <> 0 : + twist = twist + 30 + perspective (900, 1, 1.0, 10.0) + polarview (10.0, 0, 0, twist) + elif dev = DEVICE.MOUSE3 and val <> 0 : + freeze = 1 - freeze + + +# the main program +# +def main () : + initgl () + GoForIt (0) + +# +# exec main +# +main () diff --git a/demo/sgi/gl/nurbs.py b/demo/sgi/gl/nurbs.py new file mode 100755 index 0000000..ee48e23 --- /dev/null +++ b/demo/sgi/gl/nurbs.py @@ -0,0 +1,171 @@ +#! /ufs/guido/bin/sgi/python + +# Rotate a 3D surface created using NURBS. +# +# Press left mouse button to toggle surface trimming. +# Press ESC to quit. +# +# See the GL manual for an explanation of NURBS. + +from gl import * +from GL import * +from DEVICE import * + +TRUE = 1 +FALSE = 0 +ORDER = 4 + +idmat = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1] + +surfknots = [-1, -1, -1, -1, 1, 1, 1, 1] + +def make_ctlpoints(): + c = [] + # + ci = [] + ci.append(-2.5, -3.7, 1.0) + ci.append(-1.5, -3.7, 3.0) + ci.append(1.5, -3.7, -2.5) + ci.append(2.5, -3.7, -0.75) + c.append(ci) + # + ci = [] + ci.append(-2.5, -2.0, 3.0) + ci.append(-1.5, -2.0, 4.0) + ci.append(1.5, -2.0, -3.0) + ci.append(2.5, -2.0, 0.0) + c.append(ci) + # + ci = [] + ci.append(-2.5, 2.0, 1.0) + ci.append(-1.5, 2.0, 0.0) + ci.append(1.5, 2.0, -1.0) + ci.append(2.5, 2.0, 2.0) + c.append(ci) + # + ci = [] + ci.append(-2.5, 2.7, 1.25) + ci.append(-1.5, 2.7, 0.1) + ci.append(1.5, 2.7, -0.6) + ci.append(2.5, 2.7, 0.2) + c.append(ci) + # + return c + +ctlpoints = make_ctlpoints() + +trimknots = [0., 0., 0., 1., 1., 2., 2., 3., 3., 4., 4., 4.] + +def make_trimpoints(): + c = [] + c.append(1.0, 0.0, 1.0) + c.append(1.0, 1.0, 1.0) + c.append(0.0, 2.0, 2.0) + c.append(-1.0, 1.0, 1.0) + c.append(-1.0, 0.0, 1.0) + c.append(-1.0, -1.0, 1.0) + c.append(0.0, -2.0, 2.0) + c.append(1.0, -1.0, 1.0) + c.append(1.0, 0.0, 1.0) + return c + +trimpoints = make_trimpoints() + +def main(): + init_windows() + setup_queue() + make_lights() + init_view() + # + set_scene() + setnurbsproperty( N_ERRORCHECKING, 1.0 ) + setnurbsproperty( N_PIXEL_TOLERANCE, 50.0 ) + trim_flag = 0 + draw_trim_surface(trim_flag) + # + while 1: + while qtest(): + dev, val = qread() + if dev = ESCKEY: + return + elif dev = WINQUIT: + dglclose(-1) # this for DGL only + return + elif dev = REDRAW: + reshapeviewport() + set_scene() + draw_trim_surface(trim_flag) + elif dev = LEFTMOUSE: + if val: + trim_flag = (not trim_flag) + set_scene() + draw_trim_surface(trim_flag) + +def init_windows(): + foreground() + #prefposition(0, 500, 0, 500) + wid = winopen('nurbs') + wintitle('NURBS Surface') + doublebuffer() + RGBmode() + gconfig() + lsetdepth(0x000, 0x7fffff) + zbuffer( TRUE ) + +def setup_queue(): + qdevice(ESCKEY) + qdevice(REDRAW) + qdevice(RIGHTMOUSE) + qdevice(WINQUIT) + qdevice(LEFTMOUSE) #trimming + +def init_view(): + mmode(MPROJECTION) + ortho( -4., 4., -4., 4., -4., 4. ) + # + mmode(MVIEWING) + loadmatrix(idmat) + # + lmbind(MATERIAL, 1) + +def set_scene(): + lmbind(MATERIAL, 0) + RGBcolor(150,150,150) + lmbind(MATERIAL, 1) + clear() + zclear() + # + rotate( 100, 'y' ) + rotate( 100, 'z' ) + +def draw_trim_surface(trim_flag): + bgnsurface() + nurbssurface(surfknots, surfknots, ctlpoints, ORDER, ORDER, N_XYZ) + if trim_flag: + bgntrim() + nurbscurve(trimknots, trimpoints, ORDER-1, N_STW) + endtrim() + endsurface() + swapbuffers() + +def make_lights(): + lmdef(DEFLMODEL,1,[]) + lmdef(DEFLIGHT,1,[]) + # + # define material #1 + # + a = [] + a = a + [EMISSION, 0.0, 0.0, 0.0] + a = a + [AMBIENT, 0.1, 0.1, 0.1] + a = a + [DIFFUSE, 0.6, 0.3, 0.3] + a = a + [SPECULAR, 0.0, 0.6, 0.0] + a = a + [SHININESS, 2.0] + a = a + [LMNULL] + lmdef(DEFMATERIAL, 1, a) + # + # turn on lighting + # + lmbind(LIGHT0, 1) + lmbind(LMODEL, 1) + +main() diff --git a/demo/sgi/gl/zrgb.py b/demo/sgi/gl/zrgb.py new file mode 100755 index 0000000..c3f934a --- /dev/null +++ b/demo/sgi/gl/zrgb.py @@ -0,0 +1,169 @@ +#! /ufs/guido/bin/sgi/python + +# zrgb (Requires Z buffer.) +# +# This program demostrates zbuffering 3 intersecting RGB polygons while +# in doublebuffer mode where, movement of the mouse with the LEFTMOUSE +# button depressed will, rotate the 3 polygons. This is done by compound +# rotations allowing continuous screen-oriented rotations. +# +# Press the "Esc" key to exit. + +from gl import * +from GL import * +from DEVICE import * + + +objmat=[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0] + +idmat=[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0] + +def main() : + # + # old and new mouse position + # + # + mode = 0 + omx = 0 + mx = 0 + omy = 0 + my = 0 + # + initialize () + # + draw_scene (objmat) + # + while (1) : + # + dev, val = qread() + # + if dev = ESCKEY : + if val : + break + # exit when key is going up, not down + # this avoids the scenario where a window + # underneath this program's window + # would otherwise "eat up" the up- + # event of the Esc key being released + return + # + elif dev = REDRAW : + reshapeviewport() + draw_scene(objmat) + # + elif dev = LEFTMOUSE: + omx = mx + omy = my + if val : + mode = 1 + else : + mode = 0 + elif dev = MOUSEX : + omx = mx + mx = val + #print omx, mx + objmat = update_scene(objmat,mx,my,omx,omy,mode) + # + elif dev = MOUSEY : + omy = my + my = val + #print omy, my + objmat = update_scene(objmat,mx,my,omx,omy,mode) + # + + +def initialize () : + # + foreground () + keepaspect(5, 4) + w = winopen('Zbuffered RGB') + # + doublebuffer() + RGBmode() + gconfig() + zbuffer(1) + lsetdepth(0x0, 0x7FFFFF) + # + qdevice(ESCKEY) + qdevice(LEFTMOUSE) + qdevice(MOUSEX) + qdevice(MOUSEY) + +def update_scene (mat, mx, my, omx, omy, mode) : + # + if mode = 1 : + mat = orient(mat, mx, my, omx, omy) + draw_scene(mat) + return mat + +def orient (mat, mx, my, omx, omy) : + # + # + pushmatrix() + loadmatrix(idmat) + # + if mx - omx : rot (float (mx - omx), 'y') + if omy - my : rot (float (omy - my), 'x') + # + multmatrix(mat) + mat = getmatrix() + # + # + popmatrix() + # + return mat + +def draw_scene (mat) : + RGBcolor(40, 100, 200) + clear() + zclear() + # + perspective(400, 1.25, 30.0, 60.0) + translate(0.0, 0.0, -40.0) + multmatrix(mat) + # + # skews original view to show all polygons + # + rotate(-580, 'y') + draw_polys() + # + swapbuffers() + +polygon1 = [(-10.0,-10.0,0.0),(10.0,-10.0,0.0),(-10.0,10.0,0.0)] + +polygon2 = [(0.0,-10.0,-10.0),(0.0,-10.0,10.0),(0.0,5.0,-10.0)] + +polygon3 = [(-10.0,6.0,4.0),(-10.0,3.0,4.0),(4.0,-9.0,-10.0),(4.0,-6.0,-10.0)] + +def draw_polys(): + bgnpolygon() + cpack(0x0) + v3f(polygon1[0]) + cpack(0x007F7F7F) + v3f(polygon1[1]) + cpack(0x00FFFFFF) + v3f(polygon1[2]) + endpolygon() + # + bgnpolygon() + cpack(0x0000FFFF) + v3f(polygon2[0]) + cpack(0x007FFF00) + v3f(polygon2[1]) + cpack(0x00FF0000) + v3f(polygon2[2]) + endpolygon() + # + bgnpolygon() + cpack(0x0000FFFF) + v3f(polygon3[0]) + cpack(0x00FF00FF) + v3f(polygon3[1]) + cpack(0x00FF0000) + v3f(polygon3[2]) + cpack(0x00FF00FF) + v3f(polygon3[3]) + endpolygon() + + +main () diff --git a/demo/sgi/gl_panel/README b/demo/sgi/gl_panel/README new file mode 100644 index 0000000..889a2cf --- /dev/null +++ b/demo/sgi/gl_panel/README @@ -0,0 +1,23 @@ +This directory contains demos that use the Panel Library by NASA Ames. +They only run on SGI machines and require the 'pnl' and 'gl' built-in +modules. Each subdirectory contains one demo. + +apanel A trivial user interface to the audio capabilities of + the 4D/25 (Personal IRIS). Lets you record a sample and + play it back at different volumes. Requires the 'audio' + built-in module. + +flying A large demonstration that can display several + differently shaped objects through space. Control + panels let you manipulate light sources, material + properties and drawing modes. + +nurbs A demo of the capabilities of the GL 'nurbs' functions + that can display the control points. (It was intended + to let you move these as well, but there was a problem + with the mapping of mouse movements in a 3-D world.) + +twoview A demo of GL's transformation primitives. Two views on + a scene are given, and the position and orientation of a + viewer in one of the views can be changed through + various buttons and dials in a control panel. diff --git a/demo/sgi/gl_panel/apanel/apanel.py b/demo/sgi/gl_panel/apanel/apanel.py new file mode 100755 index 0000000..de9a710 --- /dev/null +++ b/demo/sgi/gl_panel/apanel/apanel.py @@ -0,0 +1,63 @@ +#! /ufs/guido/bin/sgi/python + +# A (too) trivial control panel to record a sound sample and play it back. +# Requires the audio built-in module. +# Requires the NASA AMES Panel Library. + +import sys + +import gl +import panel + +panel.block(1) + +import audio + +def main(): + gl.foreground() + gl.noport() + #gl.prefposition(700, 850, 950, 970) + wid = gl.winopen('audio demo') + # + panels = panel.defpanellist('apanel.s') # XXX + p = panels[0] + p.playbackbutton.back = p + p.recordbutton.back = p + p.sample = '' + # + def quit(a): + sys.exit(0) + # + p.quitbutton.downfunc = quit + # + def playback(a): + p = a.back + gain = int(255.0*p.outputgain.val) + a.val = 1.0 + a.fixact() + panel.drawpanel() + audio.setoutgain(gain) + audio.write(p.sample) + audio.setoutgain(0) + a.val = 0.0 + a.fixact() + # + p.playbackbutton.downfunc = playback + # + def record(a): + p = a.back + size = int(10.0 * 8192.0 * p.recordsize.val) + a.val = 1.0 + a.fixact() + panel.drawpanel() + audio.setoutgain(0) + p.sample = audio.read(size) + a.val = 0.0 + a.fixact() + # + p.recordbutton.downfunc = record + # + while 1: + act = panel.dopanel() + +main() diff --git a/demo/sgi/gl_panel/apanel/apanel.s b/demo/sgi/gl_panel/apanel/apanel.s new file mode 100644 index 0000000..7c94da2 --- /dev/null +++ b/demo/sgi/gl_panel/apanel/apanel.s @@ -0,0 +1,76 @@ +;;; This file was automatically generated by the panel editor. +;;; If you read it into gnu emacs, it will automagically format itself. + +(panel (prop help creator:user-panel-help) +(prop user-panel #t) +(label "Audio Control Panel") +(x 395) +(y 69) +(al (pnl_filled_vslider (name "outputgain") +(prop help creator:user-act-help) +(label "output gain") +(x 6.5) +(y 0.75) +(w 0.4) +(h 4.35) +(val 0.329) +(labeltype 13) +(downfunc move-then-resize) +) +(pnl_frame (prop help creator:user-frame-help) +(x 0.25) +(y 2.75) +(w 5.1) +(h 2.3) +(downfunc move-then-resize) +(al (pnl_filled_hslider (name "recordsize") +(prop help creator:user-act-help) +(label "recording length") +(x -0.75) +(w 3.3) +(h 0.4) +(val 0.1) +(labeltype 11) +(downfunc move-then-resize) +) +(pnl_label (prop help creator:user-act-help) +(label "(max 10 seconds)") +(x -0.75) +(y -0.75) +(downfunc move-then-resize) +) +(pnl_wide_button (name "recordbutton") +(prop help creator:user-act-help) +(label "record from microphone...") +(x -0.75) +(y 0.75) +(w 4.7) +(downfunc move-then-resize) +) +) +) +(pnl_wide_button (name "playbackbutton") +(prop help creator:user-act-help) +(label "playback to speaker") +(x 0.25) +(y 2) +(w 5.15) +(downfunc move-then-resize) +) +(pnl_wide_button (name "quitbutton") +(prop help creator:user-act-help) +(label "quit") +(x 0.25) +(y 0.25) +(w 1.75) +(downfunc move-then-resize) +) +) +) +;;; Local Variables: +;;; mode: scheme +;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3)) +;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")")) +;;; eval: (indent-region (point-min) (point-max) nil) +;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer)) +;;; End: diff --git a/demo/sgi/gl_panel/flying/data.py b/demo/sgi/gl_panel/flying/data.py new file mode 100644 index 0000000..bfc934a --- /dev/null +++ b/demo/sgi/gl_panel/flying/data.py @@ -0,0 +1,42 @@ + +# two string constants +ARROW = '-> ' +NULL = '' +ZERO = 0 +ONE = 1 + +# +# the color light-blue +# +lightblue = (43,169,255) + + +# +# a couple of rotation, translation, scaling vectors +# +rts1 = [[3.0,3.1,2.0],[2.2, 1.2, 2.0], [0.8,0.8,0.8]] +rts2 = [[3.2,2.6,1.8],[-1.9, 1.2, 1.6], [0.3,0.3,1.0]] +rts3 = [[2.2,3.3,1.4], [-1.0, 1.2,-1.5], [0.6,0.6, 0.6]] +rts4 = [[4.2,2.1,3.2],[1.2, 1.3, 1.0],[0.5,0.5,0.8]] +rts5 = [[1.2,3.3,2.4], [-2.0, 1.4,-2.1], [0.8, 0.8, 0.2]] +rts6 = [[3.2,3.6,2.4], [1.1, 1.6, 2.5], [0.8,0.3,0.1]] +rts7 = [[2.3,2.7,3.3], [1.1, 2.3, 1.7], [0.6,0.6,0.5]] +rts8 = [[4.2,2.1,3.2], [1.2, 1.3, 0.0], [0.5,0.5,0.5]] +# +rts90 = [[4.2,2.1,3.2], [2.0, 0.0, 0.9], [0.3,0.3,1.0]] +rts91 = [[4.2,2.1,3.2], [-2.0, 0.0, 0.9], [0.3,0.3,1.0]] +rts92 = [[4.2,2.1,3.2], [0.0, 2.0, 0.9], [0.3,0.3,1.0]] +rts93 = [[4.2,2.1,3.2], [0.0, -2.0, 0.9], [0.3,0.3,1.0]] +rts10 = [[4.2,2.1,3.2], [0.0, 0.0, 0.0], [2.2,2.2,0.2]] + +# +# (composite) object definitions +# +o1 = [['sphere',rts1, 1]] +o2 = [['cylinder', rts2, 4]] +o3 = [['cube', rts3, 3]] +o4 = [['cone', rts4, 2], ['sphere', rts8, 9]] +o5 = [['sphere', rts5, 5]] +o6 = [['cube', rts6, 6]] +o7 = [['pyramid', rts7, 8]] +o8 = [['cube', rts10, 9], ['cylinder', rts90, 2], ['cylinder', rts91, 2], ['cylinder', rts92, 2], ['cylinder', rts93, 2]] diff --git a/demo/sgi/gl_panel/flying/flying.py b/demo/sgi/gl_panel/flying/flying.py new file mode 100755 index 0000000..e6fd823 --- /dev/null +++ b/demo/sgi/gl_panel/flying/flying.py @@ -0,0 +1,375 @@ +#! /ufs/guido/bin/sgi/python + +from gl import * +from objdict import * +from GL import * +import DEVICE, time +import objectdef, light, panel, material + +def fixmatact (p) : + p.diffR.fixact () + p.diffG.fixact () + p.diffB.fixact () + p.specR.fixact () + p.specG.fixact () + p.specB.fixact () + p.shine.fixact () + +def fixlichtact (p) : + p.R.fixact () + p.G.fixact () + p.B.fixact () + p.X.fixact () + p.Y.fixact () + p.Z.fixact () + p.local.fixact () + +def cbsetlight (a) : + p = a.back + setlight (p, a.label) + +def cbsetmaterial (a) : + p = a.back + setmaterial (p, a.label) + +mater = [0] +licht = [0] + +def setmaterial (p, mname) : + # + mater [0:1] = [material.materdict [mname]] + # + p.diffR.val = mater [0][1] + p.diffG.val = mater [0][2] + p.diffB.val = mater [0][3] + # + p.specR.val = mater [0][5] + p.specG.val = mater [0][6] + p.specB.val = mater [0][7] + # + p.shine.val = mater [0][9] / 128.0 + fixmatact (p) + +def setlight (p, mname) : + # + licht [0:1] = [material.lichtdict [mname]] + # + p.R.val = licht [0][1] + p.G.val = licht [0][2] + p.B.val = licht [0][3] + # + p.X.val = (licht [0][5] + 10.0) / 20.0 + p.Y.val = (licht [0][6] + 10.0) / 20.0 + p.Z.val = (licht [0][7] + 10.0) / 20.0 + # + p.local.val = licht [0][8] + # + fixlichtact (p) + +def cbmaterial (a) : + # + if mater[0] = 0 : return + # + p = a.back + mater [0][5:8] = [p.diffR.val, p.diffG.val, p.diffB.val] + mater [0][1:4] = [p.specR.val, p.specG.val, p.specB.val] + mater [0][9:10] = [128.0 * p.shine.val] + light.bindlight (0) + +def cblight (a) : + # + if licht[0] = 0 : return + # + p = a.back + licht [0][1:4] = [p.R.val, p.G.val, p.B.val] + licht [0][5:8] = [20.0 * p.X.val - 10.0, 20.0 * p.Y.val - 10.0, 20.0 * p.Z.val - 10.0] + if p.local.val = 0.0 : + licht [0][8:9] = [0.0] + else: + licht [0][8:9] = [1.0] + # + light.bindlight (0) + +# +# initgl : initialize window, pipeline, light, viewing +# +def initgl () : + # + # init window + # + foreground () + keepaspect (1, 1) + prefposition (100, 500, 100, 500) + w = winopen ('flying objects') + keepaspect (1, 1) + winconstraints () + # + # configure pipline + # + doublebuffer () + shademodel (GOURAUD) + zbuffer (1) + RGBmode () + gconfig () + # + # init lighting + # + light.bindlight (1) + # + # set viewing + # + lookat (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0) + # + +# +# drawit : draws the object with the given attributes. +# +# rfac : the rotation factor. +# mat : the material identification +# attr : a list of attributes : +# +# [[rotate vector ], [tranlate vector], [scale vector]] +# i.e : +# [[rX, rY, rZ], [tX, tY, tZ], [sX, sY, sZ]] +# +def drawit(object, rfac, attr, mat) : + pushmatrix() + rot (attr[0][0] * float (rfac), 'X') + rot (attr[0][1] * float (rfac), 'Y') + rot (attr[0][2] * float (rfac), 'Z') + translate(attr[1][0], attr[1][1], attr[1][2]) + scale(attr[2][0], attr[2][1], attr[2][2]) + lmbind(MATERIAL, mat) + objectdef.drawobject(object) + popmatrix() + +def callbacksphere (a) : + putDict (objects, 'sphere', int (a.val)) + +def callbackcylinder (a) : + putDict (objects, 'cylinder', int (a.val)) + +def callbackcube (a) : + putDict (objects, 'cube', int (a.val)) + +def callbackicecream (a) : + putDict (objects, 'icecream', int (a.val)) + +def callbackdisk (a) : + putDict (objects, 'disk', int (a.val)) + +def callbackdiamond (a) : + putDict (objects, 'diamond', int (a.val)) + +def callbackglass (a) : + putDict (objects, 'glass', int (a.val)) + +def callbackpyramid (a) : + putDict (objects, 'pyramid', int (a.val)) + +def callbacktable (a) : + putDict (objects, 'table', int (a.val)) + +def callbackflat (a) : + shademodel(FLAT) + +def callbackgouraud (a) : + shademodel(GOURAUD) + +def callbackwire (a) : + objectdef.putFunc ([bgnclosedline, endclosedline]) + +def callbackfilled (a) : + objectdef.putFunc ([bgnpolygon, endpolygon]) + +def callbackquit (a) : + import sys + sys.exit (-1) + +def allObjects(p, val) : + p.sphere.val = val + p.sphere.fixact () + p.cube.val = val + p.cube.fixact () + p.cylinder.val = val + p.cylinder.fixact () + p.pyramid.val = val + p.pyramid.fixact () + p.disk.val = val + p.disk.fixact () + p.diamond.val = val + p.diamond.fixact () + p.icecream.val = val + p.icecream.fixact () + p.table.val = val + p.table.fixact () + p.fixpanel() + + +def callbackshowall (a) : + #print objects + for key in objects.keys () : + #print key + putDict (objects, key, 1) + allObjects (a.back, 1.0) + +def callbackshownone (a) : + for key in objects.keys () : + putDict (objects, key, 0) + allObjects (a.back, 0.0) + +# +# main : makeobjects, initialze graphics, and loop continuously. +# +def main () : + # + # iter keeps track of the iterations. It is used as the + # (x, y, z) rotation increments to which the objects rotate. + iter = 0 + # + # make the objects. the objects are put in the odict dictionary + # + od = objectdef.makeobjects () + # + # initialize gl + # + initgl () + # + # initialize time and iterations per second + # + time0 = time.time () # epoch-time of previous second + fps = 0 # frames per second + # + # initialize panels + # + panel.needredraw() + panels = panel.defpanellist('flying.s') #XXX + p = panels[0] + p.sphere.upfunc = callbacksphere + p.cylinder.upfunc = callbackcylinder + p.cube.upfunc = callbackcube + p.icecream.upfunc = callbackicecream + p.disk.upfunc = callbackdisk + p.diamond.upfunc = callbackdiamond + # NOT YET IMPLEMENTED p.glass.upfunc = callbackglass + p.pyramid.upfunc = callbackpyramid + p.table.upfunc = callbacktable + p.wire.upfunc = callbackwire + p.filled.upfunc = callbackfilled + p.flat.upfunc = callbackflat + p.gouraud.upfunc = callbackgouraud + p.quit.upfunc = callbackquit + p.showall.upfunc = callbackshowall + p.shownone.upfunc = callbackshownone + p.showall.back = p + p.shownone.back = p + # + qanels = panel.defpanellist('freeze.s') #XXX + q = qanels[0] + # + ranels = panel.defpanellist('materials.s') #XXX + r = ranels[0] + r.m9.upfunc = cbsetmaterial + r.m8.upfunc = cbsetmaterial + r.m7.upfunc = cbsetmaterial + r.m6.upfunc = cbsetmaterial + r.m5.upfunc = cbsetmaterial + r.m4.upfunc = cbsetmaterial + r.m3.upfunc = cbsetmaterial + r.m2.upfunc = cbsetmaterial + r.m1.upfunc = cbsetmaterial + r.specR.activefunc = cbmaterial + r.specG.activefunc = cbmaterial + r.specB.activefunc = cbmaterial + r.diffR.activefunc = cbmaterial + r.diffG.activefunc = cbmaterial + r.diffB.activefunc = cbmaterial + r.shine.activefunc = cbmaterial + r.m9.back = r + r.m8.back = r + r.m7.back = r + r.m6.back = r + r.m5.back = r + r.m4.back = r + r.m3.back = r + r.m2.back = r + r.m1.back = r + r.diffR.back = r + r.diffG.back = r + r.diffB.back = r + r.specR.back = r + r.specG.back = r + r.specB.back = r + r.shine.back = r + # + sanels = panel.defpanellist('light.s') #XXX + s = sanels[0] + s.X.back = s + s.Y.back = s + s.Z.back = s + s.R.back = s + s.G.back = s + s.B.back = s + s.light1.back = s + s.light2.back = s + s.local.back = s + s.light1.upfunc = cbsetlight + s.light2.upfunc = cbsetlight + s.R.activefunc = cblight + s.G.activefunc = cblight + s.B.activefunc = cblight + s.X.activefunc = cblight + s.Y.activefunc = cblight + s.Z.activefunc = cblight + # + while 1 : + # + act = panel.dopanel() + # + wid = panel.userredraw () + if wid : + winset (wid) + reshapeviewport() + # + # increment iter + # + if int (q.freeze.val) = 0 : + iter = iter + 1 + fps = fps + 1 + if time.time() - time0 >= 1 : + f = float(fps)/float(time.time()-time0) + q.mystrip.val = f + q.mystrip.fixact () + q.fixpanel() + time0 = time.time() + fps = 0 + # + # clear the zbuffer and make the background light blue + # + zclear() + c3i (LightBlue) + clear() + # + # for each object in the objects dictionary + # + for key in objects.keys() : + # + # if the object should be displayed + # + if getDict (objects, key, 0) = ONE : + loo = getDict (objects, key, 1) + for o in loo : + # + # get attributes and materail + # + attr = o [1] + mat = o [2] + # + # display the object + # + drawit(od[o[0]],iter,attr,mat) + # + swapbuffers() + # + +main() diff --git a/demo/sgi/gl_panel/flying/flying.s b/demo/sgi/gl_panel/flying/flying.s new file mode 100644 index 0000000..a39fdaa --- /dev/null +++ b/demo/sgi/gl_panel/flying/flying.s @@ -0,0 +1,140 @@ +;;; This file was automatically generated by the panel editor. +;;; If you read it into gnu emacs, it will automagically format itself. + +(panel (prop help creator:user-panel-help) +(prop user-panel #t) +(label "flying objects") +(al (pnl_toggle_button (name "table") +(prop help creator:user-act-help) +(label "table") +(x 4.75) +(y 0.25) +(downfunc move-then-resize) +) +(pnl_toggle_button (name "pyramid") +(prop help creator:user-act-help) +(label "pyramid") +(x 4.75) +(y 0.75) +(downfunc move-then-resize) +) +(pnl_toggle_button (name "glass") +(prop help creator:user-act-help) +(label "glass") +(x 4.75) +(y 1.25) +(downfunc move-then-resize) +) +(pnl_toggle_button (name "diamond") +(prop help creator:user-act-help) +(label "diamond") +(x 4.75) +(y 1.75) +(downfunc move-then-resize) +) +(pnl_toggle_button (name "disk") +(prop help creator:user-act-help) +(label "disk") +(x 4.75) +(y 2.25) +(downfunc move-then-resize) +) +(pnl_toggle_button (name "icecream") +(prop help creator:user-act-help) +(label "ice cream") +(x 4.75) +(y 2.75) +(downfunc move-then-resize) +) +(pnl_toggle_button (name "cube") +(prop help creator:user-act-help) +(label "cube") +(x 4.75) +(y 3.25) +(val 1) +(downfunc move-then-resize) +) +(pnl_toggle_button (name "cylinder") +(prop help creator:user-act-help) +(label "cylinder") +(x 4.75) +(y 3.75) +(downfunc move-then-resize) +) +(pnl_toggle_button (name "sphere") +(prop help creator:user-act-help) +(label "sphere") +(x 4.75) +(y 4.25) +(downfunc move-then-resize) +) +(pnl_button (name "quit") +(prop help creator:user-act-help) +(label "quit") +(x 0.25) +(y 2.25) +(w 1.3) +(h 0.65) +(labeltype 16) +(downfunc move-then-resize) +) +(pnl_button (name "showall") +(prop help creator:user-act-help) +(label "show all") +(x 3.75) +(y 3.75) +(labeltype 8) +(downfunc move-then-resize) +) +(pnl_button (name "shownone") +(prop help creator:user-act-help) +(label "show none") +(x 3.75) +(y 3.25) +(labeltype 8) +(downfunc move-then-resize) +) +(pnl_radio_button (name "wire") +(prop end-of-group #t) +(prop help creator:user-act-help) +(label "wire frame") +(x 0.25) +(y 4.5) +(h 0.36) +(downfunc move-then-resize) +) +(pnl_radio_button (name "filled") +(prop help creator:user-act-help) +(label "filled") +(x 0.25) +(y 4) +(h 0.36) +(val 1) +(downfunc move-then-resize) +) +(pnl_radio_button (name "flat") +(prop end-of-group #t) +(prop help creator:user-act-help) +(label "flat shaded") +(x 0.25) +(y 0.5) +(h 0.36) +(downfunc move-then-resize) +) +(pnl_radio_button (name "gouraud") +(prop help creator:user-act-help) +(label "gouraud shaded") +(x 0.25) +(h 0.36) +(val 1) +(downfunc move-then-resize) +) +) +) +;;; Local Variables: +;;; mode: scheme +;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3)) +;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")")) +;;; eval: (indent-region (point-min) (point-max) nil) +;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer)) +;;; End: diff --git a/demo/sgi/gl_panel/flying/freeze.s b/demo/sgi/gl_panel/flying/freeze.s new file mode 100644 index 0000000..4bfa88c --- /dev/null +++ b/demo/sgi/gl_panel/flying/freeze.s @@ -0,0 +1,31 @@ +;;; This file was automatically generated by the panel editor. +;;; If you read it into gnu emacs, it will automagically format itself. + +(panel (prop help creator:user-panel-help) +(prop user-panel #t) +(label "frames per second") +(al (pnl_toggle_button (name "freeze") +(prop help creator:user-act-help) +(label "freeze") +(x 0.25) +(y 4.3) +(w 1.45) +(h 0.6) +(labeltype 16) +(downfunc move-then-resize) +) +(pnl_scale_chart (name "mystrip") +(prop help creator:user-act-help) +(x 0.25) +(y 0.25) +(downfunc move-then-resize) +) +) +) +;;; Local Variables: +;;; mode: scheme +;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3)) +;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")")) +;;; eval: (indent-region (point-min) (point-max) nil) +;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer)) +;;; End: diff --git a/demo/sgi/gl_panel/flying/light.py b/demo/sgi/gl_panel/flying/light.py new file mode 100644 index 0000000..f6bf379 --- /dev/null +++ b/demo/sgi/gl_panel/flying/light.py @@ -0,0 +1,46 @@ +from GL import * +from gl import * + +# identity matrix +idmat=[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0] + +# the different materials. +m1=[SPECULAR,0.8,0.0,0.0,DIFFUSE,0.4,0.0,0.0,SHININESS,40.0,LMNULL] +m2=[SPECULAR,1.0,0.4,0.0,DIFFUSE,1.0,0.4,0.0,SHININESS,80.0,LMNULL] +m3=[SPECULAR,0.0,0.0,0.6,DIFFUSE,0.0,0.0,0.8,SHININESS,60.0,LMNULL] +m4=[SPECULAR,0.0,1.0,0.0,DIFFUSE,0.0,0.6,0.0,SHININESS,120.0,LMNULL] +m5=[SPECULAR,1.0,1.0,0.0,DIFFUSE,0.6,0.6,0.0,SHININESS,100.0,LMNULL] +m6=[SPECULAR,1.0,0.0,1.0,DIFFUSE,0.6,0.0,0.6,SHININESS,120.0,LMNULL] +m7=[SPECULAR,0.9,0.9,0.9,DIFFUSE,0.6,0.6,0.6,SHININESS,120.0,LMNULL] +m8=[SPECULAR,0.4,0.7,0.4,DIFFUSE,0.5,1.0,0.5,SHININESS,50.0,LMNULL] +m9=[SPECULAR,0.2,0.0,0.1,DIFFUSE,0.8,0.0,0.3,SHININESS,10.0,LMNULL] + +#the lightsources. +light1 = [LCOLOR,1.0,1.0,1.0,POSITION,10.0,10.0,5.0,0.0,LMNULL] +light2 = [LCOLOR,1.0,1.0,1.0,POSITION,-10.0,10.0,5.0,0.0,LMNULL] + +# the lightmodel. +model = [AMBIENT,0.4,0.4,0.4,LMNULL] + +def bindlight (bool) : + # Initializes all settings for a window. + if bool <> 0 : + mmode(MVIEWING) + perspective (900, 1.0, 1.0, 35.0) + loadmatrix(idmat) + # define materials and lights + lmdef(DEFMATERIAL, 1, m1) + lmdef(DEFMATERIAL, 2, m2) + lmdef(DEFMATERIAL, 3, m3) + lmdef(DEFMATERIAL, 4, m4) + lmdef(DEFMATERIAL, 5, m5) + lmdef(DEFMATERIAL, 6, m6) + lmdef(DEFMATERIAL, 7, m7) + lmdef(DEFMATERIAL, 8, m8) + lmdef(DEFMATERIAL, 9, m9) + lmdef(DEFLIGHT, 1, light1) + lmdef(DEFLIGHT, 2, light2) + lmdef(DEFLMODEL, 1, model) + lmbind(LIGHT0,1) + lmbind(LIGHT1,2) + lmbind(LMODEL,1) diff --git a/demo/sgi/gl_panel/flying/light.s b/demo/sgi/gl_panel/flying/light.s new file mode 100644 index 0000000..ad56861 --- /dev/null +++ b/demo/sgi/gl_panel/flying/light.s @@ -0,0 +1,94 @@ +;;; This file was automatically generated by the panel editor. +;;; If you read it into gnu emacs, it will automagically format itself. + +(panel (prop help creator:user-panel-help) +(prop user-panel #t) +(label "Light Sources") +(al (pnl_hslider (name "X") +(prop help creator:user-act-help) +(label "x") +(y 4) +(w 3.3) +(h 0.4) +(val 0.50) +(labeltype 0) +(downfunc move-then-resize) +) +(pnl_hslider (name "Y") +(prop help creator:user-act-help) +(label "y") +(y 3.5) +(w 3.3) +(h 0.4) +(val 0.50) +(labeltype 0) +(downfunc move-then-resize) +) +(pnl_hslider (name "Z") +(prop help creator:user-act-help) +(label "z") +(y 3) +(w 3.3) +(h 0.4) +(val 0.50) +(labeltype 0) +(downfunc move-then-resize) +) +(pnl_radio_button (name "light2") +(prop help creator:user-act-help) +(label "light 2") +(x 5) +(y 4) +(h 0.36) +(downfunc move-then-resize) +) +(pnl_radio_button (name "light1") +(prop help creator:user-act-help) +(label "light 1") +(x 5) +(y 4.5) +(h 0.36) +(downfunc move-then-resize) +) +(pnl_toggle_button (name "local") +(prop help creator:user-act-help) +(label "local") +(x 5) +(y 2.75) +(downfunc move-then-resize) +) +(pnl_filled_hslider (name "B") +(prop help creator:user-act-help) +(label "B") +(w 3.3) +(h 0.4) +(labeltype 0) +(downfunc move-then-resize) +) +(pnl_filled_hslider (name "G") +(prop help creator:user-act-help) +(label "G") +(y 0.5) +(w 3.3) +(h 0.4) +(labeltype 0) +(downfunc move-then-resize) +) +(pnl_filled_hslider (name "R") +(prop help creator:user-act-help) +(label "R") +(y 1) +(w 3.3) +(h 0.4) +(labeltype 0) +(downfunc move-then-resize) +) +) +) +;;; Local Variables: +;;; mode: scheme +;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3)) +;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")")) +;;; eval: (indent-region (point-min) (point-max) nil) +;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer)) +;;; End: diff --git a/demo/sgi/gl_panel/flying/material.py b/demo/sgi/gl_panel/flying/material.py new file mode 100644 index 0000000..f9137ea --- /dev/null +++ b/demo/sgi/gl_panel/flying/material.py @@ -0,0 +1,26 @@ +import light + +def mkmatdict () : + m = {} + m['material 1'] = light.m1 + m['material 2'] = light.m2 + m['material 3'] = light.m3 + m['material 4'] = light.m4 + m['material 5'] = light.m5 + m['material 6'] = light.m6 + m['material 7'] = light.m7 + m['material 8'] = light.m8 + m['material 9'] = light.m9 + # + return m + +materdict = mkmatdict () + +def mklichtdict () : + m = {} + m['light 1'] = light.light1 + m['light 2'] = light.light2 + # + return m + +lichtdict = mklichtdict () diff --git a/demo/sgi/gl_panel/flying/materials.s b/demo/sgi/gl_panel/flying/materials.s new file mode 100644 index 0000000..ae45ca9 --- /dev/null +++ b/demo/sgi/gl_panel/flying/materials.s @@ -0,0 +1,161 @@ +;;; This file was automatically generated by the panel editor. +;;; If you read it into gnu emacs, it will automagically format itself. + +(panel (prop help creator:user-panel-help) +(prop user-panel #t) +(label "Materials") +(al (pnl_label (prop help creator:user-act-help) +(label "specular") +(x 4) +(y 0.5) +(downfunc move-then-resize) +) +(pnl_label (prop help creator:user-act-help) +(label "diffuse") +(x 4) +(y 4) +(downfunc move-then-resize) +) +(pnl_radio_button (name "m7") +(prop help creator:user-act-help) +(label "material 7") +(x 6.5) +(y 1.5) +(h 0.36) +(downfunc move-then-resize) +) +(pnl_radio_button (name "m9") +(prop help creator:user-act-help) +(label "material 9") +(x 6.5) +(y 0.5) +(h 0.36) +(downfunc move-then-resize) +) +(pnl_radio_button (name "m8") +(prop help creator:user-act-help) +(label "material 8") +(x 6.5) +(y 1) +(h 0.36) +(downfunc move-then-resize) +) +(pnl_radio_button (name "m6") +(prop help creator:user-act-help) +(label "material 6") +(x 6.5) +(y 2) +(h 0.36) +(downfunc move-then-resize) +) +(pnl_radio_button (name "m5") +(prop help creator:user-act-help) +(label "material 5") +(x 6.5) +(y 2.5) +(h 0.36) +(downfunc move-then-resize) +) +(pnl_radio_button (name "m4") +(prop help creator:user-act-help) +(label "material 4") +(x 6.5) +(y 3) +(h 0.36) +(downfunc move-then-resize) +) +(pnl_radio_button (name "m3") +(prop help creator:user-act-help) +(label "material 3") +(x 6.5) +(y 3.5) +(h 0.36) +(downfunc move-then-resize) +) +(pnl_radio_button (name "m2") +(prop help creator:user-act-help) +(label "material 2") +(x 6.5) +(y 4) +(h 0.36) +(downfunc move-then-resize) +) +(pnl_radio_button (name "m1") +(prop help creator:user-act-help) +(label "material 1") +(x 6.5) +(y 4.5) +(h 0.36) +(downfunc move-then-resize) +) +(pnl_filled_hslider (name "diffB") +(prop help creator:user-act-help) +(label "B") +(y 3.5) +(w 3.3) +(h 0.4) +(labeltype 0) +(downfunc move-then-resize) +) +(pnl_filled_hslider (name "diffG") +(prop help creator:user-act-help) +(label "G") +(y 4) +(w 3.3) +(h 0.4) +(labeltype 0) +(downfunc move-then-resize) +) +(pnl_filled_hslider (name "diffR") +(prop help creator:user-act-help) +(label "R") +(y 4.5) +(w 3.3) +(h 0.4) +(labeltype 0) +(downfunc move-then-resize) +) +(pnl_filled_hslider (name "specB") +(prop help creator:user-act-help) +(label "B") +(w 3.3) +(h 0.4) +(labeltype 0) +(downfunc move-then-resize) +) +(pnl_filled_hslider (name "specG") +(prop help creator:user-act-help) +(label "G") +(y 0.5) +(w 3.3) +(h 0.4) +(labeltype 0) +(downfunc move-then-resize) +) +(pnl_filled_hslider (name "specR") +(prop help creator:user-act-help) +(label "R") +(y 1) +(w 3.3) +(h 0.4) +(labeltype 0) +(downfunc move-then-resize) +) +(pnl_filled_hslider (name "shine") +(prop help creator:user-act-help) +(label "shininess") +(y 2.25) +(w 3.3) +(h 0.4) +(labeltype 0) +(downfunc move-then-resize) +) +) +) +;;; Local Variables: +;;; mode: scheme +;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3)) +;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")")) +;;; eval: (indent-region (point-min) (point-max) nil) +;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer)) +;;; End: diff --git a/demo/sgi/gl_panel/flying/objdict.py b/demo/sgi/gl_panel/flying/objdict.py new file mode 100644 index 0000000..a5d5371 --- /dev/null +++ b/demo/sgi/gl_panel/flying/objdict.py @@ -0,0 +1,41 @@ + +from data import * + +# +#the color light-blue +# +LightBlue = lightblue + +# the 'object' dictionary contains the strings of the menu items +# that denote the objects +objects = {} + +# object dictionary initialization +objects['sphere'] = [ZERO, o1] +objects['cylinder'] = [ZERO, o2] +objects['cube'] = [ONE, o3] +objects['icecream'] = [ZERO, o4] +objects['disk'] = [ZERO, o5] +objects['diamond'] = [ZERO, o6] +#objects['glass'] = [ZERO] +objects['pyramid'] = [ZERO, o7] +objects['table'] = [ZERO, o8] + +# 'putDict' sets the value of entry 'key' of dictionary 'dict' +def putDict(dict, key, val) : + dict[key][0] = val + +# +# 'getDict' get the contents of entry i of key 'key' +# of dictionary 'dict' +# +def getDict(dict, key, i) : + return dict[key][i] + +# the 'options' dictionary contains the strings of the menu items +# that denote the options +options = {} + +# option dictionary initialization +options['wire'] = [ZERO] +options['filled'] = [ONE] diff --git a/demo/sgi/gl_panel/flying/objectdef.py b/demo/sgi/gl_panel/flying/objectdef.py new file mode 100644 index 0000000..3e96113 --- /dev/null +++ b/demo/sgi/gl_panel/flying/objectdef.py @@ -0,0 +1,147 @@ +from math import * +from objdict import * +from gl import * + +FUZZY = 0.00001 + +# first try - brute force method (ala M.Overmars...) + +def makespinobject (smooth,rot,n,x1,z1,nx1,nz1,x2,z2,nx2,nz2) : + object = [] + dth = 2.0 * pi / float (rot) + for i in range (0, n) : + for j in range (0, rot) : + th = dth * float (j) + # + if smooth = 1: + a1 = th + a2 =th+dth + else : + a1 = th + dth / 2.0 + a2 = th + dth / 2.0 + # + v0 = (x1[i]*sin(th),x1[i]*cos(th),z1[i]) + n0 = (nx1[i]*sin(a1),nx1[i]*cos(a1),nz1[i]) + # + v1 = (x1[i]*sin(th+dth),x1[i]*cos(th+dth),z1[i]) + n1 = (nx1[i]*sin(a2), nx1[i]*cos(a2), nz1[i]) + # + v2 = (x2[i]*sin(th+dth),x2[i]*cos(th+dth),z2[i]) + n2 = (nx2[i]*sin(a2), nx2[i]*cos(a2), nz2[i]) + # + v3 = (x2[i]*sin(th), x2[i]*cos(th), z2[i]) + n3 = (nx2[i]*sin(a1), nx2[i]*cos(a1), nz2[i]) + # + patch = ((v0,n0), (v1,n1), (v2,n2), (v3,n3)) + #patch = ((n0,v0), (n1,v1), (n2,v2), (n3,v3)) + # + if x1[i] < FUZZY : + patch = patch[1:] + # + object.append (patch) + # + return object + +def makesphere (n): + asin = [] + acos = [] + for i in range (0, n-1): + asin.append (sin((pi/float (n))*(1.0+float (i)))) + acos.append(cos((pi/float (n))*(1.0+float (i)))) + # + x1 = [0.0] + asin + z1 = [1.0] + acos + nx1 = [0.0] + asin + nz1 = [1.0] + acos + # + x2 = asin + [0.0] + z2 = acos + [-1.0] + nx2 = asin + [0.0] + nz2 = acos + [-1.0] + # + return makespinobject (1,2*n,n,x1,z1,nx1,nz1,x2,z2,nx2,nz2) + +def makecylinder(n) : + x1 = [0.0, 1.0, 1.0] + nx1 = [0.0, 1.0, 0.0] + z1 = [1.0, 1.0, -1.0] + nz1 = [1.0, 0.0, -1.0] + # + z2 = [1.0, -1.0, -1.0] + nz2 = [1.0, 0.0, -1.0] + x2 = [1.0, 1.0, 0.0] + nx2 = [0.0, 1.0, 0.0] + # + return makespinobject(1,2*n,3,x1,z1,nx1,nz1,x2,z2,nx2,nz2) + +def makecone(n) : + x1 = [0.0, 1.0, 1.0] + nx1 = [2.0/sqrt(5.0), 0.0, 0.0] + z1 = [1.0, -1.0, -1.0] + nz1 = [1.0/sqrt(5.0), -1.0, -1.0] + # + x2 = [1.0, 0.0, 0.0] + nx2 = [2.0/sqrt(5.0), 0.0, 0.0] + nz2 = [1.0/sqrt(5.0), -1.0, -1.0] + z2 = [-1.0, -1.0, -1.0] + # + return makespinobject(1,2*n,2,x1,z1,nx1,nz1,x2,z2,nx2,nz2) + +def makecube() : + x1 = [0.0, sqrt(2.0), sqrt (2.0)] + nx1 = [0.0, 1.0, 0.0] + z1 = [1.0, 1.0, -1.0] + nz1 = [1.0, 0.0, -1.0] + # + x2 = [sqrt(2.0), sqrt(2.0), 0.0] + nx2 = [0.0, 1.0, 0.0] + z2 = [1.0, -1.0, -1.0] + nz2 = [1.0, 0.0, -1.0] + # + return makespinobject(0,4,3,x1,z1,nx1,nz1,x2,z2,nx2,nz2) + + +def makepyramid() : + x1 = [0.0, sqrt(2.0), 0.0] + nx1 = [2.0 / sqrt(5.0), 0.0, 0.0] + z1 = [1.0, -1.0, 0.0] + nz1 = [1.0 / sqrt(5.0), -1.0, 0.0] + # + x2 = [sqrt(2.0), 0.0, 0.0] + nx2 = [2.0 / sqrt(5.0), 0.0, 0.0] + z2 = [-1.0, -1.0, -1.0] + nz2 = [1.0/sqrt(5.0), -1.0, 0.0] + # + return makespinobject(0,4,3,x1,z1,nx1,nz1,x2,z2,nx2,nz2) + +def makeobjects () : + cube = makecube() + sphere = makesphere (6) + cylinder = makecylinder (6) + cone = makecone (6) + pyramid = makepyramid () + # + odict = {} + odict ['cube'] = cube + odict ['pyramid'] = pyramid + odict ['sphere'] = sphere + odict ['cylinder'] = cylinder + odict ['cone'] = cone + odict ['diamond'] = cube + odict ['disk'] = sphere + # + return odict + + +renderfuncs = [bgnpolygon, endpolygon] + +def putFunc (funcs) : + renderfuncs [:] = funcs + +def drawobject (obj) : + # + for patch in obj : + renderfuncs[0] () + vnarray (patch) + renderfuncs[1] () + diff --git a/demo/sgi/gl_panel/flying/panel.s b/demo/sgi/gl_panel/flying/panel.s new file mode 100644 index 0000000..2365a76 --- /dev/null +++ b/demo/sgi/gl_panel/flying/panel.s @@ -0,0 +1,76 @@ +;;; This file was automatically generated by the panel editor. +;;; If you read it into gnu emacs, it will automagically format itself. + +(panel (prop help creator:user-panel-help) +(prop user-panel #t) +(label "Panel Control") +(x 394) +(y 622) +(al (pnl_radio_button (name "button4") +(prop help creator:user-act-help) +(y 2.5) +(h 0.36) +(downfunc move-then-resize) +) +(pnl_radio_button (name "button3") +(prop help creator:user-act-help) +(y 3) +(h 0.36) +(downfunc move-then-resize) +) +(pnl_radio_button (name "button2") +(prop help creator:user-act-help) +(y 3.5) +(h 0.36) +(downfunc move-then-resize) +) +(pnl_radio_button (name "button1") +(prop help creator:user-act-help) +(y 4) +(h 0.36) +(downfunc move-then-resize) +) +(pnl_wide_button (name "title1") +(prop help creator:user-act-help) +(x 0.75) +(y 4.75) +(w 2.44) +(downfunc move-then-resize) +) +(pnl_wide_button (name "title2") +(prop help creator:user-act-help) +(x 3.5) +(y 4.75) +(w 2.44) +(downfunc move-then-resize) +) +(pnl_wide_button (name "title3") +(prop help creator:user-act-help) +(x 6.25) +(y 4.75) +(w 2.44) +(downfunc move-then-resize) +) +(pnl_wide_button (name "title4") +(prop help creator:user-act-help) +(x 9) +(y 4.75) +(w 2.44) +(downfunc move-then-resize) +) +(pnl_button (name "root") +(prop help creator:user-act-help) +(label "R") +(y 4.75) +(labeltype 16) +(downfunc move-then-resize) +) +) +) +;;; Local Variables: +;;; mode: scheme +;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3)) +;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")")) +;;; eval: (indent-region (point-min) (point-max) nil) +;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer)) +;;; End: diff --git a/demo/sgi/gl_panel/nurbs/nurbs.py b/demo/sgi/gl_panel/nurbs/nurbs.py new file mode 100755 index 0000000..686c3bd --- /dev/null +++ b/demo/sgi/gl_panel/nurbs/nurbs.py @@ -0,0 +1,196 @@ +#! /ufs/guido/bin/sgi/python + +# Fancy NURBS demo. Require Z buffer and Panel Library. + +from gl import * +from GL import * +from DEVICE import * +from nurbsdata import * +import panel + +# +# flags = trim_f, invis_f, cpvis_f, tpvis_f, axvis_f, freeze_f +# +TRIM = 0 +VIS = 1 +CPVIS = 2 +TPVIS = 3 +AXVIS = 4 +FREEZE = 5 +flags = [0, 1, 0, 0, 0, 0] + +def draw_axis () : + cpack (0x0) + zero = (0.0, 0.0, 0.0) + # + one = (1.0, 0.0, 0.0) + smallline (zero, one) + cmov (1.0, 0.0, 0.0) + charstr ('x') + # + one = (0.0, 1.0, 0.0) + smallline (zero, one) + cmov (0.0, 1.0, 0.0) + charstr ('y') + # + one = (0.0, 0.0, 1.0) + smallline (zero, one) + cmov (0.0, 0.0, 1.0) + charstr ('z') + +DELTA = 0.1 + +def cross (p) : + p0 = [p[0], p[1], p[2]] + p1 = [p[0], p[1], p[2]] + for i in range (0, 3) : + p0[i] = p0[i] + DELTA + p1[i] = p1[i] - DELTA + smallline (p0, p1) + p0[i] = p0[i] - DELTA + p1[i] = p1[i] + DELTA + +def smallline (p0, p1) : + bgnline () + v3f (p0) + v3f (p1) + endline () + +def draw_pts (pnts, color) : + linewidth (2) + cpack (color) + for i in pnts : + cross (i) + +def init_windows(): + foreground() + wid = winopen('nurbs') + wintitle('NURBS Surface') + doublebuffer() + RGBmode() + gconfig() + lsetdepth(0x000, 0x7fffff) + zbuffer( TRUE ) + +def init_view(): + mmode(MPROJECTION) + ortho( -5., 5., -5., 5., -5., 5. ) + # + mmode(MVIEWING) + loadmatrix(idmat) + # + lmbind(MATERIAL, 1) + +def set_scene(flags): + # + lmbind(MATERIAL, 0) + RGBcolor(150,150,150) + lmbind(MATERIAL, 1) + clear() + zclear() + # + if not flags[FREEZE] : + rotate( 100, 'y' ) + rotate( 100, 'z' ) + +def draw_trim_surface(flags): + pnts = ctlpoints + if flags[VIS] : + bgnsurface() + nurbssurface(surfknots,surfknots,pnts,ORDER,ORDER,N_XYZ) + if flags[TRIM]: + bgntrim() + nurbscurve(trimknots,trimpoints,ORDER-1,N_STW) + endtrim() + endsurface() + # + if flags[CPVIS] : + for i in pnts : + draw_pts (i, RED) + # + if flags[TPVIS] : + tpts = trimpoints + draw_pts (tpts, YELLOW) + # + if flags[AXVIS] : + draw_axis () + # + swapbuffers() + +def make_lights(): + lmdef(DEFLMODEL,1,[]) + lmdef(DEFLIGHT,1,[]) + # + # define material #1 + # + a = [] + a = a + [EMISSION, 0.0, 0.0, 0.0] + a = a + [AMBIENT, 0.1, 0.1, 0.1] + a = a + [DIFFUSE, 0.6, 0.3, 0.3] + a = a + [SPECULAR, 0.0, 0.6, 0.0] + a = a + [SHININESS, 2.0] + a = a + [LMNULL] + lmdef(DEFMATERIAL, 1, a) + # + # turn on lighting + # + lmbind(LIGHT0, 1) + lmbind(LMODEL, 1) + +def main(): + init_windows() + make_lights() + init_view() + # + panel.needredraw() + panels = panel.defpanellist('nurbs.s') + p = panels[0] + # + def cbtrim (a) : + flags[TRIM:TRIM+1] = [int (a.val)] + p.trim.upfunc = cbtrim + # + def cbquit (a) : + import sys + sys.exit (1) + p.quit.upfunc = cbquit + # + def cbmotion (a) : + flags[FREEZE:FREEZE+1] = [int (a.val)] + p.motion.upfunc = cbmotion + # + def cbxyzaxis (a) : + flags[AXVIS:AXVIS+1] = [int (a.val)] + p.xyzaxis.upfunc = cbxyzaxis + # + def cbtrimpnts (a) : + flags[TPVIS:TPVIS+1] = [int (a.val)] + p.trimpnts.upfunc = cbtrimpnts + # + def cbcntlpnts (a) : + flags[CPVIS:CPVIS+1] = [int (a.val)] + p.cntlpnts.upfunc = cbcntlpnts + # + def cbnurb (a) : + flags[VIS:VIS+1] = [int (a.val)] + p.nurb.upfunc = cbnurb + # + set_scene(flags) + setnurbsproperty( N_ERRORCHECKING, 1.0 ) + setnurbsproperty( N_PIXEL_TOLERANCE, 50.0 ) + draw_trim_surface(flags) + # + while 1: + act = panel.dopanel() + # + wid = panel.userredraw () + if wid : + winset (wid) + reshapeviewport() + set_scene(flags) + draw_trim_surface(flags) + # + set_scene(flags) + draw_trim_surface(flags) + +main() diff --git a/demo/sgi/gl_panel/nurbs/nurbs.s b/demo/sgi/gl_panel/nurbs/nurbs.s new file mode 100644 index 0000000..05fb514 --- /dev/null +++ b/demo/sgi/gl_panel/nurbs/nurbs.s @@ -0,0 +1,81 @@ +;;; This file was automatically generated by the panel editor. +;;; If you read it into gnu emacs, it will automagically format itself. + +(panel (prop help creator:user-panel-help) +(prop user-panel #t) +(label "NURB controls") +(x 815) +(y 22) +(al (pnl_toggle_button (name "trim") +(prop help creator:user-act-help) +(label "trim on/off") +(x 4) +(y 4.5) +(w 0.45) +(h 0.4) +(downfunc move-then-resize) +) +(pnl_toggle_button (name "motion") +(prop help creator:user-act-help) +(label "motion on/off") +(y 1) +(downfunc move-then-resize) +) +(pnl_toggle_button (name "xyzaxis") +(prop help creator:user-act-help) +(label "xyz-axis") +(y 3) +(downfunc move-then-resize) +) +(pnl_toggle_button (name "trimpnts") +(prop help creator:user-act-help) +(label "trimming pnts") +(y 3.5) +(downfunc move-then-resize) +) +(pnl_toggle_button (name "cntlpnts") +(prop help creator:user-act-help) +(label "control pnts") +(y 4) +(downfunc move-then-resize) +) +(pnl_toggle_button (name "nurb") +(prop help creator:user-act-help) +(label "nurb") +(y 4.5) +(val 1) +(downfunc move-then-resize) +) +(pnl_button (name "quit") +(prop help creator:user-act-help) +(label "quit") +(x 4) +(y 1) +(labeltype 1) +(downfunc move-then-resize) +) +(pnl_label (prop help creator:user-act-help) +(label "TRIMMING") +(x 4) +(y 5) +(downfunc move-then-resize) +) +(pnl_label (prop help creator:user-act-help) +(label "MOTION") +(y 1.5) +(downfunc move-then-resize) +) +(pnl_label (prop help creator:user-act-help) +(label "VISIBILITY") +(y 5) +(downfunc move-then-resize) +) +) +) +;;; Local Variables: +;;; mode: scheme +;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3)) +;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")")) +;;; eval: (indent-region (point-min) (point-max) nil) +;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer)) +;;; End: diff --git a/demo/sgi/gl_panel/nurbs/nurbsdata.py b/demo/sgi/gl_panel/nurbs/nurbsdata.py new file mode 100644 index 0000000..ed7e705 --- /dev/null +++ b/demo/sgi/gl_panel/nurbs/nurbsdata.py @@ -0,0 +1,82 @@ +# Data used by fancy nurbs demo. + +TRUE = 1 +FALSE = 0 + +RED = 0xff +YELLOW = 0xffff + +# +# nurb order +# +ORDER = 4 + +# +# identity matrix +# +idmat = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1] + +# +# s and t knots +# +surfknots = [-1, -1, -1, -1, 1, 1, 1, 1] + +# +# list of list of control points +# +def make_ctlpoints(): + c = [] + # + ci = [] + ci.append(-2.5, -3.7, 1.0) + ci.append(-1.5, -3.7, 3.0) + ci.append(1.5, -3.7, -2.5) + ci.append(2.5, -3.7, -0.75) + c.append(ci) + # + ci = [] + ci.append(-2.5, -2.0, 3.0) + ci.append(-1.5, -2.0, 4.0) + ci.append(1.5, -2.0, -3.0) + ci.append(2.5, -2.0, 0.0) + c.append(ci) + # + ci = [] + ci.append(-2.5, 2.0, 1.0) + ci.append(-1.5, 2.0, 0.0) + ci.append(1.5, 2.0, -1.0) + ci.append(2.5, 2.0, 2.0) + c.append(ci) + # + ci = [] + ci.append(-2.5, 2.7, 1.25) + ci.append(-1.5, 2.7, 0.1) + ci.append(1.5, 2.7, -0.6) + ci.append(2.5, 2.7, 0.2) + c.append(ci) + # + return c + +ctlpoints = make_ctlpoints () + +# +# trim knots +# +trimknots = [0., 0., 0., 1., 1., 2., 2., 3., 3., 4., 4., 4.] + +def make_trimpoints(): + c = [] + # + c.append(1.0, 0.0, 1.0) + c.append(1.0, 1.0, 1.0) + c.append(0.0, 2.0, 2.0) + c.append(-1.0, 1.0, 1.0) + c.append(-1.0, 0.0, 1.0) + c.append(-1.0, -1.0, 1.0) + c.append(0.0, -2.0, 2.0) + c.append(1.0, -1.0, 1.0) + c.append(1.0, 0.0, 1.0) + # + return c + +trimpoints = make_trimpoints() diff --git a/demo/sgi/gl_panel/twoview/block.py b/demo/sgi/gl_panel/twoview/block.py new file mode 100644 index 0000000..9ac518d --- /dev/null +++ b/demo/sgi/gl_panel/twoview/block.py @@ -0,0 +1,73 @@ +# module 'block' imported by twoview demo. + +from gl import n3f, bgnpolygon, varray, endpolygon, lmbind +from GL import MATERIAL + +# Draw a single 2x2x2 block with its center at (0, 0, 0) +# Arguments are the material indices (0 = don't call lmbind) +# +def block(m_front, m_back, m_left, m_right, m_top, m_bottom): + # + # Distances defining the sides + # + x_left = -1.0 + x_right = 1.0 + y_top = 1.0 + y_bottom = -1.0 + z_front = 1.0 + z_back = -1.0 + # + # Top surface points: A, B, C, D + # + A = x_right, y_top, z_front + B = x_right, y_top, z_back + C = x_left, y_top, z_back + D = x_left, y_top, z_front + # + # Bottom surface points: E, F, G, H + # + E = x_right, y_bottom, z_front + F = x_right, y_bottom, z_back + G = x_left, y_bottom, z_back + H = x_left, y_bottom, z_front + # + # Draw front face + # + if m_front: lmbind(MATERIAL, m_front) + n3f(0.0, 0.0, 1.0) + face(H, E, A, D) + # + # Draw back face + # + if m_back: lmbind(MATERIAL, m_back) + n3f(0.0, 0.0, -1.0) + face(G, F, B, C) + # + # Draw left face + # + if m_left: lmbind(MATERIAL, m_left) + n3f(-1.0, 0.0, 0.0) + face(G, H, D, C) + # + # Draw right face + # + if m_right: lmbind(MATERIAL, m_right) + n3f(1.0, 0.0, 0.0) + face(F, E, A, B) + # + # Draw top face + # + if m_top: lmbind(MATERIAL, m_top) + n3f(0.0, 1.0, 0.0) + face(A, B, C, D) + # + # Draw bottom face + # + if m_bottom: lmbind(MATERIAL, m_bottom) + n3f(0.0, -1.0, 0.0) + face(E, F, G, H) + +def face(points): + bgnpolygon() + varray(points) + endpolygon() diff --git a/demo/sgi/gl_panel/twoview/camera.s b/demo/sgi/gl_panel/twoview/camera.s new file mode 100644 index 0000000..f61a58e --- /dev/null +++ b/demo/sgi/gl_panel/twoview/camera.s @@ -0,0 +1,55 @@ +;;; This file was automatically generated by the panel editor. +;;; If you read it into gnu emacs, it will automagically format itself. + +(panel (prop help creator:user-panel-help) +(prop user-panel #t) +(label "Camera Control") +(x 1010) +(y 589) +(al (pnl_wide_button (name "quitbutton") +(prop help creator:user-act-help) +(label "quit") +(x 3.5) +(y 1) +(w 0.94) +(downfunc move-then-resize) +) +(pnl_filled_hslider (name "farclip") +(prop help creator:user-act-help) +(label "far clipping plane") +(x 1.25) +(y 3.5) +(w 3.3) +(h 0.4) +(val 0.752) +(downfunc move-then-resize) +) +(pnl_filled_hslider (name "nearclip") +(prop help creator:user-act-help) +(label "near clipping plane") +(x 1.25) +(y 4.5) +(w 3.3) +(h 0.4) +(val 0.17) +(downfunc move-then-resize) +) +(pnl_filled_vslider (name "zoom") +(prop help creator:user-act-help) +(label "zoom") +(x 0.2) +(y 1.25) +(w 0.4) +(h 3.9) +(val 0.344) +(downfunc move-then-resize) +) +) +) +;;; Local Variables: +;;; mode: scheme +;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3)) +;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")")) +;;; eval: (indent-region (point-min) (point-max) nil) +;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer)) +;;; End: diff --git a/demo/sgi/gl_panel/twoview/observer.s b/demo/sgi/gl_panel/twoview/observer.s new file mode 100644 index 0000000..ddcfe7a --- /dev/null +++ b/demo/sgi/gl_panel/twoview/observer.s @@ -0,0 +1,98 @@ +;;; This file was automatically generated by the panel editor. +;;; If you read it into gnu emacs, it will automagically format itself. + +(panel (prop help creator:user-panel-help) +(prop user-panel #t) +(label "Observer Control") +(x 876) +(y 10) +(al (pnl_right_arrow_button (name "right") +(prop help creator:user-act-help) +(x 3.2) +(y 2.09) +(downfunc move-then-resize) +) +(pnl_up_double_arrow_button (name "fast_forward") +(prop help creator:user-act-help) +(label "step forward") +(x 2.66) +(y 3.13) +(h 0.45) +(labeltype 4) +(downfunc move-then-resize) +) +(pnl_up_arrow_button (name "forward") +(prop help creator:user-act-help) +(x 2.66) +(y 2.64) +(downfunc move-then-resize) +) +(pnl_down_arrow_button (name "reverse") +(prop help creator:user-act-help) +(x 2.66) +(y 1.49) +(h 0.45) +(labeltype 12) +(downfunc move-then-resize) +) +(pnl_down_double_arrow_button (name "fast_reverse") +(prop help creator:user-act-help) +(label "step back") +(x 2.66) +(y 1) +(labeltype 12) +(downfunc move-then-resize) +) +(pnl_left_arrow_button (name "left") +(prop help creator:user-act-help) +(x 2.11) +(y 2.09) +(downfunc move-then-resize) +) +(pnl_right_double_arrow_button (name "fast_right") +(prop help creator:user-act-help) +(label "turn right") +(x 3.75) +(y 2.09) +(downfunc move-then-resize) +) +(pnl_left_double_arrow_button (name "fast_left") +(prop help creator:user-act-help) +(label "turn left") +(x 1.57) +(y 2.09) +(labeltype 8) +(downfunc move-then-resize) +) +(pnl_vslider (name "ypos") +(prop help creator:user-act-help) +(x 6.25) +(y 1) +(w 0.4) +(h 2.9) +(val 0.0758) +(downfunc move-then-resize) +) +(pnl_down_arrow_button (name "down") +(prop help creator:user-act-help) +(label "eye height") +(x 6.25) +(y 0.5) +(labeltype 12) +(downfunc move-then-resize) +) +(pnl_up_arrow_button (name "up") +(prop help creator:user-act-help) +(x 6.25) +(y 4) +(downfunc move-then-resize) +) +) +) +;;; Local Variables: +;;; mode: scheme +;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3)) +;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")")) +;;; eval: (indent-region (point-min) (point-max) nil) +;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer)) +;;; End: diff --git a/demo/sgi/gl_panel/twoview/topview.s b/demo/sgi/gl_panel/twoview/topview.s new file mode 100644 index 0000000..0e380cc --- /dev/null +++ b/demo/sgi/gl_panel/twoview/topview.s @@ -0,0 +1,47 @@ +;;; This file was automatically generated by the panel editor. +;;; If you read it into gnu emacs, it will automagically format itself. + +(panel (prop help creator:user-panel-help) +(prop user-panel #t) +(label "Top View Control") +(x 1020) +(y 287) +(al (pnl_hslider (name "xpos") +(prop help creator:user-act-help) +(label "X") +(x 2) +(y 0.5) +(w 3.85) +(h 0.4) +(val 0.5) +(downfunc move-then-resize) +) +(pnl_vslider (name "zpos") +(prop help creator:user-act-help) +(label "Z") +(x 1.25) +(y 1.3) +(w 0.4) +(h 3.6) +(val 0.5) +(downfunc move-then-resize) +) +(pnl_dial (name "direction") +(prop help creator:user-act-help) +(label "looking direction") +(x 2.15) +(y 1.4) +(w 3.5) +(h 3.45) +(val 0.5) +(downfunc move-then-resize) +) +) +) +;;; Local Variables: +;;; mode: scheme +;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3)) +;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")")) +;;; eval: (indent-region (point-min) (point-max) nil) +;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer)) +;;; End: diff --git a/demo/sgi/gl_panel/twoview/twoview.py b/demo/sgi/gl_panel/twoview/twoview.py new file mode 100755 index 0000000..eea7c75 --- /dev/null +++ b/demo/sgi/gl_panel/twoview/twoview.py @@ -0,0 +1,395 @@ +#! /ufs/guido/bin/sgi/python + +# A demo of GL's viewing transformations, showing two views on one scene. +# Requires the NASA AMES Panel Library. Requires Z buffer. + +from gl import * +from GL import * +import panel +from math import sin, cos, pi + +inf = 1000000.0 +far = 1000.0 +near = 100.0 + +def main(): + foreground() + # + keepaspect(1, 1) + prefposition(10, 610, 10, 610) + obswid = winopen('Observer View') + doublebuffer() + RGBmode() + gconfig() + # + keepaspect(1, 1) + prefposition(10, 310, 650, 950) + topwid = winopen('Top View') + doublebuffer() + RGBmode() + gconfig() + # + panels = panel.defpanellist('observer.s') + panels = panels + panel.defpanellist('camera.s') + panels = panels + panel.defpanellist('topview.s') + # + p = panels[0] + q = panels[1] + r = panels[2] + # + p.farclip = q.farclip + p.nearclip = q.nearclip + p.zoom = q.zoom + p.quitbutton = q.quitbutton + # + p.xpos = r.xpos + p.zpos = r.zpos + p.direction = r.direction + # + p.direction.winds = 1.0 # allow full rotation + # + def quit(act): + import sys + sys.exit(0) + p.quitbutton.downfunc = quit + # + p.left.back = p + p.fast_left.back = p + p.right.back = p + p.fast_right.back = p + p.forward.back = p + p.fast_forward.back = p + p.reverse.back = p + p.fast_reverse.back = p + p.up.back = p + p.down.back = p + # + p.left.activefunc = left + p.fast_left.activefunc = fast_left + p.right.activefunc = right + p.fast_right.activefunc = fast_right + p.forward.activefunc = forward + p.fast_forward.activefunc = fast_forward + p.reverse.activefunc = reverse + p.fast_reverse.activefunc = fast_reverse + p.up.activefunc = up + p.down.activefunc = down + # + makeobjects() + # + drawall(p, obswid, topwid) + panel.needredraw() + while 1: + act = panel.dopanel() + if panel.userredraw() or act: + drawall(p, obswid, topwid) + +def left(a): + doturn(a.back, 0.01) + +def fast_left(a): + doturn(a.back, 0.1) + +def right(a): + doturn(a.back, -0.01) + +def fast_right(a): + doturn(a.back, -0.1) + +def doturn(p, angle): + alpha = lookangle(p) + angle + # Reverse the following assignment: + # alpha = pi*1.5 - p.direction.val*2.0*pi + val = (pi*1.5 - alpha) / 2.0 / pi + while val < 0.0: val = val + 1.0 + while val > 1.0: val = val - 1.0 + p.direction.val = val + p.direction.fixact() + +def forward(a): + dostep(a.back, 1.0) + +def fast_forward(a): + dostep(a.back, 10.0) + +def reverse(a): + dostep(a.back, -1.0) + +def fast_reverse(a): + dostep(a.back, -10.0) + +def dostep(p, step): + x, y, z = observerpos(p) + alpha = lookangle(p) + x = x + step*cos(alpha) + z = z - step*sin(alpha) + # Reverse the following assignments: + # x = 2.0 * p.xpos.val * near - near + # z = near - 2.0 * p.zpos.val * near + p.xpos.val = (x + near) / 2.0 / near + p.zpos.val = - (z - near) / 2.0 / near + p.xpos.fixact() + p.zpos.fixact() + +def up(a): + doup(a.back, 0.2) + +def down(a): + doup(a.back, -0.2) + +def doup(p, step): + x, y, z = observerpos(p) + y = y + step + # Reverse: + # y = p.ypos.val * near + p.ypos.val = y/near + p.ypos.fixact() + +def drawall(p, obswid, topwid): + # + winset(obswid) + obsview(p) + drawscene() + swapbuffers() + # + winset(topwid) + topview(p) + drawscene() + drawobserver(p) + swapbuffers() + +def drawobserver(p): + x, y, z = observerpos(p) + alpha = lookangle(p) + fov = 2.0 + 1798.0 * p.zoom.val + beta = fov*pi/3600.0 # Half fov, expressed in radians + # + c3i(0, 255, 0) + # + move(x, y, z) + x1 = x + inf*cos(alpha+beta) + y1 = y + z1 = z - inf*sin(alpha+beta) + draw(x1, y1, z1) + # + move(x, y, z) + x1 = x + inf*cos(alpha-beta) + y1 = y + z1 = z - inf*sin(alpha-beta) + draw(x1, y1, z1) + +def observerlookat(p): + x, y, z = observerpos(p) + alpha = lookangle(p) + return x, y, z, x+near*cos(alpha), y, z-near*sin(alpha), 0 + +def observerpos(p): + x = 2.0 * p.xpos.val * near - near + y = p.ypos.val * near + z = near - 2.0 * p.zpos.val * near + return x, y, z + +def lookangle(p): + return pi*1.5 - p.direction.val*2.0*pi + +idmat = 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 + +def topview(p): + mmode(MVIEWING) + ortho(-far, far, -far, far, far, -far) + loadmatrix(idmat) + rotate(900, 'x') + +def obsview(p): + fov = 2.0 + 1798.0 * p.zoom.val + nearclip = p.nearclip.val * 10.0 + farclip = p.farclip.val * 10.0*far + aspectratio = 1.0 + mmode(MVIEWING) + perspective(int(fov), aspectratio, nearclip, farclip) + loadmatrix(idmat) + lookat(observerlookat(p)) + +def drawscene(): + # + # clear window + # + c3i(0, 0, 0) + clear() + # + # turn on z buffering and clear it + # + zbuffer(TRUE) + zclear() + # + # dark blue sky (depending on your gamma value!) + # + c3i(0, 0, 150) + callobj(41) + # + # bright red near and far units circle + # (use rotate since circ() always draws in x-y plane) + # + c3i(255, 0, 0) + pushmatrix() + rotate(900, 'x') + circ(0.0, 0.0, near) + circ(0.0, 0.0, far) + popmatrix() + # + # bright white striping + # + c3i(255, 255, 200) + callobj(42) + # + # building (does its own colors) + # + building() + # + # some other objects + # + dice() + +def makeobjects(): + # + # sky object + # + makeobj(41) + pmv(-inf, 0.0, -far) + pdr(inf, 0.0, -far) + pdr(inf, inf, -far) + pdr(-inf, inf, -far) + pclos() + closeobj() + # + # road stripes object + # + makeobj(42) + stripes() + closeobj() + # + # lighting model definitions + # + deflight() + +def stripes(): + # + # left line + # + botrect(-11, -10, far, -far) + # + # right line + # + botrect(10, 11, far, -far) + # + # center lines + # + z = far + while z > -far: + botrect(-0.5, 0.5, z, z - 4.0) + z = z - 10.0 + +def dice(): + from block import block + uselight() + pushmatrix() + translate(0.0, 1.0, -20.0) + rotate(200, 'y') + block(1, 0, 0, 0, 0, 0) + translate(1.0, 0.0, 3.0) + rotate(500, 'y') + block(2, 0, 0, 0, 0, 0) + popmatrix() + +def deflight(): + # Material for first die (red) + lmdef(DEFMATERIAL, 1, (DIFFUSE, 1.0, 0.0, 0.0)) + # Material for second die (green) + lmdef(DEFMATERIAL, 2, (DIFFUSE, 0.0, 1.0, 0.0)) + # First light source (default: white, from front) + lmdef(DEFLIGHT, 1, ()) + # Second light source (red, from back) + lmdef(DEFLIGHT, 2, (POSITION, 0.0, 1.0, -1.0, 0.0)) + lmdef(DEFLIGHT, 2, (LCOLOR, 1.0, 0.0, 0.0)) + # Lighting model + lmdef(DEFLMODEL, 1, (AMBIENT, 0.0, 0.0, 1.0)) + +def uselight(): + lmbind(LIGHT0, 1) + lmbind(LIGHT1, 2) + lmbind(LMODEL, 1) + # (materials are bound later) + +def building(): + # + c3i(0, 255, 255) + # + # house bounding coordinates + # + x1 = 20.0 + x1a = 25.0 + x2 = 30.0 + y1 = 0.0 + y2 = 15.0 + y2a = 20.0 + z1 = -40.0 + z2 = -55.0 + # + # door y and z coordinates + # + dy1 = 0.0 + dy2 = 4.0 + dz1 = -45.0 + dz2 = -47.0 + # + # front side (seen from origin) + # + A1 = (x1, y1, z1) + B1 = (x2, y1, z1) + C1 = (x2, y2, z1) + D1 = (x1a, y2a, z1) + E1 = (x1, y2, z1) + # + # back size + # + A2 = (x1, y1, z2) + B2 = (x2, y1, z2) + C2 = (x2, y2, z2) + D2 = (x1a, y2a, z2) + E2 = (x1, y2, z2) + # + # door in the left side + # + P = x1, dy1, dz2 + Q = x1, dy2, dz2 + R = x1, dy2, dz1 + S = x1, dy1, dz1 + # + # draw it + # + concave(TRUE) + c3i(255, 0, 0) + face(A1, B1, C1, D1, E1) + c3i(127, 127, 0) + face(A1, E1, E2, A2, P, Q, R, S) + c3i(0, 255, 0) + face(E1, D1, D2, E2) + c3i(0, 127, 127) + face(D1, C1, C2, D2) + c3i(0, 0, 255) + face(C1, B1, B2, C2) + c3i(127, 0, 127) + face(E2, D2, C2, B2, A2) + concave(FALSE) + +def face(points): + bgnpolygon() + varray(points) + endpolygon() + +# draw a rectangle at y=0.0 +# +def botrect(x1, x2, z1, z2): + polf(x1, 0.0, z1, x2, 0.0, z1, x2, 0.0, z2, x1, 0.0, z2) + +main() diff --git a/demo/stdwin/wdiff.py b/demo/stdwin/wdiff.py new file mode 100755 index 0000000..bc005f8 --- /dev/null +++ b/demo/stdwin/wdiff.py @@ -0,0 +1,480 @@ +#! /ufs/guido/bin/sgi/python + +# A window-oriented recursive diff utility. +# NB: This uses undocumented window classing modules. + +# TO DO: +# - faster update after moving/copying one file +# - diff flags (-b, etc.) should be global or maintained per window +# - use a few fixed windows instead of creating new ones all the time +# - ways to specify patterns to skip +# (best by pointing at a file and clicking a special menu entry!) +# - add rcsdiff menu commands +# - add a way to view status of selected files without opening them +# - add a way to diff two files with different names +# - add a way to rename files +# - keep backups of overwritten/deleted files +# - a way to mark specified files as uninteresting for dircmp + +import sys +import posix +import path +import rand +import commands +import dircache +import statcache +import cmp +import cmpcache +import stdwin +import gwin +import textwin +import filewin +import tablewin +import anywin + +mkarg = commands.mkarg +mk2arg = commands.mk2arg + +# List of names to ignore in dircmp() +# (Should be done with function, so we can specify patterns as well) +# +skiplist = ['RCS', '.Amake', 'tags', '.', '..'] + + +def anydiff(a, b, flags): # Display differences between any two objects + print 'diff', flags, a, b + if path.isdir(a) and path.isdir(b): + w = dirdiff(a, b, flags) + else: + w = filediff(a, b, flags) + addstatmenu(w, [a, b]) + w.original_close = w.close + w.close = close_dirwin + return w + +def close_dirwin(w): + close_subwindows(w, (), 0) + w.original_close(w) + +def filediff(a, b, flags): # Display differences between two text files + diffcmd = 'diff' + if flags: diffcmd = diffcmd + mkarg(flags) + diffcmd = diffcmd + mkarg(a) + mkarg(b) + difftext = commands.getoutput(diffcmd) + return textwin.open_readonly(mktitle(a, b), difftext) + +def dirdiff(a, b, flags): # Display differences between two directories + data = diffdata(a, b, flags) + w = tablewin.open(mktitle(a, b), data) + w.flags = flags + w.a = a + w.b = b + addviewmenu(w) + addactionmenu(w) + return w + +def diffdata(a, b, flags): # Compute directory differences. + # + a_only = [('A only:', header_action), ('', header_action)] + b_only = [('B only:', header_action), ('', header_action)] + ab_diff = [('A <> B:', header_action), ('', header_action)] + ab_same = [('A == B:', header_action), ('', header_action)] + data = [a_only, b_only, ab_diff, ab_same] + # + a_list = dircache.listdir(a)[:] + b_list = dircache.listdir(b)[:] + dircache.annotate(a, a_list) + dircache.annotate(b, b_list) + a_list.sort() + b_list.sort() + # + for x in a_list: + if x in ['./', '../']: + pass + elif x not in b_list: + a_only.append(x, a_only_action) + else: + ax = path.cat(a, x) + bx = path.cat(b, x) + if path.isdir(ax) and path.isdir(bx): + if flags = '-r': + same = dircmp(ax, bx) + else: + same = 0 + else: + try: + same = cmp.cmp(ax, bx) + except posix.error: + same = 0 + if same: + ab_same.append(x, ab_same_action) + else: + ab_diff.append(x, ab_diff_action) + # + for x in b_list: + if x in ['./', '../']: + pass + elif x not in a_list: + b_only.append(x, b_only_action) + # + return data + +# Re-read the directory. +# Attempt to find the selected item back. + +def update(w): + setbusy(w) + icol, irow = w.selection + if 0 <= icol < len(w.data) and 2 <= irow < len(w.data[icol]): + selname = w.data[icol][irow][0] + else: + selname = '' + statcache.forget_dir(w.a) + statcache.forget_dir(w.b) + tablewin.select(w, (-1, -1)) + tablewin.update(w, diffdata(w.a, w.b, w.flags)) + if selname: + for icol in range(len(w.data)): + for irow in range(2, len(w.data[icol])): + if w.data[icol][irow][0] = selname: + tablewin.select(w, (icol, irow)) + break + +# Action functions for table items in directory diff windows + +def header_action(w, string, (icol, irow), (pos, clicks, button, mask)): + tablewin.select(w, (-1, -1)) + +def a_only_action(w, string, (icol, irow), (pos, clicks, button, mask)): + tablewin.select(w, (icol, irow)) + if clicks = 2: + w2 = anyopen(path.cat(w.a, string)) + if w2: + w2.parent = w + +def b_only_action(w, string, (icol, irow), (pos, clicks, button, mask)): + tablewin.select(w, (icol, irow)) + if clicks = 2: + w2 = anyopen(path.cat(w.b, string)) + if w2: + w2.parent = w + +def ab_diff_action(w, string, (icol, irow), (pos, clicks, button, mask)): + tablewin.select(w, (icol, irow)) + if clicks = 2: + w2 = anydiff(path.cat(w.a, string), path.cat(w.b, string), '') + w2.parent = w + +def ab_same_action(w, string, sel, detail): + ax = path.cat(w.a, string) + if path.isdir(ax): + ab_diff_action(w, string, sel, detail) + else: + a_only_action(w, string, sel, detail) + +def anyopen(name): # Open any kind of document, ignore errors + try: + w = anywin.open(name) + except (RuntimeError, posix.error): + stdwin.message('Can\'t open ' + name) + return 0 + addstatmenu(w, [name]) + return w + +def dircmp(a, b): # Compare whether two directories are the same + # To make this as fast as possible, it uses the statcache + print ' dircmp', a, b + a_list = dircache.listdir(a) + b_list = dircache.listdir(b) + for x in a_list: + if x in skiplist: + pass + elif x not in b_list: + return 0 + else: + ax = path.cat(a, x) + bx = path.cat(b, x) + if statcache.isdir(ax) and statcache.isdir(bx): + if not dircmp(ax, bx): return 0 + else: + try: + if not cmpcache.cmp(ax, bx): return 0 + except posix.error: + return 0 + for x in b_list: + if x in skiplist: + pass + elif x not in a_list: + return 0 + return 1 + + +# View menu (for dir diff windows only) + +def addviewmenu(w): + w.viewmenu = m = w.menucreate('View') + m.action = [] + add(m, 'diff -r A B', diffr_ab) + add(m, 'diff A B', diff_ab) + add(m, 'diff -b A B', diffb_ab) + add(m, 'diff -c A B', diffc_ab) + add(m, 'gdiff A B', gdiff_ab) + add(m, ('Open A ', 'A'), open_a) + add(m, ('Open B ', 'B'), open_b) + add(m, 'Rescan', rescan) + add(m, 'Rescan -r', rescan_r) + +# Action menu (for dir diff windows only) + +def addactionmenu(w): + w.actionmenu = m = w.menucreate('Action') + m.action = [] + add(m, 'cp A B', cp_ab) + add(m, 'rm B', rm_b) + add(m, '', nop) + add(m, 'cp B A', cp_ba) + add(m, 'rm A', rm_a) + +# Main menu (global): + +def mainmenu(): + m = stdwin.menucreate('Wdiff') + m.action = [] + add(m, ('Quit wdiff', 'Q'), quit_wdiff) + add(m, 'Close subwindows', close_subwindows) + return m + +def add(m, text, action): + m.additem(text) + m.action.append(action) + +def quit_wdiff(w, m, item): + if askyesno('Really quit wdiff altogether?', 1): + sys.exit(0) + +def close_subwindows(w, m, item): + while 1: + for w2 in gwin.windows: + if w2.parent = w: + close_subwindows(w2, m, item) + w2.close(w2) + break # inner loop, continue outer loop + else: + break # outer loop + +def diffr_ab(w, m, item): + dodiff(w, '-r') + +def diff_ab(w, m, item): + dodiff(w, '') + +def diffb_ab(w, m, item): + dodiff(w, '-b') + +def diffc_ab(w, m, item): + dodiff(w, '-c') + +def gdiff_ab(w, m, item): # Call SGI's gdiff utility + x = getselection(w) + if x: + a, b = path.cat(w.a, x), path.cat(w.b, x) + if path.isdir(a) or path.isdir(b): + stdwin.fleep() # This is for files only + else: + diffcmd = 'gdiff' + diffcmd = diffcmd + mkarg(a) + mkarg(b) + ' &' + print diffcmd + sts = posix.system(diffcmd) + if sts: print 'Exit status', sts + +def dodiff(w, flags): + x = getselection(w) + if x: + w2 = anydiff(path.cat(w.a, x), path.cat(w.b, x), flags) + w2.parent = w + +def open_a(w, m, item): + x = getselection(w) + if x: + w2 = anyopen(path.cat(w.a, x)) + if w2: + w2.parent = w + +def open_b(w, m, item): + x = getselection(w) + if x: + w2 = anyopen(path.cat(w.b, x)) + if w2: + w2.parent = w + +def rescan(w, m, item): + w.flags = '' + update(w) + +def rescan_r(w, m, item): + w.flags = '-r' + update(w) + +def rm_a(w, m, item): + x = getselection(w) + if x: + if x[-1:] = '/': x = x[:-1] + x = path.cat(w.a, x) + if path.isdir(x): + if askyesno('Recursively remove A directory ' + x, 1): + runcmd('rm -rf' + mkarg(x)) + else: + runcmd('rm -f' + mkarg(x)) + update(w) + +def rm_b(w, m, item): + x = getselection(w) + if x: + if x[-1:] = '/': x = x[:-1] + x = path.cat(w.b, x) + if path.isdir(x): + if askyesno('Recursively remove B directory ' + x, 1): + runcmd('rm -rf' + mkarg(x)) + else: + runcmd('rm -f' + mkarg(x)) + update(w) + +def cp_ab(w, m, item): + x = getselection(w) + if x: + if x[-1:] = '/': x = x[:-1] + ax = path.cat(w.a, x) + bx = path.cat(w.b, x) + if path.isdir(ax): + if path.exists(bx): + m = 'Can\'t copy directory to existing target' + stdwin.message(m) + return + runcmd('cp -r' + mkarg(ax) + mkarg(w.b)) + else: + runcmd('cp' + mkarg(ax) + mk2arg(w.b, x)) + update(w) + +def cp_ba(w, m, item): + x = getselection(w) + if x: + if x[-1:] = '/': x = x[:-1] + ax = path.cat(w.a, x) + bx = path.cat(w.b, x) + if path.isdir(bx): + if path.exists(ax): + m = 'Can\'t copy directory to existing target' + stdwin.message(m) + return + runcmd('cp -r' + mkarg(bx) + mkarg(w.a)) + else: + runcmd('cp' + mk2arg(w.b, x) + mkarg(ax)) + update(w) + +def nop(args): + pass + +def getselection(w): + icol, irow = w.selection + if 0 <= icol < len(w.data): + if 0 <= irow < len(w.data[icol]): + return w.data[icol][irow][0] + stdwin.message('no selection') + return '' + +def runcmd(cmd): + print cmd + sts, output = commands.getstatusoutput(cmd) + if sts or output: + if not output: + output = 'Exit status ' + `sts` + stdwin.message(output) + + +# Status menu (for all kinds of windows) + +def addstatmenu(w, files): + w.statmenu = m = w.menucreate('Stat') + m.files = files + m.action = [] + for file in files: + m.additem(commands.getstatus(file)) + m.action.append(stataction) + +def stataction(w, m, item): # Menu item action for stat menu + file = m.files[item] + try: + m.setitem(item, commands.getstatus(file)) + except posix.error: + stdwin.message('Can\'t get status for ' + file) + + +# Compute a suitable window title from two paths + +def mktitle(a, b): + if a = b: return a + i = 1 + while a[-i:] = b[-i:]: i = i+1 + i = i-1 + if not i: + return a + ' ' + b + else: + return '{' + a[:-i] + ',' + b[:-i] + '}' + a[-i:] + + +# Ask a confirmation question + +def askyesno(prompt, default): + try: + return stdwin.askync(prompt, default) + except KeyboardInterrupt: + return 0 + + +# Display a message "busy" in a window, and mark it for updating + +def setbusy(w): + left, top = w.getorigin() + width, height = w.getwinsize() + right, bottom = left + width, top + height + d = w.begindrawing() + d.erase((0, 0), (10000, 10000)) + text = 'Busy...' + textwidth = d.textwidth(text) + textheight = d.lineheight() + h, v = left + (width-textwidth)/2, top + (height-textheight)/2 + d.text((h, v), text) + del d + w.change((0, 0), (10000, 10000)) + + +# Main function + +def main(): + print 'wdiff: warning: this version does NOT yet make backups' + argv = sys.argv + flags = '' + if len(argv) >= 2 and argv[1][:1] = '-': + flags = argv[1] + del argv[1] + m = mainmenu() # Create menu earlier than windows + if len(argv) = 2: # 1 argument + w = anyopen(argv[1]) + if not w: return + elif len(argv) = 3: # 2 arguments + w = anydiff(argv[1], argv[2], flags) + w.parent = () + else: + sys.stdout = sys.stderr + print 'usage:', argv[0], '[diff-flags] dir-1 [dir-2]' + sys.exit(2) + del w # It's preserved in gwin.windows + while 1: + try: + gwin.mainloop() + break + except KeyboardInterrupt: + pass # Just continue... + +# Start the main function (this is a script) +main() diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..f2a83bf --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,47 @@ +# Makefile for Python documentation. + +LATEX= latex +DVIPS= dvips +TEXPREVIEW= xdvi + +PRINT= lpr + +tut: tut.dvi + $(TEXPREVIEW) tut + +tut.dvi tut.ps: tut.toc tut.tex myformat.sty + +mod: mod.dvi + $(TEXPREVIEW) mod + +mod.dvi mod.ps: mod.toc mod.tex mod1.tex mod2.tex mod3.tex myformat.sty + +ALL= tut.ps mod.ps + +all: $(ALL) + +print: $(ALL) + $(PRINT) $(ALL) + +clean: + rm -f *.dvi *.aux *.toc *.log *.ps core [#@,]* *~ + +.SUFFIXES: # Remove default suffixes + +.SUFFIXES: .tex .aux .toc .dvi .ps + +.tex.aux: + $(LATEX) $* + +.tex.toc: + $(LATEX) $* + +.tex.dvi: + $(LATEX) $* + +.dvi.ps: + $(DVIPS) $* >$*.ps + +.tex.ps: + $(LATEX) $* + $(DVIPS) $* >$*.ps diff --git a/doc/README b/doc/README new file mode 100644 index 0000000..14c3de9 --- /dev/null +++ b/doc/README @@ -0,0 +1,24 @@ +This directory contains the LaTeX source to the Python documentation. +The documentation is not all finished, but good enough to get you +started. + +The following are the important latex source files: + + tut.tex A tutorial + mod.tex The library reference + +They both read the style option file "myformat.sty". + +You can use the Makefile to format, preview and print the documents. +Type "make tut" or "make mod" to preview either document with xdvi. +Type "make print" to print them both (this only works if your print +spooler is set up just like mine...), or "make all" to create postscript +files that you can you can print using your local printing commands. +Type "make clean" to get rid of all the intermediate files produced by +the latex process, and other junk files. + +You can just as well ignore the Makefile; all you really need is: + latex tut + latex tut + dvips tut | lpr +and similar for the "mod" document. diff --git a/doc/SetClass.py b/doc/SetClass.py new file mode 100644 index 0000000..8a5fb9e --- /dev/null +++ b/doc/SetClass.py @@ -0,0 +1,17 @@ +class Set(): + def new(self): + self.elements = [] + return self + def add(self, e): + if e not in self.elements: + self.elements.append(e) + def remove(self, e): + if e in self.elements: + for i in range(len(self.elements)): + if self.elements[i] = e: + del self.elements[i] + break + def is_element(self, e): + return e in self.elements + def size(self): + return len(self.elements) diff --git a/doc/fibo.py b/doc/fibo.py new file mode 100644 index 0000000..e8cafa8 --- /dev/null +++ b/doc/fibo.py @@ -0,0 +1,15 @@ +# Fibonacci numbers demo + +def fib(n): # write Fibonacci series up to n + a, b = 0, 1 + while b <= n: + print b, + a, b = b, a+b + +def fib2(n): # return Fibonacci series up to n + ret = [] + a, b = 0, 1 + while b <= n: + ret.append(b) + a, b = b, a+b + return ret diff --git a/doc/mod.tex b/doc/mod.tex new file mode 100644 index 0000000..c2d2355 --- /dev/null +++ b/doc/mod.tex @@ -0,0 +1,62 @@ +% Format this file with latex. + +%\documentstyle[garamond,11pt,myformat]{article} +\documentstyle[11pt,myformat]{article} + +% A command to force the text after an item to start on a new line +\newcommand{\itembreak}{ + \mbox{}\\*[0mm] +} + +% A command to define a function item +\newcommand{\funcitem}[2]{\item[#1(#2)]} + +% A command to define an exception item +\newcommand{\excitem}[2]{ +\item[#1 = {\tt '#2'}] +\itembreak +} + +\title{\bf + Python Library Reference \\ + (DRAFT) +} + +\author{ + Guido van Rossum \\ + Dept. CST, CWI, Kruislaan 413 \\ + 1098 SJ Amsterdam, The Netherlands \\ + E-mail: {\tt gu...@cwi.nl} +} + +\begin{document} + +\pagenumbering{roman} + +\maketitle + +\begin{abstract} + +\noindent +This document describes the built-in types, exceptions and functions and +the standard modules that come with the {\Python} system. +It assumes basic knowledge about the {\Python} language. +For an informal introduction to the language, see the Tutorial document. +The Language Reference document (XXX not yet existing) +gives a more formal reference to the language. + +\end{abstract} + +\pagebreak + +\tableofcontents + +\pagebreak + +\pagenumbering{arabic} + +\input{mod1.tex} +\input{mod2.tex} +\input{mod3.tex} + +\end{document} diff --git a/doc/mod1.tex b/doc/mod1.tex new file mode 100644 index 0000000..2dac554 --- /dev/null +++ b/doc/mod1.tex @@ -0,0 +1,521 @@ +\section{Introduction} + +The {\Python} library consists of three parts, with different levels of +integration with the interpreter. +Closest to the interpreter are built-in types, exceptions and functions. +Next are built-in modules, which are written in C and linked statically +with the interpreter. +Finally there are standard modules that are implemented entirely in +{\Python}, but are always available. +For efficiency, some standard modules may become built-in modules in +future versions of the interpreter. + +\section{Built-in Types, Exceptions and Functions} + +Names for built-in exceptions and functions are found in a separate +read-only symbol table which cannot be modified. +This table is searched last, so local and global user-defined names can +override built-in names. +Built-in types have no names but are created by syntactic constructs +(such as constants) or built-in functions. +They are described together here for easy reference.% +\footnote{ +The descriptions sorely lack explanations of the exceptions that +may be raised---this will be fixed in a future version of this +document. +} + +\subsection{Built-in Types} + +The following sections describe the standard types that are built into the +interpreter. +\subsubsection{Numeric Types} + +There are two numeric types: integers and floating point numbers. +Integers are implemented using {\tt long} in C, so they have at least 32 +bits of precision. +Floating point numbers are implemented using {\tt double} in C. +All bets on precision are off. +Numbers are created by numeric constants or as the result of built-in +functions and operators. + +Numeric types support the following operations: + +\begin{center} +\begin{tabular}{|c|l|c|} +\hline +Operation & Result & Notes \\ +\hline +{\tt abs}({\em x}) & absolute value of {\em x} & \\ +{\tt int}({\em x}) & {\em x} converted to integer & (1) \\ +{\tt float}({\em x}) & {\em x} converted to floating point & \\ +{\tt -}{\em x} & {\em x} negated & \\ +{\tt +}{\em x} & {\em x} unchanged & \\ +{\em x}{\tt +}{\em y} & sum of {\em x} and {\em y} & \\ +{\em x}{\tt -}{\em y} & difference of {\em x} and {\em y} & \\ +{\em x}{\tt *}{\em y} & product of {\em x} and {\em y} & \\ +{\em x}{\tt /}{\em y} & quotient of {\em x} and {\em y} & (2) \\ +{\em x}{\tt \%}{\em y} & remainder of {\em x}{\tt /}{\em y} & (3) \\ +\hline +\end{tabular} +\end{center} + +\noindent +Notes: +\begin{description} +\item[(1)] +This may round or truncate as in C; see functions {\tt floor} and +{\tt ceil} in module {\tt math}. +\item[(2)] +Integer division is defined as in C: the result is an integer; with +positive operands, it truncates towards zero; with a negative operand, +the result is unspecified. +\item[(3)] +Only defined for integers. +\end{description} + +Mixed arithmetic is not supported; both operands must have the same type. +Mixed comparisons return the wrong result (floats always compare smaller +than integers).% +\footnote{ +These restrictions are bugs in the language definitions and will be +fixed in the future. +} +\subsubsection{Sequence Types} + +There are three sequence types: strings, lists and tuples. +Strings constants are written in single quotes: {\tt 'xyzzy'}. +Lists are constructed with square brackets: {\tt [a,~b,~c]}. +Tuples are constructed by the comma operator or with an empty set of +parentheses: {\tt a,~b,~c} or {\tt ()}. + +Sequence types support the following operations ({\em s} and {\em t} are +sequences of the same type; {\em n}, {\em i} and {\em j} are integers): + +\begin{center} +\begin{tabular}{|c|l|c|} +\hline +Operation & Result & Notes \\ +\hline +{\tt len}({\em s}) & length of {\em s} & \\ +{\tt min}({\em s}) & smallest item of {\em s} & \\ +{\tt max}({\em s}) & largest item of {\em s} & \\ +{\em x} {\tt in} {\em s} & + true if an item of {\em s} is equal to {\em x} & \\ +{\em x} {\tt not} {\tt in} {\em s} & + false if an item of {\em s} is equal to {\em x} & \\ +{\em s}{\tt +}{\em t} & the concatenation of {\em s} and {\em t} & \\ +{\em s}{\tt *}{\em n}, {\em n}*{\em s} & + {\em n} copies of {\em s} concatenated & (1) \\ +{\em s}[{\em i}] & {\em i}'th item of {\em s} & \\ +{\em s}[{\em i}:{\em j}] & + slice of {\em s} from {\em i} to {\em j} & (2) \\ +\hline +\end{tabular} +\end{center} + +\noindent +Notes: +\begin{description} +\item[(1)] +Sequence repetition is only supported for strings. +\item[(2)] +The slice of $s$ from $i$ to $j$ is defined as the sequence +of items with index $k$ such that $i \leq k < j$. +Special rules apply for negative and omitted indices; see the Tutorial +or the Reference Manual. +\end{description} + +\paragraph{Mutable Sequence Types.} + +List objects support additional operations that allow in-place +modification of the object. +These operations would be supported by other mutable sequence types +(when added to the language) as well. +Strings and tuples are immutable sequence types and such objects cannot +be modified once created. +The following operations are defined on mutable sequence types (where +{\em x} is an arbitrary object): + +\begin{center} +\begin{tabular}{|c|l|} +\hline +Operation & Result \\ +\hline +{\em s}[{\em i}] = {\em x} & + item {\em i} of {\em s} is replaced by {\em x} \\ +{\em s}[{\em i}:{\em j}] = {\em t} & + slice of {\em s} from {\em i} to {\em j} is replaced by {\em t} \\ +{\tt del} {\em s}[{\em i}:{\em j}] & + same as {\em s}[{\em i}:{\em j}] = [] \\ +{\em s}.{\tt append}({\em x}) & + same as {\em s}[{\tt len}({\em x}):{\tt len}({\em x})] = [{\em x}] \\ +{\em s}.{\tt insert}({\em i}, {\em x}) & + same as {\em s}[{\em i}:{\em i}] = [{\em x}] \\ +{\em s}.{\tt sort}() & + the items of {\em s} are permuted to satisfy \\ + & + $s[i] \leq s[j]$ for $i < j$\\ +\hline +\end{tabular} +\end{center} + +\subsubsection{Mapping Types} + +A +{\em mapping} +object maps values of one type (the key type) to arbitrary objects. +Mappings are mutable objects. +There is currently only one mapping type, the +{\em dictionary}. +A dictionary's keys are strings. +An empty dictionary is created by the expression \verb"{}". +An extension of this notation is used to display dictionaries when +written (see the example below). + +The following operations are defined on mappings (where {\em a} is a +mapping, {\em k} is a key and {\em x} is an arbitrary object): + +\begin{center} +\begin{tabular}{|c|l|c|} +\hline +Operation & Result & Notes\\ +\hline +{\tt len}({\em a}) & the number of elements in {\em a} & \\ +{\em a}[{\em k}] & the item of {\em a} with key {\em k} & \\ +{\em a}[{\em k}] = {\em x} & set {\em a}[{\em k}] to {\em x} & \\ +{\tt del} {\em a}[{\em k}] & remove {\em a}[{\em k}] from {\em a} & \\ +{\em a}.{\tt keys}() & a copy of {\em a}'s list of keys & (1) \\ +{\em a}.{\tt has\_key}({\em k}) & true if {\em a} has a key {\em k} & \\ +\hline +\end{tabular} +\end{center} + +\noindent +Notes: +\begin{description} +\item[(1)] +Keys are listed in random order. +\end{description} + +A small example using a dictionary: +\bcode\begin{verbatim} +>>> tel = {} +>>> tel['jack'] = 4098 +>>> tel['sape'] = 4139 +>>> tel['guido'] = 4127 +>>> tel['jack'] +4098 +>>> tel +{'sape': 4139; 'guido': 4127; 'jack': 4098} +>>> del tel['sape'] +>>> tel['irv'] = 4127 +>>> tel +{'guido': 4127; 'irv': 4127; 'jack': 4098} +>>> tel.keys() +['guido', 'irv', 'jack'] +>>> tel.has_key('guido') +1 +>>> +\end{verbatim}\ecode +\subsubsection{Other Built-in Types} + +The interpreter supports several other kinds of objects. +Most of these support only one or two operations. + +\paragraph{Modules.} + +The only operation on a module is member acces: {\em m}{\tt .}{\em name}, +where {\em m} is a module and {\em name} accesses a name defined in +{\em m}'s symbol table. +Module members can be assigned to. + +\paragraph{Classes and Class Objects.} + +XXX Classes will be explained at length in a later version of this +document. + +\paragraph{Functions.} + +Function objects are created by function definitions. +The only operation on a function object is to call it: +{\em func}({\em optional-arguments}). + +Built-in functions have a different type than user-defined functions, +but they support the same operation. + +\paragraph{Methods.} + +Methods are functions that are called using the member acces notation. +There are two flavors: built-in methods (such as {\tt append()} on +lists) and class member methods. +Built-in methods are described with the types that support them. +XXX Class member methods will be described in a later version of this +document. + +\paragraph{Type Objects.} + +Type objects represent the various object types. +An object's type is accessed by the built-in function +{\tt type()}. +There are no operations on type objects. + +\paragraph{The Null Object.} + +This object is returned by functions that don't explicitly return a +value. +It supports no operations. +There is exactly one null object, named {\tt None} +(a built-in name). + +\paragraph{File Objects.} + +File objects are implemented using C's +{\em stdio} +package and can be created with the built-in function +{\tt open()}. +They have the following methods: +\begin{description} +\funcitem{close}{} +Closes the file. +A closed file cannot be read or written anymore. +\funcitem{read}{size} +Reads at most +{\tt size} +bytes from the file (less if the read hits EOF). +The bytes are returned as a string object. +An empty string is returned when EOF is hit immediately. +(For certain files, like ttys, it makes sense to continue reading after +an EOF is hit.) +\funcitem{readline}{size} +Reads a line of at most +{\tt size} +bytes from the file. +A trailing newline character, if present, is kept in the string. +The size is optional and defaults to a large number (but not infinity). +EOF is reported as by +{\tt read().} +\funcitem{write}{str} +Writes a string to the file. +Returns no value. +\end{description} + +\subsection{Built-in Exceptions} + +The following exceptions can be generated by the interpreter or +built-in functions. +Except where mentioned, they have a string argument (also known as the +`associated value' of an exception) indicating the detailed cause of the +error. +The strings listed with the exception names are their values when used +in an expression or printed. +\begin{description} +\excitem{EOFError}{end-of-file read} +(No argument.) +Raised when a built-in function ({\tt input()} or {\tt raw\_input()}) +hits an end-of-file condition (EOF) without reading any data. +(N.B.: the {\tt read()} and {\tt readline()} methods of file objects +return an empty string when they hit EOF.) +\excitem{KeyboardInterrupt}{end-of-file read} +(No argument.) +Raised when the user hits the interrupt key (normally Control-C or DEL). +During execution, a check for interrupts is made regularly. +Interrupts typed when a built-in function ({\tt input()} or +{\tt raw\_input()}) is waiting for input also raise this exception. +\excitem{MemoryError}{out of memory} +%.br +Raised when an operation runs out of memory but the situation +may still be rescued (by deleting some objects). +\excitem{NameError}{undefined name} +%.br +Raised when a name is not found. +This applies to unqualified names, module names (on {\tt import}), +module members and object methods. +The string argument is the name that could not be found. +\excitem{RuntimeError}{run-time error} +%.br +Raised for a variety of reasons, e.g., division by zero or index out of +range. +\excitem{SystemError}{system error} +%.br +Raised when the interpreter finds an internal error, but the situation +does not look so serious to cause it to abandon all hope. +\excitem{TypeError}{type error} +%.br +Raised when an operation or built-in function is applied to an object of +inappropriate type. +\end{description} + +\subsection{Built-in Functions} + +The {\Python} interpreter has a small number of functions built into it that +are always available. +They are listed here in alphabetical order. +\begin{description} +\funcitem{abs}{x} +Returns the absolute value of a number. +The argument may be an integer or floating point number. +\funcitem{chr}{i} +Returns a string of one character +whose ASCII code is the integer {\tt i}, +e.g., {\tt chr(97)} returns the string {\tt 'a'}. +This is the inverse of {\tt ord()}. +\funcitem{dir}{} +Without arguments, this function returns the list of names in the +current local symbol table, sorted alphabetically. +With a module object as argument, it returns the sorted list of names in +that module's global symbol table. +For example: +\bcode\begin{verbatim} +>>> import sys +>>> dir() +['sys'] +>>> dir(sys) +['argv', 'exit', 'modules', 'path', 'stderr', 'stdin', 'stdout'] +>>> +\end{verbatim}\ecode +\funcitem{divmod}{a, b} +%.br +Takes two integers as arguments and returns a pair of integers +consisting of their quotient and remainder. +For +\bcode\begin{verbatim} +q, r = divmod(a, b) +\end{verbatim}\ecode +the invariants are: +\bcode\begin{verbatim} +a = q*b + r +abs(r) < abs(b) +r has the same sign as b +\end{verbatim}\ecode +For example: +\bcode\begin{verbatim} +>>> divmod(100, 7) +(14, 2) +>>> divmod(-100, 7) +(-15, 5) +>>> divmod(100, -7) +(-15, -5) +>>> divmod(-100, -7) +(14, -2) +>>> +\end{verbatim}\ecode +\funcitem{eval}{s} +Takes a string as argument and parses and evaluates it as a {\Python} +expression. +The expression is executed using the current local and global symbol +tables. +Syntax errors are reported as exceptions. +For example: +\bcode\begin{verbatim} +>>> x = 1 +>>> eval('x+1') +2 +>>> +\end{verbatim}\ecode +\funcitem{exec}{s} +Takes a string as argument and parses and evaluates it as a sequence of +{\Python} statements. +The string should end with a newline (\verb"'\n'"). +The statement is executed using the current local and global symbol +tables. +Syntax errors are reported as exceptions. +For example: +\bcode\begin{verbatim} +>>> x = 1 +>>> exec('x = x+1\n') +>>> x +2 +>>> +\end{verbatim}\ecode +\funcitem{float}{x} +Converts a number to floating point. +The argument may be an integer or floating point number. +\funcitem{input}{s} +Equivalent to +{\tt eval(raw\_input(s))}. +As for +{\tt raw\_input()}, +the argument is optional. +\funcitem{int}{x} +Converts a number to integer. +The argument may be an integer or floating point number. +\funcitem{len}{s} +Returns the length (the number of items) of an object. +The argument may be a sequence (string, tuple or list) or a mapping +(dictionary). +\funcitem{max}{s} +Returns the largest item of a non-empty sequence (string, tuple or list). +\funcitem{min}{s} +Returns the smallest item of a non-empty sequence (string, tuple or list). +\funcitem{open}{name, mode} +%.br +Returns a file object (described earlier under Built-in Types). +The string arguments are the same as for stdio's +{\tt fopen()}: +{\tt 'r'} +opens the file for reading, +{\tt 'w'} +opens it for writing (truncating an existing file), +{\tt 'a'} +opens it for appending.% +\footnote{ +This function should go into a built-in module +{\tt io}. +} +\funcitem{ord}{c} +Takes a string of one character and returns its +ASCII value, e.g., {\tt ord('a')} returns the integer {\tt 97}. +This is the inverse of {\tt chr()}. +\funcitem{range}{} +This is a versatile function to create lists containing arithmetic +progressions of integers. +With two integer arguments, it returns the ascending sequence of +integers starting at the first and ending one before the second +argument. +A single argument is used as the end point of the sequence, with 0 used +as the starting point. +A third argument specifies the step size; negative steps are allowed and +work as expected, but don't specify a zero step. +The resulting list may be empty. +For example: +\bcode\begin{verbatim} +>>> range(10) +[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] +>>> range(1, 1+10) +[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +>>> range(0, 30, 5) +[0, 5, 10, 15, 20, 25] +>>> range(0, 10, 3) +[0, 3, 6, 9] +>>> range(0, -10, -1) +[0, -1, -2, -3, -4, -5, -6, -7, -8, -9] +>>> range(0) +[] +>>> range(1, 0) +[] +>>> +\end{verbatim}\ecode +\funcitem{raw\_input}{s} +%.br +The argument is optional; if present, it is written to standard output +without a trailing newline. +The function then reads a line from input, converts it to a string +(stripping a trailing newline), and returns that. +EOF is reported as an exception. +For example: +\bcode\begin{verbatim} +>>> raw_input('Type anything: ') +Type anything: Mutant Teenage Ninja Turtles +'Mutant Teenage Ninja Turtles' +>>> +\end{verbatim}\ecode +\funcitem{reload}{module} +Causes an already imported module to be re-parsed and re-initialized. +This is useful if you have edited the module source file and want to +try out the new version without leaving {\Python}. +\funcitem{type}{x} +Returns the type of an object. +Types are objects themselves: +the type of a type object is its own type. +\end{description} diff --git a/doc/mod2.tex b/doc/mod2.tex new file mode 100644 index 0000000..46f6d62 --- /dev/null +++ b/doc/mod2.tex @@ -0,0 +1,1083 @@ +\section{Built-in Modules} + +The modules described in this section are built into the interpreter. +They must be imported using +{\tt import}. +Some modules are not always available; it is a configuration option to +provide them. +Details are listed with the descriptions, but the best way to see if +a module exists in a particular implementation is to attempt to import +it. + +\subsection{Built-in Module {\tt sys}} + +This module provides access to some variables used or maintained by the +interpreter and to functions that interact strongly with the interpreter. +It is always available. +\begin{description} +\funcitem{argv} +The list of command line arguments passed to a {\Python} script. +{\tt sys.argv[0]} +is the script name. +If no script name was passed to the {\Python} interpreter, +{\tt sys.argv} +is empty. +\funcitem{exit}{n} +Exits from {\Python} with numeric exit status +{\tt n}. +This closes all open files and performs other cleanup-actions required by +the interpreter (but +{\em finally clauses} +of +{\tt try} +statements are not executed!). +\funcitem{modules} +Gives the list of modules that have already been loaded. +This can be manipulated to force reloading of modules and other tricks. +\funcitem{path} +A list of strings that specifies the search path for modules. +Initialized from the environment variable {\tt PYTHONPATH}, or an +installation-dependent default. +\funcitem{ps1,~ps2} +Strings specifying the primary and secondary prompt of the interpreter. +These are only defined if the interpreter is in interactive mode. +Their initial values in this case are +{\tt '>>> '} +and +{\tt '... '}. +\funcitem{stdin, stdout, stderr} +%.br +File objects corresponding to the interpreter's standard input, output +and error streams. +{\tt sys.stdin} +is used for all interpreter input except for scripts but including calls +to +{\tt input()} +and +{\tt raw\_input()}. +{\tt sys.stdout} +is used for the output of +{\tt print} and expression statements +and for the prompts of +{\tt input()} +and +{\tt raw\_input()}. +The interpreter's own prompts and its error messages are written to +stderr. +Assigning to +{\tt sys.stderr} +has no effect on the interpreter; it can be used to write error messages +to stderr using +{\tt print}. +\end{description} + +\subsection{Built-in Module {\tt math}} + +This module is always available. +It provides access to the mathematical functions defined by the C +standard. +They are: +{\tt acos(x)}, +{\tt asin(x)}, +{\tt atan(x)}, +{\tt atan2(x,y)}, +{\tt ceil(x)}, +{\tt cos(x)}, +{\tt cosh(x)}, +{\tt exp(x)}, +{\tt fabs(x)}, +{\tt floor(x)}, +%{\tt fmod(...)} XXX not yet +%{\tt frexp(...)} XXX not yet +%{\tt ldexp(...)} XXX not yet +{\tt log(x)}, +{\tt log10(x)}, +%{\tt modf(...)} XXX not yet +{\tt pow(x,y)}, +{\tt sin(x)}, +{\tt sinh(x)}, +{\tt sqrt(x)}, +{\tt tan(x)}, +{\tt tanh(x)}. + +It also defines two mathematical constants: +{\tt pi} +and +{\tt e}. + +\subsection{Built-in Module {\tt time}} + +This module provides various time-related functions. +It is always available. +Functions are: +\begin{description} +\funcitem{sleep}{secs} +Suspends execution for the given number of seconds. +\funcitem{time}{} +Returns the time in seconds since the Epoch (Thursday January 1, +00:00:00, 1970 UCT on \UNIX\ machines). +\end{description} + +\noindent +In some versions (Amoeba, Mac) the following functions also exist: +\begin{description} +\funcitem{millisleep}{msecs} +Suspends execution for the given number of milliseconds. +\funcitem{millitimer}{} +Returns the number of milliseconds of real time elapsed since some point +in the past that is fixed per execution of the python interpreter (but +may change in each following run). +\end{description} + +\noindent +The granularity of the milliseconds functions may be more than a +millisecond (100 msecs on Amoeba, 1/60 sec on the Mac). + +\subsection{Built-in Module {\tt regexp}} + +This module provides a regular expression matching operation. +It is always available. + +The module defines a function and an exception: + +\begin{description} + +\funcitem{compile}{pattern} + +Compile a regular expression given as a string into a regular +expression object. +The string must be an egrep-style regular expression; +this means that the characters +{\tt '(' ')' '*' '+' '?'\ '|' }\verb='^' '$'= +are special. +(It is implemented using Henry Spencer's regular expression matching +functions.) + +excitem{error}{regexp.error} + +Exception raised when a string passed to {\tt compile()} is not a +valid regular expression (e.g., unmatched parentheses) or when some other +error occurs during compilation or matching +(``no match found'' is not an error). + +\end{description} + +Compiled regular expression objects support a single method: + +\begin{description} + +\funcitem{exec}{str} + +Find the first occurrence of the compiled regular expression in the +string {\tt str}. +The return value is a tuple of pairs specifying where a match was +found and where matches were found for subpatterns specified with +{\tt '('} and {\tt ')'} in the pattern. +If no match is found, an empty tuple is returned; otherwise the first +item of the tuple is a pair of slice indices into the search string +giving the match found. +If there were any subpatterns in the pattern, the returned tuple has an +additional item for each subpattern, giving the slice indices into the +search string where that subpattern was found. + +\end{description} + +For example: +\bcode\begin{verbatim} +>>> import regexp +>>> r = regexp.compile('--(.*)--') +>>> s = 'a--b--c' +>>> r.exec(s) +((1, 6), (3, 4)) +>>> s[1:6] # The entire match +'--b--' +>>> s[3:4] # The subpattern +'b' +>>> +\end{verbatim}\ecode + +\subsection{Built-in Module {\tt posix}} + +This module provides access to operating system functionality that is +standardized by the C Standard and the POSIX standard (a thinly diguised +{\UNIX} interface). +It is available in all {\Python} versions except on the Macintosh. +Errors are reported exceptions. +It defines the following items: +\begin{description} +\funcitem{chdir}{path} +Changes the current directory to +{\tt path}. +\funcitem{chmod}{path, mode} +Change the mode of +{\tt path} +to the numeric +{\tt mode}. +\funcitem{environ} +A dictionary representing the string environment at the time +the interpreter was started. +(Modifying this dictionary does not affect the string environment of the +interpreter.) +For example, +{\tt posix.environ['HOME']} +is the pathname of your home directory, equivalent to +{\tt getenv("HOME")} +in C. +\excitem{error}{posix.error} +%.br +The exception raised when an POSIX function returns an error. +The value accompanying this exception is a pair containing the numeric +error code from +{\tt errno} +and the corresponding string, as would be printed by the C function +{\tt perror()}. +\funcitem{getcwd}{} +Returns a string representing the current working directory. +\funcitem{link}{src, dst} +Creates a hard link pointing to +{\tt src} +named +{\tt dst}. +\funcitem{listdir}{path} +Returns a list containing the names of the entries in the +directory. +The list is in arbitrary order. +It includes the special entries +{\tt '.'} +and +{\tt '..'} +if they are present in the directory. +\funcitem{mkdir}{path, mode} +Creates a directory named +{\tt path} +with numeric mode +{\tt mode}. +\funcitem{rename}{src, dst} +Renames the file or directory +{\tt src} +to +{\tt dst}. +\funcitem{rmdir}{path} +Removes the directory +{\tt path}. +\funcitem{stat}{path} +Performs a +{\em stat} +system call on the given path. +The return value is a tuple of at least 10 integers giving the most +important (and portable) members of the +{\em stat} +structure, in the order +{\tt st\_mode}, +{\tt st\_ino}, +{\tt st\_dev}, +{\tt st\_nlink}, +{\tt st\_uid}, +{\tt st\_gid}, +{\tt st\_size}, +{\tt st\_atime}, +{\tt st\_mtime}, +{\tt st\_ctime}. +More items may be added at the end by some implementations. +\funcitem{system}{command} +Executes the command (a string) in a subshell. +This is implemented by calling the Standard C function +{\tt system()}, +and has the same limitations. +Changes to +{\tt posix.environ}, +{\tt sys.stdin} +etc. are not reflected in the environment of the executed command. +The return value is the exit status of the process as returned by +Standard C +{\tt system()}. +\funcitem{umask}{mask} +Sets the current numeric umask and returns the previous umask. +\funcitem{unlink}{path} +Unlinks the file +{\tt path}. +\funcitem{utimes(path, }{atime, mtime)} +%.br +Sets the access and modified time of the file to the given values. +(The second argument is a tuple of two items.) +\end{description} + +The following functions are only available on systems that support +symbolic links: +\begin{description} +\funcitem{lstat}{path} +Like +{\tt stat()}, +but does not follow symbolic links. +\funcitem{readlink}{path} +Returns a string representing the path to which the symbolic link +points. +\funcitem{symlink}{src, dst} +Creates a symbolic link pointing to +{\tt src} +named +{\tt dst}. +\end{description} + +\subsection{Built-in Module {\tt stdwin}} + +This module defines several new object types and functions that +provide access to the functionality of the Standard Window System +Interface, STDWIN [CWI report CR-R8817]. +It is available on systems to which STDWIN has been ported (which is +most systems). +It is only available if the {\tt DISPLAY} environment variable is set +or an explicit `{\tt -display \it displayname}' argument is passed to +the interpreter. + +Functions have names that usually resemble their C STDWIN counterparts +with the initial `w' dropped. +Points are represented by pairs of integers; rectangles +by pairs of points. +For a complete description of STDWIN please refer to the documentation +of STDWIN for C programmers (aforementioned CWI report). +\subsubsection{Functions Defined in Module {\tt stdwin}} + +The following functions are defined in the {\tt stdwin} module: +\begin{description} +\funcitem{open}{title} +%.br +Opens a new window whose initial title is given by the string argument. +Returns a window object; window object methods are described below.% +\footnote{ +The {\Python} version of STDWIN does not support draw procedures; all +drawing requests are reported as draw events. +} +\funcitem{getevent}{} +%.br +Waits for and returns the next event. +An event is returned as a triple: the first element is the event +type, a small integer; the second element is the window object to which +the event applies, or +{\tt None} +if it applies to no window in particular; +the third element is type-dependent. +Names for event types and command codes are defined in the standard +module +{\tt stdwinevent}. +\funcitem{setdefwinpos}{h, v} +%.br +Sets the default window position. +\funcitem{setdefwinsize}{width, height} +%.br +Sets the default window size. +\funcitem{menucreate}{title} +%.br +Creates a menu object referring to a global menu (a menu that appears in +all windows). +Methods of menu objects are described below. +\funcitem{fleep}{} +%.br +Causes a beep or bell (or perhaps a `visual bell' or flash, hence the +name). +\funcitem{message}{string} +%.br +Displays a dialog box containing the string. +The user must click OK before the function returns. +\funcitem{askync}{prompt, default} +%.br +Displays a dialog that prompts the user to answer a question with yes or +no. +The function returns 0 for no, 1 for yes. +If the user hits the Return key, the default (which must be 0 or 1) is +returned. +If the user cancels the dialog, the +{\tt KeyboardInterrupt} +exception is raised. +\funcitem{askstr}{prompt, default} +%.br +Displays a dialog that prompts the user for a string. +If the user hits the Return key, the default string is returned. +If the user cancels the dialog, the +{\tt KeyboardInterrupt} +exception is raised. +\funcitem{askfile}{prompt, default, new} +%.br +Asks the user to specify a filename. +If +{\tt new} +is zero it must be an existing file; otherwise, it must be a new file. +If the user cancels the dialog, the +{\tt KeyboardInterrupt} +exception is raised. +\funcitem{setcutbuffer}{i, string} +%.br +Stores the string in the system's cut buffer number +{\tt i}, +where it can be found (for pasting) by other applications. +On X11, there are 8 cut buffers (numbered 0..7). +Cut buffer number 0 is the `clipboard' on the Macintosh. +\funcitem{getcutbuffer}{i} +%.br +Returns the contents of the system's cut buffer number +{\tt i}. +\funcitem{rotatebutbuffers}{n} +%.br +On X11, this rotates the 8 cut buffers by +{\tt n}. +Ignored on the Macintosh. +\funcitem{getselection}{i} +%.br +Returns X11 selection number +{\tt i.} +Selections are not cut buffers. +Selection numbers are defined in module +{\tt stdwinevents}. +Selection {\tt WS\_PRIMARY} is the +{\em primary} +selection (used by +xterm, +for instance); +selection {\tt WS\_SECONDARY} is the +{\em secondary} +selection; selection {\tt WS\_CLIPBOARD} is the +{\em clipboard} +selection (used by +xclipboard). +On the Macintosh, this always returns an empty string. +\funcitem{resetselection}{i} +%.br +Resets selection number +{\tt i}, +if this process owns it. +(See window method +{\tt setselection()}). +\funcitem{baseline}{} +%.br +Return the baseline of the current font (defined by STDWIN as the +vertical distance between the baseline and the top of the +characters).% +\footnote{ +There is no way yet to set the current font. +This will change in a future version. +} +\funcitem{lineheight}{} +%.br +Return the total line height of the current font. +\funcitem{textbreak}{str, width} +%.br +Return the number of characters of the string that fit into a space of +{\tt width} +bits wide when drawn in the curent font. +\funcitem{textwidth}{str} +%.br +Return the width in bits of the string when drawn in the current font. +\end{description} + +\subsubsection{Window Object Methods} + +Window objects are created by +{\tt stdwin.open()}. +There is no explicit function to close a window; windows are closed when +they are garbage-collected. +Window objects have the following methods: +\begin{description} +\funcitem{begindrawing}{} +Returns a drawing object, whose methods (described below) allow drawing +in the window. +\funcitem{change}{rect} +Invalidates the given rectangle; this may cause a draw event. +\funcitem{gettitle}{} +Returns the window's title string. +\funcitem{getdocsize}{} +\begin{sloppypar} +Returns a pair of integers giving the size of the document as set by +{\tt setdocsize()}. +\end{sloppypar} +\funcitem{getorigin}{} +Returns a pair of integers giving the origin of the window with respect +to the document. +\funcitem{getwinsize}{} +Returns a pair of integers giving the size of the window. +\funcitem{menucreate}{title} +Creates a menu object referring to a local menu (a menu that appears +only in this window). +Methods menu objects are described below. +\funcitem{scroll}{rect,~point} +Scrolls the given rectangle by the vector given by the point. +\funcitem{setwincursor}{name} +\begin{sloppypar} +Sets the window cursor to a cursor of the given name. +It raises the +{\tt Runtime\-Error} +exception if no cursor of the given name exists. +Suitable names are +{\tt 'ibeam'}, +{\tt 'arrow'}, +{\tt 'cross'}, +{\tt 'watch'} +and +{\tt 'plus'}. +On X11, there are many more (see +{\tt }). +\end{sloppypar} +\funcitem{setdocsize}{point} +Sets the size of the drawing document. +\funcitem{setorigin}{point} +Moves the origin of the window to the given point in the document. +\funcitem{setselection}{i, str} +Attempts to set X11 selection number +{\tt i} +to the string +{\tt str}. +(See stdwin method +{\tt getselection()} +for the meaning of +{\tt i}.) +Returns true if it succeeds. +If it succeeds, the window ``owns'' the selection until +(a) another applications takes ownership of the selection; or +(b) the window is deleted; or +(c) the application clears ownership by calling +{\tt stdwin.resetselection(i)}. +When another application takes ownership of the selection, a +{\tt WE\_LOST\_SEL} +event is received for no particular window and with the selection number +as detail. +Ignored on the Macintosh. +\funcitem{settitle}{title} +Sets the window's title string. +\funcitem{settimer}{dsecs} +Schedules a timer event for the window in +{\tt dsecs/10} +seconds. +\funcitem{show}{rect} +Tries to ensure that the given rectangle of the document is visible in +the window. +\funcitem{textcreate}{rect} +Creates a text-edit object in the document at the given rectangle. +Methods of text-edit objects are described below. +\end{description} + +\subsubsection{Drawing Object Methods} + +Drawing objects are created exclusively by the window method +{\tt begindrawing()}. +Only one drawing object can exist at any given time; the drawing object +must be deleted to finish drawing. +No drawing object may exist when +{\tt stdwin.getevent()} +is called. +Drawing objects have the following methods: +\begin{description} +\funcitem{box}{rect} +Draws a box around a rectangle. +\funcitem{circle}{center, radius} +%.br +Draws a circle with given center point and radius. +\funcitem{elarc(center, (rh, rv), }{a1, a2)} +%.br +Draws an elliptical arc with given center point. +{\tt (rh, rv)} +gives the half sizes of the horizontal and vertical radii. +{\tt (a1, a2)} +gives the angles (in degrees) of the begin and end points. +0 degrees is at 3 o'clock, 90 degrees is at 12 o'clock. +\funcitem{erase}{rect} +Erases a rectangle. +\funcitem{invert}{rect} +Inverts a rectangle. +\funcitem{line}{p1, p2} +Draws a line from point +{\tt p1} +to +{\tt p2}. +\funcitem{paint}{rect} +Fills a rectangle. +\funcitem{text}{p, str} +Draws a string starting at point p (the point specifies the +top left coordinate of the string). +\funcitem{shade}{rect, percent} +%.br +Fills a rectangle with a shading pattern that is about +{\tt percent} +percent filled. +\funcitem{xorline}{p1, p2} +Draws a line in XOR mode. +\funcitem{baseline(), lineheight(), textbreak(), textwidth}{} +%.br +These functions are similar to the corresponding functions described +above for the +{\tt stdwin} +module, but use the current font of the window instead of the (global) +default font. +\end{description} + +\subsubsection{Menu Object Methods} + +A menu object represents a menu. +The menu is destroyed when the menu object is deleted. +The following methods are defined: +\begin{description} +\funcitem{additem}{text, shortcut} +%.br +Adds a menu item with given text. +The shortcut must be a string of length 1, or omitted (to specify no +shortcut). +\funcitem{setitem}{i, text} +Sets the text of item number +{\tt i}. +\funcitem{enable}{i, flag} +Enables or disables item +{\tt i}. +\funcitem{check}{i, flag} +Sets or clears the +{\em check mark} +for item +{\tt i}. +\end{description} + +\subsubsection{Text-edit Object Methods} + +A text-edit object represents a text-edit block. +For semantics, see the STDWIN documentation for C programmers. +The following methods exist: +\begin{description} +\funcitem{arrow}{code} +Passes an arrow event to the text-edit block. +The +{\tt code} +must be one of +{\tt WC\_LEFT}, +{\tt WC\_RIGHT}, +{\tt WC\_UP} +or +{\tt WC\_DOWN} +(see module +{\tt stdwinevents}). +\funcitem{draw}{rect} +Passes a draw event to the text-edit block. +The rectangle specifies the redraw area. +\funcitem{event}{type, window, detail} +%.br +Passes an event gotten from +{\tt stdwin.getevent()} +to the text-edit block. +Returns true if the event was handled. +\funcitem{getfocus}{} +Returns 2 integers representing the start and end positions of the +focus, usable as slice indices on the string returned by +{\tt getfocustext()}. +\funcitem{getfocustext}{} +Returns the text in the focus. +\funcitem{getrect}{} +Returns a rectangle giving the actual position of the text-edit block. +(The bottom coordinate may differ from the initial position because +the block automatically shrinks or grows to fit.) +\funcitem{gettext}{} +Returns the entire text buffer. +\funcitem{move}{rect} +Specifies a new position for the text-edit block in the document. +\funcitem{replace}{str} +Replaces the focus by the given string. +The new focus is an insert point at the end of the string. +\funcitem{setfocus}{i,~j} +Specifies the new focus. +Out-of-bounds values are silently clipped. +\end{description} + +\subsubsection{Example} + +Here is a simple example of using STDWIN in Python. +It creates a window and draws the string ``Hello world'' in the top +left corner of the window. +The window will be correctly redrawn when covered and re-exposed. +The program quits when the close icon or menu item is requested. +\bcode\begin{verbatim} +import stdwin +from stdwinevents import * + +def main(): + mywin = stdwin.open('Hello') + # + while 1: + (type, win, detail) = stdwin.getevent() + if type = WE_DRAW: + draw = win.begindrawing() + draw.text((0, 0), 'Hello, world') + del draw + elif type = WE_CLOSE: + break + +main() +\end{verbatim}\ecode + +\subsection{Built-in Module {\tt amoeba}} + +This module provides some object types and operations useful for +Amoeba applications. +It is only available on systems that support Amoeba operations. +RPC errors and other Amoeba errors are reported as the exception +{\tt amoeba.error = 'amoeba.error'}. +The module +{\tt amoeba} +defines the following items: +\begin{description} +\funcitem{name\_append}{path,~cap} +%.br +Stores a capability in the Amoeba directory tree. +Arguments are the pathname (a string) and the capability (a capability +object as returned by +{\tt name\_lookup()}). +\funcitem{name\_delete}{path} +%.br +Deletes a capability from the Amoeba directory tree. +Argument is the pathname. +\funcitem{name\_lookup}{path} +%.br +Looks up a capability. +Argument is the pathname. +Returns a +{\em capability} +object, to which various interesting operations apply, described below. +\funcitem{name\_replace}{path,~cap} +%.br +Replaces a capability in the Amoeba directory tree. +Arguments are the pathname and the new capability. +(This differs from +{\tt name\_append()} +in the behavior when the pathname already exists: +{\tt name\_append()} +finds this an error while +{\tt name\_replace()} +allows it, as its name suggests.) +\funcitem{capv} +A table representing the capability environment at the time the +interpreter was started. +(Alas, modifying this table does not affect the capability environment +of the interpreter.) +For example, +{\tt amoeba.capv['ROOT']} +is the capability of your root directory, similar to +{\tt getcap("ROOT")} +in C. +\excitem{error}{amoeba.error} +%.br +The exception raised when an Amoeba function returns an error. +The value accompanying this exception is a pair containing the numeric +error code and the corresponding string, as returned by the C function +{\tt err\_why()}. +\funcitem{timeout}{msecs} +%.br +Sets the transaction timeout, in milliseconds. +Returns the previous timeout. +Initially, the timeout is set to 2 seconds by the {\Python} interpreter. +\end{description} + +\subsubsection{Capability Operations} + +Capabilities are written in a convenient ASCII format, also used by the +Amoeba utilities +{\em c2a}(U) +and +{\em a2c}(U). +For example: +\bcode\begin{verbatim} +>>> amoeba.name_lookup('/profile/cap') +aa:1c:95:52:6a:fa/14(ff)/8e:ba:5b:8:11:1a +>>> +\end{verbatim}\ecode +The following methods are defined for capability objects. +\begin{description} +\funcitem{dir\_list}{} +Returns a list of the names of the entries in an Amoeba directory. +\funcitem{b\_read}{offset, maxsize} +%.br +Reads (at most) +{\tt maxsize} +bytes from a bullet file at offset +{\tt offset.} +The data is returned as a string. +EOF is reported as an empty string. +\funcitem{b\_size}{} +Returns the size of a bullet file. +\funcitem{dir\_append(), dir\_delete(), dir\_lookup(), dir\_replace}{} +%.br +\itembreak +Like the corresponding +{\tt name\_*} +functions, but with a path relative to the capability. +(For paths beginning with a slash the capability is ignored, since this +is the defined semantics for Amoeba.) +\funcitem{std\_info}{} +Returns the standard info string of the object. +\funcitem{tod\_gettime}{} +Returns the time (in seconds since the Epoch, in UCT, as for POSIX) from +a time server. +\funcitem{tod\_settime}{t} +Sets the time kept by a time server. +\end{description} + +\subsection{Built-in Module {\tt audio}} + +This module provides rudimentary access to the audio I/O device +{\tt /dev/audio} +on the Silicon Graphics Personal IRIS; see audio(7). +It supports the following operations: +\begin{description} +\funcitem{setoutgain}{n} +Sets the output gain (0-255). +\funcitem{getoutgain}{} +Returns the output gain. +\funcitem{setrate}{n} +Sets the sampling rate: 1=32K/sec, 2=16K/sec, 3=8K/sec. +\funcitem{setduration}{n} +Sets the `sound duration' in units of 1/100 seconds. +\funcitem{read}{n} +Reads a chunk of +{\tt n} +sampled bytes from the audio input (line in or microphone). +The chunk is returned as a string of length n. +Each byte encodes one sample as a signed 8-bit quantity using linear +encoding. +This string can be converted to numbers using {\tt chr2num()} described +below. +\funcitem{write}{buf} +Writes a chunk of samples to the audio output (speaker). +\end{description} + +These operations support asynchronous audio I/O: +\begin{description} +\funcitem{start\_recording}{n} +%.br +Starts a second thread (a process with shared memory) that begins reading +{\tt n} +bytes from the audio device. +The main thread immediately continues. +\funcitem{wait\_recording}{} +%.br +Waits for the second thread to finish and returns the data read. +\funcitem{stop\_recording}{} +%.br +Makes the second thread stop reading as soon as possible. +Returns the data read so far. +\funcitem{poll\_recording}{} +%.br +Returns true if the second thread has finished reading (so +{\tt wait\_recording()} would return the data without delay). +\item[{\tt start\_playing(chunk)}, {\tt wait\_playing()}, +{\tt stop\_playing()}, {\tt poll\_playing()}] +%.br +\begin{sloppypar} +Similar but for output. +{\tt stop\_playing()} +returns a lower bound for the number of bytes actually played (not very +accurate). +\end{sloppypar} +\end{description} + +The following operations do not affect the audio device but are +implemented in C for efficiency: +\begin{description} +\funcitem{amplify}{buf, f1, f2} +%.br +Amplifies a chunk of samples by a variable factor changing from +{\tt f1}/256 to {\tt f2}/256. +Negative factors are allowed. +Resulting values that are to large to fit in a byte are clipped. +\funcitem{reverse}{buf} +%.br +Returns a chunk of samples backwards. +\funcitem{add}{buf1, buf2} +%.br +Bytewise adds two chunks of samples. +Bytes that exceed the range are clipped. +If one buffer shorter, it is assumed to be padded with zeros. +\funcitem{chr2num}{buf} +%.br +Converts a string of sampled bytes as returned by {\tt read()} into +a list containing the numeric values of the samples. +\funcitem{num2chr}{list} +%.br +\begin{sloppypar} +Converts a list as returned by +{\tt chr2num()} +back to a buffer acceptable by +{\tt write()}. +\end{sloppypar} +\end{description} + +\subsection{Built-in Module {\tt gl}} + +This module provides access to the Silicon Graphics +{\em Graphics Library}. +It is available only on Silicon Graphics machines. + +{\bf Warning:} +Some illegal calls to the GL library cause the {\Python} interpreter to dump +core. +In particular, the use of most GL calls is unsafe before the first +window is opened. + +The module is too large to document here in its entirety, but the +following should help you to get started. +The parameter conventions for the C functions are translated to {\Python} as +follows: + +\begin{itemize} +\item +All (short, long, unsigned) int values are represented by {\Python} +integers. +\item +All float and double values are represented by {\Python} floating point +numbers. +In most cases, {\Python} integers are also allowed. +\item +All arrays are represented by one-dimensional {\Python} lists. +In most cases, tuples are also allowed. +\item +\begin{sloppypar} +All string and character arguments are represented by {\Python} strings, +for instance, +{\tt winopen('Hi~There!')} +and +{\tt rotate(900,~'z')}. +\end{sloppypar} +\item +All (short, long, unsigned) integer arguments or return values that are +only used to specify the length of an array argument are omitted. +For example, the C call +\bcode\begin{verbatim} +lmdef(deftype, index, np, props) +\end{verbatim}\ecode +is translated to {\Python} as +\bcode\begin{verbatim} +lmdef(deftype, index, props) +\end{verbatim}\ecode +\item +Output arguments are omitted from the argument list; they are +transmitted as function return values instead. +If more than one value must be returned, the return value is a tuple. +If the C function has both a regular return value (that is not omitted +because of the previous rule) and an output argument, the return value +comes first in the tuple. +Examples: the C call +\bcode\begin{verbatim} +getmcolor(i, &red, &green, &blue) +\end{verbatim}\ecode +is translated to {\Python} as +\bcode\begin{verbatim} +red, green, blue = getmcolor(i) +\end{verbatim}\ecode +\end{itemize} + +The following functions are non-standard or have special argument +conventions: +\begin{description} +\funcitem{varray}{} +Equivalent to but faster than a number of +{\tt v3d()} +calls. +The argument is a list (or tuple) of points. +Each point must be a tuple of coordinates (x, y, z) or (x, y). +The points may be 2- or 3-dimensional but must all have the +same dimension. +Float and int values may be mixed however. +The points are always converted to 3D double precision points +by assuming z=0.0 if necessary (as indicated in the man page), +and for each point +{\tt v3d()} +is called. +\funcitem{nvarray}{} +Equivalent to but faster than a number of +{\tt n3f} +and +{\tt v3f} +calls. +The argument is an array (list or tuple) of pairs of normals and points. +Each pair is a tuple of a point and a normal for that point. +Each point or normal must be a tuple of coordinates (x, y, z). +Three coordinates must be given. +Float and int values may be mixed. +For each pair, +{\tt n3f()} +is called for the normal, and then +{\tt v3f()} +is called for the point. +\funcitem{vnarray}{} +Similar to +{\tt nvarray()} +but the pairs have the point first and the normal second. +\funcitem{nurbssurface}{s\_k[], t\_k[], ctl[][], s\_ord, t\_ord, type} +%.br +\itembreak +Defines a nurbs surface. +The dimensions of +{\tt ctl[][]} +are computed as follows: +{\tt [len(s\_k)~-~s\_ord]}, +{\tt [len(t\_k)~-~t\_ord]}. +\funcitem{nurbscurve}{knots, ctlpoints, order, type} +%.br +Defines a nurbs curve. +The length of ctlpoints is +{\tt len(knots)~-~order}. +\funcitem{pwlcurve}{points, type} +%.br +Defines a piecewise-linear curve. +{\tt points} +is a list of points. +{\tt type} +must be +{\tt N\_ST}. +\funcitem{pick(n), select}{n} +%.br +The only argument to these functions specifies the desired size of the +pick or select buffer. +\funcitem{endpick(), endselect}{} +%.br +These functions have no arguments. +They return a list of integers representing the used part of the +pick/select buffer. +No method is provided to detect buffer overrun. +\end{description} + +Here is a tiny but complete example GL program in {\Python}: +\bcode\begin{verbatim} +import gl, GL, time + +def main(): + gl.foreground() + gl.prefposition(500, 900, 500, 900) + w = gl.winopen('CrissCross') + gl.ortho2(0.0, 400.0, 0.0, 400.0) + gl.color(GL.WHITE) + gl.clear() + gl.color(GL.RED) + gl.bgnline() + gl.v2f(0.0, 0.0) + gl.v2f(400.0, 400.0) + gl.endline() + gl.bgnline() + gl.v2f(400.0, 0.0) + gl.v2f(0.0, 400.0) + gl.endline() + time.sleep(5) + +main() +\end{verbatim}\ecode + +\subsection{Built-in Module {\tt pnl}} + +This module provides access to the +{\em Panel Library} +built by NASA Ames (to get it, send e-mail to +{\tt panel-...@nas.nasa.gov}). +All access to it should be done through the standard module +{\tt panel}, +which transparantly exports most functions from +{\tt pnl} +but redefines +{\tt pnl.dopanel()}. + +{\bf Warning:} +the {\Python} interpreter will dump core if you don't create a GL window +before calling +{\tt pnl.mkpanel()}. + +The module is too large to document here in its entirety. diff --git a/doc/mod3.tex b/doc/mod3.tex new file mode 100644 index 0000000..d1a99b1 --- /dev/null +++ b/doc/mod3.tex @@ -0,0 +1,484 @@ +\section{Standard Modules} + +The following standard modules are defined. +They are available in one of the directories in the default module +search path (try printing +{\tt sys.path} +to find out the default search path.) + +\subsection{Standard Module {\tt string}} + +This module defines some constants useful for checking character +classes, some exceptions, and some useful string functions. +The constants are: +\begin{description} +\funcitem{digits} +The string +{\tt '0123456789'}. +\funcitem{hexdigits} +The string +{\tt '0123456789abcdefABCDEF'}. +\funcitem{letters} +The concatenation of the strings +{\tt lowercase} +and +{\tt uppercase} +described below. +\funcitem{lowercase} +The string +{\tt 'abcdefghijklmnopqrstuvwxyz'}. +\funcitem{octdigits} +The string +{\tt '01234567'}. +\funcitem{uppercase} +The string +{\tt 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'}. +\funcitem{whitespace} +A string containing all characters that are considered whitespace, +i.e., +space, tab and newline. +This definition is used by +{\tt split()} +and +{\tt strip()}. +\end{description} + +The exceptions are: +\begin{description} +\excitem{atoi\_error}{non-numeric argument to string.atoi} +%.br +Exception raised by +{\tt atoi} +when a non-numeric string argument is detected. +The exception argument is the offending string. +\excitem{index\_error}{substring not found in string.index} +%.br +Exception raised by +{\tt index} +when +{\tt sub} +is not found. +The argument are the offending arguments to index: {\tt (s, sub)}. +\end{description} + +The functions are: +\begin{description} +\funcitem{atoi}{s} +Converts a string to a number. +The string must consist of one or more digits, optionally preceded by a +sign ({\tt '+'} or {\tt '-'}). +\funcitem{index}{s, sub} +Returns the lowest index in +{\tt s} +where the substring +{\tt sub} +is found. +\funcitem{lower}{s} +Convert letters to lower case. +\funcitem{split}{s} +Returns a list of the whitespace-delimited words of the string +{\tt s}. +\funcitem{splitfields}{s, sep} +%.br +Returns a list containing the fields of the string +{\tt s}, +using the string +{\tt sep} +as a separator. +The list will have one more items than the number of non-overlapping +occurrences of the separator in the string. +Thus, +{\tt string.splitfields(s, ' ')} +is not the same as +{\tt string.split(s)}, +as the latter only returns non-empty words. +\funcitem{strip}{s} +Removes leading and trailing whitespace from the string +{\tt s}. +\funcitem{swapcase}{s} +Converts lower case letters to upper case and vice versa. +\funcitem{upper}{s} +Convert letters to upper case. +\funcitem{ljust(s, width), rjust(s, width), center}{s, width} +%.br +These functions respectively left-justify, right-justify and center a +string in a field of given width. +They return a string that is at least +{\tt width} +characters wide, created by padding the string +{\tt s} +with spaces until the given width on the right, left or both sides. +The string is never truncated. +\end{description} + +\subsection{Standard Module {\tt path}} + +This module implements some useful functions on POSIX pathnames. +\begin{description} +\funcitem{basename}{p} +Returns the base name of pathname +{\tt p}. +This is the second half of the pair returned by +{\tt path.split(p)}. +\funcitem{cat}{p, q} +Performs intelligent pathname concatenation on paths +{\tt p} +and +{\tt q}: +If +{\tt q} +is an absolute path, the return value is +{\tt q}. +Otherwise, the concatenation of +{\tt p} +and +{\tt q} +is returned, with a slash ({\tt '/'}) inserted unless +{\tt p} +is empty or ends in a slash. +\funcitem{commonprefix}{list} +%.br +Returns the longest string that is a prefix of all strings in +{\tt list}. +If +{\tt list} +is empty, the empty string ({\tt ''}) is returned. +\funcitem{exists}{p} +Returns true if +{\tt p} +refers to an existing path. +\funcitem{isdir}{p} +Returns true if +{\tt p} +refers to an existing directory. +\funcitem{islink}{p} +Returns true if +{\tt p} +refers to a directory entry that is a symbolic link. +Always false if symbolic links are not supported. +\funcitem{ismount}{p} +Returns true if +{\tt p} +is an absolute path that occurs in the mount table as output by the +{\tt /etc/mount} +utility. +This output is read once when the function is used for the first +time.% +\footnote{ +Is there a better way to check for mount points? +} +\funcitem{split}{p} +Returns a pair +{\tt (head,~tail)} +such that +{\tt tail} +contains no slashes and +{\tt path.cat(head, tail)} +is equal to +{\tt p}. +\funcitem{walk}{p, visit, arg} +%.br +Calls the function +{\tt visit} +with arguments +{\tt (arg, dirname, names)} +for each directory in the directory tree rooted at +{\tt p} +(including +{\tt p} +itself, if it is a directory). +The argument +{\tt dirname} +specifies the visited directory, the argument +{\tt names} +lists the files in the directory (gotten from +{\tt posix.listdir(dirname)}). +The +{\tt visit} +function may modify +{\tt names} +to influence the set of directories visited below +{\tt dirname}, +e.g., +to avoid visiting certain parts of the tree. +(The object referred to by +{\tt names} +must be modified in place, using +{\tt del} +or slice assignment.) +\end{description} + +\subsection{Standard Module {\tt getopt}} + +This module helps scripts to parse the command line arguments in +{\tt sys.argv}. +It uses the same conventions as the {\UNIX} +{\tt getopt()} +function. +It defines the function +{\tt getopt.getopt(args, options)} +and the exception +{\tt getopt.error}. + +The first argument to +{\tt getopt()} +is the argument list passed to the script with its first element +chopped off (i.e., +{\tt sys.argv[1:]}). +The second argument is the string of option letters that the +script wants to recognize, with options that require an argument +followed by a colon (i.e., the same format that {\UNIX} +{\tt getopt()} +uses). +The return value consists of two elements: the first is a list of +option-and-value pairs; the second is the list of program arguments +left after the option list was stripped (this is a trailing slice of the +first argument). +Each option-and-value pair returned has the option as its first element, +prefixed with a hyphen (e.g., +{\tt '-x'}), +and the option argument as its second element, or an empty string if the +option has no argument. +The options occur in the list in the same order in which they were +found, thus allowing multiple occurrences. +Example: +\bcode\begin{verbatim} +>>> import getopt, string +>>> args = string.split('-a -b -cfoo -d bar a1 a2') +>>> args +['-a', '-b', '-cfoo', '-d', 'bar', 'a1', 'a2'] +>>> optlist, args = getopt.getopt(args, 'abc:d:') +>>> optlist +[('-a', ''), ('-b', ''), ('-c', 'foo'), ('-d', 'bar')] +>>> args +['a1', 'a2'] +>>> +\end{verbatim}\ecode +The exception +{\tt getopt.error = 'getopt error'} +is raised when an unrecognized option is found in the argument list or +when an option requiring an argument is given none. +The argument to the exception is a string indicating the cause of the +error. + +\subsection{Standard Module {\tt rand}} + +This module implements a pseudo-random number generator similar to +{\tt rand()} +in C. +It defines the following functions: +\begin{description} +\funcitem{rand}{} +Returns an integer random number in the range [0 ... 32768). +\funcitem{choice}{s} +Returns a random element from the sequence (string, tuple or list) +{\tt s.} +\funcitem{srand}{seed} +Initializes the random number generator with the given integral seed. +When the module is first imported, the random number is initialized with +the current time. +\end{description} + +\subsection{Standard Module {\tt whrandom}} + +This module implements a Wichmann-Hill pseudo-random number generator. +It defines the following functions: +\begin{description} +\funcitem{random}{} +Returns the next random floating point number in the range [0.0 ... 1.0). +\funcitem{seed}{x, y, z} +Initializes the random number generator from the integers +{\tt x}, +{\tt y} +and +{\tt z}. +When the module is first imported, the random number is initialized +using values derived from the current time. +\end{description} + +\subsection{Standard Module {\tt stdwinevents}} + +This module defines constants used by STDWIN for event types +({\tt WE\_ACTIVATE} etc.), command codes ({\tt WC\_LEFT} etc.) +and selection types ({\tt WS\_PRIMARY} etc.). +Read the file for details. +Suggested usage is +\bcode\begin{verbatim} +>>> from stdwinevents import * +>>> +\end{verbatim}\ecode + +\subsection{Standard Module {\tt rect}} + +This module contains useful operations on rectangles. +A rectangle is defined as in module +{\tt stdwin}: +a pair of points, where a point is a pair of integers. +For example, the rectangle +\bcode\begin{verbatim} +(10, 20), (90, 80) +\end{verbatim}\ecode +is a rectangle whose left, top, right and bottom edges are 10, 20, 90 +and 80, respectively. +Note that the positive vertical axis points down (as in +{\tt stdwin}). + +The module defines the following objects: +\begin{description} +\excitem{error}{rect.error} +%.br +The exception raised by functions in this module when they detect an +error. +The exception argument is a string describing the problem in more +detail. +\funcitem{empty} +%.br +The rectangle returned when some operations return an empty result. +This makes it possible to quickly check whether a result is empty: +\bcode\begin{verbatim} +>>> import rect +>>> r1 = (10, 20), (90, 80) +>>> r2 = (0, 0), (10, 20) +>>> r3 = rect.intersect(r1, r2) +>>> if r3 is rect.empty: print 'Empty intersection' +Empty intersection +>>> +\end{verbatim}\ecode +\funcitem{is\_empty}{r} +%.br +Returns true if the given rectangle is empty. +A rectangle +{\em (left,~top), (right,~bottom)} +is empty if +{\em left~$\geq$~right} +or +{\em top~$\leq$~bottom}. +\funcitem{intersect}{list} +%.br +Returns the intersection of all rectangles in the list argument. +It may also be called with a tuple argument or with two or more +rectangles as arguments. +Raises +{\tt rect.error} +if the list is empty. +Returns +{\tt rect.empty} +if the intersection of the rectangles is empty. +\funcitem{union}{list} +%.br +Returns the smallest rectangle that contains all non-empty rectangles in +the list argument. +It may also be called with a tuple argument or with two or more +rectangles as arguments. +Returns +{\tt rect.empty} +if the list is empty or all its rectangles are empty. +\funcitem{pointinrect}{point, rect} +%.br +Returns true if the point is inside the rectangle. +By definition, a point +{\em (h,~v)} +is inside a rectangle +{\em (left,~top),} +{\em (right,~bottom)} +if +{\em left~$\leq$~h~$<$~right} +and +{\em top~$\leq$~v~$<$~bottom}. +\funcitem{inset(rect, }{dh, dv)} +%.br +Returns a rectangle that lies inside the +{\tt rect} +argument by +{\tt dh} +pixels horizontally +and +{\tt dv} +pixels +vertically. +If +{\tt dh} +or +{\tt dv} +is negative, the result lies outside +{\tt rect}. +\funcitem{rect2geom}{rect} +%.br +Converts a rectangle to geometry representation: +{\em (left,~top),} +{\em (width,~height)}. +\funcitem{geom2rect}{geom} +%.br +Converts a rectangle given in geometry representation back to the +standard rectangle representation +{\em (left,~top),} +{\em (right,~bottom)}. +\end{description} + +\subsection{Standard Modules {\tt GL} and {\tt DEVICE}} + +These modules define the constants used by the Silicon Graphics +{\em Graphics Library} +that C programmers find in the header files +{\tt } +and +{\tt }. +Read the module files for details. + +\subsection{Standard Module {\tt panel}} + +This module should be used instead of the built-in module +{\tt pnl} +to interface with the +{\em Panel Library}. + +The module is too large to document here in its entirety. +One interesting function: +\begin{description} +\funcitem{defpanellist}{filename} +%.br +Parses a panel description file containing S-expressions written by the +{\em Panel Editor} +that accompanies the Panel Library and creates the described panels. +It returns a list of panel objects. +\end{description} + +{\bf Warning:} +the {\Python} interpreter will dump core if you don't create a GL window +before calling +{\tt panel.mkpanel()} +or +{\tt panel.defpanellist()}. + +\subsection{Standard Module {\tt panelparser}} + +This module defines a self-contained parser for S-expressions as output +by the Panel Editor (which is written in Scheme so it can't help writing +S-expressions). +The relevant function is +{\tt panelparser.parse\_file(file)} +which has a file object (not a filename!) as argument and returns a list +of parsed S-expressions. +Each S-expression is converted into a {\Python} list, with atoms converted +to {\Python} strings and sub-expressions (recursively) to {\Python} lists. +For more details, read the module file. + +\section{P.M.} + +\begin{verse} + +commands + +cmp? + +*cache? + +localtime? + +calendar? + +\_\_dict? + +mac? + +\end{verse} diff --git a/doc/myformat.sty b/doc/myformat.sty new file mode 100644 index 0000000..be70239 --- /dev/null +++ b/doc/myformat.sty @@ -0,0 +1,34 @@ +% Style parameters and macros used by all documents here + +% Page lay-out parameters +\textwidth = 160mm +\textheight = 240mm +\topmargin = -11mm +\oddsidemargin = 0mm +\evensidemargin = 0mm +%\parindent = 0mm + +% Frequently used system names +\newcommand{\Python}{Python} % Sometimes I want this italicized +\newcommand{\UNIX}{U{\sc nix}} + +% Variable used by begin code command +\newlength{\codewidth} + +\newcommand{\bcode}{ + % Calculate the text width for the minipage: + \setlength{\codewidth}{\linewidth} + \addtolength{\codewidth}{-\parindent} + % + \vspace{3mm} + \par + \indent + \begin{minipage}[t]{\codewidth} +} + +\newcommand{\ecode}{ + \end{minipage} + \vspace{3mm} + \par + \noindent +} diff --git a/doc/pytry b/doc/pytry new file mode 100755 index 0000000..dcc3f84 --- /dev/null +++ b/doc/pytry @@ -0,0 +1,20 @@ +TMP=/usr/tmp/pytry$$ +trap 'rm -f $TMP; exit 1' 1 2 3 13 14 15 + +cat $* >$TMP + +( + cat $TMP + + sed ' + s/^>>> // + s/^>>>$// + s/^\.\.\. // + s/^\.\.\.$// + ' $TMP | + python + + echo '>>> ' +) 2>&1 + +rm $TMP diff --git a/doc/tut.tex b/doc/tut.tex new file mode 100644 index 0000000..ad5f56c --- /dev/null +++ b/doc/tut.tex @@ -0,0 +1,1550 @@ +% Format this file with latex. + +%\documentstyle[garamond,11pt,myformat]{article} +\documentstyle[11pt,myformat]{article} + +\title{\bf + Python Tutorial \\ + (DRAFT) +} + +\author{ + Guido van Rossum \\ + Dept. CST, CWI, Kruislaan 413 \\ + 1098 SJ Amsterdam, The Netherlands \\ + E-mail: {\tt gu...@cwi.nl} +} + +\begin{document} + +\pagenumbering{roman} + +\maketitle + +\begin{abstract} + +\noindent +\Python\ is a simple, yet powerful programming language that bridges the +gap between C and shell programming, and is thus ideally suited for rapid +prototyping. +Its syntax is put together from constructs borrowed from a variety of other +languages; most prominent are influences from ABC, C, Modula-3 and Icon. + +The \Python\ interpreter is easily extended with new functions and data +types implemented in C. +\Python\ is also suitable as an extension language for highly +customizable C applications such as editors or window managers. + +\Python\ is available for various operating systems, amongst which +several flavors of \UNIX, Amoeba, and the Apple Macintosh O.S. + +This tutorial introduces the reader informally to the basic concepts and +features of the \Python\ language and system. +It helps to have a \Python\ interpreter handy for hands-on experience, +but as the examples are self-contained, the tutorial can be read +off-line as well. + +For a description of standard objects and modules, see the Library +Reference document. +The Language Reference document (XXX not yet existing) +gives a more formal reference to the language. + +\end{abstract} + +\pagebreak + +\tableofcontents + +\pagebreak + +\pagenumbering{arabic} + +\section{Whetting Your Appetite} + +If you ever wrote a large shell script, you probably know this feeling: +you'd love to add yet another feature, but it's already so slow, and so +big, and so complicated; or the feature involves a system call or other +funcion that is only accessible from C \ldots +Usually the problem at hand isn't serious enough to warrant rewriting +the script in C; perhaps because the problem requires variable-length +strings or other data types (like sorted lists of file names) that +are easy in the shell but lots of work to implement in C; or perhaps +just because you're not sufficiently familiar with C. + +In all such cases, \Python\ is just the language for you. +\Python\ is simple to use, but it is a real programming language, offering +much more structure and support for large programs than the shell has. +On the other hand, it also offers much more error checking than C, and, +being a +{\em very-high-level language}, +it has high-level data types built in, such as flexible arrays and +dictionaries that would cost you days to implement efficiently in C. +Because of its more general data types \Python\ is applicable to a +much larger problem domain than +{\em Awk} +or even +{\em Perl}, +yet most simple things are at least as easy in \Python\ as in those +languages. + +\Python\ allows you to split up your program in modules that can be reused +in other \Python\ programs. +It comes with a large collection of standard modules that you can use as +the basis for your programs --- or as examples to start learning to +program in \Python. +There are also built-in modules that provide things like file I/O, +system calls, and even a generic interface to window systems (STDWIN). + +\Python\ is an interpreted language, which saves you considerable time +during program development because no compilation and linking is +necessary. +The interpreter can be used interactively, which makes it easy to +experiment with features of the language, to write throw-away programs, +or to test functions during bottom-up program development. +It is also a handy desk calculator. + +\Python\ allows writing very compact and readable programs. +Programs written in \Python\ are typically much shorter than equivalent C +programs: +No declarations are necessary (all type checking is +dynamic); statement grouping is done by indentation instead of begin/end +brackets; and the high-level data types allow you to express complex +operations in a single statement. + +\Python\ is +{\em extensible}: +if you know how to program in C it is easy to add a new built-in module +to the interpreter, either to perform critical operations at maximum +speed, or to link \Python\ programs to libraries that may be only available +in binary form (such as a vendor-specific graphics library). +Once you are really hooked, you can link the \Python\ interpreter into an +application written in C and use it as an extension or command language. + +\subsection{Where From Here} + +Now that you are all excited about \Python, you'll want to examine it in +some more detail. +Since the best introduction to a language is using it, you are invited +here to do so. + +In the next section, the mechanics of using the interpreter are +explained. +This is rather mundane information, but essential for trying out the +examples shown later. +The rest of the tutorial introduces various features of the \Python\ +language and system though examples, beginning with simple expressions, +statements and data types, through functions and modules, and finally +touching upon advanced concepts like exceptions and classes. + +\section{Using the Python Interpreter} + +The \Python\ interpreter is usually installed as +{\tt /usr/local/python} +on those machines where it is available; putting +{\tt /usr/local} +in your \UNIX\ shell's search path makes it possible to start it by +typing the command +\bcode\begin{verbatim} +python +\end{verbatim}\ecode +to the shell. +Since the choice of the directory where the interpreter lives is an +installation option, other places instead of +{\tt /usr/local} +are possible; check with your local \Python\ guru or system +administrator.% +\footnote{ + At CWI, at the time of writing, the interpreter can be found in + the following places: + On the Amoeba Ultrix machines, use the standard path, + {\tt /usr/local/python}. + On the Sun file servers, use + {\tt /ufs/guido/bin/}{\em arch}{\tt /python}, + where {\em arch} can be {\tt sgi} or {\tt sun4}. + On piring, use {\tt /userfs3/amoeba/bin/python}. + (If you can't find a binary advertised here, get in touch with me.) +} + +The interpreter operates somewhat like the \UNIX\ shell: when called with +standard input connected to a tty device, it reads and executes commands +interactively; when called with a file name argument or with a file as +standard input, it reads and executes a +{\em script} +from that file.% +\footnote{ + There is a difference between ``{\tt python file}'' and + ``{\tt python $<$file}''. In the latter case {\tt input()} and + {\tt raw\_input()} are satisfied from {\em file}, which has + already been read until the end by the parser, so they will read + EOF immediately. In the former case (which is usually what + you want) they are satisfied from whatever file or device is + connected to standard input of the \Python\ interpreter. +} +If available, the script name and additional arguments thereafter are +passed to the script in the variable +{\tt sys.argv}, +which is a list of strings. + +When standard input is a tty, the interpreter is said to be in +{\em interactive\ mode}. +In this mode it prompts for the next command with the +{\em primary\ prompt}, +usually three greater-than signs ({\tt >>>}); for continuation lines +it prompts with the +{\em secondary\ prompt}, +by default three dots ({\tt ...}). +Typing an EOF (Control-D) at the primary prompt causes the interpreter +to exit with a zero exit status. + +When an error occurs in interactive mode, the interpreter prints a +message and a stack trace and returns to the primary prompt; with input +from a file, it exits with a nonzero exit status. +(Exceptions handled by an +{\tt except} +clause in a +{\tt try} +statement are not errors in this context.) +Some errors are unconditionally fatal and cause an exit with a nonzero +exit; this applies to internal inconsistencies and some cases of running +out of memory. +All error messages are written to the standard error stream; normal +output from the executed commands is written to standard output. + +Typing an interrupt (normally Control-C or DEL) to the primary or +secondary prompt cancels the input and returns to the primary prompt. +Typing an interrupt while a command is being executed raises the +{\tt KeyboardInterrupt} +exception, which may be handled by a +{\tt try} +statement. + +When a module named +{\tt foo} +is imported, the interpreter searches for a file named +{\tt foo.py} +in a list of directories specified by the environment variable +{\tt PYTHONPATH}. +It has the same syntax as the \UNIX\ shell variable +{\tt PATH}, +i.e., a list of colon-separated directory names. +When +{\tt PYTHONPATH} +is not set, an installation-dependent default path is used, usually +{\tt .:/usr/local/lib/python}.% +\footnote{ + Modules are really searched in the list of directories given by + the variable {\tt sys.path} which is initialized from + {\tt PYTHONPATH} or from the installation-dependent default. + See the section on Standard Modules later. +} + +On BSD'ish \UNIX\ systems, \Python\ scripts can be made directly executable, +like shell scripts, by putting the line +\bcode\begin{verbatim} +#! /usr/local/python +\end{verbatim}\ecode +(assuming that's the name of the interpreter) at the beginning of the +script and giving the file an executable mode. +(The +{\tt \#!} +must be the first two characters of the file.) + +\subsection{Interactive Input Editing and History Substitution} + +Some versions of the \Python\ interpreter support editing of the current +input line and history substitution, similar to facilities found in the +Korn shell and the GNU Bash shell. +This is implemented using the +{\em GNU\ Readline} +library, which supports Emacs-style and vi-style editing. +This library has its own documentation which I won't duplicate here; +however, the basics are easily explained. + +If supported,% +\footnote{ + Perhaps the quickest check to see whether command line editing + is supported is typing Control-P to the first \Python\ prompt + you get. If it beeps, you have command line editing. + If not, you can skip the rest of this section. +} +input line editing is active whenever the interpreter prints a primary +or secondary prompt. +The current line can be edited using the conventional Emacs control +characters. +The most important of these are: +C-A (Control-A) moves the cursor to the beginning of the line, C-E to +the end, C-B moves it one position to the left, C-F to the right. +Backspace erases the character to the left of the cursor, C-D the +character to its right. +C-K kills (erases) the rest of the line to the right of the cursor, C-Y +yanks back the last killed string. +C-underscore undoes the last change you made; it can be repeated for +cumulative effect. + +History substitution works as follows. +All non-empty input lines issued are saved in a history buffer, +and when a new prompt is given you are positioned on a new line at the +bottom of this buffer. +C-P moves one line up (back) in the history buffer, C-N moves one down. +Any line in the history buffer can be edited; an asterisk appears in +front of the prompt to mark a line as modified. +Pressing the Return key passes the current line to the interpreter. +C-R starts an incremental reverse search; C-S starts a forward search. + +The key bindings and some other parameters of the Readline library can +be customized by placing commands in an initialization file called +{\tt \$HOME/.initrc}. +Key bindings have the form +\bcode\begin{verbatim} +key-name: function-name +\end{verbatim}\ecode +and options can be set with +\bcode\begin{verbatim} +set option-name value +\end{verbatim}\ecode +Example: +\bcode\begin{verbatim} +# I prefer vi-style editing: +set editing-mode vi +# Edit using a single line: +set horizontal-scroll-mode On +# Rebind some keys: +Meta-h: backward-kill-word +Control-u: universal-argument +\end{verbatim}\ecode +Note that the default binding for TAB in \Python\ is to insert a TAB +instead of Readline's default filename completion function. +If you insist, you can override this by putting +\bcode\begin{verbatim} +TAB: complete +\end{verbatim}\ecode +in your +{\tt \$HOME/.inputrc}. +(Of course, this makes it hard to type indented continuation lines.) + +This facility is an enormous step forward compared to previous versions of +the interpreter; however, some wishes are left: +It would be nice if the proper indentation were suggested on +continuation lines (the parser knows if an indent token is required +next). +The completion mechanism might use the interpreter's symbol table. +A function to check (or even suggest) matching parentheses, quotes +etc. would also be useful. + +\section{An Informal Introduction to Python} + +In the following examples, input and output are distinguished by the +presence or absence of prompts ({\tt >>>} and {\tt ...}): to repeat the +example, you must type everything after the prompt, when the prompt +appears; everything on lines that do not begin with a prompt is output +from the interpreter. +Note that a secondary prompt on a line by itself in an example means you +must type a blank line; this is used to end a multi-line command. + +\subsection{Using Python as a Calculator} + +Let's try some simple \Python\ commands. +Start the interpreter and wait for the primary prompt, +{\tt >>>}. +The interpreter acts as a simple calculator: you can type an expression +at it and it will write the value. +Expression syntax is straightforward: the operators +{\tt +}, +{\tt -}, +{\tt *} +and +{\tt /} +work just as in most other languages (e.g., Pascal or C); parentheses +can be used for grouping. +For example: +\bcode\begin{verbatim} +>>> # This is a comment +>>> 2+2 +4 +>>> +>>> (50-5+5*6+25)/4 +25 +>>> # Division truncates towards zero: +>>> 7/3 +2 +>>> +\end{verbatim}\ecode +As in C, the equal sign ({\tt =}) is used to assign a value to a variable. +The value of an assignment is not written: +\bcode\begin{verbatim} +>>> width = 20 +>>> height = 5*9 +>>> width * height +900 +>>> +\end{verbatim}\ecode +There is some support for floating point, but you can't mix floating +point and integral numbers in expression (yet): +\bcode\begin{verbatim} +>>> 10.0 / 3.3 +3.0303030303 +>>> +\end{verbatim}\ecode +Besides numbers, \Python\ can also manipulate strings, enclosed in single +quotes: +\bcode\begin{verbatim} +>>> 'foo bar' +'foo bar' +>>> 'doesn\'t' +'doesn\'t' +>>> +\end{verbatim}\ecode +Strings are written inside quotes and with quotes and other funny +characters escaped by backslashes, to show the precise value. +(There is also a way to write strings without quotes and escapes.) +Strings can be concatenated (glued together) with the +{\tt +} +operator, and repeated with~{\tt *}: +\bcode\begin{verbatim} +>>> word = 'Help' + 'A' +>>> word +'HelpA' +>>> '<' + word*5 + '>' +'' +>>> +\end{verbatim}\ecode +Strings can be subscripted; as in C, the first character of a string has +subscript 0. +There is no separate character type; a character is simply a string of +size one. +As in Icon, substrings can be specified with the +{\em slice} +notation: two subscripts (indices) separated by a colon. +\bcode\begin{verbatim} +>>> word[4] +'A' +>>> word[0:2] +'He' +>>> word[2:4] +'lp' +>>> # Slice indices have useful defaults: +>>> word[:2] # Take first two characters +'He' +>>> word[2:] # Drop first two characters +'lpA' +>>> # A useful invariant: s[:i] + s[i:] = s +>>> word[:3] + word[3:] +'HelpA' +>>> +\end{verbatim}\ecode +Degenerate cases are handled gracefully: an index that is too large is +replaced by the string size, an upper bound smaller than the lower bound +returns an empty string. +\bcode\begin{verbatim} +>>> word[1:100] +'elpA' +>>> word[10:] +'' +>>> word[2:1] +'' +>>> +\end{verbatim}\ecode +Slice indices (but not simple subscripts) may be negative numbers, to +start counting from the right. +For example: +\bcode\begin{verbatim} +>>> word[-2:] # Take last two characters +'pA' +>>> word[:-2] # Drop last two characters +'Hel' +>>> # But -0 does not count from the right! +>>> word[-0:] # (since -0 equals 0) +'HelpA' +>>> +\end{verbatim}\ecode +The best way to remember how slices work is to think of the indices as +pointing +{\em between} +characters, with the left edge of the first character numbered 0. +Then the right edge of the last character of a string of +{\tt n} +characters has index +{\tt n}, +for example: +\bcode\begin{verbatim} + +---+---+---+---+---+ + | H | e | l | p | A | + +---+---+---+---+---+ + 0 1 2 3 4 5 +-5 -4 -3 -2 -1 +\end{verbatim}\ecode +The first row of numbers gives the position of the indices 0...5 in the +string; the second row gives the corresponding negative indices. +For nonnegative indices, the length of a slice is the difference of the +indices, if both are within bounds, +e.g., +the length of +{\tt word[1:3]} +is 3--1 = 2. + +Finally, the built-in function {\tt len()} computes the length of a +string: +\bcode\begin{verbatim} +>>> s = 'supercalifragilisticexpialidocious' +>>> len(s) +34 +>>> +\end{verbatim}\ecode +\Python\ knows a number of +{\em compound} +data types, used to group together other values. +The most versatile is the +{\em list}, +which can be written as a list of comma-separated values between square +brackets: +\bcode\begin{verbatim} +>>> a = ['foo', 'bar', 100, 1234] +>>> a +['foo', 'bar', 100, 1234] +>>> +\end{verbatim}\ecode +As for strings, list subscripts start at 0: +\bcode\begin{verbatim} +>>> a[0] +'foo' +>>> a[3] +1234 +>>> +\end{verbatim}\ecode +Lists can be sliced and concatenated like strings: +\bcode\begin{verbatim} +>>> a[1:3] +['bar', 100] +>>> a[:2] + ['bletch', 2*2] +['foo', 'bar', 'bletch', 4] +>>> +\end{verbatim}\ecode +Unlike strings, which are +{\em immutable}, +it is possible to change individual elements of a list: +\bcode\begin{verbatim} +>>> a +['foo', 'bar', 100, 1234] +>>> a[2] = a[2] + 23 +>>> a +['foo', 'bar', 123, 1234] +>>> +\end{verbatim}\ecode +Assignment to slices is also possible, and this may even change the size +of the list: +\bcode\begin{verbatim} +>>> # Replace some items: +>>> a[0:2] = [1, 12] +>>> a +[1, 12, 123, 1234] +>>> # Remove some: +>>> a[0:2] = [] +>>> a +[123, 1234] +>>> # Insert some: +>>> a[1:1] = ['bletch', 'xyzzy'] +>>> a +[123, 'bletch', 'xyzzy', 1234] +>>> +\end{verbatim}\ecode +The built-in function {\tt len()} also applies to lists: +\bcode\begin{verbatim} +>>> len(a) +4 +>>> +\end{verbatim}\ecode + +\subsection{Tuples and Sequences} + +XXX To Be Done. + +\subsection{First Steps Towards Programming} + +Of course, we can use \Python\ for more complicated tasks than adding two +and two together. +For instance, we can write an initial subsequence of the +{\em Fibonacci} +series as follows: +\bcode\begin{verbatim} +>>> # Fibonacci series: +>>> # the sum of two elements defines the next +>>> a, b = 0, 1 +>>> while b < 100: +... print b +... a, b = b, a+b +... +1 +1 +2 +3 +5 +8 +13 +21 +34 +55 +89 +>>> +\end{verbatim}\ecode +This example introduces several new features. +\begin{itemize} +\item +The first line contains a +{\em multiple\ assignment}: +the variables +{\tt a} +and +{\tt b} +simultaneously get the new values 0 and 1. +On the last line this is used again, demonstrating that the expressions +on the right-hand side are all evaluated first before any of the +assignments take place. +\item +The +{\tt while} +loop executes as long as the condition (here: $b < 100$) remains true. +In \Python, as in C, any non-zero integer value is true; zero is false. +The condition may also be a string or list value, in fact any sequence; +anything with a non-zero length is true, empty sequences are false. +The test used in the example is a simple comparison. +The standard comparison operators are written as +{\tt <}, +{\tt >}, +{\tt =}, +{\tt <=}, +{\tt >=} +and +{\tt <>}.% +\footnote{ + The ambiguity of using {\tt =} + for both assignment and equality is resolved by disallowing + unparenthesized conditions at the right hand side of assignments. +} +\item +The +{\em body} +of the loop is +{\em indented}: indentation is \Python's way of grouping statements. +\Python\ does not (yet!) provide an intelligent input line editing +facility, so you have to type a tab or space(s) for each indented line. +In practice you will prepare more complicated input for \Python\ with a +text editor; most text editors have an auto-indent facility. +When a compound statement is entered interactively, it must be +followed by a blank line to indicate completion (since the parser +cannot guess when you have typed the last line). +\item +The +{\tt print} +statement writes the value of the expression(s) it is given. +It differs from just writing the expression you want to write (as we did +earlier in the calculator examples) in the way it handles multiple +expressions and strings. +Strings are written without quotes and a space is inserted between +items, so you can format things nicely, like this: +\bcode\begin{verbatim} +>>> i = 256*256 +>>> print 'The value of i is', i +The value of i is 65536 +>>> +\end{verbatim}\ecode +A trailing comma avoids the newline after the output: +\bcode\begin{verbatim} +>>> a, b = 0, 1 +>>> while b < 1000: +... print b, +... a, b = b, a+b +... +1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 +>>> +\end{verbatim}\ecode +Note that the interpreter inserts a newline before it prints the next +prompt if the last line was not completed. +\end{itemize} + +\subsection{More Control Flow Tools} + +Besides the {\tt while} statement just introduced, \Python\ knows the +usual control flow statements known from other languages, with some +twists. + +\subsubsection{If Statements} + +Perhaps the most well-known statement type is the {\tt if} statement. +For example: +\bcode\begin{verbatim} +>>> if x < 0: +... x = 0 +... print 'Negative changed to zero' +... elif x = 0: +... print 'Zero' +... elif x = 1: +... print 'Single' +... else: +... print 'More' +... +\end{verbatim}\ecode +There can be zero or more {\tt elif} parts, and the {\tt else} part is +optional. +The keyword `{\tt elif}' is short for `{\tt else if}', and is useful to +avoid excessive indentation. +An {\tt if...elif...elif...} sequence is a substitute for the +{\em switch} or {\em case} statements found in other languages. + +\subsubsection{For Statements} + +The {\tt for} statement in \Python\ differs a bit from what you may be +used to in C or Pascal. +Rather than always iterating over an arithmetic progression of numbers +(as Pascal), or leaving the user completely free in the iteration test +and step (as C), \Python's {\tt for} statement iterates over the items +of any sequence (e.g., a list or a string). +For example (no pun intended): +\bcode\begin{verbatim} +>>> # Measure some strings: +>>> a = ['cat', 'window', 'defenestrate'] +>>> for x in a: +... print x, len(x) +... +cat 3 +window 6 +defenestrate 12 +>>> +\end{verbatim}\ecode + +\subsubsection{The {\tt range()} Function} + +If you do need to iterate over a sequence of numbers, the built-in +function {\tt range()} comes in handy. +It generates lists containing arithmetic progressions, +e.g.: +\bcode\begin{verbatim} +>>> range(10) +[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] +>>> +\end{verbatim}\ecode +The given end point is never part of the generated list; +{\tt range(10)} generates a list of 10 values, +exactly the legal indices for items of a sequence of length 10. +It is possible to let the range start at another number, or to specify a +different increment (even negative): +\bcode\begin{verbatim} +>>> range(5, 10) +[5, 6, 7, 8, 9] +>>> range(0, 10, 3) +[0, 3, 6, 9] +>>> range(-10, -100, -30) +[-10, -40, -70] +>>> +\end{verbatim}\ecode +To iterate over the indices of a sequence, combine {\tt range()} +and {\tt len()} as follows: +\bcode\begin{verbatim} +>>> a = ['Mary', 'had', 'a', 'little', 'boy'] +>>> for i in range(len(a)): +... print i, a[i] +... +0 Mary +1 had +2 a +3 little +4 boy +>>> +\end{verbatim}\ecode + +\subsubsection{Break Statements and Else Clauses on Loops} + +The {\tt break} statement breaks out of the smallest enclosing {\tt for} +or {\tt while} loop. +Loop statements may have an {\tt else} clause; it is executed when the +loop terminates through exhaustion of the list (with {\tt for}) or when +the condition becomes false (with {\tt while}) but not when the loop is +terminated by a {\tt break} statement. +This is exemplified by the following loop, which searches for a list +item of value 0: +\bcode\begin{verbatim} +>>> for n in range(2, 10): +... for x in range(2, n): +... if n % x = 0: +... print n, 'equals', x, '*', n/x +... break +... else: +... print n, 'is a prime number' +... +2 is a prime number +3 is a prime number +4 equals 2 * 2 +5 is a prime number +6 equals 2 * 3 +7 is a prime number +8 equals 2 * 4 +9 equals 3 * 3 +>>> +\end{verbatim}\ecode + +\subsubsection{Pass Statements} + +The {\tt pass} statement does nothing. +It can be used when a statement is required syntactically but the +program requires no action. +For example: +\bcode\begin{verbatim} +>>> while 1: +... pass # Busy-wait for keyboard interrupt +... +\end{verbatim}\ecode + +\subsubsection{Conditions Revisited} + +XXX To Be Done. + +\subsection{Defining Functions} + +We can create a function that writes the Fibonacci series to an +arbitrary boundary: +\bcode\begin{verbatim} +>>> def fib(n): # write Fibonacci series up to n +... a, b = 0, 1 +... while b <= n: +... print b, +... a, b = b, a+b +... +>>> # Now call the function we just defined: +>>> fib(2000) +1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 +>>> +\end{verbatim}\ecode +The keyword +{\tt def} +introduces a function +{\em definition}. +It must be followed by the function name and the parenthesized list of +formal parameters. +The statements that form the body of the function starts at the next +line, indented by a tab stop. +The +{\em execution} +of a function introduces a new symbol table used for the local variables +of the function. +More precisely, all variable assignments in a function store the value +in the local symbol table; variable references first look in the local +symbol table, then in the global symbol table, and then in the table of +built-in names. +Thus, the global symbol table is +{\em read-only} +within a function. +The actual parameters (arguments) to a function call are introduced in +the local symbol table of the called function when it is called; +thus, arguments are passed using +{\em call\ by\ value}.% +\footnote{ + Actually, {\em call by object reference} would be a better + description, since if a mutable object is passed, the caller + will see any changes the callee makes to it (e.g., items + inserted into a list). +} +When a function calls another function, a new local symbol table is +created for that call. + +A function definition introduces the function name in the global symbol +table. +The value has a type that is recognized by the interpreter as a +user-defined function. +This value can be assigned to another name which can then also be used +as a function. +This serves as a general renaming mechanism: +\bcode\begin{verbatim} +>>> fib + +>>> f = fib +>>> f(100) +1 1 2 3 5 8 13 21 34 55 89 +>>> +\end{verbatim}\ecode +You might object that +{\tt fib} +is not a function but a procedure. +In \Python, as in C, procedures are just functions that don't return a +value. +In fact, technically speaking, procedures do return a value, albeit a +rather boring one. +This value is called {\tt None} (it's a built-in name). +Writing the value {\tt None} is normally suppressed by the interpreter +if it would be the only value written. +You can see it if you really want to: +\bcode\begin{verbatim} +>>> print fib(0) +None +>>> +\end{verbatim}\ecode +It is simple to write a function that returns a list of the numbers of +the Fibonacci series, instead of printing it: +\bcode\begin{verbatim} +>>> def fib2(n): # return Fibonacci series up to n +... result = [] +... a, b = 0, 1 +... while b <= n: +... result.append(b) # see below +... a, b = b, a+b +... return result +... +>>> f100 = fib2(100) # call it +>>> f100 # write the result +[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] +>>> +\end{verbatim}\ecode +This example, as usual, demonstrates some new \Python\ features: +\begin{itemize} +\item +The +{\tt return} +statement returns with a value from a function. +{\tt return} +without an expression argument is used to return from the middle of a +procedure (falling off the end also returns from a proceduce). +\item +The statement +{\tt ret.append(b)} +calls a +{\em method} +of the list object +{\tt ret}. +A method is a function that `belongs' to an object and is named +{\tt obj.methodname}, +where +{\tt obj} +is some object (this may be an expression), and +{\tt methodname} +is the name of a method that is defined by the object's type. +Different types define different methods. +Methods of different types may have the same name without causing +ambiguity. +See the section on classes, later, to find out how you can define your +own object types and methods. +The method +{\tt append} +shown in the example, is defined for list objects; it adds a new element +at the end of the list. +In this case it is equivalent to +{\tt ret = ret + [b]}, +but more efficient.% +\footnote{ + There is a subtle semantic difference if the object + is referenced from more than one place. +} +\end{itemize} +The list object type has two more methods: +\begin{description} +\item[{\tt insert(i, x)}] +Inserts an item at a given position. +The first argument is the index of the element before which to insert, +so {\tt a.insert(0, x)} inserts at the front of the list, and +{\tt a.insert(len(a), x)} is equivalent to {\tt a.append(x)}. +\item[{\tt sort()}] +Sorts the elements of the list. +\end{description} +For example: +\bcode\begin{verbatim} +>>> a = [10, 100, 1, 1000] +>>> a.insert(2, -1) +>>> a +[10, 100, -1, 1, 1000] +>>> a.sort() +>>> a +[-1, 1, 10, 100, 1000] +>>> # Strings are sorted according to ASCII: +>>> b = ['Mary', 'had', 'a', 'little', 'boy'] +>>> b.sort() +>>> b +['Mary', 'a', 'boy', 'had', 'little'] +>>> +\end{verbatim}\ecode + +\subsection{Modules} + +If you quit from the \Python\ interpreter and enter it again, the +definitions you have made (functions and variables) are lost. +Therefore, if you want to write a somewhat longer program, you are +better off using a text editor to prepare the input for the interpreter +and run it with that file as input instead. +This is known as creating a +{\em script}. +As your program gets longer, you may want to split it into several files +for easier maintenance. +You may also want to use a handy function that you've written in several +programs without copying its definition into each program. +To support this, \Python\ has a way to put definitions in a file and use +them in a script or in an interactive instance of the interpreter. +Such a file is called a +{\em module}; +definitions from a module can be +{\em imported} +into other modules or into the +{\em main} +module (the collection of variables that you have access to in +a script and in calculator mode). + +A module is a file containing \Python\ definitions and statements. +The file name is the module name with the suffix +{\tt .py} +appended. +For instance, use your favorite text editor to create a file called +{\tt fibo.py} +in the current directory with the following contents: +\bcode\begin{verbatim} +# Fibonacci numbers module + +def fib(n): # write Fibonacci series up to n + a, b = 0, 1 + while b <= n: + print b, + a, b = b, a+b + +def fib2(n): # return Fibonacci series up to n + ret = [] + a, b = 0, 1 + while b <= n: + ret.append(b) + a, b = b, a+b + return ret +\end{verbatim}\ecode +Now enter the \Python\ interpreter and import this module with the +following command: +\bcode\begin{verbatim} +>>> import fibo +>>> +\end{verbatim}\ecode +This does not enter the names of the functions defined in +{\tt fibo} +directly in the symbol table; it only enters the module name +{\tt fibo} +there. +Using the module name you can access the functions: +\bcode\begin{verbatim} +>>> fibo.fib(1000) +1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 +>>> fibo.fib2(100) +[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] +>>> +\end{verbatim}\ecode +If you intend to use a function often you can assign it to a local name: +\bcode\begin{verbatim} +>>> fib = fibo.fib +>>> fib(500) +1 1 2 3 5 8 13 21 34 55 89 144 233 377 +>>> +\end{verbatim}\ecode + +\subsubsection{More on Modules} + +A module can contain executable statements as well as function +definitions. +These statements are intended to initialize the module. +They are executed only the +{\em first} +time the module is imported somewhere.% +\footnote{ + In fact function definitions are also `statements' that are + `executed'; the execution enters the function name in the + module's global symbol table. +} + +Each module has its own private symbol table, which is used as the +global symbol table by all functions defined in the module. +Thus, the author of a module can use global variables in the module +without worrying about accidental clashes with a user's global +variables. +On the other hand, if you know what you are doing you can touch a +module's global variables with the same notation used to refer to its +functions, +{\tt modname.itemname}. + +Modules can import other modules. +It is customary but not required to place all +{\tt import} +statements at the beginning of a module (or script, for that matter). +The imported module names are placed in the importing module's global +symbol table. + +There is a variant of the +{\tt import} +statement that imports names from a module directly into the importing +module's symbol table. +For example: +\bcode\begin{verbatim} +>>> from fibo import fib, fib2 +>>> fib(500) +1 1 2 3 5 8 13 21 34 55 89 144 233 377 +>>> +\end{verbatim}\ecode +This does not introduce the module name from which the imports are taken +in the local symbol table (so in the example, {\tt fibo} is not +defined). + +There is even a variant to import all names that a module defines: +\bcode\begin{verbatim} +>>> from fibo import * +>>> fib(500) +1 1 2 3 5 8 13 21 34 55 89 144 233 377 +>>> +\end{verbatim}\ecode +This imports all names except those beginning with an underscore +({\tt \_}). + +\subsubsection{Standard Modules} + +\Python\ comes with a library of standard modules, described in a separate +document (Python Library and Module Reference). +Some modules are built into the interpreter; these provide access to +operations that are not part of the core of the language but are +nevertheless built in, either for efficiency or to provide access to +operating system primitives such as system calls. +The set of such modules is a configuration option; e.g., the +{\tt amoeba} +module is only