commit 6764738d92df13f63c1dd67f54ddea5deebc8bcc Author: whatever Date: Mon Sep 14 20:19:29 2026 -0400 created mirror diff --git a/C++/README b/C++/README new file mode 100644 index 0000000..c58acb0 --- /dev/null +++ b/C++/README @@ -0,0 +1,5 @@ +C++ version of gzizag +===================== +C++ version has been removed from here, because it's not usefull +anymore. + diff --git a/CODING b/CODING new file mode 100644 index 0000000..b9a76b9 --- /dev/null +++ b/CODING @@ -0,0 +1,122 @@ +Coding rules for GZigZag -*- Text -*- +======================== + Tuomas Lukka + Antti-Juhani Kaijanaho + +$Id: CODING,v 1.18 2001/03/08 15:05:12 tjl Exp $ + +This document attempts to give a brief guide on how to write +Java code for this project. + +- each Java file should contain the boilerplate copyright and + license notice (see e.g. Java/ZZCell.java). + +- all of the classes should be in a package. The packages are + org.gzigzag -- general core stuff + org.gzigzag.module -- modules + org.gzigzag.dimension -- dimensions for use with DimSpace + +- The main Java/ subdirectory may only depend on the JDK 1.1.8 APIs. + Swing is not allowed. + + There is also Java/exp for experimental things that touch the core + which may depend on anything but shall not be compiled by default. + + Modules/ can depend on anything, as long as the dependency is documented. + Nothing in the main Java/ subdirectory may depend on anything in Modules/ + This ensures that we retain portability and easy installation. All the user + has to do is to give up on a module that has an odd dependency, not the whole + system. + + Note that all modules need not be in the Modules/ subdirectory: for instance, + the TextCloud module does not depend on anything beyond the core Java code + and may in the future be called by the core Java code so it is located in + the core subdirectory. + + + +- Each class should start with the line (not indented to save space) + +public static final String rcsid = "$Id: CODING,v 1.18 2001/03/08 15:05:12 tjl Exp $"; + + except interfaces, which should have + +String rcsid = "$Id: CODING,v 1.18 2001/03/08 15:05:12 tjl Exp $"; + + instead. + + This will pull in the version identifier from the CVS file. + XXX IT SHOULD PROBABLY BE INCLUDED IN THE JAVADOC AS WELL! + +- For debugging log messages, use the code + + public static boolean dbg = false; + protected static void p(String s) { if(dbg) ZZLogger.log(s); } + protected static void pa(String s) { ZZLogger.log(s); } + + to print out messages. The System.out.println() is too verbose to insert + into code. This code can be added to the beginning of any class. + + NOTE THE CHANGE FROM PREVIOUS: there is NO "final" qualifier for dbg, + as a non-final dbg can be used on the commandline to switch debugging + on at runtime, without a recompilation. Not all files have been changed yet. + + NOTE THE CHANGE FROM PREVIOUS: We now use ZZLogger, allowing logging + the debug output into a file that can be sent to us in case of a + puzzling bug. This avoids having to have a scrollback buffer in + your terminal emulator. + + NOTE THE CHANGE FROM PREVIOUS: there are NO "final" qualifiers for p and pa, + because they are unnecessary for static methods. p and pa are now private. + Not all files have been changed yet. + + NOTE THE CHANGE FROM PREVIOUS: The methods are now protected; this allows + them to be used in subclasses. When they were private, debugging subclasses + was impossible. Not all files have been changed yet. + +- If you want to kill the program, use SafeExit.exit instead of System.exit; + this allows consistent cleanup at exit time + +- Avoid both under- and overdocumenting. + +- Use Java 1.1.8: use of 1.2 features is allowable IF you carefully check + that the code works in 1.1.8, minus the features given by 1.2. So for + instance, if you make a cache that works with the garbage collector + interface in 1.2 to enable passive cleaning, the code should run on 1.1.8, + either without the cache, or without the cleaning (currently the ZZCellScroll + caches without any cleaning). + + One of the considerations here is that Kaffe JVM provides a completely + free platform on which we can run the free GZigZag. If SUN or someone else + ever releases their Java implementation under a free license, the situation + is completely different. + +- Use anonymous classes freely + +- Try to keep the external APIs small, *with the exception* of providing + convenience routines for classes like ZZCell. + +- Indenting: tabstop==8, shiftwidth == 4, cuddled braces, i.e. + + public void method() { + if(...) { + ... + } else { + ... + } + } + + however, you may use smaller shiftwidth if the function really really requires + it (although you should try to split it up). + +- for any more complicated functionality, feel free to start a new + "white paper" -type documentation in the Documentation/ subdirectory. + +- make your code such that it can be compiled in jikes +P (pedantic), + JDK1.1.8 and JDK1.2.2 without warnings or errors. + +- as an aside, I really recommend using a coloring editor since there are + many points where significant sections have been commented out. This + is bad practice but inevitable in a system that doesn't easily allow + us to attach the sections which are not useful now but might be later + to the text in a xanadu-like manner. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..70add5d --- /dev/null +++ b/ChangeLog @@ -0,0 +1,4403 @@ +2002-03-07 Thursday 21:02 Benjamin Fallenstein + + * Java/flob/: FlobSet.java, StdLinks.zob (ver_0_6): Fix FlobSet: + findPath(String path, ZZCell c) did not respect 'path'. + +2002-03-07 Thursday 19:56 Antti-Juhani Kaijanaho + + * NEWS, Documentation/index.html (ver_0_6): fix trivial doc bug, + see Debian BTS #128279 + +2002-03-07 Thursday 19:36 Benjamin Fallenstein + + * Java/ZZUtil.java (ver_0_6): Try fixing the depth bug that has + caused raster errors in prerelease. + +2002-03-07 Thursday 17:59 Benjamin Fallenstein + + * NEWS (ver_0_6): Update NEWS. + +2002-03-05 Tuesday 20:46 Benjamin Fallenstein + + * NEWS, Java/ZZUtil.java, Java/flob/RowColView.zob (ver_0_6): The + Row and Column views have been fixed to show the dimensions always. + Previously, in some common cases the dimensions were hidden under + the cells shown by the views. + +2002-03-05 Tuesday 19:48 Antti-Juhani Kaijanaho + + * NEWS (ver_0_6): preparation for 0.6.3 + +2002-03-05 Tuesday 18:21 Benjamin Fallenstein + + * Java/: ZZPrimitiveActions.java, ZZUtil.java (ver_0_6): Add a + version of PUICOPYLINE that makes each cell a paragraph + (PUICOPYRANK, invoked by Ctrl-Alt-C + +2002-02-16 Saturday 18:58 Tuukka Hastrup + + * Modules/prez/PrezRaster.zob (ver_0_6): Asko's Presenation view + fixes. BallCell went already in... + +2002-02-16 Saturday 18:56 Tuukka Hastrup + + * Java/Makefile (ver_0_6): Revert accidental Makefile change + +2002-02-16 Saturday 18:51 Tuukka Hastrup + + * Java/: Makefile, flob/BallCell.java (ver_0_6): Add Mind module to + JARMODULES too + +2002-02-16 Saturday 17:21 Antti-Juhani Kaijanaho + + * NEWS (ver_0_6): minor nits; ready for release? + +2002-02-16 Saturday 16:33 Tuukka Hastrup + + * Modules/mind/MindSun.java (ver_0_6): Really change to JDK 1.1 API + +2002-02-16 Saturday 16:25 Tuukka Hastrup + + * Modules/mind/MindSun.java (ver_0_6): Change to JDK 1.1 API + +2002-02-16 Saturday 15:46 Tuukka Hastrup + + * Modules/mind/Mind.java (ver_0_6): Added Asko's tree export + actions, (not in DefaultSpace yet) + +2002-02-16 Saturday 15:19 Tuukka Hastrup + + * Java/Makefile, Java/ZZDefaultSpace.java, Modules/mind/Mind.java, + Modules/mind/MindSun.java, Modules/mind/MindSundew.java (ver_0_6): + Added Asko's views as module Mind + +2002-02-16 Saturday 15:19 Tuukka Hastrup + + * Modules/mind/Mind.java: file Mind.java was initially added on + branch ver_0_6. + +2002-02-16 Saturday 15:19 Tuukka Hastrup + + * Modules/mind/MindSun.java: file MindSun.java was initially added + on branch ver_0_6. + +2002-02-16 Saturday 15:19 Tuukka Hastrup + + * Modules/mind/MindSundew.java: file MindSundew.java was initially + added on branch ver_0_6. + +2002-02-16 Saturday 14:19 Benjamin Fallenstein + + * NEWS (ver_0_6): Update NEWS again + +2002-02-16 Saturday 14:07 Benjamin Fallenstein + + * NEWS (ver_0_6): Update NEWS + +2002-02-13 Wednesday 13:48 Tuomas J. Lukka + + * Documentation/misc/argh-useful.jpeg: Why the argh-view can be + useful + +2002-02-10 Sunday 12:39 Benjamin Fallenstein + + * Java/ZZViewComponent.java (ver_0_6): Comment out consume() (the + offending call on JDK 1.2+) + +2002-02-10 Sunday 12:37 Benjamin Fallenstein + + * Java/ZZCursorReal.java (ver_0_6): Make compile (without modules, + at least) + +2002-02-08 Friday 07:57 Tuomas J. Lukka + + * Documentation/misc/gzz-functional-notes.sxw: Another day's work + towards functional cellviews + +2002-02-07 Thursday 09:25 Tuomas J. Lukka + + * Documentation/misc/: gzz-functional-notes.sxw, gzz-ogl-notes.sxw: + more + +2002-02-06 Wednesday 12:43 Tuomas J. Lukka + + * Documentation/misc/gzz-functional-notes.sxw: More stuff about + func prog + +2002-02-05 Tuesday 15:55 Tuomas J. Lukka + + * Documentation/misc/gzz-functional-notes.sxw: Ok, now... + +2002-02-05 Tuesday 12:55 Tuomas J. Lukka + + * Documentation/misc/gzz-functional-notes.sxw: Functional + +2002-02-04 Monday 14:57 Tuomas J. Lukka + + * Documentation/misc/PPPrototypeDesign.sxw: Important spec change + +2002-02-04 Monday 13:45 Tuomas J. Lukka + + * Documentation/misc/gzz-ogl-notes.sxw: Forgot to add this when + moving stuff + +2002-02-03 Sunday 19:29 Tuomas J. Lukka + + * Documentation/misc/gzz-ogl-notes.sxw: more + +2002-02-03 Sunday 11:18 Tuomas J. Lukka + + * Documentation/misc/gzz-ogl-notes.sxw: mor + +2002-02-02 Saturday 20:37 Tuomas J. Lukka + + * Documentation/misc/gzz-ogl-notes.sxw: More thoughts + +2002-02-02 Saturday 15:33 Tuomas J. Lukka + + * Documentation/misc/gzz-ogl-notes.sxw: Opengl notes + +2002-02-02 Saturday 12:36 Tuomas J. Lukka + + * Documentation/misc/: PPPrototypeDesign.sxw, + PPPrototypeDesign.sxw, PPPrototypeDesign.sxw: more + +2002-02-02 Saturday 11:10 Tuomas J. Lukka + + * Documentation/misc/: PPPrototypeDesign.sxw, + PPPrototypeDesign.sxw: more + +2002-02-02 Saturday 10:44 Tuomas J. Lukka + + * Documentation/misc/PPPrototypeDesign.sxw: more + +2002-02-02 Saturday 09:03 Tuomas J. Lukka + + * Documentation/misc/: PPPrototypeDesign.sxw, jyvasaly.txt: + Perheportaali design + +2002-01-17 Thursday 19:01 Benjamin Fallenstein + + * Documentation/Mediaserver/ms.wml: Add status information + throughout mediaserver doc, corrrect minor typos + +2002-01-16 Wednesday 19:48 Benjamin Fallenstein + + * Documentation/: Makefile, PROTOCOL, ApplitudeWriters/Makefile, + ApplitudeWriters/appw.wml, Networking/Makefile, + Networking/ZTP-usage.txt, Networking/ZTP.txt, + Networking/mock-ZTPTCP.txt, Networking/ztp.wml, misc/ADDRESSING, + misc/Curseling, misc/RENDERING, misc/TORESOLVE: Remove some + seemingly outdated documentation. Shout if something of this was + still important. + +2001-12-03 Monday 05:30 Antti-Juhani Kaijanaho + + * Documentation/misc/oske1.tex: update report dates + +2001-11-26 Monday 20:56 vegai + + * Documentation/misc/jyvasaly.txt: Few typos and obscurities + +2001-11-26 Monday 14:37 Tuomas J. Lukka + + * Documentation/misc/jyvasaly.txt: More + +2001-10-17 Wednesday 08:17 vegai + + * README: Documented 0.8-tree somewhat. (1st commit, be very + afraid) + +2001-10-11 Thursday 12:53 Tuomas J. Lukka + + * Documentation/misc/: nets-1.txt, nets-2.txt, nets-2.txt: more + +2001-10-11 Thursday 12:28 Tuomas J. Lukka + + * Documentation/misc/: nets-1.txt, nets-2.txt: more + +2001-10-11 Thursday 11:46 Tuomas J. Lukka + + * Documentation/misc/nets-1.txt: Changes + +2001-10-11 Thursday 11:20 Tuomas J. Lukka + + * Documentation/misc/nets-1.txt: Fmt, add COTS stuff + +2001-10-11 Thursday 11:17 Tuomas J. Lukka + + * Documentation/misc/: nets-1.txt, nets-2.txt: Add nets docs for + review + +2001-10-08 Monday 04:36 Tuomas J. Lukka + + * Documentation/: Mediaserver/ms.wml, Spec/zzspec.wml: Updates + +2001-10-03 Wednesday 11:21 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/gzigzag.bib: fix + +2001-10-02 Tuesday 05:30 Benjamin Fallenstein + + * Java/flob/RowColView.zob (ver_0_6): Fix RowCol's structparams and + add 'repeat' + +2001-09-21 Friday 08:14 Antti-Juhani Kaijanaho + + * Documentation/misc/oske1.tex: Correct HT01 reference + +2001-09-21 Friday 08:09 Antti-Juhani Kaijanaho + + * Documentation/misc/oske1.tex: Added explicit date range; noted + that 1stZZW talks were invited + +2001-09-17 Monday 10:21 Tuomas J. Lukka + + * Documentation/misc/oske1.tex: Typo + +2001-09-17 Monday 09:16 Tuomas J. Lukka + + * Documentation/misc/oske1.tex: OSKE first report, please read and + comment + +2001-08-29 Wednesday 08:32 Antti-Juhani Kaijanaho + + * Makefile: some stuff to make alpha releases + +2001-08-24 Friday 19:58 Benjamin Fallenstein + + * Java/flob/MagGrid.zob (ver_0_6): Make MagGrid default values so + much more useful + +2001-08-24 Friday 06:06 Antti-Juhani Kaijanaho + + * Java/ZZViewComponent.java (ver_0_6): revert focus change (if we + find a better fix, we can always do a 0.6.2) + +2001-08-17 Friday 12:15 Antti-Juhani Kaijanaho + + * manifest-filter.lst (ver_0_6): do not include src + +2001-08-17 Friday 12:13 Antti-Juhani Kaijanaho + + * NEWS (ver_0_6): prepare for the release + +2001-08-16 Thursday 14:51 Benjamin Fallenstein + + * Java/ZZDefaultSpace.java (ver_0_6): Add flowing clang execution + dimension to the standard dimension list + +2001-08-16 Thursday 14:51 Benjamin Fallenstein + + * Java/ZZKeyBindings1.java (ver_0_6): Ugly fix for Flowing Clang + execution as a key binding + +2001-08-16 Thursday 14:39 Benjamin Fallenstein + + * Java/ZZViewComponent.java (ver_0_6): Fix greedy focus + +2001-08-16 Thursday 14:19 Benjamin Fallenstein + + * NEWS (ver_0_6): Update NEWS + +2001-08-16 Thursday 14:13 Benjamin Fallenstein + + * Java/ZZPrimitiveActions.java (ver_0_6): Oopsie, forgot to add + EDITHACK to actions list + +2001-08-16 Thursday 14:09 Benjamin Fallenstein + + * Java/ZZPrimitiveActions.java (ver_0_6): Make flowing clang + programs work directly as actions (i.e., now one can write a + flowing clang function and clone it directly onto the key bindings + list). Now, testing; then, from my side we're ready for the next + 0.6 release. + +2001-08-16 Thursday 13:50 Benjamin Fallenstein + + * Java/: ZZTextView.java, media/LineBreaker.java (ver_0_6): Set + window bounds for text view; fix compilation with Klasses.jar + +2001-08-16 Thursday 13:40 Benjamin Fallenstein + + * Java/: Makefile, clang/flowing/Flowing.java (ver_0_6): Make + Flowing Clang compile again + +2001-08-16 Thursday 08:48 Tuomas J. Lukka + + * Documentation/Spec/zzspec.wml, Java/Makefile, + Java/clang/flowing/Flowing.java: Make flowing clang work again, + update spec, Add println clasm primitive and twiddle with linux + joystick + +2001-08-12 Sunday 09:00 Antti-Juhani Kaijanaho + + * Makefile: update ChangeLog + +2001-08-11 Saturday 16:29 Tuukka Hastrup + + * Documentation/: Clang_Design/.cvsignore, Mediaserver/.cvsignore, + Spec/.cvsignore: Ignore more autogenerated files + +2001-08-08 Wednesday 14:55 Tuukka Hastrup + + * Documentation/Clang_Design/clasm.wml: Update dimension names in + the text + +2001-08-08 Wednesday 14:46 Tuukka Hastrup + + * Documentation/Clang_Design/clasm-tutorial.wml: Update dimension + names in the text (not in pictures) + +2001-08-06 Monday 15:28 Benjamin Fallenstein + + * Documentation/Spec/zzspec.wml: fix + +2001-08-06 Monday 15:17 Benjamin Fallenstein + + * Documentation/Spec/zzspec.wml: Span storage stuff + +2001-08-05 Sunday 15:04 Tuomas J. Lukka + + * Documentation/: Makefile, Mediaserver/ms.wml: Saving + +2001-08-05 Sunday 14:08 Tuomas J. Lukka + + * Documentation/Mediaserver/ms.wml: Pointers proposal + +2001-08-05 Sunday 10:58 Tuomas J. Lukka + + * Documentation/Spec/zzspec.wml: Make the syntax parse a little + better + +2001-08-05 Sunday 10:55 Benjamin Fallenstein + + * Documentation/Spec/zzspec.wml: fix + +2001-08-05 Sunday 10:47 Tuomas J. Lukka + + * Documentation/Spec/zzspec.wml: Upd format + +2001-08-05 Sunday 10:24 Tuomas J. Lukka + + * Documentation/Spec/zzspec.wml: Edit + +2001-08-01 Wednesday 18:40 Tuomas J. Lukka + + * Documentation/Spec/zzspec.wml: Start working on mediaserver + scrollblocks + +2001-08-01 Wednesday 14:55 Rauli Ruohonen + + * Documentation/Spec/mainloop.jpg: Pic of main loop + +2001-07-30 Monday 10:01 Antti-Juhani Kaijanaho + + * Makefile, manifest-filter.lst: release builds src/ jars now and + ignores Java/ + +2001-07-25 Wednesday 11:01 Antti-Juhani Kaijanaho + + * Documentation/Mediaserver/ms.wml: Make the HTTP interface spec + match current expectations. + +2001-07-25 Wednesday 10:45 Antti-Juhani Kaijanaho + + * Documentation/Mediaserver/ms.wml: committing something i've + forgotten to commit previously + +2001-07-21 Saturday 21:00 Benjamin Fallenstein + + * Documentation/Spec/zzspec.wml: Start thinking about file format + representation for the new spans + +2001-07-21 Saturday 20:37 Benjamin Fallenstein + + * Documentation/Spec/zzspec.wml: some more + +2001-07-21 Saturday 18:16 Benjamin Fallenstein + + * Documentation/Spec/zzspec.wml: A bit more + +2001-07-21 Saturday 18:06 Benjamin Fallenstein + + * Documentation/Spec/: span-insertion-after.gif, + span-insertion-before.gif: add + +2001-07-21 Saturday 18:04 Benjamin Fallenstein + + * Documentation/Spec/zzspec.wml: doc fixes + +2001-07-21 Saturday 13:18 Benjamin Fallenstein + + * Documentation/Spec/zzspec.wml: Some doccing about the new span + concepts + +2001-07-19 Thursday 18:22 Benjamin Fallenstein + + * Documentation/Clang_Design/: 1.gif, 2.gif, 3.gif, 4.gif, 5.gif, + 6.gif, 7.gif, clasmpics.html: clasm pics (as on the mailing list, + plus comments-- don't count on them making too much sense ;) ;)) + +2001-07-19 Thursday 17:41 Rauli Ruohonen + + * Documentation/Mediaserver/ms.wml: Pics to the wml. + +2001-07-19 Thursday 17:27 Tuomas J. Lukka + + * Documentation/Makefile: Oooppsss - have forgotten to add these + +2001-07-19 Thursday 17:26 Rauli Ruohonen + + * Documentation/Mediaserver/ms.wml: Added obsoleteness comment to + 'a scheme'. + +2001-07-19 Thursday 16:47 Tuomas J. Lukka + + * Documentation/: DesignProblems/ABCD.jpg, + DesignProblems/ConflictLevels.jpg, + DesignProblems/DifficultMerge.jpg, + DesignProblems/LLMergeProblem.jpg, + DesignProblems/LLMergeProblem2.jpg, + DesignProblems/LargeScaleRearrange.jpg, DesignProblems/Makefile, + DesignProblems/RelationConflict.jpg, DesignProblems/SegCases.jpg, + DesignProblems/SegExamples.jpg, DesignProblems/dp.wml, + DesignProblems/mergemath.tex, diagrams/Molecule1.jpg, + diagrams/Molecule2.jpg, diagrams/Molecule3.jpg: Reorganize + Designproblems by splitting off merging + +2001-07-17 Tuesday 13:49 Benjamin Fallenstein + + * Documentation/Spec/zzspec.wml: update spec: no inclusions, but + transcopies in file format + +2001-07-16 Monday 21:37 Tuomas J. Lukka + + * Documentation/: Spec/sliceinclusion-dimsame.jpg, Spec/zzspec.wml, + wmlinc/art.css: Make images take less space horizontally + +2001-07-16 Monday 16:11 Rauli Ruohonen + + * Documentation/Spec/: spaces1.jpeg, spaces2.jpeg, spaces3.jpeg, + zzspec.wml: Some inclusion pics + +2001-07-12 Thursday 14:58 Benjamin Fallenstein + + * Documentation/Spec/zzspec.wml: Move inclusion parts after ID of + previous spaces + +2001-07-11 Wednesday 11:31 Benjamin Fallenstein + + * Documentation/Spec/zzspec.wml: I take the content section spec + back: new cells should be independent of delete cells, because the + first ought to be at the beginning and the second ought to be at + the end of the delta. + +2001-07-11 Wednesday 10:43 Benjamin Fallenstein + + * Documentation/Spec/zzspec.wml: Change file format ebnf to have + cell status sections like in GZZ1Handler + +2001-07-09 Monday 18:39 Rauli Ruohonen + + * Documentation/Spec/zzspec.wml: Removed my proposal. It was no + longer relevant. + +2001-07-09 Monday 18:08 Tuukka Hastrup + + * Documentation/wmlinc/: art.css, common.wml: Reply to Tuomas + +2001-07-09 Monday 13:30 Tuomas J. Lukka + + * Documentation/Spec/zzspec.wml: Move inclusion parts + +2001-07-09 Monday 13:27 Tuomas J. Lukka + + * Documentation/Spec/zzspec.wml: Fix + +2001-07-09 Monday 13:21 Tuomas J. Lukka + + * Documentation/Makefile: Add to makefile, comment + +2001-07-09 Monday 12:27 Tuomas J. Lukka + + * Documentation/Spec/zzspec.wml: Comment + +2001-07-09 Monday 11:20 Rauli Ruohonen + + * Documentation/Spec/zzspec.wml: Comment on library call dispatch. + +2001-07-09 Monday 11:04 Tuomas J. Lukka + + * Documentation/Spec/: zzspec.wml, zzspec.wml: Note about dimension + ids + +2001-07-09 Monday 10:59 Tuomas J. Lukka + + * Documentation/Spec/zzspec.wml: More id stuff + +2001-07-09 Monday 10:48 Rauli Ruohonen + + * Documentation/Spec/zzspec.wml: Put my proposal to the perspective + it was intended to be in. + +2001-07-09 Monday 10:39 Tuomas J. Lukka + + * Documentation/Spec/zzspec.wml: Format for inclusion + +2001-07-08 Sunday 19:30 Tuomas J. Lukka + + * Documentation/Spec/: sliceinclusion-containment.jpg, + sliceinclusion-simple.jpg, zzspec.wml: Some more + +2001-07-08 Sunday 18:14 Tuomas J. Lukka + + * Documentation/Spec/: sliceinclusion-containment.jpg, + sliceinclusion-dimsame.jpg, sliceinclusion-preflet-types.jpg, + sliceinclusion-simple.jpg, sliceinclusion-upgrade-conflict.jpg, + sliceinclusion-upgrade.jpg, zzspec.wml: More stuff about inclusions + +2001-07-07 Saturday 19:36 Tuomas J. Lukka + + * Documentation/Makefile: Make the makefile make something by + default. Distdocs is what one'd usually want. + +2001-07-07 Saturday 16:44 Tuomas J. Lukka + + * Documentation/Spec/transspace-versioning-inclusion.jpg: Fix image + +2001-07-07 Saturday 16:36 Tuomas J. Lukka + + * Documentation/Spec/: transspace-versioning-inclusion.jpg, + transspace-versioning.jpg, zzspec.wml: More comments + +2001-07-07 Saturday 15:22 Tuomas J. Lukka + + * Documentation/: Clang_Design/Makefile, Spec/zzspec.wml: Comments + +2001-07-07 Saturday 13:48 Rauli Ruohonen + + * Documentation/Spec/zzspec.wml: Oops + +2001-07-07 Saturday 13:45 Rauli Ruohonen + + * Documentation/Spec/zzspec.wml: Clarifying the cell id stuff. + +2001-07-07 Saturday 12:55 Rauli Ruohonen + + * Documentation/Spec/zzspec.wml: More cell id stuff. + +2001-07-07 Saturday 12:18 Rauli Ruohonen + + * Documentation/Spec/zzspec.wml: Adding cell identity stuff to + zzspec, as requested by tjl. + +2001-07-07 Saturday 10:05 Tuomas J. Lukka + + * Documentation/Makefile: Make makefile make + +2001-07-06 Friday 11:34 Benjamin Fallenstein + + * Documentation/Spec/zzspec.wml: Notes about transcopies in the + file format + +2001-07-06 Friday 00:37 Benjamin Fallenstein + + * Documentation/misc/cellids: stuff about cell ids and related + issues + +2001-07-04 Wednesday 12:38 uid31808 + + * Documentation/Clang_Design/clasm-tutorial.wml: Add some notes to + the pictures + +2001-07-04 Wednesday 11:00 uid31808 + + * Documentation/Clang_Design/clasm-1.gif: correct + +2001-07-04 Wednesday 08:54 uid31808 + + * Documentation/Clang_Design/: clasm-1.gif, clasm-2.gif, + clasm-3.gif, clasm-4.gif, clasm-5.gif: Some images + +2001-07-03 Tuesday 13:51 Benjamin Fallenstein + + * Documentation/Clang_Design/clasm.wml: More work on the clasm + definition + +2001-07-02 Monday 11:20 Benjamin Fallenstein + + * Documentation/Clang_Design/clasm.wml: Clasm design (not finished, + and actually not converted to WML yet) + +2001-07-02 Monday 04:08 Tuomas J. Lukka + + * CODING: Mention collections + +2001-07-01 Sunday 19:08 Benjamin Fallenstein + + * Java/UndoList.java: Fix what I'm pretty sure is a bug + +2001-07-01 Sunday 17:23 Tuomas J. Lukka + + * Documentation/Spec/zzspec.wml: Fix span spec + +2001-07-01 Sunday 16:08 Tuomas J. Lukka + + * Documentation/Spec/zzspec.wml: Fix lookahead bug + +2001-07-01 Sunday 15:29 Tuomas J. Lukka + + * Documentation/Spec/zzspec.wml: Benja: should specify prev space + +2001-07-01 Sunday 15:26 Tuomas J. Lukka + + * Documentation/Spec/zzspec.wml: Benja's request: 0 -> 00 in end + +2001-07-01 Sunday 15:24 Tuomas J. Lukka + + * Documentation/Spec/zzspec.wml: Finish? the format + +2001-07-01 Sunday 14:26 Tuomas J. Lukka + + * Documentation/Spec/zzspec.wml: More syntax + +2001-07-01 Sunday 13:06 Tuomas J. Lukka + + * Documentation/Spec/zzspec.wml: More format, version comment + +2001-07-01 Sunday 12:53 Tuomas J. Lukka + + * Documentation/Spec/: SCRATCH, zzspec.wml, zzspec.wml: Start + working towards new file format. Move stuff that doesn't belong + into the spec into the scratch document. Point out to Tuukka where + he should start. + +2001-06-29 Friday 20:09 Rauli Ruohonen + + * Documentation/Math/math.ptex: Added raster definition + +2001-06-29 Friday 14:47 Tuomas J. Lukka + + * Documentation/Mediaserver/: id-format.jpg, id-sig-scheme.jpg: Add + images + +2001-06-29 Friday 14:15 Tuomas J. Lukka + + * Documentation/diagrams/revper-3.jpg: Third revper diagram + +2001-06-29 Friday 10:57 Tuomas J. Lukka + + * Documentation/diagrams/revper-2.jpg: A second diagram about + revper + +2001-06-29 Friday 10:51 Tuomas J. Lukka + + * Documentation/diagrams/revper-1.jpg: New diagram about reverse + perspective + +2001-06-29 Friday 08:45 Benjamin Fallenstein + + * Documentation/Mediaserver/ms.wml: Few comments + +2001-06-28 Thursday 23:12 Tuomas J. Lukka + + * Documentation/Mediaserver/ms.wml: A little more discussion + +2001-06-28 Thursday 22:38 Benjamin Fallenstein + + * Documentation/Mediaserver/ms.wml: Umlauts into HTML entities + +2001-06-28 Thursday 22:36 Benjamin Fallenstein + + * Documentation/Mediaserver/ms.wml: Update somewhat after IRC + discussion + +2001-06-28 Thursday 18:34 Tuomas J. Lukka + + * Documentation/Mediaserver/spoof-3rdparty.jpg: Add spoof image + +2001-06-21 Thursday 12:49 Tuomas J. Lukka + + * Documentation/Clang_Design/preflet_ladder.jpg: An amusing ladder + +2001-06-21 Thursday 11:17 Tuomas J. Lukka + + * Documentation/Clang_Design/cursor-impliedcells.jpg: Image + +2001-06-21 Thursday 11:03 Rauli Ruohonen + + * Documentation/Clang_Design/spacepart-cursor.jpeg: Doesn't work. + +2001-06-21 Thursday 10:22 Rauli Ruohonen + + * Documentation/Clang_Design/spacepart-cursor.jpeg: [no log + message] + +2001-06-21 Thursday 09:27 Tuomas J. Lukka + + * Documentation/: CyberText/1.png, CyberText/3.png, + CyberText/4.png, CyberText/Makefile, CyberText/ct-old.wml, + CyberText/ct.wml, CyberText/email.dia, CyberText/kello-o.png, + CyberText/kello.png, CyberText/permascroll.dia, + CyberText/rank1vert.dia, CyberText/rank2vert.dia, + CyberText/rank3both.dia, CyberText/vilma.png, Syntaxless/synt.wml: + Move manuscripts + +2001-06-21 Thursday 09:18 Tuomas J. Lukka + + * Documentation/: CellScroll/SCRATCH, DimBased/Makefile, + DimBased/dim.ptex, Interfacing/.cvsignore, Interfacing/Makefile, + Interfacing/int.ptex: Remove obsolete stuff + +2001-06-18 Monday 11:49 Kimmo Wideroos + + * Java/ZZGroupHighlightCache.java: get -method + +2001-06-18 Monday 04:54 Kimmo Wideroos + + * Java/flob/MultiFocusView.zob: minor + +2001-06-16 Saturday 09:53 Tuomas J. Lukka + + * Documentation/DesignProblems/mergemath.tex, Java/Makefile: Some + som code independent of everything else. For use in cookbook view + and possibly others. + +2001-06-14 Thursday 21:41 Tuomas J. Lukka + + * Documentation/DesignProblems/dp.wml: Make use of collections API + (which is included in debian's Kaffe) in Merge1. Makes code much + more readable, also almost working molecules + +2001-06-13 Wednesday 21:42 Tuomas J. Lukka + + * Modules/joystick/LinuxJoystick.java: Make filename used for test + changeable. + +2001-06-13 Wednesday 21:42 Tuomas J. Lukka + + * Documentation/index.html: Fix index + +2001-06-13 Wednesday 21:37 Tuomas J. Lukka + + * Documentation/: DesignProblems/dp.wml, + DesignProblems/mergemath.tex, diagrams/Molecule1.jpg, + diagrams/Molecule2.jpg, diagrams/Molecule3.jpg: More work on dp + +2001-06-13 Wednesday 11:29 Kimmo Wideroos + + * Java/: ZZGroupHighlightCache.java, ApplitudeMgr.java, + ZZDefaultSpace.java, ZZPrimitiveActions.java, flob/ClockView.zob, + flob/MultiFocusView.zob: multifocusview - several applitudes on + same view so that the layout changes as the focus changes. + +2001-06-12 Tuesday 00:01 Tuomas J. Lukka + + * Documentation/: DesignProblems/Makefile, DesignProblems/dp.wml, + DesignProblems/mergemath.tex, diagrams/Molecule1.jpg, + diagrams/Molecule2.jpg, diagrams/Molecule3.jpg, wmlinc/art.css: + More mergemath + +2001-06-09 Saturday 09:45 Kimmo Wideroos + + * Java/flob/CellFlobFactory1.zob: ...oops! forgot + +2001-06-09 Saturday 09:41 Kimmo Wideroos + + * Java/: ZZCanvasView.java, ZZGroupHighlightCache.java, + ZZKeyBindings1.java, ZZPrimitiveActions.java: (experimental...) + highlight cell(s) mouse touches + +2001-06-09 Saturday 09:27 Kimmo Wideroos + + * Java/ZZDefaultSpace.java: ClockView added in views + +2001-06-09 Saturday 09:26 Kimmo Wideroos + + * Java/flob/ClockView.zob: flobs arranged around a circle / 1-d + view + +2001-06-09 Saturday 09:24 Kimmo Wideroos + + * Java/ZZUtil.java: small fix: showDims support 1-d view + +2001-06-07 Thursday 09:55 Tuomas J. Lukka + + * Documentation/DesignProblems/: Makefile, dp.wml, mergemath.tex: + Integrate mergemath into dp + +2001-06-05 Tuesday 21:28 Benjamin Fallenstein + + * Documentation/Mediaserver/ms.wml: Gah, I've misread something. + Removed comment + +2001-06-05 Tuesday 18:52 Tuomas J. Lukka + + * Documentation/: DesignProblems/Makefile, DesignProblems/dp.wml, + DesignProblems/mergemath.tex, Mediaserver/Makefile, + Mediaserver/ms.wml, wmlinc/article.wml: More stuff. Merge logic. + Mediaserver crypto + +2001-06-02 Saturday 21:16 Antti-Juhani Kaijanaho + + * Documentation/wmlinc/: art.css, common.wml: ibid's voice + +2001-06-01 Friday 19:25 Benjamin Fallenstein + + * Documentation/Mediaserver/ms.wml: Update, commment + +2001-05-31 Thursday 06:46 Kimmo Wideroos + + * Documentation/misc/byrokratiadoku.txt: text-version, personnel + section slightly revisioned. + +2001-05-30 Wednesday 10:13 Tuomas J. Lukka + + * Documentation/DesignProblems/dp.wml: Note about independence + +2001-05-30 Wednesday 10:10 Tuomas J. Lukka + + * Documentation/DesignProblems/dp.wml: Define terminology for + change chunks: quarks, atoms, molecules + +2001-05-29 Tuesday 13:21 Tuomas J. Lukka + + * Documentation/Mediaserver/ms.wml: Ids + +2001-05-29 Tuesday 13:03 Tuomas J. Lukka + + * Documentation/Mediaserver/ms.wml: Remove the vulnerable scheme + +2001-05-29 Tuesday 12:52 Tuomas J. Lukka + + * Documentation/: DesignProblems/dp.wml, Mediaserver/ms.wml, + wmlinc/article.wml: Make ms doc validate correctly with w3c + validator. + +2001-05-29 Tuesday 12:29 Tuomas J. Lukka + + * Documentation/wmlinc/: art.css, common.wml: Colors + +2001-05-29 Tuesday 11:15 Tuomas J. Lukka + + * Documentation/Mediaserver/: ms.wml, ms.wml, ms.wml: More + +2001-05-29 Tuesday 10:43 Tuomas J. Lukka + + * Documentation/Mediaserver/: mediaserver.tex, ms.wml: Convert to + WML-HTML + +2001-05-28 Monday 07:28 Benjamin Fallenstein + + * Documentation/DesignProblems/dp.wml: Refer to Semantics + +2001-05-26 Saturday 17:24 Tuomas J. Lukka + + * Documentation/: DesignProblems/dp.wml, wmlinc/art.css: Merge + stuff. Talk and code. + +2001-05-25 Friday 12:54 Benjamin Fallenstein + + * Documentation/: DesignProblems/dp.wml, wmlinc/art.css, + wmlinc/common.wml: comment + +2001-05-24 Thursday 20:40 Rauli Ruohonen + + * Documentation/DesignProblems/dp.wml: Comment about "n" + dimensions. + +2001-05-24 Thursday 20:30 Rauli Ruohonen + + * Documentation/DesignProblems/dp.wml: Added stuff about 1:1 + dimensions to merge. + +2001-05-24 Thursday 19:11 Rauli Ruohonen + + * Documentation/DesignProblems/dp.wml: Clarifications. + +2001-05-24 Thursday 18:30 Rauli Ruohonen + + * Documentation/DesignProblems/dp.wml: Minor fix to the split rank + algorithm + a comment. + +2001-05-24 Thursday 18:19 Tuomas J. Lukka + + * Documentation/DesignProblems/dp.wml: Change chunks + +2001-05-24 Thursday 18:07 Tuomas J. Lukka + + * Documentation/: DesignProblems/CornerListViolation.jpg, + DesignProblems/dp.wml, Gentle_Introduction/gi.wml, + diagrams/CornerListViolation.jpg: Move discussion of structural + design + +2001-05-24 Thursday 17:32 Tuomas J. Lukka + + * Documentation/DesignProblems/dp.wml: Some more comments + +2001-05-24 Thursday 14:15 Rauli Ruohonen + + * Documentation/DesignProblems/dp.wml: Clarified myself wrt. + multiple split ranks. + +2001-05-23 Wednesday 21:10 Antti-Juhani Kaijanaho + + * Documentation/Spec/: formal.tex, oz.sty: a WIP spec in Z + +2001-05-23 Wednesday 20:23 Antti-Juhani Kaijanaho + + * Documentation/DesignProblems/dp.wml: fix a wml syntax error + +2001-05-23 Wednesday 19:43 Rauli Ruohonen + + * Documentation/DesignProblems/dp.wml: Committing, as I'm going + home now. I don't know whether I make any sense, as I don't have + time now to read what I wrote.. Anyway, added stuff about merging + split ranks. + +2001-05-23 Wednesday 16:38 Tuomas J. Lukka + + * Documentation/Manuscripts/gzigzag.bib: More refs + +2001-05-23 Wednesday 16:27 Rauli Ruohonen + + * Documentation/: DesignProblems/dp.wml, wmlinc/art.css, + wmlinc/common.wml: Added stuff about merging to dp. + +2001-05-23 Wednesday 14:56 Tuomas J. Lukka + + * Documentation/: Glossary/gl.wml, Manuscripts/gzigzag.bib: new + versioning refs. Mostly available through citeseer. + +2001-05-23 Wednesday 13:29 Tuomas J. Lukka + + * Documentation/Gentle_Introduction/: Cells.jpg, Dims.jpg, + ListGridTreeMesh.jpg, LocalGlobal.jpg, SpreadSheet.jpg, gi.wml: + Pictures + +2001-05-23 Wednesday 12:22 Tuomas J. Lukka + + * Documentation/DesignProblems/: ConflictLevels.jpg, dp.wml, + dp.wml: Conflict levels + +2001-05-23 Wednesday 10:08 Rauli Ruohonen + + * Documentation/: DesignProblems/dp.wml, RauliLogo.png: [no log + message] + +2001-05-23 Wednesday 05:43 Rauli Ruohonen + + * Documentation/misc/byrokratiadoku: Some ancient uncommitted + changes. + +2001-05-22 Tuesday 11:24 Tuomas J. Lukka + + * Documentation/DesignProblems/: RelationConflict.jpg, dp.wml: Ok, + getting there. Biggest problem seems now to be HTML and the page + layout. Urgh. Hope we can get ZZ there soon + +2001-05-21 Monday 09:45 Tuomas J. Lukka + + * Documentation/DesignProblems/dp.wml: The floating images seem to + be impossible for anything else except mozilla to handle. Sad. + +2001-05-21 Monday 08:02 Tuomas J. Lukka + + * Documentation/: DesignProblems/ABCD.jpg, + DesignProblems/LLMergeProblem.jpg, + DesignProblems/LLMergeProblem2.jpg, DesignProblems/SegCases.jpg, + DesignProblems/SegExamples.jpg, DesignProblems/beamorder.png, + DesignProblems/dp.wml, DesignProblems/linkorder.png, + wmlinc/art.css: Some images, getting towards solution + +2001-05-20 Sunday 08:01 Tuomas J. Lukka + + * Documentation/wmlinc/art.css: Adjust margin + +2001-05-19 Saturday 18:10 Tuomas J. Lukka + + * Documentation/TjlLogo.png: Add + +2001-05-19 Saturday 18:06 Tuomas J. Lukka + + * Documentation/: DesignProblems/dp.wml, wmlinc/art.css, + wmlinc/common.wml: Add voices to the DesignProblems doc. We should + discuss this kind of thing in more detail at some point, as it + seems that all our docs are going that way - is it just me or is it + actully useful? It seems to work so that there is one editor, who + decides what the 'absolute' voice is and he and others as well + discuss things and propose changes. Also, if you feel like it, you + can make a logo and pick a color for yourself - it clarifies the + comments somewhat. + +2001-05-18 Friday 23:06 Rauli Ruohonen + + * Documentation/DesignProblems/dp.wml: Mods. + +2001-05-18 Friday 19:32 Rauli Ruohonen + + * Documentation/DesignProblems/dp.wml: Corrected myself. + +2001-05-18 Friday 17:44 Rauli Ruohonen + + * Documentation/DesignProblems/dp.wml: Added basic stuff about + identity cells. + +2001-05-18 Friday 12:08 Tuomas J. Lukka + + * Documentation/: DesignProblems/dp.wml, wmlinc/art.css: More stuff + about versioning. Please read, some important ideas inside (see + Linked-list approach fails) + +2001-05-17 Thursday 21:02 Tuomas J. Lukka + + * Documentation/DesignProblems/: CornerListViolation.jpg, + DifficultMerge.jpg, LargeScaleRearrange.jpg, dp.wml: Add images + +2001-05-17 Thursday 09:18 Tuomas J. Lukka + + * Documentation/: lib.mk, DesignProblems/dp.wml, wmlinc/art.css: + More design + +2001-05-16 Wednesday 14:33 Tuomas J. Lukka + + * Documentation/DesignProblems/dp.wml: More + +2001-05-16 Wednesday 13:54 Tuomas J. Lukka + + * Documentation/: DesignProblems/dp.wml, wmlinc/art.css: Remove + out-of-date stuff. Add styles for speakers. + +2001-05-16 Wednesday 08:42 Tuomas J. Lukka + + * Documentation/DesignProblems/dp.wml: Start reviving this + document. Please put in comments etc. + +2001-05-15 Tuesday 14:26 Kimmo Wideroos + + * Documentation/Manuscripts/Awt/view-zzstructure.epsi: awt + iew+struct for dummies + +2001-05-15 Tuesday 14:23 Kimmo Wideroos + + * Documentation/Manuscripts/Awt/awt.tex: awt (work in progress) + description + +2001-05-15 Tuesday 14:18 Kimmo Wideroos + + * Documentation/Manuscripts/gzigzag.bib: awt refs + +2001-05-15 Tuesday 04:33 Tuomas J. Lukka + + * Documentation/Manuscripts/gzigzag.bib: Work on image scrolls + +2001-05-11 Friday 17:38 Vesa Parkkinen + + * Documentation/Manuscripts/gzigzag.bib: added robertson91 + +2001-05-11 Friday 14:33 Kimmo Wideroos + + * Documentation/Manuscripts/gzigzag.bib: Berlage's taps ref + +2001-05-11 Friday 07:07 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/: Makefile, hyps.tex: oho + +2001-05-10 Thursday 21:32 Rauli Ruohonen + + * Java/flob/: RankTextView.zob, SplitCellFlob1.java: The real fix + by Tuomas. + +2001-05-10 Thursday 20:57 Rauli Ruohonen + + * Java/flob/RankTextView.zob: A terrible, non-working hack. + +2001-05-10 Thursday 13:47 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyps.tex: more... + +2001-05-10 Thursday 13:36 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyps.tex: Some more + +2001-05-10 Thursday 10:17 Tuomas J. Lukka + + * Java/flob/SimpleBeamer.zob: More baming + +2001-05-10 Thursday 09:57 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyps.tex: bah + +2001-05-10 Thursday 09:55 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyps.tex: Some more + +2001-05-10 Thursday 08:33 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyps.tex: A rather trivial + shortening of hyp, focusing on RFCs as a document set + +2001-05-09 Wednesday 16:01 Benjamin Fallenstein + + * Java/ZZTextView.java (ver_0_6): Update + +2001-05-09 Wednesday 15:41 Benjamin Fallenstein + + * Java/: ZZPrimitiveActions.java, ZZTextView.java (ver_0_6): A + quick hack for Marlene using AWT for editing + +2001-05-09 Wednesday 12:33 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/gzigzag.bib: Fix GZZ capitalization + +2001-05-09 Wednesday 10:21 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/gzigzag.bib: some references + +2001-05-06 Sunday 22:27 Tuomas J. Lukka + + * Documentation/Manuscripts/gzigzag.bib: Add jazz ref + +2001-04-30 Monday 09:31 Tuomas J. Lukka + + * Java/: arch/java2d/ZZDrawingJ2D.java, flob/SceneFlob.java: Fix my + quick fix that reverted Benja's work. Now RotatedSceneFlob + correctly says that it doesn't need a box + +2001-04-30 Monday 08:38 Tuomas J. Lukka + + * Java/flob/FTextLayouter.zob, + Modules/virtualcommunity/MessageFlobFactory.zob: More + virtualcommunity fixes + +2001-04-30 Monday 08:23 Tuomas J. Lukka + + * Java/flob/SceneFlob.java, + Modules/virtualcommunity/MessageFlobFactory.zob: Make + virtualcommunity demo work again: SceneFlob MUST NOT BE BOXED FLOB: + rotated sceneflobs go totally screwy. + +2001-04-29 Sunday 22:21 Tuomas J. Lukka + + * Documentation/Manuscripts/gzigzag.bib: Ref + +2001-04-25 Wednesday 09:36 Tuomas J. Lukka + + * Modules/benchmark/GraphBench.java: Color benchmark + +2001-04-24 Tuesday 11:13 Tuomas J. Lukka + + * Documentation/Manuscripts/: gzigzag.bib, gzigzag.bib: More + +2001-04-24 Tuesday 07:36 Tuomas J. Lukka + + * Documentation/Manuscripts/gzigzag.bib: Ref + +2001-04-23 Monday 21:56 Benjamin Fallenstein + + * Modules/zaubertrank/Zaubertrank.java: Simplify a LOT + +2001-04-23 Monday 21:45 Benjamin Fallenstein + + * Modules/zaubertrank/ZaubertrankTemplate.java: Simplify + +2001-04-23 Monday 21:22 Benjamin Fallenstein + + * Modules/zaubertrank/ZaubertrankCellView.java: Some work on the + zaubertrank + +2001-04-23 Monday 14:19 Benjamin Fallenstein + + * Modules/zaubertrank/Zaubertrank.java: Make it (somewhat) work + +2001-04-23 Monday 13:25 Benjamin Fallenstein + + * Modules/zaubertrank/Zaubertrank.java: yet more + +2001-04-23 Monday 13:18 Benjamin Fallenstein + + * Modules/zaubertrank/: Zaubertrank.java, ZaubertrankTemplate.java: + More internals of the zaubertrank + +2001-04-23 Monday 12:12 Benjamin Fallenstein + + * Java/VirtualEditCursor.java: add size() to VirtualEditCursor + +2001-04-23 Monday 12:07 Benjamin Fallenstein + + * Java/VirtualEditCursor.java: Make VirtualEditCursor impl more + reasonable + +2001-04-23 Monday 11:38 Benjamin Fallenstein + + * Java/: EditCursor.java, VirtualEditCursor.java: Virtual edit + cursors + +2001-04-21 Saturday 16:34 Benjamin Fallenstein + + * Modules/zaubertrank/ZaubertrankTemplate.java: more + +2001-04-21 Saturday 12:39 Benjamin Fallenstein + + * Modules/zaubertrank/ZaubertrankTemplate.java: Hah! Another + successful iteration of the zaubertrank! ;) + +2001-04-21 Saturday 04:31 Benjamin Fallenstein + + * Java/Makefile, Modules/zaubertrank/ZaubertrankTemplate.java: + Small addition to the test + +2001-04-21 Saturday 04:24 Benjamin Fallenstein + + * Modules/zaubertrank/ZaubertrankTemplate.java: Yet another small + zaubertrank iteration (this is working towards a better editor, but + building abstractions in small steps first, to be sure they work + right) + +2001-04-21 Saturday 03:51 Benjamin Fallenstein + + * Modules/zaubertrank/ZaubertrankTemplate.java: Yet more work on + the zaubertrank + +2001-04-21 Saturday 01:11 Benjamin Fallenstein + + * Java/p2p/P2PStorageCache.java: Make p2p compile by creating dummy + method bodies in P2PStorageCache + +2001-04-21 Saturday 01:04 Benjamin Fallenstein + + * Java/Makefile: Make tests compiled and run by default, like in + the new API (archieved by defaulting ARCH to junit). + +2001-04-21 Saturday 01:02 Benjamin Fallenstein + + * Java/: media/ImageSpan.java, transform/Version2.java: Make + compile without warnings (except for p2p) + +2001-04-19 Thursday 18:33 Benjamin Fallenstein + + * Java/Makefile: Make compile again + +2001-04-19 Thursday 14:49 Benjamin Fallenstein + + * Modules/zaubertrank/Zaubertrank.java: Small changes + +2001-04-19 Thursday 05:59 Benjamin Fallenstein + + * Java/ZZUtil.java, Modules/zaubertrank/Zaubertrank.java, + Modules/zaubertrank/ZaubertrankCellView.java: More work on the + zaubertrank, make keyboard editing work as well as mouse editing + (however, both are somewhat crude still) + +2001-04-18 Wednesday 23:38 Benjamin Fallenstein + + * Java/ZZCell.java: Make old intersect() and intersectAll() + implementations include the cells they're starting at; they're part + of the rank, so they can form an intersection (i.e. if one of the + two start cells is on the rank the other start cell forms) + +2001-04-18 Wednesday 21:46 Benjamin Fallenstein + + * Java/flob/.cvsignore: Add SimpleBeamer2 + +2001-04-18 Wednesday 21:46 Benjamin Fallenstein + + * Java/Makefile: Add Archimedes to makefile + +2001-04-18 Wednesday 21:40 Benjamin Fallenstein + + * Java/EditCursor.java, Java/ZZDefaultSpace.java, + Java/ZZModule.java, Java/ZZPrimitiveActions.java, + Modules/zaubertrank/Zaubertrank.java, + Modules/zaubertrank/ZaubertrankCellView.java: More fiddling with + the zaubertrank; make actions taking dirs work in modules + +2001-04-18 Wednesday 19:22 Tuomas J. Lukka + + * Java/EditCursor.java: Fix unclosed em + +2001-04-17 Tuesday 16:40 Antti-Juhani Kaijanaho + + * Java/: Makefile, ZZCanvasView.java, ZZKeyBindings1.java, + ZZObsTrigger.java, ZZPrimitiveActions.java, ZZViewComponent.java, + part/VersionPart.java: merge from 0.6 + +2001-04-17 Tuesday 15:47 Benjamin Fallenstein + + * Java/: EditCursor.java, ZZCursorReal.java: More edit cursor stuff + +2001-04-17 Tuesday 11:25 Benjamin Fallenstein + + * Java/: media/FText.java, flob/SplitCellFlob1.java: Allow + arbitrary handles (== objects returned by hit()) for SplitCellFlobs + and FText.CellParts + +2001-04-16 Monday 21:33 Benjamin Fallenstein + + * Java/: EditCursor.java, ZZCursorReal.java: Edit cursor stuff + (ZZPrimitiveActions hasn't been converted yet) + +2001-04-16 Monday 10:44 Benjamin Fallenstein + + * Java/ZZPrimitiveActions.java: Oops. (removed a part that would've + prevented compiling). Now, the change in ZZPrimitiveActions is that + all actions using VStream are removed. + +2001-04-16 Monday 10:37 Benjamin Fallenstein + + * Java/ZZPrimitiveActions.java, + Modules/zaubertrank/ZaubertrankCellView.java: More Archimedes + fiddling + +2001-04-15 Sunday 16:26 Benjamin Fallenstein + + * Modules/zaubertrank/ZaubertrankCellView.java: More tuning on + Archimedes/the zaubertrank connection + +2001-04-15 Sunday 14:18 Benjamin Fallenstein + + * Java/flob/SplitCellFlob1.java, Java/media/FText.java, + Modules/zaubertrank/ZaubertrankCellView.java: Make the zaubertrank + work somewhat together with Archimedes + +2001-04-15 Sunday 11:01 Tuomas J. Lukka + + * Java/media/VStream.java: Remove VStream.java + +2001-04-15 Sunday 11:00 Tuomas J. Lukka + + * Java/p2p/: P2PStorage.java, P2PStorageCache.java, UniqueID.java: + Small changes + +2001-04-13 Friday 22:40 Benjamin Fallenstein + + * Java/ZZKeyHacks.java: Oops... and huh? + +2001-04-13 Friday 22:38 Benjamin Fallenstein + + * Java/ZZKeyBindings1.java: Another input event hack, this time for + the Macintosh mouse (convert no button --> Button 1, and when the + Meta key is down (Apple key on Macs), use Button 3 bindings which + are quite important in GZZ.) + +2001-04-13 Friday 21:47 Kimmo Wideroos + + * Java/flob/: BeamDecor2.java, SimpleBeamer2.zob: + oops! fixed class naming - hope it works now. Thanks Benja for + mentioning! + +2001-04-12 Thursday 11:26 Kimmo Wideroos + + * Modules/awtool/: AwtNileView.java, AwtUtil.java, AwtView1.java, + Awtool.java, Awtool.zob, README: Resizing, Nile transclusion etc. + +2001-04-12 Thursday 09:23 Kimmo Wideroos + + * Java/flob/: BeamDecor2.java, SimpleBeamer2.zob: Instead of filled + beams draw frames around transcluded textchunks. + +2001-04-09 Monday 09:19 Antti-Juhani Kaijanaho + + * manifest-filter.lst (ver_0_6): don't include manuscripts in + releases + +2001-04-08 Sunday 18:12 Antti-Juhani Kaijanaho + + * Java/Makefile (ver_0_6): remove multimedia, virtualcommunity & + java2d from jar build + +2001-04-08 Sunday 17:07 Antti-Juhani Kaijanaho + + * Java/Makefile (ver_0_6): add jar arch support + +2001-04-08 Sunday 17:00 Antti-Juhani Kaijanaho + + * Modules/virtualcommunity/MessageFlobFactory.zob (ver_0_6): make + vc compile + +2001-04-08 Sunday 16:36 Antti-Juhani Kaijanaho + + * Java/Makefile (ver_0_6): add virtualcommunity and multimedia back + to jars + +2001-04-08 Sunday 16:24 Antti-Juhani Kaijanaho + + * Java/part/VersionPart.java (ver_0_6): fix + +2001-04-08 Sunday 16:18 Benjamin Fallenstein + + * NEWS (ver_0_6): Add umlaut bugfix + +2001-04-08 Sunday 16:13 Antti-Juhani Kaijanaho + + * Java/ZZObsTrigger.java (ver_0_6): fix a lame bug (causes null + pointer exceptions) + +2001-04-08 Sunday 15:49 Benjamin Fallenstein + + * Java/: ZZPrimitiveActions.java, ZZPrimitiveActions.java + (ver_0_6): Fix + +2001-04-08 Sunday 15:36 Antti-Juhani Kaijanaho + + * NEWS (ver_0_6): update + +2001-04-08 Sunday 15:17 Benjamin Fallenstein + + * Java/: ZZKeyHacks.java, ZZPrimitiveActions.java (ver_0_6): Use + Unicode character range instead of some predefined characters + +2001-04-08 Sunday 15:16 Antti-Juhani Kaijanaho + + * Java/Makefile (ver_0_6): add it here too + +2001-04-08 Sunday 15:11 Benjamin Fallenstein + + * Java/Makefile: Add the zaubertrank to JARMODULES + +2001-04-08 Sunday 15:07 Antti-Juhani Kaijanaho + + * Java/Makefile: fix BuildInfo building + +2001-04-08 Sunday 13:27 Antti-Juhani Kaijanaho + + * Java/Makefile (ver_0_6): BAH! + +2001-04-08 Sunday 13:20 Antti-Juhani Kaijanaho + + * Java/Makefile (ver_0_6): remove net from sources + +2001-04-08 Sunday 13:00 Benjamin Fallenstein + + * Java/: ZZCanvasView.java, ZZKeyBindings1.java, + ZZPrimitiveActions.java (ver_0_6): Background colors for modes + +2001-04-08 Sunday 13:00 Antti-Juhani Kaijanaho + + * Java/Makefile (ver_0_6): remove multimedia from jarmodules + +2001-04-08 Sunday 12:56 Tuomas J. Lukka + + * Modules/textcloud/TextCloud.zob: Textcloud is not compatible with + intended changes - will need to be rewritten later + +2001-04-08 Sunday 12:50 Antti-Juhani Kaijanaho + + * Java/Makefile (ver_0_6): remove virtualcommunity from jarmodules + +2001-04-08 Sunday 11:50 Benjamin Fallenstein + + * Java/ZZKeyHacks.java: file ZZKeyHacks.java was initially added on + branch ver_0_6. + +2001-04-08 Sunday 11:50 Benjamin Fallenstein + + * Java/: ZZKeyHacks.java, ZZViewComponent.java (ver_0_6): The + umlaut hack detecting VM behavior + +2001-04-07 Saturday 18:17 Tuomas J. Lukka + + * Java/media/: ZZDefaultText.java, ZZText.java: Remove: this should + be done with cell content applitudes. + +2001-04-05 Thursday 15:14 Benjamin Fallenstein + + * Modules/vob/: View.java, Vob.java, VobSet.java, VobStore.java: We + can get rid of these anyway. + +2001-04-05 Thursday 13:27 Tuomas J. Lukka + + * Modules/: nile/draft/Nile3Unit.java, vob/Vob.java: Make 1.3 + javadoc work again. + +2001-04-05 Thursday 13:24 Tuomas J. Lukka + + * Modules/vob/Connection.java: What in the world was that? + +2001-04-05 Thursday 08:54 Antti-Juhani Kaijanaho + + * Java/Makefile: an experimental target for native compilation + using GCC Java + +2001-04-04 Wednesday 18:10 Tuomas J. Lukka + + * Java/: Makefile, media/ImageSpan.java, p2p/P2PStorage.java, + p2p/P2PStorageCache.java, p2p/UniqueID.java: More p2p stuff. + StorageCache is already outdated + +2001-04-04 Wednesday 18:09 Tuomas J. Lukka + + * Java/storage/DummyStreamSet.java, Modules/applet/ZZApplet.java: + Id + +2001-04-03 Tuesday 15:29 Benjamin Fallenstein + + * NEWS: Update + +2001-04-03 Tuesday 15:28 Benjamin Fallenstein + + * Java/ZZDefaultSpace.java: Add multiline cell view and quad view + to standard views/cell views (quad because currently you can see + multiline only there). + +2001-04-03 Tuesday 15:02 Benjamin Fallenstein + + * Java/: ZZDefaultSpace.java, ZZKeyBindings1.java, + ZZPrimitiveActions.java: Add support for cellview-specific + bindings; however, this isn't very useful until we have seperate + view and edit cursors, too... + +2001-04-03 Tuesday 11:23 Antti-Juhani Kaijanaho + + * Documentation/Mediaserver/mediaserver.tex: New ID format + +2001-04-03 Tuesday 08:59 Antti-Juhani Kaijanaho + + * Documentation/Mediaserver/mediaserver.tex: A draft spec for the + storage module HTTP interface + +2001-04-02 Monday 20:32 Benjamin Fallenstein + + * Java/Makefile: Add zaubertrank to modules + +2001-04-02 Monday 20:30 Benjamin Fallenstein + + * Modules/zaubertrank/: Actions.java, Evaluator.java, + ParsedView.zob, Parser.java, Primitive.java, PrimitiveSet.java, + SimpleView.zob, TokenFlob.java, TokenGrouper.java, + Zaubertrank.java, ZaubertrankPart.java: Move + +2001-04-02 Monday 20:29 Benjamin Fallenstein + + * Modules/zaubertrank/old/: Actions.java, Evaluator.java, + ParsedView.zob, Parser.java, Primitive.java, PrimitiveSet.java, + SimpleView.zob, TokenFlob.java, TokenGrouper.java, + Zaubertrank.java, ZaubertrankPart.java: Move old crud + +2001-04-02 Monday 20:23 Benjamin Fallenstein + + * Modules/zaubertrank/ZaubertrankCellView.java: Another cell view + for the zaubertrank, showing a tree of assembled tokens + +2001-04-02 Monday 20:21 Benjamin Fallenstein + + * Java/flob/SplitCellFlob1.java: Fix even more + +2001-04-02 Monday 20:20 Benjamin Fallenstein + + * Java/flob/FTextCellView.zob: fix more + +2001-04-02 Monday 20:02 Benjamin Fallenstein + + * Java/: flob/RankTextView.zob, flob/SimpleTextView.zob, + media/FText.java: Show cursors again + +2001-04-02 Monday 20:00 Benjamin Fallenstein + + * Java/flob/SplitCellFlob1.java: Do show backgrounds during + interpolation + +2001-04-02 Monday 19:31 Benjamin Fallenstein + + * Java/: flob/FTextCellView.zob, media/FText.java: Fix + FTextCellView.getSize() + +2001-04-02 Monday 17:23 Tuomas J. Lukka + + * Java/p2p/: P2PStorage.java, UniqueID.java: Add ids + +2001-04-02 Monday 17:22 Tuomas J. Lukka + + * Documentation/Mediaserver/mediaserver.tex: Rm code + +2001-04-02 Monday 16:59 Benjamin Fallenstein + + * Java/flob/FTextCellView.zob: Small fix (pass rootclone to + getFText()). + +2001-04-02 Monday 16:38 Benjamin Fallenstein + + * Java/ZZCursorReal.java: A method in ZZCursorReal to get the color + of the first colored cursor accursing a cell. + +2001-04-02 Monday 10:09 Antti-Juhani Kaijanaho + + * Documentation/Mediaserver/mediaserver.tex: Some crypto + +2001-04-01 Sunday 17:45 Benjamin Fallenstein + + * Modules/zaubertrank/TokenTextCellView.java: A cell view for + zaubertrank token text editing. + +2001-04-01 Sunday 15:47 Tuomas J. Lukka + + * Java/p2p/: P2PStorage.java, UniqueID.java: Add mediaserver apis + +2001-04-01 Sunday 15:46 Tuomas J. Lukka + + * Java/storage/DummyStreamSet.java, Modules/applet/ZZApplet.java: + Separate dummystreamset + +2001-04-01 Sunday 11:38 Tuomas J. Lukka + + * Modules/benchmark/: GraphBench.java, ZZBench.java, + java2d/Java2DBench.java: Some extra tests + +2001-03-31 Saturday 13:31 Tuomas J. Lukka + + * Documentation/Mediaserver/mediaserver.tex: Add id + +2001-03-31 Saturday 13:30 Tuomas J. Lukka + + * Documentation/Mediaserver/mediaserver.tex: Some more + +2001-03-31 Saturday 13:26 Tuomas J. Lukka + + * Documentation/Mediaserver/mediaserver.tex: Indents + +2001-03-31 Saturday 13:23 Tuomas J. Lukka + + * Documentation/Mediaserver/mediaserver.tex: Architecture + +2001-03-30 Friday 17:21 Benjamin Fallenstein + + * Java/flob/FTextCellView.java: Yuck + +2001-03-30 Friday 16:19 Benjamin Fallenstein + + * Java/flob/: .cvsignore, CellFlobFactory1.zob, FTextCellView.java, + FTextCellView.zob, FTextLayouter.zob, SplitCellFlob1.java: An + FText-based cell view doing multiline; fixes. Note that + SplitCellFlobs won't show cursors in their backgrounds any more. + Need to fix this for RankTextView probably. (However, for 'real' + applications it just got in the way before.) + +2001-03-30 Friday 13:26 Antti-Juhani Kaijanaho + + * Documentation/Mediaserver/mediaserver.tex: Some ideas, including + a way to decentralizedly guarantee unique IDs. + +2001-03-30 Friday 10:33 Antti-Juhani Kaijanaho + + * NEWS: Update + +2001-03-30 Friday 10:30 Antti-Juhani Kaijanaho + + * changelog-authors: fix wikikr + +2001-03-29 Thursday 13:06 Antti-Juhani Kaijanaho + + * Java/: CommandLineOptionsParser.java, Main.java: a new + command-line options parser, closes task#20858 + +2001-03-28 Wednesday 08:37 Antti-Juhani Kaijanaho + + * Java/ZZDefaultSpace.java: Fix Tuomas' fix. + +2001-03-28 Wednesday 07:03 Antti-Juhani Kaijanaho + + * Documentation/Mediaserver/mediaserver.tex: More TeXification + +2001-03-28 Wednesday 06:48 Antti-Juhani Kaijanaho + + * Documentation/Mediaserver/mediaserver.tex: Fix LaTeX + +2001-03-28 Wednesday 06:47 Antti-Juhani Kaijanaho + + * Documentation/: mediaserver, Mediaserver/mediaserver.tex: TeXify + mediaserver + +2001-03-28 Wednesday 06:32 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/ZZTech/zztech.tex: Remove a comment. + +2001-03-28 Wednesday 05:55 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/ZZTech/zztech.tex: Some tinkering of + the abstract + the length requirement for the abstract + +2001-03-27 Tuesday 20:43 Tuomas J. Lukka + + * Documentation/mediaserver, Java/ZZDefaultSpace.java, + Modules/sound/Player.java, Modules/sound/SimplePlayer.java, + Modules/sound/Sound.java: Cleanup, fixes. Add new mediaserver doc + +2001-03-26 Monday 14:39 Rauli Ruohonen + + * Documentation/misc/byrokratiadoku: Mods. + +2001-03-26 Monday 14:24 Tuomas J. Lukka + + * Documentation/Manuscripts/ZZTech/zztech.tex: Draft abstract + +2001-03-26 Monday 12:41 Tuomas J. Lukka + + * Java/ZZDrawing.java, Java/arch/java2d/ZZDrawingJ2D.java, + Modules/benchmark/GraphBench.java, Modules/benchmark/ZZBench.java, + Modules/benchmark/java2d/Java2DBench.java: Add new benchmarks. Very + instructive to run on a couple of different JVMs + +2001-03-25 Sunday 12:06 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/ZZTech/zztech.tex: Small touches + +2001-03-23 Friday 08:30 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/ZZTech/zztech.tex: A small comment on + versioning. + +2001-03-21 Wednesday 20:03 Tuomas J. Lukka + + * Java/Makefile, Modules/benchmark/README, + Modules/benchmark/ZZBench.java: Benchmarking JVMs. Sun 1.3 vs IBM + 1.3 is interesting... + +2001-03-21 Wednesday 10:01 Antti-Juhani Kaijanaho + + * Java/media/UTF8Char.java: c.b starts at 0, not at start. + embarrassing. + +2001-03-20 Tuesday 11:08 Antti-Juhani Kaijanaho + + * Java/flob/BoxedFlob.java: from Benja + +2001-03-20 Tuesday 09:45 Tuomas J. Lukka + + * Documentation/Manuscripts/Rasters/raster.tex, + Java/exp/rast/vanishing.view: MOre constr + +2001-03-19 Monday 07:31 Tuomas J. Lukka + + * Documentation/Manuscripts/Rasters/raster.tex: Add point + +2001-03-18 Sunday 20:22 Tuomas J. Lukka + + * Java/net/: ReliableUDPMessage.java, + ReliableUDPMessageFactory.java, ReliableUDPSocket.java: Reformat + and add doc + +2001-03-18 Sunday 20:21 Antti-Juhani Kaijanaho + + * Java/net/Peer.java: Document Peer. + +2001-03-18 Sunday 19:31 Antti-Juhani Kaijanaho + + * Java/net/: ReliableUDPMessage.java, + ReliableUDPMessageFactory.java, ReliableUDPSocket.java: some + documentation on the reliable UDP scheme + +2001-03-18 Sunday 17:50 Benjamin Fallenstein + + * Java/flob/BoxType.java, Java/flob/CellFlob1.java, + Java/flob/FlobSet.java, Java/flob/SceneFlob.java, + Java/flob/SimpleBoxType.java, Java/flob/SimpleSceneFlob.java, + Java/flob/WindowCellView.zob, + Modules/daytimedemo/ClockCellView.zob: Now make regular background + colors for BoxType boxes work. At the same time, move CellFlobs to + use BoxTypes. -- ATTN: Changing CellFlob1's superclass breaks + binary compatibility again... + +2001-03-18 Sunday 11:04 Benjamin Fallenstein + + * Java/flob/FlobSet.java: Aforementioned bug fixed. + +2001-03-18 Sunday 10:38 Benjamin Fallenstein + + * Java/flob/IdiosyncraticFlobFactory.zob, + Java/flob/WindowCellView.zob, + Modules/daytimedemo/ClockCellView.zob: Idiosyncratic should search + the cell view at the root clone, so that e.g. clocks and windows + (in the examples) can be cloned. There's a BUG though which haven't + been able to track down yet: showing two clones of the same thing + at the same time causes the update loop to stop. + +2001-03-17 Saturday 23:08 Benjamin Fallenstein + + * Java/flob/: BoxType.java, Flob.java, FlobSet.java, + SimpleBoxType.java, SimpleSceneFlob.java: An interface separating + frame/bg rendering from content rendering, currently drawing the + same background/frame as CellBgFlob. Used to give the window cell + view cells a real frame. They don't look that bad now. + +2001-03-17 Saturday 22:12 Benjamin Fallenstein + + * Java/flob/: .cvsignore, SimpleSceneFlob.java, WindowCellView.zob: + A cell view showing the contents of a window-- i.e., a window's + cursor cell is drawn as a SceneFlob regularly filled with that + window's view/contents. + +2001-03-17 Saturday 20:13 Benjamin Fallenstein + + * Java/flob/: FlobSet.java, Renderable.java, SceneFlob.java: Some + preparations for doing actual transpointing windows based on + SceneFlobs. ATTN: I have changed FlobSet.DepthIter from an + interface to an abstract class. This doesn't change the source, + because DepthIter is always implemented/subclassed anonymously, but + it breaks binary compatibility. + +2001-03-17 Saturday 11:17 Benjamin Fallenstein + + * Java/flob/SimpleSceneFlob.java, Modules/daytimedemo/.cvsignore, + Modules/daytimedemo/ClockCellView.zob, + Modules/daytimedemo/DayTimeDemo.zob: In order to get familiar with + the SceneFlob code, a simple demo showing cells as daytimedemo + clocks (i.e. a cell view for use with idiosyncratic) + +2001-03-16 Friday 14:46 Rauli Ruohonen + + * Documentation/misc/byrokratiadoku: The "explanation of + GZigZag"-part should be much better now. + +2001-03-16 Friday 14:15 Rauli Ruohonen + + * Documentation/misc/byrokratiadoku: Quite heavy mods. + +2001-03-16 Friday 12:33 Kimmo Wideroos + + * Documentation/Manuscripts/: gzigzag.bib, Awt/Makefile, + Awt/awt.tex, Awt/awtf.tex, Awt/ht01e.sty: Started a shortpaper on + awt concept map demo. My latex skills are 0, so I had to "borrow" + some tex-stuff from HyperRFC-article. Thanks Tuomas, Rauli, Vesa + and AJK ;) + +2001-03-16 Friday 12:19 Kimmo Wideroos + + * Modules/awtool/: AwtCursor.java, AwtMetrics.java, AwtMetrics.zob, + AwtNileView.java, AwtUtil.java, AwtView1.java, Awtool.java, + Awtool.zob: Nile embedded. If you want to try it out, change + between Nile and Awtool by 'Alt-N'. This is preliminary work, only + basic Nile actions "tested". + +2001-03-15 Thursday 19:24 Antti-Juhani Kaijanaho + + * Java/: Makefile, net/Peer.java, net/ReliableUDPMessage.java, + net/ReliableUDPMessageFactory.java, net/ReliableUDPSocket.java: an + untested but compilable Reliable UDP implementation + +2001-03-15 Thursday 16:50 Rauli Ruohonen + + * Documentation/misc/byrokratiadoku: Better paragraph 2? (rest of + the document doesn't work at all) + +2001-03-15 Thursday 15:50 Rauli Ruohonen + + * Documentation/misc/byrokratiadoku: Minor mod to paragraph 2. + +2001-03-15 Thursday 14:37 Rauli Ruohonen + + * Documentation/misc/byrokratiadoku: Bureaucracy. + +2001-03-14 Wednesday 20:10 Benjamin Fallenstein + + * Documentation/Manuscripts/ZZTech/zztech.tex: More versioning + comments + +2001-03-14 Wednesday 07:13 Antti-Juhani Kaijanaho + + * Java/ZZLogger.java: Emphasize that logfile is null at startup. + +2001-03-13 Tuesday 15:30 Rauli Ruohonen + + * Documentation/misc/byrokratiadoku: More bureaucracy. + +2001-03-12 Monday 14:03 Tuomas J. Lukka + + * Documentation/Manuscripts/Rasters/raster.tex: Twid + +2001-03-12 Monday 13:38 Tuomas J. Lukka + + * Documentation/Manuscripts/Rasters/raster.tex: More + +2001-03-12 Monday 13:32 Rauli Ruohonen + + * Documentation/misc/byrokratiadoku: Added a terrible byrocratic + document (in Finnish). Hopefully it drops off the edge of the hard + disk soon. + +2001-03-12 Monday 11:08 Tuomas J. Lukka + + * Documentation/Manuscripts/Rasters/: Makefile, raster.tex: More + +2001-03-12 Monday 06:04 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/ZZTech/zztech.tex: Some thoughts about + version persistency and branching. + +2001-03-11 Sunday 19:14 Vesa Parkkinen + + * Java/media/Span.java, Modules/sound/Player.java, + Modules/sound/Recorder.java, Modules/sound/SimplePlayer.java, + Modules/sound/SimpleRecorder.java, Modules/sound/Sound.java, + Modules/sound/gsm_def.h, Modules/sound/gsm_player.c, + Modules/sound/gsm_recorder.c, + Modules/sound/org_gzigzag_module_SimplePlayer.h, + Modules/sound/org_gzigzag_module_SimpleRecorder.h, + Modules/sound/ZZPlayer.java: some sound stuff + +2001-03-11 Sunday 10:41 Kimmo Wideroos + + * Modules/awtool/: AwtUtil.java, AwtView1.java, Awtool.java, + Awtool.zob: bugfixes, got rid of some unnecessary variables + +2001-03-10 Saturday 10:32 Tuomas J. Lukka + + * Documentation/Manuscripts/Rasters/raster.tex: oops + +2001-03-10 Saturday 10:31 Tuomas J. Lukka + + * Documentation/Manuscripts/Rasters/raster.tex: Index changes + +2001-03-09 Friday 13:34 Tuomas J. Lukka + + * Documentation/Manuscripts/gzigzag.bib: Add more constr refs + +2001-03-09 Friday 08:54 Tuomas J. Lukka + + * Documentation/Manuscripts/: gzigzag.bib, Rasters/raster.tex: Add + constr refs + +2001-03-08 Thursday 15:05 Tuomas J. Lukka + + * Documentation/Manuscripts/Rasters/raster.tex: Some more + +2001-03-08 Thursday 15:05 Tuomas J. Lukka + + * CODING: Document exp + +2001-03-08 Thursday 13:54 Antti-Juhani Kaijanaho + + * Java/: part/VersionPart.java, storage/ZZCacheDimSpace.java: + AAARGH + +2001-03-08 Thursday 13:37 Antti-Juhani Kaijanaho + + * Java/: ZZSpacePart.java, part/VersionPart.java, + storage/ZZCacheDimSpace.java: make rest of the triggers work + (hopefully) + +2001-03-08 Thursday 10:50 Antti-Juhani Kaijanaho + + * Java/part/VersionPart.java: Oops + +2001-03-08 Thursday 10:48 Antti-Juhani Kaijanaho + + * Java/part/VersionPart.java: Mostly fix triggering; + rationalization + +2001-03-07 Wednesday 12:57 Antti-Juhani Kaijanaho + + * Java/part/VersionPart.java: hm + +2001-03-07 Wednesday 12:51 Antti-Juhani Kaijanaho + + * Java/: ZZDimSpace.java, part/VersionPart.java: make old-dimension + connections along versioned regular dimensions truly immutable + +2001-03-07 Wednesday 12:06 Antti-Juhani Kaijanaho + + * Java/part/VersionPart.java: simplify the fix + +2001-03-07 Wednesday 12:05 Antti-Juhani Kaijanaho + + * Java/part/VersionPart.java: active-versions dimension + a bugfix + for the versioned regular dims + +2001-03-06 Tuesday 14:22 Antti-Juhani Kaijanaho + + * Makefile: split ChangeLog + +2001-03-06 Tuesday 14:09 Antti-Juhani Kaijanaho + + * changelog-authors: add wikikr to changelog-authors + +2001-03-06 Tuesday 14:05 Antti-Juhani Kaijanaho + + * NEWS: update + +2001-03-06 Tuesday 13:44 Antti-Juhani Kaijanaho + + * NEWS, Java/Main.java, Java/storage/ContentHash.java, + Java/storage/DimHash.java, Java/storage/DirSet.java, + Java/storage/Recs.pl, Java/storage/TestDimHash.java, + Java/storage/WritableHash.java, Java/storage/WritableIS.java, + Java/storage/WritableSet.java, + Java/storage/ZZPersistentDimSpace.java, + Java/storage/ZZPersistentDimension.java, + Java/transform/Convert.java: removing PersistentDimSpace and + associated cruft + +2001-03-06 Tuesday 13:36 Antti-Juhani Kaijanaho + + * cvsparser.pl: oops + +2001-03-06 Tuesday 13:32 Antti-Juhani Kaijanaho + + * cvsparser.pl, cvsparser.pl: fix Manifest making when files are + marked as deleted + +2001-03-05 Monday 14:44 Tuomas J. Lukka + + * Documentation/Manuscripts/Rasters/raster.tex: Name the first + restricted model + +2001-03-05 Monday 14:44 Tuomas J. Lukka + + * Java/exp/rast/vanishing.view: Experimental hypothetical code for + vanishing view in a declarative way + +2001-03-05 Monday 11:01 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/Rasters/: raster.tex, raster.tex: Bah + +2001-03-05 Monday 10:56 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/Rasters/raster.tex: More fixes + +2001-03-05 Monday 10:45 Tuomas J. Lukka + + * Documentation/Manuscripts/Rasters/raster.tex: ? + +2001-03-05 Monday 10:42 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/Rasters/raster.tex: More the same. + +2001-03-05 Monday 10:40 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/Rasters/raster.tex: Improve the LaTeX + +2001-03-05 Monday 10:10 Tuomas J. Lukka + + * Documentation/Manuscripts/Rasters/raster.tex: more + +2001-03-05 Monday 10:03 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/: gzigzag.bib, HyperRFC/Makefile, + HyperRFC/hyp.bib, HyperRFC/hyp.tex: use common bib database + +2001-03-05 Monday 08:44 Tero Mäyränen + + * Modules/multimedia/: MediaFlobView.java, MediaMath.java, + MediaZOb.java, Pixels.java, PolygonRenderer.java, Polygons.java, + adjust.java, crop.java, dots.java, mm.java, move.java, readme.html, + rect.java, sin.java: a couple of new mediazobs + +2001-03-03 Saturday 18:24 Tuomas J. Lukka + + * Documentation/Manuscripts/Rasters/raster.tex: More + +2001-03-03 Saturday 14:59 Tuomas J. Lukka + + * Documentation/Manuscripts/Rasters/raster.tex: More + +2001-03-03 Saturday 14:43 Tuomas J. Lukka + + * Documentation/Manuscripts/Rasters/raster.tex: Grid is wrong name + +2001-03-03 Saturday 13:17 Tuomas J. Lukka + + * Documentation/Manuscripts/Rasters/raster.tex: Some more, and + bugfix + +2001-03-03 Saturday 10:58 Tuomas J. Lukka + + * Documentation/Manuscripts/Rasters/raster.tex: More stuff. Now + actually showing one good example of why rasters and constraints + are important + +2001-03-02 Friday 16:00 Tuomas J. Lukka + + * Documentation/Manuscripts/: RFC2/rfc2.tex, Rasters/raster.tex, + ZZTech/zztech.tex: Rasters doc. More stuff + +2001-03-02 Friday 12:14 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/gzigzag.bib: Forgot Tarjan. + +2001-03-02 Friday 11:57 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/: gzigzag.bib, ZZTech/Makefile, + ZZTech/zztech.tex: references + +2001-03-02 Friday 07:13 Antti-Juhani Kaijanaho + + * Documentation/keybindings.wml: Document the panic button. + +2001-03-02 Friday 06:44 Antti-Juhani Kaijanaho + + * Java/part/VersionPart.java: fix showing old connections along + regular dimensions + +2001-03-02 Friday 06:43 Antti-Juhani Kaijanaho + + * Java/ZZKeyBindings1.java: Fix panic button + +2001-03-02 Friday 00:30 Kimmo Wideroos + + * Modules/awtool/: AwtLink.java, AwtLink.zob, AwtMetrics.java, + AwtMetrics.zob, AwtMetricsFC.java, AwtMetricsFC2.java, + AwtMetricsNormal.java, AwtNote.java, AwtNote.zob, AwtUtil.java, + AwtView1.java, Awtool.java, Awtool.zob, BooleanMesh.java, README, + TODO, ZObCellRepr.java: Adding a new module: A(ssociative) writing + tool a (multilayered) concept map -demo + +2001-03-01 Thursday 13:56 Antti-Juhani Kaijanaho + + * Java/: Main.java, part/VersionPart.java: optionally show old + connections on regular dimensions + +2001-03-01 Thursday 13:53 Antti-Juhani Kaijanaho + + * Java/storage/GZZ0.java: Not writing / writing notifications are + good + +2001-03-01 Thursday 11:48 Antti-Juhani Kaijanaho + + * Java/ZZKeyBindings1.java: add a panic button + +2001-03-01 Thursday 10:21 Antti-Juhani Kaijanaho + + * Java/Makefile: remove multimedia from MODULES, as it requires + java2d + +2001-03-01 Thursday 10:20 Antti-Juhani Kaijanaho + + * Java/Makefile: remove virtualcommunity from MODULES, as it + requires java2d + +2001-03-01 Thursday 09:57 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/ZZTech/zztech.tex: simplify TeX + +2001-03-01 Thursday 09:16 Antti-Juhani Kaijanaho + + * Java/: ZZDimSpace.java, storage/ZZCacheDimSpace.java: fix nextID + problem with -slurping + +2001-02-28 Wednesday 10:34 Tuomas J. Lukka + + * Documentation/Manuscripts/: MsgFoc/msgfoc.tex, ZZTech/zztech.tex: + Fixes + +2001-02-28 Wednesday 10:18 Tuomas J. Lukka + + * Modules/virtualcommunity/: MessageFlobFactory.zob, VCView2.java, + VCView4.java, VirtualCommunity.zob: Final fixes that were done + before morning demo. (I also tweaked the space to have different + parameter sets for view2). Vesa, take a look at this to understand + the flobset hierarchy and how I meant it on the phone. + +2001-02-28 Wednesday 05:16 Tuomas J. Lukka + + * Modules/: multimedia/image.java, + virtualcommunity/MessageFlobFactory.zob, + virtualcommunity/VCView2.java, virtualcommunity/VCView4.java, + virtualcommunity/VirtualCommunity.zob: Fixes + +2001-02-28 Wednesday 04:25 Vesa Parkkinen + + * Java/flob/SceneFlob.java, + Modules/virtualcommunity/MessageFlobFactory.zob, + Modules/virtualcommunity/VCView2.java, + Modules/virtualcommunity/VCView4.java, + Modules/virtualcommunity/VirtualCommunity.zob, + Modules/virtualcommunity/VirtualCommunity.zob: vc work + +2001-02-28 Wednesday 03:14 Tuomas J. Lukka + + * Modules/virtualcommunity/: MessageFlobFactory.zob, VCView2.java, + VirtualCommunity.zob: Rm debuging + +2001-02-28 Wednesday 03:02 Tuomas J. Lukka + + * Modules/: servlet/VCServlet.java, + virtualcommunity/VirtualCommunity.zob: Oops + +2001-02-28 Wednesday 02:16 Tuomas J. Lukka + + * Modules/virtualcommunity/: VCView2.java, VirtualCommunity.zob: + More parametrization + +2001-02-28 Wednesday 02:12 Tuomas J. Lukka + + * Modules/virtualcommunity/VCView2.java: Small twiddles + +2001-02-28 Wednesday 01:43 Tuomas J. Lukka + + * Java/flob/FlobSet.java, Java/flob/SceneFlob.java, + Modules/virtualcommunity/VCView4.java: Select lod for vcview4 + +2001-02-28 Wednesday 01:03 Vesa Parkkinen + + * Modules/virtualcommunity/VCView4.java: more stuff to vc demo + +2001-02-28 Wednesday 01:01 Vesa Parkkinen + + * Modules/virtualcommunity/: VCView2.java, VCView4.java, + VirtualCommunity.zob: some stuff to vc demo + +2001-02-28 Wednesday 00:46 Tuomas J. Lukka + + * Java/arch/java2d/ZZDrawingJ2D.java, Java/flob/FlobSet.java, + Java/flob/SceneFlob.java, + Modules/virtualcommunity/MessageFlobFactory.zob, + Modules/virtualcommunity/VirtualCommunity.zob: Whew. Selective + level-of-detail animation + +2001-02-27 Tuesday 23:55 Tuomas J. Lukka + + * Modules/: multimedia/image.java, + virtualcommunity/MessageFlobFactory.zob: Take tailer hack out. This + needs to be done right. + +2001-02-27 Tuesday 23:49 Vesa Parkkinen + + * Modules/virtualcommunity/: MessageFlobFactory.zob, VCView1.java, + VCView2.java, VCView4.java, VirtualCommunity.zob: added products + +2001-02-27 Tuesday 23:32 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/ZZTech/zztech.tex: explained a bit what + this paper is in the comments; moved beja's comment away from the + margin, it did not fit there + +2001-02-27 Tuesday 23:18 Tuomas J. Lukka + + * Documentation/Manuscripts/MsgFoc/msgfoc.tex: Write down a thought + +2001-02-27 Tuesday 22:57 Tuomas J. Lukka + + * Modules/virtualcommunity/: VCView4.java, VirtualCommunity.zob: + vcview 4 + +2001-02-27 Tuesday 21:53 Tuomas J. Lukka + + * Modules/virtualcommunity/VCView2.java: Fix vc2 when two children + +2001-02-27 Tuesday 21:12 Benjamin Fallenstein + + * Documentation/Manuscripts/ZZTech/zztech.tex: comment on + versioning (I hope the TeX code is correct, I've never used TeX) + +2001-02-27 Tuesday 21:08 Tuomas J. Lukka + + * Modules/virtualcommunity/: VCView2.java, VirtualCommunity.zob: + More depth + +2001-02-27 Tuesday 20:45 Tuomas J. Lukka + + * Modules/virtualcommunity/VirtualCommunity.zob: Without rotation + :( + +2001-02-27 Tuesday 20:39 Tuomas J. Lukka + + * Modules/virtualcommunity/: MessageFlobFactory.zob, VCView2.java, + VirtualCommunity.zob: Text doing a little different + +2001-02-27 Tuesday 20:31 Tuomas J. Lukka + + * Modules/virtualcommunity/MessageFlobFactory.zob: Now leave out if + center outside screen. Too much, but faster + +2001-02-27 Tuesday 20:26 Tuomas J. Lukka + + * Modules/virtualcommunity/: VCView2.java, VirtualCommunity.zob: + lisaa + +2001-02-27 Tuesday 20:04 Antti-Juhani Kaijanaho + + * Java/storage/GZZ0.java: add id to ZZFatalError + +2001-02-27 Tuesday 20:03 Vesa Parkkinen + + * Modules/virtualcommunity/VirtualCommunity.zob: added vcview3 + +2001-02-27 Tuesday 20:02 Antti-Juhani Kaijanaho + + * Java/storage/CountingStream.java: Fix. + +2001-02-27 Tuesday 20:02 Vesa Parkkinen + + * Modules/virtualcommunity/VCView3.java: added + +2001-02-27 Tuesday 20:00 Tuomas J. Lukka + + * Java/storage/CountingStream.java: ARGH + +2001-02-27 Tuesday 19:57 Tuomas J. Lukka + + * Java/storage/GZZ0.java: Countingstream + appl + +2001-02-27 Tuesday 19:12 Tuomas J. Lukka + + * Modules/virtualcommunity/: VCView2.java, VirtualCommunity.zob: + Temporary: don't render out-of-sight msgflobs. But have to do this + in a different place in reality + +2001-02-27 Tuesday 17:12 Tuomas J. Lukka + + * Modules/virtualcommunity/VCView2.java: Better view2 + +2001-02-27 Tuesday 16:27 Rauli Ruohonen + + * Modules/virtualcommunity/MessageFlobFactory.zob: Removed the red + letters. + +2001-02-27 Tuesday 16:19 Tuomas J. Lukka + + * Modules/virtualcommunity/VCView2.java: getHeight testing + +2001-02-27 Tuesday 16:12 Rauli Ruohonen + + * Modules/virtualcommunity/MessageFlobFactory.zob: Bugfixes. + +2001-02-27 Tuesday 16:02 Tuomas J. Lukka + + * Modules/virtualcommunity/VCView2.java: Better + +2001-02-27 Tuesday 15:43 Rauli Ruohonen + + * Modules/virtualcommunity/MessageFlobFactory.zob: Bugfix. + +2001-02-27 Tuesday 15:35 Tuomas J. Lukka + + * Modules/virtualcommunity/VCView2.java: Parempi + +2001-02-27 Tuesday 15:34 Tuomas J. Lukka + + * Modules/virtualcommunity/: VCView2.java, VirtualCommunity.zob: + View2 primitively works + +2001-02-27 Tuesday 15:15 Rauli Ruohonen + + * Modules/virtualcommunity/: MessageFlobFactory.zob, + VirtualCommunity.zob: In the middle of a bugfix to getHeight() in + MFF. + +2001-02-27 Tuesday 14:35 Tuomas J. Lukka + + * Modules/virtualcommunity/VCView2.java: Ups + +2001-02-27 Tuesday 14:10 Rauli Ruohonen + + * Modules/virtualcommunity/MessageFlobFactory.zob: Fixes. + +2001-02-27 Tuesday 14:06 Tuomas J. Lukka + + * Modules/virtualcommunity/: MessageFlobFactory.zob, VCView1.java, + VCView2.java, VirtualCommunity.zob: Second view. Some small + twiddles elsewhere + +2001-02-27 Tuesday 13:40 Rauli Ruohonen + + * Modules/virtualcommunity/: MessageFlobFactory.zob, VCView1.java, + VirtualCommunity.zob: Text animation intermediate commit. + +2001-02-27 Tuesday 13:02 Rauli Ruohonen + + * Modules/virtualcommunity/MessageFlobFactory.zob: Coloring stuff + to VC + +2001-02-27 Tuesday 12:29 Rauli Ruohonen + + * Modules/virtualcommunity/MessageFlobFactory.zob: Antialiasing + outline during animation. (VC) + +2001-02-27 Tuesday 12:10 Rauli Ruohonen + + * Java/arch/java2d/ZZDrawingJ2D.java, + Modules/virtualcommunity/MessageFlobFactory.zob: Added use of + "VALUE_RENDER_SPEED" to ZZDJ2D, and a getSize() cache to MFF. + +2001-02-27 Tuesday 11:48 Rauli Ruohonen + + * Modules/virtualcommunity/MessageFlobFactory.zob: More height + stuff to VC. + +2001-02-27 Tuesday 11:35 Rauli Ruohonen + + * Modules/virtualcommunity/MessageFlobFactory.zob: + MessageFlobFactory: Calculation of height stuff. + +2001-02-27 Tuesday 10:55 Tuomas J. Lukka + + * Java/arch/java2d/ZZDrawingJ2D.java, + Modules/virtualcommunity/VCView1.java, + Modules/virtualcommunity/VirtualCommunity.zob: Move material around + - now easy to make new vc views + +2001-02-27 Tuesday 10:43 Rauli Ruohonen + + * Modules/virtualcommunity/MessageFlobFactory.zob: Removed + subj/auth drawing from animation. + +2001-02-27 Tuesday 08:42 Rauli Ruohonen + + * Java/ZZDrawing.java, Java/arch/java2d/ZZDrawingJ2D.java, + Modules/multimedia/MediaFlobFactory.java, + Modules/virtualcommunity/MessageFlobFactory.zob: Enabled image + drawing only when qualityEnabled(). + +2001-02-27 Tuesday 08:36 Rauli Ruohonen + + * Java/ZZCanvasView.java, Java/ZZDrawing.java, + Java/ZZUpdateManager.java, Java/arch/java2d/ZZDrawingJ2D.java, + Modules/virtualcommunity/MessageFlobFactory.zob: Cleaned up "draw + last frame twice" - now it does it once w/ setQuality() disabled + and right afterwards with it enabled. Commented out most of the + disables from VC demo. (but it still renders text too slowly) + +2001-02-27 Tuesday 06:14 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/ZZTech/zztech.tex: Some ideas. + +2001-02-26 Monday 21:21 Tuomas J. Lukka + + * Java/arch/java2d/ZZDrawingJ2D.java, + Modules/virtualcommunity/MessageFlobFactory.zob, + Modules/virtualcommunity/VirtualCommunity.zob: Fix rotated flob + interpolation. Messageflobs must always be rotatedflobs but we + needn't rotate unless rotated (clear?) + +2001-02-26 Monday 20:48 Rauli Ruohonen + + * Modules/virtualcommunity/: MessageFlobFactory.zob, + VirtualCommunity.zob: Committed rotation changes to VC. + +2001-02-26 Monday 20:00 Rauli Ruohonen + + * Java/ZZCanvasView.java, Java/ZZUpdateManager.java, + Modules/virtualcommunity/MessageFlobFactory.zob: Added back text + display in VC. Added renderInterp() call at 1.0 frames. + +2001-02-26 Monday 19:45 Rauli Ruohonen + + * Modules/: multimedia/MediaFlobFactory.java, + virtualcommunity/MessageFlobFactory.zob: Stripped down displaying + of almost everything from VC demo to get speed. (will be added + back later) + +2001-02-26 Monday 18:42 Rauli Ruohonen + + * Java/arch/java2d/ZZDrawingJ2D.java, + Modules/multimedia/MediaFlobFactory.java: Mod:ed the kludge a bit. + +2001-02-26 Monday 18:29 Rauli Ruohonen + + * Java/arch/java2d/ZZDrawingJ2D.java, + Modules/multimedia/MediaFlobFactory.java: Added a kludge to disable + antialiasing during image drawing + +2001-02-26 Monday 18:14 Tuomas J. Lukka + + * Java/arch/java2d/ZZDrawingJ2D.java: Doc + +2001-02-26 Monday 18:12 Tuomas J. Lukka + + * Java/arch/java2d/ZZDrawingJ2D.java: Fix rotation interpolation: + center was wrong + +2001-02-26 Monday 18:03 Rauli Ruohonen + + * Java/arch/java2d/ZZDrawingJ2D.java, Java/flob/CellBgFlob.java, + Java/flob/SplitCellFlob1.java, + Modules/virtualcommunity/MessageFlobFactory.zob: Removed some + clipping + added a quality hint (J2D). + +2001-02-26 Monday 16:40 Rauli Ruohonen + + * Java/arch/java2d/ZZDrawingJ2D.java, + Modules/virtualcommunity/MessageFlobFactory.zob: Fixed a bug in J2D + (AffineTransform w/ wrong anchor point) and VirtualCommunity + (clicking "Author" no longer does anything + all clipping is + removed [this part is not a bugfix, but a bugintroduction :-)]). + +2001-02-26 Monday 16:03 Rauli Ruohonen + + * Java/arch/java2d/ZZDrawingJ2D.java, + Modules/multimedia/MediaFlobFactory.java, + Modules/virtualcommunity/MessageFlobFactory.zob: Bugfixes. Demo + does rotation. (but doesn't work w/o java2d for now) + +2001-02-26 Monday 15:43 Tero Mäyränen + + * Modules/multimedia/: MediaZOb.java, readme.html: Added macrostuff + +2001-02-26 Monday 15:41 Rauli Ruohonen + + * Java/Makefile, Java/flob/FlobSet.java, + Modules/multimedia/MediaFlobFactory.java, + Modules/virtualcommunity/MessageFlobFactory.zob: Fixed some + breakages of the last commit. Broke MessageFlobFactory. + +2001-02-26 Monday 14:57 Rauli Ruohonen + + * Java/ZZDimSpace.java, Java/ZZObsTrigger.java, + Java/ZZViewComponent.java, Java/flob/FlobSet.java, + Java/media/FText.java, Modules/multimedia/MediaFlobFactory.java, + Modules/multimedia/MediaZOb.java, Modules/multimedia/image.java, + Modules/virtualcommunity/MessageFlobFactory.zob, + Modules/virtualcommunity/VirtualCommunity.zob: Made the + virtualcommunity demo cuter; fixed bugs in multimedia module, + ZZDimSpace, FlobSet, FText, worked around a JVM implementation one + in ZZViewComponent. + +2001-02-26 Monday 14:55 Tuomas J. Lukka + + * Java/arch/java2d/ZZDrawingJ2D.java: Oops, we want center, not + origin rotation + +2001-02-26 Monday 14:53 Tuomas J. Lukka + + * Java/: arch/java2d/ZZDrawingJ2D.java, flob/SceneFlob.java: + Untested rotated subflobset code. + +2001-02-26 Monday 14:43 Tuomas J. Lukka + + * Java/flob/SceneFlob.java: Sceneflob more + +2001-02-26 Monday 14:29 Tuomas J. Lukka + + * Java/flob/SceneFlob.java: New flob type that can contain other + flobs. You may have guessed - this is for rotation. + +2001-02-26 Monday 14:08 Tuomas J. Lukka + + * Documentation/Manuscripts/ZZTech/zztech.tex: some items + +2001-02-26 Monday 14:04 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/ZZTech/zztech.tex: *Very* minimal + structure. + +2001-02-26 Monday 13:16 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/ZZTech/zztech.tex: tweak + +2001-02-26 Monday 13:10 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/ZZTech/zztech.tex: initial rev + +2001-02-26 Monday 12:58 Tuomas J. Lukka + + * Documentation/Manuscripts/RFC2/rfc2.tex: Start + +2001-02-26 Monday 12:36 Tuomas J. Lukka + + * Documentation/Manuscripts/MsgFoc/msgfoc.tex: Some fixes + +2001-02-26 Monday 10:29 Tuomas J. Lukka + + * Documentation/Manuscripts/MsgFoc/msgfoc.tex: Outline. Please read + and comment + +2001-02-26 Monday 10:13 Antti-Juhani Kaijanaho + + * Java/part/VersionPart.java: version:list->version:active, add + benja's version:list + +2001-02-26 Monday 10:11 Tuomas J. Lukka + + * Documentation/Manuscripts/MsgFoc/msgfoc.tex: Fix + +2001-02-26 Monday 08:23 Tuomas J. Lukka + + * Modules/virtualcommunity/MessageFlobFactory.zob: Add vile java + mode + +2001-02-24 Saturday 08:55 Tero Mäyränen + + * Modules/multimedia/: ImageSource.java, flobcolors.java, + text.java: This commit will hopefully remove some old files. + +2001-02-23 Friday 15:01 Tuomas J. Lukka + + * Java/Makefile: Remove multimedia from main makefile as it's + broken. + +2001-02-23 Friday 15:01 Tuomas J. Lukka + + * Java/media/TestLines.java: Remove 8-bit char string --- jikes + didn't like ISO-Latin1. + +2001-02-23 Friday 13:57 Benjamin Fallenstein + + * Java/part/VersionPart.java: A little interface enhancement: the + dimension version:d.xxx shows the connections of a cell along d.xxx + no matter which version it is from (only works for dimensions + prefixed by 'd.') + +2001-02-23 Friday 13:47 Antti-Juhani Kaijanaho + + * Java/part/VersionPart.java: Heavy commenting and documenting. + +2001-02-23 Friday 12:20 Benjamin Fallenstein + + * Java/: ZZSpace.java, part/VersionPart.java: Fix to compile with + javac: No static members in inner classes; and error messages that + ZZSpace.readonly isn't initialized in the constructors. I can't + explain that latter one, but to compile I've just un-finalized + readonly. Someone who understands these matters better please look + into it and find a clean solution. + +2001-02-23 Friday 08:33 Antti-Juhani Kaijanaho + + * Java/: ZZCellHandle.java, ZZDefaultSpace.java, ZZDimSpace.java, + ZZSpace.java, ZZSpacePart.java, storage/ZZCacheDimSpace.java, + storage/ZZCacheDimension.java, storage/ZZPersistentDimSpace.java, + part/VersionPart.java: accessing past versions works now + +2001-02-22 Thursday 16:26 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/MsgFoc/msgfoc.tex: Fix. + +2001-02-22 Thursday 16:26 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/MsgFoc/msgfoc.tex: Modernize the LaTeX + a little :-) + +2001-02-22 Thursday 16:16 Tuomas J. Lukka + + * Documentation/Manuscripts/MsgFoc/msgfoc.tex: Outline next article + +2001-02-22 Thursday 15:46 Tuomas J. Lukka + + * Java/: ZZDrawing.java, arch/java2d/ZZDrawingJ2D.java, + flob/FlobSet.java: Try rotation under 1.3. This code needs to be + disabled (made to check for e.g. a Java property on whether to + activate) before release... + +2001-02-22 Thursday 15:31 Tero Mäyränen + + * Modules/multimedia/: Default.java, MediaFlobFactory.java, + MediaZOb.java, Pixels.java, crop.java, dots.java, image.java, + mm.java, move.java, next.java, rect.java: A complete rewrite. + +2001-02-22 Thursday 15:27 Tuomas J. Lukka + + * Java/Main.java: Fix 1.3 ambiguity + +2001-02-22 Thursday 12:23 Antti-Juhani Kaijanaho + + * CODING: p and pa protected + +2001-02-21 Wednesday 06:11 Antti-Juhani Kaijanaho + + * Java/storage/ZZCacheDimSpace.java: dbg should not be final. + +2001-02-20 Tuesday 11:32 Antti-Juhani Kaijanaho + + * Java/: SpaceDump.java, ZZDimSpace.java: slurp works now + +2001-02-19 Monday 12:52 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: More text + +2001-02-19 Monday 12:50 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Transpoint + +2001-02-19 Monday 12:50 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/: utopia.mp, utopiapara.tex: + Added clipping. + +2001-02-19 Monday 12:47 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/utopia.mp: Make connections + look more reasonable + +2001-02-19 Monday 12:44 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.bib: another fix + +2001-02-19 Monday 12:38 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/utopia.mp: Lines. (incredibly + stupid-looking) + +2001-02-19 Monday 12:37 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/: hyp.bib, hyp.tex: parallel + windows mockup + +2001-02-19 Monday 12:00 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/utopia.mp: Mods. + +2001-02-19 Monday 11:48 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/utopia.mp: Fix putitrot + +2001-02-19 Monday 11:38 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/utopia.mp: Still more buggy. + +2001-02-19 Monday 11:04 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/: utopia.mp, utopiapara.tex: + Buggy version for Tuomas. + +2001-02-19 Monday 09:57 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/utopia.mp: Rotatoin. + +2001-02-19 Monday 09:48 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/utopiapara.tex: A different + idea. + +2001-02-19 Monday 09:36 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/utopiapara.tex: Mods. + +2001-02-19 Monday 08:54 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/: utopia.mp, utopiapara.tex: + First draft of the left side. + +2001-02-19 Monday 08:40 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Fix + +2001-02-19 Monday 08:39 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Fix an overfull box. + +2001-02-19 Monday 08:00 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/utopiapara.tex: Oops. + +2001-02-19 Monday 07:54 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/: utopia.mp, utopiapara.tex: + Improvements to the fig. + +2001-02-19 Monday 07:51 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Fix + +2001-02-19 Monday 07:48 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Fixes based on + Janne's comments. + +2001-02-19 Monday 07:45 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Fix abstract again ;) + +2001-02-19 Monday 07:42 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Fix some abstract. + +2001-02-19 Monday 07:40 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Fix quote formatting + +2001-02-19 Monday 07:37 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Small fixes. + +2001-02-19 Monday 06:37 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.bib: Fix some underfull + boxen. + +2001-02-19 Monday 06:27 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Fix one more overfull + box + +2001-02-19 Monday 06:25 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: typos + +2001-02-19 Monday 06:24 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Deal with overfull + hboxen + +2001-02-19 Monday 06:02 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Updated a fig caption + +2001-02-19 Monday 05:55 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Typoes + +2001-02-19 Monday 05:49 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Typo + +2001-02-19 Monday 05:06 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Make figures slightly + smaller + +2001-02-19 Monday 04:48 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: utopia.mp, utopiapara.tex: + Raulin muutoksia + +2001-02-19 Monday 04:25 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Lisaa... + +2001-02-19 Monday 03:43 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Another low-level + editing round + +2001-02-19 Monday 02:56 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Ok, now all text has + been gone through at least once today. + +2001-02-19 Monday 02:16 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: Makefile, hyp.bib, hyp.tex, + utopiapara.tex: Here's how to alter parwidth... Not pretty but it + works. + +2001-02-19 Monday 02:05 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: hyp.tex, utopia.mp, + utopiapara.tex: Changes. + +2001-02-19 Monday 00:47 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Rm old comments + +2001-02-19 Monday 00:21 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: hyp.tex, hyp.tex: More + low-level editing. + +2001-02-19 Monday 00:00 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Procedural -> + presentational + +2001-02-18 Sunday 23:59 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Edit little + +2001-02-18 Sunday 23:49 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: More editing. + +2001-02-18 Sunday 23:32 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: More work + +2001-02-18 Sunday 23:11 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Work on RFC intro + +2001-02-18 Sunday 23:06 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/: hyp.bib, hyp.tex: fix some + references + +2001-02-18 Sunday 22:49 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/: hyp.bib, hyp.tex: some ZZ + references + +2001-02-18 Sunday 22:40 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/utopiapara.tex: Fix spacing + +2001-02-18 Sunday 21:48 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.bib: Remove XXX to make + such references more obvious. + +2001-02-18 Sunday 21:46 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Emails + +2001-02-18 Sunday 21:43 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Comments, fixes + +2001-02-18 Sunday 21:08 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Fixes. + +2001-02-18 Sunday 21:00 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/utopiapara.tex: A complete + yuck(tm)-solution + +2001-02-18 Sunday 20:58 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/utopiapara.tex: Some fixes to + metapost. Table still doesn't work... + +2001-02-18 Sunday 20:39 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/: utopia.mp, utopiapara.tex: + [no log message] + +2001-02-18 Sunday 20:22 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Conclude more + +2001-02-18 Sunday 20:05 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: hyp.tex, utopiapara.tex: Fix + mp font + +2001-02-18 Sunday 20:01 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Start conclusions + +2001-02-18 Sunday 20:00 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/: utopia.mp, utopiapara.tex: + Diagram changes. + +2001-02-18 Sunday 19:57 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.bib: More fixing. + +2001-02-18 Sunday 19:52 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/: hyp.bib, hyp.tex: fix the + urls in bibtex db + +2001-02-18 Sunday 19:47 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Move relwork again + +2001-02-18 Sunday 19:31 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: More edits on + otherwork-refer + +2001-02-18 Sunday 19:19 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Move hyperdocuments + in f+c to different place + +2001-02-18 Sunday 19:07 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Rmcrud + +2001-02-18 Sunday 18:24 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: utopia.mp, utopiapara.tex: + Add more stuff to utopia + +2001-02-18 Sunday 18:10 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: Makefile, diagram.mp, + hyp.tex, utopia.mp, utopiapara.tex: Start utopia image. Not very + utopistic yet... + +2001-02-18 Sunday 17:33 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Related-material + addition to the HTML section. + +2001-02-18 Sunday 17:01 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.bib: Hyphens to {} - don't + work + +2001-02-18 Sunday 16:59 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyperimg.txt: Added + description for the "real" picture. It is incomplet and probably + incorrekt. + +2001-02-18 Sunday 16:57 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: hyp.bib, hyp.tex: Twid with + ref + +2001-02-18 Sunday 16:35 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: RFC talk + +2001-02-18 Sunday 16:29 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: rmcrud + +2001-02-18 Sunday 16:28 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Small improvements + +2001-02-18 Sunday 16:24 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Edits + +2001-02-18 Sunday 16:19 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Twid + +2001-02-18 Sunday 16:13 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: hyp.bib, hyp.tex: Bib fix, + Kata didn't want to go on + +2001-02-18 Sunday 16:04 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: LOTS of reorg and rm + crud. Getting there + +2001-02-18 Sunday 15:57 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Move quote + +2001-02-18 Sunday 15:52 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Edit + +2001-02-18 Sunday 15:50 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Separate vr into its + own section --- possibly good + +2001-02-18 Sunday 15:47 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Add nakki + +2001-02-18 Sunday 15:42 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Move figure + +2001-02-18 Sunday 15:40 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: Makefile, hyp.bib, hyp.tex: + Refer to XLink (IMPORTANT) + +2001-02-18 Sunday 15:20 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Move markup again + +2001-02-18 Sunday 15:19 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: [no log message] + +2001-02-18 Sunday 14:31 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Comment. + +2001-02-18 Sunday 14:29 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Oops. + +2001-02-18 Sunday 14:27 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Moved Vesa's figure + and added some text to SI: F+C. + +2001-02-18 Sunday 13:56 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: [no log message] + +2001-02-18 Sunday 13:52 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: rm crud2 + +2001-02-18 Sunday 13:51 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: rm crud + +2001-02-18 Sunday 13:47 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: More + +2001-02-18 Sunday 13:45 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Some changes. (Really + informational, isn't it?) + +2001-02-18 Sunday 13:44 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Oops + +2001-02-18 Sunday 13:43 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Move markup section + +2001-02-18 Sunday 13:36 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Introon yksi kappale + - miettikaa + +2001-02-18 Sunday 13:33 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: hyp.bib, hyp.tex: Nakki + + sect.nimi + oikea viite Coombsiin + +2001-02-18 Sunday 13:22 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Reword + +2001-02-18 Sunday 13:20 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Remove comment + +2001-02-18 Sunday 13:10 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Convert caption, more + float work + +2001-02-18 Sunday 11:49 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: [no log message] + +2001-02-18 Sunday 11:45 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: hyp.bib, hyp.tex: Add a + rewritten version of Kimmo's thought. This could be the way to + explain our thinking... + +2001-02-18 Sunday 07:14 Vesa Parkkinen + + * Documentation/Manuscripts/HyperRFC/: hyp.bib, hyp.tex: stuff + +2001-02-17 Saturday 22:44 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: Makefile, hyp.tex, hypf.tex: + Make it possible to simultaneously have both draft and non-draft + version (hypf). Fix a bit of wording, note some more oddities + +2001-02-17 Saturday 21:55 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Work on htmlification + +2001-02-17 Saturday 19:48 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Remove redundant + comments + +2001-02-17 Saturday 19:47 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Improve caption, + refer to figure in right place + +2001-02-17 Saturday 19:42 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Comments bigger again + - there are less of them. Remove commented-out parts we will not be + using. + +2001-02-17 Saturday 18:33 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Replaced not-so-good + text with possibly bad text. + +2001-02-17 Saturday 18:09 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: /me puts the wiener + back on the table, uneaten. + +2001-02-17 Saturday 17:52 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Eating one of the + wieners + +2001-02-17 Saturday 17:47 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.bib: Finetune the BibTeX + database (accents & capitals, oh my) + +2001-02-17 Saturday 16:21 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Foo. + +2001-02-17 Saturday 16:03 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Nakki + +2001-02-17 Saturday 15:51 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: hyp.bib, hyp.tex: Add Ted's + quote + +2001-02-17 Saturday 15:49 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: F+C stuff. + +2001-02-17 Saturday 15:30 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Kata's new abstract + +2001-02-17 Saturday 15:30 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Rearrangement. + +2001-02-17 Saturday 15:20 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: diagram.mp, hyp.tex: enlarge + font in diagrams + +2001-02-17 Saturday 15:08 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Remove references to + syntax descriptions, as we don't have time to do that properly + +2001-02-17 Saturday 15:02 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Title and comment + updates + +2001-02-17 Saturday 14:47 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Remove redundant + figure + +2001-02-17 Saturday 14:43 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: More f+c work, it's + getting better. Also added a Q to Tuomas. + +2001-02-17 Saturday 14:39 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Improved floats. + +2001-02-17 Saturday 13:59 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/: HTML-RFC-index.ps, hyp.tex: + Added paper frames to index pic. + +2001-02-17 Saturday 13:56 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Some work on f+c, not + finished yet + +2001-02-17 Saturday 13:51 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: More work on + htmlification. Now settling... + +2001-02-17 Saturday 13:41 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Fix final version + build. + +2001-02-17 Saturday 13:26 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/Makefile: Add PDF generation + (could work better with pdflatex but the images don't work with + it.) + +2001-02-17 Saturday 13:19 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Make figures flow in + non-draft version + +2001-02-17 Saturday 13:13 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/: HTML-RFC-index.ps, hyp.tex: + Pic stuff. + +2001-02-17 Saturday 13:06 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Twid + +2001-02-17 Saturday 13:05 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: rm crud + +2001-02-17 Saturday 13:01 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: More work on + htmlification + +2001-02-17 Saturday 12:55 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Change wiener + +2001-02-17 Saturday 12:54 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Move figures, write + more about HTMLification + +2001-02-17 Saturday 12:30 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: hyp.bib, hyp.tex: Fix figure + captions, add Kimmo's reference + +2001-02-17 Saturday 12:25 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Fixed pic size. + +2001-02-17 Saturday 12:11 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Move figures + +2001-02-17 Saturday 12:08 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Oops + +2001-02-17 Saturday 12:06 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: Makefile, hyp.tex: Add + Vesa's diagrams to the text. Needs work. + +2001-02-17 Saturday 12:02 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: hyp.bib, hyp.tex: Small + beginnings of a better htmlrfc section + +2001-02-17 Saturday 11:59 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/: HTML-RFC.ps, demo1.css, + demo1.ps, demo2.css, demo2.ps, demo3.css, demo3.ps, demo4.css, + demo4.ps, hyp.tex: Added some pics. + +2001-02-17 Saturday 11:55 Vesa Parkkinen + + * Documentation/Manuscripts/HyperRFC/diagram.mp: added diarams + +2001-02-17 Saturday 11:43 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/Makefile: Add hyp.ps to + targets + +2001-02-17 Saturday 09:07 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Nakki... + +2001-02-17 Saturday 08:05 Vesa Parkkinen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: added a quick comment + +2001-02-16 Friday 20:35 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Make the comments + smaller and restore old title + +2001-02-16 Friday 16:36 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: comments + +2001-02-16 Friday 16:22 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Comments. + +2001-02-16 Friday 15:58 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Commented out + \includegraphics, since the ps files aren't ready yet. + +2001-02-16 Friday 15:45 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/: demo1.css, demo3.css, + hyp.tex, rfc1034.html: Comments. + +2001-02-16 Friday 15:41 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Remove old wiener + +2001-02-16 Friday 15:33 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Comment on f+c + +2001-02-16 Friday 15:15 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Remove, as it doesn't + say anything useful. If we want, we can mention the xanadu + annotations etc. elsewhere + +2001-02-16 Friday 15:13 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Nakki Vesalle!!! + +2001-02-16 Friday 15:07 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Shaping up... + +2001-02-16 Friday 14:19 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Uusi nakki, + kommentteja + +2001-02-16 Friday 14:14 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.bib: Fix Ted's name. + +2001-02-16 Friday 14:13 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/: hyp.bib, hyp.tex: focus and + context first attempt + +2001-02-16 Friday 14:07 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: More work. Shaping + up. + +2001-02-16 Friday 13:55 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: hyp.tex, hyp.tex: More 2disp + work + +2001-02-16 Friday 13:52 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Add a wiener + +2001-02-16 Friday 13:42 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.bib: Added HTML spec. + +2001-02-16 Friday 13:25 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Some more transfer + +2001-02-16 Friday 13:06 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: More transfer... + +2001-02-16 Friday 12:59 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Some work on transfer + +2001-02-16 Friday 12:36 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Small twiddle in + transfer... + +2001-02-16 Friday 12:17 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.bib: Forgot to commit, + aargh (RFC index et al) + +2001-02-16 Friday 12:07 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Figures. + +2001-02-16 Friday 11:46 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Add ack + +2001-02-16 Friday 10:48 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Small twiddle + +2001-02-16 Friday 10:43 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Remove obsolete + comments + +2001-02-16 Friday 10:41 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: move comments + +2001-02-16 Friday 10:03 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Start about + region-to-region links: it's a property of our current problem, the + RFCs. + +2001-02-16 Friday 10:01 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Heading + +2001-02-16 Friday 10:00 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Reorg + +2001-02-16 Friday 09:56 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Clarify stage + +2001-02-16 Friday 08:09 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Better addressing. + +2001-02-16 Friday 08:08 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Comments & fixes. + +2001-02-16 Friday 07:50 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: A frankfurter done. + +2001-02-16 Friday 06:36 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.bib: Further fixing of + bibtex db + +2001-02-16 Friday 06:33 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/: hyp.bib, hyp.tex: added + affiliation address + +2001-02-16 Friday 05:43 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.bib: Comment on the RFCs + and fix the months. + +2001-02-15 Thursday 23:12 Vesa Parkkinen + + * Documentation/Manuscripts/HyperRFC/: hyp.bib, hyp.tex: little + fixes + +2001-02-15 Thursday 22:48 Vesa Parkkinen + + * Documentation/Manuscripts/HyperRFC/: hyp.bib, hyp.tex: lisätty + ranskalaisia nakkien seuraksi. + +2001-02-15 Thursday 22:06 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Some more stuff. + PLEASE read and help fix the new section and structure + +2001-02-15 Thursday 21:51 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Move trouble into + transfer section + +2001-02-15 Thursday 21:33 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Move examples, start + editing problems section + +2001-02-15 Thursday 16:18 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: More rearrangement + +2001-02-15 Thursday 16:10 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Another batch of + comments. + +2001-02-15 Thursday 16:07 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Ok + +2001-02-15 Thursday 16:06 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Rearrange a bit + +2001-02-15 Thursday 16:00 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Comment. + +2001-02-15 Thursday 16:00 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Make non-draft really + work. Remove XXX ordering from authorname -- now it fits but only + barely. We have to order the authors later. Add new section. + +2001-02-15 Thursday 15:52 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Comments & remove the + old thebibliography environment. + +2001-02-15 Thursday 15:21 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/: demo1.css, demo2.css, + demo3.css, demo4.css, rfc1034.html, rfcgen.sh: HTML f+c / non-f+c + stuff. + +2001-02-15 Thursday 14:58 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Clean up intro a + little bit + +2001-02-15 Thursday 14:57 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Make non-draft work + again. We're up to 5 pages without figures. Also, add clarifying + lines before sections in the source + +2001-02-15 Thursday 14:53 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Fiddle with abstract + +2001-02-15 Thursday 14:44 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Oops... + +2001-02-15 Thursday 14:42 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: New abstract. I'm + beginning to feel really good about this: Finally we are getting to + our real MESSAGE. + +2001-02-15 Thursday 14:25 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Mods. + +2001-02-15 Thursday 14:16 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: bah + +2001-02-15 Thursday 14:02 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: demo1.css, hyp.tex, + rfc1034.html: Add css for the html demo + +2001-02-15 Thursday 13:34 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Remove the silly + notice + +2001-02-15 Thursday 13:33 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Add RCS id + +2001-02-15 Thursday 13:28 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Refer to hyperbolic + stuff for animation + +2001-02-15 Thursday 13:25 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Small fix + +2001-02-15 Thursday 13:23 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: 1 nakki lisaa + +2001-02-15 Thursday 13:10 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: 1 nakki tehty + +2001-02-15 Thursday 12:49 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Nakkeja + +2001-02-15 Thursday 12:41 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/rfc1034.html: [no log message] + +2001-02-15 Thursday 12:39 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Nakki + +2001-02-15 Thursday 11:53 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: answer + +2001-02-15 Thursday 11:48 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Comment + +2001-02-15 Thursday 11:32 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.bib: fix a cite + +2001-02-15 Thursday 11:28 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: make better one rfc + para + +2001-02-15 Thursday 09:55 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Real hyperstructure + -> actual hyperstructure + +2001-02-15 Thursday 09:53 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Fix intuitivity + +2001-02-15 Thursday 09:45 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/Makefile: added a clean target + +2001-02-15 Thursday 09:38 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/Makefile: a makefile to + automate the processing + +2001-02-15 Thursday 09:33 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: jvk's comments + +2001-02-15 Thursday 06:57 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/: hyp.bib, hyp.tex: bibtexify + +2001-02-15 Thursday 05:45 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: a comment + +2001-02-14 Wednesday 21:53 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Add comments, edit a + little + +2001-02-14 Wednesday 19:59 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: More. + +2001-02-14 Wednesday 19:57 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Some small + improvements on the RFC section. + +2001-02-14 Wednesday 19:49 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: A fully rewritten RFC + intro section and couple of small nitpicks. + +2001-02-14 Wednesday 16:47 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Remove old comments + +2001-02-14 Wednesday 16:18 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Fix a typograpghic + mistake. + +2001-02-14 Wednesday 15:15 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Little + +2001-02-14 Wednesday 14:38 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Move closer to + acm-required format + +2001-02-14 Wednesday 14:21 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Move co-operative + stuff + +2001-02-14 Wednesday 14:12 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: move a comment + +2001-02-14 Wednesday 14:11 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: A bit on the virutal + paper stuff + +2001-02-14 Wednesday 14:04 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Fix typo, rearrange + something, make possible to typeset in draft mode (with marginal + notes) and final mode. + +2001-02-14 Wednesday 13:59 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Reorg + +2001-02-14 Wednesday 13:56 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: my name & dept name + +2001-02-14 Wednesday 13:09 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Small fixes + +2001-02-14 Wednesday 12:57 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Small + +2001-02-14 Wednesday 12:37 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Foo. + +2001-02-14 Wednesday 12:03 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: cat->tjl + +2001-02-14 Wednesday 11:43 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Some answers. I'll + start modifying later. + +2001-02-14 Wednesday 09:50 Rauli Ruohonen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Blaa. + +2001-02-14 Wednesday 09:40 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: fix some typesetting + mistakes + +2001-02-14 Wednesday 08:53 Antti-Juhani Kaijanaho + + * Java/Main.java, Java/SpaceDump.java, Java/ZTPCommand.java, + Modules/ztp/client/Response.java, Modules/ztp/client/Session.java, + Modules/ztp/common/Command.java, + Modules/ztp/common/SubspaceDump.java, + Modules/ztp/server/Session.java: dump & slurp functionality + +2001-02-14 Wednesday 08:29 Katariina Ervasti + + * Documentation/Manuscripts/HyperRFC/hyp.tex: korjauksia + +2001-02-14 Wednesday 08:11 Antti-Juhani Kaijanaho + + * Documentation/Manuscripts/HyperRFC/hyp.tex: comments and typos + +2001-02-14 Wednesday 00:04 Vesa Parkkinen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: added a comment + +2001-02-13 Tuesday 22:59 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Answer most of Vesa's + comments. I jaksan't write any more tonight but tomorrow. Please + feel free to also contribute actual text ;) + +2001-02-13 Tuesday 21:54 Vesa Parkkinen + + * Documentation/Manuscripts/HyperRFC/hyp.tex: comments + +2001-02-13 Tuesday 19:55 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: foo + +2001-02-13 Tuesday 18:59 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: More + +2001-02-13 Tuesday 18:54 Antti-Juhani Kaijanaho + + * Documentation/Spec/zzspec.wml: some cell ID stuff wrt space parts + and foreign cells + +2001-02-13 Tuesday 13:53 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: More. PLEASE comment + +2001-02-13 Tuesday 11:01 Antti-Juhani Kaijanaho + + * Java/SpaceDump.java (gzigzag_conversion_2000_07_06): fix the dump + format + +2001-02-12 Monday 21:22 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: Small change + +2001-02-12 Monday 13:59 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: hyp.tex, hyp.tex, hyp.tex: + More + +2001-02-12 Monday 13:40 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/hyp.tex: More hyperrfc + +2001-02-12 Monday 13:30 Antti-Juhani Kaijanaho + + * Java/SpaceDump.java: file SpaceDump.java was initially added on + branch gzigzag_conversion_2000_07_06. + +2001-02-12 Monday 13:30 Antti-Juhani Kaijanaho + + * Java/ZZInvalidDimensionError.java: file + ZZInvalidDimensionError.java was initially added on branch + gzigzag_conversion_2000_07_06. + +2001-02-12 Monday 13:30 Antti-Juhani Kaijanaho + + * Java/: Main.java, SpaceDump.java, ZZDimSpace.java, + ZZInvalidDimensionError.java, ZZSpace.java, storage/DirSet.java, + storage/Recs.java, storage/Recs.pl, storage/WritableHash.java, + storage/WritableSet.java, storage/ZZPersistentDimSpace.java, + storage/ZZPersistentDimension.java (gzigzag_conversion_2000_07_06): + add space dump functionality for conversion purposes + +2001-02-12 Monday 12:50 Tuomas J. Lukka + + * Documentation/Manuscripts/HyperRFC/: ht01e.sty, hyp.tex: foo + +2001-02-09 Friday 08:30 Antti-Juhani Kaijanaho + + * Java/media/StringScroll.java: some documentation + +2001-02-09 Friday 06:05 Antti-Juhani Kaijanaho + + * Documentation/Networking/: ZTP-usage.txt, ZTP-usage.txt: document + more + +2001-02-09 Friday 06:00 Antti-Juhani Kaijanaho + + * Java/ZZEmergencyCommandLineInterface.java: oops + +2001-02-09 Friday 05:59 Antti-Juhani Kaijanaho + + * Documentation/FAQ, Java/ZZEmergencyCommandLineInterface.java: + refer to the new bug reporting page + +2001-02-08 Thursday 11:31 Antti-Juhani Kaijanaho + + * Modules/ztp/client/Session.java: fix a bug + +2001-02-08 Thursday 11:18 Antti-Juhani Kaijanaho + + * Documentation/Networking/mock-ZTPTCP.txt, Java/ZZCell.java, + Java/ZZDimSpace.java, Java/ZZSpace.java, + Java/storage/ZZCacheDimSpace.java, Modules/ztp/client/Get.java, + Modules/ztp/client/Session.java, + Modules/ztp/common/SubspaceDump.java, + Modules/ztp/server/PutMessage.java: more ZTP work; now GET works + even in client + +2001-02-08 Thursday 08:19 Antti-Juhani Kaijanaho + + * Modules/ztp/: client/Get.java, client/Put.java, + client/Subspace.java, common/SubspaceDumper.java, + server/PutMessage.java, client/Session.java, + common/SubspaceDump.java, common/SubspaceDumper.java, + server/GetMessage.java, server/PutMessage.java: more ZTP work + +2001-02-08 Thursday 05:51 Antti-Juhani Kaijanaho + + * Java/: SysLogger.java, arch/syslog/arch.mk: more gnu->syslog + + making the arch.mk better + +2001-02-08 Thursday 05:42 Antti-Juhani Kaijanaho + + * Documentation/Networking/ZTP-usage.txt: gnu->syslog + +2001-02-08 Thursday 05:41 Antti-Juhani Kaijanaho + + * Java/arch/syslog/: arch.mk, org_gzigzag_SysLogger.c: another + move, hope this one is final (it's not gnu either:-) + +2001-02-07 Wednesday 14:24 Antti-Juhani Kaijanaho + + * Modules/ztp/: client/.cvsignore, server/.cvsignore: some ignores + +2001-02-07 Wednesday 14:23 Antti-Juhani Kaijanaho + + * Documentation/Networking/ZTP-usage.txt: added brief ZTP usage + instructions + +2001-02-07 Wednesday 14:02 Antti-Juhani Kaijanaho + + * Documentation/Networking/mock-ZTPTCP.txt, Java/SafeExit.java, + Java/ZZCell.java, Modules/ztp/ZTPclient.java, + Modules/ztp/client/Action.java, Modules/ztp/client/Get.java, + Modules/ztp/client/Put.java, + Modules/ztp/client/RemotePieceData.zob, + Modules/ztp/client/Response.java, Modules/ztp/client/Session.java, + Modules/ztp/common/Command.java, + Modules/ztp/common/LineBufferedIO.java, + Modules/ztp/common/SubspaceDumper.java, + Modules/ztp/server/GetMessage.java, + Modules/ztp/server/PutMessage.java: "first partially working + client: it can put! + +2001-02-07 Wednesday 10:39 Antti-Juhani Kaijanaho + + * Modules/ztp/common/Command.java: document + +2001-02-07 Wednesday 10:35 Antti-Juhani Kaijanaho + + * Modules/ztp/: common/Command.java, server/Command.java, + common/Command.java: Command is used by both client and server + +2001-02-07 Wednesday 10:32 Antti-Juhani Kaijanaho + + * Documentation/Networking/mock-ZTPTCP.txt, + Modules/ztp/ZTPclient.java, Modules/ztp/server/Session.java: some + more work on ZTP client + +2001-02-07 Wednesday 10:29 Katariina Ervasti + + * Documentation/UsersGuide/newug.wml: documentation again + +2001-02-07 Wednesday 10:19 Katariina Ervasti + + * Documentation/UsersGuide/newug.wml: cat also forgot something + else of the user's guide + +2001-02-07 Wednesday 10:14 Katariina Ervasti + + * Documentation/UsersGuide/: active.png, aftermove.png, + newcells.png, newstory.png, newstory2.png, newstory3.png, + rastererror.png, start.png, story.png, storytext.png: uups cat + forgot to add the images + +2001-02-07 Wednesday 10:11 Katariina Ervasti + + * Documentation/UsersGuide/newug.wml: # cat finally updates the + user's guide + +2001-02-07 Wednesday 08:21 Antti-Juhani Kaijanaho + + * Modules/ztp/server/: GetMessage.java, PutMessage.java: added some + synchronization + +2001-02-07 Wednesday 07:38 Antti-Juhani Kaijanaho + + * Modules/ztp/server/: GetMessage.java, Session.java: a very + primitive ZTP GET works now for the whole space + +2001-02-07 Wednesday 07:12 Antti-Juhani Kaijanaho + + * Modules/ztp/server/Command.java: fix bug in encode + +2001-02-07 Wednesday 06:01 Antti-Juhani Kaijanaho + + * Modules/ztp/server/Command.java: better style for ASCII_word_char + +2001-02-06 Tuesday 12:12 Antti-Juhani Kaijanaho + + * Documentation/Networking/mock-ZTPTCP.txt, + Documentation/Networking/ztp.wml, Modules/ztp/server/Command.java, + Modules/ztp/server/GetMessage.java, + Modules/ztp/server/PutMessage.java: more ZTP work + +2001-02-06 Tuesday 07:47 Antti-Juhani Kaijanaho + + * Modules/ztp/server/: Command.java, PutMessage.java: oops + +2001-02-06 Tuesday 07:35 Antti-Juhani Kaijanaho + + * Modules/ztp/: ZTPserver.java, common/LineBufferedIO.java, + server/Listener.java, server/Session.java, server/UserManager.java, + server/UserRecord.zob: move around ZTP classes into a more refined + package structure + +2001-02-06 Tuesday 07:11 Antti-Juhani Kaijanaho + + * Documentation/Networking/mock-ZTPTCP.txt, + Modules/ztp/server/Session.java: ztp put works for the whole space + now + +2001-02-05 Monday 13:25 Antti-Juhani Kaijanaho + + * Documentation/Networking/mock-ZTPTCP.txt, + Modules/ztp/server/Session.java: today's work on ztp + +2001-02-05 Monday 11:47 Antti-Juhani Kaijanaho + + * Java/Makefile, Modules/ztp/server/Listener.java: more ztp work + +2001-02-05 Monday 11:38 Antti-Juhani Kaijanaho + + * Java/SysLogger.java: hmm, it's not posix, so it's better off + being gnu + +2001-02-05 Monday 11:26 Antti-Juhani Kaijanaho + + * Java/Main.java, Java/Makefile, Java/SysLogger.java, + Java/ZZLogger.java, Modules/ztp/ZTPserver.java, + Modules/ztp/server/Session.java, + Modules/ztp/server/UserManager.java: more work on ZTP server + +2001-02-05 Monday 08:31 Antti-Juhani Kaijanaho + + * Java/Main.java, Modules/ztp/ZTPserver.java: now works from Main + too:-) + +2001-02-05 Monday 08:09 Antti-Juhani Kaijanaho + + * Documentation/Networking/: ZTP.txt, ztp.wml: more STP->ZTP + +2001-02-05 Monday 08:04 Antti-Juhani Kaijanaho + + * Documentation/Networking/Makefile, + Documentation/Networking/STP.txt, Documentation/Networking/ZTP.txt, + Documentation/Networking/mock-STPTCP.txt, + Documentation/Networking/mock-ZTPTCP.txt, + Documentation/Networking/stp.wml, Documentation/Networking/ztp.wml, + Java/Main.java, Java/Makefile, Modules/ztp/ZTPserver.java, + Modules/ztp/server/Listener.java, Modules/ztp/server/Session.java, + Modules/ztp/server/UserManager.java, + Modules/ztp/server/UserRecord.zob, + Modules/ztp/common/LineBufferedIO.java: file renames to move stp -> + ztp + +2001-02-05 Monday 07:40 Antti-Juhani Kaijanaho + + * Documentation/Networking/mock-STPTCP.txt, Java/Makefile: first + working version, no real functionality yet + +2001-02-05 Monday 06:11 Antti-Juhani Kaijanaho + + * Java/Makefile: scan stp subdirectories for zobs + +2001-02-02 Friday 12:32 Antti-Juhani Kaijanaho + + * Documentation/Networking/Makefile: oops, forgot this one + +2001-01-26 Friday 13:53 Antti-Juhani Kaijanaho + + * NEWS, Java/Makefile, Java/ZZKeyBindings1.java, + Java/flob/RowColView.zob, Java/media/FText.java, + Java/media/FirstMatchBreaker.java, + Java/storage/ZZPersistentDimension.java, Modules/nile/Nile1.java, + Modules/nile/Nile1View.zob, Modules/nile/Nile2Ops.java: merge from + 0.5 + +2001-01-26 Friday 13:47 Antti-Juhani Kaijanaho + + * Java/: Makefile, media/UTF8Char.java: a currently useless + framework for a mock-STP/TCP server + +2001-01-25 Thursday 12:46 Rauli Ruohonen + + * Java/Main.java: PDA mode: Added flag '-pda'. + +2001-01-25 Thursday 10:09 Rauli Ruohonen + + * Java/storage/: ZZPersistentDimension.java (ver_0_5), + ZZPersistentDimension.java: Fixed a trigger bug. + +2001-01-24 Wednesday 17:10 Benjamin Fallenstein + + * Java/flob/RowColView.zob (ver_0_5): Show the dimensions in + RowColView + +2001-01-24 Wednesday 17:02 Benjamin Fallenstein + + * Modules/nile/: Nile1.java, Nile2Ops.java (ver_0_5): More Nile + fixes + +2001-01-24 Wednesday 17:00 Benjamin Fallenstein + + * Java/ZZKeyBindings1.java (ver_0_5): A new kind of binding, + INSERT, which is tried immediately before DEFAULT, if the action + was a single-character key press (used in Nile to change the mode + to character mode only if we will actually insert something, and + probably useful in all applitude tools which allow entering text) + +2001-01-24 Wednesday 14:05 Benjamin Fallenstein + + * Modules/nile/: Nile1.java, Nile1View.zob, Nile2Ops.java + (ver_0_5): Nile fixes + +2001-01-24 Wednesday 11:05 Benjamin Fallenstein + + * Java/media/FirstMatchBreaker.java (ver_0_5): oops, forgot to add + +2001-01-24 Wednesday 11:05 Benjamin Fallenstein + + * Java/media/FirstMatchBreaker.java: file FirstMatchBreaker.java + was initially added on branch ver_0_5. + +2001-01-24 Wednesday 11:03 Benjamin Fallenstein + + * Java/media/FText.java (ver_0_5): A new linebreaker -- not the TeX + one, but another trivial first-fit one. Works perfectly (as far as + I have tested it), is faster, and does multiline + +2001-01-24 Wednesday 08:32 Vesa Parkkinen + + * Java/ZZDimension.java: fixed a null pointer in hop + +2001-01-22 Monday 08:37 Antti-Juhani Kaijanaho + + * Java/Makefile (ver_0_5): Fix MODULES. + +2001-01-20 Saturday 08:56 Benjamin Fallenstein + + * Modules/vob/: Connection.java, View.java, Vob.java, VobSet.java, + VobStore.java: Vob draft, based on what Vesa and I figured out + yesterday -- VobSets are pseudo-hierarchical, coordinates + conceptually belong into VobSets, connections are between vobs + (does not compile yet) + +2001-01-20 Saturday 08:52 Benjamin Fallenstein + + * Modules/panes/: .cvsignore, PaneView.zob: First draft of paned + view + +2001-01-19 Friday 11:19 Tero Mäyränen + + * Modules/multimedia/: Default.java, MediaFlobFactory.java, + MediaZOb.java, flobcolors.java, image.java, next.java, rect.java, + text.java: This version attempts to cache the MediaZObs.. + +2001-01-18 Thursday 10:06 Antti-Juhani Kaijanaho + + * Documentation/Networking/: STP.txt, stp.wml: work-in-progress + versions of STP docs + +2001-01-18 Thursday 07:59 Antti-Juhani Kaijanaho + + * Java/Makefile (ver_0_5): sync JARMODULES with MODULES + +2001-01-18 Thursday 07:47 Antti-Juhani Kaijanaho + + * Java/Makefile (ver_0_5): add another build iteration to jar + target + +2001-01-18 Thursday 07:39 Antti-Juhani Kaijanaho + + * Java/Makefile (ver_0_5): enable vc and mm modules + +2001-01-18 Thursday 07:34 Antti-Juhani Kaijanaho + + * NEWS (ver_0_5): 0.5 preparation + +2001-01-17 Wednesday 14:27 Tuomas J. Lukka + + * Modules/servlet/: VCServlet.java, ZZServlet.java, startjetty, + zzserv.prp, zzserv2.prp: Servlets... + +2001-01-17 Wednesday 14:23 Tuomas J. Lukka + + * Java/: ZZCell.java, ZZCellHandle.java: Hopefully fix cells in + hashtables as keys + +2001-01-17 Wednesday 12:46 Benjamin Fallenstein + + * Java/flob/CellFlobFactory2.zob: A new version of CellView 2, + finally able to do multiline (but not bug-free) + +2001-01-17 Wednesday 10:50 Rauli Ruohonen + + * Modules/virtualcommunity/: MessageFlobFactory.zob, + VirtualCommunity.zob, VirtualCommunity.zob: [no log message] + +2001-01-17 Wednesday 10:20 Rauli Ruohonen + + * Java/flob/FTextLayouter.zob, + Modules/virtualcommunity/MessageFlobFactory.zob: [no log message] + +2001-01-17 Wednesday 10:13 Benjamin Fallenstein + + * Java/flob/FTextLayouter.zob: Fix + +2001-01-17 Wednesday 10:12 Rauli Ruohonen + + * Java/media/FText.java, + Modules/virtualcommunity/MessageFlobFactory.zob, + Modules/virtualcommunity/VirtualCommunity.zob: Foo + +2001-01-17 Wednesday 09:24 Antti-Juhani Kaijanaho + + * Modules/virtualcommunity/VirtualCommunity.zob: fixed copyright + year + +2001-01-17 Wednesday 08:56 Rauli Ruohonen + + * Java/media/FText.java, + Modules/virtualcommunity/MessageFlobFactory.zob, + Modules/virtualcommunity/VirtualCommunity.zob: Blaa. + +2001-01-17 Wednesday 08:03 Antti-Juhani Kaijanaho + + * Java/ZZViewComponent.java: a really bad quick hack to make a + ring, a diaeresis and o diaeresis work + +2001-01-17 Wednesday 05:43 Vesa Parkkinen + + * Modules/virtualcommunity/VirtualCommunity.zob: more vc demo stuff + +2001-01-17 Wednesday 03:04 Vesa Parkkinen + + * Java/flob/CellBgFlob.java: added a method to set the background + color + +2001-01-17 Wednesday 03:00 Vesa Parkkinen + + * Modules/virtualcommunity/: MessageFlobFactory.zob, + VirtualCommunity.zob: more work on the vc demo + +2001-01-16 Tuesday 16:18 Rauli Ruohonen + + * Java/ZZPrimitiveActions.java, Java/flob/CellFlobFactory1.zob, + Java/flob/FTextLayouter.zob, Java/media/FText.java, + Modules/multimedia/MediaFlobFactory.java, + Modules/virtualcommunity/MessageFlobFactory.zob, + Modules/virtualcommunity/VirtualCommunity.zob: Bugfixes. + +2001-01-16 Tuesday 14:09 Rauli Ruohonen + + * Java/flob/Flob.java, Modules/multimedia/MediaFlobFactory.java, + Modules/virtualcommunity/MessageFlobFactory.zob: Some bugfixes. + +2001-01-16 Tuesday 12:58 Vesa Parkkinen + + * Java/flob/FTextLayouter.zob: quick fix to get virtualcommunity + demo working + +2001-01-16 Tuesday 11:40 Vesa Parkkinen + + * Modules/multimedia/: ImageSource.java, MediaFlobFactory.java: + fixed few non-1.1 methods + +2001-01-16 Tuesday 10:12 Vesa Parkkinen + + * Modules/virtualcommunity/: MessageFlobFactory.zob, + VirtualCommunity.zob: more code to the demo + +2001-01-16 Tuesday 09:57 Tero Mäyränen + + * Modules/multimedia/: MediaFlobFactory.java, MediaZOb.java, + image.java: Small update, shows image by just writing an URL to a + cell when mm.MediaFlobFactory is in use... + +2001-01-16 Tuesday 02:39 Rauli Ruohonen + + * Modules/virtualcommunity/: MessageFlobFactory.zob, + VirtualCommunity.zob: Some code for the demo. + +2001-01-15 Monday 18:25 Vesa Parkkinen + + * Modules/virtualcommunity/VirtualCommunity.zob: added + virtualcommunity module + +2001-01-15 Monday 13:07 Tero Mäyränen + + * Modules/multimedia/: Default.java, ImageSource.java, + MediaFlobFactory.java, MediaZOb.java, flobcolors.java, image.java, + mm.java, next.java, rect.java, text.java: Preliminary version of + the multimedia module primarily just for the upcoming demo. + +2001-01-12 Friday 12:55 Antti-Juhani Kaijanaho + + * Java/ZZDefaultSpace.java: Add cursor view to AllViews + +2001-01-07 Sunday 18:59 Benjamin Fallenstein + + * Modules/nile/draft/: Nile3Ops.java, Nile3Part.java, + Nile3Pos.java, Nile3Unit.java: A very preliminary version of a + possible 3rd generation Nile API + +2001-01-07 Sunday 18:21 Benjamin Fallenstein + + * Java/clang/Data.java, Modules/zaubertrank/Evaluator.java, + Modules/zaubertrank/ZaubertrankPart.java: More work on the + zaubertrank + +2001-01-06 Saturday 21:32 Benjamin Fallenstein + + * Modules/notemap/Notemap.zob: Now supporting directed links. + Selecting certain link types is needed next. + +2001-01-05 Friday 12:33 Antti-Juhani Kaijanaho + + * NEWS, changelog-authors, Documentation/Makefile, + Documentation/index.html, Documentation/Nile/Makefile: merge from + 0.4 + +2001-01-04 Thursday 14:07 Benjamin Fallenstein + + * Modules/notemap/.cvsignore: cvsignore + +2001-01-04 Thursday 14:06 Benjamin Fallenstein + + * Java/ZZCursorReal.java, Java/clang/Data.java, + Modules/zaubertrank/Actions.java, + Modules/zaubertrank/Evaluator.java, + Modules/zaubertrank/Primitive.java, + Modules/zaubertrank/PrimitiveSet.java: Some more work on the + zaubertrank, ZZCursorReal.adjustCursors for use after insertions or + deletions in cells + +2001-01-03 Wednesday 16:47 Rauli Ruohonen + + * Java/Main.java, Java/ZZCanvasView.java, Java/ZZDefaultSpace.java, + Java/ZZObsTrigger.java, Java/ZZPrimitiveActions.java, + Java/ZZViewComponent.java, Java/ZZWindows.java, + Modules/applet/ZZApplet.java, Modules/nile/NileApplet.java: Added + ZZ structure observation in ZZWindows, enable/disable and + chg(ZZObs) to ZZObsTrigger, fixed some bugs and moved most of the + windowing stuff from the applets to ZZWindows. + +2001-01-02 Tuesday 11:53 Rauli Ruohonen + + * Java/: Main.java, ZZCanvasView.java, ZZCell.java, + ZZObsTrigger.java, ZZUpdateManager.java, ZZUtil.java, + ZZViewComponent.java, ZZWindows.java, + storage/ZZCacheDimension.java: Triggering bugfixes and some changes + in behavior. + diff --git a/ChangeLog.2000 b/ChangeLog.2000 new file mode 100644 index 0000000..7f6ea31 --- /dev/null +++ b/ChangeLog.2000 @@ -0,0 +1,1329 @@ +2000-12-31 Sunday 15:23 Benjamin Fallenstein + + * Java/flob/CursorView.zob: Fix + +2000-12-31 Sunday 15:15 Benjamin Fallenstein + + * Java/: ApplitudeMgr.java, ZZDefaultSpace.java, + ZZKeyBindings1.java, ZZPrimitiveActions.java, + flob/CombinedView.zob: Fixes + +2000-12-31 Sunday 15:12 Benjamin Fallenstein + + * Java/flob/FlobSet.java: Make FlobSet MUCH more efficient, not + using Vectors when not needed + +2000-12-29 Friday 00:01 Benjamin Fallenstein + + * Java/Makefile: Add notemap + +2000-12-28 Thursday 22:46 Benjamin Fallenstein + + * Java/flob/MultiView.zob: Improve applitude interconnectivity + +2000-12-28 Thursday 02:18 Benjamin Fallenstein + + * Java/flob/.cvsignore: ...and now: an attempt at THE REAL THING + (applitude interconnectivity) + +2000-12-28 Thursday 01:19 Benjamin Fallenstein + + * Modules/nile/NileDemo.java: Now applitude bindings work quite + well, including mode changes -- i.e., Nile works together with + other applitudes + +2000-12-27 Wednesday 21:11 Benjamin Fallenstein + + * Java/flob/Flob.java: Now able to change applitude by clicking + +2000-12-27 Wednesday 12:14 Benjamin Fallenstein + + * Modules/notemap/Notemap.zob: Half-fix: it isn't *right*, but + readable now even in special cases + +2000-12-27 Wednesday 12:11 Antti-Juhani Kaijanaho + + * Documentation/Math/ajk-scribbles.tex: Initial revision. + +2000-12-27 Wednesday 00:43 Benjamin Fallenstein + + * NEWS: Update + +2000-12-26 Tuesday 22:48 Benjamin Fallenstein + + * Java/storage/MemWritable.java, Modules/nile/NileApplet.java: OK, + make it actually work + +2000-12-26 Tuesday 21:59 Benjamin Fallenstein + + * Modules/nile/SplitNileDemo.java: Draft of an applet demoing split + nile (actually, it works, except StringScroll needs a writable -- + which disables scrolls/spans -- which disables transclusions, which + basicly is the coolest thing we want to show...) + +2000-12-26 Tuesday 21:13 Benjamin Fallenstein + + * Modules/nile/.cvsignore: Add SplitNileView + +2000-12-26 Tuesday 21:12 Benjamin Fallenstein + + * Modules/nile/Nile1.java: Fix a bit + +2000-12-26 Tuesday 20:15 Benjamin Fallenstein + + * Modules/nile/SplitNileView.zob: Forgot to add, again... + +2000-12-26 Tuesday 20:15 Benjamin Fallenstein + + * Java/flob/CoordDecor.java: WOW: Parallel Nile streams -- showing + transclusions with beams + +2000-12-26 Tuesday 15:20 Benjamin Fallenstein + + * Java/flob/SplitView.zob: Oops, forgot to add... + +2000-12-26 Tuesday 15:20 Benjamin Fallenstein + + * Java/flob/Renderable.java: Put in hooks for the basic capability + of combining views, and a funny view that uses them + +2000-12-26 Tuesday 14:09 Benjamin Fallenstein + + * Java/media/FText.java: Fix capitalisation + +2000-12-25 Monday 19:55 Benjamin Fallenstein + + * Modules/nile/Nile2Ops.java: ...and, forgot to commit this + +2000-12-25 Monday 19:37 Benjamin Fallenstein + + * Java/: flob/FTextLayouter.zob, media/Capitalizer.java: Abstract + string capitalization out to a Capitalizer class, change FText and + FTextLayouter API (next step would be to move firstCap out of + FTextLayouter -- it does NOT belong there! -- and into the views; + at the same time, get rid of the calls with beginningSentence[]. + Too much work to do it now) + +2000-12-25 Monday 17:26 Benjamin Fallenstein + + * Java/clang/: Data.java, flowing/Data.java: Make Data usable by + all clangs also, doc a bit (I moved it to org.gzigzag because that + causes the least changes, but it'd be better to move it to + org.gzigzag.clang someday.) + +2000-12-25 Monday 13:58 Benjamin Fallenstein + + * Modules/zaubertrank/ZaubertrankPart.java, + Java/storage/ZZCacheDimSpace.java: A spacepart for the zaubertrank, + with a dimension that shows the elements of a zaubertrank token + tree in Reverse Polish Notation. + +2000-12-25 Monday 13:54 Benjamin Fallenstein + + * Java/errors/: MissingTermError.java, SyntaxError.java: Oops, + publicize + +2000-12-25 Monday 12:22 Benjamin Fallenstein + + * Java/clang/thales/SyntaxError.java: Move SyntaxError to + org.gzigzag and Java/errors -- I think it should be possible for + all clangs to use the same SyntaxError exception. If we want to + separate, we can have subclasses. + +2000-12-25 Monday 09:45 Benjamin Fallenstein + + * changelog-authors: Last time commits weren't mailed through + gzz-commits, not everyone was on changelog-authors, so try adding + everyone on the SourceForge Project Member List ;) (it can't hurt, + can it now?) + +2000-12-24 Sunday 21:24 Benjamin Fallenstein + + * Java/transform/Convert.java: A handy little utility to convert + from old to new file format + +2000-12-24 Sunday 13:54 Benjamin Fallenstein + + * Java/: Dump.java, dump2java.pl: More work on dumping + +2000-12-22 Friday 22:44 Benjamin Fallenstein + + * Java/Dumper.java: Make im- and export of dumps work; dump2java + converter later to be invoked on compiletime, to make a Java file + which recreates the dumped subspace + +2000-12-20 Wednesday 22:26 Benjamin Fallenstein + + * Modules/nile/Nile2Iter.java: Jump between nile transclusions -- + unfortunately, this *does* cheat + +2000-12-18 Monday 19:24 Benjamin Fallenstein + + * Java/: Main.java, ZZDimSpace.java, ZZSpace.java: Put the hooks in + to find all cells whose spans overlap a given span. New arg for + Main, -span, so that normal users won't be slowed down until we + have a reasonable implementation for SpanSet. + +2000-12-17 Sunday 17:24 Benjamin Fallenstein + + * Modules/nile/Nile1View.zob: Turn standard debug off + +2000-12-17 Sunday 16:32 Benjamin Fallenstein + + * Modules/nile/Nile2Unit.java: Nile transclusions + +2000-12-12 Tuesday 18:43 Tuomas J. Lukka + + * Java/storage/ZZPersistentDimSpace.java: + PersistentDimSpace.recreateMasterDimList must set the space of the + dimension or there'll be problems. + +2000-12-12 Tuesday 11:18 Antti-Juhani Kaijanaho + + * Java/storage/ZZPersistentDimension.java: s/final// for dbg, also + enable one commented-out p() + +2000-12-11 Monday 21:38 Tuomas J. Lukka + + * Java/media/TestLines.java: Change method use deprecated in jdk1.3 + +2000-12-11 Monday 19:47 Tuomas J. Lukka + + * Java/ScalableFont.java: Clean up, restyle, document + +2000-12-11 Monday 13:57 Antti-Juhani Kaijanaho + + * Documentation/Nile/Makefile (ver_0_4): Fix^2: Nile in 0.4 doc + tarball + +2000-12-11 Monday 13:40 Antti-Juhani Kaijanaho + + * Documentation/Makefile (ver_0_4): Nile in 0.4 doc tarball + +2000-12-11 Monday 13:20 Antti-Juhani Kaijanaho + + * Documentation/index.html (ver_0_4): Nile docs + +2000-12-11 Monday 09:20 Rauli Ruohonen + + * Java/ZZUpdateManager.java, Modules/applet/ZZApplet.java, + Modules/prez/PrezRaster.zob: Cleaned ZZUpdateManager up a bit + (clarified comments, removed unused variables). Fixed a null + pointer reference bug in PrezRaster. Modified ZZApplet so that it + works again. + +2000-12-11 Monday 09:03 Rauli Ruohonen + + * Java/ZOb.java, Java/ZZCommand.java, Java/ZZWindows.java, + Java/zob2java.pl, Java/flob/CellFlobFactory1.zob, + Java/flob/CellFlobFactory2.zob, + Java/flob/IdiosyncraticFlobFactory.zob, + Java/flob/ParallelTextView.zob, Java/flob/RankTextView.zob, + Modules/textcloud/TextCloud.zob: Replaced ad hoc font scaling stuff + in zobs with use of ScalableFont. Nile is the only view still using + the old way. + +2000-12-11 Monday 02:54 Tuomas J. Lukka + + * Java/flob/VanishingView.zob: Add more efficient getPoint to Flob, + document FlobSet little + +2000-12-11 Monday 02:54 Tuomas J. Lukka + + * Java/flob/VobSet.java: Start drafting new API + +2000-12-10 Sunday 21:18 Benjamin Fallenstein + + * Java/flob/SimpleTextView.zob: Make editview work with + SimpleTextView, new HELP command bound to F1 + +2000-12-10 Sunday 17:14 Tuomas J. Lukka + + * Modules/nile/Nile1.zob: Reorganize a bit + +2000-12-09 Saturday 02:29 Tuomas J. Lukka + + * Documentation/Nile/nileug.wml: Short nile user's guide + +2000-12-08 Friday 23:05 Tuomas J. Lukka + + * Documentation/Nile/nile.wml, Java/ZZCursorReal.java: Nile now + basically works as a text editor. Now it's time to start testing it + out and fixing the details. Whew! + +2000-12-08 Friday 12:50 Benjamin Fallenstein + + * Modules/zaubertrank/: Actions.java, ParsedView.zob, Parser.java, + Zaubertrank.java: Yet some more work on the zaubertrank + +2000-12-07 Thursday 00:37 Tuomas J. Lukka + + * Modules/nile/: Nile1Ops.java, Nile1Text.java, Nile2Test.java: + More nile work. Now moved to new APIs, which make things a LOT + simpler than the earlier ones. The way the word-breaking code works + is almost clear now ;). Sentences and paragraphs untested. Should + define actions soon. + +2000-12-07 Thursday 00:36 Tuomas J. Lukka + + * Java/ZZCell.java: Add new method: findCell to look for a cell + along a rank. + +2000-12-06 Wednesday 10:36 Benjamin Fallenstein + + * Modules/zaubertrank/SimpleView.zob: More work on the zaubertrank + +2000-12-05 Tuesday 03:44 Tuomas J. Lukka + + * Java/mungencss.pl: A small script to remove generated routines + from the javancss output. + +2000-12-05 Tuesday 03:43 Tuomas J. Lukka + + * Java/clang/heraclitus/: HeraclitusClang.java, + HeraclitusCommand.zob, Primitive.java: Comment some more, change + cursorparam to param. + +2000-12-05 Tuesday 02:01 Tuomas J. Lukka + + * Documentation/wmlinc/art.css: More nile doc + +2000-12-04 Monday 22:11 Benjamin Fallenstein + + * Modules/zaubertrank/: .cvsignore, README.html, TokenFlob.java, + TokenGrouper.java: More work on the zaubertrank + +2000-12-04 Monday 13:01 Tuomas J. Lukka + + * Java/: JEv.java, ZZViewComponent.java, media/Stream.java: Clean + up some old code + +2000-11-30 Thursday 19:44 Tuomas J. Lukka + + * Java/flob/SplitCellFlob1.java: SplitCellFlobs MUST have the same + cell if they are parent and nextPart. + +2000-11-30 Thursday 19:43 Tuomas J. Lukka + + * Java/ZZUtil.java: Make mix a little more careful + +2000-11-30 Thursday 08:44 Antti-Juhani Kaijanaho + + * Makefile, manifest-filter.pl, Java/ZZDimension.java, + Java/ZZLocalDimension.java, Java/storage/ZZCacheDimension.java, + Modules/test/TestUndo.java: merge from 0.3 + +2000-11-28 Tuesday 12:07 Antti-Juhani Kaijanaho + + * Java/media/StringScroll.java: Update author info. + +2000-11-27 Monday 11:09 Antti-Juhani Kaijanaho + + * Java/media/UTF8Char.java: New UTF-8 StringScroll format + +2000-11-25 Saturday 00:36 Tuomas J. Lukka + + * Java/: ZZCursor.java, ZZCursorVirtual.java: Nile now knows how to + select single words when clicked by mouse. Hopping them over each + other is the next task... + +2000-11-24 Friday 16:24 Tuomas J. Lukka + + * Java/media/VStream.java: Further nile work - now showing the + selected unit should just about work, then for making the actual + units. This nastily complicates the view code but that's life - it + shouldn't be getting much worse after this, anyway. + +2000-11-24 Friday 03:02 Tuomas J. Lukka + + * Modules/nile/README: More nile work. Factor out vstream cursor + move from PrimitiveActions - this should probably be done for a + number of other actions, too... + +2000-11-22 Wednesday 17:19 Antti-Juhani Kaijanaho + + * Documentation/: CyberText/permascroll.png, + CyberText/rank1vert.png, CyberText/rank2vert.png, + CyberText/rank3both.png, Spec/canvasraster.png, Spec/cursor1.png, + Spec/cursordim.png, Spec/inheritparam.png, Spec/rasterspec.png: + generated files OUT! + +2000-11-22 Wednesday 00:35 Tuomas J. Lukka + + * Modules/nile/Nile1GenTreeModel.java: Various changes to make nile + have its own window and modes. Now we can start working on the ops + in peace, and because it's bound to a real window, we can very + easily see what is happening in the structure. Of course, this is + not how it will be in the end: in the end it will be just one of + the views and views can also have states but for now, we'll do + this. + +2000-11-20 Monday 17:36 Tuomas J. Lukka + + * Modules/nile/Nile1Div.java: More nile work + +2000-11-20 Monday 12:59 Tuomas J. Lukka + + * Java/flob/FlobView.java: Fix rcsid + +2000-11-19 Sunday 01:49 Tuomas J. Lukka + + * Modules/hypergenealogy/HyperGenealogy.zob: More work - now can + show each time step, so can basically animate. + +2000-11-17 Friday 18:46 Tuomas J. Lukka + + * Java/flob/FTextLayouter.java: Add firstcap and + section-title-jumping to nile. It is starting to look pretty good. + Text entry is still difficult because you have to make the tags by + hand but that'll get easier soon. The problem with fistcap is that + it's done completely wrong now and needs to be redone. 1: there + should be a central place to do it, with its own state object, 2: + there should be less awareness of it throughout classes, it should + be a single call to FText, not involving FTextLayout at all, 3: it + should be thought out whether we do really want it to e at this + level or whether we should explicitly store sentence breaks in nile + - I don't know yet. But entering the sentence break by two spaces + feels quite natural (that's Ted's design). + +2000-11-17 Friday 13:52 Antti-Juhani Kaijanaho + + * Documentation/UsersGuide/: addressbook.png, alku.png, bind1.png, + bind2.png, boring.png, breakkafka.png, change1.png, change2.png, + child1.png, child2.png, connection1.png, creation.png, + dimensio.png, extra.png, f2.png, familytree.png, font.png, + grey.png, hop1.png, hop2.png, hopolympos.png, htree.png, kafka.png, + klooni.png, make1.png, make2.png, make3.png, make4.png, make5.png, + make6.png, margins.png, mark1.png, mark2.png, markconnect.png, + mutsi.png, mutsiosoite.png, myspeech.png, myspeech1.png, + myspeech2.png, myspeech3.png, newug.wml, olympos.png, olympos2.png, + osoite.png, para.png, rainy.png, rcfact1.png, rotate.png, row.png, + shiny.png, shinyhappy.png, shinyhappy2.png, shinyhappy3.png, + structure1.png, structure2.png, suku.png, testi.png, + wallstreet.png, widthstr.png, wrongconn.png (ver_0_2): bring + current manual from trunk to frozen branch + +2000-11-16 Thursday 21:01 Tuomas J. Lukka + + * Java/part/GenTreePart.java: Make space upgrade work again. Put + the old system list in a reasonable place. Remove dcold since it + doesn't mean anything after that. + +2000-11-16 Thursday 20:33 Benjamin Fallenstein + + * Java/clang/flowing/: Flowing.java, FlowingClang.java, + StackFrame.java, StackFrameReal.java, StackFrameVirtual.java: A + newer flowing clang version + +2000-11-16 Thursday 20:28 Benjamin Fallenstein + + * Java/DimRecursor.java, Java/Iter.java, + Java/flob/EnumVanishingView.zob, Modules/iter/.cvsignore, + Modules/iter/DimRecursor.java, Modules/iter/EnumVanishingView.zob, + Modules/iter/Iter.java, Modules/iter/README: Move iteration + experiments into Modules/ + +2000-11-16 Thursday 00:25 Tuomas J. Lukka + + * Java/part/: GenTreePartModel.java, GenTreeTestModel.java: More + work on tree-like parts: define a general interface. This makes the + code a bit simpler and now we can use this on nile. Excellent... + +2000-11-15 Wednesday 16:26 Tuomas J. Lukka + + * Java/arch/java2d/ZZDrawingJ2D.java: Lesser quality settings + +2000-11-13 Monday 11:59 Tuomas J. Lukka + + * Java/part/ImpliedTreePart2.java: Use parsed IDs. Improvement? + +2000-11-13 Monday 11:59 Tuomas J. Lukka + + * Java/: ZZSpacePart.java, part/ImpliedTreePart.java: Rationalize + +2000-11-13 Monday 11:58 Tuomas J. Lukka + + * Java/ZZCellHandle.java: Optimize + +2000-11-10 Friday 17:45 Benjamin Fallenstein + + * Java/flob/FlobFactory.java: An iteration draft which abstracts + the dimension recursion out; a not-yet-really-working version of + the Vanishing view in less than 175 lines, using that; functions to + place flobs visual center to visual center. + +2000-11-10 Friday 09:59 Antti-Juhani Kaijanaho + + * Documentation/wmlinc/catart.wml: (hopefully) fix anchoring + +2000-11-07 Tuesday 23:07 Tuomas J. Lukka + + * Java/: ZZSlicedDimSpace.java, storage/Sliced.java, + storage/SlicedCursor.java, storage/SlicedHomes.java, + storage/SlicedSame.java: Remove compilation warnings. Start work on + a sequence-implied tree + +2000-11-07 Tuesday 13:06 Antti-Juhani Kaijanaho + + * Java/flob/RowColRaster.zob: merge + +2000-11-07 Tuesday 12:38 Antti-Juhani Kaijanaho + + * Java/flob/CompassRaster.zob, Java/flob/CompassView.zob, + Java/flob/FlobRaster.java, Java/flob/ICView.zob, + Java/flob/Level.java, Java/flob/LevelRaster.zob, + Java/flob/LevelView.zob, Java/flob/ManyToManyRaster.zob, + Java/flob/ManyToManyView.zob, Java/flob/NullRaster.zob, + Java/flob/NullView.zob, Java/flob/RasterCellFactory1.zob, + Java/flob/RasterCellFactory2.zob, Java/flob/RasterFlobFactory.java, + Java/flob/RowColView.zob, Java/flob/SimpleFlobRaster.zob, + Java/flob/SimpleFlobView.zob, Java/flob/TreeRaster.zob, + Java/flob/TreeView.zob, Java/flob/VStreamRaster.zob, + Modules/daytimedemo/Calendar2.zob, + Modules/daytimedemo/DayTimeDemo.zob, Modules/mbox/SingleMail.zob: + merge + +2000-11-06 Monday 12:39 Tuomas J. Lukka + + * Java/part/: BinaryTreePart.java, DoubleStepPart.java, + ZZROSpacePart.java, ZZROStrSpacePart.java: An amusing new space + part: double-step dimensions + +2000-11-06 Monday 12:06 Antti-Juhani Kaijanaho + + * Java/clang/heraclitus/.cvsignore, Modules/daytimedemo/.cvsignore, + Modules/hypergenealogy/.cvsignore, Modules/mbox/ZZMbox.java: + merging from 0.2 branch + +2000-11-05 Sunday 19:11 Tuomas J. Lukka + + * Java/: ZZRODimension.java, storage/SlicedOV.java, + storage/SlicedStpr.java: BIG change. Please test, as things may be + BADLY broken. Change ZZDimension to use ZZCellHandles instead of + Strings, based on the potentially faulty assumption that + ZZCellHandles are a good idea. This is very experimental. + +2000-11-05 Sunday 18:22 Tuomas J. Lukka + + * Java/arch/javadoc/ZobDoc.java: First working version of ZOb docs. + +2000-11-05 Sunday 12:51 Tuomas J. Lukka + + * Java/.cvsignore: Add generated zob documentation + +2000-11-05 Sunday 12:49 Tuomas J. Lukka + + * Modules/openGL/ZZOpenGLGraphics.java: Start work on a doclet for + generating ZOb structparam docs. The point is to leave out the + things that are not interesting for use in the structure. + +2000-11-03 Friday 08:25 Antti-Juhani Kaijanaho + + * Java/: clang/ZZClangOps.pl, storage/Recs.pl: much better file by + perl generation + +2000-11-03 Friday 08:01 Antti-Juhani Kaijanaho + + * Java/media/Scroll.java, Java/storage/DimHash.java, + Java/storage/DirSet.java, Java/storage/WritableHash.java, + Java/storage/WritableSet.java, Modules/xml/XML.java: hopefully + final 0.1.x merge + +2000-11-03 Friday 06:47 Antti-Juhani Kaijanaho + + * Java/storage/Recs.java: generated file OUT! + +2000-11-02 Thursday 13:03 Tuomas J. Lukka + + * Java/LoopDetector.java: Important: use .equals instead of == for + comparison. + +2000-11-02 Thursday 13:01 Tuomas J. Lukka + + * Java/ZZDrawing.java: Rendering quality: I want my antialiased + fonts antialiased. + +2000-11-01 Wednesday 08:12 Tuomas J. Lukka + + * Java/: ZZCanvasView.java, ZZPhotoView.java, + media/ZZSoundView.java: Make painting always happen into + doublebuffer. + +2000-11-01 Wednesday 00:39 Tuomas J. Lukka + + * Java/: ZZIter.java, flob/StdLinks.zob: Various fixes to views, + including curving. Not complete yet: need to add bulge. + +2000-10-31 Tuesday 15:12 Tuomas J. Lukka + + * Java/TestSpace.java: First optional architecture: Java2D. If you + have Java2D in your compilation *and* execution environment and use + 'make ARCH=java2d', you'll get translucent cells. We can use the + improved rendering of Java2D now. + +2000-10-31 Tuesday 14:20 Antti-Juhani Kaijanaho + + * Documentation/UsersGuide/Makefile: fix a bug + +2000-10-31 Tuesday 14:01 Antti-Juhani Kaijanaho + + * Documentation/: lib.mk, wmlinc/article.wml, wmlinc/common.wml: + first version of cat's UG - talk to her if you want to work on it + +2000-10-30 Monday 15:25 Tuomas J. Lukka + + * Java/: ZZModule.java, flob/VanishingRaster.zob: VanishingRaster + -> vanishingview + +2000-10-30 Monday 10:44 Tuomas J. Lukka + + * Java/ZZModules.java: Why would we need an extra ZZModules class + after all? + +2000-10-29 Sunday 19:34 Tuomas J. Lukka + + * Modules/wordnet/conv.pl: Longer func name, for a change. Count + better. Make deleteFromRank called excise. + +2000-10-29 Sunday 19:19 Tuomas J. Lukka + + * Java/TimeTest.java: Twiddle + +2000-10-27 Friday 13:55 Tuomas J. Lukka + + * Java/flob/BallCell.java: Oops, forgot to add + +2000-10-26 Thursday 18:15 Tuomas J. Lukka + + * Java/flob/LineDecor.java: Fix dbg + +2000-10-26 Thursday 18:15 Tuomas J. Lukka + + * Java/flob/Colorer.java: A bit more structure + +2000-10-26 Thursday 18:14 Tuomas J. Lukka + + * Java/flob/CellBgFlob.java: Adjust for colorer + +2000-10-26 Thursday 18:09 Tuomas J. Lukka + + * Java/: SafeExit.java, UndoList.java, d.java, + errors/ZZInvalidCursorPositionError.java, flob/ArrowDecor.java, + flob/FlobDecorator.java: More javadoc comments + +2000-10-26 Thursday 13:08 Antti-Juhani Kaijanaho + + * Documentation/: keybindings.wml, Spec/Makefile: merge + +2000-10-26 Thursday 12:25 Antti-Juhani Kaijanaho + + * Java/NEWS (ver_0_1): oops, move NEWS to toplevel dir + +2000-10-22 Sunday 09:15 Tuomas J. Lukka + + * Java/flob/MagGrid.zob: Decrease trybefore a bit for smoother + animation + +2000-10-21 Saturday 23:07 Tuomas J. Lukka + + * Java/flob/GridGeom.java: Start reimplementing row-column stuff. + The aim is to get a cleaner abstraction so that we can start + bootstrapping by rewriting the new, easy code using cells. + +2000-10-21 Saturday 13:46 Tuomas J. Lukka + + * Java/README: Update requirements + +2000-10-21 Saturday 13:45 Tuomas J. Lukka + + * Documentation/Gentle_Introduction/gi.wml: Rewrite the whole XML + import / export stuff. We really don't want DOM to load the whole + document in memory but SAX since we can just stream off the tags. + This should make import/export of large amounts of stuff faster, + just what we need for the wordnet demo... + +2000-10-20 Friday 15:47 Benjamin Fallenstein + + * Java/ZZRasterDirection.java: This doesn't make sense to me + anymore... + +2000-10-20 Friday 15:16 Benjamin Fallenstein + + * Java/clang/flowing/X.java: Change back earlier i18n attempt + +2000-10-20 Friday 11:35 Tuomas J. Lukka + + * Java/RString.java: This may become something eventually - + referential strings as objects. I'll have to talk with Ted about + what a cell should really be able to contain + +2000-10-19 Thursday 17:04 Tuomas J. Lukka + + * Java/media/: ZZDefaultText.java, ZZText.java: Next draft + +2000-10-18 Wednesday 14:35 Tuomas J. Lukka + + * Java/ZZConnection.java, Java/ZZPath.java, + Java/clang/ZZClang1.java, Java/clang/ZZClangContextReal.java, + Java/clang/flowing/T.java, Java/clang/heraclitus/PS1.java, + Java/clang/thales/Environment.java, + Java/clang/thales/SyntaxForm.java, Java/clang/thales/Task.java, + Java/clang/thales/syntaxforms/Abstraction.java, + Java/clang/thales/syntaxforms/CellDenoter.java, + Java/clang/thales/syntaxforms/CellLiteral.java, + Java/clang/thales/syntaxforms/Primitive.java, + Java/clang/thales/syntaxforms/Sequence.java, + Java/transform/ChangeDim.java, Java/transform/ClearDim.java, + Java/transform/CopyDim.java, Java/transform/FoldDim.java, + Java/transform/ReverseDim.java, Java/transform/Version0.java, + Modules/database/DB0.java, Modules/openGL/OpenGLCloud.java, + Modules/sound/ZZPlayer.java, Modules/test/TestClang1.java, + Modules/test/TestHuge.java: HUGE HUGE HUGE change. Global replace + all getNeighbours, getHeadcells and newCells. Now the code should + be a lot cleaner-looking... + +2000-10-17 Tuesday 11:05 Tuomas J. Lukka + + * Documentation/FAQ: Clarify who programs and who doesn't (someone + got confused) + +2000-10-17 Tuesday 08:01 Antti-Juhani Kaijanaho + + * CODING: Recommend ZZLogger. + +2000-10-13 Friday 13:52 Benjamin Fallenstein + + * Java/clang/flowing/: B.java, C.java, Primitive.java, + PrimitiveSet.java: Improve flowing + +2000-10-11 Wednesday 13:28 Antti-Juhani Kaijanaho + + * Java/clang/heraclitus/HeraclitusCommand.java: oops + +2000-10-10 Tuesday 09:03 Antti-Juhani Kaijanaho + + * Documentation/diagrams/Makefile: another merge + +2000-09-29 Friday 12:34 Antti-Juhani Kaijanaho + + * README: Demo for cat: added a space. + +2000-09-23 Saturday 12:00 Antti-Juhani Kaijanaho + + * cvsparser.pl, Documentation/ApplitudeWriters/Makefile, + Documentation/Clang_Design/Makefile, + Documentation/CyberText/Makefile, + Documentation/DesignProblems/Makefile, + Documentation/DimBased/Makefile, + Documentation/Gentle_Introduction/Makefile, + Documentation/Glossary/Makefile, Documentation/Math/Makefile: + another merge + +2000-09-19 Tuesday 10:31 Antti-Juhani Kaijanaho + + * Documentation/Glossary/gl.wml, Java/ChkVersion.java, + Java/NullZOb.java, Java/SoundObs.java, Java/ZZEvObs.java, + Java/ZZExec.java, Java/ZZKeyBindings.java, + Java/ZZKeyBindings0.java, Java/ZZObs.java, Java/ZZObsTrigger.java, + Java/ZZScene.java, Java/ZZTraverseCB.java, Java/ZZView.java, + Java/clang/ZZClangContext.java, + Java/clang/ZZClangContextVirtual.java, Java/clang/ZZClangOp.java, + Java/errors/ZZConnectWouldBreakError.java, + Java/errors/ZZError.java, Java/errors/ZZFatalError.java, + Java/errors/ZZInfiniteLoop.java, + Java/errors/ZZInvalidDimensionError.java, Java/flob/BeamDecor.java, + Java/flob/CellFlob1.java, Java/flob/ConnectionLineDecor.java, + Java/flob/SimpleBeamer.zob, Java/flob/SimpleFlobConnector.zob, + Java/flob/SpanFlob.java, Java/flob/TextDecor.java, + Java/media/Address.java, Java/media/ByteScroll.java, + Java/media/CharScroll.java, Java/media/LineBreaker.java, + Java/media/LineInfo.java, Java/media/SimpleLineBreaker.java, + Java/media/SimpleLineInfo.java, Java/media/SoundScroll.java, + Java/media/Span.java, Java/media/SpanSet.java, + Java/media/SpanTree.java, Java/media/ZZHumber.java, + Java/storage/ContentHash.java, Java/storage/ContentStore.java, + Java/storage/ContentStorer.java, Java/storage/DimStore.java, + Java/storage/FileWritable.java, Java/storage/Flushable.java, + Java/storage/GZZ0.java, Java/storage/SimpleContentFile.java, + Java/storage/SimpleDimFile.java, Java/storage/TestDimHash.java, + Java/storage/Writable.java, Java/storage/WritableIS.java, + Java/storage/ZZCacheContentStore.java, + Java/storage/ZZDimStorer.java, Java/transform/Version1.java, + Java/transform/Version2.java, Java/transform/VersionChanger.java, + Modules/extern/Extern.java, Modules/joystick/LinuxJoystick.java, + Modules/mbox/ZZDateParser.java, Modules/prez/Prez.java: another + merge + +2000-09-19 Tuesday 09:45 Tuomas J. Lukka + + * INSTALL: test lock release + +2000-09-18 Monday 14:28 Tuomas J. Lukka + + * Java/storage/: DirStreamSet.java, StreamSet.java: Add deletion of + extra cells associated with cursors + +2000-09-17 Sunday 23:50 Tuomas J. Lukka + + * Documentation/Syntaxless/synt.wml: Start writing + +2000-09-17 Sunday 23:44 Tuomas J. Lukka + + * Java/Cell.java: This doesn't have much to give any more... + +2000-09-17 Sunday 13:45 Antti-Juhani Kaijanaho + + * Java/clang/heraclitus/PrimitiveSet.java: merge again, also fixing + the brokenness of previous merge + +2000-09-17 Sunday 13:07 Antti-Juhani Kaijanaho + + * Java/BuildInfo.java.in, Java/ZZLogger.java, + Java/ZZPrimitiveCommand.zob, Java/clang/thales/DimensionNames.java, + Java/clang/thales/Evaluator.java, + Java/clang/thales/PrimitiveOperation.java, + Java/clang/thales/Refcounted.java, + Java/clang/thales/ThalesClang.java, + Java/clang/thales/ThalesProgram.zob, + Java/clang/thales/primitives/If.java, + Java/script/ZZScriptPerl.java, Modules/applet/example1.html: merge + from stable branch, does not compile + +2000-09-15 Friday 09:51 Antti-Juhani Kaijanaho + + * makedist.sh, manifest-filter.lst (ver_0_1): dist maker fixes + +2000-09-14 Thursday 16:10 Antti-Juhani Kaijanaho + + * .cvsignore, makedist.param: merge from ver_0_1 + +2000-09-13 Wednesday 15:06 Tuomas J. Lukka + + * Documentation/CyberText/: 1.png, 3.png, 4.png, ct.wml, + kello-o.png, kello.png, vilma.png: Put in new version + +2000-09-13 Wednesday 14:58 Tuomas J. Lukka + + * Documentation/CyberText/ct-old.wml: Save old version in current + tree as well + +2000-09-13 Wednesday 14:55 Tuomas J. Lukka + + * Documentation/Gentle_Introduction/zzgentle.tex: Start html + conversion + +2000-09-13 Wednesday 14:54 Tuomas J. Lukka + + * Documentation/Spec/zzspec.wml: add summary of dims (to be grown) + +2000-09-12 Tuesday 17:12 Tuomas J. Lukka + + * Documentation/UsersGuide/ug.wml: Improve + +2000-09-09 Saturday 13:37 Tuomas J. Lukka + + * Documentation/STARTING: Update + +2000-09-09 Saturday 09:32 Tuomas J. Lukka + + * Java/storage/: MultiFile.java, WriteCacheOp.java: Mark various + storage files deprecated + +2000-09-08 Friday 09:53 Antti-Juhani Kaijanaho + + * Java/clang/thales/Primitive.java: move Primitive to syntaxforms + +2000-09-07 Thursday 22:57 Tuomas J. Lukka + + * Documentation/UsersGuide/: clone1.png, clone2.png, connect1.png, + connect2.png: Add clones + +2000-09-07 Thursday 22:42 Tuomas J. Lukka + + * Documentation/UsersGuide/: bothwins.png, edit1.png, edit2.png, + edit3.png, edit4.png, rightmoved.png, showingz.png: User's guide, + first half of first draft + +2000-09-07 Thursday 18:27 Tuomas J. Lukka + + * Documentation/CellScroll/: .cvsignore, Makefile, cs.ptex: Remove + old crud + +2000-09-07 Thursday 12:34 Antti-Juhani Kaijanaho + + * Documentation/Clang_Design/thales.wml: markup fix + +2000-09-06 Wednesday 05:30 Antti-Juhani Kaijanaho + + * Java/clang/thales/.cvsignore: ignore generated file + +2000-09-04 Monday 19:10 Tuomas J. Lukka + + * Java/storage/ZZWriteCacheDimension.java: First undo test working + +2000-08-29 Tuesday 07:39 Antti-Juhani Kaijanaho + + * Java/ZZEventQueue.java: ZZEventQueue is not used anywhere + +2000-08-28 Monday 11:12 Antti-Juhani Kaijanaho + + * Java/Next.java: seems to be superseded by ZZDimSpace.IDDimension + +2000-08-27 Sunday 14:20 Benjamin Fallenstein + + * Java/ZZClangOps.java: Now what was this doing here? + +2000-08-27 Sunday 08:40 Tuomas J. Lukka + + * Java/: ZZHash.java, ZZHashObs.java, ZZViewObs.java: And some + more. Lots of evolution has been going on, apparently. + +2000-08-27 Sunday 08:37 Tuomas J. Lukka + + * Java/: ZZAbstractClient.java, ZZJavaRegistry.java, + ZZLinkRenderer.java, ZZLinkRenderer1.java, ZZRank.java: Remove more + old cruft. The nightly jars are already down to 297k from 350k... I + wonder how low we can go ;) + +2000-08-26 Saturday 21:51 Tuomas J. Lukka + + * Java/example1.html: Move it to where it should be + +2000-08-25 Friday 02:55 Tuomas J. Lukka + + * Java/TODO: Mention sf task manager + +2000-08-24 Thursday 19:21 Tuomas J. Lukka + + * Java/: ZZCanvas.java, ZZCanvasCell1.java, ZZCanvasCellBg.java, + ZZCanvasTextSpanSet.java, ZZGraphics.java, ZZPathCoordRaster.java, + ZZRaster.java, ZZTreeRaster.java, ZZVanishingRaster.java, + media/TestSpans.java, media/VStreamRenderer.java, + media/ZZCanvasBeamThing.java, media/ZZCanvasTextMark.java, + media/ZZCanvasTextSpan.java: Remove a LOT of crud! I wonder how + much the next .jar files will be smaller by... + +2000-08-24 Thursday 10:48 Tuukka Hastrup + + * Modules/database/: zz.queries, zz.sql: SQL samples we used in the + demo + +2000-08-22 Tuesday 19:46 Tuukka Hastrup + + * Modules/xml/: XML2ZZ.java, ZZXML1.java: New XML import/export is + "complete". Removing old versions. + +2000-08-21 Monday 18:12 Tuukka Hastrup + + * Java/storage/.cvsignore: Obvious ;-) One more autogenerated file. + +2000-08-21 Monday 18:10 Tuukka Hastrup + + * Java/ZZLocal.java, Java/ZZRemote.java, Java/ZZSimpleEdit.java, + Java/storage/TestScroll.java, Java/storage/ZZCellScroll.java, + Modules/xml/TestXML.java: Old test implementations of space and + related files removed. + +2000-08-19 Saturday 12:16 Antti-Juhani Kaijanaho + + * Documentation/Clang_Design/design.ptex: oops + +2000-08-19 Saturday 05:35 Tuukka Hastrup + + * Modules/database/createscript.pl: Polishing things up for a demo + +2000-08-18 Friday 22:52 Tuomas J. Lukka + + * Modules/: prez/.cvsignore, textcloud/.cvsignore: Ignore cvs + +2000-08-17 Thursday 12:56 Tuomas J. Lukka + + * Documentation/ApplitudeWriters/appw.wml: Doc changes + +2000-08-15 Tuesday 11:58 Antti-Juhani Kaijanaho + + * Java/clang/thales/README: Initial revision. + +2000-08-15 Tuesday 05:19 Tuomas J. Lukka + + * Documentation/DesignProblems/dp.wml: Solve (?) versioning problem + +2000-08-14 Monday 19:22 Tuomas J. Lukka + + * Java/TextCloud.java: Change textcloud into ZOb + +2000-08-11 Friday 10:43 Tuukka Hastrup + + * Modules/mbox/MailRaster.zob: Forgot to commit this removal. + +2000-08-10 Thursday 22:14 Tuukka Hastrup + + * Modules/mbox/.cvsignore: Renamed MailRaster to SingleMail. + +2000-08-05 Saturday 22:27 Benjamin Fallenstein + + * Documentation/misc/Curseling: Cursor selection (curseling) doc + (XXX zzspec not yet updated) + +2000-08-03 Thursday 20:41 Tuomas J. Lukka + + * Java/: ZZGlobal.java, ZZList.java: LOTS of changes: ZZObs should + work again, things should be a little faster and some things are + deprecated. I may have broken something, please tell me if I did. + +2000-07-28 Friday 08:36 Tuomas J. Lukka + + * Documentation/Spec/email1.dia: New diagram + +2000-07-27 Thursday 10:15 Tuukka Hastrup + + * Java/flob/FlatRaster.zob: Renamed FlatRaster as CompassRaster. + Shows all the connections from accursed cell. Draft + +2000-07-23 Sunday 23:39 Tuomas J. Lukka + + * Java/ZZAbstractView.java: Good riddance, once more. + +2000-07-23 Sunday 23:11 Tuomas J. Lukka + + * Java/ZZSimpleClient2.java: Good riddance, you, too ;) + +2000-07-23 Sunday 14:50 Tuomas J. Lukka + + * Java/media/ZZSoundCanvasComb.java: Start removal of swing. + +2000-07-22 Saturday 18:14 Tuomas J. Lukka + + * Java/ZZTextView.java: Good riddance ;) + +2000-07-18 Tuesday 09:34 Antti-Juhani Kaijanaho + + * Java/flob/VanishingRaster.java: Ignore generated files + +2000-07-18 Tuesday 05:21 Antti-Juhani Kaijanaho + + * Documentation/Math/math.ptex: Make the ZZSpace definition a + little more explicit. + +2000-07-17 Monday 22:02 Tuomas J. Lukka + + * Java/ZZDummyGraphics.java: Obsolete + +2000-07-14 Friday 00:15 Tuomas J. Lukka + + * Documentation/Spec/inheritparam.dia: Update + +2000-07-11 Tuesday 12:30 Tuomas J. Lukka + + * Java/clang/.cvsignore: Small tidy-ups + +2000-07-11 Tuesday 12:22 Tuomas J. Lukka + + * Java/: ZZClang1.java, ZZClangContext.java, + ZZClangContextReal.java, ZZClangContextVirtual.java, + ZZClangOp.java, ZZClangOps.pl: Move clang stuff to its own subdir + +2000-07-11 Tuesday 11:10 Tuomas J. Lukka + + * Java/: ZZConnectWouldBreakError.java, ZZError.java: Slightly more + graceful error handling. + +2000-07-09 Sunday 20:50 Tuomas J. Lukka + + * Java/RasterFlobFactory.java: Move flobstuff + +2000-07-09 Sunday 14:31 Tuomas J. Lukka + + * Documentation/README: Add keybindings + +2000-07-09 Sunday 12:20 Tuomas J. Lukka + + * Java/: Flob.java, FlobSet.java: Move flob-related stuff to flob/. + Add Renderable for decorations and as a base class. We're close + now. + +2000-07-07 Friday 18:34 Tuomas J. Lukka + + * Java/make-src-tree.sh: Doc generation patch from Tuukka + +2000-07-04 Tuesday 19:02 Tuomas J. Lukka + + * Java/FlobFactory.java: Move FlobFactory to RasterFlobFactory - + it's more for rasters than general flob stuff + +2000-07-04 Tuesday 18:25 Tuomas J. Lukka + + * Java/ZZHomeComb.java: Some flob work + +2000-07-04 Tuesday 17:40 Tuomas J. Lukka + + * Java/: ZZFlobDim.java, ZZFlobIter.java, ZZFlobIterable.java, + ZZFlobRenderer.java: Remove old attempts in order not to confuse + people + +2000-07-03 Monday 22:26 Tuomas J. Lukka + + * Documentation/Spec/: canvasraster.dia, cursor1.dia, + cursordim.dia, rasterspec.dia: Talk about rasters + +2000-07-02 Sunday 21:42 Tuomas J. Lukka + + * Documentation/Spec/zzspec.ptex: Start htmlization + +2000-06-21 Wednesday 19:34 Vesa Parkkinen + + * Documentation/CyberText/email.dia: overview, more to come. + Tomorrow... + +2000-06-13 Tuesday 11:34 Tuomas J. Lukka + + * Documentation/DesignProblems/: beamorder.dia, linkorder.dia: add + +2000-06-03 Saturday 09:41 Vesa Parkkinen + + * Modules/xml/old2xml.pl: fixes, to be cleaned + +2000-05-29 Monday 21:26 Tuomas J. Lukka + + * Modules/openGL/: Makefile, ZZOpenGLGraphics.cc: Add comments + +2000-05-26 Friday 10:14 Tuomas J. Lukka + + * Documentation/CyberText/permascroll.dia: Oops + +2000-05-26 Friday 10:08 Vesa Parkkinen + + * Modules/openGL/fi_iki_lukka_ZZOpenGLGraphics.h: some simple + code... + +2000-05-22 Monday 16:48 Tuomas J. Lukka + + * Documentation/CyberText/: rank2vert.dia, rank3both.dia: oops + +2000-05-21 Sunday 00:47 Tuomas J. Lukka + + * Documentation/CyberText/rank1vert.dia: First figure... more to + follow + +2000-05-20 Saturday 15:55 Tuomas J. Lukka + + * Java/: ZZCellRenderer.java, ZZCellRenderer1.java: Restart now + retains TextCloud window. + +2000-05-19 Friday 01:46 Tuomas J. Lukka + + * Java/ZZSingleCellView.java: Discard singlecellview + +2000-05-16 Tuesday 14:57 Tuomas J. Lukka + + * Documentation/: diagrams/ZZCanvas.dia, diagrams/cursoring.dia, + misc/RENDERING: Diagrams + +2000-05-14 Sunday 18:31 Tuomas J. Lukka + + * Java/StringScroll.java: ... + +2000-05-09 Tuesday 17:29 Tuomas J. Lukka + + * Java/: Test1.java, ZZ2DBlob.java, ZZ2DCanvas.java, + ZZ2DCanvasGridRaster.java, ZZ2DCanvasRaster.java, + ZZ2DCanvasVanishingRaster.java, ZZ2DCanvasView.java: Speedup, + cleanup + +2000-05-08 Monday 23:56 Tuomas J. Lukka + + * Documentation/misc/: billow, textcloud: X + +2000-05-08 Monday 01:37 Tuomas J. Lukka + + * TODO: ... + +2000-05-03 Wednesday 04:30 Vesa Parkkinen + + * C++/: Data.cpp, Data.h, INSTALL, Makefile, Makefile.in, + Renderer.cpp, Renderer.h, ZZ2DGrid.cpp, ZZ2DGrid.h, ZZ2DRaster.h, + ZZ2DRaster_Col.cpp, ZZ2DRaster_Col.h, ZZ2DRaster_Row.cpp, + ZZ2DRaster_Row.h, ZZ2DRaster_Soft1.cpp, ZZ2DRaster_Soft1.h, + ZZ2DRaster_Soft2.cpp, ZZ2DRaster_Soft2.h, ZZ2DRaster_SoftRow.cpp, + ZZ2DRaster_SoftRow.h, ZZCell.cpp, ZZCell.h, ZZCliComm.cpp, + ZZCliComm.h, ZZClient.cpp, ZZClient.h, ZZClientInterface.h, + ZZClientViewIf.h, ZZFileHandler.cpp, ZZFileHandler.h, + ZZFileHandlerInterface.h, ZZId.h, ZZScript.cpp, ZZScript.h, + ZZScriptAPI_1.h, ZZScriptInterface.h, ZZScriptServerInterface.h, + ZZServer.cpp, ZZServer.h, ZZServerInterface.h, ZZSettings.h, + ZZView.cpp, ZZView.h, configure, configure.in, main.cpp, main.h: + removed c++-version again : + ------------------------------------------------------------------- + --- + +2000-05-03 Wednesday 03:06 Tuomas J. Lukka + + * Documentation/misc/keys: foo + +2000-05-03 Wednesday 03:04 Tuomas J. Lukka + + * Java/ZZCanvasVanishingRaster.java: Flobs. Whew. + +2000-05-02 Tuesday 10:15 Vesa Parkkinen + + * C++/README: removed c++ version + +2000-05-01 Monday 04:21 Tuomas J. Lukka + + * Java/ZZ2DCanvasButteredRaster.java: Improve new canvas + +2000-04-30 Sunday 11:41 Tuomas J. Lukka + + * Java/: ContentHash.java, ContentStore.java, DimHash.java, + DimStore.java, DirSet.java, MultiFile.java, Recs.java, Recs.pl, + Sliced.java, SlicedOV.java, SlicedStpr.java, TestDimHash.java, + TestScroll.java, Writable.java, WritableHash.java, WritableIS.java, + WritableSet.java, ZZCellScroll.java, ZZPersistentDimSpace.java, + ZZPersistentDimension.java: More reorg + +2000-04-30 Sunday 11:36 Tuomas J. Lukka + + * Java/: Address.java, ByteScroll.java, CharScroll.java, + Scroll.java, SoundScroll.java, Span.java, SpanTree.java, + TestSpans.java, VStream.java, VStreamRenderer.java, + ZZCanvasBeamThing.java, ZZCanvasTextMark.java, + ZZCanvasTextSpan.java, ZZHumber.java, ZZSoundCanvasComb.java, + ZZSoundView.java, media/README: Reorg + +2000-04-30 Sunday 11:26 Tuomas J. Lukka + + * Java/: ZZMarkView.java, ZZMouseListener.java: Remove refs to + swing + +2000-04-13 Thursday 14:09 Tuomas J. Lukka + + * Java/ZZCompound.java: cursor + +2000-04-06 Thursday 03:22 Tuomas J. Lukka + + * Documentation/Gentle_Introduction/.cvsignore: Twid + +2000-03-28 Tuesday 12:51 Vesa Parkkinen + + * Modules/README: added applet + +2000-03-28 Tuesday 07:54 Vesa Parkkinen + + * Java/ZZApplet.java: moved to Modules + +2000-03-13 Monday 00:19 Tuomas J. Lukka + + * Java/check.pl: Make view font etc selection simpler + +2000-03-12 Sunday 10:57 Tuomas J. Lukka + + * Java/.gvimrc: Add help + +2000-03-12 Sunday 10:55 Tuomas J. Lukka + + * Documentation/Slices/SliceLogic, + Documentation/Slices/zzSliceLogic.jpg, Java/ZZSliced.java: Small + things + +2000-03-06 Monday 05:36 Vesa Parkkinen + + * Java/: Scene.java, ZZRenderer3d.java: removed 3d code + +2000-03-04 Saturday 15:45 Tuomas J. Lukka + + * Documentation/DimBased/dim.ptex: add docs + +2000-02-29 Tuesday 00:42 Tuomas J. Lukka + + * Java/ZZEdit.java: edit to space change + +2000-02-20 Sunday 17:33 Tuomas J. Lukka + + * Java/: TestXML.java, ZZXML1.java: Make XML a module + +2000-02-19 Saturday 18:06 Tuomas J. Lukka + + * Documentation/Clang_Design/.cvsignore, + Documentation/Interfacing/.cvsignore, + Documentation/Spec/.cvsignore, Java/ZZ2DGrid.java, + Java/ZZ2DGridRaster.java, Java/ZZ2DGridRasters.java, + Java/ZZ2DGridView.java: Remove 2dgrid legacy code + +2000-02-19 Saturday 18:01 Tuomas J. Lukka + + * Modules/test/README: Clang WORKS + +2000-02-08 Tuesday 00:40 Tuomas J. Lukka + + * Java/ZZ2DCanvasRasters.java: Many small things, cleaning reorg + +2000-02-03 Thursday 09:35 Vesa Parkkinen + + * Java/script/Makefile: [no log message] + +2000-02-01 Tuesday 23:06 Tuomas J. Lukka + + * Perl/README: Preparing for 0.01 + +2000-01-30 Sunday 19:39 Tuomas J. Lukka + + * Java/Package.html: Simplification of space code - preparing for + transients + +2000-01-27 Thursday 18:00 Tuomas J. Lukka + + * Documentation/Interfacing/Makefile: Doc makefiles + +2000-01-26 Wednesday 18:28 Tuomas J. Lukka + + * Java/ZZObsCaster.java: New event model ++ + +2000-01-03 Monday 02:35 Tuomas J. Lukka + + * Java/: ZZ2DGridComponent.java, ZZSimpleClient.java: Getting + there... + +2000-01-01 Saturday 00:52 Tuomas J. Lukka + + * Java/: ZZBrowse.java, ZZVCell.java: Reshaping and + undinosaurifying + +1999-12-24 Friday 16:33 Tuomas J. Lukka + + * Documentation/CellScroll/SCRATCH: Ignoring stuff... + +1999-12-24 Friday 16:30 Tuomas J. Lukka + + * Documentation/Gentle_Introduction/README: foo + +1999-12-23 Thursday 01:53 Tuomas J. Lukka + + * Documentation/Interfacing/int.ptex: Add rcs info to doc files + +1999-12-23 Thursday 01:44 Tuomas J. Lukka + + * Documentation/Clang_Design/design.pod: Change format + +1999-12-09 Thursday 16:15 Tuomas J. Lukka + + * Java/script/: ZZScriptAPI_1_JNI.h, ZZScriptPerl.cpp: Minor + JNIPerl fixes + +1999-12-09 Thursday 13:13 Tuomas J. Lukka + + * Java/script/: ZZScriptAPI_1_JNI.cpp, invoke.c: foo + +1999-12-09 Thursday 01:31 Tuomas J. Lukka + + * Java/script/ZZId.h: Start jni-perl + +1999-12-04 Saturday 18:01 Tuomas J. Lukka + + * Documentation/: PROTOCOL, misc/ADDRESSING, misc/TORESOLVE: foo + +1999-12-04 Saturday 17:37 Tuomas J. Lukka + + * LICENSE.lgpl, LICENSE.xpl, VERSION, Perl/PerlServImpl.pm, + Perl/ZZPerlDBServ.pm, Perl/ZZPerlServ.pm, + Perl/ZZPerlSimpleClient.pm, Perl/cperl.pl, Perl/sperl.pl: foo + diff --git a/Documentation/ApplitudeWriters/Makefile b/Documentation/ApplitudeWriters/Makefile new file mode 100644 index 0000000..05b5117 --- /dev/null +++ b/Documentation/ApplitudeWriters/Makefile @@ -0,0 +1,10 @@ +DIAGRAMS=../wmlinc/article.wml +# rank1vert.png rank2vert.png rank3both.png permascroll.png + +all: appw.html appw-ns4.html + +appw.html: appw.wml $(DIAGRAMS) + +appw-ns4.html: appw.wml $(DIAGRAMS) + +include ../lib.mk diff --git a/Documentation/ApplitudeWriters/appw.wml b/Documentation/ApplitudeWriters/appw.wml new file mode 100644 index 0000000..6eb0861 --- /dev/null +++ b/Documentation/ApplitudeWriters/appw.wml @@ -0,0 +1,90 @@ + + + +{: [[s/\bZZModule\b/\1<\/code>]] + + + + Applitude Writer's Guide + +#include '../wmlinc/article.wml' + + + + + +

Applitude Writer's Guide

+
$Id: appw.wml,v 1.1 2000/08/17 12:56:45 tjl Exp $
+ + Tuomas Lukka
+
+ + + +
+ + + + + + +Applitudes are the preferred way of including more functionality into +GZigZag. This document explains how they are written. + + + +

Introduction

+ +

+ An applitude is basically a view and related actions. + +

ZZModule

+ +

+ The ZZModule abstract class provides the basic mechanism for + including Java code into GZigZag without having to modify and/or + recompile GZigZag. GZigZag uses the Java reflection API to connect + to new modules. + +

+ The ZZModule architecture is slightly different than one might + expect: instead of directly inheriting from the class, + modules use a static member which is a ZZModule: for example, + +

+public class TextCloud implements ... {
+	...
+	static public ZZModule module = new ZZModule() {
+		public void action(String id, ...) {
+			... execute action id
+		}
+		public ZOb newZOb(String id) {
+			... return a new ZOb instance with the given
+			    name
+		}
+	};
+}
+
+ + +
+ + + +:} + + + diff --git a/Documentation/CellScroll/SCRATCH b/Documentation/CellScroll/SCRATCH new file mode 100644 index 0000000..1215701 --- /dev/null +++ b/Documentation/CellScroll/SCRATCH @@ -0,0 +1,8 @@ + + +As a synching method, it is made so that the file is +4k-aligned, i.e. no records (except those that are longer than 4k by themselves) +are allowed to cross a 4-k boundary. Zero padding is added to fill +the gap. This of course requires that the first byte of a magic no is never +zero --- then a zero can be interpreted to mean ``jump to the next 4k limit''. + diff --git a/Documentation/Clang_Design/Makefile b/Documentation/Clang_Design/Makefile new file mode 100644 index 0000000..bdd274d --- /dev/null +++ b/Documentation/Clang_Design/Makefile @@ -0,0 +1,11 @@ +DEP=../wmlinc/article.wml + +all thales: thales.html thales-ns4.html + +thales.html: thales.wml $(DIAGRAMS) $(DEP) + +thales-ns4.html: thales.wml $(DIAGRAMS) $(DEP) + +ps: design.ps + +include ../lib.mk \ No newline at end of file diff --git a/Documentation/Clang_Design/design.ptex b/Documentation/Clang_Design/design.ptex new file mode 100644 index 0000000..4610a74 --- /dev/null +++ b/Documentation/Clang_Design/design.ptex @@ -0,0 +1,456 @@ +% BE SURE TO EDIT design.ptex -*- LaTeX -*- +\documentclass{article} + +\usepackage{rcs} +\RCS $Date: 2000/08/19 12:16:43 $ +\RCS $Revision: 1.9 $ +\date{Rev.\RCSRevision~~\RCSDate} + +\title{Clang Design Document} +\author{Tuomas J. Lukka\and Antti-Juhani Kaijanaho} +\begin{document} +\maketitle + +\newcommand{\zz}{ZigZag} + +\section{Introduction} + +.PS +box "Clang" ht 0.25 +.PE +$$\box\graph$$ + +A cellular language, based on the structure of ZigZag has been in Ted Nelson's +plans all along. This document attempts to clarify the various issues in +Clang's design and propose various solutions. + +\subsection{The role of Clang} + +The exact role of Clang in the various uses of \zz\ is still unclear. +The \zz\ system will interface to a wide variety of languages (currently +Java and Perl), and all these can be used to perform various tasks. + +One possible role is as a beginners' language, especially if good visualizations +and ways to write programs in Clang are devised. + +Another possibility is as a kind of device-independent +virtual machine from which code can be compiled to a faster representation +or directly interpreted. + +A further possibility (one being realized right now (Dec.1999)) is a +least-common-denominator scripting language, allowing a simple pure Java +implementation of \zz\ for demonstrations as well as practical use, without +requiring the recipient to set up many libraries and interpreters. + +The ability to record macros directly from user input is a great thing. + +\subsection{Relevant ZigZag features} + +In this section, we shall look at some of the less obvious features +of \zz\ that might be useful. + +\subsubsection{Intersections} + +One of the important operations in ZigZag that is quite relevant +to Clang is the ability to take intersections of ranks. +As an example, this can be used to find an entry at the intersection +of a row and column in a traditional 2-dimensional table. +Of course, as often is with ZigZag, there is a twist: there may be +many different intersection points, since the relationships between +the different ranks are not restricted on a global level. + +For most of Clang we are however only interested in single +intersection points, e.g. to find the value of a given variable in +a give stack frame or the code for a given virtual method in an object. + +Eventually, the server should allow requests to store tables +of intersections so that certain predefined sets of intersections can +be found in $O(1)$ time instead of the most general $O(N+M)$ where $N$ +and $M$ are the lengths of the two ranks (you get $O(N+M)$ instead of +the horrible $O(NM)$ through using a hash table). +However, this is not yet implemented. + +\subsubsection{Clones} + +Clones are quite an interesting concept. Basically, they are just +cells that are on a rank on \texttt{d.clone} with the ``original'' as +the headcell. What is important about clones is the two implications: +the visual and the semantic. The visual implication is that +the rest of the cells will always show the same contents as the +headcell and all modifications are done to the headcell, not the clones. +The semantic implication is more important: it says that the clones +are somehow \emph{same} as the original. + +As with the intersection above, clones can be used e.g.~to clone +method names from an interface to an implementation or something like that. + +But now, the important thing to realize about clones is that they +are special only in these two senses and that we can, if we need +(and we will, as you'll see), define other dimensions with similar +properties. + +\section{Global goals} + +\subsection{Structure-based referencing} + +The most fundamental thing about Clang is that references to various +structures are structure- and not name-based. Thus, a variable is +defined by a cell, which is e.g. cloned along \texttt{d.clone} or some +other suitable dimension to all the places in a subroutine where it +occurs. + +This makes easy many of the functionalities that the so called +Integrated Development Environments (IDEs) work very hard to provide +such as jumping to the definition of a variable or subroutine. +Also, along with some special rasters the structure allows many +useful visualizations of the resulting program structure. + +The question this change raises, of course, is development speed. +Will it be significantly slower to write Clang code than corresponding +Java code? However, some consideration shows this point to be moot: it +is not at all difficult to come up with suitable macros so that Clang +can be \emph{written} like a normal name-based language, but where at +the moment of writing the interpretation to structure takes place. + +\subsection{Compilability} + +Clang code should be relatively easily compilable into a strongly-typed +language such as Java in order to gain execution speed. + +\subsection{Simplicity} + +Ideally, Clang should be simple so that even a beginner is able to write +simple scripts. + +\subsection{Power} + +However, many simple languages lack the power to do complicated things. + +\subsection{Self-implementability} + +To ensure Clang's power as a general-purpose structural language, it should +be possible to completely implement a Clang interpreter using Clang itself. +The only potential problem for this is the dimension along which cell +pointers are used (see Cell pointers below). + + + + + +\section{Interesting ideas} + +\subsection{Visible stack} + +Stack frames can be represented as sets of clones from the local +variables (along a different dimension from the cloning to the references +to the variable in the code). + +Then, the primitive rank-intersection operation in ZigZag can be used +to find the value of a local variable in a stackframe or thread. + +\subsection{Trace} + +A trace of executed code can easily be shown on a dimension, with +relation cells if necessary, along with information about the status +of data at any point. On the other hand, in a fully versioning ZigZag +space the whole history of the state of the space is conserved throughout +the execution (although this may not be wise for complicated scripts +where the space overhead would grow too much -- there only the space being +operated on should be versioned and even that possibly at the beginning +and the end of a script run). + +\subsection{Objects and virtual tables} + +It is delightfully simple to do objects and virtual tables using the +ZigZag structure. + +Quite simply, a virtual interface can be defined simply as a rank of +cells and a type implementing them will have the methods' implementations +start on the intersection of the cell describing the type and the cell +naming the method. + +As an interesting side, since the pointers are bidirectional it is always +possible to find all the instances of a given class or traverse +structures both ways, something that +programmers in more traditional languages would never dream of. +Naturally this comes at a some performance penalty but the coherence +of the structure makes finding bugs in programs far easier. + + + + + + + + + +\section{Questions} + +\subsection{Context} + +How much context should the virtual machine have? +This is an important issue for short scripts +which should be definable with the minimum effort. +Ted says (and I agree) that it should be at least a cursor and three +dimensions (also as cursors), i.e. a viewspex. + +\subsection{Cell pointers} + +A variable should in general hold a pointer to a cell (possibly also +a direct value +but this could just as well be implemented as a temporary cell). + +The problem here is clean self-referencing: how can all the cells involved +in a cell pointer structure be referenced in another cell pointer structure? + +SUGGESTION1: "Local" dimensions? This would lead the ZigZag model closer +to a model of ordered triplets of cells... + +SUGGESTION2: Use the same cursor mechanism (the two dimensions \texttt{d.mycursor} +and \texttt{d.cursor} as the rest of GZigZag). + +\subsection{Parameter passing} + +\subsection{Expressions} + +A rather neat way of doing expressions for parameter passing +to primitives and functions: +the first cell on \texttt{d.1} gives the primitive or function to call. +Then, on \texttt{d.1} come the parameters - either directly \emph{or} if +they are connected along \texttt{d.mycursor}, using cursors (global variables) +\emph{or} if they are connected using \texttt{d.clone} to a parameter cell, +that parameter. + +However, this is only the beginning: from each parameter, you can +start a path down on \texttt{d.2}, which would mean + +\subsection{Exceptions} + + + +\subsection{Typing} + +Typing for Clang is a difficult issue. +On the one hand, Perl-like weak typing would suit the ZigZag paradigm +quite well but on the other hand, compiling a strongly typed program +into e.g. Java is much easier as well as much more efficient. + +SUGGESTION: Have two different languages (Clang and Cling?), one +strongly and one weakly typed. The one we would first define is +the weakly typed one which is generally easier to use for humans. + +POSSIBLE IDEA: Dynamically type cell content in Perl style (assign +dynamically a union of types to a cell based on an analysis of the +content, for example whether the content string can be parsed as a +number), but have statically typed cell references. We'll need here a +powerful type system (look into type theory, Hindley-Milner typing +etc), a Java-like type system would probably kill this idea. + +\section{Extra-primitive Clang} + +XXX This is NOT what is implemented - see the next section!!!! + +This section describes the very first steps taken towards +a cellular language since one is now needed in a hurry to get +a pure Java implementation of \zz\ out soon (Dec.1999) + +This is a testbed-version only and any or all features may be broken +by further versions. Especially the dimensions may be changed (the first +version tries to use as few as possible to facilitate viewing on the +current primitive rasters). +This version has no expressions so it is rather like an assembly +language instead of a scripting language. + +That said, let's begin. + +First of all, we shall have subroutines or procedures. +They are defined by a cell with the name of the subroutine, +which has some cells on {\tt d.args} describing the arguments the +routine requires. The cells on {\tt d.args} will be cloned later +to refer to the arguments (structural reference). +NOTE: there is a potential problem here: we also want to be able +to clone parameter sets for virtual methods and standard routines, +e.g.~for keybindings). Thus, the cloning dimension may change. + +Negwards on {\tt d.args} (later, with better visualizations, on +{\tt d.retval} or somesuch) are the return values of the subroutine. + +The next cell from the main subroutine cell on {\tt d.xeq} is +a clone of the cell {\tt VAR}, introducing the local variables just +like usual languages. + +After this, on {\tt d.xeq} the body of the subroutine follows. +The cell on {\tt d.xeq} is a clone of the operation (or subroutine) +cell and +like above, {\tt d.args} contains the parameters (clones of +the parameter or variable cells) that are given to the operation, +and negwards are the return values. + +\begin{figure} +{ +\tt +.PS +linewid=0.15; +lineht=0.15; +boxwid=0.55; +SUM: box "sum" ht 0.25; line; DIFF: box "diff" same; line; +SH: box "sumdiff" same; line; X: box "x" same; line; Y: box "y" same; +move to SH.s; down; line; box "VAR" same; line; +PLUS: box "+" same; line; +MINUS: box "-" same; +move to PLUS.e; right; line; X2: box "x" same ; line; Y2: box "y" same ; +move to MINUS.e; right; line; X3: box "x" same ; line; Y3: box "y" same ; +move to PLUS.w; left; line; SUM2: box "sum" same; +move to MINUS.w; left; line; DIFF2: box "diff" same; +spline from X.s then down 0.1 right 0.1 then down 0.2 left 0.2 to X2.n; +spline from Y.s then down 0.1 right 0.1 then down 0.2 left 0.2 to Y2.n; +spline from X2.s then down 0.05 right 0.02 to X3.n; +spline from Y2.s then down 0.05 right 0.02 to Y3.n; +spline from SUM.s down 0.1 then right 0.65 down 0.1 to SUM2.n +spline from DIFF.s down 0.3 then left 0.65 down 0.1 then down 0.4 to DIFF2.n +.PE +\box\graph +} +\caption{A simple Clang routine {\tt sumdiff} +that calculates the sum and difference +of two numbers by calling the more primitive {\tt +} and {\tt -} +operations. Horizontally we see {\tt d.args} and vertically {\tt d.xeq}. +The curvy lines indicate clones along {\tt d.clone}.} +\end{figure} + +The model used to store the parameters is, as alluded to above, difficult, +as it will be difficult to accommodate the self-referentiality and +self-implementability. +For the extra-primitive version, we'll just make do with Clang pointers +being ordinary relcells. +Parameters are passed by value. + +\begin{figure} +{ +\tt +.PS +boxht=0.25 +SUM: box "+"; line; X1: box "a"; Y1: box "b"; +move to SUM.s; down; line; +SUMDIFF: box "sumdiff"; move to last box.e; right; +line 0.5; X2: box "x"; Y2: box "y" +move to X1.s ; line to 2/1 of the way between X1.s and X2.s; down; box "Param1"; +move to Y1.s ; line to 2/1 of the way between Y1.s and Y2.s; down; box "Param1"; +.PE +\box\graph +} +\caption{The stack of the virtual machine at the call to the {\tt +} +operation. +We see vertically {\tt d.stack}, horizontally {\tt d.args} +and diagonally {\tt d.clangref}. +Note that the cells {\tt +}, {\tt sumdiff}, {\tt a}, {\tt b}, {\tt x} and +{\tt y} are clones of the cells defining the procedures. +The result cells are not shown, they are referenced the same way +except through {\tt d.clangretref}, in order to allow passing of +variables by reference. +} +\end{figure} + + +\section{Clang1} + +This section describes the first clang, called Clang1 to distinguish. + +The basic concepts are as above: execution down {\tt d.2}, +parameters and formal parameters (prototype) on {\tt d.1}, +parameters by cloning. + +However, there is one important detail which makes programming easier. +This is the concept of ``it'' which is one cell that is in a special +case position. This can later be extended to a stack, if it is felt that +that is appropriate but that might not be quite as helpful (we do not want +FORTH, do we?). Now, this concept is there so that it is simple +to express paths from cells, to be used as expressions. + +Now, all scripts are associated with a viewspecs cell that contains +at least a cursor and usually some dimensions. +The cursor is then equated to the ``it'' so on the main level, moving +``it'' corresponds to moving the cursor (possibly optimized so that the +cursor is moved once, at the end of the script). + +\begin{figure} +\caption{ +An expression as a parameter to an operation. +The main operation is {\tt Op}, the cell we start from is {\tt v}, +and we use a route that takes us to the cell representing the dimension +that the view whose maincell is {\tt v} is showing on the Z axis +(the cursor three steps on {\tt d.dims} from the maincell). +} +{\tt +.PS +box "Op"; arrow; box "v"; +down; move to last box.s; +arrow; +STEP: box "step"; +right; move to STEP.e; +arrow; box "d.dims"; arrow; box "+3"; +.PE +\box\graph +} +\end{figure} + +In the first implementation, to make it as fast as possible to implement +(and to save some space since the current cellscroll does not support +transient cells), the stack is not stored in the structure. This is +unfortunate but since no semantics change, it is quite simple to change +this later. + +As some examples, we'll implement some operations here explicitly in +Fig.~\ref{fig:ops} +\begin{figure} +\caption{\label{fig:ops} +Some operations. a) move poswards on the X axis. b) advance the X dimension +to the next on the X dimlist. c) One possible alternative, allowing the +user to clone "X" only once by expressing the cursor to use negwards on d.1. +In this case, the {\tt SETC} operation would not be necessary at all. +} +{\tt +.PS +STEP:box "STEP"; line; box "X"; line; box "+" +move to STEP.s; line down; +move to STEP.n; line up; +.PE +a)\box\graph\\ +.PS +STEP: box "SETC"; line; box "X"; line; box "X"; +down; move to last box.s; line; box "STEP"; +right; move to last box.e; line; box "d.2"; line; box "+" +move to STEP.s; line down; +move to STEP.n; line up; +.PE +b)\box\graph\\ +.PS +box "X"; line; STEP:box "STEP"; line; box "d.2"; line; box "+" +move to STEP.s; line down; +move to STEP.n; line up; +.PE +c)\box\graph +} +\end{figure} + +\section{Greek Clang} + +My (Antti-Juhani's) intention is to build several parallel prototype +versions of Clang. Since the version of Clang which will be adopted +might well use ideas from several orthogonal Clang prototypes, these +``Greek Clang'' prototypes are not successive versions, improving one +another, but separate parallel ventures into the design space. Thus +they will not be version numbered; instead I'm going to name them +after ancient Greek philosophers. + +\subsection{Thales Clang} + +Thales Clang is a small nonstrict, weakly typed procedural-functional +language with a design in many ways owing to Lisp and nonstrict +functional languages. + +\end{document} + + +% +% vim: set syntax=tex : diff --git a/Documentation/Clang_Design/thales.wml b/Documentation/Clang_Design/thales.wml new file mode 100644 index 0000000..8b6c88f --- /dev/null +++ b/Documentation/Clang_Design/thales.wml @@ -0,0 +1,187 @@ +# -*- HTML -*- + + + +# FIXME + + %body +

%body

+
+ +

%body

+
+ +

%body

+
+ +#include '../wmlinc/article.wml' +Thales Clang Draft Spec +
$Id: thales.wml,v 1.4 2000/09/07 12:34:24 ajk Exp $
+ + + Antti-Juhani Kaijanaho
+ gaia@iki.fi
+ Dept. of Mathematical Information Technology
+ University of Jyväskylä +
+
+ + +

+WARNING! This document is extremely unstable. You +should not depend on any of it to remain as it is. +

+ +Introduction + +

+ +The ZigZag Structure + +

+ +

+The ZigZag structure consists of cells, cell content and connections +between cells along dimensions. Each cell has content (either a +string or a span), and cells are connected along dimensions. +Dimensions have unique names. Dimensions have two directions: the +positive direction and the negative direction. A cell may have at +most one connection along a dimension on a direction. The term +posward means the positive direction and the term +negward means the negative direction; in English text they are +used analoguously to such terms as rightward and upward. A particular +instance of the ZigZag structure is called a ZigZag space. +

+ +Cell references in ZigZag: the cursor mechanism +

+ +Thales Clang Syntax + +

+Thales Clang has six syntactic forms: cell literals, +primitives, cell denoters, applications, +sequences and abstractions. Instances of these +syntactic forms are called expressions. +

+ +

+All expressions have an identity cell, a cell that denotes the +expression as a whole. The identity cell of all expression is a +member of a rank along the dimension d.thales-syntactic-form. +The headcell of that dimension determines the syntactic form of the +expression. An expression can incorporate another expression as a +subexpression by incorporating in its structure a clone of the +subexpression's identity cell. +

+ +Cell literals + +

+A cell literal is a cell that statically represents a cell. It is its +own identity cell. The cell literal refers to the cell in the +structure that it represents, using the cursor mechanism. +

+ +Primitives + +

+A primitive is a cell that represents a primitive operation +implemented outside Thales Clang. It is its own identity cell. +

+ +

+Primitive cells are mapped to their implementations using the +following mechanism. From the home cell, a rank along +d.thales-primitives enumerates all known primitives. Each +primitive cell is connected posward along +d.thales-primitive-binding to a cell whose content is a magic +cookie (a string) used to identify the primitive. +

+ +Cell denoters + +

+A cell denoter is a cell that dynamically represents a cell. It is +its own identity cell. It is an error for a non-clone cell denoter to +appear as a subexpression outside the abstraction parameter list (see +section~). +

+ +Applications + +

+An application expression is a rank of cells along +d.thales-application. The cells in that rank must be identity cells +or clones of identity cells. The identity cell of this expression is +the headcell of the rank. The headcell of the rank must be a clone of +the identity cell of either a primitive expression or an abstraction +expression. +

+ +Sequences + +

+A sequence expression is a rank of cells along +d.thales-sequence. Its identity cell is the headcell of that +rank, and the rest of the cells must be clones of identity cells of +identity cells or identity cells of application expressions. +

+ +Abstractions + +

+An abstraction expression is a subspace generated by the expression +identity cell with respect to the dimensions +d.thales-sequence and d.thales-application. +

+ +

+The rank along d.thales-application from the identity cell +excluding the identity cell itself and the posend cell of the rank +contains a list of formal parameters for this abstraction. The posend +cell of the rank must be an identity cell of another expression, known +as the body of the abstraction. +

+ +Informal semantics + +

+The mechanism by which an application expression whose identity cell +is a clone of a primitive is evaluated is implementation-defined. +

+ +

+An application expression whose identity cell is a clone of the +identity cell of an abstraction is evaluated as follows: +

+ +

+The subexpression denoted by the headcell of the expression rank is +evaluated. The resulting value will be an abstraction. A fresh +environment is created with exactly as many positional slots as the +abstraction value has parameters and one ``inherited environment'' +slot. The environment captured by the resulting abstraction value is +bound to the ``inherited environment'' slot of the fresh environment. +The rest of the cells in the application rank are evaluated in +negative-to-positive order and the results are bound to the +corresponding positional slots. A fresh activation record is created, +and the fresh environment is bound to its environment slot. The +current active activation record is bound to the fresh AR's saved AR +slot. The fresh AR is made current active AR. The body of the +abstraction is now evaluated. The AR in the current active AR's saved +AR slot is made current active AR. The result of this evaluation is +the result value of the body. +

+ + + diff --git a/Documentation/CyberText/1.png b/Documentation/CyberText/1.png new file mode 100644 index 0000000..3fef463 Binary files /dev/null and b/Documentation/CyberText/1.png differ diff --git a/Documentation/CyberText/3.png b/Documentation/CyberText/3.png new file mode 100644 index 0000000..fe0a030 Binary files /dev/null and b/Documentation/CyberText/3.png differ diff --git a/Documentation/CyberText/4.png b/Documentation/CyberText/4.png new file mode 100644 index 0000000..184b262 Binary files /dev/null and b/Documentation/CyberText/4.png differ diff --git a/Documentation/CyberText/Makefile b/Documentation/CyberText/Makefile new file mode 100644 index 0000000..e476a74 --- /dev/null +++ b/Documentation/CyberText/Makefile @@ -0,0 +1,11 @@ +DIAGRAMS=../wmlinc/article.wml \ + rank1vert.png rank2vert.png rank3both.png permascroll.png + +all: ct.html ct-ns4.html + +ct.html: ct.wml $(DIAGRAMS) + +ct-ns4.html: ct.wml $(DIAGRAMS) + +include ../lib.mk + diff --git a/Documentation/CyberText/ct-old.wml b/Documentation/CyberText/ct-old.wml new file mode 100644 index 0000000..3625582 --- /dev/null +++ b/Documentation/CyberText/ct-old.wml @@ -0,0 +1,911 @@ + + + + + + GZigZag: a platorm for Hypertext experiments + +#include '../wmlinc/article.wml' + + + + + +

GZigZag: a platorm for Hypertext experiments

+
$Id: ct-old.wml,v 1.1 2000/09/13 14:58:08 tjl Exp $
+ + Tuomas Lukka
+ lukka@iki.fi
+ Dept. of Mathematical Information Technology
+ University of Jyväskylä +
+ Vesa Parkkinen + + Katariina Ervasti + and + Ted Nelson +
+ + + + +

+This is a preprint of an article to appear in the Cybertext Yearbook 2000, +edited by Markku Eskelinen & Raine Koskimaa, to be published by Research Unit +for Contemporary Culture. +All trademarks are the respective trademarks of their owners. + + + + +We present a short summary of the ongoing work at the Hyperstructure Group +in Jyväskylä University. +We are interested in structures that currently dominant software +paradigm makes difficult +or impossible to express or edit. +For example, current operating systems are fixated on files and directories +which could be replaced by a much more flexible and more +fine-grained structural system. +For many applications it would be useful to keep track of where text +has been copied from via cut&paste. The current paradigm does not support +this but e.g. the Xanadu88 paradigm does. +Additionally we are interested in useful visualizations of these structures. + +Most of our work is based on Nelson's ZigZag +structure, and we have a prototype program GZigZag on which various +variations are tried. + + + +

Introduction

+ +

+This article attempts to give an overview of the activities of the +Hyperstructure Group at the University of Jyväskylä. +The group, founded in fall-99 is focused on a long-term collaboration +with Ted Nelson and implementing and testing +his ZigZag design and some Xanadu designs. + +

+The most basic idea +underlying all of our work is that today's computers do not +allow the user to store and visualize most of the real structure of +his information. +An interesting feature of this problem is that it is never visible +on a small scale, with a few documents or files. On a small scale, the human +brain is able to superimpose the true structure of the data on the +structure forced by the computer (filenames and directory hierarchies). + +

+Unfortunately, most software is only tested with small amounts +of example data in the prototype stage. +If there are hundreds of documents, modified by dozens of people, +it is easy to fall into chaos unless the true structure of the data +is used. One simple example of such true structure is that of origination(XXX): +being able to track all text across several cut&paste operations and +visualize this makes it simple to see what rearrangements other people +have done on a piece of text after having seen it last time. + +

+Our work is based on Nelson's ZigZag structure XXXREF, introduced below. +We often use the term ``ZigZag structure''. This is an approximation: +ZigZag is in a sense a metastructure with which it is easy to model any +structure, even structures that would be difficult to model on paper +or on usual computer programs without a special program designed explicitly +for that structure - for example a family tree. + + +

Basics of ZigZag

+ +

+ZigZag is a new way of putting information into computers, kind of a crossing +between a database, a filesystem, a personal information manager and +many others. And even that isn't sufficient to describe it: it's simply +something new. +There are two important differences between systems built on ZigZag +and "normal" computer systems. + +

+First of all, files and directories are unnecessary (REF paradigms). +A traditional filesystem uses filenames to refer to large chunks of +information and possibly HTML-like anchors to refer to smaller pieces +inside the files. This is a fragile way of representing the information +since the only structure stored by the system is the files based +on the names - finding which files reference a given file is timeconsuming +or requires a pre-indexing scheme. +ZigZag is a flexible hyperstructure, allowing different micro-level +connections between various pieces of information. +In ZigZag all references are two-directional and do not work through +user-visible namespaces. Rather, the micro-level two-directional +referencing is built right into the system. Changing some of +the connections of a piece of information (e.g. renaming the "file" it +is inside in the listing) will leave the other connections unchanged. + +

XXXXX +Second, in ZigZag, all +the information about the system will be stored in the same structure. +In Windows, there is a filesystem and separately from it, there is the +registry. In UNIX, there is just the filesystem with configuration +information for applications being represented as text files inside +the same filesystem; same tools can be used to edit normal text files +and configuration files. +ZigZag takes this a step further: all information is in the same fine-grained +structure instead of the coarse "file-grained" structure. +The same tools can be used to edit any part of data on the system, be it +metadata, configuration information, user interface bindings or a spreadsheet +or document. XXX selitä paremmin + +

Cells and dimensions

+ +
+ Two ranks on d.2. The rules of the ZZ structure + are that each cell may only be on one rank along a given dimension. +
+ +
+ Two different ranks involving some of the same cells, on + a different dimension d.1 +
+ +
+ One possible way to flatten the ranks of the two previous + figures to show both dimensions at once. Note how the structure + feels locally spreadsheet-like at each cell but globally + the connections between the cells must curve when flattened + to a 2-D plane. +
+ +

+ In ZigZag, all data is in cells, much like a spreadsheet. + The only important difference is that while a spreadsheet enforces + a two- (or possibly three-) -dimensional lattice structure + between the cells, ZigZag allows the cells to be connected in + a much freer way. + +

+ First of all, the number of dimensions is unlimited. + Like on a spreadsheet, a dimension is still structured so that + each cell may have one predecessor and one successor on each + dimension, and the converse relationship "A is B's successor + implies B is A's predecessor" holds. + However, there are no restrictions between the dimensions + for the connections: for example, in the figure, + the cell A is located two steps right and three steps up + from itself (right = d.1, down = d.2). + +

+ To manage the potentially infinite number of dimensions, + they are referred to with descriptive strings. + The most commonly used dimensions are the three general-purpose + dimensions d.1, + d.2 and d.3 and then d.clone, + used for logical duplication of cells and d.cursor, used + for pointing. These uses are mostly a matter of convention. + +

+ The strength of using dimensions instead of names (as in filenames) + or numbers (as in pointers or references) to refer to other + information is that all references are two-directional. + This is an important feature since a large fraction of programming + errors in languages such as HTML or C++ have to + do with referring to things + that are no longer there: on WWW, moving a page or changing the + name of an anchor on a page breaks all links to that page or anchor, + because the links are strings, naming the previous location. + In C++, the references are pointers, i.e. numbers representing + memory addresses: if the object being referred to is not any + more at the given address, the program crashes. + ZigZag introduces the concept of connection + on a primitive level and obviates the need for making new systems + of referencing for each new program. XXX + +

+ There are many different possible structures with similar + capabilities. What makes ZigZag special is the beautiful tradeoff + between simplicity and complexity: each cell's neighborhood + is limited by the two-neighbours-per-dimension rule but further + away the cells can be connected to each other in a free fashion. + +

Rasters and operations: the default UI

+ +

+ Given the complexity of the structure, it is usually impossible + to see it all at once. Focus&context methods (XXXREF) are + useful for simple visualizations: two or more dimensions are + chosen, and the cells near the user's focus (cursor) are + laid flat on the screen using those dimensions, as far as is + possible within the limits of the structure. Since the structure + locally resembles a spreadsheet, this visualization is extremely + navigable, especially with animation between the motions. + +

+ There are several different possibilities for choosing which cells + to place where, called rastersXXX. + The vanishing raster, for example, renders all cells + up to a given number of steps from the cursor, while + gradually reducing the size of the cells. This gives the user a good + picture of what is happening slightly further along in the structure + and uses the depth perception cues of the human eye to a great + advantage. There are also rasters based on rectangular grids, + with the two most important ones being the vertical and horizontal, + which + Examples of these rasters showing a looping structure are shown in + XXX. + +

+ Motion is performed through the keyboard or the mouse. + Many simple edit operations take directions as parameters, + so for instance, creating a new cell leftwards from the current + cursor is achieved by pressing n and then the same + key that normally moves the cursor left (l). + + +

+ The basic operations include connecting and disconnecting cells, + moving the cursor, rotating the view (choosing different dimensions + to show on the X, Y and Z axes) and modifying the text in a cell. + There are also some more complicated operations that are especially + useful, such as hop, an example of which is shown in XXX. + +

Totality of the structure

+ +

+ Currently, computers are complicated and messy. + Application code has to worry about the structure of data on + disk, the structure of data in memory, and the structure of data + held by the operating and windowing systems. + All these are usually different and cause applications to + translate between each other, making the application overtly + complicated. + +

+ ZigZag represents all this data in the structure: the structure is + persistent and unified. + Just as with virtual memory, + the program does not need to care whether a cell + is in memory or on disk. The logical structure + is the same. Of course, to retain an acceptable level of performance, + solutions such as transient cells or saving only every n + seconds have to be devised but these are optimizations rather + than fundamental structure of the application. + +

+ The unification of the structure is more difficult to explain + since it reflects a completely different mindset from the ordinary. + Ideally, the lower-level code which takes the structure and renders + it on screen will have to know only one cell. + From this cell, it uses the structure to find what windows are + where, which cells to show + in the centers (via d.cursor) and which dimensions + to raster along (also via the structure). + +

+ This greatly simplifies programming in ZigZag since all + operations can be expressed as alterations to the structure. + For example, when the user presses a key to move the cursor left, + what happens is that the callback code looks through the structure + to see which dimension is currently "left-right", then looks + for the cursor and the cell leftwards of it. Finally, the code + connects that cell in the structure so that it will thereafter + be interpreted as the cursor. + +

+ There are many other benefits as well: since all operations + are in the structure, scripting becomes trivial since everything + can be achieved simply through modifying the structure. + +

+ Unification of data is not a new idea: the original + UNIX philosophy of "everything is a file" contains some of the same + spirit. However, the UNIX APIs still force the loading of files + into memory into a different representation; in ZigZag, the cell + structure is all you need. + +

+ Another previous version of the same basic idea is the + popular Model-View-Controller paradigm (XXXREF), where a program + with a user interface is split into a model and + user interfaces (views and controllers) to that model. + This structure makes it simple to add a new view to the same data. + ZigZag takes this approach to new heights by providing a + global model which all features of the visible display + use. + +

Permascrolls

+ +

+ Permascrolls are a concept that originated in Xanadu88 (XXX???). + The essential idea is that whenever a piece of fluid media + (i.e. text, audio, video, image) enters the system, it is assigned + a permanent identifier. After that, all references to that + piece of media go through that identifier so that it is easy to find + where a particular piece of text has been cut&pasted to, for example. + +

+ Permascrolls seem to be the most easily misunderstood part of + Xanadu88 because with today's web, confusing the physical + location and the identity of a document is easy. A permascroll + does not mean that all information should only be + stored in one place. It is not an URL, but more like an URI: it + is an identifier which is known to map to the same information + always. It is also more fine-grained than run-of-the-mill W3C + URIs, as it allows referencing any subset of the original up to + an atomic level. + Most commonly it is not single atoms in the permascroll that + are referred to; rather, the reference type is + span, which is a reference to a single contiguous piece + of a permascroll. + +

XXX SELITÄ VSTREAM HETI + In the permascroll paradigm, a particular version + of a "document" is represented as a vstream: a list + of spans. Editing a document then consists of adding a new + span, splitting existing spans, deleting existing spans and + rearranging spans. + +

+ Two different versions of a document using vstreams + and permascrolls. The second version is produced from the + first by a rearrangement and an insertion. + When comparing the two versions side by side, it is + easy to determine + which parts are the same and simply have been rearranged + by comparing the references to the permascroll. +
+ +

+ ZigZag supports permascolls by allowing a cell to contain + a span (a reference to a single + contiguous piece of the permascroll). + A rank of cells on a dimension (usually d.2) + can then be interpreted + (see next section) as a virtual text (or other media) stream. + +

+ To reiterate, a permascroll is not a place: + it is a state of mind, in which you keep track of what all + information copied or cut&pasted originally was. + For example, it is planned that in a future version of GZigZag + the user will be able to send an email with some cells + as well as the parts of the permascroll that is referred to + by those cells. The recipient's computer can then + store those pieces of the permascroll and notice if any other + references to them exist. + In fact, permascrolls are excellent candidates for caching since + the identifiers to the content are indeed permanent, unlike + on WWW where the content of a cached URL can change at any time. + + +

+ Another application where permascrolls show their power is + comparison: most utilities used for text comparison (e.g. the + unix diff utility) do a reasonably good job if the + user is simply adding or removing or changing small pieces of + text. However, such tools have great troubles with rearrangement, + exactly because of the lacking text model where only the content, + not the origin is stored. Thus, a rearrangement usually shows + up as large insertions and deletions, which is actually exactly + what it is, in the primitive text model. + +

+ It is possible to overcome some of this problem by writing + more and more refined algorithms for finding similar texts but + once we get to phrase-level elements, they become useless since + the same phrases can occur again and again in a document. + +

+ With permascrolls, rearranging a text file is not about moving + the text content - it's about moving pointers to the + content. So two different revisions, the latter of which has + been rearranged, still point to the same spans of text in the + permascroll. Now, visualizing the differences becomes easy: + all that is necessary is to point out to the user which pieces + of text are stored in the same place in the permascroll. + See Figure XXX below, where this is demonstrated. + +

+ This feature may seem like unimportant but in projects with more + than one worker and much rearrangement of the manuscript + it can be truly invaluable for finding where a certain part of the + previous version of the manuscript ended up. + +

Alternative visualizations: applitudes

+ +

+ Although interesting, the above structure and visualizations + would fit most applications rather poorly. However, given the + basic ZZ structure it is simple to define new visualizations. + +

+ Taken together, a visualization and operations are referred + to as an applitude, + as opposed to the traditional term application + since all the data is still in the same structure and other + operations can be used to edit this data and these operations + can be used to edit other data. + +

+ For example, a vstream is a kind of an applitude: there is a + clearly defined internal structure and special operations for + the vstream for inserting and deleting characters. + There is also a good visualization of a text vstream: simply + the characters in a paragraph (formatting capabilities will + be added later). + The default cell-based visualization and the natural vstream + visualization for a small piece of text is shown in XXX. + Note how the colored cursor is shown in both panes. + +

+ The interesting thing about applitudes is that they can be designed + to be connected to each other in a more fine-grained fashion than + current embedding frameworks such as Bonobo, KParts, or OLE/COM. + + + + +

Some Textual Applitudes of ZigZag

+ +

+In this section, we'll look at some functioning applitudes. +As explained in the previous section, the strength of ZigZag lies in that +all these applitudes can be used together fairly easily since all the data +is stored openly in the ZZ structure. + +

+One important function that GZigZag provides for all applitudes is +animation. This works by associating a cell with all "things" +that are rendered on the screen. +When two "things" in subsequent keyframes (i.e. the fully rastered frames) +are associated with each other, the system generates as many interpolated +frames between them as the speed of the host machine allows. +The time between keyframes is estimated from the interval between +the user's keystrokes: the system attempts to be ready 100ms before +the user strikes the next key. This gives the system a fluid, responsive +feel while allowing smooth, slow animation if the user is moving slower. + +

+An example of such animation can be found in XXX ANIMATED GIF ON +GZIGZAG PAGES + +

Text cloud - real cut&paste

+ +

+ One of the points Nelson has made in several talks (XXX??? on paper?) + is that the term "cut&paste", as used in the computer field, is + a really bad choice of words. Originally cut&paste meant physically + cutting a text into pieces, rearranging the pieces and glueing + them together. This seems a little similar to what the computers + do. + +

+ However, there is a crucial difference: in physical cut&paste, + the text can be cut up into as many pieces as desired; + all the pieces are visible all the time; the pieces can be slowly + rearranged into the optimum order in a parallel fashion. + Indeed, when the text is cut up, the actual data model + of the text + is changed from the single text stream to a cloud of text + fragments. + +

+ Most current computer programs (XXX Exceptions?) force the user + to stay within the formal one-stream text model all the time during + editing, except for a single piece of text cut onto the "clipboard", + which is not seen. + This is why several people (REF: private communication) seem + to use a second window next to the main one to hold fragments. + This, of course, has several disadvantages: the fragments are + stored separately from the main body of text, the fragments still + have to be stored in the one-stream text model and the system is + rather clumsy. Of course, some people are able to write near-perfect + prose in near-perfect order. + +

+ One of the interesting differences between this system + and the dominant paradigm is the way of selecting text. + In most current systems, selecting text is performed by + painting, i.e. pressing the mouse button at one end of the + span being selected and releasing the mouse button at + the other end. In the TextCloud demo, text is never really + "selected" in the same way: instead, the user can make any + number of cuts into the document using the right + mouse button. Then, when the user presses the left mouse button + on some text and drags, the text is separated at the neighbouring + cuts to allow the user move a single piece of text. + +

+ Already Nelson's original mockup pictures about Xanadu + (see XXX (pic on WWW)) + include transpointing windows, i.e. windows which show the + connections of their respective contents graphically. + These connections can be either transclusions or links. In this + article, we concentrate on transclusions. + +

+ GZigZag is probably (XXX???) the first system to implement such + transpointing with beams: an earlier Xanadu client Pyxi by XXX + shows transclusions by colors but does not do transpointing. + The TextCloud applitude is a good place to see the transpointing beams + in action: simply copying (i.e. dragging with Shift-MouseButton1 instead + of just MouseButton1) a vstream creates a transclusion and the + beam appears. Then, when editing one (or both) of the streams by + cutting&pasting text the beams remain + connected; this is because the beams are really connected to the actual + text content, not just the external object. + +

+ The TextCloud is a simple model and its current implementation clear + limitations: all text must be stored in this one area and the size + of the text cannot be changed. + Also, it does not interface well with the other parts of the system. + It is simply one step on the way towards the full system, in order + to test one user interface aspect of it. + + +

Editing longer documents using cells

+ +

+ A different way for editing longer documents is through putting + vstream fragments of the documents in ZZ cells which are then rendered + in a raster. All the structural capabilities of ZigZag are + then in use for rearranging the pieces. + +

+ This being ZigZag, note that "putting fragments in ZZ cells" + does not a literal inclusion but an interpreted inclusion: + the view has a special raster which knows how to look for + the vstream to include in a cell. + When the space is being rastered, + +

+ Unfortunately this demo is not yet finished so we cannot offer + a screenshot. + +

Hypertext without lexias (XXX?)

+ +

+ Hypertext has come to mean "WWW-like" in many places: + a paradigm where the user is presented with one lexiXXX, + performs a selection, for example clicking with the mouse, + and is taken to another lexiXXX. + +

+ GZigZag makes it possible to easily create a wealth of flexible + visualizations that do not use such fixed screenfuls of text. + This is because GZigZag is built in a modular fashion and makes + it easy to describe a new visualization. + +

+ For example, let's start with a text model that contains + simply paragraphs of text, one after another. + + +

Email or forums with coordinates

+ +

+ In this section, we come once again to a problem which + does not exist for small data sets. If there are + only 10 messages in + a mailbox, it does not matter in the least how incredibly + bad the mail reading program is: + humans can still manage since they can remember + and overlay the true structure on top of the rigid and unnatural + structure imposed + by the mail reader program. + +

+ However, consider the linux-kernel email list or + corresponding high-volume newsgroups on the usenet. + Most programs for reading news or email are based on the assumption + that the reader wants to read all or most of the incoming messages - + a natural assumption stemming from the original volume of the forums. + However, with time the number of messages in a forum has grown + unmanageably yet programs mostly offer only rigid pre-selection systems + such as killfiles which remove all messages with a given subject + or sender from the view. + + +

+ ZigZag and FloatingWorld provide an interesting alternative + which we have so far had time to only scratch the surface of. + When a mailbox or a newsgroup is incorporated into the structure + correctly, it is simple to write interesting visualizations + that show some of the emails. + +

+ The structure underlying the email applitude is described in + FIGUREXXX. + +

+ The first, simplest visualization FIGUREXXX + is simply the traditional + mailbox visualization, offered by many programs such as Pine, XXX. + This simply shows some of the most relevant header fields of + messages on each line, arranged vertically in the mailbox order. + Already here ZigZag has several tricks up its sleeve. For example, + a message may be stored in several "folders" (lists), either + by using different dimensions for different folders or by + cloning the headcell of the + message onto different ranks on the same dimension. + Another trick here is that it is easy to see which folders + a given message has been connected to, since all connections are + two-directional. This is an advantage caused by the fact that ZZ + considers the message to be an entity rather than a stream of + characters that can be copied but has no identity + (like emails in normal email folder files). + +

+ Sorting the emails is of course possible, either by presorting + and making a rank of them and using that + or by post-sorting at each time they are shown. + For sorting, ZZ offers an interesting user interface: when the + user moves the active cell horizontally, the list of + mails is shown sorted according to that cell. + XXX Mailboxes, many folders per email!!!!! + XXX Good argument for postsorting or cached postsorting. + XXX Notifications + +

+ +

+ Now, one interesting thing that ZZ offers is multiple windows + with different views whose cursors are bound together (using + the cursor-cargo mechanism; see the ZZ Spec XXXREF). + All the views above have one "active" cell. We can have several + useful views visible at the same time, which stay in lockstep with + each other. + + + +

+ The FloatingWorld model offers an alternative: messages + or icons of messages can be shown in a two- or three-dimensional + coordinate system. + +

+ Such a system is trivial to implement in a general fashion + using ZigZag since the homogeneous structure makes it simple + to specify paths to obtain coordinates through, whereas if + using a traditional programming language, it would be all too easy + to restrict the world of possible coordinates to some set + that is easily specifiable in the structure that was chosen. + +

+ Additionally, normal email programs or HyperMail (XXXREF) + -like HTML indexers treat the messages as their own, making it + almost impossible to link the discussions into the places where + they would belong: for example, linking the discussion leading up + to a particular decision in a standard (say XHTML) into the place + in the standard would be an invaluable aid to those trying to + understand afterwards how something is supposed to work. + +

+ Consider, for instance, a document such as the Kernel Traffic + weekly newsletter (XXXREF) which summarizes the main discussion threads + on the Linux-Kernel mailing list that week. + + XXX transclusions, etc. + +

Editing hyperliterature with nodes

+

+ - editing trad. hyperliterature easier: visualize the STRUCTURE of + the whole work, then rendered into HTML + +

Scientific publishing using Xanadu hypertext

+ +

+ A long-known problem in scientific publishing on paper media is + that bibliographic references are always backwards in time, while + it would often be more interesting for the reader to + know the future references, i.e. either articles that refer + to the current one or articles that the author has deemed + interesting enough to refer to at a later date from publication. + +

+ Now, in the Xanadu model, quoting is equivalent to linking because + of transclusions. + +

+ Transclusions may seem foreign as an instrument of quoting and + responding to a selected portion of an article. However, they + are actually quite close to another widely used paradigm: quoting + when replying to an email. The only addition here is that + the quoted parts (which are somehow visually indicated) are + not copies but transclusions from the original article. Because of + this, they are actively connected to the originals in an implicit + two-way link. + +

+ The system of moderation used on sites such as slashdot.org + is surprisingly similar to the scientific refereeing process. + The privilege of moderating other users' comments is granted + to established members of the community (members whose previous + moderations have been approved by other members), the process + is anonymous and determines on whether users get to see the comment. + However, there are important differences: +

    +
  • The moderation is not "accept/reject" but rather + "leave as is/ increase score/ decrease score". +
  • Comments are not deleted even if they have a low score; + users browsing the site can set their comment limit + themselves to determine what minimum rating for comments + they wish to see. +
  • A user has a default score based on his/her earlier + success in posting comments +
  • Comments are usually short notices on +
+ Upon consideration, some of these points are quite applicable + to scientific publishing as well. Specifically, the "letters + to the editor" section of scientific journals seems to be the + closest that print journals can come to this kind of convenience. + +

+ Indeed, this sort of publishing system could create a far more + interactive scientific discourse. + For example, a user can choose which links he wishes to see + when reading an article: refereed links, all links, links by certain + persons etc. + + + + +

The Code

+ +

+GZigZag, which is the program that is shown in all of the screenshots +in this article, is free software. It is distributed under the FSF's +Lesser General Public License (LGPL) and is available on SourceForge. + +In the language of the free software community, "Patches accepted". + +

Conclusions

+

+ +

Acknowledgements

+

+ +

References

+

+http://www.acm.org/cacm/AUG96/antimac.htm + +

Glossary

+ +

+This article uses many terms that are most likely unfamiliar to the reader. +We attempt to summarize the most important ones below. + +


+
+
ZigZag structure / space +
A simple structure, based on cells and dimensions + which the user is able to easily shape into any desired + structure. All interrelated pieces of information can be + close to each other on some dimension. +
cell +
The smallest unit of information in ZigZag. + A cell can contain a text string or + a single span in a permascroll; the separation is + because a text string can be edited but a span can only + be lengthened or shortened: no characters can be + inserted. Cells are connected to each other along + dimensions. +
dimension +
Connecting cells along dimensions is what ZigZag is + about. Locally, dimensions work just like on a spreadsheet: + each cell can be connected to one cell in the positive + direction and to one cell in the negative direction + along each dimension. However, there are no global constraints + between the dimensions. + +
rank +
A rank on a dimension D is simply a set of cells that are + connected to each other on D. A given cell can only + be on one rank on a given dimension. + +
raster +
A simple visualization of the ZZ structure. + A raster is given a cell to place in the center of + the view and a set of dimensions chosen for the coordinate + axes X, Y and possibly Z, and it starts at the center cell + and places other cells on the screen according to simple + rules. + There are several different rasters. +
+
+
+ +
FloatingWorld +
Ted Nelson's design built on top of ZigZag structure, + based on flobs. +
flob +
A multi-dimensional flying object. That is, an entity + representing something that may have any number of + flob coordinates. For example, an email's sender is one + flob coordinate, its subject another. + +
+
+
+ + +
Xanadu88 +
A hypertext system, finished in 1988, which works by + stable fluid media content instead of URL-like pointers. +
fluid media +
Any media types that can be subdivided. + Text, audio, video, images. +
permascroll +
A storage philosophy for fluid media where + each smallest unit (e.g. character of text) + is assigned a permanent identifier when + it first enters the system. Of course, + references to the smallest units usually happen + through spans for efficiency. +
span +
A (reference to a) contiguous section of the permascroll. +
vstream +
A list of spans that describe a virtual stream of + fluid media. A "document" or one version of a document. + Modifying a document does not modify the permascroll, except + by appending new inserted characters. Instead, the spans + of the vstream are modified: split apart, new spans + inserted etc. +
transclusion +
The inclusion of the same material in a permascroll in + two different documents. One of the fundamentals of the Xanadu88 + model is that it is efficient to search for transclusions + of a given span. +
transpointing windows +
Windows on a computer screen that show the connections or + transclusions between each other. + +
+ +

SCRATCH

+ +

+ +This section contains rejected pieces of text that may still +have some interest. + +

+ Naturally, if desired, dimensions can be used to construct + systems analogous to files and directories: for instance, + a number of cells going down d.2 can contain names + and these cells are connected on some dimension to the content + for that "file". + +

+ This is somewhat analogous + to the hyperbolic visualization + for graphs (XXXREF): hyperbolic space also looks locally like + Euclidean space but there is more "room" because the correspondence + to Euclidean space does not hold over distances. + An interesting similarity between the two is the volume of balls: + in hyperbolic space, the volume enclosed in a ball grows exponentially + with the radius and the same is true for ZigZag - if + desired; ZigZag cells can also be arranged in a less complex + fashion where the growth of the volume of balls is more restricted. + +


+
+ + + + + diff --git a/Documentation/CyberText/ct.wml b/Documentation/CyberText/ct.wml new file mode 100644 index 0000000..10bf472 --- /dev/null +++ b/Documentation/CyberText/ct.wml @@ -0,0 +1,275 @@ + + + +GZigZag - A Platform for Cybertext Experiments + + + +
+

+GZigZag - A Platform for Cybertext Experiments
+Tuomas Lukka & Katariina Ervasti +

+ +

ABSTRACT

+ +

This article describes GZigZag, which is currently the main project of the Hyperstructure Group +at the univ. of Jyväskylä. GZigZag is an implemention of ZigZag, a computer paradigm invented +by Ted Nelson. The paradigm abandons many currently central concepts, such as folders, files and +applications, and instead offers a more flexible way to arrange information. Already at this early stage +of development GZigZag has advantages compared with other computer systems.

+ +

1. INTRODUCTION

+ +

"COMPUTERS ARE FUNDAMENTALLY BROKEN" lectures Ted Nelson (7 February 2000). Unlike +many other critics, he also offers ideas for improving the situation. Some of his ideas are +currently being implemented by the Hyperstructure Group at the university of Jyväskylä, Finland. +In this article we present a short summary of our ongoing work.

+ +

1.1 Defamiliarization of files, folders and applications

+ +

Nelson (1999a) offers many reasons for why users face difficulties with present PCs. This article +only includes a short attempt to defamiliarize (1) folders, applications and files from the user's point of view. +This is not an easy task, because folders, applications and files are one of the first things a beginner +is taught and are not often questioned.

+ +

Hierarchical directories, also referred to as 'folders', were invented to help finding the right file +among many files (Nelson 1999a). Let us say that in September -99 a writer has been writing an +article dealing with the impossible nature of her cat Vilma. In September 2000 she wants to find the +article again to edit it for a new purpose. In order to find the article, she opens a folder named 'Vilma'. +The folder includes approximately twenty files, which are either versions of the final article or include +some ideas the writer has considered worth writing down at some point of the writing process. The +files have names such as vilma3.doc, vilma4.doc, vilfoo.doc and vilmaprob.doc. By the time the +writer finished the article she had no time to make an index explaining the contents of each file. Finally, +after opening and closing several files, she succeeds in finding the right file and starts working. When +editing, she suddenly remembers that she had a slightly different version of a paragraph in another +document. Once again, she has to start opening and closing files to find the right file.

+ +

Applications, then, are used for performing different tasks with the computer (Nelson 1999a). Problems +arise when a user wants to use the same information in many applications. For example, a multimedia +author, who has manipulated sound with SoundEdit, might want to use the sound in a multimedia +presentation made with Macromedia Director. Since applications do not support all file formats, +he has to find out which sound file formats Macromedia Director supports. After a study of sound +file formats, he saves the file in a suitable format and imports it to Macromedia Director. Then, if he +later views the presentation and wants to find a different sound sample, which he remembers recording +in the same session, it will not be easy. This is because there is simply no connection between +the Macromedia Director file and the original sound sample nor between the original sound sample +and the second sample from the same session.

+ +

These examples demonstrate how the files and folders model of storing information is insufficient: +it does not allow the users to track the conceptual relationships between related information or +versions. Files, folders and applications are easy to understand but do not need to be, as +Nelson (lecture, 30 August 2000) explains, fundamental concepts of software. The above +problems could be solved by designing software differently, starting from different assumptions.

+ +

1.2 Traditions of Bush and Engelbart

+ +

Vannevar Bush and Douglas Engelbart developed ideas for tools that would improve the +working conditions of people who perform complicated tasks in the complicated world. Bush, who +had noticed the explosion of information already in the 1940's, is famous for proposing Memex, +a "mechanized private file and library" designed to help individual scientists store and handle the +growing amounts of information needed in their work (Bush 1945). Engelbart, the developer of NLS, +a tool for collaborative work, writes about augmentation of man's intellect, which has been the goal +of his work with computers. By augmenting man's intellect he means "increasing the capability +of a man to approach a complex problem situation, gain comprehension to suit his particular +needs and to derive solutions to problems" (Engelbart 1962). The purpose of our work is similar +to Bush's and Engelbart's: we want to facilitate the production and arrangement of information +by creating, as Nelson (1999b) expresses it, "a high-power personal and media system, with editing +and presentation systems that expand the state of art".

+ +

2. BASICS OF ZIGZAG

+ +

Defining ZigZag is difficult, because ZigZag is so different from any software in the currently +dominant computer paradigm. It is not an application but neither is it an operating system or +a platform. It is a new way of putting information into computers, a cross between a database, +a filesystem, a personal information manager and many others, and even that is not sufficient +to describe it. ZigZag is simply something new and different.

+ +

3.1.1 Cells, Dimensions, Views and Applitudes

+ +

A ZigZag structure consists of cells and dimensions. A cell is the basic unit of information +in ZigZag. A cell can contain an information unit of any kind, for example text (e.g. "Vilma"), an +image (e.g. a picture of Vilma) or sound (e.g. "Meow" by Vilma). Cells can be connected with +each other along dimensions, which are referred to with names such as d.1 or d.cursor. On +each dimension, each cell can have two neighbours: a predecessor and a successor. The number +of dimensions is not restricted, and it is easy to create new dimensions. For example, if Ville wants +to comment on many different cells, he could use d.Ville-comment for connecting his comments +to the cells.

+ +

Figure 1 shows a simple structure. In the Figure, cells are represented by rectangles and neighbours +along a dimension by a line.

+ +

Figure 1.Seven cells, connected to each other along the two dimensions d.1 and d.2

+ +

There are several different visualizations (views) of the ZigZag structure. The views range from +general views that are useful for looking at all kinds of structures to specific views +that are useful for only one particular kind of structure. For example, Fig. 2 shows a generic view of a structure +that represents a schedule of a day. This view can show any kind of structure in a fairly reasonable +way, by showing the cells arranged along the dimensions and their text contents.

+ +

Figure 2.The most important events of a day in a general view

+ +

Figure 3, then, shows a specific view of the same structure. The underlying data is exactly the +same, but the specific view designed especially for the purpose interprets the structure and draws +the events in a more visual manner. Looking at another structure through this view would not make +sense because the view is designed especially for this structure.

+ +

Figure 3.The same events in a specific view

+ +

Combining the specific view such as the schedule view above with special operations for editing +such a structure, for example dragging the start and end times with the mouse makes an applitude. +Thus, an applitude consists of views and operations designed for a particular purpose. Even though +the term 'applitude' resembles the term 'application', there is an important difference: in ZigZag +nothing is separate, and applitudes, unlike applications, can be combined with each other, as the +example of the next section shows.

+ +

3.1.2 Example: Address Book and Family Tree in GZigZag

+ +

One of the first examples Nelson (pers.com., 25 August 2000) has used to demonstrate +ZigZag is the Holm Family Demo, a family tree prepared for his talk at the University of Oslo +to show how he is related to one of the professors of the university. Here, a variant of Nelson's +original example is used, combined with an address book.

+ +

The structure of the address book is simple: it is a list of names and addresses . The names are +listed along d.2 in alphabetical order. The addresses are connected to the names along d.1. +Figure 4 shows the (incomplete) address book in the row view.

+ +

Figure 4. The address book in the row view.

+ +

Since the list of relatives is long, only a subset of it can be seen on the screen at a time. In Figure 4 +the cursor is on the cell 'cousin 1'. Moving the cursor down would cause more cells below +the 'grandfather 2' cell on d.2 to become visible.

+ +

Next, the address book is combined with the family tree, which is represented by a slightly more +complicated structure, shown in Figure 3.

+ +

Figure 5. One family of the family tree in the row view

+ +

The two dimensions d.marriage and d.children are used to represent the family tree. Siblings +are connected along d.children, and married couples along d.marriage (2). An extra cell ("+") is used +on d.marriage to make the structure symmetric, and the list of children from the marriage on +d.children starts from that cell. Figures 5 and 6 show two different views of the structure. +The row view, as Figure 5 shows, enables dealing with one family at a time. The vanishing +view shown in Figure 6 gives a better picture of the family tree as a whole.

+ +

Figure 6. The family tree in the vanishing view + +

It is important to realize that the same cells are used to represent the relatives in both the +address book and the family tree, and that the connections related to the two applitudes are +along different dimensions. In the default views only two or three dimensions (x,y,z) can be +shown at the screen at a time. As it can be seen on Figure 4, the dimensions used for viewing +the address book are x=d.1 and y=d.2. Rotating the dimensions to +x=d.marriage and y=d.children shows the family tree, as in Figure 5.

+ +

The address book and the family tree could be combined with further applitudes. For example, +a cell representing a person could also be connected to photographs and emails having to do +with that person. Simply all related information could be connected so that it is easily accessible. +A consequence of the ZigZag structure is that all connections are two-directional, which means +that navigating between related information is easy.

+ +

3.2 Utility of GZigZag

+ +

ZigZag offers several advantages compared with existing computer systems. To begin with, as Nelson (pers.com., 25 August 2000) usually +remarks after showing his Holm Family Demo, "we did not create a genealogy program". Modeling a complicated structure such as the family +tree on usual computer systems would require creating a specific program for that purpose. Modeling a complicated structure using +GZigZag requires only creating of new cells and connecting them along dimensions.

+ +

Remarkably, there are no separate files and applications in ZigZag. As seen above, the same +cells can simultaneously be part of different structures without any restrictive boundaries. +Thus, a multimedia author using GZigZag would not have the same problem as the multimedia +author described in 2.1. Connecting the same cells in various structures also facilitates updating +information. Updating the last name of a newly married aunt in the family tree and address book +requires updating only one cell.

+ +

In addition to this, ZigZag is a more flexible way to arrange information than the conventional +files and folders model. A certain piece of information is found by following the connections +that the user has previously made based on his associations. Hence, a user of GZigZag does +not need to remember file names in order to find the right information. The writer looking for +a document containing an interesting paragraph about Vilma (described in 2.1) could simply +follow a connection made previously. Also, moving between different versions of the same +paragraph is simple when using the Xanadu content model.

+ +

Finally, ZigZag separates the structure and visualization of information. This is somewhat +similar to HTML 4.0 and CSS, but ZigZag generalizes this: all structures and all visualizations +are possible. The same GZigZag structure can be used in different media from mobile +phones to the immersive virtual reality of the CAVE, because different visualizations +can be constructed to take full advantage of each medium.

+ +

3. CONCLUSION AND FUTURE WORK

+ +

The primary purpose of this article, which is the first publication of the Hyperstructure Group, +is to present a short summary of our ongoing work, especially GZigZag. This is not a simple +task because we are dealing with such a different view of the computer. Indeed, the difficulty +of explaining the new ideas to people has been one of the main problems of Nelson's broader +Xanadu project.

+ +

In the near future we are focused on developing a stable, working GZigZag on the Java +platform and cellular language Clang, which would make programming easier. We are also +planning a network protocol for exchanging cells between computers +and developing applitudes for several purposes in order to learn more about the system.

+ +

We believe that Nelson's ideas are creative, excellent, original and that they should finally be +understood and implemented. Our long-term goal is to develop a computer system we would +like to use ourselves. ;-)

+ +

Everyone interested in our project is welcome to test and work on the current version of GZigZag, +which can be downloaded from the project's homepage. GZigZag is a free software project: the +source code is released under the LGPL license and interested parties are welcome to join +our mailing list. By the time this article is published, we hope to have released the first stable +version (recommended for non-developers). "Patches", as people of the free software +community say, and any other ideas of developing the system are gladly accepted.

+ +

ACKNOWLEDGEMENTS

+ +

We would like to thank Theodor Holm Nelson and Marlene Mallicoat for our collaboration. +We would also like to thank the other members of the Hyperstructure Group: Tuukka Hastrup, +Antti-Juhani Kaijanaho and Vesa Parkkinen.

+ +

FOOTNOTES

+ +

1 According to Fowler (1986: 35, 42) defamiliarization is the use of a strategy to force us to look at familiar things in a critical way, to see the +absurdity of a familiar object. Criticism, as Fowler sees it, is not a negative practice. The basic motivation for criticism is "healthily sceptical +inquisitiveness", which can give a stimulus to developing things for better (Fowler 1986: 34).

+ +

2 If a person has been married several times, a mechanism called cloning is used to represent this in the structure. However, +this is beyond the scope of this article.

+ +

REFERENCES

+ +

Print References

+ +

Fowler, Roger (1986). Linguistic Criticism. Oxford: Oxford University Press.

+ +

Electronic References

+ +

Bush, Vannevar (1945). As We May Think.
+Available in the Internet: +http://www.theatlantic.com/unbound/flashbks/computer/bushf.htm

+ +

Engelbart, Douglas (1962). Augmenting Human Intellect: A Conceptual Framework.
+Available in the Internet: +http://www.histech.rwth-aachen.de/www/quellen/engelbart/ahi62index.html

+ +

Nelson, Ted (1999a). Ted Nelson's Computer Paradigm, Expressed as One-Liners.
+Available in the Internet: +http://www.sfc.keio.ac.jp/~ted/TN/WRITINGS/TCOMPARADIGM/tedCompOneLiners.html

+ +

Nelson, Ted (1999b). ZX Views.
+Available in the Internet: +http://www.xanadu.com/FW99/ZXviews.html

+ +

Other References + +

Nelson, Ted. Lectures at the University of Jyväskylä. 7 February 2000 & 30 August 2000.

+ +

Nelson, Ted. Conversation with the authors. 25 August 2000.

+ +
+ + + + + + + diff --git a/Documentation/CyberText/email.dia b/Documentation/CyberText/email.dia new file mode 100644 index 0000000..163cb9e Binary files /dev/null and b/Documentation/CyberText/email.dia differ diff --git a/Documentation/CyberText/kello-o.png b/Documentation/CyberText/kello-o.png new file mode 100644 index 0000000..be3d832 Binary files /dev/null and b/Documentation/CyberText/kello-o.png differ diff --git a/Documentation/CyberText/kello.png b/Documentation/CyberText/kello.png new file mode 100644 index 0000000..54833c3 Binary files /dev/null and b/Documentation/CyberText/kello.png differ diff --git a/Documentation/CyberText/permascroll.dia b/Documentation/CyberText/permascroll.dia new file mode 100644 index 0000000..cee518b Binary files /dev/null and b/Documentation/CyberText/permascroll.dia differ diff --git a/Documentation/CyberText/rank1vert.dia b/Documentation/CyberText/rank1vert.dia new file mode 100644 index 0000000..6c5ba05 --- /dev/null +++ b/Documentation/CyberText/rank1vert.dia @@ -0,0 +1,601 @@ + + + + + + + + + + #A4# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #A# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #B# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #C# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #D# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #E# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #F# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #d.2# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #G# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #H# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #I# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #J# + + + + + + + + + + + + + + + + + + + + + diff --git a/Documentation/CyberText/rank2vert.dia b/Documentation/CyberText/rank2vert.dia new file mode 100644 index 0000000..f847b51 --- /dev/null +++ b/Documentation/CyberText/rank2vert.dia @@ -0,0 +1,375 @@ + + + + + + + + + + #A4# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #d.1# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #A# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #G# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #F# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #J# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #D# + + + + + + + + + + + + + + + + + + + + + diff --git a/Documentation/CyberText/rank3both.dia b/Documentation/CyberText/rank3both.dia new file mode 100644 index 0000000..7507be8 --- /dev/null +++ b/Documentation/CyberText/rank3both.dia @@ -0,0 +1,745 @@ + + + + + + + + + + #A4# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #A# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #B# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #C# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #G# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #H# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #I# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #D# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #E# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #F# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #J# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #d.1# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #d.2# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Documentation/CyberText/vilma.png b/Documentation/CyberText/vilma.png new file mode 100644 index 0000000..20a0e42 Binary files /dev/null and b/Documentation/CyberText/vilma.png differ diff --git a/Documentation/DesignProblems/Makefile b/Documentation/DesignProblems/Makefile new file mode 100644 index 0000000..850da15 --- /dev/null +++ b/Documentation/DesignProblems/Makefile @@ -0,0 +1,11 @@ +DIAGRAMS=linkorder.png beamorder.png + +all : dp.html dp-ns4.html + +dp.html: dp.wml $(DIAGRAMS) + +dp-ns4.html: dp.wml $(DIAGRAMS) + +include ../lib.mk + + diff --git a/Documentation/DesignProblems/beamorder.dia b/Documentation/DesignProblems/beamorder.dia new file mode 100644 index 0000000..af40a46 Binary files /dev/null and b/Documentation/DesignProblems/beamorder.dia differ diff --git a/Documentation/DesignProblems/dp.wml b/Documentation/DesignProblems/dp.wml new file mode 100644 index 0000000..39db2da --- /dev/null +++ b/Documentation/DesignProblems/dp.wml @@ -0,0 +1,680 @@ + + + + + + The major internal design problems left in GZigZag +#include '../wmlinc/article.wml' + + +{: [[s/(?)(d\.+\w+)/\1<\/code>/g]] +

The major internal design problems left in GZigZag

+
$Id: dp.wml,v 1.14 2000/08/15 05:19:18 tjl Exp $
+ + Tuomas Lukka
+ lukka@iki.fi
+ Dept. of Mathematical Information Technology
+ University of Jyväskylä +
+
+ + + + + +

+This is a short exposition of the design problems currently in ZigZag +(as of June 2000). The intent is to eventually evolve this into an exposition +of the internal design of GZigZag, after the problems are solved. But +at the moment most of the problems still exist. + + + +

Introduction

+ +

+ This document is intended as an internal discussion document + on the most difficult design problems for the GZigZag source code. + This is work-in-progress: if there are any unclear parts, feel + free to ask me to clarify things. + +

Device-independent Floating Graphics

+ +

FloatingWorld Graphics

+ +

+ The FloatingWorld graphics model built on top of ZigZag is based + on flexibly plotting objects defined by cells on the screen. + ZigZag rasters are simply a special case of this: the coordinates + are given by hopping along ZigZag ranks and the objects rendered + are simply the cells and the texts inside them. + +

+ Conceptually, there are two kinds of objects shown on the + screen: flobs and relations. Also, there are three + different processes in the background: where are flobs + rendered, what kind of flobs are rendered and what + relationships between them should be shown. All these are + relatively independent of each other and should be clearly + decoupled in the backend. + +

+ Animation has been supported from very early on in GZigZag with + excellent results: the human eye can use the motion to understand + the relation of the different views in time much better than + if the views are just switched without the intermediate frames. + This feature should be global: if the same object is shown in two + consequent views, it should animate from the previous view to the + next to show the deep relationship between the two appearances. + Even a simple linear interpolation, without any regard to the + true structure of the transformation between the two views is + astonishingly helpful. It is easy to see that animation mostly + concerns the flobs which must interpolate their coordinates frame + by frame between rasters. In fact, currently the links are not + shown when animating; this does not appear to be a significant + problem to the human observer: maintaining a high frame rate is + much more important than giving a complete picture. + +

+ In addition to animation, depth perception of the human eye + is misused in the vanishing raster to a great advantage: cells + further away from the cursor are shown smaller and grayer and + are rendered behind the cells closer to the cursor. I term this a + misuse since there is no 3D model behind: it's just an algorithm + that lays out cells that happen to look smaller and grayer and + thus further away. + +

The desired level of generality

+ + We shall take four views as an example of the generality the system + has to offer. +
    +
  • + Normal, box-and-stick view (loose-brick) +
  • + Tight-brick view: the cells are drawn right next to each + other. The line drawn between the cells (or on edges) + tells what kind of edge it is (connected, no connection, + connection underneath the other cell). +
  • + Loose-brick view but with variable-sized content of cells: + vstreams or images. +
  • + Email flobs: emails on a coordinate system, connected + with lines indicating reply-to relationships. The flobs + may show the content, diminished as the view moves away + from the cursor. +
+ +

Problems

+ + +
+ A simple case where rendering a link in one go gives + suboptimal results. +
+ +
+ A beam with cells is even more complicated: the beam + has to be between the text and the cell background but + behind any other cells on the way to avoid cluttering + the screen. If the beams' borders should float above + the beams, then this gets even more difficult. +
+ +

+ A fairly short-term goal in the expansion of GZigZag is to make + it support 3D graphics using OpenGL, as well as retain the current + functionality using pure Java graphics. Especially useful would be + the ability to use the 2D views directly through the OpenGL layer, + as well as 3D views, and the ability to animate between the two. + +

+

+
Reusability of views +
Flexibility +
As an example, using an existing raster but putting an image + or a vstream (somehow connected to the cell) instead of + the text into the cell should be simple. +
Simplicity +
The system +
Performance +
+ +

+ If small factories are used for letting the rasters create cells, + handling depth gets more complicated. + +

+ There are also interesting problems in the rendering order of + links: if there is a link between cells that are at different + depths, then which cells should be in front. It is especially + difficult to include something like beams into this framework, + if a Z-buffer and a real third coordinate is not used. + One possibility is to split all links and beams in the middle + and render the two halves independently. However, as seen in + the beam figure, that will not be enough. + + +

Potential solutions

+ +

+ Let us start from the obvious. + +

+ For each raster, the locations and appearances (and the depths + for rendering) of the flobs must be stored somewhere quickly + accessible for the animation between rasters. + +

+ The raster must ask the flob-producer what size and aspect ratio + would be most suitable (given a shrinking factor). Being able to + cache something that was calculated (such as a line breaking) + would be most beneficial. Of course, depending on the form of + the raster, it may or may not accept the size and aspect ratio + given by the flob producer. The flobs are internally cached as + objects that know how to render themselves and how to interpolate + between two keyframes. + +

+ The links are produced after rastering, from the + coordinates of the flobs. This operation is thus well encapsulated + from changing rasters. In fact, the links do not even need to + be made into self-standing objects at all times: all that is + needed is that the FlobSet knows to call a certain method of a + certain object to plot links. + +

+ These considerations produce a rather different picture + from the current one. The classes Flob and + FlobSet would be the natural starting point. A + FlobSet, unlike the current ZZCanvas, would only store the flobs + and not the connections. The connections could be drawn just as + the flobset is being rendered from back to front. + +

+ One interesting point regarding the identification of Flobs from + the FlobSet is that the FlobSet may be hierarchical in nature. + For example when doing the VStreams-in-Cells raster, the same + vstream might be shown in two different cells (clones of each + other). Now, if flobs were identified just by their cell, then + the flobs for the spans of text would be identical and therefore + interpolated animation could do very strange things. The trivial + solution to this is to allow container flobs to exist, which + exist just to identify that certain cells are accessed through + a certain other cell. If the FlobSet has knowledge about this, + it is easy to both treat the FlobSet as flat (for e.g. beams), + or as the hierarchy (for identification of the corresponding + flob in another FlobSet for animation). + +

+ This solution is currently being tested as of 20000806. + +

Problems with the hierarchy

+ +

+ The hierarchy does not solve all the problems and + brings some new ones. + Some operations use hierarchy, some don't. +

+
Depth-ordering +
May be done with hierarchy (so the whole hierarchy branch + has a depth - effect like overlapping windows or + without hierarchy - effect like a three-dimensional cloud. + Both effects are probably useful in different situations. +
Animation +
Hierarchy is taken into account: it informs which instances + of a cell animate to which other instances. +
Link / beam display +
Hierarchy is not relevant to these except that sometimes + links/beams inside the same branch may be hidden. +
+ +

+ Because the hierarchy is kind of optional, + the hierarchy in the current prototype + is simply handled by identifying + each flob with a string ("path") and a cell. + This seems to give both enough detail and efficiency. + +

Decorations

+ +

+ Another interesting feature with the views are decorations: + things that either connect flobs between each other or + show some relationship in some other way + (for example, the three-line thing that shows the directions + of the coordinate axes). + +

+ These decorations aren't considered first-class citizens like + flobs in the current model. + This may make it possible to find extremely efficient + ways to implement them. + One obstacle to efficiency, however, is that the decorations + should be rendered at the same depth as the cells. If we have + a Z-buffer like in OpenGL, this is of course not a problem. + +

+ Now, there are several kinds of decorations: +

+
One-off +
Decorations that occur once or twice in a display, such + as the abovementioned coordinate thingy. +
Global +
Decorations that occur between most cells (at least, + most cells at a given path), such as links in the X direction. +
Overriding +
Decorations that override global decorations for selected + cells, for example if we want to show a connection that + is at the same time a clone relation by a different + visual. +
+ +

+ In order to trample over less memory, it would be nice to + be able to render global decorations for a set of cells (at + a given depth) at once. + +

+ There is one situation where decorations present a problem, + and that is when the decorations should move with the interpolation. + This is generally desirable in complicated views (e.g. email-flob) + to provide the user with additional visual cues about the structure. + There is a slightly incorrect solution that get us close to where + we want: a decoration that wants to interpolate is named a flob + and it stores references to the flobs and uses their + interpTo fields to calculate the interpolated + coordinates. The only problem is the depth: this algorithm does + not correctly alter the depth in interpolation. + However, when using java.awt.Graphics none of the other + flobs take care of their depths properly when interpolating so + it is not a problem. And if using three-D graphics, the renderer + can use the flobs' Z coordinates. + + +

Floating graphics in general.

+ +

Handles and cursors

+ +

Problem

+ +

+ One of the versions of Ted's specs specifies the following + structure for flob. + First of all, there is the central handle cell which + is the center of the flob. The flob is referred through it and + all the parts of the flob can be found through it. + That version of the spec specifies d.handle as the dimension to + reach the rest of the flob from the handle cell, and + d.ref as the dimension to use to refer to that handle cell and + thereby to the whole flob. (the spec has apparently changed + now but the changes do not affect this problem). + +

+ The cells on d.ref are basically stand-ins for the whole flob, + kind of like clones are stand-ins for a cell. + An email can be included in several mailboxes (lists of emails + running on d.2) by including cells that are on d.ref from + the original email's handle cell. + +

+ The problem, then, is basically about what is getting shown: + we'd like to be able to show +

    +
  1. The actual flob +
  2. The fact that a cursor is on the referring cell +
  3. Possibly, the contents of the referring cell +
+ This is a problem since in the current codebase, a flob + is known by one cell, whereas the above obviously + requires two cells: the referring cell and the handle cell. + Even more important is that the FlobSet knows + about the handle cell since otherwise connecting the flobs + becomes a less efficient procedure, requiring the FlobSet to + look at all referring cells to see whether they are included. + +

+ So the question really becomes: is there any point in storing + the referring cell in the flob structure, except as presentational + info about the string and cursor colors to show. + +

+ If ZZ is expanded to allow the user to place the text + insertion cursor in a cell by a mouse click, then the referring + cell is obviously needed if any of its text is rendered. + +

Current solution

+ +

+ Well, currently this is solved by having the handle cell always + be the Flob.c and if the flob has to give out + other events, it can be given a different cell. + + + + + +

Caching before saving - new file format

+ +

+ The slowest part of the current implementation, as witnessed + by time testing, is writing to the file. Also, the current file + format does not properly allow undo & branching backtracking. + +

+ The goals for the system are +

+
Write-caching +
Each cell change should not cause several system calls + to occur. Rather, cell changes should be held in memory + and flushed to disk in larger chunks every once in a while + (as the user chooses). +
Undo +
The list of operations in memory should be usable for + low-level undo operations, such as undoing writing letter + by letter. +
Granularity +
The user should be able to specify that when saved to + disk, only larger sets of changes are undoable. This may + save a lot of space, e.g. if a number of cursor moves + are compressed + to one undo set, many cells will not have changed at all. + This is especially important now that the character-by-character + editing of cell content is also done in the structure: + each insertion of a character currently saves two + cell contents: the cell being edited and the cursor cell + (giving the offset). +
Notifications +
It would be useful if the change list could also be used for + change notifications: after a set of operations is completed + (or at prespecified times) the list is examined for changes + to cells under observation. +
+ +

List format

+ +

+ It is vital that the in-memory change list is compact in format + and extremely light-weight for Java usage as it is going to be a + hot spot. + +

+ One relatively sparing implementation would be to have one long + array of Object inside which every third element would be an operation, + and the other two would be its parameters. This way, no separate + Operation object would need to be created and the references to + operations sequentially would stay memory-local: the cost + of the typecast + of Object to the Operation type is negligible compared + to the cost of accessing two or three long arrays instead of one. + +

+ There would likely be one to few Operation objects per dimension object, + which is perfectly acceptable. + +

+ The long array would have the sequence stamps and would be operable + either for undo or for committing to disk. + +

Problems

+ +

+ There is one important problem with this approach: the operations + are fairly low-level ops: this cell connected to this one, or + disconnected, or whatever. + The semantic information about an operation such as insertion + is not saved. This could be a problem with synching later on. + +

Notifications

+ +

+ In the following, N is the number of cells changed, B is the number + of observers. Also, K is the number of cells one observer typically + observes. + + +

+ It is important for the notification mechanism to be fast: specifying + a set of cells that a particular entity is interested in and scrapping + the whole set (when the entity is refreshed) will very likely be one + of the most common operations. Not trampling through a lot of memory + and being easily garbage collectible are vital considerations, as well + as good scaling w.r.t.~several things. + +

+ Observer insertion is naturally O(K) and observer removal is + either O(1) or O(K). + +

+ If a separate hashtable is used for each observer, testing which + observers to wake up is O(N*B) operation, which is not very nice. + + + +

Slices

+ +

+Slices are used for viewing a number of ZigZag spaces as one compound +space, and for sending a group of cells over to another user. +Slices are probably the most crucial aspect of the system for common use +as they will enable collaboration and upgrading. + +

+Among the issues here are +

+
Permanent IDs for versions of cells +
Specifying a group of cells for slicing. +
This is simple when the all the cells are ones edited by the user. + This gets very hairy when the user wants e.g. to send a view. Which + control cells are included? +
Reconciling differences: collaborative editing. +
A mechanism for keeping two peoples' versions of a "document" + in synch by sending minimal groups of cells across. +
d.cursor and slices. +
Having the cursors in the structure is both a blessing and a curse. + Cursors are used both for "variables" internal to the structure + with Clang and views' centers. + Their interaction with slices and versioning is unclear to say the least. +
Inclusion of a slice into multiple spaces +
What a can of worms. +
Viewing a space remotely +
Only the cells seen should be sent over. How does d.cursor + work here? +
The identity of dimensions +
If a dimension is just a string, we have a namespace problem. + Dimension being identified with a particular cell might be a solution + but this is again not without its own problems. +
Clones +
Ted wants these to be used as a solution to many problems here. + But is it possible? Can all code be made to support the situation + where suddenly one of the cells is split into two clones when + the script expected them to be together. +
Transcluding +
Taking a cell from another space with a permanent ID and connecting + its transclusion somewhere in the local space - this creates a new + version of the cell! +
d.ref and d.handle +
Interaction of higher-level items with the slice code? +
+ +

+And of course the really important question of what we're really after. +Slices have distinct, but related functionalities: +

+
Part of personal space. +
This is what Ted's example of bringing in months of the calendar + from slices is about. Each day connects to a weekday on one dimension, + and the months connect naturally in the right order by preflets. + Here, the idea is that the slice connects to the "main space". +
A fixed, distributed "package". +
For example, the default space with the default bindings for keys, or + packages that demonstrate various features. + These are less often modified by the user and are brought in by the user + and attached somewhere. + Here, the main space connects to the slice. +
Versioning. +
This is rather similar to the abovementioned fixed, distributed + packages: the user can attach the old version of some slice + somewhere, without modifying it (causing a branch) just by looking + and browsing it. + Naturally, if two versions of the same slice are brought in, the cells + should be connected along d.version or somesuch. +
+ + +

Packages

+

+ Of the above functions, the most critical one for GZigZag + currently is the packages: distributing the main default space + as a slice would be a great step: then it would be possible for + users to start stable personal spaces which would not be needed + to be brought forwards for every new version of the bindings. + +

+ The most important problems here are cursors. Just about + everything else can be resolved by explicit hook cells ("hook your + own bindings negwards on d.3 here"). Cursors are + a different matter. They are used for several things, to name + a few: + +

+
Center of view +
Selecting dimensions from dimension lists +
Selecting rasters from raster lists +
Arbitrary selections for viewing operations +
+ +

+ Additionally, there is the cursor cargo dimension which allows + cursors to piggyback on one another - for example, combining + the cursors for one view and another view's X axis allows one + to change the dimension list for the X axis by moving the other + view's center. + +

+ The default space and other packages which have views will most + likely have cursors. In order for the spaces to be useful, + these cursors should be movable when the package-slice is + included and should be movable by changing the main space, + not the package-slice. Also, cursor cargo should be changeable. + +

+ There is a simple solution to these problems: the package slices' + own d.cursor and d.cursor-cargo are + mapped to some other dimensions, e.g. d.ps-cursor. + When a slice is first incorporated into the system, the + default cursors from the slice are copied to the global + d.cursor. There then need to be operations on the + slice cell to reload or commit the cursors of a slice, which + simply copy the assignments of the cursors to the package-slice + (provided all cursors lie on cells of that package-slice as + they should) or copy the cursors from the package-slice to the + main space. + +

Most trivial slices

+ +

+ Because waiting for the full design to be finalized would + have seriously slowed down development (as the main developers + wouldn't be able to use GZZ for real work) there is + now a primitive slice implementation in place. Even in its + rudimentary form it is surprisingly complete. In addition, + this experiment gives valuable experience in the complexities + of implementing any types of slice systems. + +

+ The system works by handling two dimensions, d.slices + and (naturally) d.cursor specially. These are in + fact the only dimensions that are allowed to connect between the + slices; all others are constrained to be only among the cells + of the same slice. + +

+ The dimension d.slices simply connects the homecells + of the slices in the slice order. There are no other connections + along this dimension and it cannot be modified. + +

+ d.cursor is a different matter. In order to be + useful, even the most trivial slices must allow connections that + transcend the slices on d.cursor. In this model, + d.cursor is constrained so that the only operation + allowed is insertion negwards (currently the cursor is obtained + by going to the end of d.cursor poswards, which + will change). Also, cells in slice 0 may be inserted to any + other cell but not vice versa: cells (cursors) in other slices + may only point to cells in the same slice. + +

+ These semantics are fairly simple but still their correct + implementation is not at all trivial, especially for + d.cursor. The implementation uses preflets in + slice 0 to connect to the other slices and when reading, the + whole rank in slice 0 is placed before all the other cells in + the non-zero slice accursing the same cell, so the cursors are + not necessarily in the same order they were inserted in. + +

Adapter slices

+ +

+ One possible solution in the long term to the package-slice + problem is simply having adapter-like slices for the external + packages. These slices would have preflets pointing to s.0 as + well as the external package - possibly even without intervening + cells. + +

Versioning

+ +

+Versioning is one of the most difficult problems in defining a ZZ space. +This is because having a versioned space is not useful, unless +cursors can point to past versions of cells using the normal mechanism, +d.cursor. If views and pointing were handled outside the normal space, +this would be no problem. + +

+This immediately suggests the trivial but unsatisfactory solution of +simply not versioning d.cursor. This is unsatisfactory because d.cursor +is used for an increasing number of things, e.g. Clang variables: what +good would it be to have access to a previous state without being able +to access the values of the variables. + +

+The other solution, simply allowing retroactive changes to d.cursor +of past cells to point to the future is more attractive but not without +its own downsides. Let's say the user, at time 100 looks at a cell A at time 5 +and does some changes in the space, e.g. moves the other cursor or +writes text somewhere else, until time 105 after which he moves +the cursor away. In this case, the rank on d.cursor from cell A would +contain the user's viewcell at times 100, 101, 102, 103, 104 and 105. +This is not that great either, because the algorithm that displays the +cursor moves through d.cursor to find the coloring of the cell to show +the colors of the cursors on it. The number of cursors on past cells would +be compounded. + +

+A potentially interesting solution, avoiding the preceding problem, +is to rename d.cursor to d..cursor-past for the past cells: +a connection on d.cursor would mean that a current cursor is on the cell. +This solution is attractive, as it preserves the values of all Clang +variables "pickled" using another dimension on which they can be browsed, +but also does not grow the number of cursors on a cell too much. + + + + + +:} + + + diff --git a/Documentation/DesignProblems/linkorder.dia b/Documentation/DesignProblems/linkorder.dia new file mode 100644 index 0000000..1bb0a89 Binary files /dev/null and b/Documentation/DesignProblems/linkorder.dia differ diff --git a/Documentation/DimBased/Makefile b/Documentation/DimBased/Makefile new file mode 100644 index 0000000..3b37cb1 --- /dev/null +++ b/Documentation/DimBased/Makefile @@ -0,0 +1,3 @@ +all : dim.dvi dim.ps + +include ../lib.mk diff --git a/Documentation/DimBased/dim.ptex b/Documentation/DimBased/dim.ptex new file mode 100644 index 0000000..b273d0b --- /dev/null +++ b/Documentation/DimBased/dim.ptex @@ -0,0 +1,53 @@ +% BE SURE TO EDIT design.ptex +\documentclass{article} + +\usepackage{rcs} +\RCS $Date: 2000/03/04 15:45:59 $ +\RCS $Revision: 1.1 $ +\date{Rev.\RCSRevision~~\RCSDate} + +\title{Dimension-based thinking for ZigZag} +\author{Tuomas J. Lukka} +\begin{document} +\maketitle + +\def\zz{ZigZag} + +\section{Introduction} + +When designing the code to implement a \zz\ space, the +place most people would start at would be the cell object, which would +have a set of pointers to other cells, named with dimension names. +However, this is not the only way to structure the internals - indeed, +it is not necessarily a good way at all. + +\section{Dimension-based view} + +With cells, you have to always take steps to enforce the two-directional +connection consistency rule. +The dimension-based view starts from the realization that if we consider +each {\em dimension} an entity by itself, this gets much simpler: +simply put, each dimension is a one-to-one mapping from some cells of the +space to some other cells. + +\section{Advantages} + +The dimension-based view has several advantages: +\begin{itemize} +\item {\bf Specialization} + It is much easier to define a single dimension object to + do something different than the others, e.g. a dimension where + getting the {\it n}th cell is fast but inserting and deleting cells + is allowed to be slow. +\item {\bf Simplicity} + Since one object is in charge of the both ends of a connection, + it is easier to avoid mistakes. Coding transient cell connections + is easy as well, as that object can keep tabs on the transient + connections separate from the stable ones. + + + +% .PS +% box "Clang" ht 0.25 +% .PE +% $$\box\graph$$ diff --git a/Documentation/FAQ b/Documentation/FAQ new file mode 100644 index 0000000..1e75b8f --- /dev/null +++ b/Documentation/FAQ @@ -0,0 +1,262 @@ +Frequently Asked Questions about GZigZag, with answers. +$Id: FAQ,v 1.7 2001/02/09 05:59:36 ajk Exp $ + +All trademarks are the trademarks of their respective owners. + +Note that the 'I' in this document is Tuomas Lukka. + +============================================================= +Section I: General questions + + +1. Where to get the latest version of this FAQ? + +The source code for all versions of this FAQ is kept as a part of the +GZigZag CVS repository. See the GZigZag sourceforge page at + + http://gzigzag.sourceforge.net + +for accessing the source. The FAQ is in the directory Documentation/ + +----- +2. What is ZigZag? + +ZigZag, an invention of Ted Nelson, is a new type of data structure. + +For mathematicians, the key words would be + + - discrete + - multidimensional + - locally euclidean + - with global directions (coordinate axes) + +and for non-mathematicians, these are explained below: + + Discrete: + the information is stored in cells, kind of like a + spreadsheet. + + Multidimensional: + instead of two dimensions, X and Y, that a spreadsheet + has, a ZigZag space can have any number of dimensions + which are distinguished by strings. + + Locally Euclidean: + a spreadsheet is globally euclidean, i.e. it is a lattice. + ZigZag is only locally euclidean, so the neighborhood of + (i.e. the cells next to) a given cell looks euclidean: + if you go up and come down, you are back where you were before. + + But if you start from location 1, and go up, left, down and + right, you might not get back to where you were, let's + say you are at location 2. But if you then go left, up, down + and right from location 2, you get back to location 1. + + The connections in ZigZag are user-alterable so you can + connect any two cells along any given dimension, but + because of the local euclidean constraint, each cell + can be connected to only one cell in the positive and one + cell in the negative direction on each dimension. + +Computer scientists might note that ZigZag is an interesting special +case of graphs. + +----- +3. What is GZigZag? + +GZigZag is an implementation of ZigZag developed by a research group led +by Tuomas Lukka at the university of Jyvaskyla. + +It is licensed under the LGPL (and XPL, the Xanadu Public License which +is still under works). + +----- +4. Who is the maintainer of GZigZag? + +Tuomas Lukka, . He has written most of the code in GZigZag (and +most of it while traveling on trains). + +This maintainership is by proxy from Ted Nelson, who has the official +maintainership but who does not program. + +----- +5. How complete/stable is GZigZag? + +It's pre-alpha. It is already usable for many things but it is nowhere +near feature complete yet. + +As for stability, crashes are quite rare but the development speed is high. + +----- +6. What are some planned features? + +See Java/TODO in the distribution. + +----- +7. Are there any mailing lists associated with ZigZag/GZigZag? + +See http://www.xanadu.com/zigzag + +----- +8. How can I help? + +Email Tuomas Lukka and ask. + + +============================================================= +Section II: Using (G)ZigZag + +1. How can I learn to create my own structures so that they work well? + +There are some ideas in the document "A Gentle Introduction to ZigZag", +available under the + + Documentation/Gentle_Introduction + +directory on the CVS, or as a postscript file from the web page. + +============================================================= +Section III: Questions specific to the Java version + +1. Why Java? + +Portability, garbage collection, SPEED (with JIT: for linux, IBM's +JDK-1.1.8 is GREAT), portable graphics, easy C interface, available APIs +(e.g. JMF), etc. + +You will note that I did not mention the language itself above: +I don't like the language itself that much: I'd prefer to work in +Perl. Unfortunately it does not provide all of these other features and +the ones it does it does not provide as easily and conveniently as Java. + +----- +1.1 Where do I get Java sources for GZigZag? + +If you know CVS, you can checkout module GZigZag in +:pserver:anonymous@cvs.gzigzag.sourceforge.net:/cvsroot/gzigzag . +Otherwise, you can use our nightly-generated source snapshots +available at ftp://gzigzag.sourceforge.net/pub/gzigzag/snapshots/ . +They are packaged in GNU-Zipped tar archives and in ZIP archives, +choose whichever is best for you. + +The Java sources are located in the Java/ subdirectory of the full +source tree. + +----- +1.2 Where do I get precompiled class files for GZigZag? + +We have a build daemon that builds the current CVS version nighly and +puts two JAR archives of it in +ftp://gzigzag.sourceforge.net/pub/gzigzag/snapshots/ . The +-without-modules version contains the core GZigZag. The -with-modules +version is much larger and contains some additional functionality. + +----- +1.5. It's WAY too slow! Are you out of your mind? + +No. For me, it's quite comfortable on my 233MHz Pentium 80Mb laptop. +There are several possible reasons for this: + +* You are using a Java interpreter without a JIT (Just-In-Time) + compiler. As mentioned in the answer to the previous question, for + Linux, I recommend IBM's JDK 1.1.8. Do NOT ask me about proprietary + operating systems - GZigZag works there but over there you're on + your own for platform-specific questions. Another quite fast JVM is + Kaffe, but unfortunately at least some versions of Kaffe have a + nasty bug that makes using GigZag on it quite unpleasant. + +* Your Java interpreter is not using enough memory. By default, some Java + interpreters only use 16Megs at maximum. Try starting with + + java -mx30m -ms30m foo.Main + + to set it to allocate 30Megs at startup (or more if you have enough memory). + That way it won't be garbage collecting constantly and you may get quite a + significant performance improvement. + +----- +1.5.1. I can't use IBM's JDK: it doesn't have the Swing classes + +You are using an old version of GZigZag. Current CVS versions and +snapshots do not require Swing. + +----- +1.9. I want to report a bug; how do I do that? + +There are instructions about this in http://www.gzigzag.org/bugs.html . + +----- +2. How is the Java code structured? + +ZZCell and ZZSpace are the center of it all. Start from there and +also ZZDimension, ZZDimSpace, ZZLocalDimension, ZZPersistentDimension, +ZZPersistentDimSpace ... +These latter ones are still a bit new and finding their places. + +----- +3. Why is the ZZEventQueue not called / what is ZZObs / ... ? + +Legacy. It's currently supplanted by the ZZUpdateManager for view updates +but may be revived later. + +----- +4. What is the saved file format? + +See the Java/storage/ and Java/media subdirectories of the source +tree, especially storage/Recs.java, storage/ZZPersistentDimSpace.java +and media/StringScroll.java. + +----- +5. Will my files be upwards compatible? + +No: the format will change soon. However, you can dump the space into XML +(will be explained later) and restore it to the new file type. + +----- +6. Are there any coding standards? + +See the file CODING in CVS. + +----- +7. Do you accept patches? + +Yes, we do, but it helps if you consult with us first to make sure your +intended change is in a reasonable direction. Much functionality should go +into the Modules/ as well. + +diff -u (unified diff) is preferred. + + +----- +8. What are the advantages of the new Java version over the old Perl version? + +- Graphics. You just need to see the vanishing view to see why it's important. +And that's just the beginning. + +- Active development. + +----- +9. What are the disadvantages of the new Java version over the old Perl version? + +- Ted's own keystrokes do not yet work (to be fixed soon) + + + +============================================================= +Section III: Questions specific to the Perl version + +1. Wasn't there a Perl version or something? + +Yes, written by Andrew Pam and others. + +----- +2. Are the files from the Perl version compatible with the new Java version? + +No. + +----- +3. Is it possible to import files from the Perl version to the new Java version? + +Not yet, but soon. Only needs a short Perl script to read the DB_File from +the Perl version and write the corresponding XML code and then you can import +it. diff --git a/Documentation/Gentle_Introduction/Makefile b/Documentation/Gentle_Introduction/Makefile new file mode 100644 index 0000000..4f2f387 --- /dev/null +++ b/Documentation/Gentle_Introduction/Makefile @@ -0,0 +1,19 @@ +all: gi.html gi-ns4.html +# zzgentle.tex +zzgentle.dvi: zzgentle.tex + pic -t <$*.tex >$*.tex + latex $* + cat $*.dvi >$*.dvi +ps: zzgentle.ps + +# DIAGRAMS=linkorder.png beamorder.png +DIAGRAMS=../wmlinc/article.wml + +gi.html: gi.wml $(DIAGRAMS) + +gi-ns4.html: gi.wml $(DIAGRAMS) + +include ../lib.mk + + + diff --git a/Documentation/Gentle_Introduction/README b/Documentation/Gentle_Introduction/README new file mode 100644 index 0000000..f9034f8 --- /dev/null +++ b/Documentation/Gentle_Introduction/README @@ -0,0 +1 @@ +Requires latex and the xypic package for latex. diff --git a/Documentation/Gentle_Introduction/gi.wml b/Documentation/Gentle_Introduction/gi.wml new file mode 100644 index 0000000..0975fb7 --- /dev/null +++ b/Documentation/Gentle_Introduction/gi.wml @@ -0,0 +1,586 @@ + + + + + + A Gentle Introduction to Ted Nelson's ZigZag Structure +#include '../wmlinc/article.wml' + + +{: [[s/(?)\b(d\.+\w+)/\1<\/code>/g]] +

A Gentle Introduction to Ted Nelson's ZigZag Structure

+
$Id: gi.wml,v 1.4 2000/10/21 13:45:30 tjl Exp $
+ + Tuomas Lukka
+ lukka@iki.fi
+
+
+ + + +

+This document provides a short introduction to the abstract ZigZag +structure and gives some pointers for designing structures for various +applitudes. Unlike most of the other documentation related to GZigZag, +this document is more about the abstract structure, not this one particular +implementation. + +

+This introduction, even though it is short, is still +rather technical and detailed +and therefore the even gentler manuscript "GZigZag: a platform for +Cybertext Experiments" is recommended to be read before this document. + +

+This is work-in-progress: if there are any unclear parts, feel +free to ask me to clarify things. + + + +

Introduction

+ +

+The best words I've heard to describe the ZigZag structure +are "hyperstructure kit". It is a set of tools or primitives for +building hyperstructures. +ZigZag was invented by Ted Nelson and is currently being implemented +as a prototype at the University of Jyväskylä under the direction of +the author. +The purpose of this document is to introduce +the reader to the ZigZag structure and some example applications of +it. + +

+This document was written using material and ideas from +documents by and discussions with Ted Nelson, +but also contains original ideas and material. + +

+See also the glossary of ZigZag terminology in XXX. + +

Basics

+ +

+To arrive at ZigZag from a general perspective, consider the problem +of storing and visualizing information in a structure. +Now, we naturally need some kind of ``atoms'', i.e.~indivisible +pieces of information --- let's make an atom connected to a piece of text +as the information it carries. Now, atoms should be connected to each other. +Consider the two principles: 1) all connections must be two-directional +and 2) to preserve visualizability, no cell should have an enormous number +of connections. There are of course several different ways of realizing +these principles but ZigZag is a particularly simple one. + +

+ZigZag is a paradigm for manipulating data and devices, a platform +if you may, in some way like UNIX. In UNIX (at least originally), everything +is a file. Whether it is really a printer or the console or a network +connection doesn't matter: the same basic operations (or at least +a subset of +them) is available. ZigZag is quite similar: everything is a cell and +connections between the cells. However, the structure set up by ZigZag is +far richer than a hierarchical file system, allowing more interconnectivity +between related information. + +

+All data in ZigZag consists of cells. +A cell can contain e.g. text, an image +or something like that --- basically, a unit of data. +It does not matter how the content is stored; simply +think of a cell as a little +bit of data that has no significant internal structure (except of course the +sequence for text, the places of the pixels for an image etc). + +FIGURE + +

+
+ +

+The cells are the primitives of the structure and the structure is formed +by connecting cells to each other through dimensions. +In each dimension, each cell can have one positive and one negative +neighbour. This means that all connections between cells are +two-directional: we speak of being neighbour to, or connected to, +not of linking to since linking nowadays means one-directional HTML-like +links. +The different dimensions are denoted by names, such as d.1 or d.clone. + +

+Now, if we have two dimensions and the cells are connected in a regular +lattice, then this corresponds to a normal spreadsheet. However, no +restriction is placed on which positive and negative ends are connected +together - this is why this is called the ZigZag structure. All kinds +of structures are possible: loops, M\oe bius strips, spheres etc. +The kind of structure to choose for your application is up to your +imagination. + +

+However, locally, from the perspective of one or two cells, this will +still look like the spreadsheet: each cell has its neighbours and +you go from it to one direction and then turn around and come back in +the opposite direction, you end up in the same cell. So locally this +structure is logical and simple --- like a spreadsheet --- but globally +it is paradoxical: you can just keep going into one direction and +arrive back where +you came from, for example, or you can go left, down, right and up, +and +{\em not} come back where you started from in the end. +This property gives more room in ZigZag for putting things +in than a spreadsheet has, for instance. + +

+One good way of visualizing this kind of structure is to think a +device commonly found in science fiction books and films: a hallway +with several doors. One door leads to a desert, and another to the +antarctic. When you go through the door, you are in a different place +but you can still walk back through the door, open the other door and +walk through it. At each moment separately, you are operating under +the rules of three-dimensional space known to us but when you pass the +door and realize that you don't see the other door from the other side, +you know that you are in a paradoxical environment. + +

+Another place to look for good, related visualizations, is the work +of M.C.Escher, who has created many paradoxical spaces that would fit +well with ZigZag. However, not all of his paintings work this way: in ZigZag, +directions are global: up is the same ``up'' everywhere, unlike in some +of Escher's work, so care has to be taken with this analogy. + +

+A slightly different way of looking at the structure that may sometimes +help thinking about it is to consider dimensions +as {\em labeled lists} of cells. +That is, instead of considering cells and connections, consider lists (each +list labeled with a string) of +cells where the same cell may be on several lists (but only one +with any given label). +It is not difficult to see that this is exactly the same +structure as above but viewed from a different angle: emphasizing the ranks +instead of the single cell and its connections. + +

+As an example of such a structure, consider a list of people and their +birth years. It'd be quite natural to have first names, last names and +birth years in their own columns, each row being one person. +If done e.g.~on a spreadsheet, you would have to settle +for the global rectangular structure. However, with ZigZag you can +do more interesting things such as have the first names in alphabetical +order, the last names in alphabetical order and finally even the birth +years in numerical order in their own colums. This is because the columns +are independent of each other, bound together simply by having the rows +going across them. Displaying such a structure can be done in several +different ways. +Also, it would then be easy to select subsets of the people on other dimensions, +for example for people who are currently in the same class or whatever. + +

+It is useful to be able to see the structure from both perspectives +since this will both help to overcome the feeling of paradoxicality +from the spreadsheet-like connective picture but also remember that +the cells are important objects in the list picture. + +

Comparing ZigZag with existing computer structures.

+ +

+To put it coarsely, outside ZigZag there are three different kinds of +structures in computers today: linear lists (and grids i.e.~lists of lists), +hierarchical trees and messes. That is really messes, not meshes. By +a mess, I mean any complicated data structure, usually with one-directional +links to make things even more unmanageable. + +

+The first two are inflexible, even with one-directional +hierarchy-crossing links +such as symlinks in filesystems or XML IDs. +The third always requires much +programming and debugging to do and is often hard to visualize. + +

+ZigZag offers a fundamental new kind of structure where encoding +new structures is simple because the coherence of the underlying +simple flexible structure is guaranteed. +At first it may seem strange that a structure that restricts the +number of connections from each cell can be generic but this simple +restriction is what brings about the coherence of ZigZag. +In the sections below you'll see how this restriction does not prevent +any structure from being represented using ZigZag but it enables several +clever visualizations. + +

+Among other things, +ZigZag guarantees that there are no dangling pointers: all links are +two-directional. You can always find which cells refer to a given cell. + +

+One interesting thing to note +about ZigZag and existing structures, +the importance of which I really only realized while doing a demo at Nokia +is simply that by using different dimensions, ZigZag allows you to +arrange the same things into different traditional +structures. So you can have the same cells in a tree along two +dimensions (as you'll see below, trees are easiest done using two +dimensions, one to go from the parent to the first child and the other +to move along siblings), a list along another dimension and a table +along two other dimensions. And possibly another tree in yet two more +dimensions, if desired. +If you use relcells (see below) +you can even put the same things (this time, not cells: you do have to do a step of indirection) +into different structures along the +same dimensions. + +

Viewing

+ +

+Now that the structure is defined, we have to be able to view and edit +it on the computer somehow. Of course, we could just put this +structure in a text file and edit it by naming cells with numbers and +links by naming the cell numbers but this would lose the visuality +inherent in the design. + +

+There are many variations to the theme of viewing +ZigZag structures. Views range from generic to specific views. +Generic views are designed to be useful with a wide range of structures +and usually therefore show only a small number of dimensions +or a small number of steps along each dimension. +Specific views on the other hand are free to do anything that +suits the application at hand. + +

+Specific views are related to applitudes, explained below +in more detail. + +

+In this section, we look at the structure of several generic views. +Before going to the views themselves, let us first define some terms: +the raster and the view. +A raster is a way of selecting cells from the structure. +A view is a way of placing the selected cells on the screen. + +

+In order to look clear to the human observer, visual cues about the +structure are vital. All neighbouring cells that lie next to each other +should be connected with a line, and all cells that have neighbours +that were not displayed because of the raster should have e.g. half of a +connecting line, disappearing underneath the other cell in some visual +fashion to show this. Also, when moving in the structure so that the +part of + + +

2D rectangular views

+ +

+ The 2D rectangular views are characterized by placing the + cells in a spreadsheet-like rectangular grid on the screen. + Even here, there are many different possible + rasters for choosing which cells to place where, since + a general ZigZag structure will not fit a rectangular grid + and parts have to be clipped out. + Note that the 2D here refers to the two-dimensionality of the + rectangular grid, not that there need to be only two dimensions + of the ZigZag structure showing. Usually we only have two + in these views but as we see below, this is not a requirement. + +

+ The two simplest rasters useful for the rectangular views + are the row and column rasters, which are actually + the same raster but placed on the screen rotated 90 degrees + from each other. + These rasters are genuinely two-dimensional: they only + use two dimensions in the ZigZag structure to find cells + to display. + +

+ The row/column raster + starts from the cursor and moves along one ZigZag dimension + and place cells on the center column/row of the grid. + After that column/row is full, the raster starts from + the cells placed and from each, moves along the other + dimension and places the cells found along the other + dimension there. + +

+ These rasters are called hard rasters: + the arrangement of cells is fixed so that there is + only one possible path from the cursor to a cell to be + placed in a given position on the screen. If there is no + cell in the structure along such a path, then that + location is left empty. + +

+ The converse of hard rasters are the soft rasters + where there can be several different paths for + each cell of the on-screen grid. + The point of soft rasters is that since ZigZag structures are + often relatively sparse in terms of connections, the + hard row and column rasters may show relatively few cells at + a time. Soft rasters are able to show more of the structure + at the same time. + +

+ There are many different ways to define soft rasters for + the rectangular grid. One fairly useful way is to specify + the soft raster so that all the cells that a certain hard + raster would show are shown, but additionally, if there + is space left, more cells are shown along the dimensions. + + +

Vanishing view

+ +

+ The vanishing view looks a little like the hard row/column + raster above but is in fact a completely different beast. + The raster for a vanishing view consists of all the cells + within a given 2- or 3-dimensional Manhattan distance + from the cursor (a Manhattan distance simply means the number + of connections in any direction to get from one cell to another). + +

+ These cells are then placed on screen starting with the center + cell and reducing the cell size as the distance from the cursor + grows. This causes cells that would be in the same slot + in the rectangular grid to be plotted apart from each other. + +

+ This could easily be generalized to more than three dimensions. + +

Compass view

+ +

+ The previous views have dealt with a few dimensions but several + steps along those dimensions. The compass + +

Multicentric views

+ +

+ XXX + +

Text view

+ +

+ One simple view that can be easily overlooked is to simply + take a rank of cells and show their texts appended to each other. + +

Applitudes

+ +

+To distinguish itself from the traditional, monolithic applications, +ZigZag uses the term applitude for a "zone of functionality". +The difference between applications and applitudes is the interconnectivity: +whereas conventional, monolithic applications are used to having all data +in their own files, applitudes can easily share cells and simply use +their own, orthogonal dimensions to connect cells. + +

+The differences caused by this simple shift are enormous: instead +of a selection of monolithic blocks, the contents of the computer can +become an interconnected, organic whole. +Everything connected to a particular person, for example, is +connected to the same cell, whether in the email applitude, the calendar, +the collection of documents or anything. + + +

Designing structures

+ +

+In this section, we'll go through some commonly occurring +structural patterns in ZigZag. These can be thought of as being +analogous to Design Patterns in Object-Oriented Programming. +The patterns here are not formalized as far as OO design patterns +but carrying out such a treatment would not be difficult. + +

+As you will see, there are several different ways of encoding +the same conceptual structure in ZigZag. The choice between +using a different dimension or a rank of clones, for example. +These alternative codings resemble in some way one of XML's +similar ambiguities: for example whether to code something as an attribute +or as a contained text-only element. + +

+It is important to understand the difference +between the low-level structure and the implied, higher-level +structure. Single cells and single connections are building +blocks, not necessarily complete entities by themselves. +

Cloning

+ +

+ One of the basic structural mechanisms in ZigZag is + cloning, i.e. connecting cells on d.clone to imply that + they are somehow the same as the root clone, i.e. negend + of d.clone. + +

+ This mechanism is coupled with the cell content: + the contents of all clones is the same as the contents + of the root clone, and editing a clone edits the root clone. + +

+ XXX + +

+ There are alternatives to cloning, and in many cases they + may be preferable. + For instance, in a calendar applitude it would be possible + to clone the cells for persons into the structures + representing meetings but a possibly preferable approach + would be to use an applitude-specific dimension for this. + The reason is that then this dimension would always lead + to predictable structure and the applitude could + easily give interesting visualizations of the meetings + a person participated or will participate in. + +

+ This is a fairly unsettled question. With more experience + in designing different applitudes we will be able to tell easier when + clones are appropriate and when special dimensions are better. + +

Arrangement along a dimension

+ +

+ Sometimes, there is a good, unique way of arranging cells along a + dimension, e.g. alphabetical order. However, sometimes there is not, + or there are two different orders you'd like to have. + +

+ This may seem like a difficult problem but actually, if all + but one of the desired orders are easy to determine from the + neighbours of the cells, then there is no problem at all: instead + of expressing it directly in the structure, those orderings that + are easy to construct algorithmically should be delegated to + the view (as of yet, there are no viewers capable of this but + they are under construction). + +

+ Another alternative (that does not currently work) will be + to thread the cells through several dimensions, most of which + are implicit: for example, an implicit d.1-alphabetic could + have the same ranks as d.1 but alphabetized. The implicit + dimensions would be read-only and be updated automatically + when the corresponding real dimensions changed. + +

+ If there is more than one order that is not easily determinable, + then using two dimensions or cloning becomes a thing to + consider. + +

Many to one reference

+ +

+ Even though the structure only allows only + two connections along each dimension, it + is possible for + many cells to refer to one in ZigZag. + This works by the way outlined above, by building + a higher-level + structure from the low-level building blocks of the cells + and connections. + +

+ There are of course + different ways for creating many to one reference, + but two main ones distinguish themselves. + +

+ If the cell referred is very different from the + cells referring to it, then a single rank, where + the referred-to cell is the headcell is a good choice. + Clones, for example, work this way (see above). + +

+ If the referents can be of the same "type", then + it becomes necessary to allow the cell referred to to + refer to another cell. In such case, a construction called + a corner list is used. + A corner list works by using two dimensions: + the first one connects all the cells referring to a given + cell and the second one connects the referred-to cell + to the headcell of that rank. + There are two main variants: the empty-headed + one where the headcell is + empty and the solid one where the headcell is one of the referring + cells. The insert and delete referring cells operations are + simpler for the empty-headed list since all referring + cells are in the same position but that configuration wastes + one cell. + + +

Hierarchies

+ +

+ A hierarchy can be understood as a many-to-one reference + relation, with the children of a given cell being the + cells referring to it. + +

+ This would make a tree mapped as in the figure XXX. + +

+ It is good to remember that the same cells can be in + several different trees using different dimensions. + +

Relation cells

+ +

+ Relation cells (relcells) are a commonly occurring construct + in ZigZag. Fundamentally, relcells exist to declare a relationship + between two cells or two groups of cells. + +

+ One example of a relcell would be the empty headcell in the + empty-headed version of the corner list above. + However, this is a fairly untypical example. + +

+ Typically, a relcell is on two or more ranks and implies + a relationship between the headcells of those ranks. + This way, each cell can have the same relationship to + several other cells at the same time. + +

+ A good example of the use of a relation cell is + the genealogy applitude (pardon the obvious puns). + The idea is to connect all the siblings on one rank in the family + tree and married couples on another, but this leaves + open the question of representing the children born in the marriage. + This is solved by placing a relcell between the parents, + and hanging the sibling rank off that cell as the headcell. + This relcell then implies a parent-child relationship between + the cells connected to it.. + +

Example applitudes

+ +XXX + +

The Cousin Problem

+ +

+ There is one important problem when dealing with data + that has relations, which the author calls the "Cousin" problem. + Consider the genealogy applitude. + Now, insert a new person, A, and then his cousin, B. + A moment's reflection will show that this is impossible + in the data structure explained above. + +

+ This is because in the human representation of concepts, + there is no hierarchy between mother, father, son, daughter and + cousin. There is no good way to pick just one way to represent + the information since the idea "B is A's cousin" is perfectly + valid, even without knowing whether it is on the mother's or + father's side. + +:} + + + diff --git a/Documentation/Gentle_Introduction/zzgentle.tex b/Documentation/Gentle_Introduction/zzgentle.tex new file mode 100644 index 0000000..c867c85 --- /dev/null +++ b/Documentation/Gentle_Introduction/zzgentle.tex @@ -0,0 +1,1280 @@ +% Copyright(C) 1999 Tuomas J. Lukka +% Redistribution permitted +% +% XXX redo pics in gpic. +% +% +\documentclass[12pt]{article} + + +\usepackage{rcs} +\RCS $Date: 2000/09/13 14:55:57 $ +\RCS $Revision: 1.17 $ +\date{Rev.\RCSRevision~~\RCSDate} + + +\usepackage{umlaut} +\usepackage{times} +\usepackage{xy} +\xyoption{frame} +\xyoption{matrix} +\xyoption{arrow} +\xyoption{curve} +\renewcommand{\Large}{\LARGE} + +\CompileMatrices + +\title{\bf \Huge A Gentle Introduction to +Ted~Nelson's ZigZag\footnote{ZigZag is a trademark of Ted Nelson}~ +structure} +\author{Tuomas J.~Lukka, {\tt lukka@iki.fi}} +\begin{document} +\maketitle +% \begin{abstract} +% \end{abstract} + +\tableofcontents +\listoffigures + +\section{Introduction} + +\def\zz{ZigZag} +ZigZag is a generic data structure, not tied to any particular application +but quite generic in nature. The purpose of this document is to introduce +the reader to the ZigZag structure and some example applications of +it. This document was written using material and ideas from +documents by and discussions with Ted Nelson, +but also contains some ideas the author believes to be original. + +\zz\ was invented by Ted Nelson and is currently being implemented +as a prototype at the University of Jyväskylä under the direction of +the author. + +Note that while the basic structure of \zz, i.e. cells, ranks, dimensions +is fixed, the more particular aspects, i.e. particular dimensions by name, +the actions (executable code in the structure), the interaction between +different \zz\ spaces, distributed \zz\ etc.~are still very much being +developed. We have a prototype and are experimenting with it but +we need more experience with actual applications in order to understand +the system better. +If you feel you can help and want to get in on the action, contact +the author or Ted Nelson himself. + +\section{Basics} + +\zz\ sets up a paradigm for manipulating data and devices, a platform +if you may, quite like UNIX. In UNIX (at least originally), everything +is a file. Whether it is really a printer or the console or a network +connection doesn't matter: the same basic operations (or a subset of +them) is available. \zz\ is quite similar: everything is a cell and +connections between the cells. However, the structure set up by \zz\ is +far richer than a hierarchical file system. + + +\subsection{The \zz\ structure} + +All data in \zz\ consists of cells. A cell can contain e.g.~text, an image +or something like that --- basically, an indivisible atomic unit of data. +It may be implemented in terms of a reference to a larger unit of data +but for now, this is not significant. Just think of a cell as a little +bit of data that has no significant internal structure (except of course the +sequence for text, the places of the pixels for an image etc). + +\begin{figure} +\caption{a) A cell with some data inside (the string ``Cell A''). +b) Two neighbouring cells: Cell B is poswards on the dimension {\tt d.1} +from Cell A (and conversely, Cell A is negwards +on the dimension {\tt d.1} from Cell B. +c) Two intersecting ranks, one in {\tt d.1} and the other in {\tt d.2}. +The cells in the two ranks are BCDE and ADFG. +The negend of the one on {\tt d.1} is B and the posend of the same rank +is E. The negend and the posend of the other rank are A and G, respectively. +% +%Note that there are six other ranks +%in this picture as well, each of length one: +%namely, A, F, G in {\tt d.1} and B, C, E in {\tt d.2}. +%Usually these ranks of length one will not be mentioned or talked +%about as ranks +%but they are still ranks in the sense that every cell is on every dimension. +\label{fig:onecell}} +a) +%\xymatrix{ +%*+[F]\hbox{Cell A} +%}~~~~~ +.PS +boxwid=0.6 +boxht=0.25 +box "Cell A" wid 0.6 ht 0.25 +.PE +\box\graph~~~~ +b) +%\xymatrix{ +%*+[F]\hbox{Cell A} +%\ar[r]^{\tt d.1} & +%*+[F]\hbox{Cell A} +%} +.PS +box "Cell A" same +arrow "\tt d.1" "" +box "Cell B" same +.PE +\box\graph~~~~~ +% \xymatrix { +% && *+[F]\hbox{A} \ar[d]^{\tt d.2}& \\ +% *+[F]\hbox{B} \ar[r]^{\tt d.1} & +% *+[F]\hbox{C} \ar[r]^{\tt d.1} & +% *+[F]\hbox{D} \ar[r]^{\tt d.1} \ar[d]^{\tt d.2} & +% *+[F]\hbox{E} +% \\ +% && *+[F]\hbox{F} \ar[d]^{\tt d.2}& \\ +% && *+[F]\hbox{G} & \\ +% } +.PS +move down ; +right; +B: box "B" wid 0.3 ht 0.25; +arrow "\tt d.1" ""; +C: box "C" same ; +arrow "\tt d.1" ""; +D: box "D" same ; +arrow "\tt d.1" ""; +E: box "E" same ; +move to D.s; +down; +arrow "\tt d.2" ""; +box "F" same; +arrow "\tt d.2" ""; +box "G" same; +A: box "A" same at D .n + (0,0.75) +arrow "\tt d.2" "" from A .s to D .n; +.PE +c)\box\graph +\end{figure} + +\begin{figure} +\caption{a) A paradoxical, non-spreadsheet-like structure. +There are two ranks that are longer than one: BCDE on {\tt d.1} and ADFBG on {\tt d.2} +b) A different view of the same paradoxical structure. +\label{fig:paradox}} +a) +% \xymatrix{ +% && *+[F]\hbox{A} \ar[d]^{\tt d.2}& \\ +% *+[F]\hbox{B} \ar[r]^{\tt d.1} \ar[d]^{\tt d.2} & +% *+[F]\hbox{C} \ar[r]^{\tt d.1} & +% *+[F]\hbox{D} \ar[r]^{\tt d.1} \ar[d]^{\tt d.2} & +% *+[F]\hbox{E} \\ +% *+[F]\hbox{G} && *+[F]\hbox{F} +% \POS"2,1"**\crv{[]-(0,20)&"3,1"-(0,20)&"3,1"-(20,0)&"2,1"+(0,20)}?>*\dir{>}?(.05)*!R!/^5pt/{\tt d.2} +% & \\ +% } +.PS +move down ; +right; +B: box "B" wid 0.3 ht 0.25; +arrow "\tt d.1" ""; +C: box "C" same ; +arrow "\tt d.1" ""; +D: box "D" same ; +arrow "\tt d.1" ""; +E: box "E" same ; +move to D.s; +down; +arrow "\tt d.2" rjust ""; +F: box "F" same; +move to B .s; +arrow "\tt d.2" ""; +box "G" same; +A: box "A" same at D .n + (0,0.75) +arrow "\tt d.2" "" from A .s to D .n; +move to F.s ; +spline down then left 2.1 then up 2 then right 0.5 to B.n ->; +.PE +\box\graph~~~~~ +.PS +boxwid=0.3;boxht=0.25; +down; +box "A"; arrow "\tt d.2"; D: box "D"; arrow "\tt d.2"; +box "F"; arrow "\tt d.2"; B: box "B"; arrow "\tt d.2"; +box "G"; +right; move to D.e; arrow "\tt d.1" ""; box "E"; +move to B.e; arrow "\tt d.1" ""; box "C"; +spline right then down 1 then down 0.5 left 2.0 then up 2.5 to D.w ->; +.PE +b)\box\graph +% \xymatrix{ +% *+[F]\hbox{A} \ar[d]^{\tt d.2} & \\ +% *+[F]\hbox{D} \ar[d]^{\tt d.2} \ar[r]^{\tt d.1} & *+[F]\hbox{E} \\ +% *+[F]\hbox{F} \ar[d]^{\tt d.2} & \\ +% *+[F]\hbox{B} \ar[d]^{\tt d.2} \ar[r]^{\tt d.1} & *+[F]\hbox{C} +% \POS"2,1"**\crv{[]+(30,0)&"5,1"+(20,-10)&"5,1"+(10,-10)&"5,1"+(-5,-10)&"2,1"-(30,0)}?>*\dir{>}?(0.05)*!R!/^5pt/{\tt d.1}\\ +% *+[F]\hbox{G} & \\ +% } +\end{figure} + +The \zz\ structure is organized according to {\em dimensions}. These +are just directions --- normal spreadsheets have two, x and y, and \zz\ +has an unlimited number. Dimensions are told apart from each other by +name --- like {\tt d.1} or {\tt d.clone}. + +In each dimension, each cell has a positive end and a negative end. Each +positive end can be connected to exactly one negative end (and vice +versa) in the same dimension. In diagrams, this connection is often +shown as an arrow or a line, possibly labeled with a dimension if it is +not evident from the context. A cell connected to another cell in the +positive direction on dimension {\tt d} is called the cell's posward +neighbour on {\tt d}. + +Now, if we have two dimensions and the cells are connected in a regular +lattice, then this corresponds to a normal spreadsheet. However, no +restriction is placed on which positive and negative ends are connected +together - this is why this is called the \zz\ {\em structure}. All kinds +of structures are possible: loops, M\oe bius strips, spheres etc. +The kind of structure to choose for your application is up to your +imagination. + +However, locally, from the perspective of one or two cells, this will +still look like the spreadsheet: each cell has its neighbours and +you go from it to one direction and then turn around and come back in +the opposite direction, you end up in the same cell. So locally this +structure is logical and simple --- like a spreadsheet --- but globally +it is paradoxical: you can just keep going into one direction and +arrive back where +you came from, for example, or you can go left, down, right and up and +{\em not} come back where you started from. + +One good way of visualizing this kind of structure is to think a +device commonly found in science fiction books and films: a hallway +with several doors. One door leads to a desert, and another to the +antarctic. When you go through the door, you are in a different place +but you can still walk back through the door, open the other door and +walk through it. At each moment separately, you are operating under +the rules of three-dimensional space known to us but when you pass the +door and realize that you don't see the other door from the other side, +you know that you are in a paradoxical environment. + +Another place to look for good, related visualizations, is the work +of M.C.Escher, who has created many paradoxical spaces that would fit +well with \zz. However, not all of his paintings work this way: in \zz, +directions are global: up is the same ``up'' everywhere, unlike in some +of Escher's work, so care has to be taken with this analogy. + +Another possible way of viewing this structure is the electric circuit view +where the cells are just drawn as blocks with {\tt +} and {\tt -} +connectors labeled with dimensions. Wires (connections) can now be drawn from +any {\tt +} to any {\tt -} connector in the same dimension. + + +Finally, let's go through the vocabulary of \zz: +\begin{description} +\item[cell] The basic unit of information +\item[dimensions] Orthogonal directions along which ranks of cells run. +\item[neighbour] The cell next to another cell on a given dimension. Either poswards or negwards +\item[rank] A number of cells that are neighbours to each others, that is, a list that a +given dimension runs through. Note that all cells are on ranks in all dimensions; many of them +are simply on ranks of length one by themselves. +\item[negwards, poswards] The two directions on each rank/dimension. +\item[negend, posend] The most negwards/poswards cell of a rank. +\end{description} + +The words {\em row} and {\em column} are not on the list, and there +is a reason for this: a row is just a rank viewed horizontally and +a column is a rank viewed vertically. The same rank can be seen, depending +on the view, as either a row or column. + +\subsection{A different perspective} + +A slightly different way of looking at the structure that may sometimes +help thinking about it is to consider {\em labeled lists}. +That is, instead of considering cells and connections, consider lists (each +list labeled with a string) of +cells where the same cell may be on several lists (but only on ones +with different labels). +It is not difficult to see that this is exactly the same +structure as above but viewed from a different angle: emphasizing the ranks +instead of the single cell and its connections. + +As an example of such a structure, consider a list of people and their +birth years. It'd be quite natural to have first names, last names and +birth years in their own columns, each row being one person. +If done e.g.~on a spreadsheet, you would have to settle +for the global rectangular structure. However, with ZigZag you can +do more interesting things such as have the first names in alphabetical +order, the last names in alphabetical order and finally even the birth +years in numerical order in their own colums. This is because the columns +are independent of each other, bound together simply by having the rows +going across them. Displaying such a structure can be done in several +different ways. + +Also, it would then be easy to select subsets of the people on other dimensions, +for example for people who are currently in the same class or whatever. + + + +\begin{figure} +\caption{ +} +XXX!!! +\end{figure} + +It is useful to be able to see the structure from both perspectives +since this will both help to overcome the feeling of paradoxicality +from the spreadsheet-like connective picture but also remember that +the cells are important objects in the list picture. + +\subsection{Arriving at the ZigZag structure} + +To arrive at ZigZag from a general perspective, consider the problem +of storing and visualizing information in a structure. +Now, we naturally need some kind of ``atoms'', i.e.~indivisible +pieces of information --- let's make an atom connected to a piece of text +as the information it carries. Now, atoms should be connected to each other. +Consider the two principles: 1) all connections must be two-directional +and 2) to preserve visualizability, no cell should have an enormous number +of connections. There are of course several different ways of realizing +these principles but ZigZag is a particularly simple one. + +\subsection{Special system dimensions} + +At the time of the writing, some of these dimension are still in GZigZag +with their old names and semantics, most notably d.stepper (which goes +by the handle d.cursor). + +Usually dimensions that are closely related to each other have +related names, like {\tt d.stepper} and {\tt d..stepper-cargo} below. + +Some dimensions have special meaning to \zz. Among them are +\begin{description} +\item[d.clone] The clone dimension. All cells on a clone rank are clones of each other, meaning +that their contents are enforced to be the same and changes to the contents of one are reflected +to the others. + +For example, clones could be used to represent the same email address +on a number of email headers, so that all those instances of the +same email addresses would be linked to each other through {\tt d.clone}. +\item[d.stepper] A pointing dimension. The negend of a rank on +{\tt d.stepper} is the cell being pointed at by all of the other cells +on that rank. + +This mechanism is used for instance by the views to point to the cursor which is +at the center of the view. Moving the cursor is equivalent to inserting +the maincell of the view poswards on {\tt d.stepper} from the new position +of the cursor (the accursed cell). + +\item[d..stepper-cargo] A mechanism for glueing several steppers together, +so that multiple views can share the same center and when one changes, all +change. Details explained in the GZigZag specs. + +\end{description} + +\subsection{Comparison to existing computer structures} + +To put it coarsely, outside \zz\ there are four different kinds of +structures in computers today: linear lists (and grids i.e.~lists of lists), +trees and messes (by +a mess, I mean any complicated data structure). +The first two are inflexible and the third always requires much +programming and debugging to do and is often hard to visualize. + +\zz\ offers a fundamental new kind of {\em structure} where encoding +new structures is simple because the coherence of the underlying +simple flexible structure is guaranteed. +At first it may seem strange that a structure that restricts the +number of connections from each cell can be generic but this simple +restriction is what brings about the coherence of \zz. +In the sections below you'll see how this restriction does not prevent +any structure from being represented using \zz\ but it enables several +clever visualizations. + +\zz\ guarantees that there are no dangling pointers: all links are +two-directional. You can always find which cells refer to a given cell. + +The {\em most} interesting thing about \zz\ and existing structures, +the importance of which I really only realized while doing a demo at Nokia +is simply that by using different dimensions, \zz\ allows you to +arrange the {\em same} things (cells) into {\em different} traditional +structures. So you can have the same cells in a tree along two +dimensions (as you'll see below, trees are easiest done using two +dimensions, one to go from the parent to the first child and the other +to move along siblings), a list along another dimension and a table +along two other dimensions. If you use relcells (see~\ref{sec:relcell}) +you can even put the same things (this time, not cells: you do have to do a step of indirection) +into different structures along the +{\em same} dimensions. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Viewing} + +Now that the structure is defined, we have to be able to view and edit +it on the computer somehow. Of course, we {\em could} just put this +structure in a text file and edit it by naming cells with numbers and +links by naming the cell numbers but this would lose the visuality +inherent in the design. + +There are {\bf many} variations to this theme. For different applications, +different visualizations are of course appropriate but this does not +diminish the fact that underneath all there lies a common structure which +can be visualized in any of the ways, unlike for traditional computer +applications where the structure and the view are usually closely coupled. + +\subsection{Simple 2D raster view} + +A really simple 2D view is obtained by selecting two dimensions and a +``center'' cell. These two dimensions are associated with the X and Y +coordinates and starting from the center cell A, other cells are placed +on a rectangular grid around it, according to the dimensions: let's +say the center cell is placed at coordinates (0,0). Now, if {\tt d.1} +corresponds to X and {\tt d.2} corresponds to Y, and there lies a cell B +poswards from A on {\tt d.1}, then B would be placed at (1,0), and so on. + +Of course, since the \zz\ structure can be paradoxical (it is not +inherently paradoxical in 2D: you can define a structure that looks just +like a spreadsheet), there can be several different cells that would +be typeset at the same point in the 2D diagram. For example, a simple +paradox would be that starting from cell A, going first poswards on {\tt +d.1} and then {\tt d.2} could result in a different cell than first going +poswards on {\tt d.2} and then {\tt d.1}. This is where {\em rasters} +come in. A raster is basically a rule for selecting which cells get +shown in a 2D diagram. There can be several different rasters, from +which the user can select the one best suited for the structure he is +currently viewing. + +The simplest kind of raster, a {\em hard raster} is simply a tree on the 2D +grid: it starts at the center cell and can branch at any cell (including +the center cell) but it will only arrive to each cell once. The cells that +are displayed are chosen by taking exactly those paths that the tree takes +when finding out the cells. If there is no cell in the direction from +the cell being rendered, then that whole branch of the tree is left empty. + +Two rasters, specifically the simplest ones, stand out from among the +possible hard rasters: the horizontal and vertical raster, where the +tree is formed by a single column or row, each cell in which branches +into each row/column. XXX + +\begin{figure} +\caption{The two most common hard rasters. a) row-oriented, b) column-oriented. +Both are shown on a $5\times5$ cell screen.} +.PS +[ +boxwid=0.15; boxht=0.15 +linewid=0.3; lineht=0.3; +up; +C: box; arrow; B: box; arrow; A: box; +down; +move to C.s; arrow; D: box; arrow; E: box; +copy thru % move to $1.e; right; arrow; box; arrow; box; move to $1.w; left; arrow; box; arrow; box % until "END" +A +B +C +D +E +END +] +.PE +a)\box\graph +.PS +[ +boxwid=0.15; boxht=0.15 +linewid=0.3; lineht=0.3; +right; +C: box; arrow; B: box; arrow; A: box; +left; +move to C.w; arrow; D: box; arrow; E: box; +copy thru % move to $1.n; up; arrow; box; arrow; box; move to $1.s;down; arrow; box; arrow; box % until "END" +A +B +C +D +E +END +] +.PE +~~~~~~b)\box\graph +% a) +% \xymatrix @*[F-] { +% & \ar[l] & \ar[l] \ar[r] & \ar[r] & \\ +% & \ar[l] & \ar[l] \ar[u] \ar[r] & \ar[r] & \\ +% & \ar[l] & \ar[l] \ar[u]\ar[d] \ar[r] & \ar[r] & \\ +% & \ar[l] & \ar[l] \ar[d] \ar[r] & \ar[r] & \\ +% & \ar[l] & \ar[l] \ar[r] & \ar[r] & \\ +% } +% ~~~~~b)\xymatrix @*[F-] { +% & & & & \\ +% \ar[u] & \ar[u] & \ar[u] & \ar[u] & \ar[u] \\ +% \ar[u]\ar[d] & \ar[u]\ar[d]\ar[l] & \ar[u]\ar[d]\ar[l]\ar[r] & \ar[u]\ar[d]\ar[r] & \ar[u]\ar[d] \\ +% \ar[d] & \ar[d] & \ar[d] & \ar[d] & \ar[d] \\ +% & & & & +% } +\end{figure} + +A {\em soft raster}, on the other hand is one that does not specify explicitly +how to traverse the cells --- it only specifies how to resolve conflicts +between the cells that would be displayed on the same position and in +which order to ``expand'' cells. A soft raster generally results in more +cells being displayed than a hard raster. An example of a soft raster +would be ``each new cell is expanded; preference is horizontally from +center, vertically from center, horizontally away from center, vertically +away from center''. Incidentally, this soft raster always shows exactly +the same cells at exactly the same positions as the row-oriented raster, +except that it can also show more cells that would have been left out +in the hard raster. + +In order to look clear to the human observer, visual cues about the +structure are vital. All neighbouring cells that lie next to each other +should be connected with a line, and all cells that have neighbours +that were not displayed because of the raster should have e.g. half of a +connecting line, disappearing underneath the other cell in some visual +fashion to show this. Also, when moving in the structure so that the +part of + +\subsection{``Vanishing'' view} + +The vanishing view is a computationally simple way to display 2-4 (or more) +dimensions of the structure. +First, a direction vector is defined for each dimension - for the usual X, Y and Z +they would be (1,0), (0,1) and (1,1). Then, we place the cursor cell at the +center of the screen at size one. We see whether which neighbours exist and +move to the appropriate directions but --- here comes the big innovation --- +we shrink both the size and the direction vectors by multiplying them by 0.9. +Then the process is continued from the last rendered cells, always shrinking. + +In reality, of course, the cells are buffered and rendered in the other direction +since we want the center cell to be on top (and the cells near the center to be +above the ones far from it). + +Other effects may also be applied to clarify the view for the user, such as +graying out the ``far-away'' cells (this is generally called Fog in computer +graphics), thickening the lines of the cells near the center and so on. + +In this view it is important to not render the same cell twice as that would get +even more confusing than with grid rasters. + + +\subsection{Multicentrics} + +\subsection{3D view} + +3-D rastering can be performed in just the same way as 2-D rastering +and visualized by drawing balls and sticks in a 3-D scene. + +XXX + +\subsection{Tree view} + +Since the 2D plane of the \zz\ structure can be viewed as a tree (starting +with 4 branches and branching further at each cell to 3 directions) why +not show it as one? Those places where the structure is not paradoxical +can be shown as regular grids but for the other places, a tree centered +on the home cell and extending outwards can be a good visualization. +The benefit of this view is that it shows {\em all} cells within a +certain range of the center cell --- on the other hand, some of them +may have to be drawn very small, depending on the paradoxicality of +the structure. + +\subsection{Animated cloud view} + +Each dimension has a 2-D vector associated with it and starting from +a given cell, all cells to a given radius are plotted (though not more +than once, even when reached through different paths). +If the vectors are shrunk when going farther from the origin, a view +related to the tree view is obtained. + +Animation and randomity is essential: when this structure rotates, it is +possible to grasp the structure close to a cell. + +\subsection{Pseudo-3D view} + +This view closely resembles a rastered view, except that between the +cells in the grid there are diagonally shown two cells, one poswards +and one negwards of each cell in a third dimension. The connections from +these cells are not shown (but it is shown that they do have connections). + +\subsection{Special, application-oriented views} + +To be correct, instead of application we should use the word {\em +applitude} to distinguish from the traditional kind of monolithic +application. + +For some applications (again: not programs, but rather ``things you do +with \zz''), it is useful to have special views for themselves. This +could include showing some cells from more dimensions around the center +cell than the generic view could do. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Sample structures} + +This section shows some of the possible applications of \zz. +Note that these applications are not applications as in +separate executables that are run to perform a task: that is +old-fashioned thinking. The \zz\ way is to have them all together, +in the same space. This is what Ted Nelson means when he speaks about +applications being prisons: here you can easily link together your +CDs and your pre/reprints and your meetings. + +There is an interesting phenomenon associated with inventing applications +for \zz: when you are first introduced to it, you are astonished at the +things you could do with it but when you start thinking of sample applications, +you may soon draw a blank. + +Interestingly, the reason is likely not to be \zz, but rather the fact that +we have for a long time been trained to think in traditional computer +paradigms and ``paper simulators'' that it is initially hard to see how +the freer multidimensional structure of \zz\ could be of use but slowly, +as you get used to the idea, possible uses will start popping up. +Thinking outside the box is not at all easy. + +\subsection{A CD Player} + +One quite interesting application of \zz\ would be a CD player. +The point is that you can manage the CDs you own, form different +lists of songs on them that you like or that fit particular styles, +download some of them into MP3-files and so on. And play CDs, of course. + +\begin{figure} +\caption{Some view of the suggested CD player structure. +a) The CD player cell, linked to the disk that is in the CD bay and playing +a piece. +The duration along {\tt d.1} is shown only for one piece. +Some of the songs have been cloned and linked to form a short playlist +of my very favorite songs. +\label{fig:cdplayeri} +} +a) \xymatrix@R=0.4cm @C=1.5cm{ +*+[F]\hbox{CD Player} \ar[r]^{\tt d.playing} \ar[rdddd]^{\tt d.playing}& +*+[F]\hbox{Astor Piazzolla / Oblivion} \ar[d]^{\tt d.ondisk} \\ +& *+[F]\hbox{Jeanne y Paul} \ar[d]^{\tt d.ondisk} + \ar[ddddddr]^{\tt d.clone} + \\ +& *+[F]\hbox{En penultimo} \ar[d]^{\tt d.ondisk} \\ +& *+[F]\hbox{Oblivion} \ar[d]^{\tt d.ondisk} \ar[r]^{\tt d.1} + & *+[F]\hbox{4:02 XXX} \\ +& *+[F]\hbox{Enrico IV} \ar[d]^{\tt d.ondisk} \\ +& *+[F]\hbox{Tanti anni prima} \ar[d]^{\tt d.ondisk} \\ +& *+[F]\hbox{Remembrance} \ar[d]^{\tt d.ondisk} + & *+[F]\hbox{Very best of Oblivion} \ar[d]^{\tt d.ondisk} \\ +& *+[F]\hbox{Cavalcata} \ar[d]^{\tt d.ondisk} + & *+[F]\hbox{Jeanne y Paul} \ar[d]^{\tt d.ondisk} \\ +& *+[F]\hbox{Baires '72} \ar[d]^{\tt d.ondisk} + & *+[F]\hbox{Oda para un hippie} \ar[d]^{\tt d.ondisk} \\ +& *+[F]\hbox{Oda para un hippie} \ar[d]^{\tt d.ondisk} \ar[ur]^{\tt d.clone} + & *+[F]\hbox{Fuga} \\ +& *+[F]\hbox{Fuga} \ar[d]^{\tt d.ondisk} + \ar[ur]^{\tt d.clone} \\ +& *+[F]\hbox{Homenaje a Cordoba} \ar[d]^{\tt d.ondisk} \\ +& *+[F]\hbox{En 3x4} \\ +}~~~~~ +\end{figure} + +A part of the structure is shown in Fig.~\ref{fig:cdplayeri}. +There would be one cell, representing the CD player. +Each CD would have its own headcell, containing the CDDB id (or some other +type of checksum by which a disk can be identified). +This cell would be linked to the track cells via {\tt d.ondisk}, which +would be linked to the track +names and lengths via {\tt d.1}. + +When the CD player is playing a piece, it is automatically connected +to one of the disk cells via {\tt d.playing} and one of the track +cells of that disk via {\tt d.playingtrack}. The time is shown +by some other (editable!) cells connected to the CD player cell (not shown here). +If there is a CD changer, +there could be also a dimension {\tt d.inbay} which would link the CD +player to all the disk cells of the disks in the changer. +And of course, you could make the player play a different track by +changing the link of {\tt d.playingtrack} or {\tt d.playing}. + +Now that the structure is defined, we can use it either through +the usual views, or through a special view adapted to this +purpose. + +But the most important thing is that now, unlike in most CD player +applications, even the ones that support CDDB, you can now include +your {\em own} information in this structure. The CD player code +would not mind additional connections to the track cells. +It would then be easy to make a note of (and find it again) on which +of the 60 Bach's Kantatenwerk CDs (there are 10 volumes of 6 CDs each) +that wonderful trio between the oboe d'amore, viola da gamba and continuo +was again. + +Alternatively, you could make playlists using clones along {\tt d.clone} +of the track cells, and linking them along {\tt d.ondisk}, creating +a virtual disk for the CD player. + +This kind of interface where some of the connections are ``magical'' i.e. +where changing the connection causes something to happen, and some are +not magical, is a good example of how \zz\ can be used. +Nice graphical interfaces can now be written on top of this structure +but having the simple underlying structure (like an API, except +data-, not code-based) makes it possible to link all the information +provided by the CD player to other applications. The CDDB entries have +been liberated from the prison of the CD player. + + +\subsection{Managing a collection of virtual pre/reprints} + +In academia, you often collect stacks and stacks of pre/reprints +from colleagues, which are quite difficult to keep properly organized +so that when you search for the information you remember you had +at one point it may take quite a while to find it. + +Computers have brought this problem to a completely different level: +nowadays pre- and reprints are often distributed as compressed postscript +files, and often with non-descriptive names like {\tt aaai1.ps.gz} (which +is descriptive to the author but not to others). +Unless you meticulously rename the files to include the author and +the subject, you will before long be hopelessly lost among virtual +stacks of files --- and there you won't even have the same help from +our intuitive understanding of physical space that you would have had +with physical documents. Also, it's slower to scan compressed postscript +files: it takes a few seconds for the computer to show the first page. + +This is one place where \zz\ can truly help. First of all, you can +organize your preprints in lists according to authors and journals. +You can annotate the files. +But most importantly, after doing this, you can browse them easily +using all the available \zz\ viewers. +And not only this: if you are doing your own academic projects in \zz\ as +well, you can link the relevant publications directly to the area +where you are doing your work. + +You could use a database application for this but they are often clumsy +when entering data and the browsing is not even nearly as simple as in +\zz. + +Of course, this problem is caused by not using reasonable data formats +to start with but this is what we have to work with today. + +Maintaining a similar structure e.g.~in HTML would be a nightmare: +dangling links everywhere etc. \zz\ makes it easy since all links are +2-directional and the structure is easy to edit. + +\subsection{Managing program settings} + +Having programs that allow the user to customize their look and functionality +is great. However, one pet peeve of mine is that these programs often +only allow one set of default settings. If I like to have the program to have +one look in a particular context (e.g.~when doing short documents) +and another in some other context (books), I would always have to click through +the configurations dialog and change the settings. + +Even more horribly, many X11 programs take their configuration from +X resources which are specified by name. Here it is possible to have +different configurations for the same program but they are difficult to +edit and even more difficult (or impossible) to change while the program +is running. + +\zz\ can change all this. Because of the ubiquitous data structure, +a program instance (for example, a view window showing a part of the \zz\ +structure) can be given one settings cell. Starting from this cell, the +program will use prespecified paths to find its configuration information, +all in the \zz\ structure. There are three main benefits: +1) this allows several different configurations +for the same program to coexist, 2) if the prespecified paths are done +in a smart way, configurations can ``inherit'' settings from one another +dynamically and 3) the configuration is simple to change at run time because +of the active notification properties of \zz. + +Since the relationship between the configuration property names and values +is like a list, using {\tt d.1} between the property name and value +and {\tt d.2} to link the properties is natural. +For inheriting properties, we'll just use all cells that have a connection +negwards on {\tt d.inheritsettings}. Fig.~\ref{fig:progset} shows this +structure. + +\begin{figure} +\caption{ +A structure useful for program settings. There are three sets of settings +for the program now, represented by the cells Default, MySpecial, and MyUsual. +Both MySpecial and MyUsual inherit most of their settings from Default but +nothing from each other. +\label{fig:progset} +} +\xymatrix@R=0.4cm @C=0.4cm{ +& & *+[F]\hbox{MyUsual} \ar[d]^{\tt d.2} & & *+[F]\hbox{MySpecial} \ar[d]^{\tt d.2}& \\ +& & *+[F]\hbox{BgColor} \ar[r]^{\tt d.1} \ar[d]^{\tt d.2}& *+[F]\hbox{blue} & *+[F]\hbox{Font} \ar[d]^{\tt d.2}\ar[r]^{\tt d.1} & *+[F]\hbox{weirdsym} \\ +& & *+[F]\hbox{FgColor} \ar[r]^{\tt d.1} \ar[d]^{\tt d.2}& *+[F]\hbox{yellow} & *+[F]\hbox{Animation} \ar[r]^{\tt d.1} \ar[d]^{\tt d.2}& *+[F]\hbox{no} \\ +*+[F]\hbox{Default} \ar[d]^{\tt d.2} \ar[rr]^{\tt d.inheritsettings} & & *+[F]\hbox{~} \ar[rr]^{\tt d.inheritsettings}& & *+[F]\hbox{~} \\ +*+[F]\hbox{BgColor} \ar[r]^{\tt d.1} \ar[d]^{\tt d.2} & *+[F]\hbox{white} \\ +*+[F]\hbox{FgColor} \ar[r]^{\tt d.1} \ar[d]^{\tt d.2}& *+[F]\hbox{black} \\ +*+[F]\hbox{Font} \ar[r]^{\tt d.1} \ar[d]^{\tt d.2}& *+[F]\hbox{Times} \\ +*+[F]\hbox{Title} \ar[r]^{\tt d.1} \ar[d]^{\tt d.2}& *+[F]\hbox{ZZ Window} \\ +*+[F]\hbox{Animation} \ar[r]^{\tt d.1} & *+[F]\hbox{yes} \\ +} +\end{figure} + +\label{sec:appconf} +But now there is a small potential problem: what about misspellings? +If I were to write {\tt bgcolorr} instead of {\tt bgcolor}, the +setting would be quietly ignored. +This is where the fact that \zz\ is a {\em structure} can be incredibly +helpful. Instead of creating new cells with the setting names, we simply +{\em clone} the cells representing the setting names. This can make +our life even simpler if the same cells are used in the documentation: +when you want to change a setting, you simply clone the correct cell +from the documentation, add it to the setting list and write in your setting --- +and of course this process can be automated with a small script. +As a bonus, you'd get a listing of all your settings for a given setting +by simply browsing the structure. +This is not shown as a figure because drawing this in 2D without interaction +and animation is difficult. + +Another place where the structure and links of \zz\ are wildly useful +is font management. It's possible to have a master font list from where +you can clone fonts to smaller, private lists where the fonts you like +are easily accessible and finally clone them to the settings list, +without having to remember the whole name or without having to always +pick the fonts from the long lists of possibilities. + +Due to the generic nature of \zz, the applications of this idea are +not at all limited to program settings. +The same kind of arrangement can naturally work for key- (and mouse-) +bindings as well, +where the setting would be a script that would be run when the key +is pressed. +Another application of this paradigm would be controlling parameter sets +to scientific computations. + +\subsection{Keybindings} + +There is another type of structured information that is generally +rather difficult to manage: keybindings. Most programs fix their keybindings +absolutely, allowing for no customization. Some programs allow the user +to choose which key does what but won't allow multiple states or such. + +In ZigZag, implementing keybindings is ridiculously simple: we simply +define a traversal algorithm that performs some action every time a key +is pressed. The state can be specified by a cursor-like construction. +For example, +\begin{enumerate} +\item 1. +Start from the current cell and move down on {\tt d.2} until a string +matching the keystroke is found. If not found, return. +\item 2. +Move one step on {\tt d.1}. This is the cell giving the name of the action. +Execute action, downwards on {\tt d.2} from here. +\item 3. +Move to the poscell on {\tt d.3} from the action-name cell. +Set the next state to be this. If there is no rank on {\tt d.3} from +the action-name cell, return to the original state. +\end{enumerate} +Additionally, the algorithm can be made to traverse rule sublists +listed on {\tt d.3} from a cell on the action dimension. + +The more mathematically oriented readers will have recognized this +as being a simple state machine --- which is exactly what it is. +The point here is simply that it is easy for the user to edit this state +machine using the ZigZag tools. + + +\subsection{A better {\tt javadoc}} + +Javadoc is the tool used to produce hypertext (in the ``traditional'' sense) +documentation by extracting on-line documentation from java source code +and adding links to the classes of the parameters etc. +This type of documentation is quite useful, giving the programmer +the ability to quickly jump to definitions of related classes. + +Here, however, \zz\ has a lot to give. The problem with javadoc is that +it produces HTML files which are read in a browser which does not understand +the structure of the documentation. Browsing through the package hierarchy +must happen through clicking on links and the back button. + +In \zz, it is easy to handle tree structures + + +\subsection{A personal information manager} + +\subsection{A programmer's editor} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Designing structures} + +There are as many different structures as applications but still there +are some helpful design patterns for \zz\ structures just as in OOP. + +\subsection{Arrangement along a dimension} + +Sometimes, there is a good, unique way of arranging cells along a +dimension, e.g.~alphabetical order. However, sometimes there is not, +or there are two different orders you'd like to have. + +This may seem like a difficult problem but actually, if all but one of the +desired orders are easy to determine from the neighbours of the cells, +then there is no problem at all: instead of expressing it directly in +the structure, those orderings that are easy to construct algorithmically +should be delegated to the view (as of yet, there are no viewers capable +of this but they are under construction). + +This idea applies to the clones and many to one reference sections below. + +If you really need several arrangements, you could consider +a second dimension along which to arrange the same cells, or alternatively +cloning the cells for another arrangement, or even putting dummy cells +next to the cells in some other dimension with the sole purpose of +arranging the cells (this is something that could be done to simulate +email folders so that the same piece of email can be in several +folders at once). + +\subsection{Clones} + +When designing e.g.~an email application, the same person will pop up +often in the correspondence. One good way of keeping track is to have +all the references to the person be clones i.e.~cells having the exactly +the same content, connected to each other along {\tt d.clone}. The head +cell is the ``original one'' into which you'd store other facts about +the person. + +Similarly, clones were suggested for the cells used to name +settings in the example in Sec.~\ref{sec:appconf}. + +\subsection{Many to one reference} + +Having many cells refer to one cell may be conceptually difficult in +\zz\ at first due to the fact that each cell may only have one link +in one dimension. However, this is possible through either clones +or headcells. + +Remember that there is only one headcell per rank --- why not organize all +the cells that refer to the one cell as a rank and have the headcell of +the rank be the cell linked to? It is possible to define special rasters +that take this into account. + +The reason this is better than having many cells referring to one cell +directly by a pointer or something is that now it is easy to ask the +inverse question ``which cells refer to this cell''. The structure is +much more robust because of this: there will be no dangling references, +i.e.~a cell can't be deleted without knowing that there is a link from +somewhere to it. + +In Sec.~\ref{sec:appconf} the dimension {\tt d.inheritsettings} was +used like this: two settings were able to inherit the same set of +settings by defining the headcell in {\tt d.inheritsettings} to be the +settings to be inherited. + +See also the next subsection for a structure for expressing general +relations. + +\subsection{Relation Cells} + +\label{sec:relcell} + +Relation cells (relcells) are a commonly occurring construct in \zz. +Fundamentally, relcells exist to declare a relationship between two +cells or two groups of cells. + + +% .PS +% copy thru % circle at ($1,$2) % until "END" +% 1 2 +% 3 4 +% 5 6 +% END +% box +% .PE +% +% \centerline{\raise 1em\box\graph} + + + +\begin{figure} +\caption{ +\label{fig:relcell} +a) A simple relation cell , marked with a $+$, connecting two cells +to each other. +b) The reason for such relation cells: A is related to C and D but B is +only related to C. This kind of relation is not specifiable without relation +cells. +} +a) +.PS +box "A" +arrow "d.x" "" +box "+" +down; move to last box.s +arrow "d.y" ljust +box "B" +.PE +\box\graph +b) +.PS +box "A" +arrow "d.x" "" +RC1: box "+" +arrow +box "+" +down; move to last box.s +arrow down 1 +box "D" +move to RC1.s +arrow +RC3:box "+" +arrow +box "C" +move to RC3.w +left +line <- +box "B" +.PE +\box\graph +% a) \xymatrix{ +% *+[F]\hbox{A} \ar[r]^{\tt d.x}& *+[F]\hbox{+} \ar[d]^{\tt d.y} \\ +% & *+[F]\hbox{B} +% }~~~~~ +% b) \xymatrix{ +% *+[F]\hbox{A} \ar[r]^{\tt d.x}& *+[F]\hbox{+} \ar[d]^{\tt d.y} \ar[r]^{\tt d.x} +% & *+[F]\hbox{+} \ar[dd]^{\tt d.y} \\ +% *+[F]\hbox{B} \ar[r]^{\tt d.x}& *+[F]\hbox{+} \ar[d]^{\tt d.y} \\ +% & *+[F]\hbox{C} & *+[F]\hbox{D} +% }~~~~~ +% c) \xymatrix{ +% *+[F]\hbox{A} \ar[r] +% } +\end{figure} + +As shown in {\tt fig:relcell}, +the basic relcell denotes an association between one endcell of one dimension +and another endcell of another dimension. + +This is not the only kind of relcell there is: a different type is +one that relates many cells to one, in such a way that many different +sets of cells can be related to the same cell. This kind of relation +is useful for e.g.~cursors. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Programming \zz} + +This section explains how scripts can be used in \zz. Also, +we discuss how the view applications can be made simple +through clever use of scripts. + +\subsection{The scripting API} + +The most basic operations in \zz, expressed with parameters +\begin{description} +\item[new cell(cell, dim, posneg)] Create a new cell from the given cell in the given +dimension, in the given direction. +If a cell already exists in that direction, insert this new cell between +the current cell and the existing cell in the same rank: +the rank ABCDE, if the new cell n is inserted poswards from C, +becomes ABCnDE. The other connections from all cells are unaffected. +\item[delete cell(cell)] Delete the given cell. +\item[link(fromcell, tocell, dim)] Create a connection between fromcell and tocell along dimension +dim. +\item[delete link(cell, dim, posneg)] Delete the link from the given cell in the given dimension +and direction. +\item[set cell contents(cell, data)] Set the contents of the cell to data. +\end{description} +In a visual environment, you give the parameters by clicking etc. but the basic +operations are still the same. + +Now, these are the absolute minimum operations to get by: they are +definitely not a complete set of useful operations. +All the advanced operations can be defined through these operations, though. + +There are a number of more complicated editing operations that deal with ranks: +\begin{description} +\item[jump(cell,dim,posneg)] In its rank on dimension dim, hop this cell over its neighbour. +The rank ABCDE, if B is jumped poswards, becomes ACBDE. No other connections from the cells are affected. +\end{description} + +XXX Shearing + + +\subsection{Scripts} + +Currently, a cell with a \verb+#+ sign in front of it can be +interpreted as executable code. The code gets as its parameters +the cell the code was in and one parameter cell (possibly also a +cell representing a viewer in the future). + +\subsection{Editing via scripts} + +The interface to edit the \zz\ structure in our prototype is encoded +mostly in terms scripts: the only operation the viewer knows about +is executing one cell on another cell. The viewer does not know how +to e.g.~create a new cell or link cells. + +This gives us a surprising amount of flexibility in the user interface. +For instance, if we want to have a {\tt Skip to} operation in our +CD player, we can simply write a small script in a cell that finds +the CD player that is playing the disk and connects it along the +{\tt d.playingtrack} dimension to the cell the {\tt Skip to} script +was executed on. We can then bind either tell the viewer to execute +this action or even specify a special binding for it in the viewer +configuration (which is also stored in the \zz\ structure). + +\subsection{Watches} + +(DRAFT!) +It is possible to place scripts in the structure which are run whenever +some part of the structure is changed. This is how the CD player example +above would be implemented. +This is a very simple mechanism: the scripts are placed along a +dimension {\tt d.watch} from the cell which (and the connections of which) +are being watched. Whenever the cell or one of its connections is changed +or deleted, the scripts are run. + +XXX watching a watcher? + +\section{Versioning} + +NB. This section is subject to change. It is meant to be a sketch for +implementing versioning for \zz\ and is by no means final. +This is currently not yet implemented. + +Normally, on computers, if you edit a file and save it, the previous +version is gone. You have changed the contents of the file and now the +new contents is all you can see. There are programs, like RCS and CVS, +that can be used to store and track the changes to a single file or to +a group of files. There are even versioning filesystems where you +are able to retrieve the previous versions of your files. + +In \zz, versioning is inherent in the structure: the previous versions +are accessible through simply browsing the structure itself. + +In \zz, there are two kinds of storage for cells: transient and permanent. +Cells in transient storage are treated just like normal files: when +they are deleted they are gone, or when they are changed, the previous +form is not accessible. This is what is currently being implemented in +our prototype. + +Permanent cells (the recommended type of storage in the future) are +a more interesting case: when you delete a permanent cell, you are +actually only deleting all the links to it --- or more accurately, you +are creating a new version of that cell and all its neighbours, and in +this new version, the connections between the cell being ``deleted'' +and its neighbours do not exist. Nothing is deleted from the storage; +only information about the changes is added. In permanent storage, it is +possible to access all the previous versions of any part of the structure. + +The parts of the structure that deal with versions are a good example +of {\em virtual cells}, which you can view and sometimes (depending +on the context) alter or at least link to, but which do not necessarily +exist in the same way as ordinary cells but are generated on the fly +by the \zz\ server from the information it has. + + +\subsection{Cell Identity} + +In order to distinguish between different versions of a cell, there are +two different types of cell ids. The LID (Lifespan ID) refers to all the +versions of a cell at the same time, i.e.~it refers to one rank in the +dimension {\tt d.cellversion}. The posend of that rank is the current +version of the cell. The VID (Version ID) refers to one particular +version of the cell, i.e.~that cell at all moments between two changes +that occurred to that cell. + +The {\tt d.cellversion} dimension is generally not what you want to use +since it tracks changes to that one cell only. It jumps right over any +changes to a neighbouring cell or any other cell. + +The {\tt d.version} dimension is another versioning dimension. This is +the global version, which changes for every cell when even one change +is made anywhere in the structure (a number of changes may be committed +simultaneously though). + +\begin{figure} +\caption{An example of how {\tt d.version} works. +In this example, we start with two cells, A and C. First, a new cell B is created +on {\tt d.1} from A, and then this new cell is connected to cell C and finally a new cell +D is created negwards on {\tt d.1} from A. +The straight arrows show {\tt d.globalversion} horizontally and {\tt d.1} vertically. +The curved arrows show {\tt d.cellversion}. Note how they skip several of the global versions +since nothing happened to that cell. All the connections along {\tt d.cellversion} are shown, +so it is important to notice that there is no neighbour in that dimension for many cells, only +the {\em last} cell representing each cell version. +The cells are vertically aligned by time. +Also, note that if there were more cells and they had been changed, there would be one more step +in {\tt d.globalversion} for each change not visible here. +} +\xymatrix{ +& & & D \ar[d] \\ +A \ar[r] \POS"2,3"**\crv{[]+(20,20)}?>*\dir{>} & A \ar[r]\ar[d] +& A \ar[r]\ar[d] \POS"2,4"**\crv{[]+(10,20)}?>*\dir{>} +& A\ar[d]\\ + & B \ar[r] & B \ar[r] \ar[d] & B \ar[d]\\ +C \ar[r] +& C \ar[r] \POS"4,4"**\crv{[]+(20,20)}?>*\dir{>} +& C \ar[r] & C\\ +} +\end{figure} + +\subsection{Scrolls} + +One of the fundamental concepts in the Ted Nelson's Xanadu system is that +of {\em scrolls}. A scroll is a storage form of data into which new data +is appended but old data is never removed --- it is essentially carved +in stone as it arrives. The data in scrolls is used by pointing to it. + +%%%%%%%%%%%%%%%%%%%% +\section{Distributed \zz} + +Like the section on versioning, this section is at best a raw sketch +of the functionality. + +\subsection{\zz\ remote protocol} + +In order to allow different \zz\ processors to interact, we have +defined a \zz\ data protocol. The protocol is an active one and has +state --- so it is more suitable between processes on the same machine. +A passive, stateless protocol is under planning. + +The protocol allows a client to be informed whenever any cell changes +(the client has to explicitly request to be informed about a cell, though), +change the structure, or run code. + +The protocol is still not finalized. + + +\subsection{Slices} + +There can be several different data sources: for instance, files on a disk +could be represented by a process that serves \zz\ cells through looking +at the filesystem, or \zz\ structures from different computers on a network +could be represented as data sources. + +In general, all different sources of data in the sense that they provide +a collection of \zz\ data are called slices. + +\section{ZZ Programs} + +So far, we have been talking about \zz\ on a fairly abstract level. In +this section, we'll start looking at some implementation details that +make \zz\ special. + +\subsection{Model-View-Controller} + +The Model-View-Controller (MVC) paradigm was introduced with SmallTalk. +The idea is that instead of programming a graphical program like spaghetti, +you'd clearly separate the data that is being represented, the views +of the data and whatever changes the data (the controllers). +The view and the controller are usually a part of the same object, so +that you can e.g.~drag pieces of a diagram but the point is that the +view and the controller do not communicate with each other. +The controller changes the model and then {\em all} the different views +get updated as well. + +The Model in \zz\ is of course the \zz\ structure. +Changing the raster would be achieved {\em not} by changing some +internal variable of the graphical client but rather by changing the +part of the \zz\ structure that represents the client. +Likewise, the cursors of the various views are represented in the structure +as are the selected dimensions and rasters. + +In the \zz\ system, using a MVC structure pervasively has many benefits. +First and foremost, it brings configuration and run-time data of +the \zz\ programs to the same area as the other data. This way +all the facilities of \zz\ for scripting and editing can be used +for these as well. As an example, writing a small script that finds +the next {\em relevant} dimension to show in X direction is trivial +when all the data is in the \zz\ structure but doing the same if the +application were built in a traditional way is next to impossible --- or +at least difficult, requiring a special API provided by the application. + + + + + +\end{document} + + diff --git a/Documentation/Glossary/Makefile b/Documentation/Glossary/Makefile new file mode 100644 index 0000000..404b0c8 --- /dev/null +++ b/Documentation/Glossary/Makefile @@ -0,0 +1,10 @@ +# DIAGRAMS=linkorder.png beamorder.png +DIAGRAMS=../wmlinc/article.wml + +all : gl.html gl-ns4.html + +gl.html: gl.wml $(DIAGRAMS) + +gl-ns4.html: gl.wml $(DIAGRAMS) + +include ../lib.mk diff --git a/Documentation/Glossary/gl.wml b/Documentation/Glossary/gl.wml new file mode 100644 index 0000000..f518d09 --- /dev/null +++ b/Documentation/Glossary/gl.wml @@ -0,0 +1,186 @@ + + + + + + GZigZag Glossary + +#include '../wmlinc/article.wml' + + + + + +

GZigZag Glossary

+
$Id: gl.wml,v 1.3 2000/09/19 10:31:57 ajk Exp $
+ + Tuomas Lukka
+ lukka@iki.fi
+
+ +

+This is a short glossary of terminology related to GZigZag. +Only a short definition of each term is given, possibly with +a reference to more material on the subject. + + + +


+
+
ZigZag structure / space +
A simple structure, based on cells and dimensions + which the user is able to easily shape into any desired + structure. All interrelated pieces of information can be + close to each other on some dimension. +
cell +
The smallest unit of information in ZigZag. + A cell can contain a text string or + a single span in a permascroll; the separation is + because a text string can be edited but a span can only + be lengthened or shortened: no characters can be + inserted. Cells are connected to each other along + dimensions. +
dimension +
Connecting cells along dimensions is what ZigZag is + about. Locally, dimensions work just like on a spreadsheet: + each cell can be connected to one cell in the positive + direction and to one cell in the negative direction + along each dimension. However, there are no global constraints + between the dimensions. + +
headcell +
The negend of a rank, or, for + circular ranks, a specially designated cell. + If a rank of cells has one "special" cell, then + it is usually the headcell. + + +
neighbour +
Cells that are connected along a dimension are + called each other's neighbours. Often, the term + posward or negward is used with this term as in + "the negward neighbour on d.cursor". + +
posward/negward +
In the positive/negative direction along a rank. + +
posend/negend +
As far as you can go negwards or poswards. + Circular ranks have no ends. + + +
rank +
A rank on a dimension D is simply a set of cells that are + connected to each other on D. A given cell can only + be on one rank on a given dimension. + +
raster +
A set of cells selected from the structure + by a set of rules, for visualization. + For example, the row and column raster select, + starting from the cursor, + a single rank in one dimension + an all ranks in another dimensions that + intersect that rank. + The raster for the vanishing view selects all + cells within a given radius of the cursor. + +
relcell, or relation cell +
A cell which exists not for its content but for + expressing a relationship between other cells. + For example, the cell between a father and mother + in the family tree demo is a relcell. + +
row/column +
These words simply correspond to ranks + being viewed horizontally/vertically. + They do not mean anything in the abstract structure, + but only in the visualizations. + +
view +
A way of placing the cells in a particular + raster on the screen. + +
+
+
+ +
FloatingWorld +
Ted Nelson's design built on top of ZigZag structure, + based on flobs. +
flob +
A multi-dimensional flying object. That is, an entity + representing something that may have any number of + flob coordinates. For example, an email's sender is one + flob coordinate, its subject another. + +
+
+
+ + +
Xanadu88 +
A hypertext system, finished in 1988, which works by + stable fluid media content instead of URL-like pointers. +
fluid media +
Any media types that can be subdivided. + Text, audio, video, images. +
permascroll +
A storage philosophy for fluid media where + each smallest unit (e.g. character of text) + is assigned a permanent identifier when + it first enters the system. Of course, + references to the smallest units usually happen + through spans for efficiency. +
span +
A (reference to a) contiguous section of the permascroll. +
vstream +
A list of spans that describe a virtual stream of + fluid media. A "document" or one version of a document. + Modifying a document does not modify the permascroll, except + by appending new inserted characters. Instead, the spans + of the vstream are modified: split apart, new spans + inserted etc. +
transclusion +
The inclusion of the same material in a permascroll in + two different documents. One of the fundamentals of the Xanadu88 + model is that it is efficient to search for transclusions + of a given span. +
transpointing windows +
Windows on a computer screen that show the connections or + transclusions between each other. + +
transcopyright +
A copyright scheme where the copyright holder + grants the public a permission to refer to any + portion of a given document and publishes the document + in a permanent location. + This way, anyone can quote the document by referring + to it and the reader's browser will then go to the + originator's server for the original material so that + a micropayment can be made to the original author + of the material. +
+ +
+ + + + + + diff --git a/Documentation/Interfacing/Makefile b/Documentation/Interfacing/Makefile new file mode 100644 index 0000000..f802aa5 --- /dev/null +++ b/Documentation/Interfacing/Makefile @@ -0,0 +1,6 @@ +int.dvi: int.ptex + gpic -t int.tex + latex int.tex +ps: int.ps +int.ps: int.dvi + dvips int diff --git a/Documentation/Interfacing/int.ptex b/Documentation/Interfacing/int.ptex new file mode 100644 index 0000000..55191ee --- /dev/null +++ b/Documentation/Interfacing/int.ptex @@ -0,0 +1,141 @@ +% MAKE SURE YOU EDIT THE RIGHT FILE, int.ptex and not the int.tex +% file where gpic has already expanded things. +\documentclass{article} + +\usepackage{rcs} +\RCS $Date: 1999/12/23 01:53:35 $ +\RCS $Revision: 1.3 $ +\date{Rev.\RCSRevision~~\RCSDate} + +\title{Interfacing ZigZag with ``normal'' programs} +\author{Tuomas J.~Lukka} +\begin{document} +\maketitle + +\def\zz{ZigZag} + +\section{Introduction} + +\zz\ defines a coherent universe of cells and things that happen +when cells are modified and connected to each other. +However, since the computer and windowing system underneath don't know +anything about \zz, there is a level on which the \zz\ abstraction +and ``normal'' programs in e.g.~Java meet, so that \zz\ can be implemented +in e.g.~Java. +Because \zz\ is so different from our usual programming concepts, +an interface like this is not trivial to design correctly and +efficiently. + +While the basic operations are simple, i.e.~get neighbour, connect, +create new cell etc., the handling of the interface in a coherent way +on both sides is not simple. +As an example of the difficulty, consider +keeping a list of some attributes that you want the screen to show. +It doesn't matter what these are attributes of, or how they are shown. +We are concerned with the list itself. + +\section{Model-View-Controller} + +When programming with \zz, the MVC (Model-View-Controller) representation +is a useful abstraction, the point being that all the relevant information +is kept inside the \zz\ space with many different views of the same +data being then possible. + +Let us then expand on the list-of-attributes problem. +The natural representation for a list of attributes +is rank along some dimension +in the \zz\ space, beginning at some designated cell. +Having the list in the \zz\ space gives the system the kind of +programmability and coherence which you won't find anywhere else. +However, this programmability and coherence does not come entirely +free. The trouble is when your e.g.~Java code which actually handles +the drawing on screen wants to use the list. + +Just reading the list with the above operations is easy, you just +start at the designated cell and work your way through the list. +The trouble starts when the user modifies the list. At that point, +the user's expectation is that the display will change accordingly. +So your program should realize that the list changed. + +This can be handled through callback routines but the problem is +keeping the callbacks up to date as well and handling the overzealous +callbacking with grace (e.g. if the user makes many modifications and +some while the system is busy rerendering the graph). + +\section{Synchronization} + +When several concurrent processes or threads are active on the +same \zz\ space, care is necessary to avoid race conditions (as +in all other programming with concurrent streams of execution). + + + +\section{A proposed solution: {\tt d.watchers} and {\tt d..watching}} + +As seems to happen often with \zz, the problems can be partially +solved by moving the system to \zz\ space. +So, why not have two dimensions (see the section on relcells +in the Gentle Introduction) showing the relationship between +nodes representing observers and nodes representing watchers? + +This simplifies things because there will be one cell on the \zz\ side +representing the Java object which is observing a group of cells. +The ``A observes B'' relation is encoded into the \zz\ structure +as in Fig.~\ref{fig-enc} +and makes it possible visualize and {\em debug} what is going on. + +\begin{figure} +\caption{Encoding watching relations in the \zz\ structure. +Watcher A watches both cells 1 and 2 and watcher A only watches +cell 1.} +.PS +A: box "Watcher B" height 0.25 +arrow "\tt d..watching" "" +box "" same +up +move to last box.n +line <- "~\tt d.watchers" ljust +R1: box "" same +right +move to last box.e +arrow +R2: box "" same +move to R1.w +left +line <- +B: box "Watcher A" same +move to R1.n +up +line <- +box "Cell 1" same +move to R2.n +line <- +box "Cell 2" same +.PE +\centerline{\raise 1em\box\graph} +\end{figure} + +Also, the relcells can be put to another use beyond just showing +that there is a relation +in this design: they show the {\em kind} of watching relation, +i.e.~contain a list +of things that the other cell is observing about the observed cell, +such as the content or the connections along some subset of dimensions. +This makes it easier to avoid unnecessary work in the list example +if someone wants to comment (along {\tt d.comment}) on one of +the cells in the list. + +Even more pleasantly, this design will fit in nicely with Clang: +the cell which is observing can just as well be a Clang script. + +\section{Designing \zz-code interfaces} + + + + + + +\end{document} + +% +% vim: set syntax=tex : diff --git a/Documentation/Makefile b/Documentation/Makefile new file mode 100644 index 0000000..3eb5138 --- /dev/null +++ b/Documentation/Makefile @@ -0,0 +1,39 @@ +all: + echo "Use a target" + +docdirs=ApplitudeWriters Clang_Design CyberText DesignProblems Gentle_Introduction Glossary Spec UsersGuide Nile + +distdocs: + set -e ; for d in $(docdirs); do $(MAKE) -C $$d all ; done + +dist: distdir=docdisttree +dist: distdocs + rm -rf $(distdir) + mkdir $(distdir) + ln FAQ $(distdir) + ln index.html $(distdir) + set -e; for d in $(docdirs); \ + do \ + echo -n "mkdir $(distdir)/$$d...";\ + mkdir "$(distdir)/$$d"; \ + echo "done."; \ + files=`find $$d -name \*.html -o -name \*.png`;\ + echo "Copying `echo $$files` to $(distdir)/$$d..."; \ + ln -f $$files $(distdir)/$$d; \ + echo "done."; \ + done + +ps: + (cd CellScroll; make ps) + (cd Clang_Design; make ps) + (cd Gentle_Introduction; make ps) + (cd Interfacing; make ps) + (cd Spec; make ps) + +# Special target for Tjl only ;) +mvps: ps + scp */*.ps tjl@gzigzag.sourceforge.net:/home/groups/gzigzag/www/ps/ +cleanps: + rm -f */*.ps +clean: cleanps + rm -f */*.dvi */*.log */*.xyc */*.pdf diff --git a/Documentation/Math/Makefile b/Documentation/Math/Makefile new file mode 100644 index 0000000..58a4523 --- /dev/null +++ b/Documentation/Math/Makefile @@ -0,0 +1,3 @@ +all : math.dvi math.ps + +include ../lib.mk diff --git a/Documentation/Math/ajk-scribbles.tex b/Documentation/Math/ajk-scribbles.tex new file mode 100644 index 0000000..067adf4 --- /dev/null +++ b/Documentation/Math/ajk-scribbles.tex @@ -0,0 +1,60 @@ +\documentclass{article} + +\usepackage{bbm} +\usepackage{amsmath} + +\newcommand{\N}{\mathbbm{N}} + +\newtheorem{Def}{Definition} +\newtheorem{The}{Theorem}[Def] + +\DeclareMathOperator{\Dom}{Dom} +\newcommand{\Dim}[1]{\tilde{#1}} + +\begin{document} + +Note: we assume here that dimensions are cells instead of strings. + +\begin{Def}[space] +A ZigZag space is the triplet $Z = (X, c, C)$ where $X$ is the set of +cells, $c : X \rightarrow \Sigma^*$ is the cell content mapping +and $C \subset X^3$ is the set of connections, if the following hold: +% +\begin{enumerate} +% +\item If $(d, e, f) \in C$ and $(d, e', f) \in C$ then $e = e'$. +% +\item If $(d, e, f) \in C$ and $(d, e, f') \in C$ then $f = f'$. +% +\end{enumerate} +\end{Def} + +\begin{Def}[subspace] +A ZigZag space $Z' = (X', c', C')$ is a subspace of another ZigZag +space $Z = (X, c, C)$ if the following hold: +% +\begin{enumerate} +% +\item $X' \subset X$ +% +\item $c'(x) = c(x)$ for every $x \in X'$. +% +\item $C' \subset C$ +% +\end{enumerate} +\end{Def} + +\begin{The} + Let $Z = (X, c, C)$ be a ZigZag space. For every $d \in X$, there + exists a maximal $X' \subset X$ and a unique $\Dim{d} : X' + \rightarrow X$ such that for every $x \in X'$ it holds that $(d, x, + \Dim{d}(x)) \in C$. Additionally, $\Dim{d}$ is an injection. +\end{The} + +\begin{Def}[clone dimension] + Let $Z = (X, c, C)$ be a ZigZag space. We say that $d \in X$ is a + clone dimension if, for every $x \in \Dom d$ it holds that $c(x) = + c(\Dim{d}(x))$. +\end{Def} + +\end{document} diff --git a/Documentation/Math/math.ptex b/Documentation/Math/math.ptex new file mode 100644 index 0000000..642318b --- /dev/null +++ b/Documentation/Math/math.ptex @@ -0,0 +1,110 @@ +% Emacs, note: this is a -*- LaTeX -*- file. +% MAKE SURE YOU EDIT THE RIGHT FILE, math.ptex and not the math.tex +% file where gpic has already expanded things. +\documentclass{article} + +\usepackage{rcs} +\RCS $Date: 2000/07/18 05:21:50 $ +\RCS $Revision: 1.3 $ +\date{Rev.\RCSRevision~~\RCSDate} + +\usepackage{amsmath} + +\title{Mathematics of ZigZag} +\author{Tuomas J.~Lukka} +\begin{document} +\maketitle + +\newtheorem{theorem}{Definition}[section] +\newtheorem{definition}[theorem]{Definition} + +\section{Introduction} + +The purpose of this document is to look at ZigZag from a +mathematical perspective. + +It is slowly becoming more and more obvious that this type of analysis +can help us understand some of the conceptually less clear parts of ZigZag +and why they are conceptually less clear. + +\section{Tumblers} + +\section{Definition of a ZigZag space} + +\begin{definition} +% A ZigZag space $Z$ is the tuple $(C, d, t)$ of the set of cells $C$, +% a mapping $d$ from strings to bijections between subsets of $C$, +% and a mapping $t$ from cells to cell contents +% (either permascroll spans as tumbler addresses or strings) +A ZigZag space $Z$ is the tuple $(C, d, t)$ of the set of cells $C$, a +mapping $d$ from strings to the set \( D := \{ \, f\colon $C'$ +\longrightarrow $C''$ \mid \text{$f$ is bijective and } C', C'' +\subset C \, \} \) and a mapping $t$ from cells to the set of all +possible cell content (permascroll spans as tumbler addresses or +strings). +\end{definition} + +Now, special dimensions can be defined simply as restrictions on +the space; for instance, as predicates: +\begin{definition} +The ZZspace $Z$ has a clone-dimension $d_0$ iff +for all cells $c$ for which $d(d_0)(c)$ exists, $t(d(d_0)(c)) = t(c)$. +\end{definition} + +Likewise, we can define a versioning operation: +\begin{definition} +A ZZ operation $o: Z \rightarrow Z'$ is versioning +if ... XXX +\end{definition} + + +\section{Solving real problems} + +\subsection{Slice spaces} + +It is possible to highlight some problems related to defining operations +and combinations of spaces with this type of analysis. One observation +made early on in the coding was that encapsulation makes it complicated +to define operations on e.g.~slice spaces (spaces that consist of a +combination of several spaces). For example, in $C = f(A,B)$ the ZZspace +is $C$ a slice space if it contains cells corresponding to most cells +of $A$ and $B$ (excluding {\em preflets}, i.e. cells whose meaning is to +specify for $f$ which cells are to be connected between $A$ and $B$). + +The forwards transform is simple: $C = f(A,B)$ as above. +However, problems begin to appear when we consider that normally +performing an operation functionally: $A' = \Omega(A)$ causes $A'$ to be +saved on the disk to replace $A$. $C' = \Omega(C)$ cannot do the same +as simply because we would like to trace the chain to change $A$ and $B$, +obtaining $(A', B') = f^{-1}(\Omega(f(A,B)))$. This can naturally be quite +complicated. Most combination functions $f$ used in reality are nice but still +this causes a pronounced difficulty in coding the usual operations +(new cell, etc) on slice spaces if starting from this perspective. + +Thus, the conceptually simplest way forwards might be defining a whole +new kind of mathematical object, a slice space, which has its own +operations that naturally distribute to the next level. +After this it is simple to define performance enhancements by caching parts +of the next level space but the conceptual simplicity of directly modifying +only the underlying representation (instead of e.g.~the representation {\em and} +a cache) is appealing. + +\begin{definition} +A Slice space $S$ is a +tuple $(Z_0, s)$ where $Z_0$ is the slice 0, i.e.~the root space, +and $s$ is a mapping from strings to ZigZag spaces +\end{definition} + +\begin{definition} +A slice composition function +$f_c$ is a mapping +$S \rightarrow Z$ +from a slice space to a ZigZag space (the composition function). +\end{definition} + + + +\end{document} + + + diff --git a/Documentation/Mediaserver/mediaserver.tex b/Documentation/Mediaserver/mediaserver.tex new file mode 100644 index 0000000..6f48700 --- /dev/null +++ b/Documentation/Mediaserver/mediaserver.tex @@ -0,0 +1,387 @@ +% This is a -*- LaTeX -*- file. +\documentclass[a4paper]{article} + +\newcommand{\ra}{\ensuremath{\rightarrow}} + +\ifx\dontdraft\undefined +%Draft +\newcommand{\marginaali}[1]{\marginpar{#1}} + +\setlength{\marginparwidth}{3cm} +\setlength{\textwidth}{13cm} +\setlength{\oddsidemargin}{1.3cm} +\else +%Non-draft +\newcommand{\marginaali}[1]{} +\linespread{1.6} +\fi + +\newcommand{\nakki}[1]{\marginaali{\textbf{\small Nakki: #1}}} +\newcommand{\ajk}[1]{\marginaali{\small ajk: #1}} +\newcommand{\tjl}[1]{\marginaali{\small tjl: #1}} + +\begin{document} + +\title{GZigZag mediaserver (to be renamed!) design} +\author{Tuomas J.\ Lukka \and Antti-Juhani Kaijanaho} +\date{2001} + +\maketitle + +\begin{abstract} +The purpose of the mediaserver is to implement +the Xanadu permascroll model +in an easy-to-use encapsulated fashion. + +The mediaserver incorporates both peer-to-peer and +client-server transfer of data. + +This ties in with Ted's other projects, and the intent +is to produce a simple but powerful system completely independent +of GZigZag (GZigZag is on a higher level and uses this as a library). +(The source code is currently in the GZigZag repository but +we might make a new project out of it at some point) +\end{abstract} + +\begin{verbatim} +$Id: mediaserver.tex,v 1.12 2001/04/03 11:23:58 ajk Exp $ +\end{verbatim} + + +\section{Intro} + +The Xanadu media model is based on attaching a permanent identifier +to each piece of fluid media (e.g. text, audio) entering the system. +This arrangement adds a level of indirection to media access, allowing +content linkage, version comparison of documents composited from +spans of fluid media, and automatic sharing of data between copies. + +Additionally, the Xanadu media model incorporates micropayments: +when requesting a + +The gzz mediaserver is an implementation of these ideas\ldots + +Somewhat like freenet, but encryption is not the point here, point +is media sharing, caching, replication and access. + +\subsection{Digital Rights Management versus Fair Use} + +\begin{itemize} +\item support copying of cached content between the user's machines, but + no large-scale copying without repayment to content originator + +\item voluntary compliance + +\item testing of compliance by requests + +\item give people possibility of doing the right thing + +\item Asserting copyright \ra\ revocation? + The infringer is the one granting access to the material, not the user! +\end{itemize} + +\subsection{For Gzigzag} + +If we want to include a piece of audio into a ZZ space and then copy +the space for experiment / backup, the audio will also be copied, taking +up space. Creating a simple black-box stable media server will remove +this problem. + +Also, mirroring data between machines is easier. + +Eventually, cells to be stored as change packets in the mediaserver. + + +\subsection{Local and Cached Material} + +All material is divided into local and cached material. Cached +material may be removed from the system at any time without notice. +Removing local material requires special procedures. Material may be +changed from local to cached but not the other way around.\ajk{I'd + rather have permanent and transient material; that way someone who + absolutely wants to keep a local copy of a remote datum can do so.} + + +\subsection{Quality Levels} + +It is quite simple to expand this approach to support different +qualities for sounds and images; loading the given image at a lower +quality may be more efficient especially over a slow network, likewise +for sound. + +\section{Functionality} + +\begin{itemize} + \item communicate over network with other instances of mediaserver + \item cache media locally + \item manage local store, serve published portions over network + \item return given span of media + \item record media, tag addresses / spans + \item append text, char by char, efficiently + \item manage unique ids through prefix-for-each-server.\ajk{I have + a better idea: delegateable infinite id space. Elaborated + below.} + \item ID conflict is a fatally serious issue - exchange CRCs + occasionally for random mutually shared pieces just to check. +\end{itemize} + +\subsection{Basic interface} + +Recorder / Player? See Modules/sound/*.java + +\begin{verbatim} +interface MediaServer { + /** Load the media denoted by the span, or null if not loadable. + */ + Media getMedia(Span s); + + /** Load the media denoted by the span asynchronously + * and return + * an asynchronous object that holds the media when loaded. + */ + MediaLoader getMediaAsync(Span s); + + Span append(String s); + +} + +interface Media { + final int TEXT, IMAGE, AUDIO, VIDEO; + int getType(); + ... ??? Casts? +} + +interface MediaLoader { + /** Whether loading is complete. + */ + boolean isReady(); + + /** Whether the media has been correctly, fully loaded + * without errors. + */ + boolean isValid(); + ... ??? + + /** Stop loading. + */ + void close(); + + /** Get the final media. + * null = not yet here. + */ + Media getMedia(); +} +\end{verbatim} + +\section{Decentralized unique ID scheme proposal} + +Let IDs be octet sequences of arbitrary nonzero length. + +An ID is always either \emph{assigned} or \emph{unassigned}. + +The ID x is \emph{inferior} to ID y iff y is an initial subsequence of +x. An ID is inferior to itself. + +Let A be a mediaserver and x be an ID. Now \emph{A has delegated x} +is a relation. + +Let A be a mediaserver and x be an ID. Now define that \emph{x + available to A} iff it is not inferior to an ID that A has +delegated. + +Define the relation \emph{A has authority over x}, where A is a +mediaserver and x is an ID. + +The following invariants hold: +\begin{itemize} +\item For every ID there is a mediaserver that has authority over it. +\item If a mediaserver has authority over an unassigned ID, it can + make it an assigned ID. +\item If an ID is not available to a mediaserver, the mediaserver does + not have authority over it. +\item If a mediaserver has authority over an ID x, then it has + authority over every ID that is both inferior to the ID x and is + available to the mediaserver. +\item If a mediaserver has authority over an unassigned ID and if + there are no assigned IDs inferior to that ID, it can delegate + the ID. +\end{itemize} + +The idea is that when a mediaserver needs a fresh ID, it takes an ID +it has authority over. If it has no such IDs, it requests that some +other mediaserver delegates authority over some other ID to it. + +\subsection{Advantages} + +I believe that this scheme guarantees network-wide unique IDs. It +also requires no central agency that gives out valid IDs. + +\subsection{Vulnerabilities} + +If there are two distinct networks and data is shared between the +networks, havoc occurs. The solution is to have one conceptual global +network. The network can be disconnected; if every connected +subnetwork is seeded with a distinct part of the ID space, then each +operates autonomously after seeding. + +It is possible for a malicious mediaserver to take authority over lots +of IDs. However, this will not have any fatal effects on the +mediaserver network. + +A hostile mediaserver may also distribute invalid ids around that it has +no authority over. This is probably the most serious attack. + +\subsection{Crypto?} + +It would be good to involve cryptographic signatures here so that +assigning and delegating IDs requires a verifiable digital signature +somehow. Needs work. + +\subsubsection{A scheme} + +One possible - probably incomplete - scheme follows: + +Every mediaserver shall have an asymmetric key pair for cryptographic +signing. Additionally, there shall be a key pair for the network +distinct from the mediaserver keys. Now, a mediaserver having +authority over an ID shall possess an authority certificate for that +ID (or to an ID that ID is inferior to). + +When a mediaserver having authority over an ID wants to assign that ID +to a datum, it generates a data packet containing both the datum and +the authority certificate it has and signs that packet. + +When a mediaserver having authority over an ID wants to delegate that +ID to another mediaserver, it generates a new certificate as follows: +it generates a data packet containing the authority certificate of the +delegator the ID being delegated and information that uniquely +specifies the delegatee's public key (key ID, key size and fingerprint +or something like that), and then signs that packet. This signed +packet is the new certificate. The delegatee shall then broadcast the +certificate to the whole network. + +(An attack deflector:) If a mediaserver has a valid authority +certificate for an ID and it receives a conflicting valid authority +certificate, then there is a rogue mediaserver that is delegating the +same ID to several mediaserver. The identity of the rogue should be +easy to determine and sanctions (such as removing from the network) +doable. + +A valid certificate is defined recursively: a certificate signed by +the network key is valid, and a certificate containing a valid +certificate for the correct ID is valid. + +This scheme has at least the vulnerability that a rogue mediaserver +that is in a good place in a network can prevent the network from +realizing it's giving out conflicting certificates. + +\subsubsection{Another scheme} + +\begin{itemize} +\item There will be two kinds of authority certificates: root + certificate and delegation certificate. +\item Authority certificates are a shared secret between its issuer + and its holder. +\item An authority certificate gives its holder authority over one ID + (transitively giving authority over the whole subtree). +\item The root certificate gives authority over the null ID. (Change + above description to allow it.) +\item A mediaserver holding an authority certificate for a subtree can + generate a new authority certificate for a member of the subtree. +\item A holder of a certificate must be able to verify that the + certificate has an authority path to the root. +\item It must not be possible to generate an authority certificate +\end{itemize} + +This scheme has one problem: it does not revoke authority over a +delegated subtree from the delegator. + +\section{Architecture} + +The mediaserver proposed architecture has several levels. + +\subsection{Physical} + +The physical level takes care of retrieving and storing +spans according to unique global ids. +All policy decisions are made on higher levels: this level +only opens network connections and stores the spans in files +and removes them according to instructions from the higher level. + +No reference counting is done: that is also a problem of the higher +levels. + +\begin{verbatim} +FOO +\end{verbatim} + +\section{Implementation plan} + +\subsection{Phase I} + +This is immediate: we need this yesterday. + +Unique IDs, at least a preliminary version that will remain unique +even when better schemes taken into use. + +The physical layer, except for: +Explicit synch by user. No interactive network fetches but +code to synch up two repositories completely (copy everything +in both to both). +No digital signatures or crypto: all systems completely trusted. + + +\subsection{Phase II} + +Collections? Overriding? Signatures? + +\section{HTTP Interface to Storage} + +The storage module will listen on an IP-reachable host on an TCP port +for incoming connections. The protocol used will be HTTP/1.0 or +HTTP/1.1. It is recommended that the storage module root URL be +http://localhost/mediaserver/. The root URL shall be configurable. + +The storage module uses the following ID format: first, an arbitrary +octet sequence is encoded as a sequence of hexadecimal ASCII digits +(with capital letters); then an ASCII dash is appended; finally, an +MD5-hash of the octet sequence formed by concatenating the the +arbitrary octet sequence above and the datum itself is appended as a +sequence of hexadecimal ASCII digits (with capital letters). + +The following requests are supported: + +\subsection{Request: GET \emph{root}/data} + +A GET request of the base URL with the string \verb+data+ prepended +will result in a listing of data in the storage module. Each line +describes one datum; first comes the ID and then the +length of the datum in base-10 ASCII representation. These two fields +are separated by linear whitespace. + +\subsection{Request: GET \emph{root}/data/} + +This will result in a human-readable version of the above listing. + +\subsection{Request: GET \emph{root}/data/\emph{key}} + +A GET request of the base URL with the string \verb+data/+ and the +datum ID prepended will result in the datum requested. + +\subsection{Request: PUT \emph{root}/data/\emph{key}} + +Mutatis mutandis. + +\subsection{Request: DELETE \emph{root}/data/\emph{key}} + +Mutatis mutandis. + +\section{Problems} + +Word-sized gaps in published documents for deleted words \ra\ guess +confidential content, or damaging erased content? + +\end{document} + + + diff --git a/Documentation/Networking/Makefile b/Documentation/Networking/Makefile new file mode 100644 index 0000000..ca93a8a --- /dev/null +++ b/Documentation/Networking/Makefile @@ -0,0 +1,10 @@ +# DIAGRAMS=linkorder.png beamorder.png + +all : ztp.html ztp-ns4.html + +ztp.html : ztp.wml +ztp-ns4.html : ztp.wml + +include ../lib.mk + + diff --git a/Documentation/Networking/ZTP-usage.txt b/Documentation/Networking/ZTP-usage.txt new file mode 100644 index 0000000..cff88be --- /dev/null +++ b/Documentation/Networking/ZTP-usage.txt @@ -0,0 +1,70 @@ +Brief usage instructions for the current ZTP implementation +----------------------------------------------------------- + +You need the "ztp" module for both server and client operation. + +If your system has a BSD-style syslog service, compile with ARCH=syslog. +The Makefile is set up to work with Debian-packaged Kaffe, so if you +use some other JRE, you need to edit Java/arch/syslog/arch.mk. + + +The server +---------- + +To start up the server: + LD_LIBRARY_PATH=arch/syslog kaffe org.gzigzag.Main -ztpserv 5555 cellscrollfile1 +Here 5555 is the port to bind to. + +The only way to stop the server currently is killing it (Ctrl-C or +SIGTERM signal). + +The server does not set up the GZZ-client's system list, so if you +want to view the space generated by the server, you will have to -new +it. The ZTP cells are on the rank along d.ztpserver starting from the +home cell. ZTP dimensions and cells have a prefix "ztpserver!". + + +The client +---------- + +Create a cell with the content "ZTPclient.PUT". This will be the +action to invoke when you want to put data into the server. + +Create an association list as follows: + + ---> d.1 + | serverFQDN --- server.example (server machine FQDN) + v | + d.2 serverPort --- 5555 (server port) + | + userName --- adm (username; currently only adm works) + | + subspaceName --- ALL (only ALL currently) + | + subspace ---- (a cell) + +Connect the subspace you want to put to the "subspace" cell along +"d.ztp-subspace". The subspace is currently defined to be the closure +of the cell connected to the "subspace" cell along "d.ztp-subspace" in +positive direction with respect to all available dimensions (from +d.masterdim) except "d.ztp-subspace" and "d.cellcreation". + +Before you can do anything, you need to give your space an ID. Create +a cell with the content "SETSPACEID" and another cell with the space +ID you want as the content. Have your control cursor on the +SETSPACEID cell and your data cursor on the space ID cell. Then +invoke the action (press ENTER). + +Note that the space ID should be unique among all spaces. + +To put the subspace to the server, have your control cursor on the +"STPclient.PUT" action cell mentioned above and your data cursor on +the first item of the alist ("serverFQDN"). Then invoke the action +(press ENTER). + +To get a subspace from the server, have your control cursor on a cell +that reads "STPclient.GET" (create one if necessary) and your data +cursor on the first item of the alist ("serverFQDN"). Then invoke the +action (press ENTER). + + diff --git a/Documentation/Networking/ZTP.txt b/Documentation/Networking/ZTP.txt new file mode 100644 index 0000000..b67f4b0 --- /dev/null +++ b/Documentation/Networking/ZTP.txt @@ -0,0 +1,161 @@ +ZigZag Transport Protocol +========================= + +Objective: to transfer ZZ subspaces over a network. + +This is a datagram-oriented protocol that can operate over both TCP +and UDP. The protocol can also operate over a TLS stream. The +underlying protocol is assumed to provide for transport-level +security. + + +Authentication +-------------- + +Scenarios + + 1. Preauthentication + Used with TLS streams. + + 2. Plaintext passwords + + 3. Cryptographic authentication + +What needs to be proven? + - identity + +For now, we provide only preauthenticated and password-protected +services. + +Authority of the client to order the server to do certain things +depends on the authenticated client identity. + +Privileges: + * operator privilege + * write privilege + * read privilege + + +Naming subspaces +---------------- + +Temporary naming: + + -> Client provides server with a definition of a subspace + <- Server responds with a name for that subspace + + Client may not assume that the name is valid after this session. + + This exchange may not fail for any reason. + +Permanent naming + + -> Client provides a server with a name and a definition of + a subspace + + If successful, the name will be valid until deleted, even across + sessions. + + Names are arranged into a hierarchy. Operators of the subspace the + name refers to are operators of that name. + + NOTE: This operation requires operator privilege on the parent name. + + +Reading a subspace +------------------ + + -> Client requests a reading of a named subspace + <- Server sends a description of the subspace + + NOTE: This operation requires read privileges on that subspace + + +Writing a subspace +------------------ + + -> Client requests a writing of a named subspace + <- Server gives client goahead + -> Client sends a description of the subspace + + NOTE: This operation requires read privileges on that subspace + + +User administration +------------------- + +Admin stuff: +* Create a user +* Grant privileges to user +* Suspend a user +* Delete a user + +User stuff: +* Password change + + +PROTOCOL SPECIFICATION +====================== + +Messages: + +from client: + PASSAUTH + + TMPNAME + + PERMNAME + SUBSPACE (see TMPNAME) + + READ + + WRITE + + NEWUSER + DELUSER + + GRANTPRIV + REVOKEPRIV + + FREEZEUSER + THAWUSER + + CHPASS + + QUIT + +sequences: + SEQ CELL + SEQ HARDDIM + SEQ SOFTDIM + SEQ CONTENT + SEQ CONNECT + SEQ END + +UDP SEQ responses: + REQ SEQ + ACK SEQ END + SEQ FINISH + ACK SEQ FINISH + +non-SEQ responses: + OK + ERR + +Operation over TCP or TLS: + - all messages are sent ONCE + - SEQ messages lack seqno and num, SEQ requests lack seqno + - no acknowledgement + - each non-SEQ message is responded with OK or ERR + - OK and ERR are not responded to + +Operation over UDP: + - all non-SEQ messages are resent periodically until acknowledged + with OK or ERR + - OK and ERR are not acknowledged + - SEQ END is resent periodically until acknowledged with ACK SEQ END + - after SEQ END, SEQ receiver may send REQ SEQ requests periodically + until it receives a corresponding SEQ message, sent once. + - after ACK SEQ END and any REQ SEQ, the SEQ session is ended by SEQ FINISH + sent by receiving side until it receives ACK SEQ FINISH message + diff --git a/Documentation/Networking/mock-ZTPTCP.txt b/Documentation/Networking/mock-ZTPTCP.txt new file mode 100644 index 0000000..0a5d5e2 --- /dev/null +++ b/Documentation/Networking/mock-ZTPTCP.txt @@ -0,0 +1,74 @@ +Generic command syntax: + + command = ASCII word, args, crlf; + ASCII word = ASCII letter, ASCII word; + letter = 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 + | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 + | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 97 | 98 | 99 + | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 + | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 + | 116 | 117 | 118 | 119 | 120 | 121 | 122; + whitespace = | 9 | 32; + crlf = 13, 10; + args = | whitespace, arg, args; + arg = ASCII word | ASCII number | UNICODE string; + ASCII number = 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57; + UNICODE string = 34, UNICODE string without quotes, 34; + UNICODE string without quotes = | quoted UNICODE char | UNICODE string without quotes; + quoted UNICODE char = UNICODE char (not 34) | 34, 34; + +Response code theory: + + X.Y.Z: + X denotes success / failure: + 1: Positive Preliminary response + 2: Positive Completion response + 3: Positive Intermediate response + 4: Transient Negative Completion response + 5: Permanent Negative Completion response + + Y denotes response class: + 0: Syntax + 1: Information + 2: Connections + 3: Authentication + 4: Subspaces + + Z with X and Y specifies exact problem + +Initial greeting: + 2.2.0 Hello there! + +Generic responses: + 5.0.1 What? (Syntax error) + 4.2.1 Service unavailable, closing transmission channel + + +QUIT + +Responses: + 2.2.1 Bye + +AUTH/PRE & AUTH/PASS + +Responses + 5.3.0 Access denied + 5.3.1 User disabled + 2.3.0 OK + +PUT + 2.4.0 Subspace successfully put + 3.4.0 Pleace proceed with subspace data + 5.4.0 Aborted PUT + 5.4.1 No such subspace + 5.4.2 Cannot put cells lacking a space ID + +GET + 2.4.1 Subspace successfully got + 3.4.1 Proceeding with subspace data + 5.4.1 No such subspace + +Subspace data: + C -- content + R ... -- rank + F -- finish \ No newline at end of file diff --git a/Documentation/Networking/ztp.wml b/Documentation/Networking/ztp.wml new file mode 100644 index 0000000..94fdaaa --- /dev/null +++ b/Documentation/Networking/ztp.wml @@ -0,0 +1,855 @@ +######### +## TODO +# * scrolls +# * +######### + + +#use wml::std::grid + +%body +%body + + + + + + + + GZigZag networking: ZigZag Transfer Protocol + +#include '../wmlinc/catart.wml' + +

GZigZag networking: ZigZag Transfer Protocol

+
$Id: ztp.wml,v 1.3 2001/02/06 12:12:17 ajk Exp $
+ +Written by
+Antti-Juhani Kaijanaho
+(add your name here if you do any significant modification) + +

+{#MYTOC#} + +On naming + +

The name of this protocol is the ZigZag Transfer Protocol, or ZTP, +as suggested by Tuomas Lukka. Early versions of this protocol were +called the Subspace Transfer Protocol, or STP, which we did not like. + +

Note that the acronym ZTP stands also for Zangelding Transfer +Protocol. Due to the different usages for the two protocols, we don't +expect that serious confusion will result from this. + +On subspaces + +

A subspace S' of a ZigZag space S is a ZigZag space with the +following properties: + +

    +
  1. The set of cells in S' is a subset of the set of cells in S +
  2. The set of connections in S' is a subset of the set of connection in S +
+ +

A subspace selector is a function mapping ZigZag spaces into their +subspaces. A subspace selector can be described by the triplet +<C, H, S>, where + +

+ +
C
+
is a set of cells,
+ +
H
+
is a set of dimensions, and
+ +
S
+
is a set of dimensions
+ +
+ +

and where H and S are disjoint. + +

Given a ZigZag space Z, a subspace selector chooses a subspace as +follows: the set of cells is constructed as the set of cells reachable +from the cells in C through connections along dimensions in H; and the +set of connections is constructed as the set of those connections from +Z whose both ends are in the subspace and whose dimension is in H or S. + +User access privilege management + +

Once the user is authenticated, her actions are limited by her +access privileges. There are four types of privileges: + +

    +
  • space administrator privileges (SAP) +
  • subspace operator privileges (SOP) +
  • subspace write privileges (SWP) +
  • subspace read privileges (SRP) +
+ +

+All but SAP are associated with a subspace. The subspace privileges +apply to the subspace itself and any subspaces of that subspace. + +

If a user has SOP, SWP or SRP in a subspace S and the same +privileges in a subspace T of S, and the privileges to T are revoked, +the privilege to S is unaffected by the revocation. + +Space Administrator Privileges (SAP) + +

A user having SAP is authorized to create, delete, suspend and +resume users, and give and revoke users their SOP to any subspace, and +give and revoke users their SAP. A user having SAP is also authorized +to revoke any user's SOP, SWP or SRP to any subspace. + +Subspace Operator Privileges (SOP) + +

A user having SOP on a subspace S is authorized to give or revoke +any user their SOP, SWP or SRP to any subspace of S, including S +itself. + +Subspace Write Privileges (SWP) + +

A user having SWP on a subspace S is authorized to initiate +transfer of any subspace of S, inclusing S itself, from the client to +the server. + +Subspace Read Privileges (SRP) + +

A user having SRP on a subspace S is authorized to initiate +transfer of any subspace of S, including S itself, from the server to +the client. + +Protocol overview + +

+ZTP is actually two similar protocols for the same purpose. One +operates over a reliable stream; we call this ZTP/TCP. The other +operates over a datagram service; we call this ZTP/UDP. Note that +other underlying protocols than TCP or UDP are possible; the names are +chosen for their mnemonic value, not for their accuracy. + +

+The datagram service used by ZTP/UDP is assumed to fail only in that +sent datagrams may be lost en route and that datagrams may arrive out +of order, and datagrams may be duplicated. In particular, it is +assumed that any arriving datagrams are uncorrupted. + +

+All transfer protocols used by ZTP/TCP and ZTP/UDP are assumed to +provide for confidentiality and integrity. However, the transfer +protocols are not necessarily assumed to provide for authentication. + +

Thus, good transfer protocols to use with ZTP/TCP are +

    +
  • TLS over TCP over IP +
  • SSL over TCP over IP +
  • TCP over IPSec +
  • SSH protocol +
+ +

UDP over IPSec is a good protocol to use with ZTP/UDP. + +

In a trusted environment, also TCP over IP with ZTP/TCP and UDP +over IP in ZTP/TCP can be used. Hovewer, using ZTP/TCP over +TCP over plain IP and using ZTP/UDP over UDP over plain IP on the +global Internet is DANGEROUS. + +

The ZTP protocol consists of several modules. The modules are: +

    +
  • authentication +
  • user administration +
  • subspace administration +
  • subspace naming +
  • subspace transfer +
  • SEQ scheme +
+ +

The authentication module actually consists of several alternative +modules. Pre-authentication is used when ZTP operates over +authenticating underlying protocols. It is also useful for +anonymous-access-only read-only servers, where there is no need for +real authentication. Password authentication is used when +the underlying protocol provides for data integrity and +confidentiality but not authentication, and in trusted unencrypted +environments. Cryptographic authentication will use +cryptographic means to authenticate the user and is meant to be used +in hostile environments. This specification will not define any +cryptographic authentication methods. + +

User administration module handles such things as adding, deleting, +suspending and resuming users. It is all things that require SAP. + +

Subspace administration module allows a user having SOP to a +subspace S give and revoke SOP, SWP and SRP to any subspace of S, +including S itself. + +

Subspace naming module uses the SEQ scheme to define a subspace and +then gives a name for it. All other subspace operations use that +name. + +

Subspace tranfer module uses the SEQ scheme to transfer a subspace +from the client to the server (which requires SWP) and from the server +to the client (which requires SRP). + +

The SEQ scheme is a method for dumping a subspace content from the +sender (either the client or the server) to the receiver (either the +client or the server, the one which is not the sender). The scheme is +simple in ZTP/TCP. In ZTP/UDP, the scheme is optimized for +transmission paths with low packet loss, allowing for information to +be used as the packets arrive, even if they come out of order. + +Protocol walkthrough + +

An ZTP protocol instance starts by establishing a session. In +ZTP/TCP, this is handled by the underlying protocol, so in ZTP/TCP +this phase consists of no messages. In ZTP/UDP, a session is +identified by an octet negotiated by the parties in a handshake +roundtrip. + +

After session has been established, user authentication is +performed. This is initiated by the client who sends a request for +authentication specifying which authentication method is desired. The +rest of the exchange depends on the authentication method; the +authentication phase is ended by an okaying or rejecting message from +the server. + +

After successful authentication, the client in the session is +assumed to be controlled by the authenticated user. It can then +initiate any process for which the user has sufficient privileges. + +

XXX Use cases + +

Connection can be closed at any time. It is preferred that the +connection closure scheme is used. The closure can be initiated by +either party at any time. In case connection is not properly closed, +a connection shall have a timeout of at least ten minutes for forcibly +closing the connection if no messages are exchanged in that time. + +Authentication schemes + +There are three schmes for authentication in ZTP. Preauthentication +presupposes that the underlying protocol provides authentication in +some implementation-defined manner. Password authentication uses a +trivial shared secret protocol to establish the authenticity of the +user. A slot for future amendment of the protocol is reserved; it is +expected that cryptographic authentication will be preferred over +password authentication in the future. This protocol specification +does not define any cryptographic authentication methods. + +Preauthentication + +

In preauthentication, the underlying protocol provides for enough +information to determine the authencity of the user at the client end. +The mechanism for that is beyond the scope of this specification. + +

The client requesting preauthentication shall send an AUTH REQ/PRE +message containing the user name for which authentication is desired. +If the server determines that the client is sufficiently authenticated +by the underlying protocol to be that user name, and the named user +exists and is not suspended, it shall respond with the AUTH OK +message. Otherwise it shall respond with an AUTH ERR message and +initiate connection closure. + +Password authentication + +

In password authentication the client provides the server with a +user name / password pair, which the server compares with its own +records. If the pair matches, the user is successfully authenticated. +The password is a shared secret; however, the server may use one-way +functions to store the information it needs of the password. + +

The client requesting password authentication shall send an AUTH +REQ/PASS message containing the user name for which authentication is +desired and the related password. If the password is determined to be +the same as the password for the user name stored in the server's +records, and the user is not suspended, the server shall respond with +the AUTH OK message. If there is no such user name, or the password +does not match, or the user is suspended, the server MUST respond with +an AUTH ERR message and initiate connection closure. + +AUTH message details + +Responses to AUTH REQ messages + +

The server MUST respond to an AUTH REQ message +with either the message AUTH OK or the message +AUTH ERR, based on the following rules: + +

    + +
  • If the server does not support the requested authentication type +at all, it MUST respond with AUTH ERR. + +
  • If the username is the name of an nonexistent user, +or it is an existing user who is not properly authenticated, the +server MUST respond with AUTH ERR. The message +sent MUST be identical between the different reasons in this item for +issuing the message. In other words, it MUST NOT be possible for the +client to determine based on the form of the message whether the user +name exists or not. An example of a proper explanation text for the +message is "Access denied". + +
  • If the username is properly authenticated and the +named user is disabled, the server MUST respond with AUTH +ERR. An example of a proper explanation text for the +message is "User disabled". Note that this kind of a message MUST NOT +be sent if the user is not properly authenticated. + +
  • If the username exists and is properly authenticated +and it is not disabled, the server SHOULD respond with AUTH +OK. However, the server MAY also respond with AUTH +ERR (for example, if there are local limits on the number of +simultaneous users and the limit is exceeded), in which case the +explanation text for the message SHOULD make it clear why the +authentication was rejected. + +
+ + +AUTH REQ/PRE + +Synopsis + +

+AUTH REQ/PRE username +

+ +
    +
  • username : string +
+ +Description + +

This message MUST be sent immediately after the connection has been +established by a client wishing for preauthentication. The +username is the name of the user for which the +authentication is requested. + +

The server responses to this message are defined in + +AUTH REQ/PASS + +Synopsis + +

AUTH REQ/PASS username password

+ +
    +
  • username, password : string +
+ +Description + +

This message MUST be sent immediately after the connection has been +established by a client wishing for password authentication. The +username is the name of the user for which the +authentication is requested. + +

The server verifies the authenticity of the user by verifying that +the password is the same as the valid password for the +username according to the server's records. Note that +the server MAY store only the result of a one-way hashing of the +password instead of the password itself, if this information can be +used to reliably ascertain the validity of a given +password. + +

The server responses to this message are defined in + +AUTH OK + +Synopsis + +

AUTH OK

+ +Description + +

This message indicates that the server has accepted the +authenticity of the client as the username given in the earlier +AUTH REQ message. This message concludes the +authentication phase. + +AUTH ERR + +Synopsis + +

AUTH ERR explanation

+ +
    + +
  • explanation : string + +
+ +Description + +

This message indicates that the server has not accepted the +authenticity of the client as the username given in the earlier +AUTH REQ message. The server, after sending this +message, SHOULD immediately initiate connection closure. + +

The explanation SHOULD be a human-readable description +of the reason for the authenticity rejection. Note that the server +SHOULD word the explanation so that the client cannot determine +whether it was failed authentication or a nonexistent username that +prompted the AUTH ERR message. + +User administration + +

The purpose of the user administration module in ZTP is to allow the +administrator to administrate users remotely without needing to resort +to implementation-defined behaviour. + +

Users have the following characteristics tunable using ZTP: + +

    +
  • User name (UNAME : string) +
  • Permission to be preauthenticated (AUTH/PRE : boolean) +
  • Permission to be password-authenticated (AUTH/PASS : boolean) +
  • Is suspended or not (SUSP : boolean) +
  • Permission to change password (CHPASS: boolean) +
  • Password (PASS : string) +
  • Has SAP or doesn't have SAP (SAP : boolean) +
+ +

The user administration module consists of one scheme for editing +and one scheme for viewing all these user data. The edition scheme +can be also used for adding and deleting new users. + +

A user can view their own data regardless of permissions. The user +can change the password if their CHPASS flag is set to +true. + +The server side user management concept + +

This section defines a conceptual model for the server side user +management for ZTP. Server implementations MAY use other +implementation strategies so long as the effects observable by the +clients are the same as with this model. + +

In the server, there is a table of users. The table consists of +records containing the following information: + +

    +
  • username : string +
  • password : string +
  • status : userstatus +
+ +

A particular record may be written as a triplet +<username, password, +status>. + +

The third element, status is an octet-length bit +vector with the following structure: + + +Bit 7 +Bit 6 +Bit 5 +Bit 4 +Bit 3 +Bit 2 +Bit 1 +Bit 0 + +Reserved +Reserved +Reserved +AUTH/PASS +AUTH/PRE +SAP +CHPASS +SUSP + + +

This data type is referred to in type definitions as +userstatus. Note that the elements marked as +Reserved MUST have the value false. + +

The table of users is indexed by user names. There may be at most +one record with a given username in the table. + +

In the table, the following operations are allowed: + +

    + +
  • insertion of a new user record; + +
  • replacement of a user record; + +
  • deletion of a user record; and + +
  • accessing a complete user record. + +
+ +

All of them are atomic. This means that, for the forementioned +operations, the following are true: + +

    + +
  • If an operation fails, the table will remain in the state it was +before the attempt. + +
  • Operations never overlap; thus at most one operation is in +progress at any time. + +
+ +

A user exists, if and only if there is a record with that username +on the table. A user is disabled if and only if there is a record +with that username on the table and the SUSP element of +the status element of that record has the value +true. A user has SAP if and only if there is a +record with that username on the table and the SAP +element of the status element of that record has the +value true + +UADM message details + +UADM NEW + +Synopsis + +

UADM NEW stat uname passwd +

+ +
    +
  • stat : userstatus +
  • uname, passwd : string +
+ +Description + +

This message is sent by the client when it wants to create a new +user.

+ +

After receiving this message, the server MUST follow the following +step-by-step algorithm (the term "client user" refers to the user +authenticated to control the session where the message was sent): + +

    + +
  • Check whether the client user has SAP. If not, the server MUST +send in response the UADM E/NOPERM message, and end +the processing of the message here. + +
  • Check whether the user uname exists. If it does, the +server MUST send in response the UADM E/EXISTS +message and end the processing of the message here. + +
  • The server SHOULD check that it has enough resources to handle +this new user (the criteria are implementation-defined and MAY include +local considerations). If it determines that it doesn't have the +resources, the server MUST send in response the UADM +E/NORES message and end the processing of the message here. + +
  • The server MUST insert the record <uname, +passwd, stat> into the user table. If +this fails, it MUST respond with the message UADM +E/PROB, otherwise it MUST respond with the message +UADM OK. + +
+ + +Payload transfer: the SEQ scheme + +

+The actual payload of the protocol, the subspace data, is transferred +over by the SEQ scheme. + +

The SEQ scheme consists of five SEQ data messages and four SEQ +control messages. The data messages are + +

+ +
SEQ CELL
+
Specifies a root cell for a subspace
+ +
SEQ HARDDIM
+
Specifies a hard dimension for a subspace
+ +
SEQ SOFTDIM
+
Specifies a soft dimension for a subspace
+ +
SEQ CONTENT
+
Transfers over the content of a subspace
+ +
SEQ RANK
+
Specifies a subrank in the subspace
+ +
+ +

+The SEQ control messages are listed below. + +

+ +
SEQ FIN
+
Initiates finalization phase of the SEQ scheme
+ +
SEQ REQ
+
Requests that a SEQ data message is resent
+ +
SEQ ERR
+
Response for a broken SEQ REQ.
+ +
SEQ END
+
Ends the SEQ scheme instance
+ +
+ +

A SEQ scheme instance has a sending end and a receiving end. When +the server is the sending end, the client is the receiving end and +vice versa. + +

In ZTP/TCP, the SEQ scheme consists of a number of SEQ data +messages and is finished by a SEQ END message. + +

In ZTP/UDP, the SEQ scheme consists of two phases: the data +transfer phase and the finalization phase. The data transfer phase +consists of a number of SEQ data messages and is ended by a SEQ FIN +message which also starts the finalization phase. Then the receiver +end of the SEQ scheme sends one or more SEQ REQ messages and the +sender end responds with an appropriate SEQ data message. The +finalization phase is ended by a SEQ END by both parties. + +SEQ message details + +SEQ/DATA message template + +SEQ/CTL message template + +SEQ CELL + +Synopsis + +

+SEQ/DATA CELL cellid
+

    +
  • cellid : string +
+ +Description + +

This message defines that the cell cellid is a root +cell for the subspace being described. + +SEQ HARDDIM + +Synopsis + +

+SEQ/DATA HARDDIM dimid +

+ +
    +
  • dimid: string +
+ +Description + +

This message defines that the dimension dimid is one +of the defining dimensions for the subspace being described. In other +words, this defines that any cell connected to any cell in the +subspace along dimension dimid also is in the subspace. + +

If in a SEQ scheme instance a dimension is specified using +SEQ HARDDIM, it SHOULD NOT be specified in the same +SEQ scheme instance using SEQ SOFTDIM. + +SEQ SOFTDIM + +Synopsis + +

+SEQ/DATA SOFTDIM dimid +

+
    +
  • dimid: string +
+ +Description + +

This message defines that any connections along dimension +dimid between cells that are in the subspace are included +in the subspace. However, this dimension will not take part in the +definition of the cell set of the subspace. + +

If in a SEQ scheme instance a dimension is specified using +SEQ SOFTDIM, it SHOULD NOT be specified in the same +SEQ scheme instance using SEQ HARDDIM. + +SEQ CONTENT + +Synopsis + +

SEQ/DATA CONTENT +content-type cellid content +

+
    +
  • content-type: octet +
  • cellid: string +
  • content: octet[] +
+ +Description + +

This command transfers the content of a cell, which this protocol +treats as an octet stream with no underlying structure. The type of +the content is indicated in this messages; the following content types +are now established: + + + + +0 +Octet stream, ie. unknown format + +1 +Unicode text in UTF-8 encoding + +2 +A span + + + +SEQ RANK + +Synopsis + +

SEQ/DATA RANK +dimid cellarray + +

    +
  • dimid : string +
  • cellarray : string[] +
+ +Description + +

This message denotes a subrank along dimension dimid. + +

The precise definition of this is as follows: +cellarray[n] is connected posward to +cellarray[n+1] for all n +between zero, inclusive, and the length of cellarray +minus one, exclusive. More than one SEQ RANK +message MAY define the same connection. Two SEQ +RANK messages MUST NOT define two conflicting connections +(that is, a connection posward or negward from the same cell to two +different cells). + +SEQ FIN + +Synopsis + +

SEQ/CTL FIN dmcount + +

    +
  • dmcount: uint32 +
+ +Description + +

This message closes the data transfer phase of a SEQ scheme +instance and opens its finalization phase. + +

The parameter dmcount MUST specify the number of +unique SEQ data messages sent during the data transfer phase of the +SEQ scheme instance. + +

In ZTP/UDP, the sending end of the SEQ scheme instance MUST send +this message repeatedly after sending the last SEQ data message in the +data transfer phase, until it receives either a SEQ REQ or a SEQ END +message. + +

When the receiving end of the SEQ scheme instance first receives +this message, it SHOULD check which data messages it did receive and +issue SEQ REQ messages for each missing message. When it has received +all data messages, it MUST send a SEQ END message. It should ignore +all further SEQ FIN messages associated with that SEQ scheme instance. + +

This message MUST NOT be sent in ZTP/TCP. + +SEQ REQ + +Synopsis + +

+SEQ/CTL REQ seq +

+ +
    +
  • seq : uint32 +
+ +Description + +

This message is sent by the receiving end of the SEQ scheme +instance to request that the sending end resend the SEQ data message +with the SEQ message identity number seq. + +

The receiving end MUST repeatedly resend this message if it is +sending it at all, until it receives the data message it's asking for +or a corresponding SEQ ERR. + +

The sending end MUST respond to each SEQ REQ +message it receives (even duplicates) by resending the message being +requested, or with a SEQ ERR message. + +

This message MUST NOT be sent in ZTP/TCP + +SEQ ERR + +Synopsis + +

+SEQ/CTL ERR seq +

+ +
    +
  • seq : uint32 +
+ +Description + +

This message is a response to an invalid SEQ REQ +message. It is to be sent in response to every received invalid +SEQ REQ message, even to duplicates. + +

This message MUST NOT be sent in ZTP/TCP. + +SEQ END + +Synopsis + +

+SEQ/CTL END +

+ +Description + +

This message ends the SEQ scheme instance. + +

In ZTP/UDP, the receiving end MUST send this message repeatedly +after receiving SEQ FIN and receiving all the data +it needs, until it receives a SEQ END message. The +sending end MUST respond to every SEQ END message, +even duplicates, with a SEQ END message. + +

In ZTP/TCP, the sending end MUST send a single SEQ +END message after sending all the SEQ data messages it's +going to send. The receiving end MUST NOT respond to the SEQ +END message. + diff --git a/Documentation/Nile/Makefile b/Documentation/Nile/Makefile new file mode 100644 index 0000000..ea4bf90 --- /dev/null +++ b/Documentation/Nile/Makefile @@ -0,0 +1,14 @@ +# DIAGRAMS=linkorder.png beamorder.png + +all : nileug.html nileug-ns4.html nile.html nile-ns4.html + +niledep = nile.wml ../wmlinc/art.css ../wmlinc/catart.wml ../wmlinc/common.wml $(DIAGRAMS) +nileugdep = nileug.wml ../wmlinc/art.css ../wmlinc/catart.wml ../wmlinc/common.wml $(DIAGRAMS) +nile.html: $(niledep) +nile-ns4.html: $(niledep) +nileug.html: $(nileugdep) +nileug-ns4.html: $(nileugdep) + +include ../lib.mk + + diff --git a/Documentation/Nile/nile.wml b/Documentation/Nile/nile.wml new file mode 100644 index 0000000..ad6d6a9 --- /dev/null +++ b/Documentation/Nile/nile.wml @@ -0,0 +1,259 @@ + + + +#include "catart.wml" + + +The nile (nile is a literate editor) applitude +

$Id: nile.wml,v 1.4 2000/12/08 23:05:20 tjl Exp $
+ + Tuomas J. Lukka
+ lukka@iki.fi +
+
+ + + +

+This is a short, living (hopefully) description of the Nile applitude +and issues related to it. + +

+{#MYTOC#} + +Note + +

+ Writing this document is bothersome, because now that the idea + of Nile exists in my head, using conventional writing tools is + annoying, to put it mildly. I can now very easily sympathize + with the Xanadu group not publishing too much about their work - + describing a much easier system for writing using a much more + difficult system seems almost a sacrilege. + +

+ However, this must be done. If there is no conversation + and no exchange of ideas, there is nothing. + +Introduction + +

+ The idea of nile is to experiment with doing "word processing" + (for want of better term) in ZigZag. It is by no means a final + system but already the plans for it contain several features + not found in current products. + +

+ +Units + +

+ Here, we define Nile's units for the following sections. + For each unit, the unit itself and the insertion points + are described. The insertion points are simply the points + in the stream where units of this type may be inserted. + +

+ XXX Should discuss also cutting and pasting behaviour here. + + Characters + +

+ Not much to say - pretty usual stuff. + Characters may be inserted anywhere. + + Words + +

+ A word is defined either as a sequence of alphanumeric characters, + or a single punctuation character. + Words are usually separated by spaces. + +

+ This definition is not yet complete - e.g. the handling of + smileys is incorrect, but it will do for the first version. + +

+ Words may be inserted before any other word, or at the end + of a paragraph. + +

+ Cutting and pasting words is not terribly simple because + of the way people expect them to behave. + The following drafts are rudimentary and may be in need + of significant adjustment. + +

+ When words are cut away, +

+if the word is only punctuation,
+	do nothing.
+if there is a following space or two spaces,
+	cut them along
+else, if there is a preceding space,
+	delete it.
+
+ Deleting the preceding space seems an easier alternative than + having to test for it later, at paste time. + +

+ When words are pasted, +

+if there is a space or paragraph break
+   preceding the paste location
+	paste at that location and make 
+	sure the last pasted character
+	is a space (insert if necessary)
+else if there is a space after the paste location
+	SHOULD NOT HAPPEN
+else if one of the adjacent characters is alphanumeric,
+	make sure there is a space on its side.
+
+ +

+ Except that it isn't quite that easy when punctuation + is involved. This is because we need to remember where + the punctuation was but still leave a space. + If the span to be cut away starts with punctuation, cut + all spaces before it as well as after, but insert an extra + space after having cut, if there was a space + in the end of the cut-away piece. This is still + a bit under development... + +

+ Probably I should enumerate all the possible cases here... + Brackets are the part cut away, Parentheses are the + original selected part, and an asterisk means a space added + after the cut. +

+	A [(B) ]C
+	A B[(, C) ]*D
+	...
+	
+ + Sentences + +

+ A sentence is defined as a sequence of alphanumeric characters, + punctuation and spaces that does not contain a double space anywhere + inside itself and does not start or end in a space. + Sentences are usually separated by double spaces, or alternatively + paragraph edges. + +

+ The choice of the double space is meaningful, but no time to + go into that here. + +

+ Sentences may be inserted before any other sentence, or at the end + of a paragraph. + +

+ When sentences are cut, cut the spaces after the last sentence along. + When they are pasted, make sure there are two spaces or + a paragraph beginning before the start. + + + Paragraphs + +

+ The beginning of a paragraph is marked by a special (empty) cell + in the Nile stream. Another cell, connected to the cell in the + stream tells which level of paragraph it is (H1..H6 or P, as in HTML). + +

+ Paragraphs may be inserted before any paragraph or at + the end of the stream. + +

+ Cutting and pasting paragraphs is simple: + when cutting, it must be from the initial marker cell, + up to either the end of the stream or just before another marker + cell. + When pasting, it has to go just before another marker cell + or at the end of the stream, and then everything works out. + +Modes + +

+ One of the special features of nile is that it is more + explicitly aware of the nature of text than conventional + word processors. + While e.g. recent versions of MS-Word take a mouse selection + to be at word boundaries by default, Nile goes much further + and allows the user special movement modes. + +

+ One of the underlying ideas (which Ted has been talking + about for a LONG time) here is that once a text is initially + written, there is a long period of rearrangement and revision -- + often longer than the initial writing. + In that phase, the most of the editing actions are concerned with + rearranging words, phrases, sentences, paragraphs and sections. + +

+ However, most current programs, such as e.g. Mozilla's composer, + only deal with characters and force the user to exactly aim at the word + boundaries himself. Support for words and sentences is small; + double-clicking on a word selects that word but selecting two words + requires careful aim. In MS-Word, selecting two words is fairly easy + -- but selecting two sentences again requires more aiming. + +

+ Also, after selecting the part of text, we come to one of Ted's + favorite gripes: cut&paste. To move the text to another location, + it will first have to be vanished from the screen and then + vomited out at another location. + + The Nile solution + +

+ The solution used in Nile is the hop operation. + This operation, available for cells in the usual cell view + of GZigZag performs rearrangements such as + ABCDE into ABDCE. + +

+ The hops happen along the natural units: when word or several + words are selected, they hop one word at a time, when sentence(s) + are selected, they hop one sentence at a time etc. + Of course, a super-hop operation can also be useful, which would + hop words a sentence at a time etc. + +

+ One of the reasons why hop is natural is that all text is visible + at all times. This is especially true in the GZigZag implementation, + where the infrastructure provides animation between frames. + So hopping a word causes a smooth animation to happen where the + words exchange places. This visibility makes it easier + for the user to orient to the new way the text is laid out. + There is no abrupt rebreaking of lines either: the words which + jump from one line to another also smoothly glide over. + +

+ It is important that the hop operation be reversible: + hopping left and then right should ALWAYS produce the + same text as the original, unless the hop left command + bumped into the left edge of the document. + Someone should probably go over the definitions of the word + operations mathematically to think about how to ensure + that this property works always. + + + + + + + + + + diff --git a/Documentation/Nile/nileug.wml b/Documentation/Nile/nileug.wml new file mode 100644 index 0000000..c4a28c5 --- /dev/null +++ b/Documentation/Nile/nileug.wml @@ -0,0 +1,114 @@ + + + +#include "catart.wml" +#use wml::fmt::xtable + + +Nile User's Guide +

$Id: nileug.wml,v 1.1 2000/12/09 02:29:35 tjl Exp $
+ + Tuomas J. Lukka
+ lukka@iki.fi +
+
+ + + +

+A short introduction to using Nile, mostly for explaining the +keybindings. + +

+{#MYTOC#} + +Warning + +

+ This document may be out of date. If this seems to be the case, + please contact the author. + +Keystrokes + +

+ Unlike most current word processors, + Nile has several different modes. + This may seem complicated but the modes are fairly natural. + The most commonly used modes are the character, word and + sentence modes, through which the user can move with the + TAB key. In these modes, the following cursor keys apply: + + + + + (=,1) colspan=2 + Moving and hopping text + (+,1) + Left/Right + (=, 2) + Move the cursor + (+,1) + Shift-Left/Right + (=, 2) + Extend the cursor + (+,1) + Ctrl-Left/Right + (=, 2) + Shrink the cursor + (+,1) + Alt-Left/Right + (=, 2) + Hop the selected text + + + + + (=,1) colspan=2 + Deleting text + (+,1) + Backspace + (=, 2) + Delete the previous unit. + (+,1) + Delete + (=, 2) + Delete the selected text. + + + + (=,1) colspan=2 + Inserting text and changing modes + (+,1) + [text] + (=, 2) + Insert the letter and move to character mode. + + (+,1) + Enter + (=, 2) + Break the paragraph. + (+,1) + Tab + (=, 2) + Move to the next mode. + + + + + + + + + + + diff --git a/Documentation/PROTOCOL b/Documentation/PROTOCOL new file mode 100644 index 0000000..d01d110 --- /dev/null +++ b/Documentation/PROTOCOL @@ -0,0 +1,192 @@ +Version 0.03 of the *active* ZZ protocol. To be used over short +distances and reliable connections. + +Ascii pipe / file / ... + +Newlines: UNIX-style + +Initiation: + +SERV: + ZZ(protoversion)(uniqueservid)(serversessionid) +CLI: + ZZ(protoversion)(uniqueclientid)(clientsessionid) + + +Home cell is always cell id 1. id 0 does not exist. So a natural start +would be + + 1 ref(1)(+1) + +Requests always made with reqno and may be answered out of order. +Reqno is a simple integer. + + ()()... + +Reply: + (... + +E.g. + +CLI + 50 getcell(24)(d.1)(+) +SERV + 50 cellno(40) + +or if no cell is there, + 50 cellno(0) + +EXCEPTION: +for get text and set text, the last parameter is a number, then newline +and then number bytes of binary data, not followed by newline. + +The requests are + + get()()(

)()() ---> cellno + gethead()()()()() ---> cellno + sethead()()() ---> ok + new()()()()() ---> cellno + delete() ---> ok + connect()()() ---> ok + insert()()()() ---> ok + disconnect()()() ---> ok + gettext() ---> text + settext()() ---> ok + ref()() ---> ok + lock()() ---> locked + unlock()() ---> ok + execute()()()() ---> ok + clearerr(errorid) ---> ok + +And the responses: + + cellno() + locked() + wouldblock() --- if requested non-waiting lock didn't work + ok --- no parameter + text()() + error(errorid)(errorstring) + +REFERENCE COUNTING AND INFORMING: + +The client asks the server to hold in mind that the client has n references +to a cell and wishes to be informed about any changes. The parameter +of the requests if for this purpose: it contains the number of references +this client will have to the cell. When the count goes to zero, +the server need not inform the client about changes. + +The ref request can be used to create more references or unreference, +via a negative . + +The informing happens through the special reqno code -1: + + -1 changed() + +The reason for the ref parameter for all the calls that return cells +is to avoid race conditions: getting the cell first and then referring +allows the cell to be changed in between: e.g. + + A --- B + +we know cell A and get cell B through it but before we ref it, someone +severs the link: + + A B + +but since our ref request is received only after this, we never find out +about this and assume they are still connected. Therefore, to avoid +race conditions, the immediate ref:ing is possible. + +Since the client can't otherwise behave correctly, there is a special +code when the cell is deleted: + + -1 deleted() + +since otherwise the client might try to get neighbours of the deleted +cell. + +LOCKING + +The parameter represents the number of locks this process +wants on the cell - generally 1. +The lock does NOT preclude any other client from doing anything but only +stops others from locking the cell. Locks can be requested synchronously +or asynchronously, in three different ways: + + 1. lock = "1" -> tries to lock, returns wouldblock if can't + 2. lock = "1w" -> tries to lock, waits until can lock. DEADLOCK DANGER + 3. lock = "1a" -> tries to lock, sends the locked command + only once the lock is obtained - the other results of the request + will keep going. + +A server has the right not to support any locking --- it is possible +to put a protocol filter on top of it that does. + + + +ERRORS + +If it is likely that two processes would modify the same cells, they should +agree to lock the cells. In that case, the fastest processing times would +be achieved through performing all these operations in one row: + + lock(50)(1w) + new(50)... # operate + unlock(50) + +Because of this, there needs to be a way of performing a series of +operations but only if all of them are successful. Therefore, after +sending an error, the server will wait for the clearerr command and +ignore all the commands before it. Since the error has the number of the +request in front of the command, the client will be aware of what has happened. + +This way many useless context switches can be avoided. + + + +======================================= +PROPOSAL: New change op. +Idea from Benjamin Fallenstein. + +Instead of new, delete, connect, insert, disconnect, settext you would +simply have one command to upload a fragment of zzspace, possibly identified +with a current fragment. + +So + uploadfrag + curcell(O) + delcell() + newcell(N) + connection()()()() + endupload + +where ONid is O, N or 0. + +Thus, disconnect(15, d.1, +) would be + + uploadfrag + curcell(Ocell) + connection(Ocell)(d.1)(+)(0) + endupload + +and insert(f, d.1, +, w) where the next cell after f is g, is + + uploadfrag + curcell(Of) + curcell(Og) + curcell(Ow) + connection(Of)(d.1)(+)(Ow) + connection(Ow)(d.1)(+)(Og) + endupload + +By default, all the other connections remain. + +OTOH, insert is a nice primitive operation for many things, like cursors.... +On the other hand, an operation like jump is dangerous to synchronize +otherwise, implemented using the above connect operation. + +An uploadfrag can be guaranteed to be atomic... this + locking begins +sounding good. + +- keep insert and uploadfrag, discard others? + diff --git a/Documentation/README b/Documentation/README new file mode 100644 index 0000000..3f1ad6c --- /dev/null +++ b/Documentation/README @@ -0,0 +1,55 @@ +NOTE: do contact the author (lukka@iki.fi for most of the stuff) if +there is an unfinished part that you really need - I sometimes need +prodding to get things finished. Comments are also appreciated. + +NOTE 2: +THE SUBDIRECTORIES THAT ARE CURRENTLY BEING ACTIVELY WRITTEN ARE +CyberText, DesignProblems and Spec. THE OTHERS ARE A BIT STALE. + +I recommend starting with the Gentle_Introduction and then working your +way through the others if the subject matters interests you (for example, +if you are not hacking the internals, CellScroll will not be interesting +to you). + +Some of the documents are written in LaTeX using gpic to compile +diagrams (since it seems more reasonable than e.g. xypic or any +picture language I've seen for LaTeX). See the Makefile for how +the process is supposed to go. The LaTeX files also use rcs.sty, +which is available in the Debian linux package rcs-latex, but also +probably from CTAN. I'm planning to put up autogenerated PostScript +files of these Real Soon Now. + +The files in this directory: + +Gentle_Introduction/ + an introduction to what ZigZag is and how it works. + +Clang_Design/ + Clang is a language for writing programs using the ZigZag + structure... no, better to say: Clang is a way of interpreting + a certain kind of ZigZag structure as a program. + This document discusses the various issues at stake when + designing Clang. + +CellScroll/ + CellScrolls are a way to store both the current state + and all former states of a ZigZag space. + +Interfacing/ + +misc/ + odds and ends + +DimBased/ + Some thoughs on reorganization of the model to think about ZZ + in the code to be based on dimensions, not so much cells. + +PROTOCOL + ASCII description of the ZZ network protocol. Don't rely on this: + use the source, Luke. + + The protocol needs some rethinking anyway. + +wmlinc/ + Some include files used in the WML (website modeling language) + files around. diff --git a/Documentation/STARTING b/Documentation/STARTING new file mode 100644 index 0000000..f6a8417 --- /dev/null +++ b/Documentation/STARTING @@ -0,0 +1,24 @@ +$Id: STARTING,v 1.2 2000/09/09 13:37:32 tjl Exp $ + +Documenting how to start with GZigZag is difficult because it +is a moving target. So if there are any discrepancies with the +current CVS version and this document, please ask me (lukka@iki.fi) +to update it. +Especially the keystrokes are liable to change soon. This is the situation +at the date given above. + +When you first start GZigZag, you get two windows showing cells and +their connections. +The system works so that +you click on the right-hand window to focus on it and then all you need +is the keyboard: you can forget the mouse (it does work though: clicking +on a cell moves to it). + +For the cursor motion you have the keys "IJL," and "ESFC". Pressing Tab +will give you a text insertion cursor that you can move sideways with the +arrow keys. + +Other commands are n- for new cell, / (slash)- for connecting +two cells etc. They are shown in the user's guide. + +Any other questions, just mail me. diff --git a/Documentation/Slices/SliceLogic b/Documentation/Slices/SliceLogic new file mode 100644 index 0000000..bd94b9e --- /dev/null +++ b/Documentation/Slices/SliceLogic @@ -0,0 +1,179 @@ +Date: Tue, 14 Jul 1998 19:35:41 +0900 +To: zzdev@xanadu.net +From: Ted Nelson +Subject: :zz: ZigZag Design Notes: SLICE LOGIC 1 (d6 +Cc: ted + +zzSliceLogic.d6 +98.07.14 + +[illustration accompanying this email: zzSliceLogic.bmp] + +SLICE LOGIC 1 + +The main objective of the ZigZag Slice system is to be able to combine +pieces of zzstructure. Relatively fixed material (ends of rows, ends of +columns, titles) are expected to stay in RAM, with other stuff coming and +going. + +Further objectives: +- to limit RAM usage without going to some system of virtual memory +- to allow the user to select the portions being worked on +- to allow slices to slide into the middle of other slices according to the +user's desire. (Thus slices should be connectable anywhere, even in the +middle of ranks.) + +MANY logics and rule-sets are possible for this. I have thought about this +for some years. + +What follows is the simplest method I could work out that does the job +neatly. It is called "Slice Logic 1" because it's the easy one that I +think we should implement first. (Last week I produced a document with a +more complex system, possibly for implementation later, and quite +interesting technically-- I think-- but I want you to see this one first.) + +This system need not be implemented all at once. For instance, we can +forbid Part II at first. + +- - - - - +PART 0. SKIP ON FIRST READING. + +0000. (If a rank has a leading edge, it cannot be a ringrank and +necessarily has a trailing edge.) + +000. ASSUME that the user can neatly divide the world into slices. +Slices, like dimensions, may have any names, but with a prefix: slices +begin with "s.". Lexical order thereafter will be significant. + + +00. There may be a d.slice and d.slicelist, not discussed here. +(Eventually-- or now if there is a need-- the list of slices can be +maintained along d.slice, and the cells of a slice can be connected on a +list in d.slicelist. Still under consideration.) + +- - - - - +PART I. PREFLET LOGIC. + +0. A ZigZag slice is a data set with cells which may be connected to each +other in the ordinary ZZ way. But not necessarily; there may also be loose +cells in the slice. + +1. Slice 0 (s.0) is always resident. + +Other slices may be called in as needed. + +2. Slices are independent structures. CONNECTIONS BETWEEN SLICES ARE NOT +OF THE USUAL KIND, with doubly-linked cells. Instead, they have +*preferred* points of attachment. + +3. PREFERENCE OF ATTACHMENT IS EXPRESSED BY MEANS OF A 'PREFLET'-- a piece +of information in the cell specifying a cell in another slice to which it +would *like* to be attached, negward, in a specified dimension. + +In the current design, a cell may have only one preflet in a given +dimension. + +4. The process of resolving preflets determines the way in which the +slices are attached. However, once attached, the slices are stitched +together doubly-linked in RAM somehow as ordinary zzcells. (Implementation +is not significant; eventually different slices should be storable by +different databases or other methods.) + +5. When a slice is brought in, only the preflets of its leading edge-- all +the negend cells-- are considered. (This could be done thusly: test all +cells to see if they are negends; test all negends for preflets.) + +6. Any cell with a preflet for a cell already resident, and not contested +by any other cell's preflet, gets to insert/attach itself to the specified +cell. + +7. If a cell has a preflet for a cell which is not currently resident, the +preflet is ignored. + +8. Two cells may have to be separated to honor a preflet specifying one of +them. These two cells will rejoin when the slice is swapped out, if +appropriate. + +IF THEY HAVE A LOCKED LINK (not yet implemented), they may not be separated. + +9. If two leading cells in two slices both have a preflet for the same +cell in another slice which is resident, the slice with lower lexical order +wins-- and the second slice attaches itself *indirectly*, to the trailing +edge (posend) of the winning cell's rank. See illustration. + +10. If two leading cells in the same slice A have a preflet for the same +cell in a second slice B which is resident, the slice with lexically lower +cellname wins-- and the second slice attaches itself *indirectly*, to the +trailing edge (posend) of the winning cell's rank. See illustration. +(This would probably lead to the two ranks in A later becoming a single +rank, due to rule 12.) + +11. Whenever a slice is swapped in or out, the preflets of all current +slices must be resolved again. + +12. Whenever a slice is swapped out, its detached negends are given +preflets again. These preflets will normally be to the cells from which +the cell has just been detached in s.0-- either directly or indirectly. + +13. If swapping a slice out severs a rank in some other slice (usually +s.0), that rank is reconnected where the swapped-out cells have just been +taken away. (This will re-attach cells which were separated by the +incoming slice, unless they have been moved.) + +- - - - - +EXAMPLE. + +Consider the illustration. Assume that the x-axis is d.1 and the y-axis is +d.2. + +Not shown is s.0, which contains cells 16, 42, 131, 265 and 22. These are +not necessarily negends. + +Shown are two slices, s.2 and s.4. They have leading-edge preflets for +some of the same cells in s.0. + +The preflets for 13 and 22 take effect without conflict. What follows is +about resolving the others. + +Both s.2 and s.4 have a leading-edge preflet in d.2 for cell 16. s.0 wins. + The cell in s.4 with a preflet for 16 connects to the *trailing* edge of +the same rank in s.2 (cell 68). + +Similarly, both slices share a preflet for cell 42 in d.2. s.2 wins, and +s.4 connects to the trailing cell in the same rank, cell 4. + +Similarly, both slices share a preflet for cell 265 in d.1. s.2 wins, and +s.4 connects to the trailing cell in the same rank, cell 31. + +If s.2 is swapped out, preflets are considered again at the leading edges +of all slices (except s.0). Thus s.4's preflets for 16, 42 and 265 then +cause them to be directly attached to 16, 42 and 265. + +If s.4 is then swapped out, each rank of s.4 which is extracted from within +a rank in s.0 causes that rank in s.0 to be reconnected. + +- - - - - +PART TWO: CROSSING OF CELLS BETWEEN SLICES. (May be disallowed in Phase 1.) + +13. (The user somehow knows where the slice boundaries are.) + +14. If a cell is moved / hopped / connected into a different slice, and +has *no* other connections to its former slice, all its contents are moved. + The information that travels with it includes its contents, processor of +origin, cell of origin, and which slice the cell of origin is on. + +15. If a cell is moved / hopped / connected / cloned into a different +slice, and retains connections to its former slice, a Remote Clone is +made. The information that travels with it includes its contents, +processor of origin, cell of origin, and which slice the cell of origin is on. + +16. When a cell is swapped in, Remote Clones must be resolved. + +If a Remote Clone's connections in all slices are consistent with each +other, it is considered to be one with its origin, and they are shown as +only one cell. However, if they are inconsistent-- more than one +connection posward or negative in a given dimension-- the second instance +is deemed to be a clone. After each operation its connections should be +checked for compressibility to one cell. + + diff --git a/Documentation/Slices/zzSliceLogic.jpg b/Documentation/Slices/zzSliceLogic.jpg new file mode 100644 index 0000000..8b09096 Binary files /dev/null and b/Documentation/Slices/zzSliceLogic.jpg differ diff --git a/Documentation/Spec/Makefile b/Documentation/Spec/Makefile new file mode 100644 index 0000000..5a8bd26 --- /dev/null +++ b/Documentation/Spec/Makefile @@ -0,0 +1,15 @@ +# DIAGRAMS=linkorder.png beamorder.png +DIAGRAMS=cursor1.png cursordim.png canvasraster.png rasterspec.png \ + inheritparam.png +DEP=../wmlinc/article.wml + +all : zzspec.html zzspec-ns4.html + +zzspec.html: zzspec.wml ../keybindings.wml $(DIAGRAMS) $(DEP) + +zzspec-ns4.html: zzspec.wml ../keybindings.wml $(DIAGRAMS) $(DEP) + +include ../lib.mk + + + diff --git a/Documentation/Spec/canvasraster.dia b/Documentation/Spec/canvasraster.dia new file mode 100644 index 0000000..27d98aa --- /dev/null +++ b/Documentation/Spec/canvasraster.dia @@ -0,0 +1,427 @@ + + + + + + + + + + #A4# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #viewspx# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #CanvasRaster# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #d.cursor-cargo +and +d.cursor# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #R# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #d.2# + + + + + + + + + + + + + + + + + + + + + diff --git a/Documentation/Spec/cursor1.dia b/Documentation/Spec/cursor1.dia new file mode 100644 index 0000000..13bcb85 --- /dev/null +++ b/Documentation/Spec/cursor1.dia @@ -0,0 +1,590 @@ + + + + + + + + + + #A4# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #viewspx# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #A# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #C# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #d.cursor# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #d.cursor-cargo# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #...# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #...# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + diff --git a/Documentation/Spec/cursordim.dia b/Documentation/Spec/cursordim.dia new file mode 100644 index 0000000..d27b430 --- /dev/null +++ b/Documentation/Spec/cursordim.dia @@ -0,0 +1,769 @@ + + + + + + + + + + #A4# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #Y# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #A# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #C# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #d.cursor# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #d.cursor-cargo# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #...# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #...# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #viewspx# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #X# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #d.dims# + + + + + + + + + + + + + + + + + + + + + diff --git a/Documentation/Spec/email1.dia b/Documentation/Spec/email1.dia new file mode 100644 index 0000000..a76e848 --- /dev/null +++ b/Documentation/Spec/email1.dia @@ -0,0 +1,597 @@ + + + + + + + + + + #A4# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #Mailboxes, other structure# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #d.ref# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #d.handle# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + diff --git a/Documentation/Spec/inheritparam.dia b/Documentation/Spec/inheritparam.dia new file mode 100644 index 0000000..3a072ce --- /dev/null +++ b/Documentation/Spec/inheritparam.dia @@ -0,0 +1,885 @@ + + + + + + + + + + #A4# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #start# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #param# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #value# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #+# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #param# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #param# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #value# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #Traversal# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #d.1# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #d.2# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #d.3# + + + + + + + + + + + + + + + + + + + + + diff --git a/Documentation/Spec/rasterspec.dia b/Documentation/Spec/rasterspec.dia new file mode 100644 index 0000000..322c8ae --- /dev/null +++ b/Documentation/Spec/rasterspec.dia @@ -0,0 +1,678 @@ + + + + + + + + + + #A4# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #vanishing# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #gap# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #5# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #5# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #depth# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #6# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #d.2# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #d.1# + + + + + + + + + + + + + + + + + + + + + diff --git a/Documentation/Spec/zzspec.wml b/Documentation/Spec/zzspec.wml new file mode 100644 index 0000000..f67a882 --- /dev/null +++ b/Documentation/Spec/zzspec.wml @@ -0,0 +1,1127 @@ + + + + + + GZigZag spec + +#include '../wmlinc/article.wml' +#use wml::fmt::xtable + + + + + + +

GZigZag spec

+
$Id: zzspec.wml,v 1.24 2001/02/13 18:54:28 ajk Exp $
+ +Written by
+Tuomas J. Lukka
+Benjamin Fallenstein
+Antti-Juhani Kaijanaho
+(add your name here if you do any significant modification) + + + + + +

Introduction

+ +

+The purpose of this document is to be a living specification of the +features in the GZigZag system. The GZigZag system is an implementation +of the ZigZag structure, invented by Ted Nelson. Much of this document +is simply a somewhat more verbose version of discussions with him but +other places go into more technical detail. + +

+Some parts of this specification are not yet correctly implemented by +the current version, but in these cases, this document is correct (or +it should be ;-) +and the implementation wrong. + +

+Some parts of this spec are at the moment +just general ramblings about a topic - once +we have the pole editor, I will definitely rearrange it completely. +The idea is to try to make them more and more like a true spec as +time goes by. + +

+The parts marked with the dreaded triple-X symbol (XXX) are as yet incomplete +and should be taken with a not only a grain but a mountain of salt. They +mostly contain just a few loose sentences setting the topic. + +

+If you see anything suspicious, feel free to ask me at lukka@iki.fi. + + + +

The role of ZigZag in the overall scheme of things

+ +

+ZigZag is a delightfully simple way of operating structures. +As such, it has its own uses simply as a personal information manager +for people who like multidimensionality, + +

+In addition to stand-alone use +ZigZag is related to Ted Nelson's Xanadu system; a newer version of Xanadu +is being designed to make use of ZigZag as a platform. +As a brief description of Xanadu, it has +

+
Stable media streams (permascrolls) +
A stable media stream is an invariant, addressable stream of + data, e.g.~text, video or audio. +
Documents +
In Xanadu, documents + are simply lists of spans from the stable + media streams. +
Content links +
The linking model is fundamentally different + from anything else hitherto seen. All links are handled on the + lowest level, i.e. as links between lists of spans of stable + media streams. +
Finding by content +
There are fast ways to find out in which + documents a particular point in a stable media stream is + included. All content copied via cut&paste can be tracked. +
+ +

+ZigZag can also work as a platform for other types of applications +--- or preferably applitudes, meaning that they should also expose the +other possibilities of ZigZag at the same time as being normal +applications. This is so that the interconnectivity provided by ZigZag +can be used to make the whole of two applitudes greater than the sum +of the parts. + + +

Cells, dimensions and connections

+ +

A cell is the fundamental container of data. A cell can +"physically" contain either a text string or a single, contiguous span +(which is an address, and references a permascroll). + +

A cell has an ID, which is a string. Currently, if a cell ID +contains a colon (:), the cell belongs to a space part, where +the space part ID is everything from the beginning up to and excluding +the colon. If a cell ID contains an at sign (@), it is a global +ID; everything starting from and excluding the at sign to the end +of the ID is the ID of the cell's creation space. If the +creation space ID differs from the ID of the space the cell is in, the +cell is foreign, otherwise its native. + +

+Cells may +be connected to each other along dimensions, +so that each cell can be connected to another cell in two directions +(negative and positive) on each dimension. +The more global structure is not constrained: any two cells can be +neighbours on any dimension, but some of these connections are used +for interpreting the structure into views and actions (see below). + +

+It is not yet clear whether dimensions are strings or whether they +are cells. The various slice and compound space +implementations will probably affect and depend on this. +If dimensions are cells, then several uniqueness problems are quickly solved, +but their being strings may be easier on the users. + +

+One important point is that of headcells: on non-circular ranks, the headcell +is the cell at the negative end of the rank. +Ted specifies that all ranks should have a headcell and that there should +be a way to specify the headcell of a circular rank. The exact mechanisms here +are as of yet unclear. + +

Dimension-oriented view

+ +

+An important way to describe the space is to take dimensions to be +"objects": the dimensions are +invertible mappings between cells. This is opposed to the immediate way +of thinking "cell and connections", and there is a difference. + +

+This view is important because here it is easy to discuss special dimensions +that have interesting properties. + +

Subspaces, closed cell sets, closures

+ +

+ The following terms may prove useful from time to time: + +

+

+
Closed set of cells
+
+ A set of cells C is closed with respect + to a set of dimensions D if and only if all neighbours of + the cells in the set C along the dimensions in D are also + in the set C. +
+
Semiclosed set of cells
+
+ A set of cell C is semiclosed with + respect to a set of dimension-direction pairs D if and + only if all neighbours of the cells in the set C along the + dimensions and their associated directions in D are also in + the set C. +
+
Closure
+
+ Let us have a set of cells C and a set of dimensions D. A + set C' is a closure of C with respect to + D if and only if it is a minimal closed (with respect to + D) set containing all the elements of C. +
+
Semiclosure
+
+ Let us have a set of cells C and a set of + dimension-direction pairs D. A set C' is a + semiclosure of C with respect to D if and + only if it is a minimal semiclosed (with respect to D) set + containing all the elements of C. +
+
Subspace
+
+ A subset C of the set of cells in a ZigZag space Z is a + subspace of Z with respect to a set of + dimensions D, if and only if C is closed with respect to D + in Z. +
+
Proper subspace
+
+ A subspace C of a ZigZag space Z is a proper + subspace if it is closed with respect to the set + of dimensions D which contains every dimension of Z except + d.cellcreation. +
+
Semisubspace
+
+ A subset C of the set of cells in a ZigZag space Z is a + semisubspace of Z with respect to a set + of dimension-direction pairs D, if and only if C is + semiclosed with respect to D in Z. +
+
Generated subspace
+
+ A set of cells C in a ZigZag space Z and a set of + dimensions D are said to generate a + subspace C', which is the closure of C with respect to D + in Z. +
+ +

XXX: are these definitions OK? + + +

Key structural mechanisms

+ + +

Cursors

+ +
+The path from the viewcell viewspx +to the cell the cursor of the view points to A +via the main cursor cell C which may or may not be the +same as viewspx. +C is at the negend of d.cursor-cargo +from viewspx and the accursed cell A is +at the negend of d.cursor. +
+ +

+The viewcell points to a particular cell where its cursor lies. The idea +of cursors is not restricted to cursors of views but, as we shall see +below, anything where selecting a single cell is important. This makes it +possible to create a new view to select that cell on the fly (see below). + +

+In the structure, a relcell is used so that several cursors can be +maintained pointing to the same cell. The path to find the cell the +view is pointing to is start at the viewcell, go to the posend on +d.mycursor and then to the posend on d.cursor. + +

+In order not to disturb other cursors, the insert operation should be +used to move the relcell to a new d.cursor rank. This operation +will leave the original and the new rank otherwise intact. +It is possible that any other operation on d.cursor will +be declared illegal. + +

Inheritable parameter lists

+ +

+NOTE: this is liable to change. It is only documented here for +understanding. + +

+An example of the inherited parameter traveral to find a parameter +value. Starting from start, we go poswards on d.2 +until we reach a cell with a negward connection on d.3. +We include that list and return to the main list. The parameters +that have values store them on d.1 or as cursors starting +on the parameter cell. +
+ +

+This section defines a way to inherit parameter lists based on the +structure. + +

Paths

+ +

+Paths are a precursor to Clang, and allow the user to express abstract +paths in the structure. XXX See the docs for ZZPath.java. + +

Selectors

+ +

+Selectors are a generalization of paths: where paths are like +zeroth-order logic, selectors are first-order logic, allowing quantifiers +("every cell in this rank") but not quantification over quantifiers, +or anything terribly general. + +

+The point is to be able to easily describe in the structure the operation +"show also all replies to this email", where the replies are generally +connected to the original by some route. + +

+One interesting idea that may or may not see the light of day +is using inverse paths for selectors. This has certain aesthetic +appeal. + +

Views

+ +

+A view is represented by one maincell in the structure, called the +viewcell. This cell can contain text which will be interpreted as the +``title'' of the view, but this is not mandatory. + +

+XXX Since some views which contain more than one cursor are planned, +it is possible that something will change below. + +

Visible Dimensions

+ +
+The path from the viewcell to the cell specifying the Y dimension shown. +First, we go two steps on d.dims, then +use the same method as in the previous figure for getting to the accursed +cell from there. +Note that both the viewspx cell and the X have +cursors similarly attached to them. +
+ +

+Dimensions that are currently visible +are listed on d.dims from the viewcell, in order X, +Y, Z (and possibly others, in case of complicated view rasters). The +dimension cells are treated as cursors, i.e. the cell representing the +dimension is found by going to the posend on d.mycursor and then +to the posend on d.cursor from the dimension cell. + +

+The point of this odd-seeming arrangement is, as alluded to in the +Cursors section above, is that we can very simply create a new view that +is bound to a dimension cell of another view. + +

Dimension lists

+ +

+In order to change dimensions shown, the views provide an operation ``move +the X/Y/Z-dimension-selector-cursor one step pos/negwards on d.2''. +The usual plain-vanilla dimension lists are thus simply lists of cells on d.2 +which +contain the dimension name as a string (possibly by cloning). +Most often these lists are cyclic but this is not mandatory: trying +to move past the end/beginning of a list simply does nothing. + +

+This is just the default arrangement - the user is free to create other +dimlist operators and use them to change the dimensions taking advantage of the +structure in a different way. One example of an operation we may want to provide +at some point is "change dimension but not to one already being shown". + +

+To select the dimension list for a particular dimension of a particular +view, the user can simply create a new view for the dimension cursor, +using the cursor-cargo mechanism. +To set all the dimensions to the same list, the user can set the X +dimension and then invoke a special operation that sets Y to the +d.1 poswards neighbour of X, Z to the neighbour of Y and so on, on the +same list. + +

Raster definition

+ +

Vanishing raster

+XXX + +
+Getting to the raster-defining cell R from the view specs. +Note that the cursor-traversing operation is abbreviated to the curvy arrow. +Also note that the inheriting mechanism defined previously is allowed. +
+ +

+The raster to use is obtained similar to the dimensions to use; +only the first motion is different: down on d.2 until the text +FlobRaster is found. + +

+A sample specification of a vanishing +raster, specifying values for two parameters. +Here, the vanishing cell would stand in for the +R cell in the previous image. +
+ +

+The raster itself is specified using a corner list. +An incomplete list of parameters follows: +

+
shrink +
2 floats; the numbers to multiply the width and height + of the cells with. +
gap +
2 ints: the number of pixels of space to leave between cells +
depth +
1 int: The number of cell "layers" to draw. +
dimorder +
2.. ints. The precedence of dimensions. +
initmul +
1 float. If the default size of cell will be multiplied by a number + for the center cell (it is usually good to make the center cell + larger +
+ +

+There are currently some undocumented interactions to provide for +hard rasters; see the source. + +

Simple Flob Raster

+ +The simple flob raster displays flobs extracted from the structure, +on dimensions given by the structure. +The dimensions are given by attaching paths to the cells in the dimlist. + + + +

Primitive operations

+ +

Connect

+

Insert (XXX rename)

+

Mono-chug

+ +

+ This operation changes one connection. It takes two directions + and one cell as parameters. + XXX image. + + +

Bindings

+ +

+ Keybindings offer a nice way of seeing how flexible the + ZigZag structure is for programming. + +

+ Most fundamentally, the names of the keys + (e.g. Ctrl-k) are on cells connected along d.2. The + action for each key is the poscell on d.1 from those cells - this + way several keys can be bound to the same action quite easily. + +

+ However, this is not yet sufficient: there may be several + input states, e.g. with the vi editor there is the insert mode + and the command mode, and inside the command mode there is the + special mode of waiting for a motion command. So in addition + to the command, there needs to be a way to specify the next + state. Likewise, some states are similar to each other so + states should be able to inherit commands from each other in + various ways. + +

+ GZigZag uses blank cells to represent inheritance: when the + routine that searches for a key is going down along d.2, it will + go to the poscell from that cell and check all the bindings on + that dimension before returning to continue the search along + the original rank. + +

+ The cursor mechanism is useful for keybindings as well: the + current state can easily be maintaned by a cursor as shown above, + allowing the user to easily set the cursor to a different state. + However, care has to be taken here as moving the cursor in + question can render keybindings unusable, so it is better to use + an interface where the cursor can be immediately transported to + the right place (such as clicking with the mouse). + +

+ The actual structure is currently such that the bindings + cursor is the posend on d.bind of the view cell. This cursor + points to the place where the inheritable parameter search for + the next binding is begun. The cursor is set, if the inheritable + parameter's value (on d.1) has a negward connection on d.3 -- + it is set to the negend. + +

+ Additional problems arise when the same view can show + different rasters. A different visualization of a structure + often makes different means of navigation necessary, or different + operations desirable. To provide for this, it is possible to + assign a raster a list of modifications to a bindings mode; when + the mode is selected, the raster's modifications are searched + first, and the standard bindings for the mode are searched when + the binding is not found in the modifications list. + +

+ A raster can be assigned two groups of modification lists: + one to be applied when the raster is selected in the left + (control) view, and one to be applied when the raster is + selected in the right (data) view. These groups are obtained + from the same corner list as the parameters given to the raster + (see above); the text searched for is ctrlbindings + and databindings, respective. + +

+ From that cell, an intersection on d.1 and d.clone with + the current bindings mode is searched. That means that a mode + which is intended to be modified is cloned, and attatched to the + raster's bindings cell on d.1. From this cell, a definition for + the binding is searched on d.2; if none is found, the mode's + default bindings are invoked. For any of these searches, the + standard parameter inheritance (see above) is allowed. + +

+ This method is practical because it "feels" very much + like the definition of the modes themselves, as the modes are + commonly listed on a d.1 rank from the Bindings + cell on the system list. On the other hand, it's somewhat + different structurally. + +#include '../keybindings.wml' + +

Compound spaces

+ +

+A compound space is simply a way of taking one or more existing spaces +and creating a new space that is a view of these spaces combined according +to some rule. + +

Trivial, kludgy

+ + + +

Notification, events and synchronization

+ +

+XXX + +

+There are many situations where one may want to be informed about changes +to the structure, either before it happens (with the possibility of +vetoing it), or after (e.g.~to reraster a window). + +

Updating views

+ +

+Out of an email from Ted, +

+There are several issues here.  One is just the mechanics
+ of a clean method of synchronization.  The other is
+ the problem of A FEELING OF FAST RESPONSE--
+ which means, very importantly, PREVENTING the
+ non-current windows from refreshing in order to have
+ truly INSTANTANEOUS response to each user action.
+ Anyway, as much as possible.
+
+ +

+In order to ensure a speedy response, we have to consider the numbers. +There are thousands of cells. Each view shows some fraction of them. +At each time, there are probably 1-10 views open and changes to cells +will reflect in several of them. + +

+Therefore, it is probably unnecessarily slow to store the information about +which cells are seen by which views (except if it is naturally stored by the +view itself). Rather, for views, there should just be a global list which +gives the priorities with which the views get to refresh themselves. + +

+Now, it makes no sense to start updating +at each change to the structure - internally there has to be some method to +freeze and thaw the global update queue. + +

+One interesting problem here is finding which view is really the current view: +for instance, in the two-part view +Also, displaying only the central portion of the views whose cursor changes first +could make a big difference. Or the rank along which the cursor moves plus some +small number of cells. + +

Internal triggers

+ +

+However, this is not the whole story: views are not the only things that need +to be informed when something changes. +It should be possible to define per-cell triggers as well. + +

+This is possible in the Java code by passing an extra parameter, a +ZZObs to a routine that returns some structural information, +such as a neighbour, a headcell or the contents. +The ZZObs will then be called once after any of the items it is +observing changes, i.e. the return value of the function the ZZObs +was passed to has changed. + +

+The callback is not necessarily instantaneous; rather, all the callbacks +are grouped and run after the activity that caused the trigger has finished. + +

Cursor triggers

+ +

+Eventually, it should be possible to define these triggers in the structure +as well, but the best mechanism for that is not yet known. +However, for some applications these can't wait. Especially important are +cursor triggers, which do something whenever a cursor changes value. + +

+A cursor trigger is placed by placing the action (XXX In what form) +on d..cursor-trigger of the cursor-cargo cell. +These actions are queued to be called sometime after the cursor is +changed (usually before the next screen update). + + + + + +

Cell storage mechanism

+ +

Transient cells

+ +

+ Most of the structure is persistent but some parts should be + transient in order to save space and time. For example, if the + information about the rastered representation of a part of the + space (coordinates on the 2-D display) is stored in the space, + this would waste an enormous amount of space each time the + cursor moved. + +

+ The transiency is specified at the time of the cell creation + on the Java level. How this figures in the space is yet to + be decided. + +

+ The transient cells are not trivial: because of design + considerations, they can't simply override connections and have + all their connections appear deleted in the persistent space. + Instead, the persistent space should appear as if the cells + had been truly deleted using the delete operation, which causes + the cells on opposite sides on a dimension from the cell being + deleted to be connected to each other. In other words, if we + have the rank ABCDE and the cell D is a transient cell, then + this should correspond to a rank ABCE in the persistent space. + + +

Slices

+ +

+ The slice design is what Ted ultimately wants but because + it's somewhat more complicated to implement, it's postponed + until some other parts of the system clear up (most importantly + synchronization) and the existence of other types of subspaces + and their interaction. + + +

Versioning

+ +

+ A key mechanism for versioning is timestamps, which specify + moments in the past. The full state of the ZZ space + at each timestamp can be accessed through the file formats. + +

+ The past versions of cell structures are shown in the structure + as virtual, non-modifiable cells, except for the one allowed + source of modification: d.cursor. The dimension d.cursor + is a source of much headache in versioning because of its + nature but the current solution is to move past versions + of d.cursor to d..cursor-past. + +

+ The past versions of a cell can be accessed on d.version, + and the past versions where the cell's content or connections + have changed is on d.cell-version, and the past versions + where the cell's content has changed are on d.content-version. + So d.cell-version skips on the cells of d.version, + and d.content-version skips on the cells of d.cell-version. + The skipped-to cells are the first cells with + the new, changed property. + +

+ XXX Can we do d.cell-version efficiently??? + +

Stable media streams

+ +

+Referencing stable media streams is an important part of the +overall design. For the Dominica project, we need a subset of the +features. + +

+A cell may contain either its text directly or a reference to a +stable media stream - either an address or a span between two +addresses. For now, we distinguish between the two types by having +the references to stable media connected to themselves +along d.stableref (this mechanism {\em will} change later, and +is encapsulated in the ZZCell class as the contenttype routines). + +

+Temporarily, we use the address format AAnumber where the number +is simply the byte offset into the invariant media stream. Later on, +the addresses will be converted into tumblers. + +

+Given a space, it is possible to obtain a list of cells that overlap +with a given list of spans. +These can be used in various ways to display parts of texts that have +links in different ways etc. + +

+Later on, an enfiladic (tree-like) structure will be used to perform +the cross-matching of the cell lists. + + + +

Blobs

+ +

+Blobs are a stop en route to full hyperFlobs. +Blobs are basically objects whose coordinates and appearance +in 2D come somehow from +the ZZ space, according to user-given instructions, which are +themselves stored in the ZZ structure. + +

+A blob has two separate aspects: location and appearance. +The location is composed of multiple dimensions, specified in some +way by the structure, of which the user will select a subset of +two or three (or some more if using e.g. linear combinations). +The appearance can also be selected from multiple possibilities, +with different visual aspects showing different aspects of the +entity the blob represents. + +

+Throughout this section, I will use email as the recurring +example. Email is a good application for blobs since it makes +it possible to see the usefulness of blobs in a practical setting. +Everybody gets too much email. Current email programs are not +able to handle the load - first of all, they are too slow, reading +the entire mailbox every time the program is started and the mailbox +is opened. The obvious solution of splitting your mail into several +folders is not nice either --- it makes it much more difficult to find +anything. This problem is well solved by the stable media streams +in the previous section: instead of different files as folders, +folders are just sets of pointers to the original mailbox file. +The algorithmically great thing is that the whole mailbox need not be +reread at any point, only the new messages have to be inserted into +the structure. After that, the structure is a good way of accessing +the contents of the mailbox. +But I digress - back to blobs. + +

+In the world of blobs, each email would be represented as one blob. +Likewise each person and subject line (modulus Re). + + + + +

Variables and constants

+ +

+Each ``statement'' or ``expression' in the ZZ space will have +some parameters. For instance, an expression of ``headcell'' will +need a dimension and a direction. + +

+For maximum flexibility and ease, we want to be able to store the +dimension parameter in two different ways: first, as a direct cell or +clone of a cell, e.g. d.1, and second, as a pointer. + +

+For design considerations, the first thing to note about pointers +is that it would be quite powerful if we could bind a number of pointers +to point to the same cell --- just like cursors above. So why not +equate pointer$=$cursor, so that a cell is interpreted as itself +if there's no d.mycursor poswards and otherwise as a cursor. + +

Dimensions

+ +

+The whole concept of blobs (and flobs) is based on being able +to grab visualizable dimensions from various user-defined places +in the structure and throw the blobs on the screen at those coordinates. + +

+Dimensions can be defined by the blobs themselves or by proxy (e.g. +an email can have as one of its dimensions one of the dimensions +of the sender of the email). + +

+Eventually, it should be possible to edit some dimensions by just clicking +and dragging. Some dimensions, like the date of an email, should be +read-only but you should be able to drag email on an urgency dimension +or some dimensions of your own (to arrange them in a pleasing way +in space). + +

+Note that dimensions do not need to have numerical values. +An ordering can be quite sufficient and useful. +For example, a time dimension to email may be more useful if it is +not represented linearly but rather nonlinearly, based on the message +density, expanding dense places and possibly (like in billowing) places +that are near the cursor. + +

The structure of a blobview description

+ +

+When the blobview is described in the structure, there will be +one or many sets of blobs to render, as well as their connections. +Each set of blobs is described by +

    +
  • a set of rules and paths to +find the maincells of the blobs to display, starting from the +cursor of the blobview, +
  • a set of rules to find the dimensions to show +for each blob +
  • a set of rules to show each blob on the screen +(e.g.~which cells' text to draw and how to arrange it). +
+All of these can be given directly or as (cursorial) references to +other places. +In the future, they will be able to pass parameters to each other, +so that it would be possible to implement the perspective view through +cells as blobs. + +

+The connections between blobs will currently be described simply by +giving paths from the maincell to other maincells that may be shown +on the screen and if it is shown, a line is drawn. + +

A high-level example description of a blobview

+ +

+I warned you that email would be the predominant example of this +section. +First, let's see how we describe emails in the ZZ structure for +this simple example. + +

+First of all, there is the handle for each email. This is just +a cell that is used to designate the whole email. +As emails contain the Message-ID field which is guaranteed +to be unique, the handle cell will contain that string. +Poswards on d.handle from the handle cell are the header, the body +and the attachments. + +

+The header is a simple d.2 and d.1 job for the field type +and contents. However, both the email address cells, the subject +cell and the references (message ids) are connected structurally: +all of them point on d.ref to the handle of the corresponding +structure. It may be that the structure that these cells point to is +not loaded, in which case they just form a rank on d.ref without +the handle cell at the end. + + + +

ZObs

+ +

+It is going to be fairly common for a Java class to get its parameters +from the structure. +The ZOb mechanism is useful for easily creating such Java classes that +read their parameters in a standard way. +Basically, a ZOb is a Java class for which the instance variables are +defined inside a STRUCTPARAMS {} block. There is some +syntax support for specifying the number of elements required in arrays +etc. + +

+The point of the mechanism is to allow more latitude with the parameters +later: for example, inserting them into the structure with descriptions, +or caching the ZOb parameters read from the structure for larger ZOb +systems to speed up the process. + + +

Email applitude, v1

+ +

+This is a specification for the first version of the flob-supporting email +applitude. +The relevant structure is shown in the figure. + +XXX email1 + +The handle cell is connected along d.handle to the most important header +fields and the cell containing the actual content of the message. +The rest of the headers are stored in the structure but are not relevant here. + + +The message IDs connect replies together: the In-Reply-To: +and Message-Id fields: the message ids on the reply-to fields are +clones of the original message's message-id field. This makes it easy +to track threads using only the structure. + +

+The flob dimension specification is an interesting part of this problem: +it should be compatible with the other rasters but store extra information +for each dimension about where that dimension is to be found and whether +it's user-modifiable (by clicking and dragging). +Since each dimension is special, it doesn't make sense to have the same +dimension lists for flob dimensions and normal dimensions but the operation +of advancing a dimension can remain the same, i.e. advancing a cursor on +d.2. +In the flob coordinates, the cell on that rank gives the name and is +connected on d.1 to the actual instructions on how to obtain +the correct cell and label. + +

+The fourth dimension is used for finding the flobs to show, i.e. to +select the rank of references to show. + + +

Interactions

+ +

+This section deals with the interactions between the various +planned features. Unfortunately, this is one part that is not yet +fully specced but at least we're speccing what the problems are. + +(XXX todo) + + +((1, 2)) + Clones +((1, 3)) + Cursors +((1, 4)) + Versioning (access to old versions) +((1, 5)) + Slices +((1, 6)) + Content links +((1, 7)) + I18N + +((2, 1)) + Clones +((3, 1)) + Cursors +((4, 1)) + Versioning (access to old versions) +((5, 1)) + Slices +((6, 1)) + Content links +((7, 1)) + I18N + + +

Summary of special dimensions

+ +

+

+
d.clone +
The clone dimension. All cells on a clone rank + are clones of each other, meaning + that their contents are enforced to be the same and + changes to the contents of one are reflected to the + others. + + For example, clones could be used to represent the same + email address on a number of email headers, so that all + those instances of the same email addresses would be + linked to each other through d.clone. + +
d.cursor, d.cursor-list and d.cursor-cargo. +
A set of pointing dimensions. + This mechanism is used for instance by the views to point + to the cursor which is at the center of the view. Moving + the cursor is equivalent to inserting the maincell of the + view poswards on d.cursor from the new position + of the cursor (the accursed cell). + d.cursor-cargo provides a mechanism for locking + several cursors together. +
+ + +

File format

+ +

+This section describes the GZigZag file formats that store the low-level +structure. This is separate from the space description which describes +e.g. the system list: the file format is lower-level still. + +

+The file format is arranged as several layers, in order to +make it more flexible in the future. + +

Runs

+ +

+ Runs are the lowest level of the file: they specify a sequence + of changes to the structure, moving forwards in time. + +

+ The run formats given are version 0 of the run format. + +

Dimension change run

+ +

+ A dimension change run is a sequence of instructions + telling how one dimension changed between two specific times. + It contains records specifying connecting and disconnecting cells. + The structure is that of a simple hash: disconnecting only + disconnects in one direction. + +

The records are: + + + + Connect record: connect cell id 1 to cell id 2 poswards. + + nbytes content + 1 'c' (99). Record identifier. + 2..65537 Java UTF string. Cell id 1. + 2..65537 Java UTF string. Cell id 2. + + + + + + Disconnect record: disconnect cell id 1 in given direction. + + nbytes content + 1 'd' (100). Record identifier. + 1 '+' (43) or '-' (45). Positive or negative direction. + 2..65537 Java UTF string. Cell id. + + +

+ These records are concatenated with no record identifier in + between. + +

Content change run

+ +

This is the corresponding sequence for cell content + changes. + + + + + New string content for a cell. + + nbytes content + 1 's' (115). Record identifier. + 2..65537 Java UTF string. Cell id. + 2..65537 Java UTF string. Text content. + + + + + New span content for a cell. + + nbytes content + 1 'S' (83). Record identifier. + 2..65537 Java UTF string. Cell id. + 2..65537 Java UTF string. Content, + as a string representation of a span. + + +

Character scroll

+ +

The character scroll for text is simply a sequence of + 16-bit unicode characters, addressable by offsets. + +

Run synchonization

+ +

+ The dimensions and content (but not scrolls), are stored in + streams that contain synchronization markers between runs + of changes. + + + + Header, identifying the file type, the content type + and content version. + + nbytes content + 4 ASCII "GZZ0". Magic "number". + 4 Java int: wrapper version number. + 4 Java int: content type. + 42 = dimension + 43 = content + 4 Java int: content version. + + +

+ After the header, the actual data starts. + The data is given in runs: + + + + Run: A single run between timestamps. + + nbytes content + 1 't' (114). Record identifier. + 4 Java int: timestamp number. + 4 Java int: number of bytes to follow. + 0..2147483647 + The run. + + +

+ Only the last timestamp before which changes occurred is stored: + empty runs are not necessarily stored except for the content file. + The time the save was done could be saved in a cell with the ID + 'savetime' to facilitate backup recovery by time. + +

Stream set

+ +

A stream set, then, is a container for all of the above + things, with streams named by unicode strings. + +

Currently, this is implemented simply as a directory, which + means that using non-ascii characters, or anything that's not + alphanumeric or dots or slashes is a really bad idea. + +

Later, it will probably be a single stream that encapsulates + the other streams; it may even be that runsynch and streamset + will be combined later on. + + + + + + + + diff --git a/Documentation/Syntaxless/synt.wml b/Documentation/Syntaxless/synt.wml new file mode 100644 index 0000000..974b98f --- /dev/null +++ b/Documentation/Syntaxless/synt.wml @@ -0,0 +1,100 @@ + + + + + + The case for syntaxless languages +#include '../wmlinc/article.wml' + + +{: [[s/(?)\b(d\.+\w+)/\1<\/code>/g]] +

The case for syntaxless languages

+
$Id: synt.wml,v 1.1 2000/09/17 23:50:51 tjl Exp $
+ + +

+A manuscript-in-progress about syntaxless languages such as Clang. +Intended for eventual publication in an academic journal. + + + +

Introduction

+ +

Computational structures

+ +

+The most pervasive computing paradigm of today is that of +directories and files, and of programs written as text. +All the dominant platforms, Linux/Unix, Mac and Windows are based +on the same fundamental structure. +Indeed, the structure is so pervasive that it is difficult +for many people to even imagine a different world. + +

+However, a different world is actually not even difficult to +define and implement: choosing a different data model for implementing +an operating system, for example, is completely feasible, +as shown e.g. by XXX. + +

+In our work, we focus on the ZigZag structure, which is one alternative +to the directories-files-text model. +In ZigZag, data is contained in cells which are bidirectionally +interconnected in a flexible, multidimensional structure. + + +

Parsing, symbol tables and integrated development environments

+ +

+We will probably need to use that term in every +paper we write ;) ;) + +

+Today's computer languages are, with few exceptions, expressed as text. +Even the use of the word computer language itself conveys +the expectation that computer languages, like human languages, +is expressible in a linear form. + +

+In this context, a parser and symbol tables are +an essential ingredient of a compiler; and that a language +definition requires defining a Backus-Naur form syntax and +namespaces for various identifiers. + +

+Likewise, it is often found that using an editor which understands +the language syntax and is able to suggest completions to e.g. method +names is almost irreplaceable. Especially important is the ability +to jump from a use of a symbol to the point in the code where +the symbol was defined. + +

+However, human language is expressible as one-dimensional +because of a simple constraint in speech: time. When a language +is spoken, a sequential form is a requirement. + +

+Computer languages try to mimic human languages in several ways. + +

Syntaxless languages

+ +

+A syntaxless language is based on there being a richer underlying +structure than a simple text stream. + + +

+ +:} + + + diff --git a/Documentation/UsersGuide/Makefile b/Documentation/UsersGuide/Makefile new file mode 100644 index 0000000..89484b3 --- /dev/null +++ b/Documentation/UsersGuide/Makefile @@ -0,0 +1,15 @@ +# DIAGRAMS=linkorder.png beamorder.png + +all : ug.html ug-ns4.html newug.html newug-ns4.html + +ugdep = ug.wml ../keybindings.wml ../wmlinc/article.wml ../wmlinc/common.wml $(DIAGRAMS) +ug.html : $(ugdep) +ug-ns4.html: $(ugdep) + +newugdep = newug.wml ../keybindings.wml ../wmlinc/catart.wml ../wmlinc/common.wml $(DIAGRAMS) +newug.html: $(newugdep) +newug-ns4.html: $(newugdep) + +include ../lib.mk + + diff --git a/Documentation/UsersGuide/active.png b/Documentation/UsersGuide/active.png new file mode 100644 index 0000000..b0342c6 Binary files /dev/null and b/Documentation/UsersGuide/active.png differ diff --git a/Documentation/UsersGuide/addressbook.png b/Documentation/UsersGuide/addressbook.png new file mode 100644 index 0000000..6e18531 Binary files /dev/null and b/Documentation/UsersGuide/addressbook.png differ diff --git a/Documentation/UsersGuide/aftermove.png b/Documentation/UsersGuide/aftermove.png new file mode 100644 index 0000000..001fe2a Binary files /dev/null and b/Documentation/UsersGuide/aftermove.png differ diff --git a/Documentation/UsersGuide/alku.png b/Documentation/UsersGuide/alku.png new file mode 100644 index 0000000..7697896 Binary files /dev/null and b/Documentation/UsersGuide/alku.png differ diff --git a/Documentation/UsersGuide/bind1.png b/Documentation/UsersGuide/bind1.png new file mode 100644 index 0000000..3ef2ccf Binary files /dev/null and b/Documentation/UsersGuide/bind1.png differ diff --git a/Documentation/UsersGuide/bind2.png b/Documentation/UsersGuide/bind2.png new file mode 100644 index 0000000..14cf243 Binary files /dev/null and b/Documentation/UsersGuide/bind2.png differ diff --git a/Documentation/UsersGuide/boring.png b/Documentation/UsersGuide/boring.png new file mode 100644 index 0000000..00e53b3 Binary files /dev/null and b/Documentation/UsersGuide/boring.png differ diff --git a/Documentation/UsersGuide/bothwins.png b/Documentation/UsersGuide/bothwins.png new file mode 100644 index 0000000..e71ff6e Binary files /dev/null and b/Documentation/UsersGuide/bothwins.png differ diff --git a/Documentation/UsersGuide/breakkafka.png b/Documentation/UsersGuide/breakkafka.png new file mode 100644 index 0000000..e8ea943 Binary files /dev/null and b/Documentation/UsersGuide/breakkafka.png differ diff --git a/Documentation/UsersGuide/change1.png b/Documentation/UsersGuide/change1.png new file mode 100644 index 0000000..68c1f9a Binary files /dev/null and b/Documentation/UsersGuide/change1.png differ diff --git a/Documentation/UsersGuide/change2.png b/Documentation/UsersGuide/change2.png new file mode 100644 index 0000000..7682403 Binary files /dev/null and b/Documentation/UsersGuide/change2.png differ diff --git a/Documentation/UsersGuide/child1.png b/Documentation/UsersGuide/child1.png new file mode 100644 index 0000000..a81db92 Binary files /dev/null and b/Documentation/UsersGuide/child1.png differ diff --git a/Documentation/UsersGuide/child2.png b/Documentation/UsersGuide/child2.png new file mode 100644 index 0000000..9c61632 Binary files /dev/null and b/Documentation/UsersGuide/child2.png differ diff --git a/Documentation/UsersGuide/clone1.png b/Documentation/UsersGuide/clone1.png new file mode 100644 index 0000000..de95db3 Binary files /dev/null and b/Documentation/UsersGuide/clone1.png differ diff --git a/Documentation/UsersGuide/clone2.png b/Documentation/UsersGuide/clone2.png new file mode 100644 index 0000000..78e798c Binary files /dev/null and b/Documentation/UsersGuide/clone2.png differ diff --git a/Documentation/UsersGuide/connect1.png b/Documentation/UsersGuide/connect1.png new file mode 100644 index 0000000..fecd6dd Binary files /dev/null and b/Documentation/UsersGuide/connect1.png differ diff --git a/Documentation/UsersGuide/connect2.png b/Documentation/UsersGuide/connect2.png new file mode 100644 index 0000000..8180e74 Binary files /dev/null and b/Documentation/UsersGuide/connect2.png differ diff --git a/Documentation/UsersGuide/connection1.png b/Documentation/UsersGuide/connection1.png new file mode 100644 index 0000000..76ca6dc Binary files /dev/null and b/Documentation/UsersGuide/connection1.png differ diff --git a/Documentation/UsersGuide/creation.png b/Documentation/UsersGuide/creation.png new file mode 100644 index 0000000..8ef50ba Binary files /dev/null and b/Documentation/UsersGuide/creation.png differ diff --git a/Documentation/UsersGuide/dimensio.png b/Documentation/UsersGuide/dimensio.png new file mode 100644 index 0000000..5bbd409 Binary files /dev/null and b/Documentation/UsersGuide/dimensio.png differ diff --git a/Documentation/UsersGuide/edit1.png b/Documentation/UsersGuide/edit1.png new file mode 100644 index 0000000..a1b73df Binary files /dev/null and b/Documentation/UsersGuide/edit1.png differ diff --git a/Documentation/UsersGuide/edit2.png b/Documentation/UsersGuide/edit2.png new file mode 100644 index 0000000..db8ebba Binary files /dev/null and b/Documentation/UsersGuide/edit2.png differ diff --git a/Documentation/UsersGuide/edit3.png b/Documentation/UsersGuide/edit3.png new file mode 100644 index 0000000..c507cf0 Binary files /dev/null and b/Documentation/UsersGuide/edit3.png differ diff --git a/Documentation/UsersGuide/edit4.png b/Documentation/UsersGuide/edit4.png new file mode 100644 index 0000000..3b2b461 Binary files /dev/null and b/Documentation/UsersGuide/edit4.png differ diff --git a/Documentation/UsersGuide/extra.png b/Documentation/UsersGuide/extra.png new file mode 100644 index 0000000..47d6e8a Binary files /dev/null and b/Documentation/UsersGuide/extra.png differ diff --git a/Documentation/UsersGuide/f2.png b/Documentation/UsersGuide/f2.png new file mode 100644 index 0000000..906b0a8 Binary files /dev/null and b/Documentation/UsersGuide/f2.png differ diff --git a/Documentation/UsersGuide/familytree.png b/Documentation/UsersGuide/familytree.png new file mode 100644 index 0000000..9796cd7 Binary files /dev/null and b/Documentation/UsersGuide/familytree.png differ diff --git a/Documentation/UsersGuide/font.png b/Documentation/UsersGuide/font.png new file mode 100644 index 0000000..9477a0b Binary files /dev/null and b/Documentation/UsersGuide/font.png differ diff --git a/Documentation/UsersGuide/grey.png b/Documentation/UsersGuide/grey.png new file mode 100644 index 0000000..48132e1 Binary files /dev/null and b/Documentation/UsersGuide/grey.png differ diff --git a/Documentation/UsersGuide/hop1.png b/Documentation/UsersGuide/hop1.png new file mode 100644 index 0000000..a55e0bb Binary files /dev/null and b/Documentation/UsersGuide/hop1.png differ diff --git a/Documentation/UsersGuide/hop2.png b/Documentation/UsersGuide/hop2.png new file mode 100644 index 0000000..472711d Binary files /dev/null and b/Documentation/UsersGuide/hop2.png differ diff --git a/Documentation/UsersGuide/hopolympos.png b/Documentation/UsersGuide/hopolympos.png new file mode 100644 index 0000000..9e2eef1 Binary files /dev/null and b/Documentation/UsersGuide/hopolympos.png differ diff --git a/Documentation/UsersGuide/htree.png b/Documentation/UsersGuide/htree.png new file mode 100644 index 0000000..c3b85a4 Binary files /dev/null and b/Documentation/UsersGuide/htree.png differ diff --git a/Documentation/UsersGuide/kafka.png b/Documentation/UsersGuide/kafka.png new file mode 100644 index 0000000..0911f60 Binary files /dev/null and b/Documentation/UsersGuide/kafka.png differ diff --git a/Documentation/UsersGuide/klooni.png b/Documentation/UsersGuide/klooni.png new file mode 100644 index 0000000..e55ed9b Binary files /dev/null and b/Documentation/UsersGuide/klooni.png differ diff --git a/Documentation/UsersGuide/make1.png b/Documentation/UsersGuide/make1.png new file mode 100644 index 0000000..b8c913c Binary files /dev/null and b/Documentation/UsersGuide/make1.png differ diff --git a/Documentation/UsersGuide/make2.png b/Documentation/UsersGuide/make2.png new file mode 100644 index 0000000..11f0bfa Binary files /dev/null and b/Documentation/UsersGuide/make2.png differ diff --git a/Documentation/UsersGuide/make3.png b/Documentation/UsersGuide/make3.png new file mode 100644 index 0000000..345192b Binary files /dev/null and b/Documentation/UsersGuide/make3.png differ diff --git a/Documentation/UsersGuide/make4.png b/Documentation/UsersGuide/make4.png new file mode 100644 index 0000000..835e793 Binary files /dev/null and b/Documentation/UsersGuide/make4.png differ diff --git a/Documentation/UsersGuide/make5.png b/Documentation/UsersGuide/make5.png new file mode 100644 index 0000000..b872cc3 Binary files /dev/null and b/Documentation/UsersGuide/make5.png differ diff --git a/Documentation/UsersGuide/make6.png b/Documentation/UsersGuide/make6.png new file mode 100644 index 0000000..f60d9d1 Binary files /dev/null and b/Documentation/UsersGuide/make6.png differ diff --git a/Documentation/UsersGuide/margins.png b/Documentation/UsersGuide/margins.png new file mode 100644 index 0000000..f17c968 Binary files /dev/null and b/Documentation/UsersGuide/margins.png differ diff --git a/Documentation/UsersGuide/mark1.png b/Documentation/UsersGuide/mark1.png new file mode 100644 index 0000000..8525076 Binary files /dev/null and b/Documentation/UsersGuide/mark1.png differ diff --git a/Documentation/UsersGuide/mark2.png b/Documentation/UsersGuide/mark2.png new file mode 100644 index 0000000..d4368a8 Binary files /dev/null and b/Documentation/UsersGuide/mark2.png differ diff --git a/Documentation/UsersGuide/markconnect.png b/Documentation/UsersGuide/markconnect.png new file mode 100644 index 0000000..c5bec25 Binary files /dev/null and b/Documentation/UsersGuide/markconnect.png differ diff --git a/Documentation/UsersGuide/mutsi.png b/Documentation/UsersGuide/mutsi.png new file mode 100644 index 0000000..a12c1cd Binary files /dev/null and b/Documentation/UsersGuide/mutsi.png differ diff --git a/Documentation/UsersGuide/mutsiosoite.png b/Documentation/UsersGuide/mutsiosoite.png new file mode 100644 index 0000000..ece22ef Binary files /dev/null and b/Documentation/UsersGuide/mutsiosoite.png differ diff --git a/Documentation/UsersGuide/myspeech.png b/Documentation/UsersGuide/myspeech.png new file mode 100644 index 0000000..9391520 Binary files /dev/null and b/Documentation/UsersGuide/myspeech.png differ diff --git a/Documentation/UsersGuide/myspeech1.png b/Documentation/UsersGuide/myspeech1.png new file mode 100644 index 0000000..a5e124a Binary files /dev/null and b/Documentation/UsersGuide/myspeech1.png differ diff --git a/Documentation/UsersGuide/myspeech2.png b/Documentation/UsersGuide/myspeech2.png new file mode 100644 index 0000000..f7eda8c Binary files /dev/null and b/Documentation/UsersGuide/myspeech2.png differ diff --git a/Documentation/UsersGuide/myspeech3.png b/Documentation/UsersGuide/myspeech3.png new file mode 100644 index 0000000..bd38af8 Binary files /dev/null and b/Documentation/UsersGuide/myspeech3.png differ diff --git a/Documentation/UsersGuide/newcells.png b/Documentation/UsersGuide/newcells.png new file mode 100644 index 0000000..e0fa922 Binary files /dev/null and b/Documentation/UsersGuide/newcells.png differ diff --git a/Documentation/UsersGuide/newstory.png b/Documentation/UsersGuide/newstory.png new file mode 100644 index 0000000..e966cab Binary files /dev/null and b/Documentation/UsersGuide/newstory.png differ diff --git a/Documentation/UsersGuide/newstory2.png b/Documentation/UsersGuide/newstory2.png new file mode 100644 index 0000000..4bd7dbe Binary files /dev/null and b/Documentation/UsersGuide/newstory2.png differ diff --git a/Documentation/UsersGuide/newstory3.png b/Documentation/UsersGuide/newstory3.png new file mode 100644 index 0000000..7dd254e Binary files /dev/null and b/Documentation/UsersGuide/newstory3.png differ diff --git a/Documentation/UsersGuide/newug.wml b/Documentation/UsersGuide/newug.wml new file mode 100644 index 0000000..5f74562 --- /dev/null +++ b/Documentation/UsersGuide/newug.wml @@ -0,0 +1,1222 @@ + + + +#include "catart.wml" + + +Instructions for the Use of GZigZag +
$Id: newug.wml,v 1.6 2001/02/07 10:29:44 cat Exp $
+ + Katariina Ervasti
+ cat@gzigzag.org +
+
+ + +

This is the third version of Instructions for the Use of +GZigZag, written by Katariina Ervasti, who is working with this document whenever +she has time. (Documentation is only ONE of my tasks.) +

+Last update on 7th of February, 2001. +

+ +{#MYTOC#} + +About this document + +

+The purpose of this document is to explain how to use the current +version of GZigZag (0.1.4). + +

If this is the first document you read about GZigZag, please read +GZigZag - A Platform +for Cybertext Experiments before continuing. The popularized +article deals with the reasons for developing GZigZag as well as the +main concepts and the advantages of the system. We assume that the +reader of this document has read the article, especially the definitions of the main +concepts, which will not be repeated here. + +

+We are interested in describing the use of GZigZag as clearly as +possible. Any comments on the content of this document are welcome +and can be sent to cat@gzigzag.org. + +

+And, since GZigZag is constantly being developed, also this document +is always under construction. We are doing our best to inform users +of the latest features of GZigZag! + +

+About using GZigZag + +

At this stage of the development GZigZag can be used as an +information manager. Using GZigZag as an information manager +does not require any programming skills. Yet, if you want to build a +specific view for a certain GZigZag structure, you need to know some +Java. + +

+The following structures (among others) have been made with GZigZag:

+

    +
  • a family tree +
  • a timeline of the most important happenings of the history. +
  • a personal information manager, combining e.g. contact information +of people with e-mail messages received from them +
  • a presentation about GZigZag +
  • an "organizational finder", which is a combination +of a telephone book of an organization, an organizational chart and +lists of employees involved in certain projects +
+ +

+Naturally, we have build these structures just to test the +functionality of the current version of GZigZag. In the future +GZigZag will be a foundation for - as Ted Nelson expresses it - +"a high-power personal and media system, with editing and presentation +systems that expand the state of art". +

+ +If you're interested in visualizations of the future system, see Nelson's page dealing with +Floating World. +

+Downloading GZigZag + +

+You can download the recommended version of GZigZag for users on the +Downloading GZigZag-page. +The page also includes instructions for +downloading and the commands needed for starting GZigZag. + +

+Building a GZigZag structure +

+In GZigZag - A +Platform for Cybertext Experiments we use a combination +of an address book and a family tree to make the main concepts of +GZigZag more clear. This section of the guide focuses on explaining +how the example was made.

+

+Designing a GZigZag structure +

+We started making the structure by drawing our ideas on the paper. +

+We planned the structure of the address book to be +simple: it is a list of names and addresses. The names are listed +along a dimension in alphabetical order. We decided to use d.2 +for that purpose. The addresses are connected to the names along +another dimension, and we chose d.1 for that. (Figure 1) +

+We didn't have to design the structure of the family tree from +the beginning, since we decided to use Ted Nelson's design made +for his Holm Family Demo. In this design siblings are connected +along d.children, and married couples along d.marriage. +An extra cell ("+") is used on d.marriage to make the structure symmetric, +and the list of children from the marriage on d.children starts +from that cell. (Figure 2) +

+Thus, designing a GZigZag structure is basically just thinking +about the ways cells can be connected along dimensions. +The most important thing to keep in mind is that on each dimension each cell +has two ends, a negative end and a positive end, and on each dimension +only one cell can be connected to one end. This means that +on each dimension a cell can have at most two neighbours: a predecessor, +which is connected on the negative end of the cell, and a successor, +which is connected on the positive end of the cell. +

+If you want to use the same cell on the same dimension many times, +you can use a mechanism called cloning (which is explained in + ). +

+Functions needed for building a GZigZag structure +

+Moving in GZigZag +

+Before you can start building a structure, you need some information +of how to move in the GZigZag space. +

+When you first start GZigZag, you see two windows showing the +GZigZag structure. Figure 3 represents a +window showing the GZigZag structure after starting. As it can be +seen, in GZigZag cells are represented by rectangles and neighbours +along a dimension by a line. +

+The number of dimensions in GZigZag is infinite, but only three dimensions +(x, y, z) can be shown on the screen at the same time. The dimensions used +can be seen in the top left corners of both windows. If you look at these +corners, you'll see that the default dimensions are d.1 (on the X axis), +d.2 (on the Y axis) and d.3 (on the Z axis). +

+Now, there are two cursors you can use to move in the GZigZag space, +the left (green) and the right (blue) cursor. If you look at the uppermost cell, +which is called the homecell, you can see that the both cursors +are currently on the same cell. +

+The blue cursor defines the center of the right window. The speciality +of this cursor is that in addition to navigation, it can be used for manipulating data, +for example typing text in a cell . You can use the following keys to move the blue cursor: +

+ +i +up/to the negative direction along the dimension on the Y axis + +, +down/to the positive direction along the dimension on the Y axis + +j +left/to the negative direction along along the dimension on the X axis + +l +right/to the positive direction along the dimension on the X axis + +Shift-k +up/to the negative direction along the dimension on the Z axis + +k +down/to the positive direction along the dimension on the Z axis + + +

+As you press the buttons, you can see the cursor moving in both windows +and the center of the right window changing. +

+The green cursor defines the center of the left window. The speciality +of this cursor is that in addition to navigation, it can be used for excuting commands, +for example starting an applitude.. +You can use the following keys to move the green cursor: +

+ +e +up/to the negative direction along the dimension on the Y axis + +c +down/to the positive direction along the dimension on the Y axis + +s +left/to the negative direction along along the dimension on the X axis + +f +right/to the positive direction along the dimension on the X axis + +Shift-d +up/to the negative direction along the dimension on the Z axis + +d +down/to the positive direction along the dimension on the Z axis + +

+As you press the buttons, you can see the cursor moving in both windows +and the center of the left window changing. +

+If you look at the keyboard, you can see that the keys are arranged +in diamond patterns on the keyboard, one for the left and another for +the right hand use. +

+You can also use the arrow keys to move the blue cursor and both +green and the blue cursor can be moved by pointing a cell with +the cursor of the mouse and clicking at the button of the mouse. If +you use the mouse to point & click at a cell on the right window, +the blue cursor will move. If you use the mouse to point & click at +a cell on the left window, the green cursor will move. +

+If you get lost, press ESC to return to the home cell. +

+Creating new cells and entering text +

+We started building the combination of the address book and the +family tree by building an address book. First, we created new cells +for the names of the relatives along d.2. +

+The key used for creating a new cell is +n. After pressing the n key, you have +to press one of the direction keys discussed above to +indicate to which direction the new cell is created. For example, to +create a new cell up from the blue cursor's location, press +n and i. To create a new cell up from the green +cursor's location, press n and e. +

+The new cells for the names of the relatives (Figure 4) +where created by pressing n and i five times, when the +blue cursor was on the home cell. +

+To type a name (or any other text) in a cell, you need the +blue cursor and the tab key. For example, to type the name of +your mother to the cell above the home cell, move the blue cursor on +the cell, press the tab key, type the name of your mother and then +press the tab key again. (The result of this operation can be seen +in Figure5.) +

+ +After typing the names of the relatives we wanted to add the +addresses to our address book. To add the addresses we created +new cells which were connected to the cells containing the names +along d.1. For example, to create a new cell for the address of your +mother, go to the cell containing the name of your mother and +press n and l. Figure 6 +represents the example structure after adding a cell for the address +of the mother. + +

+The addresses are added to the cells in the manner described +above. To add the address of your mother, move the blue cursor +on the cell ment for it, press the tab key, type the address +and then press the tab key again. Figure 7 +shows the example structure after typing the address of the mother. +

+If you want to make typing text easier, you can use the Edit- +window. To get the edit window on the screen, move the green +cursor on the cell, which contains the text EDITVIEW and press +enter. To find the EDITVIEW cell go to the homecell (press ESC) +and move to the positive direction from the home cell on d.2 until you get +to the cell containing the text 'Actions'. When you move to the +one step to the positive direction on d.1 from this cell you +end up in the Actions list, to which the 'EDITVIEW'-cell is connected. +

+Cloning +

+If you want to use a cell on the same dimension +many times, a mechanism called cloning is needed. +

+If you want to clone a cell, on which the green cursor is, press +Shift-t and one of buttons indicating a +direction (in which you want to place the clone). If you want +to clone a cell, on which the blue cursor is, press 't' and one of +the buttons indicating a direction (in which you want to place the +clone). +

+For example, if your mother and father have the same address, you +might want to make a clone of the address cell. You could do this for +example by moving the blue cursor on the address cell and the green +cursor on the cell containing the name of your father. After doing +this, you would press t and f. The result of +these functions can be seen in Figure +8. Notice that the colour of a cloned cell is light yellow and the +colour of a clone is dark yellow. +

+The advantage of cloning is that it makes updating easy. When +you update one of the cells containing the same information, +the change can be seen everywhere. For example, if you +change the text on either the cloned cell or the clone containing +the address of your parents, the changes can be seen in both +cells. +

+Creating new dimensions +

+After finishing the address book, we started building the +family tree. +

+Now, two new dimensions are needed for the family tree: +d.children for connecting the siblings and d.marriage for +connecting the married couples. (When you're making new +dimensions any name will do, but we are used to naming +the dimensions d.something.) +

+To add new dimensions, move to the positive direction from the home cell +along d.2 until you get to the cell containing the text 'DimLists'. When +you move one step to the positive direction along d.1 from this cell you +end up in the dimension list. The dimension list contains a cell for each +dimension, which are connected to each other in a cyclical manner. +The dimesions that are currently used (d.1, d.2 and d.3) are pink. +

+Making a new dimension simply means adding a new cell on a +dimension list and typing the name of the dimension in the +cell. Figure 9 shows the +dimension list after adding d.marriage and d.children. +

+Rotating the dimensions +

+Before we can continue our study of making the family tree, +rotating the dimensions has to be explained. The number of dimensions +in GZigZag is infinite, but only three dimensions can be shown on +the screen at the same time. This is why knowing how to rotate +dimensions is necessary. +

+The following keys are used for rotating the dimensions in the right +window: + +x +changes the dimension on the X axis + +y +changes the dimension on the Y axis + +z +changes the dimension on the Z axis +

+ +The following keys are used for rotating the dimensions in the left +window:

+ +Shift-x +changes the dimension on the X axis + +Shift-y +changes the dimension on the Y axis + +Shift-z +changes the dimension on the Z axis + +

+For example, to rotate the d.marriage dimension to the X axis of the +right window, press x until you can see the text d.marriage in the top +left corner of the window. Figure 10 shows +the right window after rotating d.marriage to the X axis. +

+Connecting existing cells along new dimensions +

+Marking and unmarking a cell +

+ +Before explaining how the cells containing the names of the relatives +were connected along d.marriage and d.children, you have to understand +how to choose the cells you want to connect. In +the GZigZag language this is called marking. + +

+ +To mark a cell, move the blue cursor on the cell you want to +mark and press m. The cell that you have marked is +now coloured red. Figure 11 shows +the example structure after marking Hippy Chick. + +

+ +Many cells can be marked at the same time. To mark another cell, move +the blue cursor on the cell you want to mark and press m. +You can now see two red cells. Figure +12 shows the example structure after marking Hippy Chick and +Happy Man. + +

+ +To unmark a cell, move the blue cursor on the cell you want to +unmark and press m. + +

+Connecting cells +

+If you want to connect two cells to each other, mark one +cell and point the other one with the blue cursor. (If you mark both +cells, they will be connected into a loop.) +

+If you want to connect three cells, mark two cells and point +the third one with the blue cursor. (If you mark all cells, they will be +connected into a loop.) +

+ +After choosing the cells (in the manner explained +above), all you need to know is the key binding for connecting the +cells. So, to connected the chosen cells, press the +- and then a key indicating a direction of the +connection. + +

+ +Connecting cells requires a lot of practice. If you make a mistake, +you can use the u-key ('undo') to delete the latest connection. + +

+ +Next we explain how the cells of the family members used in +the address book can be connected to the family tree structure. +The same result can be achieved in various ways. The method +of connecting cells explained here is just an example. + +

+ +First, we rotated d.marriage to the X axis to connect the married +couple. Then, Happy Man was marked and the blue cursor was moved on +Hippy Chick. (Figure 13.) + +

The key needed for connecting the cells is -. After +pressing the --key one of the direction keys has to be +pressed to indicate the direction in which the cells are connected. In +our example the connection, which can be seen in Figure 14, was made by pressing +- and j. + +

+ +If - and l had been pressed the result would +have been the connection seen in Figure +15. Since in the family tree design the 'dad' cell (Happy Man) +is on the left and the 'mum' cell (Hippy Chick) on the right, this +is not the connection we want. + +

+ +After this we added an extra cell (+) between Happy Man and +Hippy Chick to indicate that they are married. ( Figure 16) + +

+ +Then we wanted to connect the extra cell to the children of the couple +along d.children To do this, we rotated d.children to the Z axis. (We +kept d.marriage on the X axis and d.2 on the Y axis.) We marked Lost +Boy, Athena Dean and Big Brother and moved the blue cursor to ++. ( Figure 17) + +

+ +We pressed - and k which indicates that the cells +should be connected to the positive direction along d.children, +which was on the Z axis. + +

+ +Finally, to view the family tree we rotated d.marriage to the X axis, +d.children to the Y axis and d.3 to the Z axis. The final result can +be seen in Figure 18. + +

+ +One of the advantages of having two windows is that the left and +the right window can show different dimensions of the same GZigZag +space. The same cells used in the family tree can be viewed in the +address book in another window. + +

+Changing views +

+There are several different visualizations (views) of the +GZigZag structure. The name of the active view +can be seen in the top right corner of a window. All the +figures used in this guide so far show the address book and the +family tree using the vanishing view. +

+You can change the view of the right window by pressing the +v and the view of the left window by pressing +shift-v. Figure 19 shows +the family tree in the row view. +

+As you keep pressing v (or shift-view), you notice that +the current version of GZigZag shows four views: the vanishing +view, the strecth vanishing view, the row view and the column +view. +

+Yet, these are not the only views available. The views that are used +when the user presses v or shift-v are listed in +the Views list, which can be found by moving to the positive direction + from the home cell along d.2 until getting to the cell containing the + text 'Views'. If you move one step to the positive direction on d.1 + from this cell, you are in the Views list. +

+ To see a listing of all views, go to the cell containing + the text 'AllViews' (that is connected to the 'Views'-cell on d.2). +The list of all views is connected to this cell along d.1. +

+If you want to use one of the views listed in the 'AllViews' +list, clone the cell of the view you want to use to the Views +list. Figure20 shows the AllViews list after +cloning HTree. The HTree view can now be used by pressing +v (or SHIFT-v). +

+Most of the views of the 'AllViews' list are designed for specific +purposes. Section deals with views in more detail. +

+Making changes to the structure +

+When you are making a structure of your own, you may sometimes make +mistakes or want to change the structure afterwards. The current +version of GZigZag offers some possibilities for this. +

+Undo +

+Undo (=cancelling the last move(s)) was already briefly mentioned before. The +u-key, for example, removes the last +move of the cursor, the last connection made, the last hop, +alpha-shear or cell exchange. (The last three are explained later in +this document.) It also brings back a deleted cell. +

+Disconnecting cells +

+If you notice that you have connected the cells in a wrong way and are +no longer able to use undo to break the connection, you can +use use the b-key and one of the direction keys +(indicating the direction of the connection you want to remove). +

+For example, when making the family tree structure you may notice that +you have connected your cousin along d.children as if he was your +brother. In Figure21 Franz Kafka +is the cousin in the wrong place. Franz Kafka can be removed by +pressing b and , (when the blue cursor is on +Big Brother). The result of this can be seen in Figure 22. +

+If a cell is used on many dimensions, the other connections +still remain after breaking a connection on one dimension. In +the example given above the cell of the cousin maintains its +place in the address book. +

+Deleting a cell +

+If you have created a useless cell, you can delete it. To do this, +move the blue cursor on the useless cell and press delete . + +

+Don't delete a cell on which the green cursor is! If you +do that, you'll get a 'RASTER ERROR'. + +

+Hopping +

+When building a GZigZag structure you notice quite often that you +have a useful cell, but it is in the wrong place in the structure. +Hopping is an operation that - as the name indicates - makes a cell +hop over one of its neighbours along a chosen dimension. +

+For example, if you have arranged the names in your address book +in alphabetical order and notice that one of the names is in +the wrong place, you can move it to the right place by using the +hopping function. +

+The key used for hopping is h after which you have +to press one of the direction keys to indicate the direction +of the hop. In Figure 23 Lost Boy is in the +wrong place. Lost Boy can be moved to the right place by moving the +blue (or) the green cursor on Lost Boy and then pressing +h and a direction key. We moved Lost Boy by moving the +green cursor on it and pressing the h and c five +times. The result of this is shown in Figure24. +

+Alpha-shear +

+Another operation that can be useful when you want to move a cell in +the GZigZag structure is the alpha-shear. The hop makes a cell hop +along a dimension, but the alpha-shear moves the connection. +The alpha-shear is used by typing a and two +directions: first the direction of the connection that is moved and +then the direction into which the connection is moved. +

+The difference between the hop function and the alpha-shear function +is easier to understand with an example. So, for example, when +making the address book you notice that you have connected the address +of your sister to the address of your brother. In Figure 25 +Olympos is the address of Athena Dean, not the address of Big +Brother. +

+You can't correct this mistake by hopping because the hop function +only hops the address to the other side of Big Brother on d.1. +(Figure 26.) So, you can only correct the +mistake by using the alpha-share. We pressed a, +j and i to move Olympos to the right +place. (Figure 27 represents the result of +this.) +

+Cell exchange +

+Cell exchange is an operation that changes the location of two cells +in the GZigZag structure. First, two cells are selected using +the blue and the green cursor. After this % is +pressed. +

+For example, the family tree structure is designed so that the cells +of the children are connected to + cell along d.children from +the oldest to the youngest. If you had connected the cells so that the +oldest would be the last cell of the list and the youngest would be +the cell just below +, you could change the cells to the +right places usig the cell exchange. +

+Figure 28 shows Big Brother, who is +naturally the oldest of the children, and Lost Boy, the youngest of +the children, in the wrong places. To correct the mistake, the blue cursor +was moved on Big Brother and the green cursor was moved on Lost +Boy and then % was pressed. Figure29 shows that the brothers are now in the +right places in the family tree. +

+Navigational tricks +

+ +The basics of navigation in the GZigZag space were introduced in +Section . When you are familiar with the +basics, these tricks might help you to work more effectively with your +GZigZag. +

+Returning to the home cell +

+Currently there are two keys that help you to return to the home cell, if +you feel completely lost: +

+

    +
  1. Pressing HOME returns the blue cursor to the home cell. +
  2. Pressing ESC returns the blue and the green cursor to the +home cell +
+ +Jumping to a cell using the cell ID +

+Cells of GZigZag have an ID, the purpose of which is to help +to recognize the cells. In the current version of GZigZag IDs are +numbers and can be used to make navigation easier. +

+The ID of the cell, on which the cursor is, can be seen in the +bottom left corner of a window. The right window shows the ID +of a cell on which the blue cursor is. The left window shows the +ID of a cell on which the green cursor is. +

+The IDs can be used to help navigation in the following way: +

+

    +
  1. Type the ID of the cell, e.g. '554'. (Yes, if +you want to use this, you have to learn the IDs of the cells you +consider most important by heart.) If you make a mistake, you can use +BACKSPACE to correct the mistake.
+ +Choose one of the following depending on which cursor you want to +use +
    +
  1. If you want the blue cursor to move to the cell the ID of +which you have just typed, press g. +
  2. If you want the green cursor to move to the cell the ID of +which you have just typed, press shift-G. +
+ + +Jumping to a cell on which another cursor is +

+If you notice that you have lost one of the cursors, this +function might be useful. It brings the lost cursor to the +cell on which another cursor is. +

+To make the blue cursor jump to the cell on which the green +cursor is, press >. +

+To make the green cursor jump to the cell on which +the blue cursor is, press <. +

+Jumping to the original cell from a clone +

+If you are on a cloned cell (the colour of which is dark yellow) and +want to find out were the original cell (from which the clone was made) +is, choose one of the following depending on which cursor you want to move: +

+

    +
  1. If the blue cursor is on the clone press +o to get to the original.
  2. If the +green cursor is on the clone, press +SHIFT-o to get to the original.

    +

+ +Jumping to the end of a rank +

+A rank is one of the terms of the GZigZag language. It simply +means a set of cells connected to each other along a dimension. +For example, Figure 30 shows an incomplete +address book, in which Happy Man and Wall Street form a rank +along d.1. Also Hippy Chick and Wall Street form a rank along +d.1 as well as the cells connected along d.2 from Lost Boy to Bindings +(which cannot be seen on the figure). +

+To get to the end of a rank, press END and one of the keys indicating +a direction. For example, if you would like to move the green cursor +from Happy Man to Lost Boy (see Figure 30), +you would have to press END and e.

+ +Changing the places of the cursors +

+Sometimes you might want to change the places of the cursors.

+ +If you have an American keyboard, press ~ for doing this.

+ +In case you are not using an American keyboard pressing ~ +does not work. If you want to use the function, change the +keydinging. (See for changing the keybinding.)

+ +Curseling + +Under construction. + + Modifying the user interface of GZigZag +

+ The current version of GZigZag offers some possibilities for changing + the user interface. You can change the key bindings and the way cells + (and their contents) look like. The looks of the views can also be + modified. +

+Changing the keybindings +

+In addition to modifying the bindings of the basic functions, you can modify +the bindings of the Edit window and the bindings used for curseling. +

+To modify the bindings, go to the 'Bindings' list. You find the list by +moving to the positive direction on d.2 from the homecell until you get +to Bindings. This cell is connected to Normal mode, +Text edit mode and Cursel mode on d.1, which are +connected to cells enabling the change on d.2. +

+Say you want to change the key used for changing the places of the +cursors. Instead of ~ you want to use F10. +You move on the Normal mode list on d.2 until you find a cell containing '~'. +(Figure31.) Just replace ~ with F10. (Figure32.) +Pressing F10 should now change the places of the cursors. +

+ Changing the looks of cells and their contents (Cell views) +

+A cell view determines what cells and their contents look like. +

+By using a cell view you can affect +

    +
  • the font type and size +
  • the way fonts are displayed +
  • the background colour of the cells +
  • the width of the cells +
  • margins of the cells +
+

+As you have learned earlier, you can change a view by pressing a +certain key. The same principle works with the cell views. A cell +view of the right window can be changed by pressing F2 +and the cell view of the left window can be changed by pressing +SHIFT-F2. +

+The current version of GZigZag does not show the name of +the active cell view on the window the same way the name of the active +view is shown. The cell view that you get after starting an empty +space in your GZigZag is shown in Figure32. +After pressing F2 once, you get a cell view that can be seen in +Figure33. +

+Naturally, you can modify cell views and create a cell views of +your own, e.g. a cell view for a bad rainy day with boring grey background colour +and small font size (Figure34) and a cell view for a wonderful lovely day with +green background, big font size and huge margins (Figure35). +

+Modifying a cell view +

+Getting to know the 'Cell Views' list +

+Before you can start modifying a cell view, you have to find the +'CellViews' list. +

+You can find the list by moving to the positive direction on d.2 from +the homecell until you get to the cell containing the text "CellViews". +After this, move one step to the positive direction on d.1. You should +now be on the 'CellViews' list, which consists of cells containg the names +of the cell views. +

+If you move on the list, you notice that the current version of GZigZag +contains five standard views: "Standard Flob Factory" (which is used when +you start GZigZag, see Figure32), "Non-enlarging" +(see Figure33), "Black background", "Different font" and +"SplitCellFlobs". These standard cell views just demonstrate the different possibilities +and can be easily changed. +

+(If you take a closer look at the list, you notice that some of the cells +are coloured orange. The orange colour tells that the coloured views +are currently used in the two windows. Since the current version of GZigZag +does not show the name of the active cell view in the windows, this is the +only way to find out what is the name of the cell view used.) +

+Changing "Standard Flob Factory" to "My Grey Winter Day Standard Factory" +

+Say, you want to modify the "Standard Flob Factory". Firstly, you want to +change the name of the view to "My Grey Winter Day Standard Factory" ;-). +Then, you want to change the background colour of the cells to grey, +the font type to 'Serif' and the size of the font to '8'. +

+Changing the name +

+Changing the name of a cell view is quite easy. Just go to the +cell containing the text "Standard Flob Factory" and change the text +to "My Grey Winter Day Standard Factory". (If you don't remember +how to edit text in a cell, see ) +

+Changing the background colour +

+The state of art of "My Grey Winter Day Standard Factory" after the change of +the name can be seen in Figure36. +

+In Figure36 the blue cursor is on a cell containing the text "rcfact1", which +is an identifier cell of the programme. Every cell on the 'CellViews' list is +connected to an identifier cell like this on d.1. A user should not try +to modify this cell. +

+Figure36 also shows that the cell following "rcfact1" on d.1 is connected to a +cell including the text "bg" on d.2. The "bg" cell, then, is connected to a +cell containing the text "0xffffff" on d.1. +

+The roles of these cell are as follows: +

    +
  • +The cell containing the text "bg" (for 'background colour) holds the name of the +thing you can change (which is usually called a 'parameter') +
  • +The cell containing the text "0xffffff" includes the value of the +parameter, which in this case is the value of the background colour. If you are familiar +with the hexadecimal representation of colours used e.g. in HTML, changing the background +colour should be easy. Yet, in GZigZag '#' is replaced by '0x'.
+

+So, to change the background colour from white to grey, pick a shade +of grey from a RGB Hex Colour Chart +and replace "fffff" with an approriate value. +

+For example, if you replace "ffffff" with "888888", the result can be seen in +Figure37. +

+Changing the font type and size +

+Now you would like to change the font type and size of "My Grey Winter Day Standard +Factory", but there is a problem. If you look at Figure37, there are no cells for placing the +values of font type and size . The problem can be easily solved: just create new cells for the +parameter and values. Figure39 shows our example after adding the cells + for the font parameter and the values of the type and the size. +

+The next thing you have to do in order to change the font type and size is to type in the +values and the parameter. In the current version of GZigZag, you have to start by +typing the values . (Yes, it is rather complicated, but if you type the parameter first, +you will get an error. This will be fixed in the future.) So, type "8" (or any other value for +the font size) in the tailcell of the newly created rank, "serif " (or any other value for the font type) +in the middle cell and the text "font" in the headcell of the rank. The example after these +changes can be seen in Figure40. +

+Other possible modifications +

+The background colour and the font type and size are not the only modifications you can +make. This section introduces other possible modifications. +

+If there are no cells needed for making certain modifications, you have to create the +cells (in the manner introduced in ). +

+Changing the margins of the cells +

+Margins add invisible space inside the border of the cells, which pushes the cell's contents away +from the border on all four sides. +

+The following cells (created respectively along d.1) are needed for modifying margins: +

  • A cell for "margins"-parameter +
  • A cell for the value of the top and bottom margins (measured in pixels) +
  • A cell for the value of the left and right margins (measured in pixels)
+

+Figure41 shows "My Grey Winter Day Standard Factory" after +adding the cells for the "margins" parameter and the values. +

+Changing the width of the cells +

+You can change the width of the cells using the "widthstr" parameter. +(As you have probably noticed, the StrechVanishing is the only view +that specifies the width of the cells according to the lenght of the text +in each cell. In other views, the cells have the same width.) +

+The following cells (created respectively along d.1) are needed for modifying +the width of the cells: +

  • A cell for the "widthstr"-parameter +
  • A cell for the value of the width. (This is not a numerical value. The more text you +enter, the broader your cells.)
+

+Figure42 shows "My Grey Winter Day Standard Factory" after adding the cells +for the "widthstr" parameter and the values. +

+Changing the way fonts are displayed +

+You can affect the way the fonts are displayed on the screen by +using the "enlargefont" parameter. +

+If the "enlargefont" parameter is "true", GZigZag can use bigger +font size than specified in the font parameter to highlight the center cell +in certain views. Setting "enlargefont" to false means that the specified +font size is used everywhere. +

+The following cells (created respectively along d.1) are needed when using these parameters: +

  • A cell for the "enlargefont" parameter +
  • A cell for the value of the parameter. (The value is either "true" or "false".)
+

+Making a cell view of your own +

+You can also - instead of modifying an existing cell view - make a completely +new cell view. +

+To do this, first create a new cell on the 'CellViews'-list and type the name of +the cell view in it. (Figure43 shows a new cell (named after a song of R.E.M) +in the 'CellViews' list.) Then continue by creating an identifier cell containing +the text "rcfact1" and an empty cell, respectively, to the positive direction +along d.1. (Figure44.) After this you can start creating the cells for +the parametres on d.2. (Figure45) +

+ Changing the looks of views + + Under construction. + +More about views +

+This section introduces some of the views listed in the 'AllViews'-list. +As it was mentioned in , you have to clone the cells of these +views from the 'AllViews'-list to the 'Views'-list in order to +use them. +

+Views for hierachical structures +

+VTree, VTree with lines, HTree and HTree with lines are views +designed for showing tree structures and other hierarchies. +VTree is an abbreviation for 'vertical tree', HTree for 'horizontal +tree'. VTree shows the tree vertically, HTree horizontally. +

+The difference between the VTree and VTree with lines is -as +the name indicates - that VTree shows lines between the element +of the hierarchy. Naturally, the same applies to the difference +between HTree and HTree with lines. +

+VTree and VTree with lines +

+Say, you would like to present the organizational chart of the +Finnish National Road Administarion +using VTree with lines. +

+(The instructions given here also apply to VTree. The reason for using +VTree with lines in this example is that the writer of the instructions just +happens to like VTree with lines more.) +

+First, you create two new dimensions. You could call the dimensions +for example d.head1 and d.body1. After doing this rotate d.head1 to the +X axis and d.body1 to the Y axis. Then, change the view to +VTree with lines. Figure45 shows a GZigZag +window after these operations. +

+The board is the highest organizational unit of the hieararchy, so type +'Board' on the cell. Below the board is the director general. Create a +new cell for the director general by pressing 'n' and ',' (when the +right cursor in on that cell) and type 'Director General' on the cell. +Below the director are two units: the central administration and +the headquarters. Create a cell for the the central administration first +by pressing n and , (when the right cursor is on that cell). +Another subunit to the director general can be created by pressing +n and l (when the right cursor is on that cell). +Figure46 shows +the hierachy after these operations (and typing in the names of +the organizational units.) +

+Thus, when you are using the blue cursor, you can create a subcell for another +cell of the hierarchy by pressing n and ,. If a cell has more than +one subcells, you can create more subcells from the first subcell by +pressing n and l. +

+Figure47 shows one part of the organizational chart of the Finnish National +Road Administration after adding more organizational units. +

+After creating the organizational chart using the VTree with lines you +can view it with VTree (Figure48) and other views. Notice that the organizational +chart looks quite different in views which are not designed for +hiearchical structures. (Figure49 presents the organizational chart in +Vanishing View.) +

+HTree and HTree with lines +

+If you want to view a tree made using VTree, all you have to do +is to change the two dimensions to different axes. +

+Thus, to view the previous example using HTree or +HTree with lines, you'd have to change d.head1 to the Y axis +and d.body1 to the X axis. (Figure50) +

+In this view you can create a subcell for cell by pressing n and l. +If a cell has more than one subcells, you can create more subcells from +the first subcell by pressing n and , . +

+A view for presentations +

+If you are planning to give a presentation, you could try doing it with +GZigZag. There is a specific view called Presentation view designed +especially for this purpose. (If your version of GZigZag does not +have a cell for the Presentation view on the 'AllViews' list, make a +new cell on the list and type 'Presentation' in it (with out '- marks). After doing this make +a new cell to the positive direction from this cell on d.1 and type' Prez.R' +in it.) +

+Presentation view shows the structure of your presentation +as a list. Figure51 shows a presentation called +'My Speech'. The most important parts of 'My Speech' are +'Who am I?', 'Why am I?' and 'Where am I?'. +

+In the example the blue cursor is used to move in the presentation. +The regular keys ' i , l , , and j are used for moving the blue +cursor. Pressing , moves the blue cursor down on +the list (Figure52). When the blue cursor is on 'Who am I?', pressing + l takes you the 'Who am I?' part of the presentation (Figure53). +When the blue cursor is on 'To be honest, I dunno', pressing l +takes you to the 'To be honest, I dunno' part of the presentation +(Figure54). You can get back to the previous parts of the presentation +by pressing i . +

+After you have learned how to read a presentation using +Presentation view, you might want to take a look at the same +structure using another view. Figure55 shows +the presentation in Vanishing View. If you want to make a presentation of your own, you should +understand the structure of the presentation shown in Figure55. (The writer +of this guide thinks that a presentation is actually easier to make using +Vanishing View than Presentation view, which is just designed +for showing presentations.) +

+If you look at the Figure55, you notice that title of the presentation +('My Speech') is placed in one cell. The positive end of this cell +is connected to an empty cell on d.1. The most important parts +of the presentation ('Who am I?', 'Why am I?' and 'Where am I?') +are also in their own cells, which are connected to each other on +d.2. 'Who am I?', then, is a title of a another part of presentation, +which consists of 'Huh?', 'To be honest, I dunno' and 'Yes, it's difficult +indeed'. Thus, 'Who am I?' is followed by an empty cell on d.1 and +'Huh?', 'To be honest, I dunno' and 'Yes, it's difficult indeed' are connected +to the empty cell on d.2. +

+Do you understand the structure of a presentation now? ;-) To sum up, +a cell contain the title of a presentation (or a title of a certain part +of a presentation) is always connected to an empty cell to the positive +direction on d.1. The parts of the presentation (or the parts of a certain +part of the presentation ;-) are connected to the empty cell to the +positive direction on d.2. If you understand that you should be able +to make your own presentation with GZigZag. +

+Some applitudes +

+Nile +Nile is a writing tool of the future for people who love writing. +It will provide functionalities that are lacking from the currently +popular word processors. The very first version of Nile already +supports Ted Nelson's idea of transclusions. (See +Xanalogical Structure, Needed Now More than Ever: Parallel Documents, +Deep Links to Content, Deep Versioning and Deep Re-Use.) +

+We appriciate people who have time to test Nile and comment on it +e.g on the developer's mailing list, but we would like to remind that +this tool is NOT yet safe. So don't try writing anything +precious with it. +

+Starting Nile +

+Before you can start using Nile, you should make some empty cells. +You can think of these empty cells e.g. as cells that will rescue you if you +get RASTER ERROR while using Nile. :-) (See .) You can for example +make two empty cells above the home cell. Leave the blue cursor on +one of the cells. (See Figure56.) +

+After doing this, find the cell including the text 'SplitNileDemo' on +the 'Actions'-list using the green cursor. This cell can be found by going +to the homecell (press ESC unless you are already on the homecell) and +move to the positive direction from the home cell on d.2 until you get +to the cell containing the text 'Actions'. When you move one +step to the positive direction on d.1 from this cell you'll end up in the +Actions list, to which the 'SplitNileDemo'-cell is connected. +

+Once you have found the right cell, press ENTER. Now you should see +the Nile window (Figure57) appearing on the screen. +Then move the green cursor (on the GZZ window) on the other new +cell you have just created. +

+Writing a title +

+Click on the left or the right side of the Nile window depending on which +side of the window you want to start writing. Write a title for your text. +Figure58 shows the Nile window after clicking +on the right side of the window and typing 'Story'. +

+Writing text +

+Now that you have written a title, press enter to start writing the +actual text. You do not need to capitalize the first letter of the +the sentence if you remember to press the SPACEBAR two times +after ending the previous sentence. Nevertheless, if the first word of the +sentence is a name, you should capitalize the first letter. If you later want +to move the name word e.g. in the middle of the sentence, the first letter of the name +won't be a capitalized one anymore. To start a new paragraph, press +ENTER. Figure59 shows the Nile Window after typing +some text. +

+ Moving, activating and arranging text +

+An example. You would like to change the fourth sentence of the example text so that +"a student of communication studies" would appear before "a doctor of psychology". +

+To achieve this is, you would have to do the following things: +

    +
  1. Move the insertion cursor (which is currently at the end of the last paragraph) +near "a student of communication" +
  2. Activate "a student of communication studies" +
  3. Move "a student of communication studies" to the new place
+

+The first part of the task is easy to do with the mouse: just click on the place, +where you want the insertion cursor to be moved. (See Figure60, +which represents the situation after the move.) +

+You can also move the insertion cursor by using the arrow keys. Yet, before trying to move +the writing cursor with the arrow keys, you should learn to understand the +three modes of writing, which help you to move the writing cursor with the arrow +keys faster. You can also use the modes for activating parts of text (which is +currently done only by using the keyboard) in a more effective way. +

+The three modes are the character mode, the word mode and the sentence mode. +You can change the modes by pressing the TAB key. When you +first start using Nile, you are in the character mode. When you press the TAB key, +the mode is changed into the word mode. Pressing the TAB key after this, takes you +to the sentence mode. If you press the TAB once again, you're back in the +character mode. + +

If you want to activate words, use the word mode. +If you want to activate sentences, use the sentence mode. In our example case, +the use of the word mode is the best solution, because the phrase "a student of +communications studies" consists of many words. +

+Thus, to activate characters/words/sentences (depending in which mode you are), +use the arrow keys. If you want to activate more than one character/word/sentence/, +keep the SHIFT key down while activating. Figure61 +shows "a student of communication studies" activated by pressing the SHIFT key and the +left arrow key five times. After this, you can move the activated phrase by pressing +ALT and an arrow key indicating the direction to which you want the text to be moved. +In order to move "a student of communication studies" to its intented place you would have +to keep the ALT key down and press the left arrow key until you'd see the text in the right +place. (Note. In our current example you would also have to move the word "and".) +

+Making a Transclusion +

+The writer of our example story now decides to make an improved version of her +story. To start another version, she clicks on the right side of the Nile window, writes +a new, improved title for the story, a totally new first sentence and a beginning +for the second sentence. (See Figure61.) After this, the +writer of the new version decides that the first sentence of the first version is usable and +wants to make a transclusion. +

+To make a transclusion the writer activates the sentence in question, clicks with the mouse +on the place where she wants the transclusion to be made. In our example case the writer +clicks after the ','. The key binding for a transclusion, then, is +CTRL+T. Nevertheless, because of a bug, the result is not quite +what the writer wanted. As Figure62 demonstrates, +the transclusion did not end up in the right place. (The bug WILL be fixed.) So, all +the writer can do, is to move the sentence to the right place using the method introduced in +. The text after the move (and another transclusion) is seen in +Figure63. The use of colours demonstrates the parts +of the texts that are the same. (This is likely to change, because the borderlines +of the transclusions are a bit difficult to see.) +

+What to do if RASTER ERROR occurs +

+The writer of this document has been testing Nile for a while, but all the bugs are not yet fixed. +RASTER ERROR occurs frequently. Figure64 shows +the Nile Window after a bug. +

+To get back where you started from activate one of the GZZ-windows, press ESC +and move the green cursor and the blue cursor on the empty cells that you have +created for this purpose. (See ) Now you can return to the Nile window. (This +works often, NOT always.) +

+Quiting GZigZag +

+When you've had enough, press q. If you +want to continue working with the same space next time, use the same +cellscrollfile when starting. +

+List of keybindings +

+#include "../keybindings.wml" + + + + + + + + diff --git a/Documentation/UsersGuide/olympos.png b/Documentation/UsersGuide/olympos.png new file mode 100644 index 0000000..9b8067e Binary files /dev/null and b/Documentation/UsersGuide/olympos.png differ diff --git a/Documentation/UsersGuide/olympos2.png b/Documentation/UsersGuide/olympos2.png new file mode 100644 index 0000000..98bb9a1 Binary files /dev/null and b/Documentation/UsersGuide/olympos2.png differ diff --git a/Documentation/UsersGuide/osoite.png b/Documentation/UsersGuide/osoite.png new file mode 100644 index 0000000..dc80cd0 Binary files /dev/null and b/Documentation/UsersGuide/osoite.png differ diff --git a/Documentation/UsersGuide/para.png b/Documentation/UsersGuide/para.png new file mode 100644 index 0000000..8c3f567 Binary files /dev/null and b/Documentation/UsersGuide/para.png differ diff --git a/Documentation/UsersGuide/rainy.png b/Documentation/UsersGuide/rainy.png new file mode 100644 index 0000000..2feda4d Binary files /dev/null and b/Documentation/UsersGuide/rainy.png differ diff --git a/Documentation/UsersGuide/rastererror.png b/Documentation/UsersGuide/rastererror.png new file mode 100644 index 0000000..75ad82e Binary files /dev/null and b/Documentation/UsersGuide/rastererror.png differ diff --git a/Documentation/UsersGuide/rcfact1.png b/Documentation/UsersGuide/rcfact1.png new file mode 100644 index 0000000..964d0d7 Binary files /dev/null and b/Documentation/UsersGuide/rcfact1.png differ diff --git a/Documentation/UsersGuide/rightmoved.png b/Documentation/UsersGuide/rightmoved.png new file mode 100644 index 0000000..6fcaa30 Binary files /dev/null and b/Documentation/UsersGuide/rightmoved.png differ diff --git a/Documentation/UsersGuide/rotate.png b/Documentation/UsersGuide/rotate.png new file mode 100644 index 0000000..81d6a0a Binary files /dev/null and b/Documentation/UsersGuide/rotate.png differ diff --git a/Documentation/UsersGuide/row.png b/Documentation/UsersGuide/row.png new file mode 100644 index 0000000..d63ce8b Binary files /dev/null and b/Documentation/UsersGuide/row.png differ diff --git a/Documentation/UsersGuide/shiny.png b/Documentation/UsersGuide/shiny.png new file mode 100644 index 0000000..e608c3c Binary files /dev/null and b/Documentation/UsersGuide/shiny.png differ diff --git a/Documentation/UsersGuide/shinyhappy.png b/Documentation/UsersGuide/shinyhappy.png new file mode 100644 index 0000000..b9c5ee5 Binary files /dev/null and b/Documentation/UsersGuide/shinyhappy.png differ diff --git a/Documentation/UsersGuide/shinyhappy2.png b/Documentation/UsersGuide/shinyhappy2.png new file mode 100644 index 0000000..414f33d Binary files /dev/null and b/Documentation/UsersGuide/shinyhappy2.png differ diff --git a/Documentation/UsersGuide/shinyhappy3.png b/Documentation/UsersGuide/shinyhappy3.png new file mode 100644 index 0000000..082f5a1 Binary files /dev/null and b/Documentation/UsersGuide/shinyhappy3.png differ diff --git a/Documentation/UsersGuide/showingz.png b/Documentation/UsersGuide/showingz.png new file mode 100644 index 0000000..9babe8d Binary files /dev/null and b/Documentation/UsersGuide/showingz.png differ diff --git a/Documentation/UsersGuide/start.png b/Documentation/UsersGuide/start.png new file mode 100644 index 0000000..abebb27 Binary files /dev/null and b/Documentation/UsersGuide/start.png differ diff --git a/Documentation/UsersGuide/story.png b/Documentation/UsersGuide/story.png new file mode 100644 index 0000000..f5bc5b4 Binary files /dev/null and b/Documentation/UsersGuide/story.png differ diff --git a/Documentation/UsersGuide/storytext.png b/Documentation/UsersGuide/storytext.png new file mode 100644 index 0000000..bf31546 Binary files /dev/null and b/Documentation/UsersGuide/storytext.png differ diff --git a/Documentation/UsersGuide/structure1.png b/Documentation/UsersGuide/structure1.png new file mode 100644 index 0000000..5978949 Binary files /dev/null and b/Documentation/UsersGuide/structure1.png differ diff --git a/Documentation/UsersGuide/structure2.png b/Documentation/UsersGuide/structure2.png new file mode 100644 index 0000000..0a71003 Binary files /dev/null and b/Documentation/UsersGuide/structure2.png differ diff --git a/Documentation/UsersGuide/suku.png b/Documentation/UsersGuide/suku.png new file mode 100644 index 0000000..f6f8278 Binary files /dev/null and b/Documentation/UsersGuide/suku.png differ diff --git a/Documentation/UsersGuide/testi.png b/Documentation/UsersGuide/testi.png new file mode 100644 index 0000000..3053d52 Binary files /dev/null and b/Documentation/UsersGuide/testi.png differ diff --git a/Documentation/UsersGuide/ug.wml b/Documentation/UsersGuide/ug.wml new file mode 100644 index 0000000..056b6ed --- /dev/null +++ b/Documentation/UsersGuide/ug.wml @@ -0,0 +1,400 @@ + + + + + + GZigZag User's Guide +#include '../wmlinc/article.wml' + + +{: [[s/(?)\b(d\.+\w+)/\1<\/code>/g]] +

GZigZag User's Guide

+
$Id: ug.wml,v 1.6 2000/09/12 17:12:13 tjl Exp $
+ + Tuomas Lukka
+ lukka@iki.fi
+ Dept. of Mathematical Information Technology
+ University of Jyväskylä +
+
+ + + +

+This is the first attempt at an user's guide for GZigZag. It is not yet +complete and not a good tutorial but we will try to work on it. Patches +are gladly accepted! +This is work-in-progress: if there are any unclear parts, feel +free to ask me to clarify things. + + + +

Introduction

+ +

+GZigZag is a free implementation of Ted Nelson's ZigZag structure. +The ZigZag structure is a revolutionary new way of storing information +in a computer, in that it provides a clear, extensible structure +that can be orthogonally laid over existing information. + +

+This document attempts to help users to get started with GZigZag. +We start at the point where the user has gotten the program to start; +to get to that point, read the other documentation, including +the README files. +Note that this document does not attempt to cover designing sensible +structures: the "Gentle Introduction" document is for that purpose. +Here we only explain how to use the GZigZag implementation of the structure. + +

+GZigZag is a moving target: we will try our best to keep this document +up to date but sometimes it will simply be forgotten and be out +of date. Please notify +us if this happens. + +

The save model

+ +

+GZigZag currently stores data in directories, in which there is +one file per dimension and one or two extra files for the contents of the +cells. + +

+In the new, cached and explicit model, the data is loaded at startup +and stored in memory until it is explicitly saved. +Pressing ctrl-S saves the changes. +And indeed, in GZigZag, it is only the changes that are saved: +like CVS, GZigZag stores all the previous saved versions implicitly +as well (XXX Because of timestamp problems, not usable yet). + +

Viewing and moving around

+ +
+ The initial display of two windows next to each other. To fit them + in this document, they have been horizontally resized but otherwise + the view is exactly what you should get when starting GZigZag. +
+ +

+The first figure shows the two windows next to each other that show +up when starting GZigZag on an empty space. +There are two cursors, the green and the blue cursor, which are +seen on the same cell, the home cell. From the home cell downwards +(poswards on d.2) is the system list, which contains +metainformation about the structure as well as keybindings, which +we shall return to later. + +

+Let's move the blue cursor that defines the center of the +right-hand window down three steps. There are three different +ways to achieve this: either clicking on the "AllFlobViews" cell in the +right-hand window or by pressing the arrow down key thrice, +or (probably the most counterintuitive at first), pressing the +comma (,) key thrice. +This moves the view to the one shown in the next figure. +If your machine is fast enough, it should animate between each step +in order to better show how the cells move around. + +

+ The right-hand window, after moving the cursor down three step. + Both cursors are shown in both views, but + moving the blue cursor has moved the center of the right-side view + with it. +
+ +

+The last way is actually the recommended way since it allows you to +keep your hands on the main area of the keyboard at all times: mouse input +is not needed in GZigZag. +The direction keys for the X and Y directions are i, j, l and ',' +for the right-hand view and +e, s, f and c for the left-hand view. If you look at the keyboard, you'll +see that they are arranged in two diamond patterns on the keyboard, one +for the left and one for the right hand to use. + +

+If you look at the upper left-hand corner of the windows, you'll see +that X and Y are not the only dimensions here: there is also a third +dimension, Z, on which d.3 is shown by default. +A place in the default structure where d.3 is used can be found +by moving two steps right and one down from "AllFlobViews". +The depth cell is connected to other cells poswards on d.3. +The keys to move the right-hand view along the Z axis are k for poswards +and K (shift-k) for negwards. + +

+ A place where the third dimension shown is used, as discussed in + the text. +
+ +

+There are various different views to the structure, press 'v' or +shift-V to cycle through them in either window. + +

+Before going on, you should train yourself to use these keys to move around +in the structure. The direction keys will be used in many places later +on in this guide, since they also form a vital part of the commands. + + +

Editing the structure

+ +This section does not give all the possible operations but +tries to give a subset that will be sufficient. Marking is not discussed. + +

Creating new cells

+ +

+ We shall start from the home cell. + + Press 'n' (for "New cell") and 'l' (the direction key + discussed above) and a new cell is created left of the + blue cursor: + + The same would work for the other view, you just need to + use the direction keys for the green cursor after the "n" + command. + For practice, move to the new cell (press 'l') and + press 'n' 'l', 'n' 'j', 'n' 'i' and 'n' ',' to create new cells on all + sides of the new cells. Note that when creating the new cell + leftwards, it is inserted between the first new cell and the + home cell: + + +

Entering text

+ +

+ Now, press Tab and type in some text: + + Tab moved you to the text editing mode which is pretty + much like familiar text entry mode in other systems: + the arrow keys move the insertion cursor and typing a character + inserts it. + Press Tab again to move out of text edit mode, and + the insertion cursor vanishes. + (NOTE: one planned feature is to have the background + change when in the edit mode - these pictures were taken + when this did not yet happen). + +

+ Try putting more text into the other cells. + +

Connecting and disconnecting cells

+ +

+ Now we get to the most important part of ZigZag: making + actual structures. + There are actually several different ways of connecting + cells but we shall only cover one because there's no + time to write this user's guide completely yet. + +

+ The way to connect two cells is to move the cursor of the + left-hand view (green) and the right-hand view (blue) + on the two cells, press '/' (slash) and a direction + to connect the two cells in. + Connect will fail if either of the two cells is connected + in that direction already, except if one of them is alone + in that dimension, in which case it is inserted next to + the other one. + + + +

+ In this situation, pressing '/' ',' or, equivalently, + '/' 'e' results in + + +

Hopping

+ +

+ Hopping is a structural operation where cells are reorganized + along a rank. + It's easiest to figure out if you try it: press 'h' and a + direction key. + +

Alpha-shear

+ +

+ Another structural operation that can be very useful is + the alpha-shear, which changes a connection from the current cell + to another one in the same rank. + +

+ It is used by typing 'a' and two directions: first the connection + and then the direction into which the connection is to be moved. + +

Cell exchange

+ +

+ One more editing operation which helps a lot in making the structure + work the way you want it to. Press '%' (percent) to exchange + the connections of the two accursed cells in the visible X and Y + dimensions. + No other connections (Z or invisible) are touched. + +

Cloning

+ +

+ Cloning is an important structural operation in GZigZag, + as explained in the Gentle Introduction. + Basically, a clone of a cell is a cell poswards from that + cell on d.clone, but with the special property that their + contents are implied to be the same. Cloning is visually + shown by GZigZag by coloring the clones yellow and the original + light yellow. + A clone of a cell is made by placing the right or left cursor + on the cell and pressing 't' or shift-'t', respectively, and + a direction in which to place the clone. + + Pressing shift-T 'l' creates a clone of the left (green) cursor + and places it right of the right-side (blue) cursor: + + + +

The system list

+ +

+In this section, we explain briefly what the system list is, and +what you can do with it. + +

+Basically, the system list contains information for the user interface +of GZigZag, i.e. the types of views, keybindings etc. It is possible to +configure GZigZag to look like something completely different +but you must act carefully: it's fairly easy to accomplish something like +the following: +

+ Hmm, I want to rebind the keys completely. So let's delete the + previous binding list (click) and then I'll start making the + new bindings list (click.. click.... click....) oops, it's not + responding! Right, I just deleted the keybindings list so of + course it will not do anything when I press a key. Duh! +
+

+So remember that any changes to the system list are immediately +reflected in the behaviour of the user interface. At some point +we will probably create a mechanism for making delayed changes that you +can commit all at once but this is not yet in place. + +

+The system list starts at the home cell of the space and continues on +d.system, but for your convenience those cells you will most likely want to +use are cloned to a d.2 rank starting from the home cell. The d.2 rank +is freely modifiable but changing the text in any of the system list cells, +or breaking the d.system rank can lead to dire consequences and you probably +shouldn't do that. At a later date, the system list will probably be locked +by default. + +

+The cells on the system list simply enumerate the functions: the +actual cells that describe whatever are connected to the system list +cells on d.1. + +

Dimension list

+ +

+ The DimLists system list cell has connected to it on d.1 + a cyclical rank on d.2, the dimension list. + This list contains the names of dimensions that the views + will cycle through when you press X, Y, Z (possibly with + shift/alt). + +

+ Adding a dimension simply involves creating a new cell and + typing the name into that cell. Likewise, deleting a cell + will delete the dimension from the list (but not currently the + connections along that dimension). + NOTE: don't rotate to an empty cell: this will possibly + cause problems: at the very least, a raster error. + +

+ The dimension cursors of the different views + are a variety of pink shades. + These dimension selectors of the different views are actually + generic cursors so it would be possible to have different + dimension lists for each X, Y and Z of each view but at the moment + it's not possible to repoint them to a different list except by + trickery. We will probably provide a mechanism for this. + +

Views

+ +

+ The views are defined on three different cells in the system list: + Views, + AllViews and + CellViews. + These cells have different functions. + +

+ The windows cycle through different views by moving in the + list below Views, much like the dimensions are + cycled on the list below DimLists. + The cells below Views describe one particular + view. + +

+ The cells below Views are actually clones of + cells below AllViews that actually give those + views' parameters. For instance, the Vanishing and StretchVanishing + rasters use the same Java code but have different parameters + in the structure below AllViews. + +

+ The structure below AllViews is simple: + it is a list of the clonable cells (which name the views, but + the name is just decoration for the user: the real information + is in the structural operation of cloning), which are + connected on d.1 to the structure that actually defines the view. + +

+ The defining cells are structure along the ZOb structure, + explained better elsewhere (XXX). + +

+ Not all views in AllViews are by default cloned to the + main + Views + list for two reasons: first, there are too many views to just cycle + through, and second: some are not yet very stable or useful. + Experimentation with them is encouraged, though. + + +

+ CellViews + is similar to + Views and + AllViews + in that it also contains a list of cellviews, i.e. how to render + one cell. + + This is because currently there are not enough different cellviews + that having a separate list of more possibilities is not necessary. + + +

Bindings

+ +

Actions

+ + +

The keystrokes.

+ +This is a list of (almost) all the currently available keystrokes +in the default bindings. As explained above, it is simple to modify the +bindings. + +#include '../keybindings.wml' + +:} + + + diff --git a/Documentation/UsersGuide/wallstreet.png b/Documentation/UsersGuide/wallstreet.png new file mode 100644 index 0000000..d2e3b89 Binary files /dev/null and b/Documentation/UsersGuide/wallstreet.png differ diff --git a/Documentation/UsersGuide/widthstr.png b/Documentation/UsersGuide/widthstr.png new file mode 100644 index 0000000..f3e5aaf Binary files /dev/null and b/Documentation/UsersGuide/widthstr.png differ diff --git a/Documentation/UsersGuide/wrongconn.png b/Documentation/UsersGuide/wrongconn.png new file mode 100644 index 0000000..8ca0c23 Binary files /dev/null and b/Documentation/UsersGuide/wrongconn.png differ diff --git a/Documentation/diagrams/Makefile b/Documentation/diagrams/Makefile new file mode 100644 index 0000000..36fd595 --- /dev/null +++ b/Documentation/diagrams/Makefile @@ -0,0 +1,5 @@ +all: + @echo "go away" + exit 1 + +include ../lib.mk diff --git a/Documentation/diagrams/ZZCanvas.dia b/Documentation/diagrams/ZZCanvas.dia new file mode 100644 index 0000000..a9752b2 Binary files /dev/null and b/Documentation/diagrams/ZZCanvas.dia differ diff --git a/Documentation/diagrams/cursoring.dia b/Documentation/diagrams/cursoring.dia new file mode 100644 index 0000000..601d6dd Binary files /dev/null and b/Documentation/diagrams/cursoring.dia differ diff --git a/Documentation/index.html b/Documentation/index.html new file mode 100644 index 0000000..c4b881d --- /dev/null +++ b/Documentation/index.html @@ -0,0 +1,130 @@ + + + + GZigZag documentation + + + +

GZigZag documentation

+
$Id: index.html,v 1.4.4.1 2002/03/07 19:56:13 ajk Exp $
+ +

+ Most documents referred to from this page are incomplete. So be + warned. If there is something that you'd need urgently, please + contact the developers at <zzdev@xanadu.net>. +

+ +

+ Note that all HTML documents are available in two flavours: one + that works if your browser's CSS support, if existing, is not + too buggy (such as Mozilla, Netscape Navigator 2 or 3, or + Konqueror); and another meant for users of Netscape Navigator 4, + which has bugs that make the normal version illegible when the + stylesheet support is on. Choose your format wisely. +

+ +

User's documentation

+ + +

+ New users are encouraged to start with Gentle Introduction to Ted + Nelson's ZigZag structure (NS4-compatible + version). It introduces the reader to the ZigZag universe + in a general way without touching the aspects of actually using + it in GZigZag. The background information given by the Gentle + Introduction will be invaluable to a GZigZag user. +

+ +

+ The article GZigZag - A Platform for + Cybertext Experiments (NS4-compatible version), written + for Cybertext Yearbook edited by Markku Eskelinen & Raine + Koskimaa, is an excellent introduction to the potentials of + GZigZag. +

+ +

+ The GZigZag User's Guide (NS4-compatible version) + introduces the reader to the actual using of the GZigZag system. + This is what tells you how you create new cells and connect + cells and so on. +

+ +

+ There is also a GZigZag glossary + (NS4-compatible version) that + contains short definitions of key GZigZag terms. +

+ +

+ The The nile (nile is a literate editor) + applitude (NS4-compatible version) + article and Nile User's Guide + (NS4-compatible version) document + a new experimental way of writing text. +

+ +

Developer's documentation

+ + + + diff --git a/Documentation/keybindings.wml b/Documentation/keybindings.wml new file mode 100644 index 0000000..b880fb1 --- /dev/null +++ b/Documentation/keybindings.wml @@ -0,0 +1,182 @@ + +

Default bindings for the orthogonal rasters

+ +
$Id: keybindings.wml,v 1.4 2001/03/02 07:13:37 ajk Exp $
+ +

+These are still being discussed and are not yet frozen. Note that there is a +panic button: if there is no binding for ESC, it invokes undo. + + + Key(s) + Binding + Ctrl-S + Commit the current changes to disk. + ijl,kK + Up-left-right-down-Z+-Z- in view 1. + esfcdD + Up-left-right-down-Z+-Z- in view 0. + n dir + Create a new cell in given direction + b dir + Break a connection in given direction + h dir + Hop the accursed cell in the given direction. + Hopping means simply switching the places of + the accursed and the indicated cells in that + rank, no other ranks are affected by + the operation. + xyz + Show next dimension on list on X/Y/Z in view 1 + Alt-xyz + Show previous dimension on list on + X/Y/Z in view 1 + XYZ + Show next dimension on list on X/Y/Z in view 0 + Alt-Shift-XYZ + Show previous dimension on list + on X/Y/Z in view 0 + / dir + Connect the center cells of the right and left views + in the given direction, if no connections will be + broken by this. + ~ + Exchange the cursor positions of the two views (no + other view parameters are changed). + Delete + Delete the center cell of view 1 and move the cursor. + Cursor move tries following directions in order: + X-, X+, Y-, Y+, Z-, Z+ and finally goes to home cell. + + m + Mark or unmark the cell in view 1 + Enter + Execute cell in view 0, with the cell in view 1 + as parameter + v + Change raster in view 1. + V + Change raster in view 0. + Alt-v + Change raster in view 1 backwards. + Alt-V + Change raster in view 0 backwards. + Home + Go home: move view 1 cursor to homecell. + Esc + Move both views to home and reset dimensions to first + three dimensions on first dimlist. + 0123456789 + Insert the given number into the number insert buffer + for cell IDs. + g + Move view 1 to cell whose ID number was in buffer + G + Move view 0 to cell whose ID number was in buffer + Backspace + Remove one number from the number insert buffer + + t dir + Clone the view 1 cursor to given direction (may be + in either view). + T dir + Clone the view 0 cursor to given direction (may be + in either view). + + % + Exchange the X and Y connections of the two + accursed cells with each other. + + o + Go to original (rootclone, cell from which accursed + cell was cloned) in view 1. + O + Go to original (rootclone, cell from which accursed + cell was cloned) in view 0. + + End dir + Move to te end of the rank in the given direction. + + < + Set the cursor of the left-hand-view to the cell the + right-hand view is pointing to. + > + Set the cursor of the right-hand-view to the cell the + left-hand view is pointing to. + + - dir + Connect the current view1 cursor into marked cells + in given direction. Direction must be in view 1. + + Alt-c + Switch into "curseling" (cursor selection) mode (see + below). + + a dir dir + Monochug: change one connection. See above. + + +

Text edit mode

+ + + Key(s) + Binding + Esc or Tab + Switch off text edit mode + Delete + Delete one character after cursor + Backspace + Delete one character before cursor + Left, Right + Move the cursor within the current cell + Home + Move the cursor to the beginning of the text in + the current cell + End + Move the cursor to the end of the text in + the current cell + Ctrl-A + Move the cursor to the beginning of the current + line in the text of the current cell + Ctrl-E + Move the cursor to the end of the current line + in the text of the current cell + Enter + Insert a line separator in the text before the cursor + any key producing a printable character + Insert the character in the text before the cursor + + + + +

Curseling (Cursor selection)

+ +

+As an intermediate for multiple cursors, there is a key binding mode for +"curseling:" cursor selection. In the standard keybindings, Alt-c is used +to go into this mode, which by default supports the following key bindings: + + + Key(s) + Binding + Tab, Spacebar, Alt-c or Esc + Select this cursor, quit curseling mode. + Left, Right, jl + Select next/last cursor in system cursor list + in view 1. + Up, Down, i, + Select next/last cursor positioned on the same cell + in view 1. + sfec + Like Left/Right/Up/Down, operating on view 0. + + +

+Note that you can create four additional cursors through executing the +CreateCursors command, found in the action list, by centering the left view +on it and hitting Enter. + + + diff --git a/Documentation/lib.mk b/Documentation/lib.mk new file mode 100644 index 0000000..0c9c395 --- /dev/null +++ b/Documentation/lib.mk @@ -0,0 +1,33 @@ + +%.html : %.wml + wml -I ../wmlinc $< -o $@ + +%-ns4.html : %.wml + wml -I ../wmlinc -Dmode=ns4 $< -o $@ + +%.ps: %.dia + dia -e $@ $< + +%.png: %.ps + # gs -q -sDEVICE=ppmraw -sOutputFile=expdia.pnm -r288 -dNOPAUSE -dBATCH $< + gs -q -sDEVICE=ppmraw -sOutputFile=expdia.pnm -r144 -dNOPAUSE -dBATCH $< + pnmcrop expdia.pnm | pnmpad -white -l20 -r20 -t20 -b20 >expdiac.pnm + mogrify -antialias -geometry '20%' expdiac.pnm + # mogrify -antialias -geometry '10%' expdiac.pnm + pnmtopng expdiac.pnm >$@ + rm expdia* + +%.tex : %.ptex + gpic -t <$< >$@.new + mv $@.new $@ + +%.dvi : %.tex + latex $* + latex $* + latex $* + +%.ps : %.dvi + dvips -o $@ $< + +clean : + rm -f *.html diff --git a/Documentation/misc/ADDRESSING b/Documentation/misc/ADDRESSING new file mode 100644 index 0000000..8d930c4 --- /dev/null +++ b/Documentation/misc/ADDRESSING @@ -0,0 +1,26 @@ +A XML pointer-like scheme for addressing elements in a ZZ space. + +Neighbours of a cell + + (cell).n(d.2,+).n(d.1,-) + +Headcell of a cell + + (cell).negcell(d.2).poscell(d.1) + +Searching for an intersection of two ranks (the cell itself won't count +so you can repeat it and get all crossings) + + (cell).intersect(d.2,+, (cell), d.1,-) + +this is useful e.g. for searching clones: + + (cell).intersect(d.1,+, Color, d.clone, +).n(d.2,+) + +to find the next cell giving the color through a clone. + +XXX textual searching? + +There should be a way to detect changes not only to cells but also +expressions like this. Implementing settings would suddenly be a lot +easier. diff --git a/Documentation/misc/Curseling b/Documentation/misc/Curseling new file mode 100644 index 0000000..8bb9339 --- /dev/null +++ b/Documentation/misc/Curseling @@ -0,0 +1,46 @@ +How to use the cursel feature (as of 00-08-04) + +"Cursel" means "cursor selection." There is now a mode where you can choose +between different cursors for a view. Here are the instructions as to how. + +In normal mode: +Alt-C -- switches to cursel mode. I like to reconfigure this to spacebar -- + much faster. Note that the view's background now shows the color of + its current cursor -- useful when there are multiple cursors on the + same cell. +Esc -- now re-attaches the standard cursors to the views before it moves + them to the home cell. When you're lost, hit Esc. + +In cursel mode: +Left/Right arrow (or sf or jl): choose between cursors on the system list. +Up/Down arrow (or ec or i,): choose between cursors on the same cell as the + current cursor. +Tab or Spacebar or Esc: Select this cursor, quit cursel mode. + +To get four additional cursors: +With the left view, go to "CreateCursors" on the Action list. Hit Enter. +Note that you can apply this multiple times, but it'll give you multiple +cursors of the same color. + +To bind the two views together: +Go into cursel mode. Hit Left, Right, s, f, j, or l until both views have the +same background (and thus, cursor) color. Quit cursel mode. + +To bind a view to a "magic cursor:" +Go to the first entry on the FlobRaster list. Make sure at least one of your +views is shows this raster. Go into cursel mode. Hit Up/Down (or e/c if you +use the left view) until the background of your view gets white: this means you +have attached the view to a cursor without an associated color. Raster cursors +don't have associated colors (at the time I'm writing this). Now quit cursel +mode. Move the cursor up and down and watch what happens. (Easiest way to get +back to normal from here is to hit Esc.) + +To show very clearly how the cursing system in ZZ works: +Create the four additional cursors (see above). Edit the dimension list so that +d.cursor is on it. Cursel the golden cursor, go to the FlobRaster cell on the +system list, and go to the rightmost cell. Now cursel the violet cursor and go +to the FlobRaster cell. Make sure at least one of your views is set to the +standard vanishing raster (whose cell is between your two cursors now). Rotate +the view so that d.1 is on the X- and d.cursor on the Y-axis. Now play around +with the violet and the golden cursor, and show how the connections on d.cursor +change. \ No newline at end of file diff --git a/Documentation/misc/RENDERING b/Documentation/misc/RENDERING new file mode 100644 index 0000000..cae3b1f --- /dev/null +++ b/Documentation/misc/RENDERING @@ -0,0 +1,37 @@ + Requirements for rendering of ZZ spaces. +$Id: RENDERING,v 1.1 2000/05/16 14:57:58 tjl Exp $ + +This document is intended to start the design of the final ZZCanvas-style +thing. + +Basics: + + - placing arbitrary (extensible) graphics objects on the canvas + - either depth or reverse order to simplify rastering code: cells + rastered first should be on top, not bottom and breadth-first bottom-up + is annoyingly difficult + - getting some identifier of an object at given coordinates for e.g. + mouse clicks. IMPORTANT: could this be done by rerendering to avoid + memorizing too much? OpenGL / FreeWRL-style instead of widget-style? + TRADEOFF: + normal render = const1 * N, click = const2 * N + widget-style: const1 larger, const2 maybe smaller. + opengl-style: const1 smaller, const2 maybe larger + - for java.awt.Graphics, widget-style is somewhat necessary anyway + to get depth. However, memory consumption might go down. + - the BIG advantage of widget-style comes when there's lots of stuff + and everything does not move or change: then we can use the widget + objects as caches of stuff of interest from the structure, and set + the necessary tripwires (ZZObs) to change those objects if the structure + changes. For the textcloud stuff where most items stay still much + of the time, this would be advantageous. + + +More interesting: + + - access by other components to the raster: getting various mouse click + places + - rendering XOR-cursors for text when moving the cursor, to show where + an insert would occur + - same when dragging another piece of text. + diff --git a/Documentation/misc/TORESOLVE b/Documentation/misc/TORESOLVE new file mode 100644 index 0000000..ad21821 --- /dev/null +++ b/Documentation/misc/TORESOLVE @@ -0,0 +1,8 @@ +Questions to resolve with Ted + +- master dimension list + +- should we have a mechanism in the views to step through +tree structures so that left -> right takes us back where we were? +In essence, storing in the structure the information about where +this client was (d.prevcursor)? diff --git a/Documentation/misc/billow b/Documentation/misc/billow new file mode 100644 index 0000000..f9ad6b0 --- /dev/null +++ b/Documentation/misc/billow @@ -0,0 +1,20 @@ +Date: Mon, 22 Nov 1999 02:12:38 +0900 +From: Ted Nelson +To: "Tuomas J. Lukka" +Cc: ted@xanadu.net, marlene@xanadu.net, xanni@xanadu.net, eharter@din.or.jp +Subject: :zx,virt: "Mouse control for billowing (Was: Re2: I take it you mean... Re: Billowing + +I suggest: + up and down move the position of the billow, + right and left affect its size, + right and left with right button down enlarges and reduces + the font sizes in the billow, + while left button at any time marks the text, as usual. + +Motto: Key assignments are the most changeable aspects-- + they hardly affect the virtuality. Mapping of function that + seems consistent with usual functions is a constraint. + +Best, Ted + +.... [message being replied to clipped by Tjl] diff --git a/Documentation/misc/byrokratiadoku b/Documentation/misc/byrokratiadoku new file mode 100644 index 0000000..d0971e8 --- /dev/null +++ b/Documentation/misc/byrokratiadoku @@ -0,0 +1,169 @@ +\documentclass[a4paper,12pt]{artikel3} +\usepackage[T1]{fontenc} +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage[latin1]{inputenc} +\usepackage[finnish]{babel} +\usepackage{times} +%\def\zigzag{ZigZag} +%\def\zigzag{{\fontfamily{yinit}\fontencoding{U}\fontsize{5}{7pt}\selectfont Z} +%{\huge i}{\fontfamily{yinit}\fontencoding{U}\fontsize{5}{7pt}\selectfont G} +%{\huge}{\fontfamily{cmr}\fontencoding{OMS}\fontsize{30}{30pt}\selectfont Z} +%{\large$\displaystyle \alpha$\Huge\bf\selectfont$\gamma$}} +%\def\gzigzag{{\it \Huge G}\zigzag} +\def\zigzag{ZigZag} +\def\gzigzag{G\zigzag} +\def\url#1{\texttt{#1}} +\pagestyle{empty} +\begin{document} +{\hfill{}{\Huge Projektisuunnitelma}\hfill{}} +\vspace{1.2cm} + +\gzigzag"-projekti tutkii ja soveltaa käytäntöön nykyistä edistyneempiä +tiedonhallintamenetelmiä käyttäen pohjana Ted Nelsonin \zigzag"- ja +Xanadu"-malleja. Lähtökohtana on, että nykyiset +tiedonhallintamenetelmät ovat riittämättömiä vastaamaan tulevaisuuden +haasteisiin. Ryhmän olennaisia tutkimusalueita ovat käyttöliittymät ja +informaation varastointi hyperrakenteisiin, sekä näiden tutkimusten +tulosten soveltaminen käytäntöön. + +Suurten tietomäärien hallinta on nykyjärjestelmillä hyvin hankalaa, +koska tiedostojärjestelmässä ainut tiedostojen välinen tieto on +hakemistorakenne. Hakemistorakenne on hierarkia, eikä siksi sovellu +kuin yksinkertaiseen kategorioihin jakamiseen. HTML:ssä hakemistorakenteen +puutteita on korjattu linkeillä, jotka on varastoitu tiedoston sisälle. +Nämä linkit ovat yksisuuntaisia ja rikkoutuvat helposti. + +Tietokannat ovat paljon tiedostojärjestelmiä edistyneempi tapa hallita +tietoa. Ne ovat kuitenkin kovin jäykkiä järjestelmiä: tietokanta +suunnitellaan yleensä yksittäisen sovelluksen käyttöön, eikä sovellu +yleisen tiedon varastointiin; tietokantajärjestelmät eivät tarjoa sen +enempää mahdollisuuksia tietokantojen väliseen linkitykseen kuin +tiedostojärjestelmät; ja tietokantoihin on harvoin pääsyä ulkopuolelta +--- usein ainoastaan WWW-käyttöliittymä on saatavilla. Tietokantojen +merkittävimmät edut tiedostojärjestelmiin nähden ovat mahdollisuudet +tiedon tehokkaaseen hakuun ja tietojen välisten suhteiden tallennukseen, +mutta ne eivät ole tarpeeksi joustavia yleiseen tiedonhallintaan. + +Projektin päätavoitteena on luoda \gzigzag"-ohjelmisto, jonka +päälle voidaan helposti rakentaa tiedon esitys"-, haku"- ja +käyttöominaisuuksiltaan nykyistä parempia ohjelmia. Ohjelmiston pohjana +on \zigzag"-rakenne, joka koostuu soluista ja eri ulottuvuuksia pitkin +tehdyistä kytkennöistä. Rakenteessa tieto on soluissa, joista +kukin sisältää paljon pienemmän osan tiedosta kuin nykyiset tiedostot; +yksi solu sisältää suunnilleen saman verran tietoa kuin +taulukkolaskennan solu. +%Toisin kuin taulukkolaskennassa, kyseessä ei ole kaksiulotteinen soluhila +%vaan moniulotteinen soluavaruus, jossa sama informaatio voi olla kytkettynä +%eri dokumentteihin eri ulottuvuuksia pitkin. +Toisin kuin taulukkolaskennassa, solut on kytketty toisiinsa moniulotteisessa, +joustavassa rakenteessa, jossa jokainen solu voi olla kytkettynä mihin tahansa +soluihin. Rakenteen ulottuvuuksilla voi olla eri merkityksiä, +kuten esimerkiksi ''pöytäkirjan 3141S sisältö'', ''viittaus'', +''tarkennus asiasta kiinnostuneille'', tai ''hakemistorakenne''. +Ulottuvuuksilla ei myöskään ole samanlaisia rajoituksia kuin reaalimaailmassa: +kuljettaessa ensin ylös ja sitten oikealle voidaan päätyä eri paikkaan kuin +kuljettaessa ensin oikealle ja sitten ylös. + +Kytkentöjen kaksisuuntaisuus on eräs \zigzag"-rakenteen tärkeimmistä +ominaisuuksista. WWW:ssä, jossa on käytössä yksisuuntaiset linkit, ei ole +mahdollista esimerkiksi lisätä omia reunahuomautuksia sivuihin, tai selata +niitä sivuja, jotka viittaavat tai lainaavat jonkin kappaleen dokumentista. +\zigzag"-järjestelmässä nämä asiat ovat helppoja, ja oheisinformaation +mahdollistaman suodatuksen avulla vältetään myös asian hukkuminen erilaisten +reunahuomautusten ja tarkennusten viidakkoon. + +\gzigzag"-ohjelmistoa kehitettäessä on tarkoitus tutkia erilaisten visuaalisten +menetelmien etuja, kun niitä käytetään koko järjestelmän laajuisesti. +Ryhmä pyrkii parantamaan sovellusten käyttöliittymiä jättämällä pois +perinteisen ''ikkunat, valikot ja painonapit'' "-mallin: tieto on +esitettävä kontekstissaan, ei pilkottuna laatikoihin, joilla ei ole +minkäänlaisia keskinäisiä yhteyksiä. Menetelmistä ehkä tärkein onkin +Focus+Context, jonka pääideana on tuoda käyttäjää kullakin +ajanhetkellä kiinnostava tieto (Focus) mahdollsimman korostetusti +esille, ja siihen liittyvät asiat (Context) sen mukaan, miten tärkeitä +ne ovat fokuksen kannalta. Focus+Contextiin liittyy läheisesti +animaatio: kun käyttäjä liikkuu tietorakenteessa, on hyvin tärkeää +näyttää, miten uusi tieto liittyy edelliseen, ja paras tapa näyttää se +on animointi. + +Ryhmä kirjoittaa tutkimusten tuloksista artikkeleja kansainvälisiin +konferensseihin ja julkaisuihin, mm. UIST, HICSS ja HT01. Tällä hetkellä on +tekeillä artikkelit Focus+Contextin soveltamisesta viestiketjuihin +ja suureen joukkoon tekstidokumentteja, sekä artikkeli, jossa esitellään +\zigzag"-malli yleisellä tasolla. + +%\gzigzag"-ohjelmiston lisenssi on GNU Lesser General Public License, +%sama kuin Linuxin GNU GPL, paitsi että se antaa enemmän mahdollisuuksia +%\gzigzag in käyttöön kaupallisten järjestelmien pohjana. Tällä hetkellä +%toteutus on prototyyppiasteella, ja sen avulla voi kokeilla \zigzag"-rakenteen +%soveltuvuutta erilaisiin tehtäviin. + +\gzigzag"-ohjelmiston kehitys on julkista, ja ohjelmistoa levitetään +menestyineiden Linuxin ja Apachen tavoin vapaalla lisenssillä (GNU LGPL). Tällä +hetkellä toteutus on prototyyppiasteella, ja on saatavissa verkosta +osoitteesta \url{http://www.gzigzag.org/}. + +Vuoden 2001 loppuun on asetettu seuraavat tavoitteet: +\begin{itemize} +\item{Viesti-, kalenteri-, yms. järjestelmän prototyyppi (Sonera).} +\item{Uudenlaisen tekstinkäsittelyohjelman (Nile) prototyyppi. Nile eroaa + nykyisistä ohjelmista mm. siten, että tekstiä voidaan lainata + niin, että lainauksen vieressä näkyy dokumentti, josta lainaus + on. Dokumenttiin liittyvät asiat, kuten kuvat, kelluvat tekstin + vieressä, jolloin pitkäänkin tekstiin liittyvä kuva pysyy koko + ajan näkyvissä, vaikka tekstiä selaa eteenpäin. Versiointi takaa + sen, että vanhoja versioita pääsee aina lukemaan, ja + lainauslinkit (transkluusiot) sen, että intertekstuaaliset + yhteydet voidaan esittää käyttäjälle ymmärrettävällä tavalla.} +\end{itemize} +Vuoden 2002 loppuun mennessä on tarkoitus toteuttaa \gzigzag"-ohjelmisto +solukielillä (''bootstrap''). Tämä vaatii ensin tehtävään soveltuvien +solukielten kehittämisen, ja on eräs tärkeimmistä kehitystyön +vaiheista. Solukieliin siirtyminen mahdollistaa selkeän +\zigzag"-rakennetta käsittelevän ohjelmakoodin nopean kirjoittamisen, +ja siksi tämä vaihe on hyvin olennainen sekä tutkimustyön että +\gzigzag"-ohjelmiston kehityksen kannalta. +\newpage +Projektista vastaa FT Tuomas J. Lukka. Tehtävät on jaettu projektin +työntekijöille seuraavasti: + +\begin{tabular}{ll} +Katariina Ervasti & Tutkimus humanistisista näkökohdista, dokumentointi ja + popularisointi. \\ +Tuukka Hastrup & \zigzag in teoria. \\ +Antti-Juhani Kaijanaho & Soluavaruuksien versionhallinta, tietoverkot, + solukielet ja \zigzag in teoria.\\ +Tuomas Lukka & Projektin johto ja kokonaisuuden hallinta. \\ +Tero Mäyränen & \zigzag in käyttö multimediasovelluksissa ja solukielet. \\ +Vesa Parkkinen & \zigzag in hyödyntäminen kämmenmikroissa ja multimedia. \\ +Rauli Ruohonen & Solukielet, \zigzag in teoria ja kämmenmikrot. \\ +Kimmo Wideroos & Tietokoneavusteinen oppiminen ja prosessikirjoitus.\\ +\end{tabular} + +Ryhmä tekee yhteistyötä professori Ted Nelsonin (Keion yliopisto, Japani; +Xanadu, Inc.) ja saksalaisen opiskelijan Benjamin Fallensteinin +kanssa. Professori Nelson yhdessä tohtori Lukan kanssa kehittää +\zigzag"- ja Xanadu"-malleja eteenpäin, ja Fallenstein on mukana +\gzigzag"- ohjelmiston kehitystyössä. + +\gzigzag ia ja sen perusajatuksia voidaan periaatteessa hyödyntää minkä tahansa +loppukäyttäjälle suunnatun ohjelmiston tuottamisessa, mutta erityisen hyvin +se soveltuu tietoverkoissa toimiviin järjestelmiin ja integroituihin +järjestelmiin. + +Projektiin liittyviä riskejä ovat: +\begin{itemize} +\item{\zigzag in hyödyntämisen jääminen vähäiseksi, koska se eroaa niin paljon + nykyisistä järjestelmistä, että siihen siirtymisen kynnys voi olla + korkea.} +\item{Suljettujen tiedon tallennusmenetelmien yleistyminen voi luoda + esteitä \zigzag in yleistymiselle, sillä ne rajoittavat mahdollisuutta + tehdä \gzigzag ista yhteensopiva muiden järjestelmien kanssa. + Suljettuja tallennusmenetelmiä käyttävien ohjelmien tekemiä + tiedostoja ei voi lukea muilla ohjelmilla.} +\item{Toteutuksen vaikeus.} +\item{Avainhenkilöiden lähteminen projektista.} +\end{itemize} + +\end{document} diff --git a/Documentation/misc/keys b/Documentation/misc/keys new file mode 100644 index 0000000..e9a9582 --- /dev/null +++ b/Documentation/misc/keys @@ -0,0 +1,80 @@ +Initial ZigZag key bindings +--------------------------- +Enter Execute cell at cursor 0 +Del Delete cell at cursor 1 +0-9 Enter digit into numeric buffer +BS Backspace digit in numeric buffer + +< Import rank from text editor in specified direction +> Export rank in specified direction to text editor + +s, S Move cursor 0 negwards in X dimension +f, F Move cursor 0 poswards in X dimension +e, E Move cursor 0 negwards in Y dimension +c, C Move cursor 0 poswards in Y dimension +d Move cursor 0 negwards in Z dimension +D Move cursor 0 poswards in Z dimension + +j, J, Left Make link or move cursor 1 negwards in X dimension +l, L, Right Make link or move cursor 1 poswards in X dimension +i, I, Up Make link or move cursor 1 negwards in Y dimension +",", Down Make link or move cursor 1 poswards in Y dimension +k, PgUp Make link or move cursor 1 negwards in Z dimension +K, PgDn Make link or move cursor 1 poswards in Z dimension + +G Move cursor 0 to cell number +g, Home Move cursor 1 to cell number + +Alt-s Hop cell at cursor 0 negwards in X dimension +Alt-f Hop cell at cursor 0 poswards in X dimension +Alt-e Hop cell at cursor 0 negwards in Y dimension +Alt-c Hop cell at cursor 0 poswards in Y dimension +Alt-j Hop cell at cursor 1 negwards in X dimension +Alt-l Hop cell at cursor 1 poswards in X dimension +Alt-i Hop cell at cursor 1 negwards in Y dimension +Alt-"," Hop cell at cursor 1 poswards in Y dimension + +Control-D, Alt-d/D Edit cell at cursor 0 +Control-K, Alt-k/K Edit cell at cursor 1 + +b Break link in specified direction +h Hop cell in specified direction + +Control-L Redraw all windows + +m Mark/unmark cell at cursor 0 +M Mark/unmark cell at cursor 1 +Alt-m Rotate selection groups +Alt-M Save selection group and start a new one + +n New cell in specified direction and edit +N, Ins New cell in specified direction + +Q Toggle cursor 0 cell view +q Toggle cursor 1 cell view + +R Reset dimensions for cursor 0 +r Reset dimensions for cursor 1 + +T Create clone of cell at cursor 0 +t Create clone of cell at cursor 1 + +V Toggle cursor 0 refresh raster +v Toggle cursor 1 refresh raster + +Control-V, Alt-v/V Display Zigzag version +Control-X Exit Zigzag + +X Rotate cursor 0 X axis dimension +x Rotate cursor 1 X axis dimension +Y Rotate cursor 0 Y axis dimension +y Rotate cursor 1 Y axis dimension +Z Rotate cursor 0 Z axis dimension +z Rotate cursor 1 Z axis dimension + +Alt-X Flip cursor 0 X axis dimension +Alt-x Flip cursor 1 X axis dimension +Alt-Y Flip cursor 0 Y axis dimension +Alt-y Flip cursor 1 Y axis dimension +Alt-Z Flip cursor 0 Z axis dimension +Alt-z Flip cursor 1 Z axis dimension diff --git a/Documentation/misc/textcloud b/Documentation/misc/textcloud new file mode 100644 index 0000000..07f1a3e --- /dev/null +++ b/Documentation/misc/textcloud @@ -0,0 +1,250 @@ +Some parts of an email exchange between Tjl and Ted, edited. +(If these were real transclusions, you could jump from here to see the whole email +exchange. Wouldn't that be just so nice...) + +---------------------------------------------------------------------------- + +>Any progress on the textitems stuff? That is one priority since +>that would represent an entirely different view of the ZZ structure +>(vstreams), with interesting connectivity and applications. And I want +>to use that to write my next pieces of ZZ documentation! + +OKAY. Here's what I think you asked me for. +- keyboard commands to step around among flying items +- how to glue them together +- how to separate one item into two + +IN ADDITION, I think we want +- how to make an item bigger or smaller + +- - - - - - - - - - +Let's call this Item Cloud mode. + +I ASSUME the items can be borderless, just flying items of text on a + shared background (so in principle two identical items could cover + one another textually). +NOTE THAT since my PC Java won't accept arrow keys, I have to + have the letter alternatives esfc ijl, ESFC IJL> and sometimes dD kK. + So when I say "arrow" I mean one of those. +I AM HOPING that Java can receive keystrokes-up-and-down (raw). + +The following are keyboard suggestions to try. They should all be + reconfigurable. The trouble, of course, is making them reconfigurable + as sequences rather than as individual strokes. + +SELECTING A RIGHT-HAND ITEM: +- Select by mouse +OR (once one item is selected) +- use ijl; arrow keys to select among them. I suggest that up and down + should refer to items within epsilon vertically of the original item, + and the same horizontally-- in other words, when using arrow keys, + stay roughly near the one you're currently near. This we'll have to + fiddle with parametrically. (It's also possible to select the next item + within unseen vertical and horizontal channels-- an alt. approach.) +OR +- use the space bar to select next item IN ORDER OF CREATION. + +SELECTING A LEFT-HAND ITEM: +- Select by mouse +OR +- use esfc keys to select among items. + +TO MOVE AN ITEM +- ctrl-esfc or ctrl-ijl, +TO CEMENT LEFT AND RIGHT ITEMS +- capital S or E appends the left to the right +- capital F or C prepends to left to the right +- capital I or J appends the right to the left +- capital L or < prepends the right to the left +(Note that these are like the connection functions in Perl ZZ.) + +TO CUT +I suggest space-!-space. +Or \. (We'd go into a Special Mode if you actually want the character-- + NOT \\ for most people. +Ctrl-enter would be great, if we could do it in raw mode. + +TO ENLARGE the right-hand-item a little (its typeface) ++ +TO SHRINK the right-hand item a little +- + +---------------------------------------------------------------------------- + +>> TO MOVE AN ITEM +>> - ctrl-esfc or ctrl-ijl, +> +>And with mouse? For moving things around, the mouse is pretty good. + +Oh, of course. Sorry I forgot to mention. + +>Also, how to use the mouse to select - mouses have up to 3 buttons +>and use of shift/ctrl at the same time. + +Right. Sorry. +1. As you said, click and type. I presume you're typing on a big 2D +space, and that Items aren't distinct till you end one? + +2. Ah, we haven't talked about how an item ends... I guess with same + "sever" mechanism, no?) + +3. Move by left-mouse (to seize). + +The question is-- when should the mouse seize an item, when should + the mouse start a new item? +-- especially since it may not be exactly clear whether we are on top of + an item, since there are no borders +-- and as the area gets crowded, you want to be able to start an item in + the middle of another item. + + +^Õ ^Õ ^Õ ^Õ ^Õ ^Õ ^Õ ^Õ ^Õ ^Õ ^Õ +But why not use the other mouse buttons for Billowing? + That could combine it nicely. +---------------------------------------------------------------------------- + +>> SELECTING A LEFT-HAND ITEM: +>> - Select by mouse +>> OR +>> - use esfc keys to select among items. +> +>So here you can't use the space? Or use ctrl-space or shift-space? +>It would be nice to have the same ops for both sides. + +ZOWIE! SHIFT-SPACE! LOVE IT! That's perfect. + Never thought of spacebar with a control key. Or at least + not in the last five or ten years ... + +---------------------------------------------------------------------------- + +>But how do I append one item on the right to another item on the right. +>Example: in the left cloud, I've typed a number of ideas I want to put +>into a text, and in the right cloud, I'm working on the actual text. +>So most operations would only touch the right-hand cloud. + +and also + +>> SELECTING A LEFT-HAND ITEM: +>> - Select by mouse +>> OR +>> - use esfc keys to select among items. +> +>So here you can't use the space? Or use ctrl-space or shift-space? +>It would be nice to have the same ops for both sides. + +Here we have great examples of WOOOOPS communication. I didn't + notice that you mentioned left and right clouds. I thought we were dealing + with only one cloud. + +So anyhow shift-space would be the most consistent. + +---------------------------------------------------------------------------- + +>mouses have up to 3 buttons +>and use of shift/ctrl at the same time. + +I would say that since 90% of the mice in the world have 2 buttons-- +- Mac with 1 button is what, 5%? +- Linunix is even fewer, I think +- W98 and W2000, with 3-button mice are rare +W95 is still way the majority-- and they are an important market. + +Thus we DESIGN for 2-button mouse, leave the middle one explicitly + to be programmable. + +In other words, the third button can only be for shortcuts + and extra options. + +---------------------------------------------------------------------------- +>> TO CEMENT LEFT AND RIGHT ITEMS +>> - capital S or E appends the left to the right +>> - capital F or C prepends to left to the right +>> - capital I or J appends the right to the left +>> - capital L or < prepends the right to the left +>> (Note that these are like the connection functions in Perl ZZ.) +> +>But how do I append one item on the right to another item on the right. +>Example: in the left cloud, I've typed a number of ideas I want to put +>into a text, and in the right cloud, I'm working on the actual text. +>So most operations would only touch the right-hand cloud. + +Since when I wrote my part of the above I didn't realize you were + talking about left and right CLOUDS, I assumed that each hand + would be wandering in the one and only cloud. This is more + exciting. + +(There's a poem in English that begins, "I wandered lonely as a cloud..." + But not otherwise relevant.) + +Now how to choose? +Heh heh ... +Okay, Tuomas, it's time for MORE CURSORS! + +This is where we need the operations +- cursor fork + (Specifying which hand, assuming you're using two.) + This creates a new cursor under the chosen hand, pointing at the + same place, switches to it. +- next-cursor-step + (Specifying which hand, assuming you're using two.) + This switches under the chosen hand to the next cursor in the cycle. +- cursor kill + (Specifying which hand, assuming you're using two.) + This annihilates the cursor under the chosen hand, + prob. goes *back* to previous cursor in the cycle. + +For some wild reason I think qaz (right) QAZ (left) would be + the correct respective keys for these functions. They're in a row + and out of the way. So-- +qQ - cursor fork +aA - next-cursor-step +zZ - cursor kill + +So let's say you have two cursors. Left is in the left cloud, + right is in the right cloud. You want to start cementing items + on the right. + +Do +q- makes a new cursor (and new color) on the right; +AA- switches the left hand to that cursor (since presumably + the list is left-right-new-(loop back to left) +aa- switches right hand back to right cursor + +Now you can move and cement items as I suggested above. + +When you want to go back to 2-cloud operation, you can + either kill the third cursor or switch from it. + +ChrzT +---------------------------------------------------------------------------- +u sez + +>> 1. As you said, click and type. I presume you're typing on a big 2D +>> space, and that Items aren't distinct till you end one? +> +>Sorry, the last sentence again? + +Sorry. +You're in mid-item. Item is on big virtual sheet of paper but began + somewhere other than at top of paper. Item becomes distinct + when you end it somehow, presumably beginning another item. + +>> 2. Ah, we haven't talked about how an item ends... I guess with same +>> "sever" mechanism, no?) +> +>Escape? + +Could do. In the ASCII charworld, backslash also good. + +Anyway, if it's one character, it's easily reconfigured. + However, I'd also like an alphanumeric sequence, ideally + (just my preference), +sp-!-sp + and that means some deeper recognizer, eh? + + + + + + + diff --git a/Documentation/wmlinc/art.css b/Documentation/wmlinc/art.css new file mode 100644 index 0000000..12f8ed4 --- /dev/null +++ b/Documentation/wmlinc/art.css @@ -0,0 +1,26 @@ + body { color: black; background: white; + margin-left: 15%; margin-right: 10%; + text-align: left; + font-size: medium; + } + h1 { margin-left: -15%;} + h2 { margin-left: -15%; margin-top: 2.0em; margin-bottom: 0.5em; } + h3 { margin-left: -7%; margin-top: 0.75em; margin-bottom: 0.5em; } + h4,h5 { margin-left: -0%; margin-top: 0.5em; margin-bottom: 0.25em; } + h1, h2, h3, h4, h5, p, ul { font-family: sans-serif; } + h1, h2, h3, h4, h5 { font-weight: bold; } + h1 { font-size: xx-large; } + h2 { font-size: xx-large; } + h3 { font-size: x-large; } + h4 { font-size: large; } + h5 { font-size: medium; } + dt { font-weight: bold; } + dfn { font-weight: bold; } + code { font-family: monospace; } + .figure { float: right; padding: 1em; padding-bottom: 0em; + border: 1pt solid black; margin-left: 1.5em; } + .figureimg { text-align: center; } + .abstract { width: 60%; text-align: center; } + .algorithm { font-family: serif; background: #00E0E0; margin-left: 1cm;} + span.red { color: red; background: white;} + span.green { color: green; background: white; } diff --git a/Documentation/wmlinc/article.wml b/Documentation/wmlinc/article.wml new file mode 100644 index 0000000..47a69a6 --- /dev/null +++ b/Documentation/wmlinc/article.wml @@ -0,0 +1,7 @@ +#include "common.wml" +#use wml::std::toc style=ol type=11111 + + + diff --git a/Documentation/wmlinc/catart.wml b/Documentation/wmlinc/catart.wml new file mode 100644 index 0000000..f75ec47 --- /dev/null +++ b/Documentation/wmlinc/catart.wml @@ -0,0 +1,56 @@ +#include "common.wml" + + + {#TITLE#: %body :##}

%body

+ +<: + @sectcounter = (0,0,0,0,0); + sub sectcounter_reset { + my $level = $_[0]; + while ($level <= $#sectcounter) { + $sectcounter[$level++] = 0; + } + } + sub sectnum { + my $level = $_[0]; + my $rv = ""; + while ($level >= 0) { + $rv = "$sectcounter[$level--]." . $rv; + } + return $rv; + } +:> + + <: $sectcounter[%0]++; sectcounter_reset(%0+1); + $num = sectnum(%0); :> + {#MYTOC#: <:= $num :> %body
:##} + ><:= $num :> %body> + print $num;:##} + /> /> +
+{#REF%0#} + +
%body
+
+ +
%body
+
+ +
%body
+
+ +
%body
+
+ +
%body
+
+ + + +{#TITLE#} + + + diff --git a/Documentation/wmlinc/common.wml b/Documentation/wmlinc/common.wml new file mode 100644 index 0000000..407a0e8 --- /dev/null +++ b/Documentation/wmlinc/common.wml @@ -0,0 +1,117 @@ + + + + + {: [[s/(?)(d\.+[-\w]+)/\1<\/code>/g]] + %body + :} + + + + + + + + %body + +/> + + + + %body + +/> + + + + + + +
+ +
+

+ + + + + + + + + + + + +
+ +
+

%body +

+
+ + + + +

Abstract

+

+ %body + + +

+ +You are reading an ugly version of this document that doesn't use CSS +to place floats nicely. Figures are shown in a very crude way. +Get Mozilla and see the other version - it's MUCH better. + + + />/> + + + + + +

+
+ +
+

+ %body +

+ + +
+ + +
+

Abstract

+

+ %body +

+
+ +

+ +Note that this document contains some formatting that is best rendered +using a true CSS1 standard-compliant browser such as Mozilla; however, +it should work reasonably well with any browser that can at least ignore +CSS that it doesn't understand. Unfortunately, Netscape Navigator 4.7, +for example, doesn't. Well, that's life... + +

+A non-CSS version exists: you can try by compiling this +document from its WML version with some switches.. (if you came here +through the WWW, there should be an alternate link on the referring +page. However, I like +the pretty rendering by Mozilla so much that that's still the default. + + /> +/> + +#use wml::std::grid +#use wml::fmt::isolatin diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..fa5d03f --- /dev/null +++ b/INSTALL @@ -0,0 +1,5 @@ +INSTALL +======= + +As described in README, this package contains several implementations, +which contain their own READMEs (and possibly INSTALL) files. diff --git a/Java/.gvimrc b/Java/.gvimrc new file mode 100644 index 0000000..75ce836 --- /dev/null +++ b/Java/.gvimrc @@ -0,0 +1,2 @@ +set cindent +set shiftwidth=4 diff --git a/Java/ApplitudeMgr.java b/Java/ApplitudeMgr.java new file mode 100644 index 0000000..54222da --- /dev/null +++ b/Java/ApplitudeMgr.java @@ -0,0 +1,310 @@ +/* +ApplitudeMgr.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ + +package org.gzigzag; +import java.awt.*; +import java.util.*; + +/** Routines related to applitude management. + * This handles registering and identification of applitudes. An applitude + * has a name and a number of params. Currently, the only used param is + * the View param, which is simply a view (as a ZOb). That ought to change + * into something more sophisticated...
+ * Applitudes are associated with dimensions. If a cell is connected on one + * of an applitude's dimensions, it is said to be "in" that applitude.
+ * XXX need to make this faster! + */ + +public class ApplitudeMgr { +public static final String rcsid = "$Id: ApplitudeMgr.java,v 1.10 2000/12/31 15:15:50 bfallenstein Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + private static ZZCell getDimCell(ZZCell c0) { + ZZSpace s = c0.getSpace(); + ZZCell c = ZZDefaultSpace.findOnClientlist(s, "Applitudes", false); + if(c == null) return putDefApps(s.getHomeCell()); + return c.getOrNewCell("d.1", 1); + } + + /** Get a list of all the applitudes a cell is in. + */ + static public ZZCell[] getApplitudes(ZZCell c) { + ZZCell d = getDimCell(c); + ZZCell app = null; + boolean added = false; + Vector v = new Vector(); + for(d = d.s("d.2"); d != null; d = d.s("d.2")) { + if(d.s("d.1") != null) { app = d.s("d.1"); added = false; } + if(!added && (c.s(d.t()) != null || c.s(d.t(), -1) != null)) { + v.addElement(app); + added = true; + } + } + + ZZCell[] res = new ZZCell[v.size()]; + for(int i=0; i + * If the bindings cursor doesn't exist, it is created. If no applitude + * is set or something else goes wrong, though, null is returned. + */ + static public ZZCell getAppBindsForWin(ZZCell win) { + ZZCell app = getWindowApp(win); + if(app == null) return null; + ZZCell binds = win.intersect("d.app-bind", 1, app, "d.clone", 1); + ZZCell c = null; + if(binds != null) c = ZZCursorReal.get(binds); + if(c != null) return c; + + // CREATE + c = ZZDefaultSpace.findInheritableParam(app.s("d.1"), "Bindings"); + if(c == null) return null; + c = c.s("d.1"); + if(c == null) return null; + if(binds == null) { + binds = app.zzclone(); + win.insert("d.app-bind", 1, binds); + } + ZZCursorReal.set(binds, c); + return c; + } + + static public void setAppBindsForWin(ZZCell win, ZZCell to) { + ZZCell app = getWindowApp(win); + if(app == null) { + ZZLogger.log("Argh: Tried to set app binds for win without app"); + return; + } + ZZCell curs = win.intersect("d.app-bind", 1, app, "d.clone", 1); + if(curs == null) { + curs = app.zzclone(); + win.insert("d.app-bind", 1, curs); + } + ZZCursorReal.set(curs, to); + } + + /** Move to next or previous applitude for this window. */ + static public void rotateWindowApp(ZZCell win, int dir) { + ZZCell app = getWindowApp(win); + if(dir < 0) { + app = app.s("d.2", -1); + if(app.s("d.2", -1) == null) app = app.h("d.2", 1); + } else { + if(app.s("d.2") != null) app = app.s("d.2"); + else app = app.h("d.2").s("d.2"); + } + setWindowApp(win, app); + pa("Set win "+win+" to app "+app); + } +} \ No newline at end of file diff --git a/Java/BuildInfo.java.in b/Java/BuildInfo.java.in new file mode 100644 index 0000000..5c4d11c --- /dev/null +++ b/Java/BuildInfo.java.in @@ -0,0 +1,39 @@ +/* -*- Java -*- */ +/* +BuildInfo.java.in + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ + +package org.gzigzag; + +// THE FILE BuildInfo.java IS AUTOGENERATED FROM BuildInfo.java.in. +// Modifications to BuildInfo.java are discarded + +/** A class generated at build time, to retain info about the build. + * Currently only a single string describing the build. + */ + +public final class BuildInfo { + // Don't edit the at signs, they're placeholders used in Makefile. + /** The build date, time and builder. + */ + public static final String info = "@@@@@"; +} diff --git a/Java/ChkVersion.java b/Java/ChkVersion.java new file mode 100644 index 0000000..3dd818d --- /dev/null +++ b/Java/ChkVersion.java @@ -0,0 +1,94 @@ +/* +Main.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + + +package org.gzigzag; + +import java.lang.reflect.*; + +/** A simple class that prints the RCSIds for a number of ZZ classes. + * Eventually this'll go to the structure but for now, this is a simple + * enough way to make sure what someone is actually running. + */ + +public class ChkVersion { +public static final String rcsid = "$Id: ChkVersion.java,v 1.5 2000/09/19 10:31:58 ajk Exp $"; + + + static final String[] classes = new String[] { + "ZZCell", + "ZZCellScroll", + "ZZDefaultSpace", + "ZZError", + "ZZSimpleClient2", + "ZZApplet", + "ZZ2DBlob", + "ZZ2DCanvas", + "ZZ2DCanvasRaster", + "ZZ2DCanvasView", + "ZZViewComponent", + "ZZAbstractView", + "ZZCellRenderer", + "ZZCellRenderer1", + "ZZCompound", + "ZZSpace", + "ZZEventQueue", + "ZZExec", + "ZZGlobal", + "ZZHash", + "ZZKeyBindings", + "ZZKeyBindings1", + "ZZLinkRenderer", + "ZZLinkRenderer1", + "ZZList", + "ZZLocal", + "ZZPath", + "ZZPhotoView", + "ZZRemote", + "ZZSingleCellView", + "ZZTextView", + "ZZTraverseCB", + "ZZXML1", + "ZZUpdateManager" + }; + + + static final void p(String s) { System.out.println(s); } + public static void main(String argv[]) { + p("GZigZag checkversion --- my own id: "+rcsid); + p("Main id: "+Main.rcsid); + for(int i=0; iaction
to provide functionality to an + * option. + * + * @see HelpOption + */ + public static class Option { + /** The name of this option. A dash will be automatically + * appended to this name to produce the string that is matched + * against in command line. */ + public final String name; + + /** A list of argument names for this option. The option will + * take as many mandatory arguments as there are elements in + * this array. The names of the arguments are purely + * documentary and are used in help screens. + * + * @see org.gzigzag.CommandLineOptionsParser.HelpOption + */ + public final String[] argNames; + + /** A help text for this option. The text will be + * word-wrapped; newlines embedded in the text are + * honoured. + * + * @see org.gzigzag.CommandLineOptionsParser.HelpOption + */ + public final String helpText; + + /** The action for this option. This method will be invoked + * when this option is noticed. + * + * @param clop The instance of + * CommandLineOptionsParser that is running this + * parse. + * @param args The arguments given on the command line to this + * option. This array will have exactly as many elements as + * the argNames attribute. + */ + public void action(CommandLineOptionsParser clop, String[] args) {} + + /** Constructs an option. + * + * @param name The value to be given to the name + * attribute. + * @param argNames The value to be given to the + * argNames attribute. + * @param helpText The value to be given to the + * helpText attribute. + */ + public Option(String name, String[] argNames, String helpText) { + this.name = name; + this.argNames = argNames; + this.helpText = helpText; + } + } + + /** A command-line option for showing help about command-line + * options. */ + public static class HelpOption extends Option { + /** Constructs a HelpOption. + * @param name The name for this option (a dash will be + * automatically prepended to create the string that is + * matched against the command line). + * @param helpText The help text for this option. This text + * will be word-wrapped. Embedded newlines are honoured. + * @param exitAfter Should the program be exited after showing + * the help? + * @param prologue Text to be shown before the list of + * options. This text will be word-wrapped. Embedded + * newlines are honoured. + * @param epilogue Text to be shown before the list of + * options. This text will be word-wrapped. Embedded + * newlines are honoured. + */ + public HelpOption(String name, String helpText, boolean exitAfter, + String prologue, String epilogue) { + super(name, new String[0], helpText); + this.exitAfter = exitAfter; + this.prologue = prologue; + this.epilogue = epilogue; + } + + public void action(CommandLineOptionsParser clop, String[] args) { + int rightmargin = 75; + System.out.println(breakToLines(prologue, rightmargin, 0)); + for (Enumeration e = clop.options_in_order.elements(); + e.hasMoreElements();) { + Option opt = (Option)e.nextElement(); + int expltab = 15; + int nametab = 3; + int seplen = 2; + String help = breakToLines(opt.helpText, rightmargin, + expltab + nametab + seplen); + String name = "-" + opt.name; + for (int i = 0; i < opt.argNames.length; i++) { + name += " " + opt.argNames[i]; + } + if (name.length() > expltab) { + help = spaces(nametab) + name + '\n' + help; + } else { + help = spaces(nametab) + name + + spaces(seplen + expltab - name.length()) + + help.substring(expltab + nametab + seplen); + } + System.out.println(help); + } + System.out.println(breakToLines(epilogue, rightmargin, 0)); + if (exitAfter) SafeExit.exit(0); + } + + private String spaces(int n) { + StringBuffer sb = new StringBuffer(n); + for (int i = 0; i < n; i++) sb.append(' '); + return new String(sb); + } + + private int breakpoint(String s, int start, int maxlen) { + if (s.length() - start < maxlen) return s.length(); + int bp = start + maxlen < s.length() ? start + maxlen : s.length(); + for (int i = 0; i < maxlen && i + start < s.length(); i++) { + int c = s.charAt(start + i); + if (c == '\n') return start + i; + if (c == '\t' || c == ' ') bp = start + i; + } + return bp; + } + + private String breakToLines(String s, int rmargin, int indent) { + int maxlen = rmargin - indent; + StringBuffer sb = new StringBuffer(); + String ind = spaces(indent); + int a = 0; + while (a < s.length()) { + int b = breakpoint(s, a, maxlen); + sb.append(ind); + sb.append(s.substring(a, b)); + sb.append('\n'); + if (b < s.length() && + (s.charAt(b) == '\n' + || s.charAt(b) == ' ' + || s.charAt(b) == '\t')) { + ++b; + } + a = b; + } + return new String(sb); + } + + private final boolean exitAfter; + private final String prologue; + private final String epilogue; + } + + /** Constructs a command line options parser. + * @param options An array of preconstructed options. + * @see #put(Option) + */ + public CommandLineOptionsParser(Option[] options) { + for (int i = 0; i < options.length; i++) { + put(options[i]); + } + } + + /** Constructs a command line options parser with an initially + * empty set of acceptable options. */ + public CommandLineOptionsParser() {} + + /** Adds option to the list of valid options. */ + public void put(Option option) { + options.put(option.name, option); + options_in_order.addElement(option); + } + + /** Adds a new option to the list of valid options. The option + * object will be a new instance of class Option. + * The arguments of this method are passed unchanged to the + * constructor. + * @see Option + */ + public void put(String name, String[] argNames, String helpText) { + put(new Option(name, argNames, helpText)); + } + + /** Adds a help option to the list of valid options. The option + * object will be a new instance of HelpOption. The + * arguments of this method are passed unchanged to the + * constructor. + * @see HelpOption + */ + public void putHelp(String name, String helpText, boolean exitAfter, + String prologue, String epilogue) { + put(new HelpOption(name, helpText, exitAfter, prologue, epilogue)); + } + + /** Marks all options unseen. */ + public void clearArgs() { + optargs = new Hashtable(); + } + + /** Gets the list of arguments for the option specified. + * @param name The name of the option whose arguments are to be returned. + * @return null, if the option has not been seen, otherwise the + * same array or a copy of the same array that the + * action method of Option gets. + */ + public String[] getArgs(String name) { + Object o = optargs.get(name); + if (o == null) return null; + return (String[]) o; + } + + /** Gets a specific argument for the option specified. + * @param name The name of the option whose argument is to be + * returned + * @param i The ordinal number of the argument to be returned (0 + * for the first argument, 1 for the second and so on) + * @return null, if the option has not seen, otherwise the + * ith (0-based) argument to the option. + */ + public String getArg(String name, int i) { + return getArg(name, i, null); + } + + /** Gets a specific argument for the option specified. + * @param name The name of the option whose argument is to be + * returned + * @param i The ordinal number of the argument to be returned (0 + * for the first argument, 1 for the second and so on) + * @param deflt The object to be returned if the option has not + * been seen. + * @return deflt, if the option has not seen, otherwise the + * ith (0-based) argument to the option. + */ + public String getArg(String name, int i, String deflt) { + String[] args = getArgs(name); + if (args == null) return deflt; + return args[i]; + } + + /** Determines whether the specified option was seen in parses + * since the arguments were last cleared. */ + public boolean seen(String name) { + return optargs.containsKey(name); + } + + /** Parse command-line options from args and return the first + * index to attrs that is not an option, or attrs.length if there + * are none such . */ + public int parse(String[] args) { + int i; + for (i = 0; i < args.length; i++) { + if (args[i].length() == 0 || args[i].charAt(0) != '-') { + return i; + } + + if (!options.containsKey(args[i].substring(1))) { + throw new SyntaxError("unknown option: " + args[i]); + } + + Option opt = (Option)options.get(args[i].substring(1)); + String[] oargs = new String[opt.argNames.length]; + for (int j = 0; j < oargs.length; j++) { + ++i; + if (i >= args.length) { + throw new SyntaxError("too few arguments to option: -" + opt.name); + } + oargs[j] = args[i]; + } + optargs.put(opt.name, oargs); + opt.action(this, oargs); + } + return i; + } + + private Hashtable options = new Hashtable(); + private Vector options_in_order = new Vector(); + + private Hashtable optargs = new Hashtable(); + + +} diff --git a/Java/Dump.java b/Java/Dump.java new file mode 100644 index 0000000..c16c239 --- /dev/null +++ b/Java/Dump.java @@ -0,0 +1,242 @@ +/* +Dump.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ + +package org.gzigzag; +import java.util.*; +import java.io.*; + +/** A class to dump part of a zzspace in a cvsable way. + * XXX sort for id when dumping! (elsewise, cvs won't be usable) + * XXX make spans work correctly + * XXX make work for dumping + */ + +public class Dump { +public static final String rcsid = "$Id: Dump.java,v 1.3 2000/12/24 13:54:20 bfallenstein Exp $"; + public static final boolean dbg = true; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + static final int fmtversion = 2; // Version of Dump format + + /** Retrieve and check id for cell. + * IDs must either be numbers (given as Strings XXX should use Integer?) + * or correct Java identifiers. + */ + private static String id(ZZCell c, Hashtable ids) { + String s = (String)ids.get(c); + if(s.length() == 0) throw new ZZError("Empty Dump cell id"); + // Check if it's a number; if not, the exception is thrown + try { + Integer.parseInt(s); + } catch(NumberFormatException e) { + // Not a number. Now, test if it's a valid Java identifier. + if(!Character.isJavaIdentifierStart(s.charAt(0))) + throw new ZZError("Bad Dump cell id: '"+s+"'"); + for(int i=1; ibetween them on + * the dimensions given, exclusively. + * @param ids A hashtable mapping cells to ids. This must contain an entry + * for every cell in cells[], and there may not be any entry + * for a cell not in cells[]. + */ + public static void writeDump(ZZCell[] cells, String[] dims, + Hashtable ids, int nextid, String title, + Writer writer) { + PrintWriter w = new PrintWriter(writer); + w.println("HEADER"); w.println(); + w.println("Format: Dump "+fmtversion); + w.println("Title: "+title); + w.println("rcsid: $Id: Dump.java,v 1.3 2000/12/24 13:54:20 bfallenstein Exp $"); + if(nextid >= 0) w.println("Next free ID: "+nextid); + + w.println(); w.println(); + w.println("CONTENTS"); w.println(); + for(int i=0; i 0) { + ZZCell c1 = (ZZCell)todo.elementAt(0); + todo.removeElementAt(0); + + for(int i=0; i + *

  • A subspace (SP) has a handle cell (HC). + *
  • The HC is connected to a cell of the subspace on +d.dump-conn + *
  • The HC contains the SP file name. + *
  • Connected to the HC on +d.2 is a rank with dim names; only these dims + * are saved to the SP file. + *
  • After loading, every cell in the SP has a connection on +d.dump-id. The + * id found in that cell is a Java identifier for the cell. + *
  • Connected to the HC on +d.dump-nextid is the next free numeric id for + * SP cells (if not present, assumed to be 1). When dumping, this is used + * to create ids for cells without +d.dump-id connections; the number is + * prepended with a 'c' in that case to make it a valid Java identifier. + * + * Dump IDs may be changed to something more meaningful. When a java class + * is created from the dump by dump2java.pl, they are instance variables. + */ + +public class Dumper { +public static final String rcsid = "$Id: Dumper.java,v 1.2 2000/12/22 22:44:34 bfallenstein Exp $"; + public static final boolean dbg = true; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + static public void create(ZZCell from) { + ZZCell hdl = from.N("d.1"); + hdl.setText("MyDump"); + hdl.N("d.dump-nextid").setText("2"); + hdl.N("d.2").setText("d.3"); + hdl.N("d.2").setText("d.2"); + hdl.N("d.2").setText("d.1"); + ZZCell c1 = hdl.N("d.dump-conn"); + c1.N("d.dump-id").setText("1"); + } + + static public void write(ZZCell hdl, Writer writer) { + String title = hdl.t(); + ZZCell[] dcs = hdl.readRank("d.2", 1, false); + String[] dims = new String[dcs.length]; + for(int i=0; i 0) hdl.N("d.dump-nextid").setText(""+r.nextid); + else hdl.N("d.dump-nextid").setText("1"); + + for(int i=0; i=0; i--) + hdl.N("d.2").setText(r.dims[i]); + + if(r.cells.length > 0) + hdl.connect("d.dump-conn", 1, r.cells[0]); // save start cell! + else + ZZLogger.log("Strange: Dump without cells..."); + } + + static public ZZModule module = new ZZModule() { + public void action(String id, + ZZCell code, + ZZCell target, + ZZView view, ZZView cview, String key, Point pt, ZZScene xi) { + if(id.equals("Dump")) + write(target, new OutputStreamWriter(System.out)); + else if(id.equals("Write")) { + try { + write(target, new FileWriter(target.t()+".zzd")); + ZZLogger.log("Successfully written dump: "+target.t()); + } catch(IOException e) { ZZLogger.exc(e); } + } else if(id.equals("Read")) { + try { + read(target, new FileReader(target.t()+".zzd")); + } catch(FileNotFoundException e) { ZZLogger.exc(e); } + } else if(id.equals("Create")) create(target); + else if(id.equals("Enter")) { + ZZCell vc = view.getViewcell(); + ZZCell to = ZZCursorReal.get(vc).s("d.dump-conn"); + if(to != null) ZZCursorReal.set(vc, to); + } else if(id.equals("ChangeID")) { + ZZCell vc = view.getViewcell(); + ZZCell acc = ZZCursorReal.get(vc); + ZZCell to = acc.s("d.dump-id"); + if(to == null) to = acc.h("d.dump-id", true); + if(to == null) to = acc.N("d.dump-id"); + ZZCursorReal.set(vc, to); + } + } + + public ZOb newZOb(String id) { + return null; + } + }; +} \ No newline at end of file diff --git a/Java/JEv.java b/Java/JEv.java new file mode 100644 index 0000000..71dbf0e --- /dev/null +++ b/Java/JEv.java @@ -0,0 +1,73 @@ +/* +JEv.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.awt.*; +import java.awt.event.*; + +/** A program to simply print out events as they come. + * The point is to see what keyboard events actually contain on + * different platforms. + */ + +public class JEv { + public static void l(KeyEvent e) { + System.out.println(e); + System.out.println("Txt: \""+e.getKeyText(e.getKeyCode())+"\"\n"); + } + public static void l(MouseEvent e) { + System.out.println(e); + System.out.println("Mouse: "+e.getModifiers()); + } + + public static void main(String[] argv) { + Frame f = new Frame(); + f.setSize(300,300); + f.show(); + f.addKeyListener(new KeyListener() { + public void keyTyped(KeyEvent e) { l(e); } + public void keyPressed(KeyEvent e) { l(e); } + public void keyReleased(KeyEvent e) { l(e); } + }); + f.addMouseMotionListener(new MouseMotionListener() { + public void mouseDragged(MouseEvent e) { l(e); } + public void mouseMoved(MouseEvent e) { l(e); } + }); + f.addMouseListener(new MouseListener() { + public void mouseClicked(MouseEvent e) { l(e); } + public void mousePressed(MouseEvent e) { l(e); } + public void mouseReleased(MouseEvent e) { l(e); } + public void mouseEntered(MouseEvent e) { l(e); } + public void mouseExited(MouseEvent e) { l(e); } + }); + + + + while(true) { + try { Thread.sleep(1000); } + catch(Exception e) { + ZZLogger.exc(e); + } + System.out.println("------"); + } + } +} diff --git a/Java/LoopDetector.java b/Java/LoopDetector.java new file mode 100644 index 0000000..ac17210 --- /dev/null +++ b/Java/LoopDetector.java @@ -0,0 +1,66 @@ +/* +LoopDetector.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** A loop detector. + * Uses a simple constant-space algorithm that will detect any loop before + * it's cycled through 3 times, except very small loops. + * Example use: + *
    + * 	LoopDetector l = new LoopDetector();
    + *	while((x = iter(x)) != null) {
    + *		l.detect(x);
    + *		// ... do something with x.
    + *	}
    + * 
    + * Note: this only works for deterministic loops that always have the same + * elements and length. + *

    + * The Object.equals method is used for the comparisons. + */ + +public final class LoopDetector { +public static final String rcsid = "$Id: LoopDetector.java,v 1.6 2000/11/02 13:03:08 tjl Exp $"; + Object obj = this; + int count = 0; + int nth = 10; + public void reset() { count = 0; obj = null; } + /** Throws an error if the parameter is a part of a looping sequence. + */ + public void detect(Object o) { + if(isLooping(o)) + throw new ZZInfiniteLoop("Infinite loop detected"); + } + /** Returns true if the parameter is a part of a looping sequence. + */ + public boolean isLooping(Object o) { + if(o.equals(obj)) return true; + if(count-- < 0) { + nth *= 2; + count = nth; + obj = o; + } + return false; + } +} diff --git a/Java/Main.java b/Java/Main.java new file mode 100644 index 0000000..8f81d68 --- /dev/null +++ b/Java/Main.java @@ -0,0 +1,535 @@ +/* +Main.java + * + * Copyright (c) 1999, 2000 Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka, version control by Tuukka Hastrup, + * space locking by Antti-Juhani Kaijanaho. + */ + +package org.gzigzag; + +import org.gzigzag.*; +import java.awt.*; +import java.util.*; +import java.io.*; +import java.lang.reflect.*; + +/** The class to run to start the ZZ client. + * This class parses the command line, prepares the space and starts the + * client. If needed, a new client space with default settings is created. + * + * The one obligatory argument to give this program is the name of the file + * to use for the cellscroll of the main space. + * Additionally, the following options can be given. + *

    + *
    -new + *
    Recreate the default client space starting from + * the main cell. This is important if the internal + * client structures used by GZigZag have changed since + * the space was created, or if this is a new space. + * If the cellscroll file given does not exist, + * this is the default. + * If the file already exists, the old system list + * and the list on d.2 down from the home cell + * are placed on the d.2 list, at a cell named + * OldSysList (see ZZDefaultSpace). + *
    -convert + *
    Convert an old, incompatible, space to compatible form. + * When conversion is needed, it will be told by the + * program. Taking backup before conversion is + * recommended. After conversion you might need to use + * new and dcold to catch up with + * configuration changes. + *
    -import XMLfile + *
    When creating a new space, you can import an XML + * file describing the space. + *
    -export XMLfile + *
    Export the whole space to the specified file + *
    -recrmdim +
    Recreate master dimension list from data on disk. + *
    -dbg classname + *
    Turn on debugging in the given class. For developers + * only. + *
    -pda + *
    Run in PDA-mode. + *
    -span + *
    Save information about cells whose spans overlap. + * This may be slow at the moment, but is necessary + * to show e.g. the overlaps of two nile text streams. + *
    -ztpserv PORT + *
    Invoke the ZTP server code instead of the ZZ client code. + * Listen on the TCP port PORT for incoming connections. + *
    -dump + *
    Dump the space to the file CELLSCROLLFILE.dmp (where + * CELLSCROLLFILE is the name of the space file). + * + *
    -slurp FILENAME + *
    Slurp the space from the file called FILENAME. + *
    -versioneddims + *
    Show connections from old versions along regular dimensions + * in addition to the special version: dimensions. + * + *
    + *

    + * Some Filenames that start with ':' are special. For example, + * ':DS' starts with the ZZDimSpace instead of normal persistent space. + * You should probably only use these if you are hacking the core. + *

    + * Example: + *

    + * 	java foo.Main -new /tmp/foo
    + * 
    + * opens the cellscroll at /tmp/foo and creates the new client structure. + * XXX Make a good system for specifying the type. + *

    + * Currently, if you give extra arguments after the file name, the system + * creates a ZZSlicedDimSpace instead. + * BE VERY CAREFUL WITH THIS! Once you put some slices there with a given + * root space, never leave them out or confusion will result. + * This feature should NOT be used if you're not prepared to hack the + * storage/*Slice* code. + */ + +public class Main { +public static final String rcsid = "$Id: Main.java,v 1.70 2001/03/29 13:06:07 ajk Exp $"; + public static final boolean dbg = true; + public static int zzclientversion = 2; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + /** For storing the classes whose debug prints are turned on. + * Otherwise they might get garbage collected and debugging not + * stay turned on. + */ + static Vector dbgclasses = new Vector(); + + /** Make this class print debug info. + * Any callers from outside Main must provide their own Vector + * to put the class objects in in order to avoid garbage collection. + */ + public static void debugClass(String name, Vector into) { + try { + p("Turning on debugging for class "+name); + Class clazz = Class.forName("org.gzigzag."+name); + Field f = clazz.getField("dbg"); + f.setBoolean(null, true); + into.addElement(clazz); + into.addElement(f); + } catch(Exception e) { + e.printStackTrace(); + pa(""+e); + throw new Error("Error while turning on debug info"); + } + } + + + public static void main(String argv[]) { + + pa("Starting gZigZag client, build: "+BuildInfo.info); + pa("Clientspace version used by program is "+zzclientversion+"."); + try { + Class primact = Class.forName("org.gzigzag.ZZPrimitiveActions"); + // *** Parse command line + + if(argv.length < 1) { + System.err.println("No filename given"); + SafeExit.exit(1); + } + CommandLineOptionsParser clop = new CommandLineOptionsParser(); + String[] noargs = new String[0]; + clop.put("pda", noargs, "run in PDA mode"); + clop.put("new", noargs, + "Recreate the default client space " + + "starting from the main cell. This " + + "is important if the internal client " + + "structures used by GZigZag have changed " + + "since the space was created, or if this " + + "is a new space. If the cellscroll file " + + "given does not exist, this is the default. " + + "If the file already exists, the old system " + + "list and the list on d.2 down from the home " + + "cell are placed on the d.2 list, at a cell " + + "named OldSysList (see ZZDefaultSpace)."); + clop.put("import", new String[] { "XMLFILE" }, + "When creating a new space, you can import an XML " + + "file describing the space."); + clop.put("export", new String[] { "XMLFILE" }, + "Export the whole space to the specified file"); + clop.put("convert", noargs, + "Convert an old, incompatible, space to compatible " + + "form. When conversion is needed, it will be " + + "told by the program. Taking backup before " + + "conversion is recommended. After conversion you " + + "might need to use -new and -dcold to catch up " + + "with configuration changes."); + clop.put("xmlencoding", new String[] { "ENCODING" }, + "Specify the character encoding used by the " + + "XML export function."); + clop.put("ztpserv", new String[] { "PORT" }, + "Invoke the ZTP server code instead of the ZZ " + + "client code. Listen on the TCP port PORT for " + + "incoming connections."); + clop.put("recrmdim", noargs, + "Recreate master dimension list from data on disk."); + clop.put("foolconvert", noargs, "???"); + clop.put("textlog", noargs, "???"); + clop.put("verboselog", noargs, "???"); + clop.put("span", noargs, "Save information about cells whose " + + "spans overlap. This may be slow at the moment, " + + "but is necessary to show e.g. the overlaps of " + + "two nile text streams."); + clop.put("dump", noargs, "Dump the space to the file " + + "CELLSCROLLFILE.dmp (where CELLSCROLLFILE is the " + + "name of the space file)."); + clop.put("slurp", new String[] { "FILENAME" }, + "Slurp the space from the file called FILENAME."); + clop.put("versioneddims", noargs, + "Show connections from old versions along regular " + + "dimensions in addition to the special version: " + + "dimensions."); + clop.put(new CommandLineOptionsParser.Option("dbg", new String[] { "CLASSNAME" }, + "Turn on debugging " + + "in the given " + + "class. For " + + "developers only.") { + public void action(CommandLineOptionsParser clops, + String[] args) { + debugClass(args[0], dbgclasses); + } + + }); + clop.putHelp("help", "shows this help screen", true, + "Usage:\nGZigZag takes one mandatory parameter: the name " + + "of the directory where the space is (to be) stored. " + + "Additionally, one or more of the following options " + + "may be specified before the directory name.", + ""); + int cur = clop.parse(argv); + + // Since local classes cannot modify these, we have to do + // this ugly thing... + boolean newspace=clop.seen("new"); // New client space? + boolean textlog=clop.seen("textlog"); + boolean verboselog=clop.seen("verboselog"); + boolean pda=clop.seen("pda"); + boolean span=clop.seen("span"); // Use a SpanSet to find overlapping spans? + boolean ztpserv=clop.seen("ztpserv"); + boolean dump=clop.seen("dump"); + String slurpf=clop.getArg("slurp", 0); + int ztpport=Integer.parseInt(clop.getArg("ztpserv", 0, "0")); + + boolean recreateMasterDimList=clop.seen("recrmdim"); + boolean convert=clop.seen("convert"); // Convert client space version? + boolean foolconvert=clop.seen("foolconvert"); + String importFile=clop.getArg("import", 0, ""); // If nonempty, it'll be imported + String exportFile=clop.getArg("export", 0, ""); // If nonempty, we'll export + String encoding = clop.getArg("xmlencoding", 0, "UTF-8"); // for exporting + clop = null; // we no longer need it, throw it away + + if ( argv[cur].startsWith("-") ){ + // we don't want filenames to look like args + System.err.println("Unknown arg "+argv[cur]); + cur++; + //SafeExit.exit(1); + } + + if(argv.length < cur+1) { + System.err.println("No filename given"); + SafeExit.exit(1); + } + + if(textlog) { + ZZPrimitiveActions.textlog = + new PrintWriter(new FileOutputStream( + argv[cur] + ".txt", true)); + } + + if(verboselog) { + ZZLogger.logfile = + new PrintWriter(new FileOutputStream(argv[cur] + ".log", true)); + + } + + // *** Prepare the space: create ZZSpace objects + + System.runFinalizersOnExit(true); // needed for unlocking a space + + String[] slices = null; + + ZZSpace space; + + if(argv[cur].equals(":DS")) { + space = new ZZDimSpace(); + newspace = true; + } else { // Space stored in file + File f = new File(argv[cur]); + if(!f.exists()) newspace = true; + if(argv.length > cur+1) { + System.err.println("SLICE TEST MODE!!!!!"); + slices = new String[argv.length-(cur+1)]; + System.arraycopy(argv, cur+1, slices, 0, + argv.length-(cur+1)); + } + space = new ZZCacheDimSpace(new DirStreamSet(f)); + if(span) ((ZZDimSpace)space).spanset = new SpanTree(); + } + + // And now we switch spaces if there are slices. + if(slices != null) { + throw new ZZError("slices are broken"); + //ZZDimSpace[] ss = new ZZDimSpace[slices.length+1]; + //ss[0] = (ZZDimSpace)space; + //for(int i=0; i 0) { + ZZLogger.tryInitSyslog(); + try { + Class ztpcl = Class.forName("org.gzigzag.module.ZTPserver"); + Constructor ztpcons = ztpcl.getConstructor(new Class[] { + Class.forName("org.gzigzag.ZZSpace"), + Class.forName("java.lang.Integer")}); + Object ztp = ztpcons.newInstance(new Object[] { space, new Integer(ztpport) }); + p("main exiting - waiting for connections"); + } catch (ClassNotFoundException e) { + ZZLogger.exc(e); + } + return; + } + + if (recreateMasterDimList) { + space.recreateMasterDimList(); + space.commit(); + } + + if(newspace && !importFile.equals("")) { + // XXX should be "if a space with only the home cell" + // NOTE: Introspection is used so that there will not + // be a compile-time dependency on the XML module. + Object xml = (Class.forName("org.gzigzag.module.XML").newInstance()); + Method get = xml.getClass().getMethod("load", new Class[] {Class.forName("java.io.File"), Class.forName("org.gzigzag.ZZCell")}); + get.invoke(xml, new Object[] {new File(importFile), space.getHomeCell()}); + space.commit(); + newspace = false; // It's old then + } + if(!exportFile.equals("")) { + // NOTE: Introspection is used so that there will not + // be a compile-time dependency on the XML module. + Object xml = (Class.forName("org.gzigzag.module.XML").newInstance()); + Method get = xml.getClass().getMethod("export", new Class[] {Class.forName("java.io.File"), Class.forName("org.gzigzag.ZZSpace"), Class.forName("java.lang.String")}); + p("Invoke: "+get+" "+xml); + get.invoke(xml, new Object[] {new File(exportFile), space, encoding}); + p("File exported - exiting."); + SafeExit.exit(0); + } + + // *** Prepare client space and check version + + // Ted asked for this kind of an announcement + if(newspace) { + System.err.println("Creating or recreating the system part of the space"); + } + ZZCell home = space.getHomeCell(); + if(newspace) { + ZZDefaultSpace.create(space.getHomeCell()); + } + if (newspace) { // Might be re-init + home.getOrNewCell("d.gzz-space-version", 1) + .setText(""+zzclientversion); + } else { + ZZCell vercell = home.s("d.gzz-space-version",1); + if(vercell==null) { + pa("Version cell not found: setting version to zero."); + vercell = home.N("d.gzz-space-version", 1); + vercell.setText("0"); + } + pa("Clientspace versionstring: '"+vercell.getText()+"'"); + int fileversion; + try { + fileversion = Integer.parseInt(vercell.getText()); + } catch (NumberFormatException e) { + fileversion = 0; + } + + pa("Clientspace version in prepared space is "+fileversion+"."); + if(fileversion > zzclientversion) + quit("Can't use files from clients that new. " + + "Please upgrade client."); + if(fileversion < zzclientversion && !convert) + quit("Files from older client. Please use " + + "option -convert after backing up the file."); + if(convert && !foolconvert) { + if(fileversion == zzclientversion) + quit("File is already of same version."); + convert(fileversion, zzclientversion, space); + vercell.setText(""+zzclientversion); + vercell.getSpace().commit(); + SafeExit.exit(0); + } + } + + /* // Print all cells + ZZCell i; + p("Cells:"); + for(Enumeration e=space.cells();e.hasMoreElements();) + { + i=(ZZCell)e.nextElement(); + p(i.getID()+": "+i.getText()); + }*/ + + // Print all dimensions + String[] dims = space.dims(); + p("Dimensions: ("+dims.length+")"); + for(int s=0;s BuildInfo.java.new && mv BuildInfo.java.new BuildInfo.java + $(JAVAC) -deprecation $(DEBUG) -d . BuildInfo.java + $(JAVAC) -deprecation $(DEBUG) -d . $(SRC) + $(archcompile) + +# If you want to try out the opengl stuff +opengl: + @echo "********************************************" + @echo "* requires gltt !! *" + @echo "* add ../Modules/openGL to LD_LIBRARY_PATH *" + @echo "********************************************" + (cd ../Modules/openGL; make) + $(JAVAC) -deprecation $(DEBUG) -d . ../Modules/openGL/*.java + +doc:: $(SRC) + sh ./make-src-tree.sh $(TEMP)/zzsrc + rm -Rf doc + mkdir doc + javadoc $(JAVADOCOPTS) -d doc -sourcepath $(TEMP)/zzsrc org.gzigzag \ + org.gzigzag.clang \ + org.gzigzag.module + rm -Rf $(TEMP)/zzsrc + +zobdoc:: $(SRC) + sh ./make-src-tree.sh $(TEMP)/zzsrc + rm -Rf zobdoc + mkdir zobdoc + javadoc -doclet org.gzigzag.ZobDoc -d zobdoc \ + -sourcepath $(TEMP)/zzsrc \ + org.gzigzag org.gzigzag.clang org.gzigzag.module + rm -Rf $(TEMP)/zzsrc + + +# perl -pi.bak -e's||"".`cat Package.html`|e' doc/Package-org.gzigzag.html + +MODULESUPPORT=no +JARMODULES=applet mbox joystick test 3d xml extern prez \ + textcloud daytimedemo hypergenealogy nile notemap zaubertrank mind +JARARCHES= +JARNAME=gzigzag.jar +jar: buildir=$(JARNAME).build +jar: + cd .. && ./makedist.sh Java/$(buildir) + -$(MAKE) -C $(buildir)/Java ARCH="$(JARARCHES)" MODULES="$(JARMODULES)" all + -$(MAKE) -C $(buildir)/Java MODULES="$(JARMODULES)" allRCH="$(JARARCHES)" + -$(MAKE) -C $(buildir)/Java ARCH="$(JARARCHES)" MODULES="$(JARMODULES)" all + $(MAKE) -C $(buildir)/Java ARCH="$(JARARCHES)" MODULES="$(JARMODULES)" all + echo 'Main-Class: org.gzigzag.Main' > $(buildir)/Java/manifest + set -e ; if [ "$(MODULESUPPORT)" != "no" ] ; \ + then \ + (cd $(buildir)/Java && jar -xvf $(MODULESUPPORT) gnu org) ;\ + fi + cd $(buildir)/Java && cp ../LICENSE.lgpl ../LICENSE.xpl . + cd $(buildir)/Java && cp ../README README.source + cd $(buildir)/Java && jar cvfm $(JARNAME) manifest fi foo xanadu gnu org README README.source LICENSE* + mv $(buildir)/Java/$(JARNAME) . + rm -rf $(buildir) + + +mvdoc: doc + scp -r doc/* tjl@gzigzag.sourceforge.net:/home/groups/gzigzag/www/javadoc/ + +%.java: %.pl + perl $< $@ + +clean: + rm -rf fi foo xanadu org + rm -f $(AUTOGENERATED) + rm -f BuildInfo.java clang/ZZClangOps.java + $(archclean) + +tags: $(SRC) + ctags $(SRC) + +CVS2CL=cvs2cl + +ChangeLog:: + $(MAKE) -C .. ChangeLog + +ncss:: $(SRC) + $(JAVANCSS) -function $(SRC) | perl mungencss.pl | \ + sort -rnk3 -k1 >ncss-ccn + sort -rnk2 -k1 ncss-ncss + sort -rnk4 -k1 ncss-jvdc +# $(JAVANCSS) -all $(SRC) >ncss + + + diff --git a/Java/NullZOb.java b/Java/NullZOb.java new file mode 100644 index 0000000..5817d18 --- /dev/null +++ b/Java/NullZOb.java @@ -0,0 +1,40 @@ +/* +NullZOb.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.awt.*; +import java.util.*; +import java.io.*; + +/** An extension module implementing some Java functionality. + * Extension module classes should have a single static public member + * named module of this type. + *

    + * Clang commands implemented in extension modules are accessed + * through the Module.FUNCTION interface. + */ + +public class NullZOb implements ZOb { +String rcsid = "$Id: NullZOb.java,v 1.3 2000/09/19 10:31:58 ajk Exp $"; + public void setComponent(Component c) {} + public String readParams(ZZCell c) { return null; } +} diff --git a/Java/Package.html b/Java/Package.html new file mode 100644 index 0000000..939be7a --- /dev/null +++ b/Java/Package.html @@ -0,0 +1,9 @@ + +This package (name will probably change later) is the current home +of the GZigZag Java classes. +

    +Start from ZZCell, ZZEdit and ZZObs. +

    +Not all the documentation is there yet but this is constantly being +upgraded. Some of the classes are deprecated and most that are are +marked so. These will be removed soon. diff --git a/Java/README b/Java/README new file mode 100644 index 0000000..c5da2ea --- /dev/null +++ b/Java/README @@ -0,0 +1,146 @@ +General +======= + +Contact Tuomas Lukka at lukka@iki.fi if you want to help hack on this. + +Start the Java GZigzag through the org.gzigzag.Main class, e.g. + + java org.gzigzag.Main [options] cellscrollfile + +where the options are detailed in the javadoc for org.gzigzag.Main. + +IF IT IS TOO SLOW, CHECK THE FAQ (../Documentation/FAQ), question +II.1.5 TO GET HELP AT STARTUP, SEE ../Documentation/STARTING. There +is a quick-hack user's guide in ../Documentation/UsersGuide/ . + +Note that org.gzizgag.Main opens up two windows, showing the same +(vanishing) view of the structure. There are a lot of other views; +you can cycle a short list with `v' (data window) or `Shift-v' +(control window); more can be added to that list (Views) by cloning +views from the AllViews list. + +Note that some classes are currently work-in-progress and some are +abandoned. Some are just being tried on for size (ZZPath). See what +org.gzigzag.Main (Main.java) uses for what's reasonably current. The +truly deprecated ones will be removed little by little. Tuomas +recommends a coloring editor so you can easily see which parts are +commented out -- there are quite many of them, which will be removed +shortly. Tuomas uses gvim. + +Structure +========= + +The structure of the source is still evolving. Right now, there are +several meaningful subdirectories below this directory, including + +media/ - handling fluid media (text etc) +storage/ - how to store the ZZ information on disk in a few different formats +flob/ - all the current basic views and their support +clang/ - cellular programming language experimentation + + +Commands +======== + +See the user's guide for more info. + +Compiling +========= + +Note that some Java compilers may have trouble with dependencies so +you may have to run "make" several times. REMEMBER TO SET YOUR CLASSPATH +CORRECTLY! + +Bug reporting +============= + +Bug reports are gladly accepted. See the FAQ for more info. + +Please run + + java org.gzigzag.ChkVersion + +and include the output so we can be sure which version of each file +you're running. + + +Requirements +============ + +First of all, the center of it all: make. GNU make version 3.78.1 is +known to work. + +Java Developer's Kit, version 1.1 or later. Kaffe won't work. + +Swing is no longer required. + +Perl, version 5.004 or later, is required by the zob stuff. + +This is all you need to compile & run the core GZigZag. In the +directory ../Modules are some modules useful for various things. For +convenience, they are called from the Makefile in this directory. + +IF YOU DO NOT WANT TO INSTALL THE REQUIREMENTS FOR A MODULE, JUST +REMOVE IT FROM THE + + MODULES=... + +LINE IN THE MAKEFILE. You can also specify it on the make command +line like this: + + make MODULES="" + + +Requirements for modules +======================== + +1. xml + +To use the XML module, you need the Xerces libraries from +http://xml.apache.org, version 1.1.2 or later. +If there is a problem, please report it to me. + +2. mbox + +You need the GNU regexp libraries, version 1.0.8, for parsing mailboxes. +Note that this module is not yet very useful so it's developers only. + +3. test + +This just contains small test classes for various features and is +mostly useful for developers only. Use the source, Luke. + +4. sound + +This module requires JMF, the Java Media Framework, version 2.0, +available from java.sun.com either as a pure Java download or an accelerated +version for Solaris or NT. + +5. applet + +This module requires the XML module. If you would like to use ZZApplet +from a browser, like netscape navigator, you must have OpenXML +libraries in the path the browsers JVM searches. Tuomas got it +working by copying openxml.jar to netscapes library directory. ( vp ) + +Documentation +============= + +The javadocs embedded in the sources (which may be converted to HTML +using the Sun javadoc program) may help quite a bit. + +See also the directory ../Documentation + + +A weird JNI Perl scripting thing +================================ + +In the script/ subdirectory there is a JNI interface to the Perl scripting +module of the C++ side, which works: this is intended as a temporary +measure to allow scripting within the Java client. Eventually this should +be replaced with the ZZ Scripting language plus TCP/IP connection to a +Perl script server, if required. Compiling the jzigzag program can be +a bit difficult but is well worth it. + + + -- The GZigZag team diff --git a/Java/RString.java b/Java/RString.java new file mode 100644 index 0000000..ddf0e34 --- /dev/null +++ b/Java/RString.java @@ -0,0 +1,41 @@ +/* +RString.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.awt.*; + +/** A potentially referential immutable text string. + */ + +public interface RString { +String rcsid = "$Id: RString.java,v 1.1 2000/10/20 11:35:29 tjl Exp $"; + + String txt(); + + RString substring(int start); + RString substring(int start, int end); + + Span[] getSpans(); + Span[] getSpans(int start); + Span[] getSpans(int start, int end); + +} diff --git a/Java/SafeExit.java b/Java/SafeExit.java new file mode 100644 index 0000000..f7fe801 --- /dev/null +++ b/Java/SafeExit.java @@ -0,0 +1,95 @@ +/* +SafeExit.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho. + */ + +package org.gzigzag; + +import java.util.*; + +/** A class that can be told of things that need to be done at + shutdown and that will do them when it is asked to kill the + program. Since Java does not provide pre-shutdown hooks, we need + to provide them ourselves. */ +public class SafeExit { + + /** An object that wants to be called at exit time for cleanup. + */ + public interface Cleanupable { + /** Perform any cleanup operations necessary for this object. + */ + void cleanup() throws Throwable; + } + + private static Vector things_to_clean_up = new Vector(); + + public static void registerObject(Cleanupable o) { + things_to_clean_up.addElement(o); + } + + public static void unregisterObject(Cleanupable o) { + things_to_clean_up.removeElement(o); + } + + /** This is a safe exit procedure that kills all threads first, + then cleans up those things that are registered for cleanup + and then exits. */ + public static void exit(int exitcode) { + // The following is from "The Java Programming Language", + // Second Edition, p. 329--330 + + // this needs the threads to be modified so that they end on + // interrupt or something, so now this is disabled +// Thread myThread = Thread.currentThread(); +// ThreadGroup thisGroup = myThread.getThreadGroup(); +// int count = thisGroup.activeCount(); +// Thread[] threads = new Thread[count + 20]; +// thisGroup.enumerate(threads); + +// for (int i = 0; i < threads.length; i++) { +// if (threads[i] != null && threads[i] != myThread) { +// threads[i].interrupt(); +// } +// } + +// for (int i = 0; i < threads.length; i++) { +// if (threads[i] != null && threads[i] != myThread) { +// try { +// threads[i].join(); +// } catch (InterruptedException e) { +// // ignore +// } +// } +// } + + // Ok, now to our own stuff: clean up + for (Enumeration e = things_to_clean_up.elements(); + e.hasMoreElements();) { + Cleanupable o = (Cleanupable) e.nextElement(); + try { + o.cleanup(); + } catch (Throwable t) { + ZZLogger.exc(t, "At cleanup"); + } + } + + System.exit(exitcode); + } + +} diff --git a/Java/ScalableFont.java b/Java/ScalableFont.java new file mode 100644 index 0000000..4cb5fa8 --- /dev/null +++ b/Java/ScalableFont.java @@ -0,0 +1,122 @@ +/* +ScalableFont.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Rauli Ruohonen + */ + +package org.gzigzag; +import java.awt.*; +import java.util.*; + +/** A font object from which it is easy to obtain + * instances and metrics scaled to requested multiplications. + */ + +public class ScalableFont { + public static final String rcsid = "$Id: ScalableFont.java,v 1.3 2001/01/01 01:20:22 raulir Exp $"; + public static boolean dbg=false; + private static final void p(String s) { if(dbg) ZZLogger.log(s); } + + /** If set, font metrics will not be cached. + */ + public static boolean dontCache=false; + + /** Used to get FontMetrics for a Font. + * Should be set in e.g. main(). + */ + public static Component fmComp; + + /** The font and font metrics caches. + */ + private static Hashtable fCache=new Hashtable(),fmCache=new Hashtable(); + + /** The font family. + */ + private String fam; + + /** The font style. + */ + private int st; + + /** The point size when scaling factor is 1. + */ + private int defPt; + + /** Constructor similar to Java's Font(f,s,p). + * @param pointsize Point size when scaling factor is 1. + */ + public ScalableFont(String family,int style,int pointsize) { + fam=family; + st=style; + defPt=pointsize; + } + + /** Get a scaled instance of the font. + * @param scale Scaling factor is (scale/1000). + * @return May not return null. + */ + public Font getFont(int scale) { + int pt=scale2pt(scale); + return getFontPtId(pt,fam+"/"+st+"/"+pt); // XXX I dislike the ID -tjl + } + + /** Get font metrics for a scaled instance of the font. + * @param scale Scaling factor is (scale/1000). + * @return May not return null. + */ + public FontMetrics getFontMetrics(int scale) { + int pt=scale2pt(scale); + String id=fam+"/"+st+"/"+pt; + Font f=getFontPtId(pt,id); + + if(dontCache) return fmComp.getFontMetrics(f); + + FontMetrics fm=(FontMetrics)fmCache.get(id); + + if(fm==null) { + p("FontMetrics cache miss: "+id); + fm=fmComp.getFontMetrics(f); + fmCache.put(id,fm); + } + return fm; + } + + + + private static Font lastFont; + private static String lastId=""; + + private synchronized Font getFontPtId(int pt,String id) { + if(lastId.equals(id)) return lastFont; + lastId=id; + if(dontCache) lastFont=new Font(fam,st,pt); + else { + lastFont=(Font)fCache.get(id); + if(lastFont==null) { + p("Font cache miss: "+id); + lastFont=new Font(fam,st,pt); + fCache.put(id,lastFont); + } + } + return lastFont; + } + private int scale2pt(int scale) { + return (defPt*scale+500)/1000; + } + +} diff --git a/Java/SoundObs.java b/Java/SoundObs.java new file mode 100644 index 0000000..37b6888 --- /dev/null +++ b/Java/SoundObs.java @@ -0,0 +1,37 @@ +/* +SoundObs.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.io.*; + +/** Called by SoundScroll when things happen. + */ +public interface SoundObs { +String rcsid = "$Id: SoundObs.java,v 1.3 2000/09/19 10:31:58 ajk Exp $"; + + int STARTED = 42; + int PLAYING = 43; + int STOPPED = 44; + void playingAt(int event, long l); +} + diff --git a/Java/SpaceDump.java b/Java/SpaceDump.java new file mode 100644 index 0000000..a05b069 --- /dev/null +++ b/Java/SpaceDump.java @@ -0,0 +1,164 @@ +/* +SpaceDump.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ +/** A space dump class. This class is used to dump the whole space + * into a specially formatted text file designed to allow carrying on + * information from any space version to the next and to parse the + * aforementioned text file. */ + +package org.gzigzag; +import java.io.*; +import java.util.*; + +public class SpaceDump { +public static final String rcsid = "$Id: SpaceDump.java,v 1.3 2001/02/20 11:32:45 ajk Exp $"; + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + // this is a useful shorthand + private static String encode(String s) { return ZTPCommand.encode(s); } + + public String home; + public Hashtable content = new Hashtable(); + public Hashtable cellswithspans = new Hashtable(); + public Hashtable dims = new Hashtable(); + public Hashtable stringscrolls = new Hashtable(); + + public SpaceDump(Reader reader) throws IOException { + BufferedReader r = new BufferedReader(reader); + + ZTPCommand com; + try { + com = new ZTPCommand(r.readLine()); + if (!com.name.toUpperCase().equals("H") || com.args.length != 3 + || !com.args[0].toUpperCase().equals("ZZSpaceDump".toUpperCase())) + throw new ZZError("This is not a space dump"); + + if (!com.args[1].equals("0")) + throw new ZZError("I don't know how to slurp this file"); + } catch (SyntaxError e) { + throw new ZZError("This is not a space dump (syntax error: + " + + e.getMessage() + ")"); + } + + home = com.args[2]; + + while (true) { + com = new ZTPCommand(r.readLine()); + + if (com.name.toUpperCase().equals("C")) { + if (com.args.length != 2) + throw new SyntaxError("wrong number of arguments for C"); + + content.put(com.args[0], com.args[1]); + cellswithspans.remove(com.args[0]); + } else if (com.name.toUpperCase().equals("R")) { + if (com.args.length < 3) + throw new SyntaxError("too few arguments to R"); + + if (!dims.containsKey(com.args[0])) { + dims.put(com.args[0], new Hashtable()); + } + + Hashtable dim = (Hashtable)dims.get(com.args[0]); + + for (int i = 1; i + 1 < com.args.length; i++) { + dim.put(com.args[i], com.args[i+1]); + } + } else if (com.name.toUpperCase().equals("SP")) { + if (com.args.length != 2) + throw new SyntaxError("wrong number of arguments to SP"); + + content.put(com.args[0], com.args[1]); + cellswithspans.put(com.args[0], com.args[0]); + } else if (com.name.toUpperCase().equals("SC")) { + if (com.args.length != 2) + throw new SyntaxError("wrong number of arguments to SC"); + + String scroll = (String)stringscrolls.get(com.args[0]); + if (scroll == null) scroll = ""; + scroll += com.args[1]; + stringscrolls.put(com.args[0], scroll); + } else if (com.name.toUpperCase().equals("F")) { + break; + } else { + throw new SyntaxError("unknown command"); + } + } + } + + /** Prints a dump of space to pw. */ + public static void dump(final PrintWriter pw, final ZZSpace space) { + pw.println("H ZZSpaceDump 0 " + encode(space.getHomeCell().getID())); + + Stack stack = new Stack(); + for (Enumeration e = space.cells(); e.hasMoreElements();) { + stack.push(e.nextElement()); + } + + String[] dims = space.dims(); + + Hashtable seen = new Hashtable(); + Hashtable scrolls = new Hashtable(); + while (!stack.empty()) { + ZZCell c = (ZZCell)stack.pop(); + seen.put(c, c); + p("processing cell " + c); + + Span s = c.getSpan(); + if (s == null) { + pw.println("C " + encode(c.getID()) + " " + encode(c.getText())); + } else { + scrolls.put(s.getStart().getScroll(space), ""); + scrolls.put(s.getEnd().getScroll(space), ""); + pw.println("SP " + encode(c.getID()) + " " + encode("" + s)); + } + + for (int i = 0; i < dims.length; i++) { + ZZCell d = c.s(dims[i]); + if (d != null) { + p("processing connection (" + dims[i] + ": " + c + " -> " + d); + if (!seen.containsKey(d)) stack.push(d); + pw.println("R " + encode(dims[i]) + " " + + encode(c.getID()) + " " + encode(d.getID())); + } + d = c.s(dims[i], -1); + if (d != null) p("processing connection (" + dims[i] + ": " + d + " -> " + c); + if (d != null && !seen.containsKey(d)) stack.push(d); + } + } + + for (Enumeration e = scrolls.keys(); e.hasMoreElements();) { + Scroll s = (Scroll)e.nextElement(); + if (!(s instanceof StringScroll)) { + ZZLogger.log("ignoring non-string scroll " + s.getId()); + continue; + } + StringScroll ss = (StringScroll)s; + final int ll = 50; + for (long i = 0; i < ss.curEnd(); i += ll) { + int l = (int)(ss.curEnd() - i < ll ? ss.curEnd() - i : ll); + pw.println("SC " + encode(ss.getId()) + " " + encode(ss.getString(i, l))); + } + } + pw.println("F"); + } +} diff --git a/Java/SysLogger.java b/Java/SysLogger.java new file mode 100644 index 0000000..135f2b2 --- /dev/null +++ b/Java/SysLogger.java @@ -0,0 +1,44 @@ +/* +SysLogger.java + * + * Copyright (c) 1999, 2000 Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ + +package org.gzigzag; + +class SysLogger { + + private static native void openlog(); + private static native void syslog(String msg, boolean verbose); + + public static synchronized void init() throws UnsatisfiedLinkError { + System.loadLibrary("gzigzag-syslog"); + openlog(); + } + + public static synchronized void log(String s) { + syslog(s, false); + } + + public static synchronized void verblog(String s) { + syslog(s, true); + } + +} diff --git a/Java/TODO b/Java/TODO new file mode 100644 index 0000000..61a9fdf --- /dev/null +++ b/Java/TODO @@ -0,0 +1,155 @@ +Currently, the up-to-date task list is at sourceforge.net's task manager for +gzigzag project. All the tasks below have not yet been added, but there are +several interesting tasks there already which are mostly more well-defined +and important than the ones below. + +If you want to work on any major task, please contact lukka@iki.fi first +to avoid overlapping work. The order below is random, not importance nor +a plan. + +The two MAJOR design questions: these are not easy to solve +since there are many issues here + +- 3rd generation file format: caching of saves to speed up operation + - the three features: + - micro-level undo + - cache saves + - use as notification buffer: check notifications all at once when + the code has finished. +- slices + - code complexity + - lazy loading + +Minor design questions: +- circulars: different ops for going over back to headcell? + -> right now too easy to lock up. + +Next major code cleanup: +- event queues, caching of some renderings? +- go through ZZCell, VStream and other APIs, check function names and parameters + for consistency. +- move packages +- document some APIs +- Redo ZZPrimitiveActions using clang as an intermediator. +- StringScroll -> interface! + +Ted's requests: +- g to home cell, G ctrl home cell +- m marks current cell, M ctrl + (m done, M not) +- flags: + - no splines + - continuous drawing i.e. show same cell more than once +- repeat bars +- viewspecs also visible +- 4th dim? +- search -> mark +- place for marks (system list) +- number up/down +- washcloth windows / iris windows + +Need more specs from Ted for: +- flob coordinate handling: zoom, setting etc. +- textcloud UI - two textclouds +- outline + expanded view using billowing +- vstream internal structure + markup + cursor handling when vstream + changed + +Jobs for Vesa: +- Make FileWritable cache things: + - cache writes until a non-contiguous one is made, or + a read is done. + - cache reads by a readahead + - use a fixed buffer of e.g. 256 or 512 bytes. + - make caching optional and timetest with and without + - be very surprised about the results ;) + + - MAKE SURE TO PUT AN EXPLICIT FLUSH COMMAND INTO WRITABLE AND + CALL IT AFTER EVERY FULL RECORD IS WRITTEN! + + (If you want justification for this, just try strace'ing + a run and see how many system calls are completely redundant) + +- MBox reader: make it structural, i.e. connect values of a field on + a d.byfield (sorted!), split multi-values into several cells and use clones for + the same people and msgids. +- undo +- move all AbstractView functionality to ZZDefaultSpace + --> think about the function names, propose better if you can. +- printing ? Export to html. +- Extern module for external commands + +AJK: +project infrastructure: +- a test build daemon using JDK not Jikes +- javadoc autobuild daemon? +development: +- WET raster, structure +- add an option to TreeRaster for showing less-deep cells as larger +- fix the billowing bug in TreeRaster + +Anyone: + +- Do an RFC (e.g. 822) in a REAL, proper hypertext fashion. + +- vstream -> enfilade-like thing + + paragraph jumping + +- tight brick links & edges with lighter color + +- allow changing direction associated with dimension +- allow changing priorities - joystick & other controls? + +- improve updatemanager and the views: + - updatemanager should take care of all animation lengths etc. + - there should be a parameter "complexity" which would allow + the updatemanager to tell a view to update itself only partially + (e.g. on animation on slow machines). + +- change ViewCell to Viewcell everywhere + XXX to viewspecs / ??? + +- put debug info configuration into structure!! + - all involved classes in structure. Really neat. + +- finish defaultspace + +- separation into a global zigzag interface and a gzigzag implementation + for a standard (e.g. DOM-like) API separation + +- grep the source for 'XXX' + +- create a singlecellraster that shows all the connections from the given + cell along dimensions on a given list. + +- check double clicks! If one click rerasters, what happens after? + +- better rasters + - e.g. headcell-based. + +- change dimensions to cells instead of strings. + - think about slicing problems... must handle when bringing + in the slice. + +- first personal space: BOOKMARKS + +- Clang + - primitive and advanced + +- slices + +- cursorspaces: d.cursor implemented transiently, to avoid lengthening + the cellscroll - + - possibly implement in ZZGlobal using FLAG_TRANSIENT cells? + +- a view of the filesystem as a ZZ space. + +- cellscrolls: The data is there but the access isn't + - animate through a cellscroll + - undo from cellscroll. + (XXX Not cellscroll but persistentdimspace now!) + +- an HTML page showing pictures and applets to introduce people to ZZ: + show an image of the space and then an applet where you can move through + that space. Start by just viewing, then allow people to change the space. + diff --git a/Java/TestSpace.java b/Java/TestSpace.java new file mode 100644 index 0000000..fd9742a --- /dev/null +++ b/Java/TestSpace.java @@ -0,0 +1,53 @@ +/* +TestSpace.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.io.*; + +public class TestSpace { + static void p(String s) { System.out.println(s); } + + static public void test(ZZSpace s) { + ZZCell c1 = s.getHomeCell(); + ZZCell c2 = c1.N("d.1", 1); + c2.setText("FOO"); + p("Id: "+c2.getID()); + p("Text: "+c2.getText()); + if(!("FOO".equals(c2.getText()))) + throw new ZZError("Not FOO"); + } + public static void main(String[] argv) { + // try { + File f = new File("/tmp/zzspacetest"+Math.random()); + p("File: "+f); + ZZSpace space = new ZZCacheDimSpace(new DirStreamSet(f)); + test(space); + // } catch(Exception e) { + // ZZLogger.exc(e); + // } + System.exit(0); + } +} + + + diff --git a/Java/TimeTest.java b/Java/TimeTest.java new file mode 100644 index 0000000..d3b6a11 --- /dev/null +++ b/Java/TimeTest.java @@ -0,0 +1,155 @@ +/* +TimeTest.java + * + * Copyright (c) 2000, Ted Nelson, Tuomas Lukka and Miika Pekkarinen + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Miika Pekkarinen + * Rewritten by Tuomas Lukka + */ + +package org.gzigzag; + +import org.gzigzag.*; +import java.awt.*; +import java.util.*; +import java.io.*; + + +public class TimeTest { + static public abstract class Test { + public String name; + public abstract void test(ZZCell home, int nrounds); + } + + static Test newtest = new Test() { { name = "New"; } + public void test(ZZCell home, int nrounds) { + for(int i=0; i + * The operations are cleverly stored to minimize memory use: + * an array of Object refs, some of which are operations and after + * them their parameters. The parameters are not stored in the operation + * objects in order to avoid creating a new object instance per undoable + * operation. + *

    + * NOTE: this means that a parameter to an operation CANNOT IMPLEMENT + * UndoList.Op itself! That would break the chain. It would need to be + * e.g. wrapped into an array. + *

    + * So the orders are: undo in reverse, redo in original order and + * commit in reverse. + */ + +public class UndoList { +String rcsid = "$Id: UndoList.java,v 1.10 2000/10/26 18:09:29 tjl Exp $"; + public static boolean dbg = false; + final static void p(String s) { if(dbg) System.out.println(s); } + final static void pa(String s) { System.out.println(s); } + + /** An undoable operation. + * Classes implementing this class can either be real + * operations or simply classes of operations that take + * their parameters from the Object array, in order + * to save space and use only one instance of the Op object. + * @see UndoList + * @see ZZCacheDimension + */ + public interface Op { + /** Undo the operation. + */ + void undo(Object[] list, int nth); + /** Redo the operation. + */ + void redo(Object[] list, int nth); + /** Commit the operation. + * The operation need not be undoable after a commit. + */ + void commit(Object[] list, int nth); + } + + Object[] ops = new Object[2000]; + int nops = 0; + + int stamp0; + + int[] stamps = new int[64]; + int nstamps = 0; + + int nundoes = 0; + + UndoList(int inittime) { + stamp0 = inittime; + makeStampRoom(1); + stamps[nstamps++] = 0; + } + + /** Place a timestamp into the operation list. + * Undo and redo work on stamped boundaries. + * If no operations since last stamp, returns last stamp. + */ + public int stamp() { + p("STAMP!"); + if(nundoes != 0) return -1; + if(stamps[nstamps-1] == nops) + return stamp0 + nstamps-1; + makeStampRoom(1); + stamps[nstamps++] = nops; + return stamp0 + nstamps-1; + } + + /** Commit the changes up to the present. + * Returns the new timestamp. + */ + public int commit() { + finalizeUndo(); + + int stampno = stamp(); + for(int i=nops-1; i>=0; i--) { + if(ops[i] instanceof Op) + ((Op)ops[i]).commit(ops, i); + } + + nops = 0; + nstamps = 0; + nundoes = 0; + stamp0 = stampno; + stamps[nstamps++] = 0; + return stampno; + } + + /** Undo operations until the previous timestamp, if possible. + * After committing, undo won't work until you stamp again. + */ + public void undo() { + try { + int curop = stamps[nstamps-1 - nundoes]; + p("Undo: "+curop+" "+nstamps+" "+nundoes); + // Nothing to do. + if(curop == 0) { + ZZLogger.log("Can't undo further"); + return; + } + int prevop = stamps[nstamps-1 - nundoes - 1]; + for(int i = curop - 1; i >= prevop; i--) { + if(ops[i] instanceof Op) { + p("Undo: "+i+" "+ops[i]); + ((Op)ops[i]).undo(ops, i); + } + } + nundoes += 1; + } catch(Exception e) { + ZZLogger.exc(e); + throw new ZZFatalError("Exception while undoing"); + } + } + + /** Redo operations until the next timestamp, after undo has been + * used. Any changes meanwhile make this impossible (branches later??). + */ + public void redo() { + if(nundoes <= 0) { + ZZLogger.log("Nothing to redo"); + return; + } + try { + int curop = stamps[nstamps-1 - nundoes]; + int nextop = stamps[nstamps-1 - nundoes + 1]; + for(int i = curop; i < nextop; i++) { + if(ops[i] instanceof Op) { + p("Undo op: "+i); + ((Op)ops[i]).redo(ops, i); + } + } + nundoes -= 1; + } catch(Exception e) { + throw new ZZFatalError("Exception while undoing"); + } + + } + + /** Finalize the undo: the system will not be able to redo changes + * that happened after this. + */ + public void finalizeUndo() { + if(nundoes == 0) return; + p("FINALIZE UNDO! "+nundoes); + nops = stamps[nstamps-1 - nundoes]; + nstamps -= nundoes; + nundoes = 0; + } + + protected final void makeRoom(int n) { + if(nops + n >= ops.length) { + Object[] opsnew = new Object[ops.length * 2]; + System.arraycopy(ops, 0, opsnew, 0, nops); + ops = opsnew; + } + } + + protected final void makeStampRoom(int n) { + if(nstamps + n >= stamps.length) { + int[] stampsnew = new int[stamps.length * 2]; + System.arraycopy(stamps, 0, stampsnew, 0, nstamps); + stamps = stampsnew; + } + } + + public void add(Op o1, Object o2, Object o3) { + if(nundoes != 0) finalizeUndo(); + makeRoom(3); + int i = nops; + ops[nops++] = o1; + ops[nops++] = o2; + ops[nops++] = o3; + p("Add 3op: "+i+" "+o1+" "+o2+" "+o3); + } + public void add(Op o1, Object o2, Object o3, Object o4) { + if(nundoes != 0) finalizeUndo(); + makeRoom(3); + int i = nops; + ops[nops++] = o1; + ops[nops++] = o2; + ops[nops++] = o3; + ops[nops++] = o4; + p("Add 4op: "+i+" "+o1+" "+o2+" "+o3+" "+o4); + } + +} diff --git a/Java/ZOb.java b/Java/ZOb.java new file mode 100644 index 0000000..322d726 --- /dev/null +++ b/Java/ZOb.java @@ -0,0 +1,39 @@ +/* +ZOb.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.awt.*; + +/** An object whose data is read from the structure. + * This is an interface implemented by all the objects generated from + * .zob files by zob2java.pl. + */ + +public interface ZOb { + /** Read the parameters for this ZOb. + * Returns a string describing the errors encountered, or null if + * everything went fine.. + */ + String readParams(ZZCell c); +} + diff --git a/Java/ZTPCommand.java b/Java/ZTPCommand.java new file mode 100644 index 0000000..ab415c5 --- /dev/null +++ b/Java/ZTPCommand.java @@ -0,0 +1,207 @@ +/* +ZTPCommand.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ +package org.gzigzag; +import java.util.*; + +/** ZTP command parser. After instance construction, the attribute + * "name" contains the command name and the attribute "args" contains + * the arguments of the command. Since this class is also used in the + * conversion space dumper, it is in the main package instead of the + * ztp package. */ +public class ZTPCommand { + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log("[" + s + "]"); } + private static void pa(String s) { ZZLogger.log(s); } + + public String name; + public String[] args; + + public static class RV { + public String token; + public String rest; + public RV(String token, String rest) { + this.token = token; + this.rest = rest; + } + public String toString() { + return "[token: " + token + " | rest: " + rest + "]"; + } + } + + public static RV lwsp(String str) { + int i; + for (i = 0; i < str.length(); i++) { + if (str.charAt(i) != 9 && str.charAt(i) != 32) break; + } + return new RV(str.substring(0, i), str.substring(i)); + } + + public static boolean ASCII_word_char(char c) { + return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || c == '/'; + } + + public static RV ASCII_word(String line) { + int rlen = 0; + for (int i = 0; i < line.length(); i++) { + char c = line.charAt(i); + if (!ASCII_word_char(c)) break; + ++rlen; + } + if (rlen == 0) return null; + return new RV(line.substring(0, rlen), line.substring(rlen)); + } + + public static boolean ASCII_num_char(char c) { + return '0' <= c && c <= '9'; + } + + public static RV ASCII_number(String line) { + int rlen = 0; + for (int i = 0; i < line.length(); i++) { + char c = line.charAt(i); + if (!ASCII_num_char(c)) break; + ++rlen; + } + if (rlen == 0) return null; + return new RV(line.substring(0, rlen), line.substring(rlen)); + } + + public static RV quoted_string(String line) { + if (line.charAt(0) != 34) return null; + String rv = ""; + int i; + boolean ok = false; + for (i = 1; i < line.length(); i++) { + char c = line.charAt(i); + if (c == '"') { + if (i + 1 < line.length() && line.charAt(i+1) == '"') { + ++i; + } else { + ok = true; + break; + } + } + if (c == '\\') { + if (i + 1 == line.length()) { + throw new SyntaxError("unterminated escape sequence"); + } + if (line.charAt(i+1) == '\\' || line.charAt(i+1) == '"') { + c = line.charAt(++i); + } else if (line.charAt(i+1) == 'n') { + c = '\n'; + ++i; + } else { + throw new SyntaxError("invalid escape sequence"); + } + } + rv += c; + } + if (!ok) { + throw new SyntaxError("unterminated quoted string"); + } + return new RV(rv, line.substring(i+1)); + } + + private static String encode_quoted(String s) { + String rv = "\""; + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == '"') { + rv += "\"\""; + } else if (s.charAt(i) == '\\') { + rv += "\\\\"; + } else if (s.charAt(i) == '\n') { + rv += "\\n"; + } else { + rv += s.charAt(i); + } + } + rv += "\""; + return rv; + } + + /** Encodes s as one token for the Command parser. */ + public static String encode(String s) { + if (s.length() == 0) return "\"\""; + if (ASCII_num_char(s.charAt(0))) { + for (int i = 1; i < s.length(); i++) { + if (!ASCII_num_char(s.charAt(i))) { + return encode_quoted(s); + } + } + return s; + } + if (ASCII_word_char(s.charAt(0))) { + for (int i = 1; i < s.length(); i++) { + if (!ASCII_word_char(s.charAt(i))) { + return encode_quoted(s); + } + } + return s; + } + return encode_quoted(s); + } + + public ZTPCommand(String line) { + RV rv; + + rv = ASCII_word(line); + if (rv == null) throw new SyntaxError("error parsing command name"); + name = rv.token; + line = lwsp(rv.rest).rest; + Vector v = new Vector(); + while (line.length() > 0 && !line.equals("\n") + && !line.equals("\r") && !line.equals("\r\n")) { + p("line = " + line); + rv = quoted_string(line); + if (rv != null) { + p("arg parsed as a quoted string, token = " + rv.token); + } else { + rv = ASCII_word(line); + if (rv != null) { + p("arg parsed as an ASCII word, token = " + rv.token); + } else { + rv = ASCII_number(line); + if (rv != null) { + p("arg parsed as an ASCII number, token = " + rv.token); + } else { + throw new SyntaxError("error parsing command arguments"); + } + } + } + v.addElement(rv.token); + line = lwsp(rv.rest).rest; + } + args = new String[v.size()]; + for (int i = 0; i < args.length; i++) { + args[i] = (String)v.elementAt(i); + } + p("args.length = " + args.length); + } + + public String toString() { + String rv = name; + for (int i = 0; i < args.length; i++) { + rv += "_" + args[i]; + } + return rv; + } +} + diff --git a/Java/ZZCanvasView.java b/Java/ZZCanvasView.java new file mode 100644 index 0000000..7586f11 --- /dev/null +++ b/Java/ZZCanvasView.java @@ -0,0 +1,231 @@ +/* +ZZCanvasView.java + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.awt.event.*; +import java.awt.*; + +/** A view which creates 2-D canvases to show. + */ + +public class ZZCanvasView extends ZZViewComponent { +public static final String rcsid = "$Id: ZZCanvasView.java,v 1.35.2.1 2001/04/08 13:00:57 bfallenstein Exp $"; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + public ZZCanvasView() { + super(); + } + + public void setViewcell(ZZCell v0) { + super.setViewcell(v0); + } + + final void upd(InputEvent ev) { + p("Upd "+this); + ZZUpdateManager.setFast(this); + ZZUpdateManager.freeze(); + try { + kb.perform(ev, this, ctrlView, curcanv); + ev.consume(); + ZZObsTrigger.runObsQueue(); + } finally { + ZZUpdateManager.thaw(); + } + p("Upd finished "+this); + } + + public void mouseClicked(MouseEvent e) { + p("Mouse clicked "+ e); + upd(e); + // super.mouseClicked(e); + } + public void mousePressed(MouseEvent e) { + p("MousePressed " + e); + // clicked = curcanv.getclicked(e.getX(), e.getY()); + upd(e); + } + public void mouseDragged(MouseEvent e) { + p("MouseDragged " + e); + upd(e); + } + public void mouseReleased(MouseEvent e) { + p("MouseReleased " + e); + upd(e); + } + boolean xored = false; + int prevx; int prevy; Object prevob; + public void mouseMoved(MouseEvent e) { + if ( curcanv == null ) return; + Graphics g = getGraphics(); + Object ob = curcanv.getObjectAt(e.getX(), e.getY()); + // If there was a previous XOR cursor, wipe it out. + if(xored) { + if(ob != null && ob.equals(prevob)) { + prevx = e.getX(); + prevy = e.getY(); + return; + } + curcanv.renderXOR(g, prevx, prevy); + } + prevx = e.getX(); + prevy = e.getY(); + prevob = ob; + // This simply allows the canvas to show which element would get + // activated (such as where the insertion cursor would be placed) + // by a mouse click. + + curcanv.renderXOR(g, prevx, prevy); + xored = true; + super.mouseMoved(e); + } + + ZZScene oldcanv; + long oldtime; + ZZScene curcanv; + ZZCell cursor; + + String[]dims; + + public boolean reraster() { + p("reraster " + this); + try { + dims = ZZDefaultSpace.getDimList(viewCell); + cursor = ZZCursorReal.get(viewCell); + if(cursor == null) { + validraster = false; + p("No cursor"); + return false; + } + + Dimension d = getSize(); + + // XXX ??? + /* if(oldcanv == null) */ + oldcanv = curcanv; + + curcanv = ZZDefaultSpace.getScene(viewCell, this); + validraster = true; + + p("Reraster returning"); + return (oldcanv != null && oldcanv.isInterpUseful(curcanv)); + } catch(Exception e) { + ZZLogger.exc(e, "Exception while rastering"); + validraster = false; + oldcanv = curcanv = null; + return false; + } catch(ZZError e) { + ZZLogger.exc(e, "ZZError while rastering"); + validraster = false; + oldcanv = curcanv = null; + return false; + } + } + + public void paintInto(Graphics gr) { + // p("DOPAINT " + this + " " + parentView + " " + + // needreraster + " " + validraster +" " + animate ); + synchronized(viewCell.getSpace()) { + if(fract >= 1.0) oldcanv = null; + if(!validraster) { + reraster(); + if(!validraster) { + gr.setColor(Color.red); + gr.setFont(new Font("SansSerif", Font.BOLD, 30)); + gr.drawString("RASTER ERROR", 0, getSize().height/2); + System.out.println("Not valid raster"); + repaint(1000); + } + return; + } + /* + if(needreraster) { + needreraster = false; + re_raster(); + } + */ + // p("DOPAINT: AFTER RERASTER: "+parentView+" "+validraster); + /* + if(!validraster) { + needreraster = true; + repaint(1000); + return; + } + */ + // if(parentView!=null) { + // curcanv.dbgPrint(); + // } + // super.paint(gr); + // paintBorder(gr); + Dimension thisd = getSize(); + Color bg = getBackground(); + ZZCell modec = ZZKeyBindings1.getMode(viewCell).s("d.color"); + if(modec != null) { + if(modec.getText().equals("CURSOR")) + bg = ZZCursorReal.getColorOrWhite(viewCell); + else + bg = new java.awt.Color(Integer.parseInt(modec.getText())); + } + gr.setColor(bg); + Insets ins = getInsets(); + gr.fillRect(ins.left, ins.top, + thisd.width-ins.left-ins.right, + thisd.height-ins.top-ins.bottom); + gr.setColor(Color.black); + + // System.out.println(t+" "+oldtime); + if(fract < 1 && oldcanv != null) { + if(fract > 0.3) { + curcanv.renderInterp(gr, oldcanv, 1-fract); + } else { + oldcanv.renderInterp(gr, curcanv, fract); + } + + getToolkit().sync(); + // repaint(); + } else { + curcanv.render(gr); + + // XXX THIS CODE SHOULDN'T BE HERE! + // IT SHOULD BE SPECIFIED IN THE STRUCTURE + // FOR EACH VIEW SEPARATELY IF DESIRED + String s = ZZDefaultSpace.getInbuf(viewCell.getSpace(), + false); + if(s != null) { + if(s.equals("")) + s = ZZCursorReal.get(viewCell).getID(); + Dimension d = getSize(); + gr.drawString(s, 10, d.height-20); + } + + getToolkit().sync(); + } + if(xored) { + curcanv.renderXOR(gr, prevx, prevy); + // XXX get this right during interpolation + } + } + // p("DOPAINTRET " + this + " " + needreraster + " " + animate ); + wasInPaint = true; + } + +} diff --git a/Java/ZZCell.java b/Java/ZZCell.java new file mode 100644 index 0000000..f8f54d5 --- /dev/null +++ b/Java/ZZCell.java @@ -0,0 +1,719 @@ +/* +ZZCell.java + * + * Copyright (c) 1999-2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +/* + * Well, he'd been in enough cells. There were ways to handle these + * things. The important thing was to be direct. He got up and banged + * on the bars until the warder sauntered along the corridor. + * `Yes, mate?' + * `I just want to get things sorted out,' said Rincewind. `It's + * not as though I've got time to waste, okay?' + * `Yep?' + * `Is there any chance that you're going to fall asleep + * in a chair opposite this cell with your keys fully exposed on a table + * in front of you?' + * - Terry Pratchett, The Last Continent, p.267 + */ +package org.gzigzag; +import java.util.*; + +/** An abstract class to represent a ZigZag cell. + *

    + * There is no unique cell to Java object mapping, so there may be + * several equivalent Java objects representing the same cell. + * Use the equals method for comparisons. + */ + +public abstract class ZZCell { +public static final String rcsid = "$Id: ZZCell.java,v 1.76 2001/02/08 11:18:39 ajk Exp $"; + + /** Obtain the unique ID for this cell. + * Note that this method may throw an exception + * if the space this cell is in does not support cell IDs. + */ + public String getID() { + throw new NullPointerException("This cell type has no IDs!"); + } + + /** Create a new cell connected to this cell. + * @param dim Dimension to create the cell along + * @param dir The direction, either positive or negative + */ + public final ZZCell N(String dim, int dir) { + return N(dim, dir, null, 0); + } + public final ZZCell N(String dim) { + return N(dim, 1, null, 0); + } + + /** Get a new cell associated with this cell (ie.same slice) + */ + public abstract ZZCell N(); + + /** Get or create a new cell connected to this cell. + * A convenience function which first tries to use getNeighbour + * and if that returns null, creates a new neighbour. + * @param dim Dimension to create the cell along + * @param dir The direction, either positive or negative + * @param obs The observer + */ + public ZZCell getOrNewCell(String dim, int dir, ZZObs o) { + ZZCell r; + if((r = s(dim, dir, o)) != null) return r; + return N(dim, dir, o); + } + public ZZCell getOrNewCell(String dim, int dir) { + return getOrNewCell(dim, dir, null); + } + public ZZCell getOrNewCell(String dim) { + return getOrNewCell(dim, 1, null); + } + /** Create a new cell connected to this cell and attach an observer + * to it + * atomically. + * @param dim Dimension to create the cell along + * @param dir The direction, either positive or negative + * @param obs The observer + */ + public final ZZCell N(String dim, int dir, ZZObs o) { + return N(dim, dir, o, 0); + } + /** Create a new cell connected to this cell + * to it + * atomically. + * @param dim Dimension to create the cell along + * @param dir The direction, either positive or negative + * @param flags The flags to guide the type of the new cell + */ + public final ZZCell N(String dim, int dir, long flags) { + return N(dim, dir, null, flags); + } + /** Create a new cell connected to this cell and attach an observer + * to the connection + * atomically. + *

    + * NOTE: this routine MUST insert the cell, not just blindly + * delete the former connection. + * @param dim Dimension to create the cell along + * @param dir The direction, either positive or negative + * @param obs The observer + * @param flags The flags to guide the type of the new cell + */ + public abstract ZZCell N(String dim, int dir, ZZObs o, long flags); + + + /** Delete this cell. */ + public abstract void delete(); + /** Delete this cell from a rank along a dimension. */ + public void excise(String dim) { + synchronized(getSpace()) { + ZZCell cm = s(dim, -1); + ZZCell cp = s(dim, 1); + if(cm!=null && cp!=null) { + cm.disconnect(dim, 1); + cp.disconnect(dim, -1); + cm.connect(dim, cp); + } + else if(cm!=null) + cm.disconnect(dim, 1); + else if(cp!=null) + cp.disconnect(dim, -1); + } + } + /** Connect this cell to another along a dimension. + * If there is a former connection, + * a ZZConnectWouldBreakError is thrown. + * @param dim Dimension to connect along + * @param to Cell to connect to. This cell will end up poswards from us. + */ + public abstract void connect(String dim, ZZCell to); + /** Connect this cell to another along a dimension in a specified + * direction. + * If there is a former connection, + * a ZZConnectWouldBreakError is thrown. + * @param dim Dimension to connect along + * @param dir The direction, either positive or negative + * @param to Cell to connect to. + */ + public void connect(String dim, int dir, ZZCell to) { + if(dir > 0) { + connect(dim, to); + } else { + to.connect(dim, this); + } + } + + /** Insert a cell next to this one in the rank. + * Both connections of the what cell along the specified dimension are + * deleted before inserting it. + * @param dim Dimension to connect along + * @param dir The direction, either positive or negative + * @param what Cell to insert + */ + public abstract void insert(String dim, int dir, ZZCell what); + + /** Disconnect a connection from this cell. + * @param dim Dimension to disconnect along + * @param dir The direction, either positive or negative + */ + public abstract void disconnect(String dim, int dir); + + /** Set the text contained in the cell. + * @param text The new text + */ + public abstract void setText(String text); + + /** Set the text contained in the cell to a pointer. + * @param text The new text, as a span pointing to a stable scroll + */ + public abstract void setSpan(Span text); + + /** Get a reference to the ZZSpace object describing the whole space */ + public abstract ZZSpace getSpace(); + + /** Find the neighbour of this cell along a dimension + * attach an observer to this relation + * atomically. + * @param dim Dimension to go along + * @param dir The direction, either positive or negative + * @param obs The observer + * @return The neighbour, or null if none. + */ + public abstract ZZCell s(String dim, int dir, ZZObs o); + + /** Find the neighbour of this cell along a dimension. + * atomically. + * @param dim Dimension to go along + * @param dir The direction, either positive or negative + * @return The neighbour, or null if none. + */ + public ZZCell s(String dim, int dir) { + return s(dim,dir,null); + } + + /** Find the next cell along a dimension. + * Always moves poswards. + * @param dim Dimension to go along + * @return The neighbour, or null if none. + */ + public ZZCell s(String dim) { + return s(dim,1,null); + } + + /** Find the headcell of a rank. + * XXX The default implementation does not handle circular ranks correctly! + * @param dim Dimension to go along + * @param dir The direction, either positive or negative + * @return The headcell + */ + public ZZCell h(String dim, int dir) { + return h(dim, dir, false, null); + } + public ZZCell h(String dim, int dir, ZZObs o) { + return h(dim, dir, false, o); + } + public ZZCell h(String dim, boolean ensuremove) { + return h(dim, -1, ensuremove, null); + } + public ZZCell h(String dim, int dir, boolean ensuremove) { + return h(dim, dir, ensuremove, null); + } + /** Find the headcell of a rank. + * The headcell is the most negative cell so this call is equivalent + * to h(dim, -1). + */ + public ZZCell h(String dim) { + return h(dim, -1, false, null); + } + + /** Find the headcell of a rank. + * XXX The default implementation does not handle circular ranks correctly! + * HOWEVER, all code must be prepared for this function to return a cell + * that is just some cell in a looping rank. This means that a while loop + * looking for null going poswards from the headcell might be infinite + * and needs the user to explicitly detect loops. + * Just in case of synch problems, it is recommended that the user check + * both for equality to the headcell and use a + * LoopDetector, in case the loop changed. + * @param dim Dimension to go along + * @param dir The direction, either positive or negative + * @return The headcell + */ + public abstract ZZCell h(String dim, int dir, boolean ensuremove, + ZZObs o); + + + /** Count the length of the rank. + * @param dim Dimension to go along + * @return length of the rank. + */ + public int getRankLength(String dim) { + ZZCell cur = this; + ZZCell next; + int i = 0; + while((next=cur.s(dim,1))!=null) { + + if(next == this) + throw new ZZInfiniteLoop("CIRCULAR HEAD"); + cur = next; + i++; + } + cur = this; + while((next=cur.s(dim,-1))!=null) { + + if(next == this) + throw new ZZInfiniteLoop("CIRCULAR HEAD"); + cur = next; + i++; + } + return i+1; + } + + + /** Find the next intersection of two ranks. + * XXX The default implementation does not handle circular ranks correctly! + * @param dim Dimension to go along from this cell + * @param dir The direction, either positive or negative, from this cell + * @param cell2 The other cell + * @param dim2 Dimension to go along from the other cell + * @param dir2 The direction, either positive or negative, from the other cell + */ + public ZZCell intersect(String dim, int dir, ZZCell cell2, String dim2, int dir2) { + synchronized(getSpace()) { + // If we knew how to find the shorter one... + Hashtable h = new Hashtable(); + ZZCell cur = this.s(dim,dir); + while(cur!=null) { + h.put(cur,cur); + cur = cur.s(dim,dir); + } + cur = cell2.s(dim2,dir2); + while(cur!=null) { + if(h.get(cur) != null) { + return cur; + } + cur = cur.s(dim2,dir2); + } + return null; + } + } + + /** Find all intersections of two ranks. + * XXX The default implementation does not handle circular ranks correctly! + * @param dim Dimension to go along from this cell + * @param dir The direction, either positive or negative, from this cell + * @param cell2 The other cell + * @param dim2 Dimension to go along from the other cell + * @param dir2 The direction, either positive or negative, from the other cell + */ + public ZZCell[] intersectAll(String dim, int dir, ZZCell cell2, String dim2, int dir2) { + synchronized(getSpace()) { + // If we knew how to find the shorter one... + Hashtable h = new Hashtable(); + ZZCell cur = this.s(dim,dir); + while(cur!=null) { + h.put(cur,cur); + cur = cur.s(dim,dir); + } + Vector v = new Vector(); + cur = cell2.s(dim2,dir2); + while(cur!=null) { + if(h.get(cur) != null) { + v.addElement(cur); + } + cur = cur.s(dim2,dir2); + } + ZZCell[] r = new ZZCell[v.size()]; + for(int i=0; i + * Is this the correct implementation? + */ + public String getGlobalID() { + if (getID().indexOf("@") != -1) return getID(); + return getID()+"@"+getSpace().getID(); + } + + /** Find a cell with the given contents. + */ + public ZZCell findText(String dim, int dir, String txt) { + return findText(dim, dir, txt, null); + } + public ZZCell findText(String dim, int dir, String txt, ZZObs o) { + ZZCell cur = s(dim, dir); + while(cur!=null && cur!=this && !cur.getText(o).equals(txt)) { + cur = cur.s(dim,dir,o); + } + if(cur==this) return null; + return cur; + } + + /** Whether another cell is on the given rank in the given dir. + */ + public boolean findCell(String dim, int dir, ZZCell c) { + if(this.equals(c)) return true; + ZZCell i = this.s(dim, dir); + while(i != null && !i.equals(c) && !i.equals(this)) i = i.s(dim, dir); + if(i==null) return false; + return i.equals(c); + } + + + public ZZCell getHomeCell() { + return getSpace().getHomeCell(); + } + + + public ZZCell zzclone() { + return getHeadcell("d.clone", 1).newCell("d.clone", 1); + } + + public ZZCell getRootclone() { + return getHeadcell("d.clone", -1); + } + + // This may become the new API of choice.. + public final String t() { return getText(); } + + /** Return a stringized form of this cell. + * This form is unstable and its use for anything except + * human-readable debugging is not recommended. + * Currently the format is: The cell ID in single quotes + * and the text content after that, in parentheses, + * for example '53' (Text in cell). + */ + public String toString() { + return "'"+getID() + "' (" + getText() + ")"; + } + + + /** Enumerate a (semi)rank. + * @param dim The dimension along which the (semi)rank is to be enumerated. + * @return An enumeration of all cells starting from this cell + * along dim in positive direction. + */ + public Enumeration enumRank(String dim) { + return enumRank(dim, 1); + } + + /** Enumerate a (semi)rank. + * @param dim The dimension along which the (semi)rank is to be enumerated. + * @param dir The direction along dim to enumerate. + * @return An enumeration of all cells starting from this cell + * along dim in direction dir. + */ + public Enumeration enumRank(String dim, int dir) { + class RankEnumeration implements Enumeration { + ZZCell c; + String dimension; + int direction; + public RankEnumeration(ZZCell c, String dimension, int direction) { + this.c = c; + this.dimension = dimension; + this.direction = direction; + } + public boolean hasMoreElements() { + return c != null; + } + + public Object nextElement() { + if (!hasMoreElements()) throw new NoSuchElementException(""); + ZZCell r = c; + c = c.s(dimension, direction); + return r; + } + }; + return new RankEnumeration(this, dim, dir); + } + + // Deprecated, old versions of the calls + + /** Deprecated. + * @deprecated Use the new one-letter functions instead. + */ + public final ZZCell newCell(String dim, int dir, long flags) { + return N(dim, dir, flags); + } + /** Deprecated. + * @deprecated Use the new one-letter functions instead. + */ + public final ZZCell newCell(String dim, int dir, ZZObs o) { + return N(dim, dir, o); + } + /** Deprecated. + * @deprecated Use the new one-letter functions instead. + */ + public final ZZCell newCell(String dim, int dir) { + return N(dim, dir); + } + /** Deprecated. + * @deprecated Use the new one-letter functions instead. + */ + public final ZZCell newCell() { + return N(); + } + + /** Deprecated. + * @deprecated Use the new one-letter functions instead. + */ + public final ZZCell getNeighbour(String dim, int dir, ZZObs o) { + return s(dim, dir, o); + } + /** Deprecated. + * @deprecated Use the new one-letter functions instead. + */ + public final ZZCell getNeighbour(String dim, int dir) { + return s(dim, dir); + } + /** Deprecated. + * @deprecated Use the new one-letter functions instead. + */ + public final ZZCell getSteps(String dim, int dir, ZZObs o) { + return s(dim, dir, o); + } + /** Deprecated. + * @deprecated Use the new one-letter functions instead. + */ + public final ZZCell getSteps(String dim, int dir) { + return s(dim, dir); + } + + /** Deprecated. + * @deprecated Use the new one-letter functions instead. + */ + public final ZZCell getHeadcell(String dim, int dir, boolean ensuremove, + ZZObs o) { + return h(dim, dir, ensuremove, o); + } + /** Deprecated. + * @deprecated Use the new one-letter functions instead. + */ + public final ZZCell getHeadcell(String dim, int dir) { + return h(dim, dir); + } + /** Deprecated. + * @deprecated Use the new one-letter functions instead. + */ + public final ZZCell getHeadcell(String dim, int dir, ZZObs o) { + return h(dim, dir, o); + } + /** Deprecated. + * @deprecated Use the new one-letter functions instead. + */ + public final ZZCell getHeadcell(String dim, int dir, boolean ensuremove) { + return h(dim, dir, ensuremove); + } + /** Deprecated. + * @deprecated Use the new one-letter functions instead. + */ + public final ZZCell getHeadcell(String dim) { + return h(dim); + } + + + // Deprecated stuff. + + /** A flag passed to newCell meaning that the cell should not be stored + * persistently. This may enable some optimizations and + * save some persistent and/or temporary memory space. + * For example, cells that track which cells are shown in a view + * through a raster should probably be transient. + *

    + * Note that not all spaces support transient cells so this is + * only a hint in that context. In getFlags, the meaning is real. + * @deprecated Usefulness being evaluated + */ + long FLAG_TRANSIENT = 0x00000001; + /** A flag meaning that the text stored in this cell is + * an address. + * The method getText() will automatically + * return the text stored in the cell, whether it is just text + * or a span of text from a permascroll. + * If you want the span, use + * getSpan(). + * For users, a much better way to tell whether a cell is a span is + * simply

     c.getSpan() != null 
    . + * @deprecated Usefulness being evaluated + */ + long FLAG_ADDRESS = 0x00000002; + /** A flag meaning that the current cell is used only as a label. + * XXX Think about it a bit more - which operations shall it affect? + * @deprecated Usefulness being evaluated + */ + long FLAG_LABEL = 0x00000004; + + /** Get the flags associated with this cell. + * @deprecated Usefulness being evaluated + */ + public long getFlags() { return 0; } + /** Set the flags associated with this cell. + * @deprecated Usefulness being evaluated + */ + public void setFlags( long s, long u ) { } + +} + diff --git a/Java/ZZCellHandle.java b/Java/ZZCellHandle.java new file mode 100644 index 0000000..037181b --- /dev/null +++ b/Java/ZZCellHandle.java @@ -0,0 +1,81 @@ +/* +ZZCellHandle.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; + +/** A ZigZag cell, as a handle. + * This is a structure that is a handle to one cell. + * All handles to the same cell should be equal to each other. + * This means that the information contained within is only allowed + * to depend on the cell ID. + *

    + * The parts marked EXPERIMENTAL are such, and are subject to change. + * Those parts are related to implementing virtual subparts of spaces. + * The idea is to keep an Object handy that represents in a more simple + * form what this cell actually is in that subpart. + * Whether this is a speedup or a slowdown remains to be seen. + */ + +public abstract class ZZCellHandle extends ZZCell { +public static final String rcsid = "$Id: ZZCellHandle.java,v 1.5 2001/02/23 08:33:37 ajk Exp $"; + + /** The cell id. + */ + public final String id; + + /** EXPERIMENTAL: the part of the space that this cell is in. + */ + public final ZZSpacePart part; + + /** EXPERIMENTAL: the parsed ID (as provided by the space part) + * of this cell. + * This is supposed to be simply an easier-to-use representation + * of the ID string for the spacepart's dimensions to use. + * For instance, if the spacepart is a matrix, then parsedID could + * be a java.awt.Point -like object that contains the coordinates + * parsed out. + */ + public final Object parsedID; + + public ZZCellHandle(String id, ZZSpacePart part, Object parsedID) { + //if (id == null) throw new NullPointerException(); + this.id = id; + this.part = part; + this.parsedID = parsedID; + } + + public String getID() { + return id; + } + + public boolean equals(Object o) { + if(this == o) return true; + if(!(o instanceof ZZCellHandle)) return false; + ZZCellHandle it = (ZZCellHandle) o; + return id == it.id || id.equals(it.id); + } + + public int hashCode() { + return id.hashCode(); + } +} + diff --git a/Java/ZZCommand.java b/Java/ZZCommand.java new file mode 100644 index 0000000..03c8879 --- /dev/null +++ b/Java/ZZCommand.java @@ -0,0 +1,84 @@ +/* +ZZCommand.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ + +package org.gzigzag; +import java.awt.*; + +/** An abstract class representing a command stored in zz space. + * This should be thought of as a possible successor for ZZExec. Other than + * ZZExec, the object created is not a scripting engine, but rather a + * command which can be executed with a scripting engine. Subclasses of + * ZZCommand are expected to implement ZOb. + *

    + * This class also provides the static method getCommand, which returns the + * ZZCommand associated with a cell, if any. + */ + +public abstract class ZZCommand { + /** Execute some code as a callback from the user interface. + * This is a special execution context which is triggered through user + * action on a user interface. Note that some of the params + * are redundant and only provided for ease. All the other parameters + * can be deduced from view, ctrlview and clicked. + * @param view View where command executed + * @param cview Control view of view where command executed + * @param key The key the user pressed, as string, if any + * @param pt The point the user clicked on, if any + * @param xi The extra object - to get what was clicked, if any + */ + public void execCallback( + ZZCell target, + ZZView view, + ZZView cview, + String key, + Point pt, + ZZScene xi + ) { + exec(target); + } + + // /** Execute with parameters. + // * XXX Needs rethinking of the arguments. + // */ + // public abstract void exec(ZZCell[] params); + + /** Execute with a single parameter. + * An intermediate for calls which don't come from the UI, but from + * somewhere else (e.g., a trigger). + *

    + * Note that UI callbacks are proxied to exec by standard (that is, if + * execCallback isn't overridden.) + */ + public abstract void exec(ZZCell param); + + public static ZZCommand getCommand(ZZCell code) { + // Check if it's a ZOb first: + if(code.s("d.clone", -1) == null && + code.s("d.1", 1) == null) + return null; + ZOb z = ZZDefaultSpace.readZOb(code); + if(z != null && z instanceof ZZCommand) + return (ZZCommand) z; + return null; + } +} diff --git a/Java/ZZConnection.java b/Java/ZZConnection.java new file mode 100644 index 0000000..211c1ba --- /dev/null +++ b/Java/ZZConnection.java @@ -0,0 +1,62 @@ +/* +ZZConnection.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuukka Hastrup + */ + +package org.gzigzag; +/** A simple class defining a data type for connections in a ZZ space. + * Note, that nothing says a connection represented by a ZZConnection + * object should exist. (You can test it with exists() method). + * @see org.gzigzag.ZZCell#getConns() + */ +public class ZZConnection { + /** The start cell */ + public ZZCell c1; + /** The dimension the connection goes along */ + public String dim; + /** The direction of the connection */ + public int dir; + /** The end cell */ + public ZZCell c2; + public ZZConnection() { + } + /** Creates an object representing a link in ZZ space. + * @param c1 The first cell + * @param c2 The second cell + * @param dim The dimension of the connection + * @param dir The direction of the connection + */ + public ZZConnection(ZZCell c1, String dim, int dir, ZZCell c2) { + this.c1 = c1; + this.dim = dim; + this.dir = dir; + this.c2 = c2; + } + + /** Tests whether this connection exists in it's space. */ + public boolean exists() { + if(c1!=null && c2!=null && dim!=null && (dir==1||dir==-1) + && c1.s(dim, dir)==c2) + return true; + else + return false; + + } +} + diff --git a/Java/ZZCursor.java b/Java/ZZCursor.java new file mode 100644 index 0000000..e230224 --- /dev/null +++ b/Java/ZZCursor.java @@ -0,0 +1,70 @@ +/* +ZZCursor.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** A thing that points to a cell or to an offset at a cell. + * It is possible to have read-only ZZCursor objects which will + * throw Errors for the modification attempts. + */ + +public abstract class ZZCursor { +String rcsid = "$Id: ZZCursor.java,v 1.7 2000/11/25 00:36:33 tjl Exp $"; + /** Get the cell the cursor is pointing to. + */ + public abstract ZZCell get(); + /** Set the cursor to point to a cell. + */ + public abstract void set(ZZCell c); + /** Get the offset of this cursor. + */ + public abstract int getOffs(); + /** Set the offset of this cursor. + */ + public abstract void setOffs(int i); + + + /** Set the cursor and offset to the given cursor. + */ + public void set(ZZCursor c) { + set(c.get()); + setOffs(c.getOffs()); + } + + /** The constant to specify that there is no offset + * for this cursor. + */ + static public final int NO_OFFSET = -100; + + public boolean equals(Object o) { + if(this == o) return true; + if(!(o instanceof ZZCursor)) return false; + ZZCursor oth = (ZZCursor) o; + return (oth.get() == get() && oth.getOffs() == getOffs()); + } + + public String toString() { + return "CURS: "+getOffs()+" of "+get()+" Normal: "+super.toString(); + } + +} diff --git a/Java/ZZCursorReal.java b/Java/ZZCursorReal.java new file mode 100644 index 0000000..ad1036a --- /dev/null +++ b/Java/ZZCursorReal.java @@ -0,0 +1,367 @@ +/* +ZZCursorReal.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** A real cursor in a structure. + * This class also implements the commonly used + * static methods for convenience. + */ + +public class ZZCursorReal extends ZZCursor { +String rcsid = "$Id: ZZCursorReal.java,v 1.31.2.1 2002/02/10 12:37:40 bfallenstein Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + ZZCell ccell; + public ZZCursorReal(ZZCell start) { + // ccell = start.h("d.cursor-cargo", -1); + // XXX ?? Which one is right? + ccell = start; + } + public ZZCell get() { return get(ccell); } + public void set(ZZCell c) { set(ccell, c); } + public int getOffs() { return getOffs(ccell); } + public void setOffs(int i) { setOffs(ccell, i); } + + /** Get the cell the given cursor cell or cargo cell is pointing to. + */ + static public final ZZCell get(ZZCell start) { + // XXX Maybe should be less allowing... + return start.h("d.cursor-cargo", -1). + h("d.cursor-list", -1).s("d.cursor", -1); + } + + /** Set the given cursor cell to point to a cell. + */ + static public void setcursor(ZZCell cur, ZZCell c) { + removeFromCursorList(cur); + if (c != null) addToCursorList(cur, c); + trigger(cur); + } + + /** Set the given cursor cargo to point to a cell. + * If a cursor is cargoed already, use it. If no cursor is cargoed, + * create one. + */ + static public void setcargo(ZZCell cargo, ZZCell c) { + if(cargo.s("d.cursor-cargo", -1) == null) + cargo.N("d.cursor-cargo", -1); + setcursor(cargo.h("d.cursor-cargo", -1), c); + } + + /** Set the given cursor cell or cursor cargo cell to point to a cell. + * This routine has an interesting heuristic about creating + * a cell on d.cursor-cargo: if + * the cell is already connected negwards on d.cursor or + * d.cursor-list, + * no cursor cargo cell is created, otherwise it is. + *

    + * XXX should this be deprecated in favor of setcursor and setcargo? + */ + static public final void set(ZZCell start, ZZCell c) { + // A rather intricate check: if there's nothing on d.cursor-cargo, + // create it but only if we're not going negwards on d.cursor or + // d.cursor-list already. + + if(start.s("d.cursor-list", -1) == null && + start.s("d.cursor", -1) == null) { + setcargo(start, c); + } else + setcursor(start, c); + } + + static public void set(ZZCell c, ZZCursor curs) { + set(c, curs.get()); + setOffs(c, curs.getOffs()); + } + + /** Create a new cursor cell pointing to another cell. + * Usually you use set to create a new cell, but sometimes you don't want + * to attach a cargo cell on d.cursor-cargo; create just creates a new + * cell on d.cursor and returns it. + */ + static public final ZZCell create(ZZCell c) { + ZZCell cur = c.N(); + addToCursorList(cur, c); + return cur; + } + + /** Attach a cursor to another one on d.cursor-cargo. + * The first cell is removed from its current d.cursor-cargo rank and + * inserted poswards behind the second one. Thus, the first cursor must + * be a cursor cargo cell, not a real cursor cell (connected negwards + * along d.cursor). + */ + static public final void attach(ZZCell which, ZZCell where) { + if(which.s("d.cursor", -1) != null || + which.s("d.cursor-list", -1) != null) + throw new ZZError("which is a real cursor cell"); + where.insert("d.cursor-cargo", 1, which); + trigger(which); + } + + /** Get the color associated with this cursor in the structure. + */ + public java.awt.Color getColor() { return getColor(ccell); } + + /** Get the color associated with the given cursor in the structure. + */ + static public final java.awt.Color getColor(ZZCell start) { + ZZCell hc = start.h("d.cursor-cargo", -1); + ZZCell col = hc.s("d.1", 1); + if(col == null) + return null; + try { + return new java.awt.Color(Integer.parseInt(col.getText())); + } catch(NumberFormatException e) { + return null; + } + } + + /** Get the color associated with the given cursor, or white. + * Return Color.white if no color is associated in the structure; + * getColor would return null. + */ + static public final java.awt.Color getColorOrWhite(ZZCell start) { + java.awt.Color c = getColor(start); + if(c == null) return java.awt.Color.white; + return c; + } + + /** Set the color associated with the given cursor in the + * structure. + * XXX Move cursor color to another dimension... + */ + static public final void setColor(ZZCell start, java.awt.Color c) { + ZZCell hc = start.h("d.cursor-cargo", -1); + // if(hc.s("d.1", 1) != null) + // throw new Error("Can't set color of cursor: something's there."); + hc.getOrNewCell("d.1",1).setText(String.valueOf(c.getRGB())); + } + + /** Get the color of the first cursor associated with this cell. + * If there is no colored cursor accursing this cell, return null. + */ + static public final java.awt.Color getAccursedColor(ZZCell c) { + Enumeration e = ZZCursorReal.getPointers(c); + while(e.hasMoreElements()) { + java.awt.Color col = ZZCursorReal.getColor((ZZCell)e.nextElement()); + if(col != null) return col; + } + return null; + } + + /** Set the offset of the given cursor. + */ + static public void setOffs(ZZCell c, int i) { + String s = null; + if(i == NO_OFFSET) + s = ""; + else if(i < 0) { + throw new ZZError("Trying to set negative cursor offset!"); + } else + s = String.valueOf(i); + c.h("d.cursor-cargo", -1).setText(s); + trigger(c); + } + + /** Get the offset of the given cursor. + */ + static public int getOffs(ZZCell c) { + String s = c.h("d.cursor-cargo").getText(); + if(s==null || s.equals("")) return NO_OFFSET; + try { + int res = Integer.parseInt(s); + if(res < 0) { + ZZLogger.log( + "Serious: negative cursor offset. Resetting. "+c+" "+res); + setOffs(c, NO_OFFSET); + return NO_OFFSET; + } + return res; + } catch(NumberFormatException e) { + } + return NO_OFFSET; + } + + /** Delete extra cells associated only with the given cursor. + * After this, deleting the cell will remove all traces. + */ + static public void delete(ZZCell c) { + if(c.s("d.cursor-cargo", 1) != null) return; + c = c.s("d.cursor-cargo", -1); + if(c.s("d.cursor-cargo", -1) != null) return; + // Now, c is the cell on the cursor list with no other cargo, + // and is not the original cell. + removeFromCursorList(c); + c.delete(); + } + + static class PointerEnum implements Enumeration { + ZZCell c, cur; + { + p("PointerEnum created with " + c + ", cur = " + cur); + } + + public PointerEnum(ZZCell d) { + c = d; + cur = d.s("d.cursor", 1); + } + + public boolean hasMoreElements() { + boolean rv = cur != null; + p("PointeEnum: hasMoreElements:" + rv); + return rv; + } + + public Object nextElement() { + if (cur == null) throw new NoSuchElementException(); + Object rv = cur; + cur = cur.s("d.cursor-list", 1); + p("PointerEnum: rv = " + rv + ", cur = " + cur); + return rv; + } + } + + /** Find cursors that point to the given cell. + * This enumeration goes through the cells on the cursor list, + * note that each of those may have cursor cargo attached with + * them. There is not yet a function to go through the cursor + * cargoes. + */ + static public Enumeration getPointers(final ZZCell c) { + return new PointerEnum(c); + } + + /** Adjust the cursors on a cell after text insertion or deletion. + * This in- or decrements cursors whose offsets are past a given + * division point. Cursors without offsets remain unchanged. + * @param acc The cell on which the cursors to be changed are. + * @param div The index from which on we want offsets to be changed. + * @param inc The amount by which we want offsets to be changed. + * Negative for deletions. Note that offsets won't be set + * below div, that is after we've deleted seven characters, + * a cursor which was on the third character will be set + * where the first char was, not (7-3=)four posns before that. + */ + static public void adjustCursors(ZZCell acc, int div, int inc) { + Enumeration e = getPointers(acc); + while(e.hasMoreElements()) { + ZZCell curs = (ZZCell)e.nextElement(); + int offs = getOffs(curs); + if(offs != NO_OFFSET && offs >= div) { + if(offs + inc < div) + setOffs(curs, div); + else + setOffs(curs, offs + inc); + } + } + } + + /** Find the visual text offset for the cursor. + * This is purely a convenience routine: if the cursor has an + * offset, it returns that, but if not, it returns half of the + * length of text in the accursed cell. + */ + static public int getVisualTextOffset(ZZCell c) { + int ret = getOffs(c); + if(ret == NO_OFFSET) + ret = get(c).getText().length() / 2; + return ret; + } + + // Private stuff + + static private void removeFromCursorList(ZZCell cur) { + ZZCell acc = cur.s("d.cursor", -1); + if(acc != null) + cur.disconnect("d.cursor", -1); + + ZZCell nb = cur.s("d.cursor-list", 1); + if(acc != null && nb != null) + nb.connect("d.cursor", -1, acc); + + cur.excise("d.cursor-list"); + } + + static private void addToCursorList(ZZCell cur, ZZCell c) { + ZZCell nb = c.s("d.cursor", 1); + if(nb != null) + // insert instead of connect so that when we have headcells on + // looping ranks, d.cursor-list can loop. (Dunno if we need this, + // but kinda seemed right.) + nb.h("d.cursor-list", 1) + .insert("d.cursor-list", 1, cur); + else + c.connect("d.cursor", 1, cur); + } + + static private LoopDetector trigdetect = null; + static private boolean stoptrig = false; + + static private void trigger(ZZCell start) { + p("Cursor trigger triggered"); + boolean wasnull = false; + if(trigdetect == null) { + wasnull = true; + trigdetect = new LoopDetector(); + } + + synchronized(trigdetect) { + try { + ZZCell c = start.h("d.cursor-cargo", -1); + for(; c != null; c = c.s("d.cursor-cargo", 1)) { + if(c.s("d..cursor-trigger", -1) == null) continue; + p(""+c); + + if(trigdetect.isLooping(c)) { + ZZLogger.log("Detected trigger loop while trying "+ + "to set a cursor. Breaking triggering now."); + stoptrig = true; + break; + } + + ZZCell commcell = c.h("d..cursor-trigger", -1); + ZZCommand comm = ZZCommand.getCommand(commcell); + if(comm != null) { + p("Calling trigger command: "+commcell.getText()); + try { + comm.exec(c); + } catch(ZZError e) { + ZZLogger.exc(e, "Cursor trigger exception: "); + stoptrig = true; + } + if(stoptrig) break; + } + } + } finally { + if(wasnull) { + trigdetect = null; + stoptrig = false; + } + } + } + } +} diff --git a/Java/ZZCursorVirtual.java b/Java/ZZCursorVirtual.java new file mode 100644 index 0000000..283f256 --- /dev/null +++ b/Java/ZZCursorVirtual.java @@ -0,0 +1,61 @@ +/* +ZZCursorVirtual.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** A virtual cursor. + * Used by clang to optimize away some puts and gets, e.g. to postpone + * setting the view cursor in the structure until the end of the routine. + * XXX Clang definition needs to be VERY specific about what timings + * are guaranteed in storing things to the structure. + */ +public class ZZCursorVirtual extends ZZCursor { +String rcsid = "$Id: ZZCursorVirtual.java,v 1.7 2000/11/25 00:36:33 tjl Exp $"; + ZZCell val; + int offs; + + public ZZCursorVirtual(ZZCell startVal) { + val = startVal; + offs = NO_OFFSET; + } + public ZZCursorVirtual(ZZCell startVal, int startOffset) { + val = startVal; + offs = startOffset; + } + public ZZCursorVirtual(ZZCursor curs) { + val = curs.get(); + offs = curs.getOffs(); + } + + static public ZZCursorVirtual createFromReal(ZZCell curs) { + return new ZZCursorVirtual(ZZCursorReal.get(curs), + ZZCursorReal.getOffs(curs)); + } + + public ZZCell get() { return val; } + public void set(ZZCell c) { val = c; } + public int getOffs() { return offs; } + public void setOffs(int i) { offs = i; } +} + + diff --git a/Java/ZZDefaultSpace.java b/Java/ZZDefaultSpace.java new file mode 100644 index 0000000..c0d4fc6 --- /dev/null +++ b/Java/ZZDefaultSpace.java @@ -0,0 +1,1087 @@ +/* +ZZDefaultSpace.java + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +/* + * `He looks as though someone hit him on the head,' said Chidder. + * `No-one did, did they?' + * Arthur shook his head. Teppic's face was locked in a gentle + * grin. Whatever his eyes were focused on wasn't occupying the usual + * set of dimensions. + * Terry Pratchett, Pyramids, p.78 + */ + +package org.gzigzag; +import java.awt.*; +import java.util.*; + +/** A "simple" class to create a default space starting at a cell. + * NOT FINISHED. + *

    + * This class is kind of a center for things to be changed later. + * It could be thought of as a bad design but the very point is that + * in order to find the change-sensitive places, you grep the source + * for ZZDefaultSpace and find out what places do what. + *

    + * It is not meant to remain here once things start settling down - probably. + * Or possibly something like it will, defining a schema somewhere for things, + * and other places just reference the schema - adaptive programming, anyone? + * Actually, after we bootstrap, it'll definitely be gone. + */ + +public class ZZDefaultSpace { +public static final String rcsid = "$Id: ZZDefaultSpace.java,v 1.143.2.2 2002/02/16 15:19:25 tuukkah Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + public static final String dimListDimen = "d.2"; + + public static final String sysList = "d.system"; + + // XXX See if abstracting this out would make sense... + static class ZP { + class StrCell { + String name; ZZCell val; + StrCell(String name, ZZCell val) { this.name = name; this.val = val; } + } + String name; + String type; + Vector pars = new Vector(); + ZP(String name, String type) { this.name = name; this.type = type; } + void ap(String name) { + pars.addElement(new String[] {name}); + } + void ap(String name, String val) { + pars.addElement(new String[] {name, val}); + } + void ap(String name, ZZCell val) { + pars.addElement(new StrCell(name, val)); + } + void ap(String name, String val, String val2) { + pars.addElement(new String[] {name, val, val2}); + } + void inh(ZZCell inhfrom) { + pars.addElement(inhfrom); + } + ZZCell ins(ZZCell c) { + ZZCell h = c.N("d.2", 1); + ZZCell ret = h; + h.setText(name); h = h.N("d.1", 1); + h.setText(type); h = h.N("d.1", 1); + for(Enumeration e = pars.elements(); + e.hasMoreElements(); ) { + Object el = e.nextElement(); + if(el instanceof String[]) { + String[] a = (String[])el; + h = h.N("d.2", 1); + h.setText(a[0]); + ZZCell cur = h; + for(int i=1; i + * This function should be used to access those cells + * so that the exact mechanism (dimensions etc.) may be later changed. + *

    + * The return value may be null in the case that there is a + * d.cursor-cargo attached to the cell + */ + static public ZZCell getPossDerefCell(ZZCell c) { + ZZCell cur = c; + // XXX LoopDetector + while(true) { + ZZCell m = ZZCursorReal.get(c); + if(m==null) return cur; + cur = m; + } + } + + // XXX NOTE: THIS GOES NEGWARDS - SPACE <-> SCROLL MAPPING + // MUST BE SAVED BETWEEN RESTARTS + static public ZZCell findScrollCell(ZZCell root, String id) { + ZZCell c = root; + c = c.findText("d.2", -1, "Scrolls"); + if(c==null) throw new ZZError("No scrolls!"); + c = c.findText("d.1", 1, id); + return c; + } + + // Currently: go along + static public ZZCell findInheritableParam(ZZCell start, String id) { + ZZCell n = start; + while(n!=null) { + if(n.getText().equals(id)) return n; + ZZCell h; h = n.h("d.3", -1); + if(h!=null && h!=n) { + h = findInheritableParam(h, id); + if(h!=null) return h; + } + n = n.s("d.2", 1); + } + return null; + } + + static public Font findInheritableParamFont(ZZCell start, String id, + Font def) { + ZZCell fo = findInheritableParam(start, id); + if(fo!=null) { + fo = fo.s("d.1",1); + String name = fo.getText(); + fo = fo.s("d.1",1); + int size = Integer.parseInt(fo.getText()); + return new Font(name,Font.PLAIN,size); + } + return def; + } + + static public float[] paramFloatA(ZZCell start, String id, float[] def, + int nmin) { + ZZCell p = findInheritableParam(start, id); + if(p==null) return def; + ZZCell[] r = p.readRank("d.1", 1, false); + if(r.length < nmin) return def; + float[] arr = new float[r.length]; + for(int i=0; i 0 ) + str = str.substring(0, str.length()-1); + c.setText(str); + } else + c.setText(c.getText() + str); + } + + static public ZZScene getScene(ZZCell view, Component forc) { + p("getScene: startflob"); + Dimension size = forc.getSize(); + FlobSet fs = new FlobSet(size, forc.getForeground(), + forc.getBackground(), forc); + ZZCell c = findInheritableParam(view, "View"); + ZZCell rastname = ZZCursorReal.get(c); + + ZOb frz = readZOb(rastname); + FlobView fr = null; + if(frz != null && frz instanceof FlobView) { + fr = (FlobView)frz ; + } else { + System.out.println("getScene: invalid type: "+frz); + fr = new NullView(); + } + // XXX Signal error + + c = findInheritableParam(view, "CellView"); + + FlobFactory rff = null; + if(c != null) { + ZZCell cfact = ZZCursorReal.get(c); + + ZOb ffzob = readZOb(cfact); + rff = (FlobFactory) ffzob; + } + + p("getScene: raster"); + fr.raster(fs, rff, view, getDimList(view), ZZCursorReal.get(view)); + p("getScene: rastered"); + + if(rff != null) { + Flob rn = rff.placeFlob(fs, rastname, rastname, (float)1.5, size.width, 0, 1, 1, 0); + rn.flobPath="rastname"; + } + return fs; + } + + // static void newScroll(ZZCell root, String id, String addr) { + // } + + static public String getLang(ZZCell window) { + ZZCell c = findInheritableParam(window, "Language"); + if(c == null) return "en"; + c = c.s("d.1"); + if(c == null) return "en"; + if(c.getText().length() < 2) return "en"; + return c.getText(); + } +} diff --git a/Java/ZZDimSpace.java b/Java/ZZDimSpace.java new file mode 100644 index 0000000..e221713 --- /dev/null +++ b/Java/ZZDimSpace.java @@ -0,0 +1,442 @@ +/* +ZZDimSpace.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka (ID-stuff and d.cellcreation by Tuukka Hastrup) + */ +package org.gzigzag; +import java.util.*; + +/** A dimension-centric implementation of a space. + * The internals of this implementation are done by dimension objects + * which know how cells are connected in their dimension. + * @see ZZDimension + */ + +public class ZZDimSpace extends ZZSpace { +public static final String rcsid = "$Id: ZZDimSpace.java,v 1.49 2001/03/07 12:51:24 ajk Exp $"; + +// XXX These should be made garbage collectable ASAP! + + /** ZZDimension given string. */ + Hashtable dims = new Hashtable(); + + /** DimCell given id. */ + Hashtable cells = new Hashtable(); + + /** Space parts by names. */ + Hashtable spaceParts = new Hashtable(); + + /** Contents by id. */ + Hashtable contents = new Hashtable(); + + /** Cell by span. + * If this is null, overlapping spans cannot be searched. + */ + SpanSet spanset = null; + + public ZZDimSpace() { this(false); } + public ZZDimSpace(boolean readonly) { + super(readonly); + } + + /** Obtain the space part corresponding to the given ID. + */ + public ZZSpacePart getSpacePartByID(String id) { + return (ZZSpacePart)spaceParts.get(id); + } + + /** Obtain the ZZDimension corresponding to the given string. + */ + final public ZZDimension d(String s) { + ZZDimension r = (ZZDimension)dims.get(s); + if(r==null) { + r = createDimension(s); + if(r == null) + throw new ZZError("Illegal dimension: '"+s+"'"); + dims.put(s,r); + if (!readonly) updateMasterDimList(s); + } + return r; + } + + /** The cell given by the identifier, if already created. + * Note that this routine only returns existing cells, + * i.e. objects that have already been created. + * Dormant cells or virtual cells need to be obtained through + * getCellByID. + */ + DimCell c(String id) { return (DimCell)cells.get(id); } + + /** Obtain the cell given by the identifier. + */ + public ZZCell getCellByID(String s) { + int at = s.indexOf('@'); + if (at != -1 && getIDOrNull() != null && s.substring(at+1).equals(getID())) { + s = s.substring(0, at); + at = -1; + } + int ind = s.indexOf(':'); + if (at == -1 && ind == -1) { + try { + if (nextID != null) { + long cid = Long.parseLong(s); + long nid = Long.parseLong(nextID); + if (cid >= nid) setNextID("" + (cid+1)); + } + } catch(NumberFormatException e) { + return null; + } + } + if(ind != -1) { + ZZSpacePart part = getSpacePartByID(s.substring(0, ind)); + if(part == null) + throw new ZZError("No such part for cell "+s); + return getCellByID(part, s.substring(ind+1)); + } + return getCellByID(null, s); + } + + /** Obtain a cell, possibly in a space part. + */ + public DimCell getCellByID(ZZSpacePart p, String s0) { + String s = (p != null ? p.id + ":" + s0 : s0); + DimCell ret = null; + if (p != null) ret = p.getCellByID(s0); + if (ret == null) ret = (DimCell) cells.get(s); + if(ret==null) { + DimCell d = new DimCell(s, p, + (p != null ? p.parseIDPart(s0) : null)); + cells.put(d.id, d); + ret = d; + } + return ret; + } + + public DimCell getCellByID(ZZSpacePart p, String s0, Object o) { + String s = p.id + ":" + s0; + DimCell ret = null; + if (p != null) ret = p.getCellByID(s0); + if (ret == null) ret = (DimCell) cells.get(s); + if(ret==null) { + DimCell d = new DimCell(s, p, o); + cells.put(d.id, d); + ret = d; + } + return ret; + } + + public ZZCell[] overlaps(Span sp) { + if(spanset == null) return null; + Object[] o = spanset.overlaps(sp); + ZZCell[] res = new ZZCell[o.length]; + for(int i=0; i + * The reason for this is that it needs to be allowable for + * two cell objects with the same ID to be created without + * too much confusion. + *

    + * This is because we're aiming for Java 1.1 which does not + * have weak references. + */ + public class DimCell extends ZZCellHandle { + + protected DimCell(String id) { + super(id, null, null); + } + protected DimCell(ZZSpacePart part, Object parsedID) { + this(part.generateID(parsedID), part, parsedID); + } + + protected DimCell(String id, ZZSpacePart p, Object o) { + super(id, p, o); + } + + public String[] getRankNames() { + throw new ZZError("getRankNames Not implemented"); + } + + public final ZZSpace getSpace() { return ZZDimSpace.this; } + + public void connect(String dim, ZZCell to) { + this.disconnect(dim, 1); + to.disconnect(dim, -1); + d(dim).connect(this, ((DimCell)to)); + } + public void disconnect(String dim, int dir) { + d(dim).disconnect(this, dir); + } + public void insert(String dim, int dir, ZZCell to) { + d(dim).insert(this, dir, ((DimCell)to)); + } + public void hop(String dim, int steps) { + d(dim).hop(this, steps); + } + + public ZZCell s(String dim, int dir, ZZObs o) { + return d(dim).s(this, dir, o); + } + + public ZZCell N(String dim, int dir, ZZObs o, long flags) + { + synchronized(ZZDimSpace.this) { + DimCell n = getNewCell(id); + insert(dim, dir, n); + if(o != null) + d(dim).s(this, dir, o); + return n; + } + } + + public ZZCell N() { + synchronized(ZZDimSpace.this) { + return getNewCell(id); + } + } + + public void setText(String text) { + synchronized(ZZDimSpace.this) { + ZZCell rootClone = getRootclone(); + if(rootClone != this) { + rootClone.setText(text); + return; + } + if(part != null) { + part.setContent(this, text); + } else { + p("TEXT"); + ZZDimSpace.this.setText(id, text); + textTrig.chg(id); + } + } + } + public void setSpan(Span text) { + synchronized(ZZDimSpace.this) { + ZZCell rootClone = getRootclone(); + if(rootClone != this) { + rootClone.setSpan(text); + return; + } + if(part != null) { + part.setContent(this, text); + } else { + ZZDimSpace.this.setText(id, text); + textTrig.chg(id); + } + } + } + + // XXX part.getText should NOT BE HERE!!!! + public String getText(ZZObs o) { + synchronized(ZZDimSpace.this) { + String s; + // XXX Interaction with slices?? + // XXX Interaction with ZZObs + ZZCell rootClone = getRootclone(); + if(rootClone != this) + return rootClone.getText(o); + if(o != null) textTrig.addObs(id, o); + if(part != null) + s = part.getText(this); + else + s = ZZDimSpace.this.getText(id); + if( s == null ) + return ""; + return s; + } + } + public Span getSpan(ZZObs o) { + synchronized(ZZDimSpace.this) { + ZZCell rootClone = getRootclone(); + // XXX As in getText!!! + if(rootClone != this) + return rootClone.getSpan(o); + if(o != null) textTrig.addObs(id, o); + if(part != null) + return part.getSpan(this); + return ZZDimSpace.this.getSpan(id); + } + } + + public boolean equals(ZZCell c) { + DimCell o = (DimCell)c; + return (this == o) || + (ZZDimSpace.this == o.getSpace() && + id.equals(o.id)); + } + + public void delete() { + synchronized(ZZDimSpace.this) { + ZZDimSpace.this.deleteCell(this); + } + } + + public ZZCell h(String dim, int dir, + boolean ensuremove, ZZObs o) { + ZZCell res = d(dim).h(this, dir, o); + if(ensuremove && (res == this)) return null; + return res; + } + + } + + void deleteCell(ZZCell c) { + for(Enumeration e = dims.keys(); e.hasMoreElements(); ) { + ((ZZDimension)(dims.get(e.nextElement()))).excise((DimCell)c); + } + } + + String nextID="2"; // first cell is home cell, ID 1 + protected void setNextID(String s) { + nextID = s; + } + + /** Get the cell ID relative to a given ID, in creation order. + * @param id Given ID + * @param steps How many steps to take (negative means earlier) + */ + public String getRelativeCellID(String id, int steps) { + try { + long i = Long.parseLong(id); + if(i<0 || i+steps<1) + return null; + return ""+(i+steps); + } catch(NumberFormatException e) { + return null; + } + } + protected String getFreeCellID() { + String curID = nextID; + setNextID(getRelativeCellID(nextID, 1)); + return curID; + } + + // XXX What's this? (compared to the next) + protected DimCell getNewCell(String id) { + return getNewCell(); + } + protected DimCell getNewCell() { + return (DimCell)getCellByID(nextID); + } + public ZZCell newCell() { + return getNewCell(); + } + + /** A simple dimension listing the cells in creation order. + * It uses getRelativeCellID() to find the cells, and will check + * nextID to know whether the cell doesn't exist yet. + * XXX The positive steps taken must be 1 or skipping nextID + * is possible! + */ + class IDDimension extends ZZRODimension { + /** get a cell ID along the dimension. + * XXX Obs doesn't work correctly. + */ + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) { + String id = getRelativeCellID(c.id, steps); + if(id == null || id.equals(nextID)) + return null; + return (DimCell)getCellByID(id); + } + } + + + + // XXX posConnections()? + public ZZCell[] findLongRankHeads(String dim) { return null; } + + public void rmAllObs(ZZObs o) { } + + public String getHomeCellID() { + return "1"; + } + public ZZCell getHomeCell() { + return getCellByID(getHomeCellID()); + } + + /** Create a new dimension with the name s. + * In order to make things fast, this is the method + * to override instead of the d() method (which is final + * exactly because of that). + *

    + * The default version simply returns a new ZZLocalDimension, + * except for d.cellcreation + *

    + * Note that this routine should NOT touch the dimension hash + * but simply return the new dimension. + */ + protected ZZDimension createDimension(String s) { + if(s.indexOf(':') != -1) return createPartDimension(s); + if(!validDim(s)) return null; + ZZDimension l; + if(s.equals("d.cellcreation")) { + l = new IDDimension(); + } else { + l = new ZZLocalDimension(); + } + l.setSpace(this); + return l; + + } + + protected ZZDimension createPartDimension(String s) { + int ind = s.indexOf(':'); + ZZSpacePart part = getSpacePartByID(s.substring(0, ind)); + ZZDimension d = part.getDim(s.substring(ind+1)); + d.setSpace(this); + return d; + } + + +} + diff --git a/Java/ZZDimension.java b/Java/ZZDimension.java new file mode 100644 index 0000000..f4bb936 --- /dev/null +++ b/Java/ZZDimension.java @@ -0,0 +1,178 @@ +/* +ZZDimension.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** Dimension-centric implementation. + * A ZZDimension represents a single dimension of a space. + * It is called with the cell objects that simply contai. + *

    + * Some of the routines are given here so that they may be optimized. + * The absolute core routines that every subclass must implement + * are the abstract routines s, connect and disconnect. + */ + +public abstract class ZZDimension { +public static final String rcsid = "$Id: ZZDimension.java,v 1.25 2001/01/24 08:32:16 veparkki Exp $"; + + /** The space this dimension is affiliated with. */ + protected ZZDimSpace space; + public void setSpace(ZZDimSpace s) { space = s; } + + /** The observer trigger for this dimension. + */ + protected ZZObsTrigger triggers = new ZZObsTrigger(); + + // These three routines need to be implemented + + /** Get another cell steps steps on the dimension from c. + * @param c The cell + * @param steps Number of steps, can be negative. + */ + public abstract ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o); + /** Connect the two cells in this dimension, in order. + */ + public abstract void connect(ZZCellHandle c, ZZCellHandle d); + /** Disconnect the cell in the given direction. + */ + public abstract void disconnect(ZZCellHandle c, int dir); + + // Really throw out the old functions and + // make them so that no-one can override them. + +/* + final public String s(String c, int steps, ZZObs o) + { throw new ZZError("Old dim API"); } + final public void connect(String c, String d) + { throw new ZZError("Old dim API"); } + final public void disconnect(String c, int dir) + { throw new ZZError("Old dim API"); } + */ + + + /** The rest of the operations from here can be overridden + * for optimizations, but do it is not required: the above operations + * are all that is really needed. + */ + + /** Get headcell. + */ + + // XXX loops + public ZZCellHandle h(ZZCellHandle c, int dir, ZZObs o) { + ZZCellHandle orig = c; + ZZCellHandle prev = c; + while((c=s(c, dir, o))!=null) { + prev = c; + // Return lexically maximum id. + if(c.equals(orig)) { + // throw new ZZInfiniteLoop("CIRCULAR HEAD"); + ZZCellHandle lid = c; + while((c=s(c ,dir, o))!=null + && !c.equals(orig)) { + if(c.id.compareTo(lid.id) > 0) lid = c; + } + return lid; + } + } + return prev; + } + + public ZZCellHandle h(ZZCellHandle c, int dir) { + return h(c, dir, null); + } + + final void connect(ZZCellHandle c, int dir, ZZCellHandle d) { + if(dir<0) + connect(d,c); + else + connect(c,d); + } + + public void insert(ZZCellHandle c, int dir, ZZCellHandle d) { + ZZCellHandle p = s(d, 1); + ZZCellHandle m = s(d, -1); + //System.out.println("c = " + c); + //System.out.println("d = " + d); + //System.out.println("p = " + p); + //System.out.println("m = " + m); + + if(p!=null) + disconnect(p, -1); + if(m!=null) + disconnect(m, 1); + if(p!=null && m!=null) + connect(m, p); + ZZCellHandle o = s(c, dir); + if(o!=null) + disconnect(c, dir); + + connect(c,dir,d); + if(o!=null) + connect(d,dir,o); + } + + /** Remove the given cell from this dimension. + */ + public void excise(ZZCellHandle c) { + ZZCellHandle p = s(c, 1); + ZZCellHandle m = s(c, -1); + disconnect(c, 1); + disconnect(c, -1); + if(p!=null && m!=null) + connect(m, p); + } + + public void hop(ZZCellHandle c, int steps) { + if(steps == 0) return; + ZZCellHandle n = s(c, steps); + if(n == null ) return; + insert(n, (steps > 0 ? 1 : -1), c); + } + + /** Find the text in a cell. + * This routine is here so that it may be optimized if desired. + * If it is, then the main space object must remember to update + * this dimension if it keeps a cache in a hash etc. + */ + public ZZCellHandle findText(ZZCellHandle c, int dir, String txt) { + ZZCellHandle cur = s(c, 1); + while(cur != null && cur != c && + !cur.getText().equals(txt)) + cur = s(cur, 1); + if(cur==c) return null; + return cur; + } + + public ZZCellHandle s(ZZCellHandle c, int steps) { + return s(c, steps, null); + } + + // Same goes for these, obviously + // ZZCell intersect(ZZCell c, int dir, ZZDimension d2, ZZCell c2, int dir2); + // ZZCell[] intersectAll(ZZCell c, int dir, ZZDimension d2, ZZCell c2, int dir2); + + + + +} diff --git a/Java/ZZDrawing.java b/Java/ZZDrawing.java new file mode 100644 index 0000000..d14f351 --- /dev/null +++ b/Java/ZZDrawing.java @@ -0,0 +1,106 @@ +/* +ZZDrawing.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.awt.*; + +/** An abstraction of improved drawing primitives. + * We are aiming for Java 1.1, but for instance Java2D provides + * many features we'd like to use, if present. + * Normally, simply testing

    g instanceof Graphics2D
    + * would be sufficient but we want to also be able to compile + * with only the 1.1 libraries available, so we cannot do that. + * Also, we want to be able to hook up to e.g. OpenGL without + * having to create a full Java2D implementation there. + *

    + * This class is used to abstract out any graphics operations that + * are not in java.awt.Graphics. The default of this class is that + * each operation is a no-op (unless otherwise specified). + * All code should function reasonably under such an assumption. + * Subclasses of this object are allowed to implement operations + * in any way they like. + *

    + * TODO: Should make it possible to get drawing parameters + * from either system + * properties (possibly preferable) or the ZZ structure. + */ + +public class ZZDrawing { +public static final String rcsid = "$Id: ZZDrawing.java,v 1.6 2001/03/26 12:41:00 tjl Exp $"; + + /** Get a human-readable string identifying the ZZDrawing + * instance and the settings. + */ + public String getType() { + return "Default 1.1 API -compliant version: no antialiasing or rotation"; + } + + /** The default instance of ZZDrawing for others to use. + */ + static public final ZZDrawing instance = createInstance(); + private boolean qEnabled = true; + + /** Create an instance. + */ + static public ZZDrawing createInstance() { + ZZDrawing ret = null; + Class g2d = null, zzdj2d = null; + try { + g2d = Class.forName("java.awt.Graphics2D"); + zzdj2d = Class.forName("org.gzigzag.ZZDrawingJ2D"); + ret = (ZZDrawing)zzdj2d.newInstance(); + } catch(Exception e) { + ZZLogger.exc(e); + if(g2d != null) { + ZZLogger.log("Graphics2D found but support not compiled in."); + } + } + if(ret == null) ret = new ZZDrawing(); + return ret; + } + + /** Set rendering so that the graphics context will draw + * over translucently, with the given alpha. + */ + public void setAlpha(Graphics g, float alpha) { + } + + /** Set good rendering quality. + * XXX Should take a parameter. + */ + public void setQuality(Graphics g) { + } + + /** Return true if it makes any difference. */ + public boolean enableQuality(boolean t) { + qEnabled = t; + return false; + } + public boolean qualityEnabled() { return qEnabled; } + + /** Set the defaults. To be called on all + * Graphics objects used. + */ + public void setDefaults(Graphics g0) { + } +} + diff --git a/Java/ZZEvObs.java b/Java/ZZEvObs.java new file mode 100644 index 0000000..b572946 --- /dev/null +++ b/Java/ZZEvObs.java @@ -0,0 +1,36 @@ +/* +ZZEvObs.java + * + * Copyright (c) 1999, Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ + +package org.gzigzag; +/** A simple class that observes a cell. + * Note that this class is to be used only for one cell: the two calls + * chg(1) chg(2) can be replaced with chg(2). There will in the future be + * a new class, ZZMultiCellObs that gets a ZZCell[] as its parameter. + */ + +public interface ZZEvObs { +String rcsid = "$Id: ZZEvObs.java,v 1.5 2000/09/19 10:31:58 ajk Exp $"; + /** Called when something is changed. + */ + + void chg(); +} + + diff --git a/Java/ZZExec.java b/Java/ZZExec.java new file mode 100644 index 0000000..acc4052 --- /dev/null +++ b/Java/ZZExec.java @@ -0,0 +1,58 @@ +/* +ZZExec.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.awt.*; + +/** A generic script engine interface. + * ZZExec specifies a way of interfacing various script engines to the ZZ space. + * At the moment, only UI callback functions are allowed - later, it will be + * expanded to a more complete class. + */ + +public interface ZZExec { +String rcsid = "$Id: ZZExec.java,v 1.12 2000/09/19 10:31:58 ajk Exp $"; + /** Execute some code as a callback from the user interface. + * This is a special execution context which is triggered through user + * action on an user interface. Note that some of the params + * are redundant and only provided for ease. All the other parameters + * can be deduced from code, view, ctrlview and clicked. + * @param code Cell to start execution from + * @param view View where command executed + * @param cview Control view of view where command executed + * @param key The key the user pressed, as string, if any + * @param pt The point the user clicked on, if any + * @param xi The extra object - to get what was clicked, if any + */ + void execCallback(ZZCell code, + ZZCell target, + ZZView view, + ZZView cview, + String key, + Point pt, + ZZScene xi + ); + // /** Execute some code with parameters. + // * XXX Needs rethinking of the arguments. + // */ + // public void exec(ZZCell code, ZZCell[] params); +} diff --git a/Java/ZZIter.java b/Java/ZZIter.java new file mode 100644 index 0000000..2bb52ad --- /dev/null +++ b/Java/ZZIter.java @@ -0,0 +1,162 @@ +/* +ZZIter.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.awt.*; +import java.awt.datatransfer.*; +import java.util.*; + +/** Help for iterating along ranks in various ways. + */ + +public class ZZIter { +public static final String rcsid = "$Id: ZZIter.java,v 1.3 2000/11/01 00:39:06 tjl Exp $"; + public static final boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + + /** An callback interface for iterating along a rank with + * the cell number. + */ + public interface NIter { + /** Do whatever you like with this cell, which is the nth from + * wherever we began. + * @return True, if the iteration is to continue (in this direction). + */ + boolean go(ZZCell c, int nth); + } + + /** Go along a rank, starting from a cell, interleaving alternate + * directions. + * @param c The cell to start from. + * @param included Whether the first cell is also included. + * @param d The dimension to go along. + * @param fdir The direction to take the first step in. + * @param iter The callback object. + */ + public static void alternate(ZZCell c, boolean included, + String d, int fdir, NIter iter) { + if(c == null) return; + int i = 0; + if(included) + if(!iter.go(c, 0)) return; + boolean in = true; + boolean op = true; + ZZCell inc = c; + ZZCell opc = c; + while(in || op) { + i++; + if(in) { + inc = inc.s(d, fdir); + if(inc == null) + in = false; + else + if(!iter.go(inc, fdir * i)) + in = false; + } + if(op) { + opc = opc.s(d, -fdir); + if(opc == null) + op = false; + else + if(!iter.go(opc, -fdir * i)) + op = false; + } + } + } + + /** A cell enumeration, with index. + */ + public interface NEnum { + /** Get the next cell. + */ + ZZCell nextCell(); + /** Get the index of the last returned cell from nextCell. + */ + int nth(); + /** Whether there are more cells. + */ + boolean more(); + /** Stop advancing in the current direction. + */ + void stop(); + } + + /** Return an enumeration that alternates between the directions. + * @param c The cell to start from. + * @param included Whether the first cell is also included. + * @param d The dimension to go along. + * @param fdir The direction to take the first step in. + */ + public static NEnum alternate(final ZZCell c, final boolean included, final String d, final int fdir) { + return new NEnum() { + /** Next cell in p or n direction. + */ + ZZCell nextn = c.s(d, -fdir), nextp = c.s(d, fdir); + + int ind = 0; + + boolean started; + + public ZZCell nextCell() { + if(nextn == null && nextp == null) return null; + if(!started) { + started = true; + if(included) return c; + } + // Trick: always change ind, only after see if we have something + // to return. If not, recurse and get the next one from the other side. + if(ind <= 0) { + ind = -ind; + ind ++; + if(nextp == null) + return nextCell(); + ZZCell ret = nextp; + nextp = nextp.s(d, fdir); + return ret; + } + if(ind > 0) { + ind = -ind; + if(nextn == null) + return nextCell(); + ZZCell ret = nextn; + nextn = nextn.s(d, -fdir); + return ret; + } + return null; + } + public int nth() { + return fdir * ind; + } + public void stop() { + if(ind >= 0) nextp = null; + else nextn = null; + } + public boolean more() { + return nextn != null || nextp != null; + } + }; + } +} + + + diff --git a/Java/ZZKeyBindings.java b/Java/ZZKeyBindings.java new file mode 100644 index 0000000..82ff2b6 --- /dev/null +++ b/Java/ZZKeyBindings.java @@ -0,0 +1,39 @@ +/* +ZZKeyBindings.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.awt.event.*; +import java.awt.*; + +/** A generic keybindings driver interface. + * The point of this interface is to allow experimentation + * with different ways of specifying keybindings in the ZigZag structure. + */ + +public interface ZZKeyBindings { +String rcsid = "$Id: ZZKeyBindings.java,v 1.13 2000/09/19 10:31:58 ajk Exp $"; + /** Perform a particular key or mouse + * event associated with a particular view. + */ + void perform(InputEvent k, ZZView v, ZZView ctrlv, ZZScene xi); +} + diff --git a/Java/ZZKeyBindings0.java b/Java/ZZKeyBindings0.java new file mode 100644 index 0000000..8a4e317 --- /dev/null +++ b/Java/ZZKeyBindings0.java @@ -0,0 +1,45 @@ +/* +ZZKeyBindings0.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.awt.event.*; + +/** A very simple keybindings class which is hardcoded for the cursor keys. + * Does nothing else. OBSOLETE. + */ + /* +public class ZZKeyBindings0 implements ZZKeyBindings { +public static final String rcsid = "$Id: ZZKeyBindings0.java,v 1.7 2000/09/19 10:31:58 ajk Exp $"; + ZZCell current; + public void perform(KeyEvent k, ZZView v) { + // XXX Hardcoded - should update automatically from the structure.. + switch(k.getKeyCode()) { + case k.VK_UP: v.move(0,-1); break; + case k.VK_DOWN: v.move(0,1); break; + case k.VK_LEFT: v.move(-1,0); break; + case k.VK_RIGHT: v.move(1,0); break; + } + } +} + +*/ +class LIJFSELFJLISEFJLSEFSF { } diff --git a/Java/ZZKeyBindings1.java b/Java/ZZKeyBindings1.java new file mode 100644 index 0000000..7e9d910 --- /dev/null +++ b/Java/ZZKeyBindings1.java @@ -0,0 +1,319 @@ +/* +ZZKeyBindings1.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.awt.*; +import java.awt.event.*; + +/** The first meaningful keybindings class. + * A stateless class which looks along d.2 for a string matching + * the result of the getKeyText method of the java.awt.event.KeyEvent class. + */ + +public class ZZKeyBindings1 implements ZZKeyBindings { +public static final String rcsid = "$Id: ZZKeyBindings1.java,v 1.61.2.2 2001/08/16 14:51:24 bfallenstein Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) ZZLogger.log(s); } + static final void pa(String s) { ZZLogger.log(s); } + + /** Create ZZKeyBindings1. + @deprecated Use the noarg constructor instead. */ + ZZKeyBindings1(ZZExec x) { this(); } + ZZKeyBindings1() {} + + Point origpt; + boolean dragging = false; + + public void perform(InputEvent ie, ZZView v, ZZView ctrlv, ZZScene xi) { + ZZCell vcell = v.getViewcell(); + + String t = null; + p(" "+ie); + if(ie instanceof KeyEvent) { + /* + * This is quite complicated - more complicated than it + * should be but Java seems to screw up key events quite + * nicely for us... + * We want to have Shift-Alt-X, for example, which on some + * Javas needs quite a bit of attention. + */ + KeyEvent k = (KeyEvent) ie; + char c= k.getKeyChar(); + int kc = k.getKeyCode(); + String kt = KeyEvent.getKeyText(kc); + String kbychar = new String(new char[] {c}); + p("Have: "+c+" "+kc+" '"+kt+"' '"+kbychar+"'"); + if((c == k.CHAR_UNDEFINED + // k.CHAR_UNDEFINED changed between JDK1.1 and 1.2 + || c == 0x0 || c == 0xFFFF // needed for cross-compiling + || kc == k.VK_DELETE + || kc == k.VK_BACK_SPACE) + && kc != 0) + t = kt; + else + t = kbychar; + p("Chose: "+t); + if(t.equals("\n")) t = "Enter"; + if(t.equals("\t")) t = "Tab"; + if(t.equals("\033")) t = "Esc"; + if(t.equals("") || + Character.isISOControl(t.charAt(0)) || + k.isAltDown() || k.isControlDown() || + kt.equals("Left") || // These need shift. + kt.equals("Right") || + kt.equals("Up") || + kt.equals("Down") + ) { + p("Maybe rechoosing"); + if(kc != 0) + t = kt; + if(k.isShiftDown()) t = "Shift-"+t; + } + if(k.isAltDown()) t = "Alt-"+t; + if(k.isControlDown()) t = "Ctrl-"+t; + + p("KEYTEXT: '" + t + "', was by kt: '"+kt+"' and by char: '" + +kbychar+"'"); + if(t==null) return; + perf(t, null, v, ctrlv, t, null, xi); + } else if(ie instanceof MouseEvent) { + MouseEvent m = (MouseEvent)ie; + String modstr = ""; + + if(m.isAltDown()) modstr = "Alt-"+modstr; + if(m.isControlDown()) modstr = "Ctrl-"+modstr; + if(m.isShiftDown()) modstr = "Shift-"+modstr; + + Point pt = new Point(m.getX(), m.getY()); + String mec = null; + ZZCell targ = null; + if(m.getID() == m.MOUSE_CLICKED) { + mec = "Clicked"; + dragging = false; + // If it was a cell, give it as the target. + // XXX Need we really do this here? + Object ob = xi.getObjectAt(m.getX(), m.getY()); + if(ob instanceof ZZCell) targ = (ZZCell) ob; + + // Call applitude manager, to change app if necessary + // (Actually, just realized: because we do this here, before + // we call perf(), the applitude bindings of the new + // applitude are used, which is exactly what we want!) + ApplitudeMgr.clicked(vcell, xi, pt); + } else if(m.getID() == m.MOUSE_PRESSED) { + mec = "Pressed"; + origpt = pt; + dragging = false; + } else if(m.getID() == m.MOUSE_DRAGGED) { + mec = "Dragged"; + if(!dragging) { + perf(modstr+"MouseStartDrag", null, v, ctrlv, null, origpt, xi); + dragging = true; + } + } else if(m.getID() == m.MOUSE_RELEASED) { + mec = "Released"; + dragging = false; + // XXX EndDrag? + } else + return; + int but = 0; + int mod = m.getModifiers(); + if((mod & m.BUTTON1_MASK) != 0) but = 1; + else if((mod & m.BUTTON2_MASK) != 0) but = 2; + else if((mod & m.BUTTON3_MASK) != 0) but = 3; + + t = modstr+"Mouse"+mec+but; + + p("MOUSE: '"+t+"': event was "+m); + + perf(t, targ, v, ctrlv, null, pt, xi); + + } + } + + /** Get the key bindings mode cursor associated with this window. + * Does currently not create a new one if there is none. + * Instead, returns null. + */ + public static ZZCell getModeCursor(ZZCell window) { + return window.h("d.bind", 1, true); + } + + /** Get the key bindings mode cell associated with this window. + * Set to default mode if no mode is there. + */ + public static ZZCell getMode(ZZCell window) { + ZZCell c0 = getModeCursor(window); + if(c0 == null) { + p("NO BIND YET: SET CURS"); + c0 = window.N("d.bind", 1); + ZZCell cur0 = ZZDefaultSpace.findOnSystemlist( + window.getSpace(), "Bindings", false).s("d.1", 1); + ZZCursorReal.set(c0, cur0); + ZZCursorReal.setColor(c0, new Color(0xaf5a00)); + } + return ZZCursorReal.get(c0); + } + + void perf(String id, ZZCell target, + ZZView v, ZZView ctrl, String key, Point pt, ZZScene xi) { + p("PERF: '"+id+"'"); + ZZCell vcell = v.getViewcell(); + ZZCell accursed = ZZCursorReal.get(vcell); + ZZCell cvcell = ctrl.getViewcell(); + ZZCell cur = getMode(vcell); + p("BIND CURS: "+cur+" "+(cur!=null?cur.getID():null)); + + /** Use applitude bindings? + * As not all views show applitude data, views which do have to + * have an "appbindings" structparam to declare the bindings of the + * applitude currently prefered by this window shall be used. + */ + boolean useAppBinds = false; + + /** Is the binding found an applitude binding? + * This affects how the bindings mode is changed. + */ + boolean isAppBind = false; + + ZZCell raster = + ZZDefaultSpace.findInheritableParam(vcell, "View"); + if(raster != null) raster = ZZCursorReal.get(raster); + if(raster != null) raster = raster.h("d.clone", -1); + if(raster != null) raster = raster.s("d.1", 2); + if(ZZDefaultSpace.findInheritableParam(raster, "appbindings") != null) + useAppBinds = true; + if(raster != null) raster = + ZZDefaultSpace.findInheritableParam(raster, "databindings"); + if(raster != null) raster = raster.intersect("d.1",1,cur,"d.clone",1); + + ZZCell craster = + ZZDefaultSpace.findInheritableParam(cvcell, "View"); + if(craster != null) craster = ZZCursorReal.get(craster); + if(craster != null) craster = craster.h("d.clone", -1); + if(craster != null) craster = craster.s("d.1", 2); + if(craster != null) craster = + ZZDefaultSpace.findInheritableParam(craster, "ctrlbindings"); + if(craster != null) craster = craster.intersect( + "d.1", 1, cur, "d.clone", 1); + + ZZCell binding = null; + if(raster != null) { + binding = ZZDefaultSpace.findInheritableParam(raster, id); + p("Tried by view"); + } + if(binding == null && useAppBinds) { + ZZCell app = ApplitudeMgr.getAppBindsForWin(vcell); + binding = ZZDefaultSpace.findInheritableParam(app, id); + p("Tried by applitude"); + if(binding == null && key != null && key.length() > 0) { + binding = ZZDefaultSpace.findInheritableParam(app, "INSERT"); + p("Tried by applitude INSERT"); + } + if(binding == null) { + binding = ZZDefaultSpace.findInheritableParam(app, "DEFAULT"); + p("Tried by applitude DEFAULT"); + } + if(binding != null) + isAppBind = true; + } + if(binding == null && craster != null) { + binding = ZZDefaultSpace.findInheritableParam(craster, id); + p("Tried by ctrl view"); + } + if(binding == null) { + binding = ZZDefaultSpace.findInheritableParam(cur, id); + p("Tried by cur"); + } + if(binding == null && key != null && key.length() == 1) { + binding = ZZDefaultSpace.findInheritableParam(cur, "INSERT"); + } + if(binding == null) { + binding = ZZDefaultSpace.findInheritableParam(cur, "DEFAULT"); + p("Tried by DEFAULT"); + } + if(binding == null && + ZZDefaultSpace.findInheritableParam(cur, "EDITBINDS") != null) { + ZZCell cellview = accursed.h("d.cellview", true), ecur = null; + p("cellview: "+cellview); + if(cellview != null) + cellview = cellview.s("d.1", 2); + if(cellview != null) + cellview = ZZDefaultSpace.findInheritableParam(cellview, "EditBindings"); + if(cellview != null) + ecur = cellview.s("d.1", 1); + p("editbinds cur: "+ecur); + if(ecur == null) + ecur = ZZDefaultSpace.findOnSystemlist(vcell.getSpace(), + "EditBindings", true).getOrNewCell("d.1", 1); + if(ecur != null) { + binding = ZZDefaultSpace.findInheritableParam(ecur, id); + p("Tried by editbinds"); + if(binding == null && key != null && key.length() == 1) { + binding = ZZDefaultSpace.findInheritableParam(ecur, "INSERT"); + p("Tried by editbinds INSERT"); + } + if(binding == null) { + binding = ZZDefaultSpace.findInheritableParam(ecur, "DEFAULT"); + p("Tried by editbinds DEFAULT"); + } + } + } + + p("BINDING: "+binding); + if(binding != null) { + ZZCell bc = binding.s("d.1", 1); + p("Bind command cell: "+bc); + if(bc == null) { + System.out.println("AUGH! NO BINDING"); + return; + } + ZZCell nextstate = bc.h("d.3", -1, true); + if(nextstate != null) { + if(!isAppBind) + ZZCursorReal.set(getModeCursor(vcell), nextstate); + else + ApplitudeMgr.setAppBindsForWin(vcell, nextstate); + } + ZZCommand comm = null; + if(bc.getRootclone().s("d.xeq") == null) + comm = ZZCommand.getCommand(bc); + if(comm != null) + comm.execCallback( + target, + v, ctrl, + key, pt, xi + ); + else + new ZZPrimitiveActions().execCallback( + bc, + target, + v, ctrl, + key, pt, xi + ); + return; + } else if (key != null && key.equals("Esc")) { + v.getViewcell().getSpace().undo(); + } + } +} + diff --git a/Java/ZZKeyHacks.java b/Java/ZZKeyHacks.java new file mode 100644 index 0000000..49191eb --- /dev/null +++ b/Java/ZZKeyHacks.java @@ -0,0 +1,105 @@ +/* +ZZKeyHacks.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benja Fallenstein + */ +package org.gzigzag; +import java.awt.*; +import java.awt.event.*; + +/** Hacks to work around Java's inconsistent, ideosyncratic key events. + * Everything in this class is static, but there are (static) variables + * for the "detected state of the system": e.g., how this Java VM handles + * umlauts. + *

    + * Currently, detects whether we get umlauts through KEY_PRESSED; if not, + * invokes them at KEY_TYPED. + */ + +public class ZZKeyHacks { +public static final String rcsid = "$Id: ZZKeyHacks.java,v 1.1.2.2 2001/04/08 15:17:51 bfallenstein Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) ZZLogger.log(s); } + static final void pa(String s) { ZZLogger.log(s); } + + // Java is really screwy about what keyevents get + // pressed and what are typed. We want to catch both. + + // It seems that at least on my platform and keybindings, + // this is the totally unreasonable but working way to get + // them. + + // Ouch. + + // FIXME: This is a REALLY REALLY BAD QUICK HACK to make the + // Finnish special letters work. The problem? We don't get a + // KEY_PRESSED for them. Damn Java! + + /** Whether we ever got an umlaut from a KEY_PRESSED event. + * If this is set to true, we ignore KEY_TYPED events. If it is set to + * false, KEY_TYPED events with umlauts in them get processed like + * KEY_PRESSED events. As KEY_PRESSED events occur before KEY_TYPED + * events, this is a gain. + */ + static boolean gotPressedUmlaut; + + /** The start of the Unicode character range we treat as umlauts. */ + static final int firstumlaut = 0x00C0; + + /** The end of the Unicode character range we treat as umlauts. */ + static final int lastumlaut = 0x00FD; + + /** Do the hacks on this key event. + * Currently, does the umlaut trick, as well as the testing whether we + * need it. + */ + static public KeyEvent keyEventHack(KeyEvent e) { + if(gotPressedUmlaut) return e; + + int id = e.getID(), c = e.getKeyChar(); + boolean umlaut = (c >= firstumlaut) && (c <= lastumlaut); + + if(!umlaut) return e; + + if(id == e.KEY_PRESSED) { + gotPressedUmlaut = true; + } else if(id == e.KEY_TYPED) { + return new KeyEvent(e.getComponent(), e.KEY_PRESSED, e.getWhen(), + e.getModifiers(), e.getKeyCode(), + e.getKeyChar()); + } + + return e; + } + + /** Reset the state, so as if the program was fired up anew. + * This sets back all information gathered about the Java VM so far + * and re-initializes the class. Currently this is used for testing + * purposes only: the TestUmlauts JUnit test suite needs to be able to + * run different tests emulating different kinds of VMs. + */ + static public void reset() { + gotPressedUmlaut = false; + } + + // Initialize the class by calling reset() a first time. + { reset(); } +} + diff --git a/Java/ZZLocalDimension.java b/Java/ZZLocalDimension.java new file mode 100644 index 0000000..884cf1c --- /dev/null +++ b/Java/ZZLocalDimension.java @@ -0,0 +1,89 @@ +/* +ZZLocalDimension.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** Dimension-centric implementation of a locally + * stored dimension. + */ +public class ZZLocalDimension extends ZZDimension { +public static final String rcsid = "$Id: ZZLocalDimension.java,v 1.14 2000/11/30 08:44:32 ajk Exp $"; + public static final boolean dbg = true; + final static void p(String s) { if(dbg) ZZLogger.log(s); } + final static void pa(String s) { ZZLogger.log(s); } + + /** Connections to the positive direction. */ + Hashtable cp = new Hashtable(); + /** Connections to the negative direction. */ + Hashtable cm = new Hashtable(); + + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) { + String s = c.id; + if(o != null) triggers.addObs(s, o); + if(steps>0) + while(steps-- > 0 && s != null) { + s = (String)cp.get(s); + if(o != null) triggers.addObs(s, o); + } + else + while(steps++ < 0 && s != null) { + s = (String)cm.get(s); + if(o != null) triggers.addObs(s, o); + } + + if(s==null) return null; + return (ZZCellHandle)space.getCellByID(s); + } + public void connect(ZZCellHandle c, ZZCellHandle d) { + disconnect(c, 1); + disconnect(d, -1); + /* XXX: This is from 0.3 branch, don't know if this + should be chosen instead of the above + if(cp.get(c.id) != null || + cm.get(d.id) != null) + throw new ZZConnectWouldBreakError("localdim"); + */ + cp.put(c.id, d.id); + cm.put(d.id, c.id); + triggers.chg(c.id); + triggers.chg(d.id); + } + public void disconnect(ZZCellHandle c, int dir) { + String o; + if(dir>0) { + o = (String)cp.get(c.id); + if(o!=null) { + cp.remove(c.id); + cm.remove(o); + } + } else { + o = (String)cm.get(c.id); + if(o!=null) { + cm.remove(c.id); + cp.remove(o); + } + } + triggers.chg(c.id); + } + +} diff --git a/Java/ZZLogger.java b/Java/ZZLogger.java new file mode 100644 index 0000000..f99bd54 --- /dev/null +++ b/Java/ZZLogger.java @@ -0,0 +1,83 @@ +/* +Main.java + * + * Copyright (c) 1999, 2000 Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho and Tuomas Lukka. + */ + +package org.gzigzag; +import java.lang.reflect.*; +import java.io.*; + +/** A static package for logging things into a file. + * Used for providing ZZ developers with debug output to help them + * solve crashes. + */ + +public class ZZLogger { + public static PrintWriter logfile = null; + + private static boolean syslog = false; + + public static void tryInitSyslog() { + try { + SysLogger.init(); + } catch (UnsatisfiedLinkError e) { + exc(e); + return; + } + syslog = true; + } + + public static void exc(Throwable t, String s) { + log(""+s); + exc(t); + } + + public static void exc(Throwable t) { + if(t instanceof InvocationTargetException) { + Throwable t1 = ((InvocationTargetException)t).getTargetException(); + verblog("InvokeException content: "); + exc(t1); + } + log(""+t); + t.printStackTrace(); + if(logfile != null) { + t.printStackTrace(logfile); + logfile.flush(); + } + } + + public static void log(String s) { + System.err.println(s); + if (syslog) SysLogger.log(s); + filelog(s); + } + + private static void filelog(String s) { + if (logfile != null) { + logfile.println(s); + logfile.flush(); + } + } + + public static void verblog(String s) { + if (syslog) SysLogger.verblog(s); + } +} diff --git a/Java/ZZModule.java b/Java/ZZModule.java new file mode 100644 index 0000000..960e167 --- /dev/null +++ b/Java/ZZModule.java @@ -0,0 +1,91 @@ +/* +ZZModule.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.awt.*; +import java.util.*; +import java.io.*; + +/** An extension module implementing some Java functionality. + * Extension module classes should have a single static public member + * named module of this type. + *

    + * Clang commands implemented in extension modules are accessed + * through the Module.FUNCTION interface. + */ + +public abstract class ZZModule { +String rcsid = "$Id: ZZModule.java,v 1.14 2000/10/30 15:25:47 tjl Exp $"; + + /** Perform an action. + * For instance, if the action Foo.BAR is used in a cell, the method + * org.gzigzag.module.Foo.module.action("BAR",...) is called. + * @param id The name of the action. + * @param code The cell that the code was obtained from. + * @param target The cell that is the target of the action. Either the + * cell the cursor is on, or the cell that the user clicked + * on with the mouse. + * @param view The view the user activated this action from + * @param cview The control view associated + * @param key The event identifier + * @param pt The point clicked by the mouse + * @param xi The ZZScene describing the current contents of the window. + * May be used e.g. to draw XOR cursors. + */ + public void action(String id, + ZZCell code, + ZZCell target, + ZZView view, ZZView cview, String key, Point pt, ZZScene xi) { + } + + /** Returns a ZOb for the given id. + * A cell parameter is not needed: since it's a ZOb, the caller must + * explicitly read them (and set the Component) after getting it. + * @see ZOb + */ + public ZOb newZOb(String id) { return null; } + + // Static routines for loading + + static Hashtable mods = new Hashtable(); + + /** Obtain the ZZModule object corresponding to the given string. + * This is the module member of the corresponding class. + */ + static public ZZModule getModule(String name) { + ZZModule m; + if((m= (ZZModule)mods.get(name)) == null) { + try { + Class clazz = Class.forName("org.gzigzag.module."+name); + m = + (ZZModule)clazz.getField("module").get(null); + } catch(Exception e) { + ZZLogger.exc(e); + ZZLogger.log("Error while loading module '"+name+"'"); + return null; + } + mods.put(name, m); + } + return m; + } + +} diff --git a/Java/ZZObs.java b/Java/ZZObs.java new file mode 100644 index 0000000..d4635f1 --- /dev/null +++ b/Java/ZZObs.java @@ -0,0 +1,36 @@ +/* +ZZObs.java + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +/** A simple class that observes something. + * This class cannot distinguish what caused the event - either + * the event has to be filtered prior to this or the whole thing reread + * in any case. + */ + +public interface ZZObs { +String rcsid = "$Id: ZZObs.java,v 1.11 2000/09/19 10:31:58 ajk Exp $"; + /** Called when something is changed. + */ + void chg(); +} diff --git a/Java/ZZObsTrigger.java b/Java/ZZObsTrigger.java new file mode 100644 index 0000000..a38e922 --- /dev/null +++ b/Java/ZZObsTrigger.java @@ -0,0 +1,196 @@ +/* +ZZObs.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka, queuing and enable/disable by Rauli Ruohonen + */ + +package org.gzigzag; +import java.util.*; + +/** A class used to trigger ZZObses. + */ + +public class ZZObsTrigger { +String rcsid = "$Id: ZZObsTrigger.java,v 1.6.2.1 2001/04/08 16:13:59 ajk Exp $"; + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + // XXX Store weak references, not hard ones! + private static Vector allTrigs = new Vector(); + private static Hashtable obsQueue = new Hashtable(); + private static Hashtable obsDisabled = new Hashtable(); + + ZZObsTrigger() { + allTrigs.addElement(this); + } + + /** An object which keeps track of the observations of a single + * ZZObs. + */ + class Gob { + /** Linked list of Gobs, plus list of all objects that this + * Gob observes. + * This is a tricky part and this is also what makes us blazingly + * fast. And difficult to explain. + *

    + * First of all, there is a key for every object that this + * gob's obs has been addObs'ed for. + * The value depends on whether there are other gobs observing + * the same thing. If there are, then the hashtables form a linked + * list. If not, or if this is the last element of the linked + * list, the value in the Hashtable is this gob. + * That may seem odd until you realize that 1) hashtables can't + * store nulls, and 2) this is a pointer that is + * very likely to be in a register so fast to compare with + * the reference. + */ + Hashtable next = new Hashtable(); + /** The backward links. Only necessary links are stored. */ + Hashtable prev = new Hashtable(); + ZZObs obs; + } + + /** Key: ZZObs; Value: Gob. */ + Hashtable gobs = new Hashtable(); + + /** Key: Object (trigger); Value: Gob. */ + Hashtable trigs = new Hashtable(); + + + /** Called when something is changed. + * This call removes instances of the ZZObses triggered from + * all existing ZZObsTrigger objects. + */ + public synchronized void chg(Object o) { + Gob g,pg=null; + Hashtable next=trigs; + while((g = (Gob)next.get(o)) !=null && g!=pg) { + pg=g; + if(!chg(g.obs)) next=g.next; + } + // XXX This shouldn't be necessary! (views should use triggers) + ZZUpdateManager.chg(); + } + public static boolean chg(ZZObs obs) { + // XXX This shouldn't be necessary! (views should use triggers) + ZZUpdateManager.chg(); + synchronized(obsQueue) { + if(obsDisabled.containsKey(obs)) return false; + obsQueue.put(obs,obs); + for(int i=0; i only the + * event thread may call general ZZ structure -using code. + */ + public static void runObsQueue() { + p("runObsQueue enter"); + synchronized(obsQueue) { + while(obsQueue.size()>0) { + p("STARTTRIGSEQ "+(obsQueue.size())); + /* Trigger the queued observers in some order */ + Hashtable q=obsQueue; + obsQueue=new Hashtable(); + for(Enumeration e=q.keys();e.hasMoreElements();) + try { + ((ZZObs)e.nextElement()).chg(); + } catch(Exception ex) { + ZZLogger.exc(ex); + System.out.println("EXCEPTION WHILE TRIGGERING!"); + } + p("ENDTRIGSEQ "+(obsQueue.size())); + } + } + p("runObsQueue leave"); + } + + /** Enable/disable an observer. + * If an observer is disabled, chg(o) won't trigger it. chg(o) calls + * made before calling this method will be unaffected - that is, if + * obs is in obsQueue, it will be triggered whether it is enabled or not. + */ + public static void setEnabled(ZZObs obs,boolean t) { + if(t) obsDisabled.remove(obs); + else obsDisabled.put(obs,obs); + } +} diff --git a/Java/ZZPath.java b/Java/ZZPath.java new file mode 100644 index 0000000..2bc35ce --- /dev/null +++ b/Java/ZZPath.java @@ -0,0 +1,202 @@ + +/* +ZZPath.java + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/* Possibly publish this API later on? */ +interface PathOp { + /** Apply the pathop to the from cell, attaching the observer o + * to observe the relevant information about all the cells on the way. + * These objects do not need to attach observers to the from + * cell but all the others, including the last cell. + * @return null if the requested cell does not exist. + */ + ZZCell apply(ZZCell from, ZZObs o); +} + +/** A class to represent paths in the structure. + * It used to also be a notifier but that was changed: now it's just + * an abstract "path". + */ + +public class ZZPath { +public static final String rcsid = "$Id: ZZPath.java,v 1.26 2000/10/18 14:35:31 tjl Exp $"; + static public boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + + PathOp[] arr = new PathOp[0]; + + public ZZPath() { } + + static final String drdim(ZZCell c) { + return ZZDefaultSpace.getPossDerefCell(c).getText(); + } + + static final int drdir(ZZCell c) { + String s = ZZDefaultSpace.getPossDerefCell(c).getText(); + if(s.equals("-")) return -1; + if(s.equals("+")) return +1; + return Integer.parseInt(s); + } + + static final String drtext(ZZCell c) { return drdim(c); } + + /** Creates a ZZPath from cells. + * The cells give the path through a simple format in d.1 and d.2: + * The first cell is the operation name, and then follow the + * parameters, just like in the other calls for this class. + *

    +	 * 	STEP  dim  n
    +	 *	HEAD dim dir
    +	 *	END dim dir
    +	 *	FIND dim dir str
    +	 * 
    + * Note that this is not automatically updated each time the path + * or the cursors in the path change - to be up to date, you need + * to create a new path each time. However, this is not such a + * time-consuming operation. + *

    + * "HEAD" is now deprecated in favor of "END". + */ + static public ZZPath createFromStructure1(ZZCell c) { + ZZPath p = new ZZPath(); + while(c!=null) { + ZZCell[] args = c.readRank("d.1", 1, false); + String s = c.getText(); + if(s.equals("STEP")) { + if(args.length < 2) + throw new ZZError("Not enough args for '"+s+"'"); + p = p.step(drdim(args[0]), drdir(args[1])); + } else if(s.equals("HEAD") || s.equals("END")) { + if(args.length < 2) + throw new ZZError("Not enough args for '"+s+"'"); + p = p.headcell(drdim(args[0]), drdir(args[1])); + } else if(s.equals("FIND")) { + if(args.length < 3) + throw new ZZError("Not enough args for '"+s+"'"); + p = p.untilstring(drdim(args[0]), + drdir(args[1]), drtext(args[2])); + } else { + throw new ZZError("ZZPath syntax: '"+s+"'"); + } + c = c.s("d.2", 1); + } + return p; + } + + /** Reads the structure through this path to obtain a cell. + * @param from The cell to start from + * @param error Whether not finding a cell is an error. + * This is for coder convenience: the message + * in the exception thrown is descriptive of + * where the not-found leg of the path was. + * @param o The observer to attach. + */ + public ZZCell readFrom(ZZCell from, boolean error, ZZObs o) { + if(from == null) + throw new ZZError("Can't read path from null!"); + ZZCell n = from; + for(int i=0; i + * Even worse, it is string-based: it doesn't hassle you about structure, + * it simply takes the string in the cell and executes a corresponding command. + *

    + * The one nifty thing is the module support: + * Given a function name like ZZMbox.FOO + * it will first dynamically load the class org.gzigzag.module.ZZMbox + * (this will later be probably xanadu.zz.module), and run its action + * routine (see ZZModule and ZZMbox docs for details). + */ + +public class ZZPrimitiveActions implements ZZExec { +public static final String rcsid = "$Id: ZZPrimitiveActions.java,v 1.141.2.8 2002/03/05 18:21:50 bfallenstein Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) ZZLogger.log(s); } + static final void pa(String s) { ZZLogger.log(s); } + public ZZPrimitiveActions() {} + + public static java.io.PrintWriter textlog; + + ZZCell findPar(ZZCell view, String param) { + ZZCell cur = view.s("d.2", 1); + while(cur!=null) { + if(cur.getText().equals(param)) + return cur.s("d.1", 1); + cur = cur.s("d.2", 1); + } + return null; + } + int getDimstrAsInt(String param) { + if(param.equals("X")) return 0; + else if(param.equals("Y")) return 1; + else if(param.equals("Z")) return 2; + return -1; + } + String getDim(ZZCell view, String param) { + ZZCell c = findPar(view, param); + if(c!=null) + return c.getText(); + int ind=getDimstrAsInt(param); + + return ZZDefaultSpace.getDimList(view)[ind]; + } + String D(ZZCell view, String param) { + return getDim(view, param); + } + + void exchangeCells(ZZCell view1, ZZCell view2) { + String[] ds1 = ZZDefaultSpace.getDimList(view1); + String[] ds2 = ZZDefaultSpace.getDimList(view2); + Hashtable ds = new Hashtable(); + ds.put(ds1[0], ds1[0]); + ds.put(ds1[1], ds1[1]); + ds.put(ds2[0], ds2[0]); + ds.put(ds2[1], ds2[1]); + ZZCell c1 = ZZCursorReal.get(view1); + ZZCell c2 = ZZCursorReal.get(view2); + for(Enumeration e = ds.keys(); + e.hasMoreElements(); ) { + String d = (String)e.nextElement(); + ZZCell n1 = c1.s(d, -1); c1.disconnect(d, -1); + ZZCell n2 = c2.s(d, -1); c2.disconnect(d, -1); + if(n2 != null) c1.connect(d, -1, n2); + if(n1 != null) c2.connect(d, -1, n1); + n1 = c1.s(d, 1); c1.disconnect(d, 1); + n2 = c2.s(d, 1); c2.disconnect(d, 1); + if(n2 != null) c1.connect(d, 1, n2); + if(n1 != null) c2.connect(d, 1, n1); + } + } + + // Set view cursor + void svc(ZZCell view, ZZCell to) { + if(to == null || view == null) return; + ZZCursorReal.set(view, to); + } + + ZZCell findOtherView(ZZCell view) { + ZZCell oth = view.s("d.ctrlview", -1); + if(oth == null) + oth = view.s("d.ctrlview", 1); + if(oth == null) { + System.out.println("CNCTPAIR OTHER NOT FOUND"); + } + return oth; + } + + /** Move the cursor. + * @return Whether a timestamp would be reasonable. + */ + boolean move(ZZCell view, ZZCell viewCursor, String vdim, int dir, + ZZCell realView, ZZCell realCtrl) { + if ( viewCursor == null ) return false; + String[] ss = ZZDefaultSpace.getDirActionWaitingAndClear(view); + if(ss!=null) { + String s = ss[0]; + if(s.equals("CNCTI")) { + cnct(view, viewCursor, true, vdim, dir); + } else if(s.equals("NEW")) { + viewCursor.N(vdim, dir); +// } else if(s.equals("NEWANDEDIT")) { +// svc(view, viewCursor.N(vdim, dir)); +// switchcursmode(view); +// XXX Problem: this doesn't switch keybindings mode + } else if(s.equals("EXCISE")) { + viewCursor.excise(vdim); + } else if(s.equals("DISC")) { + viewCursor.disconnect(vdim, dir); + } else if(s.equals("HOP")) { + viewCursor.hop(vdim, dir); + } else if(s.equals("CLONE")) { + ZZCell clone = ZZCursorReal.get(realView).zzclone(); + viewCursor.insert(vdim, dir, clone); + } else if(s.equals("CLONECTRL")) { + ZZCell clone = ZZCursorReal.get(realCtrl).zzclone(); + viewCursor.insert(vdim, dir, clone); + } else if(s.equals("CNCTPAIR")) { + smartconnect(viewCursor, vdim, dir, ZZCursorReal.get( + findOtherView(view))); + } else if(s.equals("CNCTC")) { + cnctcln(view, viewCursor, true, vdim, dir); + } else if(s.equals("CNCT")) { + cnct(view, viewCursor, false, vdim, dir); + } else if(s.equals("SORTALPH")) { + ZZUtil.sortRank(viewCursor, vdim, dir, + new ZZUtil.Comparator() { + public int compare(ZZCell c1, ZZCell c2) { + return c1.getText().compareTo(c2.getText()); + } + }, true); + } else if(s.equals("END")) { + svc(view, viewCursor.h(vdim, dir)); + } else if(s.equals("MONOCHUG")) { + if(ss[1] == null || ss[1].equals("")) { + p("Move: "+s+" "+vdim+" "+dir); + ZZDefaultSpace.storeDirActionWaiting(view, s); + ZZDefaultSpace.storeDirWaiting(view, vdim, dir); + return false; + } + // monochug operation + int ddir = (ss[2].equals("+") ? 1 : -1); + String ddim = ss[1]; + ZZCell targ = viewCursor.s(ddim, ddir); + if(targ == null) return false; + targ = targ.s(vdim, dir); + if(targ == null) return false; + if(targ.s(ddim, -ddir) != null) + return false; + viewCursor.disconnect(ddim, ddir); + viewCursor.connect(ddim, ddir, targ); + } else if(s.equals("FINDTEXT")) { + String tf = ZZDefaultSpace.getInbuf(view.getSpace(), false); + if(tf == null || tf.equals("")) return false; + for(ZZCell c = viewCursor.s(vdim, dir); + c != null && c != viewCursor; + c = c.s(vdim, dir)) { + if(c.getText().indexOf(tf) >= 0) { + svc(view, c); + return true; + } + } + } + return true; + } else { + String s = ZZDefaultSpace.getInbuf(view.getSpace(), true); + /* + * * DO NOT DO IT. TOO CONFUSING FOR USERS. + if(s != null && !s.equals("")) { + ZZCell c = view.getSpace().getCellByID(s); + if(c == null) { + throw new ZZError("No such cell: '"+s+"'..."); + } + smartconnect(viewCursor, vdim, dir, c); + } + */ + svc(view, viewCursor.s(vdim, dir)); + // Do timestamp: it's a motion. + return true; + } + } + +// or only mark, if ... + void mrkmv(ZZCell v, ZZCell vc, String dim, int dir) { + // New way: in the view + synchronized(v.getSpace()) { + ZZCell m = v.s("d.mark", 1); + boolean had = false; + ZZCell m0 = v; + while(m!=null) { + if(m.h("d.mark-set",-1) + ==vc) { had = true; break; } + m0 = m; + m = m.s("d.mark", 1); + } + if(had) { + // Delete the whole relation cell. + // The ranks collapse around it just right. + m.delete(); + } else { + ZZCell mark = vc.N("d.mark-set", 1); + m0.connect("d.mark", mark); + } + } + if(dim != null && dir != 0) + move(v, vc, dim, dir, null, null); + } + + // XXX Combine the following two. + // Connect + void cnct(ZZCell v, ZZCell vc, boolean inclCurs, String dim, int dir) { + // Also clears mark. + ZZCell[] cs; + synchronized(v.getSpace()) { + cs = ZZDefaultSpace.getMark(v); + ZZDefaultSpace.clearMark(v); + ZZCell cur = (inclCurs ? vc : null); + for(int i=0; i 1) { + if(toks[1].equals("CTRL")) { usec=true; } + + if(toks[1].equals("+")) { dx=null; dir = 1; } + if(toks[1].equals("-")) { dx=null; dir = -1; } + + if(toks[1].equals("C+")) { dx=null; dir = 1; usec=true; } + if(toks[1].equals("C-")) { dx=null; dir = -1; usec=true; } + + if(toks[1].equals("X+")) { dx="X"; dir = 1; } + if(toks[1].equals("X-")) { dx="X"; dir = -1; } + if(toks[1].equals("Y+")) { dx="Y"; dir = 1; } + if(toks[1].equals("Y-")) { dx="Y"; dir = -1; } + if(toks[1].equals("Z+")) { dx="Z"; dir = 1; } + if(toks[1].equals("Z-")) { dx="Z"; dir = -1; } + + if(toks[1].equals("X")) { dx="X"; dir = 0; } + if(toks[1].equals("Y")) { dx="Y"; dir = 0; } + if(toks[1].equals("Z")) { dx="Z"; dir = 0; } + + if(toks[1].equals("CX+")) { dx="X"; dir = 1; usec=true; } + if(toks[1].equals("CX-")) { dx="X"; dir = -1; usec=true; } + if(toks[1].equals("CY+")) { dx="Y"; dir = 1; usec=true; } + if(toks[1].equals("CY-")) { dx="Y"; dir = -1; usec=true; } + if(toks[1].equals("CZ+")) { dx="Z"; dir = 1; usec=true; } + if(toks[1].equals("CZ-")) { dx="Z"; dir = -1; usec=true; } + + if(toks[1].equals("T0+")) { sndedge = 0; dir = 1; } + if(toks[1].equals("T0-")) { sndedge = 0; dir = -1; } + if(toks[1].equals("T1+")) { sndedge = 1; dir = 1; } + if(toks[1].equals("T1-")) { sndedge = 1; dir = -1; } + } + + if(usec && ctrlView == null) { + callbackFailed(c, "NO CONTROL VIEW"); + ZZDefaultSpace.getDirActionWaitingAndClear(dataView); + // Do not timestamp taking the operation out, either, + // because putting it in was not stamped. + // XXX Some strange bug? + code.getSpace().stamp(); + return; + } + + if(!usec) { + view = dataView; + otherView = ctrlView; + viewCursor = dataCursor; + zzv = zzdv; + } else { + view = ctrlView; + otherView = dataView; + viewCursor = ctrlCursor; + zzv = zzcv; + } + + if(dx != null) + vdim = D(view, dx); + if(target != null) + viewCursor = target; + + ZZCell coderoot = code.getRootclone(); + if(coderoot.s("d.xeq") != null) { + org.gzigzag.flowing.FlowingClang.run + (coderoot, new Data(ctrlView, dataView, key), false); + } else if(toks[0].equals("NEW") || + toks[0].equals("NEWANDEDIT") || + toks[0].equals("EXCISE") || + toks[0].equals("DISC") || + toks[0].equals("CNCTI") || + toks[0].equals("CNCTPAIR") || + toks[0].equals("CLONE") || + toks[0].equals("CLONECTRL") || + toks[0].equals("CNCT") || + toks[0].equals("CNCTC") || + toks[0].equals("HOP") || + toks[0].equals("MONOCHUG") || + toks[0].equals("SORTALPH") || + toks[0].equals("FINDTEXT") || + toks[0].equals("END")) { + + // XXX Should this be implemented differently, so that the + // dir doesn't need to be stored in the structure? + ZZDefaultSpace.storeDirActionWaiting(view, toks[0]); + dontClearAction = true; + if (dx != null) { + move(view, viewCursor, vdim, dir, dataView, ctrlView); + // Move has commands that take more than one dir. + } else { + dontStamp = true; + } + } else if(toks[0].equals("CRSR")) { + dontStamp = + ! move(view, viewCursor, vdim, dir, dataView, ctrlView); + // Move has commands that take more than one dir. + dontClearAction = true; + } else if(toks[0].equals("EXCHANGECELLS")) { + exchangeCells(dataView, ctrlView); + } else if(toks[0].equals("ORIGINAL")) { + svc(view, viewCursor.h("d.clone", -1)); + } else if(toks[0].equals("NEXTCLONE")) { + ZZCell foo = viewCursor.s("d.clone", 1); + if(foo != null) svc(view, foo); + } else if(toks[0].indexOf("MOUSE") == 0) { + Object ob = xi.getObjectAt(pt.x, pt.y); + ZZCursor cc=null; + ZZCell cell=null; + + if(ob instanceof ZZCursor) { + cc = (ZZCursor)ob; + cell=cc.get(); + } else if(ob instanceof ZZCell) { + cell=(ZZCell)ob; + } else return; + if(cell==null) return; + + if(toks[0].equals("MOUSESETC")) { + svc(view, cell); + fastany = false; + } + else if(toks[0].equals("MOUSESETCTXT")) { + if(cc==null) return; + svc(view, cell); + ZZCursorReal.setOffs(view, cc.getOffs()); + fastany = false; + } + else if(ctrlCursor!=null && c.equals("MOUSEEXEC")) { + pa("MOUSEEXEC"); + this.execCallback(ctrlCursor, cell, + zzv, zzcv, null, null, null); + + } + else if(toks[0].equals("MOUSEMARK")) { + mrkmv(view, cell, null, 0); + fastany = false; + } else if(toks[0].equals("MOUSESETDIMOTHER")) { + setdim(otherView, dx, cell); + } else { + callbackFailed(c, "Unknown MOUSE code"); + return; + } + } + else if(ctrlCursor!=null && c.equals("EXEC")) { + // This is an interesting one: it just means "execute + // whatever cell is visible in the control view. + // So we call ourselves... + // XXX inherit xi really? + ZZCommand comm = ZZCommand.getCommand(ctrlCursor); + if(comm != null) + comm.execCallback(viewCursor, + zzdv, zzcv, null, pt, xi); + else + this.execCallback(ctrlCursor, viewCursor, + zzdv, zzcv, null, pt, xi); + } + else if(c.equals("HERA1")) { + // Execute the first, primitive calling sequence of + // a Heraclitus Clang primitive poswards on d.2 from + // the command cell + ZZCell hc = code.s("d.2", 1); + if(hc == null) throw new ZZError("No heraclitus1 prim!"); + ZZCell curspar = code.N(); + ZZCell curs1 = code.N(); + ZZCell curs2 = curs1.N("d.1", 1); + ZZCursorReal.set(curs1, ctrlView); + ZZCursorReal.set(curs2, dataView); + ZZCursorReal.set(curspar, curs1); + try { + p("Enter heraclitus: "); + org.gzigzag.heraclitus.HeraclitusClang.execute( + hc, curspar); + p("Exit heraclitus"); + } finally { + ZZCursorReal.delete(curs1); + ZZCursorReal.delete(curs2); + ZZCursorReal.delete(curspar); + curs1.delete(); + curs2.delete(); + curspar.delete(); + } + } + + else if(toks[0].equals("MARK")) + mrkmv(view, viewCursor, dx, dir); + else if(toks[0].equals("DIM")) + chugdim(view, dx, dir); + else if(toks[0].equals("SETDIMS")) + setdims(view, viewCursor); + else if(toks[0].equals("RASTER")) + hopraster(view, dir!=0 ? dir : 1); + else if(toks[0].equals("FFACTORY")) + hopffactory(view, dir!=0 ? dir : 1); + else if(toks[0].equals("HOME")) { + ZZCell home = view.getSpace().getHomeCell(); + svc(view, home); + } + else if(toks[0].equals("HOMECLR")) { + ZZCell home = view.getSpace().getHomeCell(); + ZZCell datarec = ZZDefaultSpace + .findInheritableParam(dataView, "CursorRecovery"); + if(datarec!=null) ZZCursorReal.attach(dataView, datarec); + ZZCell ctrlrec = ZZDefaultSpace + .findInheritableParam(ctrlView, "CursorRecovery"); + if(ctrlrec!=null) ZZCursorReal.attach(ctrlView, ctrlrec); + svc(dataView, home); + svc(ctrlView, home); + ZZCell dimlist = + ZZDefaultSpace.findDefaultDimlist(home); + setdims(dataView, dimlist); + setdims(ctrlView, dimlist); + + ZZDefaultSpace.clearMark(dataView); + + } else if(toks[0].equals("DELETESCRAM")) { + ZZCell mv = null; + mv = viewCursor.s(D(view, "X"), -1); + if(mv == null) + mv = viewCursor.s(D(view, "X"), +1); + if(mv == null) + mv = viewCursor.s(D(view, "Y"), -1); + if(mv == null) + mv = viewCursor.s(D(view, "Y"), +1); + if(mv == null) + mv = viewCursor.s(D(view, "Z"), -1); + if(mv == null) + mv = viewCursor.s(D(view, "Z"), +1); + if(mv == null) + mv = view.getSpace().getHomeCell(); + svc(view, mv); + viewCursor.delete(); + } + + else if(toks[0].equals("QUIT")) { + // Commit changes to space here + viewCursor.getSpace().commit(); + SafeExit.exit(0); + } + else if(toks[0].equals("APPENDINPUT")) { + if(key != null && key.length() == 1) + ZZDefaultSpace.appendInbuf(viewCursor.getSpace(), key); + dontStamp = true; + } else if(toks[0].equals("BACKSPACEINPUT")) { + ZZDefaultSpace.appendInbuf(viewCursor.getSpace(), null); + dontStamp = true; + } else if(toks[0].equals("CLRINPUT")) { + ZZDefaultSpace.getInbuf(viewCursor.getSpace(), true); + dontStamp = true; + } else if(toks[0].equals("GOTO")) + do_goto(view); + + // Sound span adjustment. These will be useful + // in a more general way later on. + else if(toks[0].equals("SNDL")) { + Span sp = viewCursor.getSpan(); + ZZCell n = viewCursor.s("d.2", sndedge*2-1); + Span nsp = n.getSpan(); + if(sp!=null && nsp!=null) { + Span[] sps; + if(sndedge==0) { + sps = nsp.adjustEdgeLocked(100000000*dir, sp, 500000000); + n.setSpan(sps[0]); + viewCursor.setSpan(sps[1]); + } else { + sps = sp.adjustEdgeLocked(100000000*dir, nsp, 500000000); + viewCursor.setSpan(sps[0]); + n.setSpan(sps[1]); + } + } else if(sp!=null) + viewCursor.setSpan( + sp.adjustEdge(sndedge, 100000000 * dir)); + } else if(toks[0].equals("SNDS")) { + Span sp = viewCursor.getSpan(); + + if(sp!=null) + viewCursor.setSpan( + sp.adjustEdge(sndedge, 100000000 * dir)); + } else if(toks[0].equals("SNDSPLIT")) { + ZZCell n = viewCursor.N("d.2", 1); + Span sp = viewCursor.getSpan(); + if(sp!=null) { + Span[] sps = sp.splitInHalf(); + viewCursor.setSpan(sps[0]); + n.setSpan(sps[1]); + } + } else if(toks[0].equals("SNDJOIN+")) { + ZZCell o = viewCursor.s("d.2", 1); + if(o!=null) { + Span sp1 = viewCursor.getSpan(); + Span sp2 = o.getSpan(); + if(sp1!=null && sp2!=null) { + Span spj = sp1.join(sp2, 500000000); + if(spj!=null) { + viewCursor.setSpan(spj); + // XXX ??? Try to absorb links? + o.delete(); + } + } + } + } else if(toks[0].equals("SWAPCRSR")) { + ZZCell view2 = findOtherView(view); + ZZCell view2c = ZZCursorReal.get(view2); + svc(view, view2c); + svc(view2, viewCursor); + } else if(toks[0].equals("FETCH")) { + svc(findOtherView(view), viewCursor); + } else if(toks[0].equals("PUICOPY")) { + ZZUtil.puiCopy(viewCursor); + } else if(toks[0].equals("PUIPASTE")) { + ZZUtil.puiPaste(viewCursor); + } else if(toks[0].equals("PUICOPYLINE")) { // Copy along y-dim + ZZUtil.puiCopy(viewCursor, ZZCursorReal.get( + dataView.s("d.dims", 1) + .s("d.dims", 1) + ).getText()); + } else if(toks[0].equals("PUICOPYRANK")) { // Copy along y-dim + // insert \n between + // cells + ZZUtil.puiCopyRank(viewCursor, ZZCursorReal.get( + dataView.s("d.dims", 1) + .s("d.dims", 1) + ).getText()); + } else if(toks[0].equals("TXTINSERT")) { + // XXX ??? + p("Txtins: '"+key+"'"); + CharScroll cs = (CharScroll) + Scroll.obtain(viewCursor.getSpace(), + "textinput"); + long offs = cs.curEnd(); + cs.append(key); + long offs2 = cs.curEnd()-1; + VStream.insert(new ZZCursorReal(view), + Span.create( + Address.scrollOffs(cs, offs), + Address.scrollOffs(cs, offs2) + ) + ); + } else if(toks[0].equals("SWITCHCURSMODE")) { + switchcursmode(view); + dontStamp = true; + } else if(toks[0].equals("SWITCHOFFCURSMODE")) { + switchcursmodeoff(view); + } else if(toks[0].equals("CTXTHOME")) { + if (ZZCursorReal.getOffs(view) == ZZCursorReal.NO_OFFSET) return; + ZZCursorReal.setOffs(view, 0); + dontStamp = true; + } else if(toks[0].equals("CTXTEND")) { + if (ZZCursorReal.getOffs(view) == ZZCursorReal.NO_OFFSET) return; + ZZCursorReal.setOffs(view, viewCursor.getText().length()); + dontStamp = true; } else if(toks[0].equals("CTXTSOL")) { // SOL = start of line + if (ZZCursorReal.getOffs(view) == ZZCursorReal.NO_OFFSET) return; + int cur = ZZCursorReal.getOffs(view); + String line = viewCursor.getText(); + if (cur >= line.length()) cur = line.length()-1; + if (line.charAt(cur) == '\n') --cur; + for (int i = cur; i >= 0; --i) { + p("seeking SOL: charAt = " + line.charAt(i)); + if (line.charAt(i) == '\n') { + cur = i+1; + break; + } + if (i == 0) { + cur = i; + break; + } + } + if (cur > line.length()) cur = line.length(); + if (cur < 0) cur = 0; + ZZCursorReal.setOffs(view, cur); + dontStamp = true; + } else if(toks[0].equals("CTXTEOL")) { // EOL = start of line + if (ZZCursorReal.getOffs(view) == ZZCursorReal.NO_OFFSET) return; + int cur = ZZCursorReal.getOffs(view); + String line = viewCursor.getText(); + for (int i = cur; i < line.length(); ++i) { + if (line.charAt(i) == '\n') { + cur = i; + break; + } + if (i == line.length() - 1) { + cur = line.length(); + break; + } + } + if (cur > line.length()) cur = line.length(); + if (cur < 0) cur = 0; + ZZCursorReal.setOffs(view, cur); + dontStamp = true; + } else if(toks[0].equals("CTXTCRSR")) { + int cur = ZZCursorReal.getOffs(view); + if(cur == ZZCursorReal.NO_OFFSET) return; + cur += dir; + if(cur < 0) cur = 0; + if(cur > viewCursor.getText().length()) + cur = viewCursor.getText().length(); + ZZCursorReal.setOffs(view, cur); + dontStamp = true; + } else if(toks[0].equals("VSTRMCRSR")) { + if(ZZCursorReal.getOffs(view) == ZZCursorReal.NO_OFFSET) + throw new ZZError("Need cursor offset"); + + if(!Stream.move( + new ZZCursorReal(view), + VStream.dim, + dir)) { + callbackFailed("VSTRMCRSR", "nothing there"); + } else { + fastany = false; + } + + dontStamp = true; + } else if(toks[0].equals("VSTRMJUMP")) { + int offs = ZZCursorReal.getOffs(view); + String txt = viewCursor.getText(); + ZZCell next = viewCursor.s("d.2", dir!=0 ? dir : 1); + + offs = dir >= 0 ? txt.indexOf(' ', offs) + : txt.lastIndexOf(' ', offs - 1); + if(offs > -1) + ZZCursorReal.setOffs(view, offs + (dir<0 ? 0 : 1)); + else if(next != null) { + svc(view, next); + ZZCursorReal.setOffs(view, + dir<0 ? next.getText().length() : 0); + } else + ZZCursorReal.setOffs(view, dir<0 ? 0 : txt.length() - 1); + dontStamp = true; + } else if(toks[0].equals("VSTRMSPLIT")) { + ZZCell next = viewCursor.N("d.2", dir!=0 ? dir : 1); + if(viewCursor.getSpan() == null) { + int offs = ZZCursorReal.getOffs(view); + String txt = viewCursor.getText(); + String one = txt.substring(0, offs), + two = txt.substring(offs); + if(dir >= 0) { + viewCursor.setText(one); next.setText(two); + } else { + viewCursor.setText(two); next.setText(one); + } + } // XXX Split spans, too + ZZCursorReal.setOffs(view, 0); + svc(view, next); + dontStamp = true; + } else if(toks[0].equals("CTXTINSERT") || + toks[0].equals("CTXTBKSP") || + toks[0].equals("CTXTDEL")) { + dontStamp = true; + if(viewCursor.getSpan() != null) { + System.out.println("Can't modify span"); + return; + } + int cur = ZZCursorReal.getOffs(view); + // Make sure it fits. + if(cur > viewCursor.getText().length()) + cur = viewCursor.getText().length(); + if(cur == ZZCursorReal.NO_OFFSET) return; + StringBuffer s = new StringBuffer(viewCursor.getText()); + if(toks[0].equals("CTXTINSERT")) { + p("CTXTINSERT: key = " + key); + String ik = key; + if (ik != null && ik.equals("Enter")) ik = "\n"; + // Don't insert e.g. "Shift" + if(ik != null && ik.length() == 1) { + if(textlog != null) { + textlog.print(ik); + // flush all the time so nothing is lost + // in a crash + textlog.flush(); + } + s.insert(cur, ik); + cur += 1; + } + } else if(toks[0].equals("CTXTBKSP")) { + if(cur > 0) { + String str = s.toString(); + // XXX delete requires JDK 1.2 + s = new StringBuffer( str.substring(0, cur-1) ); + s.append(str.substring(cur)); + + cur -= 1; + } + } else if(toks[0].equals("CTXTDEL")) { + if(cur < viewCursor.getText().length()) { + String str = s.toString(); + s = new StringBuffer( str.substring(0, cur) ); + s.append(str.substring(cur+1)); + } + } + viewCursor.setText(s.toString()); + ZZCursorReal.setOffs(view, cur); + } else if(toks[0].equals("CURSEL")) + cursel(view, dir, false); + else if(toks[0].equals("SELEVATE")) + cursel(view, dir, true); + else if(toks[0].equals("CreateCursors")) { + ZZCell h = view.getSpace().getHomeCell(); + ZZCell sc = ZZDefaultSpace + .findOnSystemlist(view.getSpace(), "SysCursors", false); + if(sc != null) { + ZZDefaultSpace.newSysCursor(sc, h, Color.blue.brighter()); + ZZDefaultSpace.newSysCursor(sc, h, Color.yellow.darker()); + ZZDefaultSpace.newSysCursor(sc, h, Color.red.darker()); + ZZDefaultSpace.newSysCursor(sc, h, new Color(180, 0, 255)); + } else + callbackFailed(c, "SysCursors list required"); + } else if(toks[0].equals("NEWVIEWS")) { + // Create a new view pair. + ZZDefaultSpace.newViewPair(view.getSpace()); + } else if(toks[0].equals("EDITVIEW") || toks[0].equals("HELP")) { + boolean help = toks[0].equals("HELP"); + ZZCell home = dataView.getSpace().getHomeCell(); + ZZCell rl = home.findText("d.2", 1, "AllViews"); + rl = rl.s("d.1", 1); + rl = rl.findText("d.2", 1, "Edit"); + if (rl == null) throw new ZZError("Edit view not found"); + rl = rl.getOrNewCell("d.clone", 1); + ZZCell cursCell; + if(help) { + cursCell = home.N(); + ZZCursorReal.set(cursCell, + viewCursor.getOrNewCell("d.help", 1)); + } else + cursCell = dataView; + + ZZCell win = ZZDefaultSpace.newToplevelView(dataView.getSpace(), + help ? "Help" : "Edit", + help ? 100 : 512, help ? 100 : 449, + help ? 400 : 512, help ? 400 : 100, + rl, null, // XXX Defaultbind? + null, cursCell, + null, + Color.white); // XXX PREFERENCE!!! + } else if(toks[0].equals("EDITHACK")) { + new ZZTextView(view); + } else if(toks[0].equals("APPLITUDE")) { + ApplitudeMgr.rotateWindowApp(view, dir); + } else if(toks[0].equals("GETSPACEID")) { + target.setText(target.getSpace().getID()); + } else if(toks[0].equals("SETSPACEID")) { + target.getSpace().setID(target.getText()); + } else if(toks[0].equals("UPDATEWINS")) { + ZZWindows.update(); + } else if(toks[0].equals("ACCURSE")) { + // Make the cell accursed in the other window a cursor to the + // cell accursed in window for which the action occured. + ZZCursorReal.set(ZZCursorReal.get(otherView), viewCursor); + } else if(toks[0].equals("UNDO")) { + code.getSpace().undo(); + dontStamp = true; + } else if(toks[0].equals("REDO")) { + code.getSpace().redo(); + dontStamp = true; + } else if(toks[0].equals("COMMIT")) { + code.getSpace().commit(); + } + else + callbackFailed(c, "UNKNOWN CODE"); + + p("ZZPrimitiveActions: postlude: "+fastany+" "+zzv+" "+ + dontClearAction); + + if(fastany) + ZZUpdateManager.setFast(zzv); + + // Clear the waiting dir action + if(!dontClearAction) + ZZDefaultSpace.getDirActionWaitingAndClear(view); + + if(!dontStamp) + code.getSpace().stamp(); + } + } + + static ZZCell addAct(ZZCell s, String name, String act) { + ZZCell n1 = s.N("d.2", 1); + n1.setText(name); + ZZCell n2 = n1.N("d.1", 1); + n2.setText(act); + return n2; + } + + static void addAct(ZZCell s, String name, String act, ZZCell after) { + ZZCell c = addAct(s, name, act); + after.insert("d.3", 1, c); + } + + static void setModeColor(ZZCell mode, Color col) { + if(col == null) { + if(mode.s("d.color") != null) + mode.disconnect("d.color", 1); + } else { + ZZCell c = mode.getOrNewCell("d.color", 1); + c.setText(String.valueOf(col.getRGB())); + } + } + + /** Puts a number of default key bindings to the structure. + * ZZKeyBindings1 structure is assumed (list on d.2 of keys + * and on d.1 the responses) + */ + static public void putDefBinds(ZZCell start, ZZCell editstart) { + start.setText("Normal mode"); + editstart.setText("Text edit bindings"); + + // Apparently, this wasn't actually necessary! + /* + ZZCell dir = start.N("d.2", 1); + dir = dir.N("d.3", -1); + dir.setText("Motion"); + */ + ZZCell dir = start; + + ZZCell editmode = start.N("d.1", 1); + setModeColor(editmode, Color.white); + + editmode.setText("Edit mode"); + editmode.N("d.2").setText("EDITBINDS"); + addAct(editmode, "Tab", "SWITCHOFFCURSMODE", dir); + addAct(editmode, "Esc", "SWITCHOFFCURSMODE", dir); + + ZZCell curs = editstart; + curs.setText("Text edit mode"); + addAct(curs, "Ctrl-A", "CTXTSOL"); + addAct(curs, "Ctrl-E", "CTXTEOL"); + addAct(curs, "End", "CTXTEND"); + addAct(curs, "Home", "CTXTHOME"); + addAct(curs, "Right", "CTXTCRSR +"); + addAct(curs, "Left", "CTXTCRSR -"); + addAct(curs, "Backspace", "CTXTBKSP"); + addAct(curs, "Delete", "CTXTDEL"); + addAct(curs, "MouseClicked1", "MOUSESETCTXT"); + addAct(curs, "DEFAULT", "CTXTINSERT"); + + + ZZCell cursel = editmode.N("d.1", 1); + cursel.setText("Cursel mode"); + cursel.N("d.color").setText("CURSOR"); + + addAct(cursel, " ", "", dir); + addAct(cursel, "Esc", "", dir); + addAct(cursel, "Alt-C", "", dir); + addAct(cursel, "Left", "CURSEL -"); + addAct(cursel, "Right", "CURSEL +"); + addAct(cursel, "Up", "SELEVATE -"); + addAct(cursel, "Down", "SELEVATE +"); + + addAct(cursel, "j", "CURSEL -"); + addAct(cursel, "l", "CURSEL +"); + addAct(cursel, "i", "SELEVATE -"); + addAct(cursel, ",", "SELEVATE +"); + + addAct(cursel, "s", "CURSEL C-"); + addAct(cursel, "f", "CURSEL C+"); + addAct(cursel, "e", "SELEVATE C-"); + addAct(cursel, "c", "SELEVATE C+"); + + // Quote starts insert buffer mode... + ZZCell bufins = cursel.N("d.1", 1); + bufins.setText("Quotebuf"); + setModeColor(bufins, Color.pink); + + addAct(bufins, "DEFAULT", "APPENDINPUT"); + addAct(bufins, "Backspace", "BACKSPACEINPUT"); + addAct(bufins, "\"", "", dir); + addAct(bufins, "Esc", "", dir); + + // Totally temporary + addAct(dir, "Tab", "SWITCHCURSMODE", editmode); + addAct(dir, "Alt-C", "", cursel); + + addAct(dir, "\"", "CLRINPUT", bufins); + + addAct(dir, "l", "CRSR X+"); + addAct(dir, "j", "CRSR X-"); + addAct(dir, "i", "CRSR Y-"); + addAct(dir, ",", "CRSR Y+"); + addAct(dir, "k", "CRSR Z+"); + addAct(dir, "K", "CRSR Z-"); + + // Caps locked + addAct(dir, "L", "CRSR X+"); + addAct(dir, "J", "CRSR X-"); + addAct(dir, "I", "CRSR Y-"); + + addAct(dir, "a", "MONOCHUG"); + + addAct(dir, "f", "CRSR CX+"); + addAct(dir, "s", "CRSR CX-"); + addAct(dir, "e", "CRSR CY-"); + addAct(dir, "c", "CRSR CY+"); + addAct(dir, "d", "CRSR CZ+"); + addAct(dir, "D", "CRSR CZ-"); + + // Caps locked + addAct(dir, "F", "CRSR CX+"); + addAct(dir, "S", "CRSR CX-"); + addAct(dir, "E", "CRSR CY-"); + addAct(dir, "C", "CRSR CY+"); + + addAct(dir, "Right", "CRSR X+"); + addAct(dir, "Left", "CRSR X-"); + addAct(dir, "Up", "CRSR Y-"); + addAct(dir, "Down", "CRSR Y+"); + + addAct(start, "Ctrl-C", "PUICOPY"); + addAct(start, "Ctrl-Shift-C", "PUICOPYLINE"); + addAct(start, "Ctrl-Alt-C", "PUICOPYRANK"); + addAct(start, "Ctrl-V", "PUIPASTE"); + + addAct(start, "-", "CNCTI" /*, dir */); + addAct(start, "n", "NEW" /*, dir */); + // XXX Problem: must switch to edit mode AFTER arrow + // addAct(start, "N", "NEWANDEDIT", editmode); + addAct(start, "b", "DISC" /*, dir */); + addAct(start, "/", "CNCTPAIR" /*, dir */); + addAct(start, "t", "CLONE" /*, dir */); + addAct(start, "T", "CLONECTRL" /*, dir */); + addAct(start, "o", "ORIGINAL"); + addAct(start, "O", "ORIGINAL CTRL"); + addAct(start, "Alt-O", "NEXTCLONE"); + addAct(start, "Alt-Shift-O", "NEXTCLONE CTRL"); + addAct(start, "h", "HOP" /*, dir */); + addAct(start, "H", "HOP" /*, dir */); + + addAct(start, "%", "EXCHANGECELLS"); + + addAct(start, "Ctrl-X", "EXCISE"); + + addAct(start, "End", "END" /*, dir */); + + for(int i=0; i<=9; i++) + addAct(start, ""+i, "APPENDINPUT"); + addAct(start, "Backspace", "BACKSPACEINPUT"); + + addAct(start, "g", "GOTO"); + addAct(start, "G", "GOTO CTRL"); + + addAct(start, "Esc", "HOMECLR"); + addAct(start, "Home", "HOME"); + + + addAct(start, "v", "RASTER +"); + addAct(start, "Alt-V", "RASTER -"); + addAct(start, "V", "RASTER C+"); + addAct(start, "Alt-Shift-V", "RASTER C-"); + + addAct(start, "F2", "FFACTORY +"); + addAct(start, "Alt-F2", "FFACTORY -"); + addAct(start, "Shift-F2", "FFACTORY C+"); + addAct(start, "Alt-Shift-F2", "FFACTORY C-"); + + + addAct(start, "F3", "SORTALPH"); + + addAct(start, "x", "DIM X+"); + addAct(start, "Alt-X", "DIM X-"); + addAct(start, "y", "DIM Y+"); + addAct(start, "Alt-Y", "DIM Y-"); + addAct(start, "z", "DIM Z+"); + addAct(start, "Alt-Z", "DIM Z-"); + + + addAct(start, "X", "DIM CX+"); + addAct(start, "Alt-Shift-X", "DIM CX-"); + addAct(start, "Y", "DIM CY+"); + addAct(start, "Alt-Shift-Y", "DIM CY-"); + addAct(start, "Z", "DIM CZ+"); + addAct(start, "Alt-Shift-Z", "DIM CZ-"); + + addAct(start, "~", "SWAPCRSR"); + addAct(start, "<", "FETCH"); + addAct(start, ">", "FETCH CTRL"); + + addAct(start, "Ctrl-<", "ACCURSE CTRL"); + addAct(start, "Ctrl->", "ACCURSE"); + + // addAct(start, "Alt-x", "PSHDIM X+"); + // addAct(start, "Alt-y", "PSHDIM Y+"); + // addAct(start, "Alt-z", "PSHDIM Z+"); + + + + + /* + addAct(start, "L", "MARK X+"); + addAct(start, "J", "MARK X-"); + addAct(start, "I", "MARK Y-"); + addAct(start, "<", "MARK Y+"); + */ + + addAct(start, "Enter", "EXEC"); + + + addAct(start, "m", "MARK"); + + addAct(start, "u", "UNDO"); + addAct(start, "Ctrl-U", "REDO"); + addAct(start, "Ctrl-S", "COMMIT"); + + addAct(start, "Ctrl-F", "FINDTEXT"); + + addAct(start, "MouseClicked1", "MOUSESETC"); + addAct(start, "MouseClicked2", "MOUSEEXEC"); + addAct(start, "MouseClicked3", "MOUSEMARK"); + + addAct(start, "Delete", "DELETESCRAM"); + + addAct(start, "F1", "HELP"); + addAct(start, "q", "QUIT"); + } + + static public void putDefTextBinds(ZZCell start) { + start.setText("Text insert mode"); + ZZCell dir = start; + addAct(dir, "DEFAULT", "TXTINSERT"); + } + static public void putDefCmds(ZZCell fromHome) { + String [][] foo = { + { "EDITHACK" }, + {}, + { "NEWVIEWS" }, + { "TextCloud.TESTWIN" }, +/* doesn't work currently + { "ZZMbox.READMBOX", "ZZMbox.CREATEFLOBWINDOW" }, +*/ + { "NileDemo.UPDATE" }, + { "SplitNileDemo.UPDATE" }, + { "CreateCursors" }, + { "UPDATEWINS" }, + { "EDITVIEW" } , + { "XML.IMPORT" } /* , + { "---- (obsolete?)" }, + { "CNCT X+", "CNCT X-" }, + { "CNCT Y+", "CNCT Y-" }, + { "CNCTI X+", "CNCTI X-" }, + { "CNCTI Y+", "CNCTI Y-" }, + { "CNCTC X+", "CNCTC X-" }, + { "CNCTC Y+", "CNCTC Y-" }, + { "SETDIMS", "SETCDIMS" }, + //{ "RENDER" }, + { "TestClang1.1" }, + { "QUIT" }, */ + }; + ZZCell curv = fromHome; + for(int i=0; i0) curh = curh.N("d.1", 1); + curh.setText(foo[i][j]); + } + } + if(true) { + foo = new String[][]{ + { "Dumper.Create" }, + { "Dumper.Read" }, + { "Dumper.Write" }, + { "Dumper.Dump" }, + { "Dumper.Enter" }, + { "Dumper.ChangeID" }, + { "HOME" }, + }; + curv = fromHome.N("d.1", 1); + // curv.setText("Dumping"); // XXX -- set or don't? + // (what's less confusing?) + for(int i=0; i0) curh = curh.N("d.1", 1); + curh.setText(foo[i][j]); + } + } + } + if(false) { + foo = new String[][]{ + { "SNDS T0-", "SNDS T0+" }, + { "SNDS T1+", "SNDS T1-" }, + { "SNDL T0-", "SNDL T0+" }, // locked to the other one + { "SNDL T1+", "SNDL T1-" }, + { "SNDSPLIT", "SNDJOIN+" }, + { "ZZPlayer.PLAY", "ZZPlayer.PLAYLOOP", + "ZZPlayer.PAUSE", "ZZPlayer.STOP" }, + { "ZZPlayer.CRDEMO" }, + }; + curv = fromHome.N("d.1", 1); + curv.setText("Sound"); + for(int i=0; i0) curh = curh.N("d.1", 1); + curh.setText(foo[i][j]); + } + } + } + } +} diff --git a/Java/ZZPrimitiveCommand.zob b/Java/ZZPrimitiveCommand.zob new file mode 100644 index 0000000..017d117 --- /dev/null +++ b/Java/ZZPrimitiveCommand.zob @@ -0,0 +1,59 @@ +/* +ZZPrimitiveCommand.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ + +package org.gzigzag; +import java.awt.*; + +/** A ZZCommand interface to ZZPrimitiveActions. + */ + +public class ZZPrimitiveCommand extends ZZCommand implements ZOb { + + STRUCTPARAMS { + ZZCell code + = null; + } + + INITIALIZE { + if(code == null) + throw new ZZError("Must specify ZZPrimitiveCommand code!"); + } + + ZZPrimitiveActions pa = new ZZPrimitiveActions(); + + public void execCallback( + ZZCell target, + ZZView view, + ZZView cview, + String key, + Point pt, + ZZScene xi + ) { + pa.execCallback(code, target, view, cview, key, pt, xi); + } + + public void exec(ZZCell param) { + throw new ZZError("ZZPrimitiveCommand currently does not support " + +"primitives which aren't UI callbacks."); + } +} \ No newline at end of file diff --git a/Java/ZZRODimension.java b/Java/ZZRODimension.java new file mode 100644 index 0000000..938d553 --- /dev/null +++ b/Java/ZZRODimension.java @@ -0,0 +1,45 @@ +/* +ZZRODimension.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** A read-only dimension. + * This class simply extends ZZDimension by implementing the + * abstract methods that would modify the dimension by code that + * simply throws an exception. + * The only method that subclasses will need to override is s. + */ + +public abstract class ZZRODimension extends ZZDimension { +public static final String rcsid = "$Id: ZZRODimension.java,v 1.10 2000/11/05 19:11:13 tjl Exp $"; + public abstract ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o); + public void connect(ZZCellHandle c, ZZCellHandle d) { + throw new ZZError("Read-only dimension"); + } + public void disconnect(ZZCellHandle c, int dir) { + throw new ZZError("Read-only dimension"); + } + public void excise(ZZCellHandle c) { + // Do nothing. + } +} diff --git a/Java/ZZScene.java b/Java/ZZScene.java new file mode 100644 index 0000000..f996333 --- /dev/null +++ b/Java/ZZScene.java @@ -0,0 +1,74 @@ +/* +ZZScene.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** An interface for obtaining clicked -objects based on coordinates. + * This is what is given with mouse events. + */ + +public interface ZZScene { +String rcsid = "$Id: ZZScene.java,v 1.4 2000/09/19 10:31:58 ajk Exp $"; + + /** Get an identifying object for the given point on this canvas. + * This is one point where OO decoupling doesn't work properly: + * different things want to return different kinds of information: + * CellThings want to return the cell, TextSpans a VStream.Pos and so on. + */ + Object getObjectAt(int x, int y); + + /** Render this canvas, things interpolated with the given other canvas, + * on the given graphics context. + * Interpolation is used for great advantage to show the user what the + * relationship between two different states is, i.e. which cells + * are the same. The modular nature of the ZZCanvas allows Things + * to define their own interpolation semantics: for example, by default, + * links are not rendered at all when interpolating and cells + * are interpolated linearly. + */ + void renderInterp(Graphics g, ZZScene other, float fract); + + + /** Paint a cursor-like thing using XOR. + * Originally intended for drawing a ghost cursor on text when + * moving the mouse in order to show where a click would put the cursor. + */ + void renderXOR(Graphics g, int x, int y); + + /** Is interpolation to the given canvas visually useful. + * This routine returns true if there is something in this canvas + * which will be seen animated when interpolating to the new canvas. + * For example, when only changing a dimension, some cells stay where + * they are and all the others are replaced by other cells (usually... + * there are of course situations where some cells move on the screen + * when changing a dimension). In this case, the user is better served + * by not animating but simply displaying the new state as fast as + * possible. + */ + boolean isInterpUseful(ZZScene s2); + + /** Render this scene in the given graphics context. + */ + void render(Graphics g); +} diff --git a/Java/ZZSlicedDimSpace.java b/Java/ZZSlicedDimSpace.java new file mode 100644 index 0000000..e7b804a --- /dev/null +++ b/Java/ZZSlicedDimSpace.java @@ -0,0 +1,116 @@ +/* +ZZSlicedDimSpace.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import org.gzigzag.*; +import java.util.*; + +/** A space consisting of primitive slices. + * NOTE: the current code does not support changing slice IDs + * *AT ALL*. + */ + +class EHSEFKUHESMFKMEFKLSEF { } + +/* + +public class ZZSlicedDimSpace extends ZZDimSpace { +public static final String rcsid = "$Id: ZZSlicedDimSpace.java,v 1.10 2000/11/07 23:07:33 tjl Exp $"; + + static final String getOrigID(String c) { + return c.substring(c.indexOf('-')+1); + } + static final int getSliceID(String c) { + return Integer.parseInt(c.substring(0,c.indexOf('-'))); + } + static final String getConvID(int sli, String ores) { + return ""+sli+"-"+ores; + } + + ZZDimSpace[] slices; + + protected DimCell getNewCell(String id) { + int sl = getSliceID(id); + String or = getOrigID(id); + DimCell ocell = slices[sl].getNewCell(or); + id = getConvID(sl, ocell.getID()); + return (DimCell)getCellByID(id); + } + protected DimCell getNewCell() { + throw new ZZError("Can't make new cells from nothing in sliced space"); + } + + public ZZSlicedDimSpace(ZZDimSpace[] s) { + slices = s; + } + protected String getText(String id) { + int sl = getSliceID(id); + String or = getOrigID(id); + ZZCell c = slices[sl].getCellByID(or); + return c.getText(); + } + + protected Span getSpan(String id) { + int sl = getSliceID(id); + String or = getOrigID(id); + ZZCell c = slices[sl].getCellByID(or); + Span s = c.getSpan(); + return s; + } + protected void setText(String id, Object cont) { + int sl = getSliceID(id); + String or = getOrigID(id); + ZZCell c = slices[sl].getCellByID(or); + if(cont instanceof Span) { + c.setSpan((Span)cont); + } else { + c.setText((String)cont); + } + } + + public ZZCell getHomeCell() { + return getCellByID(getConvID(0, slices[0].getHomeCellID())); + } + + public ZZDimension createDimension(String s) { + if(s.equals("d.preflets")) return null; + if(s.equals("d.slices")) return new SlicedHomes(this); + if(s.equals("d.slicesame")) return new SlicedSame(this); + ZZDimension[] dims = new ZZDimension[slices.length]; + for(int i=0; icells and are defined in ZZCell.java. + *

    + * Also included are default operations for space. These can be overridden + * in concrete implementations. Note how we can leave undecided witch + * classes and objects are responsible for some operations, as it's only + * needed that the space contains all specified information. + *

    + * The dimensions are listed in the space itself, on two ranks from + * the Home cell, along d.masterdim which includes all dimensions and + * d.userdim which excludes the system dimensions that are generally + * not used by the user (such as d.cursor, d.cursor-cargo). + * (XXX d.userdim not yet) + *

    + * The event loop mechanism is included in this object since the + * event loop is per-space. Currently, the way to prevent events + * from propagating is to lock this object using synchronized(){}. + * The relationship of this synchronization to remote objects is not + * yet clear, as well as interaction with slices and such + * so this synchronization may change in the future + * to a pair of freeze and thaw method calls. + */ + +public abstract class ZZSpace { +public static final String rcsid = "$Id: ZZSpace.java,v 1.22 2001/02/23 12:20:32 bfallenstein Exp $"; + public static boolean dbg = false; + protected static void p(String s) { if(dbg) ZZLogger.log(s); } + protected static void pa(String s) { ZZLogger.log(s); } + + // CORE FUNCTIONALITY OF ZZSPACE + + /** Obtain the unique ID for this space. + * Note that this method may not throw an exception. + * if the space not have an ID. + */ + public String getIDOrNull() { + return null; + } + + /** Obtain the unique ID for this space. + * Note that this method may throw an exception, + * if the space not have an ID. + */ + public String getID() { + String rv = getIDOrNull(); + if (rv == null) { + throw new NullPointerException("This space has no valid ID"); + } + return rv; + } + + /** Set the unique ID for this space. + * Note that this method may throw an exception + * if the space does not support space IDs. + */ + public void setID(String id) { + throw new ZZError("Setting space ID not supported by this space"); + } + + /** Get the home cell of this space. + * The home cell is where everything begins */ + abstract public ZZCell getHomeCell(); + + /** Get a cell by its ID. + */ + public ZZCell getCellByID(String s) { + throw new ZZError("Not implemented for this space"); + } + + /** Get the appendable string scroll of this space. + */ + public StringScroll getStringScroll() { + return null; + } + /** Get the string scroll with the given identifier. + * (XXX???) + */ + public StringScroll getStringScroll(String name) { + return null; + } + + /** Find all cells whose span overlaps sp. + */ + public ZZCell[] overlaps(Span sp) { + return null; + } + + + // TIMESTAMP AND UNDO. + // THESE NEED NOT DO ANYTHING. + + /** Timestamp the space. + */ + public int stamp() { + return -1; + } + /** Undo to the previous timestamp. + */ + public void undo() { + } + /** Redo to the next timestamp. + */ + public void redo() { + } + /** Commit the changes. + * Commits may define their own timestamps i.e. after commit the + * micro-level timestamps may not be accessible. + */ + public int commit() { + return -1; + } + + + // TRAVERSING + + /** Returns enumeration over the cells in this space - also in slices. + */ + public Enumeration cells() { + return new Enumeration() { + ZZCell next = getHomeCell(); + ZZCell slice = next; // Homecell of current slice + public boolean hasMoreElements() { + if(next == null) + return false; + return true; + } + public Object nextElement() { + if(next == null) + throw new NoSuchElementException(); + ZZCell ret = next; + next = next.s(d.cellcreation, 1); + if(next == null) // End of this slice + slice = next = + slice.s(d.slices, 1); + return ret; + } + }; + } + + /** Get a list of the dimensions in the space. + * This function will likely change in the future as it is possible + * that dimensions become cells instead of strings. + */ + public String[] dims() { + Vector dims = new Vector(); + ZZCell c = getHomeCell().s(d.masterdim, 1); + while(c != null) { + dims.addElement(c.getText()); + c = c.s(d.masterdim, 1); + } + String[] ret = new String[dims.size()]; + for(int i = 0;i + * This is going away once dimensions are cells, not strings. + */ + class Dims { + public final String cellcreation = "d.cellcreation"; + public final String slices = "d.slices"; + public final String masterdim = "d.masterdim"; + public final String clone = "d.clone"; + } + + /** A nice hack to make it possible to use d.* names. Contains all + * dimensions witch have special meaning and are thus referenced + * to in this class. + */ + Dims d = new Dims(); +} diff --git a/Java/ZZSpacePart.java b/Java/ZZSpacePart.java new file mode 100644 index 0000000..ee8e2b5 --- /dev/null +++ b/Java/ZZSpacePart.java @@ -0,0 +1,95 @@ +/* +ZZSpacePart.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; + +/** EXPERIMENTAL: A portion of a ZZ space. + * This is a way to have some cells virtual, i.e. existing only + * when called upon, and whose connections to other cells are algorithmic, + * not stored. + *

    + * For example, it is possible to make a huge tree-like calendar + * with thousands of years at nanosecond precision using these ideas: + * the cell's ID in that part stores the data about the moment and + * the dimensions give the movement from that cell to other cells. + *

    + * Currently, cell IDs in part foo look like foo:... where ... is whatever + * string that part wants to use. + * Dimensions are like d.foo:... where ... is the name in the part. + */ + +public abstract class ZZSpacePart { +public static final String rcsid = "$Id: ZZSpacePart.java,v 1.8 2001/03/08 13:37:16 ajk Exp $"; + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + /** The space part id. This is prepended to all the IDs of the cells + * within this part. (DELIM??!!XXX) + */ + public final String id; + + /** The space this part is a part of. + */ + public final ZZDimSpace space; + + public ZZSpacePart(ZZSpace space, String id) { + this.space = (ZZDimSpace)space; + this.id = id; + } + + /** Obtain a special dimension for this part. + * The dimension name has the prefix stripped off. + * This function may return null. + */ + abstract public ZZDimension getDim(String name); + + /** The home cell for this space part. This is useful in case + * it's not connected to anywhere in the space proper. */ + public String homeID() { return null; } + + public String getText(ZZCellHandle c) { return ""; } + public Span getSpan(ZZCellHandle c) { return null; } + public void setContent(ZZCellHandle c, Object o) { + // do nothing + } + + public Object parseID(String id) { + int ind = id.indexOf(':'); + if(ind < 0) throw new SyntaxError("No delimiter in ID"); + return parseIDPart(id.substring(ind+1)); + } + abstract public Object parseIDPart(String idPart); + + public String toString() { return id; } + + public String generateID(Object parsed) { + String rv = id + ":" + generateIDPart(parsed); + return rv; + } + abstract public String generateIDPart(Object parsed); + + public ZZDimSpace.DimCell getCellByID(String s) { return null; } + + public void postCommitHook() {} +} + diff --git a/Java/ZZTextView.java b/Java/ZZTextView.java new file mode 100644 index 0000000..501d2a2 --- /dev/null +++ b/Java/ZZTextView.java @@ -0,0 +1,106 @@ +/* +ZZTextView.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka, rewritten to use AWT by Benja Fallenstein + */ +package org.gzigzag; +import java.awt.event.*; +import java.awt.*; + +/** A text view showing the contents of one cell (the cursor). + * This is shown in a window of its own, using the AWT TextArea component, + * to allow copy-and-paste functions as you know them from PUIs. Basically, + * it's a dirty hack, because it's outside the usual GZZ framework. + */ + +public class ZZTextView extends Frame implements ZZView { +public static final String rcsid = "$Id: ZZTextView.java,v 1.16.2.3 2001/08/16 13:50:01 bfallenstein Exp $"; + static final boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + ZZCell windowCell; + + /** The cell we show (i.e., the cell currently accursed). + * If reraster is called, but the cell and its text haven't changed, we do + * nothing, so that the cursor position will not be screwed. (The text + * is not cached, instead the text in the TextArea component is used: this + * way, if the TextArea itself is used for editing, the text we find there + * will be the new text in the cell, so we will not screw the cursor + * position either.) + *

    + * Note that we simply ignore updates when we have the focus. + */ + ZZCell shown; + + /** Whether we're updating the content of the TextArea right now. + * When we're updating (i.e., write stuff from the structure into + * the text area), we obviously ignore events telling us the content + * of the text area has changed. + */ + boolean isUpdating = false; + + /** Whether the text component currently has the focus. */ + boolean hasFocus; + + public ZZCell getViewcell() { return windowCell; } + public void paintNow(float fract) {} + + TextArea txt = new TextArea("", 100, 100, + TextArea.SCROLLBARS_VERTICAL_ONLY); + + public ZZTextView(ZZCell c) { + windowCell = c; + setLayout(new BorderLayout()); + add(txt, "Center"); + ZZUpdateManager.addView(this); + txt.addTextListener(new TextListener() { + public void textValueChanged(TextEvent e) { + if(isUpdating) return; + shown.setText(txt.getText()); + ZZCursorReal.setOffs(windowCell, txt.getCaretPosition()); + } + }); + txt.addFocusListener(new FocusListener() { + public void focusGained(FocusEvent e) { hasFocus = true; } + public void focusLost(FocusEvent e) { hasFocus = false; } + }); + setBounds(0, 0, 200, 300); + setVisible(true); + reraster(); + } + + public boolean reraster() { + ZZCell accursed = ZZCursorReal.get(windowCell); + if(!hasFocus && (!accursed.equals(shown) || + !accursed.getText().equals(txt.getText()))) { + isUpdating = true; + txt.setText(accursed.getText()); + int offs = ZZCursorReal.getOffs(windowCell); + if(offs == ZZCursorReal.NO_OFFSET) + txt.setCaretPosition(0); + else + txt.setCaretPosition(offs); + shown = accursed; + isUpdating = false; + } + return false; + } +} diff --git a/Java/ZZTraverseCB.java b/Java/ZZTraverseCB.java new file mode 100644 index 0000000..bf5d9f3 --- /dev/null +++ b/Java/ZZTraverseCB.java @@ -0,0 +1,43 @@ +/* +ZZSpace.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +/** An interface for creating a ZZ space through traversal. + * Cells are represented by their IDs. + */ + +public interface ZZTraverseCB { +String rcsid = "$Id: ZZTraverseCB.java,v 1.6 2000/09/19 10:31:58 ajk Exp $"; + + /** Start the traversal from the given home cell ID. + */ + void start(String home); + /** Insert the new cell. + */ + void cell(String cur, String dim, int dir, String which, + String content); + /** Connect the two given cells. */ + void connect(String c1,String dim, int dir, String c2); + /** That's all, folks. */ + void finish(); +} diff --git a/Java/ZZUpdateManager.java b/Java/ZZUpdateManager.java new file mode 100644 index 0000000..7d0cc1c --- /dev/null +++ b/Java/ZZUpdateManager.java @@ -0,0 +1,253 @@ +/* +ZZUpdateManager.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** A single global instance to manage the updating of views. + * The views are set in a priority order so that even if the user is + * moving fast, he will get an immediate response through the less important + * views not being updated at each step. + */ + +public class ZZUpdateManager implements Runnable { +public static final String rcsid = "$Id: ZZUpdateManager.java,v 1.29 2001/02/27 08:36:15 raulir Exp $"; + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + /** The order of views, from the most important to the least. + */ + private static Vector ordering = new Vector(); + + /** Whether an update is currently in progress, through + * a view being painted. + */ + private static boolean updating; + private static int disabled; + private static boolean noanimation; + /** Whether the currently ongoing update should stop immediately + * and restart from the beginning + */ + private static boolean restartUpd = false; + + public static void addView(ZZView v) { ordering.addElement(v); } + public static void rmView(ZZView v) { ordering.removeElement(v); } + + /** Set the view that has the privilege of animating the next + * update. + * Setting this to null will make all views update fast. + */ + public static void setFast(ZZView v) { + p("Setfast: "+v + " cur: "+ordering.elementAt(0)); + if(v == null) { + noanimation = true; + return; + } + if(ordering.elementAt(0)!=v) { + ordering.removeElement(v); + ordering.insertElementAt(v, 0); + } + } + + + /* Called by a space to inform that some cells have been + * changed + */ + public static void chg() { + p("UPDMANAGER CHG"); + if(restartUpd) return; + synchronized(ordering) { + restartUpd = true; + ordering.notifyAll(); + } + p("UPDMANAGER CHGOUT"); + } + + /** Disable all updating of views. + * XXX While frozen, might consider updating e.g. once every + * second... + */ + public static void freeze() { + p("ZZUpdatemanager freeze"); + synchronized(ordering) { disabled++; } + p("ZZUpdatemanager frozen "+disabled); + } + /** Enable again the updating of views. */ + public static void thaw() { + p("ZZUpdatemanager thaw"); + synchronized(ordering) { + if(disabled<=0) + throw new ZZError("thaw() without matching freeze()!"); + if(--disabled==0) ordering.notifyAll(); + } + p("ZZUpdatemanager thawed "+disabled); + } + + static ZZUpdateManager m = new ZZUpdateManager(); + static Thread t= new Thread(m); + static { + p("STARTORDTHREAD"); + t.start(); + } + + public void run() { + try { + int ind = -1; + boolean reras = true; + boolean anim = false; + Vector curUpdVec = new Vector(); + + while(true) { + p("STARTORD"); + synchronized(ordering) { + p("STARTORD SYNCHED"); + if(!anim) ind++; + updating = false; + try { + while(disabled>0 || (ind>=curUpdVec.size() && !restartUpd)) { + p("STARTORD "+disabled+" "+ind+" "+restartUpd); + ordering.wait(); + } + } catch(Exception e) { + ZZLogger.exc(e); + } + p("STARTORD WAITED"); + updating = true; + if(restartUpd) { + restartUpd = false; + curUpdVec = (Vector)ordering.clone(); + ind = 0; + reras = true; + // Try to make the system stop less at + // inconvenient, unequal times. + + // System.gc(); // doesn't seem to work. + } + if(curUpdVec.size()==0) continue; + } + try { + p("STARTORD DOING " + ind + " "+ curUpdVec+" "+reras); + ZZView v = (ZZView)curUpdVec.elementAt(ind); + if(ind==0) { // animate if need be + if(reras) { + timeNewCycle(); + + anim = v.reraster(); + reras = false; + } + float fract = timeAnimFract(); + + if(fract >= 1 || !anim || noanimation) { + fract = 1; + anim = false; + noanimation = false; + } + p("PN 0: "+fract+" "+anim+" "+lastStart+" "+millis); + // XXX paintNow() is not really safe here, because ZZ code + // in general isn't thread-safe. If Kaffe someday provides + // EventQueue.invokeAndWait(), this could be fixed. + boolean care = ZZDrawing.instance.enableQuality(false); + v.paintNow((float)fract); + if (fract == 1 && care) { + ZZDrawing.instance.enableQuality(true); + v.paintNow(1.0f); + } + } else { + p("PN: "+ind); + v.reraster(); + // XXX Ditto. + boolean care = ZZDrawing.instance.enableQuality(false); + v.paintNow(1.0f); + if (care) { + ZZDrawing.instance.enableQuality(true); + v.paintNow(1.0f); + } + } + ((java.awt.Component)v).getToolkit().sync(); + } catch(ZZError e) { + ZZLogger.exc(e); + System.out.println("EXCEPTION WHILE UPDATING!"); + } + p("STARTORD DONE: anim "+anim); + } + } finally { + System.out.println("HELP! UPDATE LOOP STOPPED. XXX"); + } + } + + static final long defmillis = 800; + /** The time before the next user event + * to try to be ready. + */ + static final long trybefore = 150; + /** The time to increment the interval with. + */ + static final long inctime = 80; + private static long lastStart = 0; + /** The interval between start and end of animation. + */ + private static long millis = defmillis; + + /** Called when we begin a new animation. */ + private void timeNewCycle() { + long cur = System.currentTimeMillis(); + // Interval between start of last animation and start of the new one. + long sinceLast = cur-lastStart; + + // sinceLast - millis = interval between end of last animation and + // start of the new one. We try to end the last animation + // trybefore ticks before the start of the new one, so if + // sinceLast - millis < trybefore, the animation takes too long. + if(sinceLast - millis < trybefore) + millis = sinceLast-trybefore; // Shorten the animation time. + + // If the animation didn't take too long, and if it's at least a unit + // (inctime) shorter than it was by default, gradually lengthen it. + else if(millis < defmillis - inctime) + millis += inctime; + + lastStart = cur; + } + + private float timeAnimFract() { + long cur = System.currentTimeMillis(); + + double fract = 1.0; + + // If we are animating at all (20 milliseconds is + // minimum time we try to use animation with), + // calculate the fraction of the animation we are at. + if(millis > 20) + fract = (cur-lastStart) / (double)millis; + + // Test for a really weird JVM problem. + if(cur - lastStart >= millis && fract < 1) { + System.out.println("AAAARRRRRGGGHHH!!! Division problem "+ cur + " "+lastStart+" "+millis); + } + + return (float)fract; + } + +} + + diff --git a/Java/ZZUtil.java b/Java/ZZUtil.java new file mode 100644 index 0000000..5c40fca --- /dev/null +++ b/Java/ZZUtil.java @@ -0,0 +1,575 @@ +/* +ZZUtil.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.awt.*; +import java.awt.datatransfer.*; +import java.util.*; + +/** Some general routines that don't fit anywhere else. + */ + +public class ZZUtil { +public static final String rcsid = "$Id: ZZUtil.java,v 1.35.4.3 2002/03/07 19:36:53 bfallenstein Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + /** Set a number of strings onto a rank. + * Overwrites existing cells and creates new for the rest. + */ + static public void putStrings(ZZCell start, String dim, boolean incStart, + String[] strs) { + for(int i=0; i= nmin) break; + throw new ZZError("Not enough strings: "+i); + } + } + p("GetStrs: "+start.getID()); + r[i] = start.getText(obs); + } + if(i == nmax) return r; + String[] r2 = new String[i]; + System.arraycopy(r, 0, r2, 0, i); + return r2; + } + static public String[] getStrings(ZZCell start, String dim, + boolean incStart, + int nmin, int nmax) { + return getStrings(start,dim,incStart,nmin,nmax,null); + } + + static public int[] getInts(ZZCell start, String dim, boolean incStart, + int nmin, int nmax,ZZObs obs) { + String[] s = getStrings(start, dim, incStart, nmin, nmax, obs); + int[] r = new int[s.length]; + for(int i=0; i 256) fract = 256; + int p = 256-fract; + int m = fract; + return new Color( + (c1.getRed()*p + c2.getRed()*m) / 256, + (c1.getGreen()*p + c2.getGreen()*m) / 256, + (c1.getBlue()*p + c2.getBlue()*m) / 256); + } + + /** Give a subtly randomly shaded version of the given color. + */ + static public Color perturb(Color c1) { + return new Color( + pff(c1.getRed()), + pff(c1.getGreen()), + pff(c1.getBlue()) + ); + } + + /** Perturb an integer in the range 0..255. + */ + static int pff(int f) { + int offs = (int)(50 * (Math.random() - 0.5)); + f += offs; + if(f < 0) f = 0; + if(f > 255) f = 255; + return f; + } + + /** Find the index of the given string that is closest to + * the given X coordinate using FontMetrics. + */ + static public int findStringHit(String txt, int x, FontMetrics fm, + boolean alwaysmin) { + if(x <= 0) return 0; + int min = 0; int max = txt.length(); + int lmin = 0; int lmax = fm.stringWidth(txt); + while(max-min > 1) { + int cur = (max+min) / 2; + int curlen = fm.stringWidth(txt.substring(0, cur)); + p("Iter: "+cur+" "+curlen+" "+max+" "+lmax+" "+min+" "+lmin); + if(curlen > x) { + max = cur; + lmax = curlen; + } else { + min = cur; + lmin = curlen; + } + // XXX potential for infinite loop for weird fontmetrics? + } + // now we should have it... + int mx = lmax - x; + int mn = x - lmin; + if(mn < mx || alwaysmin) + return min; + else + return max; + } + + static public int findStringHit(String txt, int x, FontMetrics fm) { + return findStringHit(txt, x, fm, false); + } + + /** Append a command-type thing. Strings are put in cells, cells are + * cloned. + */ + static public ZZCell appendCommand(ZZCell cur, + String cdim, String pdim, Object[] objs) { + ZZCell tmp = null; + if(objs[0] instanceof String) + (cur = cur.N(cdim, 1)).setText((String)objs[0]); + else { + tmp = ((ZZCell)objs[0]).N("d.clone", 1); + cur.connect(cdim, 1, tmp); + cur = tmp; + } + ZZCell prev = cur; + for(int i=1; i + * If a dimension is given, then contents of this rank are concatenated. + */ + static public void puiCopy(ZZCell from, String dim) + { + StringBuffer cont = new StringBuffer(from.getText()); + if(dim != null) { + ZZCell cur = from.s(dim, 1); + while(cur != null) { // XXX Use LoopDetector + String s = cur.getText(); + if(s.equals("")) + cont.append('\n'); + else + cont.append(' ').append(s); + cur = cur.s(dim, 1); + } + } + puiCopy(cont.toString()); + } + + static public void puiCopyRank(ZZCell from, String dim) + { + StringBuffer cont = new StringBuffer(from.getText()+"\n\n"); + if(dim != null) { + ZZCell cur = from.s(dim, 1); + while(cur != null) { // XXX Use LoopDetector + cont.append(cur.getText() + "\n\n"); + cur = cur.s(dim, 1); + } + } + puiCopy(cont.toString()); + } + + static public void puiCopy(ZZCell from) { + puiCopy(from.getText()); + } + + static public String puiGetClipText() + { + Clipboard clipboard = getPUIClipboard(); + Transferable content = clipboard.getContents(new Object()); + String s = ""; + if(content != null) { + try { + s = (String) content.getTransferData(DataFlavor.stringFlavor); + } catch (Exception e) { + ZZLogger.exc(e); + return null; + } + } + return s; + } + + /** Paste from PUI clipboard. + * Change a cell's contents to the (text) contents in the clipboard + * of the surrounding PUI. Return true if action succeeded; return + * false if not (because the clipboard didn't contain text). + *

    + * XXX does nothing if cell is span (but what *should* be done?) + */ + static public boolean puiPaste(ZZCell to) { + if(to.getSpan() != null) return false; + p("PuiPASTE"); + String s = puiGetClipText(); + if(s == null) return false; + to.setText(s); + return true; + } + + /** An interface which establishes an ordering (partial or full, + * depending on context) between cells. + */ + public interface Comparator { + /** Compare the things represented by the two cells to each other. + * @return 0 if equal, 1 if c1 greater, -1 if c2 greater. + */ + int compare(ZZCell c1, ZZCell c2); + } + + /* after sorting */ + static private void sameToClone(ZZCell c1, String dim, int dir, ZZCell c2, + Comparator comp){ + //pa("CLONING\n"); + ZZCell cur = c1; + for ( cur = c1.s(dim,dir); cur != null;){ + if ( c1 == c2 ) break; + ZZCell next = cur.s(dim, dir); + + if ( comp.compare(c1,cur) == 0 ){ + c1.insert( "d.clone", 1, cur ); + cur.excise(dim); + //pa("CLONED\n"); + } else { + c1 = cur; + } + cur = next; + + } + } + + static private int partition(ZZCell[] v, int l, int r, Comparator s){ + int i = l-1; + int j = r; + int len = v.length; + ZZCell p = v[r]; + //if ( p == null ) return 0; + ZZCell tmp; + while( true ){ + while(s.compare(v[++i], p) < 0 ){ + if ( i >= len ) break; + } + while(s.compare(p, v[--j]) < 0 ){ + if ( j <=0 ) break; + } + if ( i >= j ) break; + + tmp = v[i]; + v[i] = v[j]; + v[j] = tmp; + } + + tmp = v[i]; + v[i] = v[r]; + v[r] = tmp; + + return i; + } + + + static private void qs(ZZCell[] table, int l, int r,Comparator comp){ + if ( l < r ) { + int i = partition(table,l,r,comp); + if ( i == r ) { i--; } + qs(table,l,i,comp); + qs(table,i+1,r,comp); + } + } + + // yet another sorting algorithm + // this isn't too good, feel free to make a better one + static private void qsRange(ZZCell c1, String dim, int dir, ZZCell c2, + Comparator comp) { + if(c1 == c2) return; + + if ( c1 == null || c2 == null ) return; + // calculate the size of the table + + ZZCell first = c1; + int len = 1, i = 0; + for( ; c1 != c2; len++){ + c1 = c1.s(dim,dir); + if ( c1 == null ) return; + } + if ( len < 1 ) return; + + // read to table + ZZCell[] table = new ZZCell[len]; + c1 = first; + for( i = 0; i < len; i++){ + table[i] = c1; + c1 = c1.s(dim,dir); + } + + qs( table,0,len-1, comp ); + + c1 = first; + + if( c1 != table[0]) + c1.insert(dim, -dir, table[0]); + + for(i = 1 ; i < len; i++){ + c1.insert(dim, dir, table[i]); + c1 = table[i]; + } + } + + static private void sortRange(ZZCell c1, String dim, int dir, ZZCell c2, + Comparator comp) { + + // p("SortRange: "+c1.getText()+" "+c2.getText()); + if(c1 == c2) return; + + ZZCell first = c1; + ZZCell last = c2; + ZZCell cur; + for(cur = c1.s(dim, dir); cur != null;) { + // p("cur: "+cur.getText()); + ZZCell next = cur.s(dim, dir); + int cp = comp.compare(c1, cur); + if(cp > 0) { + // p("move"); + if(cur == c2) last = c2.s(dim, -dir); + c1.insert(dim, -dir, cur); + if(first == c1) first = cur; + } + + if(cur == c2) break; + cur = next; + } + if(first != c1) + sortRange(first, dim, dir, c1.s(dim, -dir), comp); + if(c1 != last) + sortRange(c1.s(dim, dir), dim, dir, last, comp); + + } + + /** Sort a rank with a given comparator. + */ + static public void sortRank(ZZCell c, String dim, int dir, + Comparator comp, boolean includeThis) { + sortRank( c, dim, dir, comp, includeThis, false); + } + + static public void sortRank(ZZCell c, String dim, int dir, + Comparator comp, + boolean includeThis, boolean clone) { + ZZCell c1; + if(!includeThis) + c1 = c.s(dim, dir); + else c1 = c; + if(c==null) return; + + //long t0 = System.currentTimeMillis(); + //sortRange(c1, dim, dir, c.h(dim, dir), comp); + qsRange(c1, dim, dir, c.h(dim, dir), comp); + //pa("TIME USED SORTING = " + (System.currentTimeMillis() - t0) ); + + if(!includeThis) + c1 = c.s(dim, dir); + else c1 = c; + + if ( clone ) + sameToClone(c1, dim, dir, c.h(dim, dir), comp); + } + + + /** Show the dimension cross of a flob view. + */ + static public void showFlobDims(FlobSet into, + FlobFactory fact, ZZCell view, int n) { + + Dimension s = fact.getSize(null, 1); + ZZCell dim = view.s("d.dims", 1); + ZZCell[] cdims = new ZZCell[3]; + int i=0; + for(; dim != null && i < n; i ++) { + cdims[i] = ZZCursorReal.get(dim); + if(cdims[i] == null) + throw new ZZError("No dimension"); + dim = dim.s("d.dims", 1); + } + Flob fl = fact.makeFlob(into, cdims[0], cdims[0], 1, + s.width, 0, 1, s.width, s.height); + fl.flobPath = "dim"; + fl = fact.makeFlob(into, cdims[1], cdims[1], 1, + 0, s.height, 1, s.width, s.height); + fl.flobPath = "dim"; + if(n > 2) { + fl = fact.makeFlob(into, cdims[2], cdims[2], 1, + s.width, s.height, 1, s.width, s.height); + fl.flobPath = "dim"; + } + int wh = s.width / 2; + int hh = s.height / 2; + into.add(new LineDecor( + new int[] { + wh, hh, wh, s.height, + wh, hh, s.width, s.height, + wh, hh, s.width, hh + }, + 12, + Color.red, + 1 + )); + + } + + + /** Create a natural-looking spline between two vectors. + * Returns an array of alternating x and y coordinates of + * a polyline. + * XXX Contains many constants that are just fixed. + * XXX Needs to be prettified a bit. + */ + static public int[] bulgeCurve( + int x0, int y0, int dx0, int dy0, + int x1, int y1, int dx1, int dy1, int NPTS) { + // Formula: x = t*(x0 + c*t*v_0) + (1-t) * (x1 + c*(1-t)*v_1) + p("bulge: "+x0+" "+y0+" "+dx0+" "+dy0+" "+x1+" "+y1+" "+ + dx1+" "+dy1+" "); + int dx = (dx0 - dx1) / 2; + int dy = (dy0 - dy1) / 2; + int dotp = dx * (x1-x0) + dy * (y1-y0); + int det = dx * (y1-y0) - dy * (x1-x0); + // if(dotp < 0 && + int[] res = new int[NPTS*2]; + // Polynomial for factor. + // a*x + b*x^3 is the polynomial through (-1,-1), (0,0) and (1,1) + // whose derivative at -1 and 1 is zero. + // Thus, it is suitable for curving. + float a = (float)1.5; + float b = (float)-0.5; + float tense = (float)20.0/NPTS; + for(int i=0; i + * In event routines, passed instead of cells for update purposes + * (asking ZZUpdateManager to make this view the fast-updated one). + * Once ZZWindows are finished, should be replaced with ZZCell of + * a ZZWindow. + *

    + * Expect a parameter "complexity" to be added to reraster and paintNow + * in the future in order for the ZZUpdateManager to be able to control + * the frame rate. + */ +public interface ZZView { +String rcsid = "$Id: ZZView.java,v 1.18 2000/09/19 10:31:58 ajk Exp $"; + /** Called to enquire whether this view needs an update, given + * that certain cells have been changed. + * NOT YET USED + */ + // public boolean needUpdate(ZZCell[] changed); + // XXX dimensions of chgd cells! + + /** Recreate the view in memory (raster the cells etc). + * @return true if it would be useful for the view to animate + * to the next view. + */ + boolean reraster(); + /** Called to tell that this view should paint itself right now. + * @param fraction The fraction between the old and the new views + * the animation should be at. + */ + void paintNow(float fraction); + + /** Get the cell in the structure representing this view. + */ + ZZCell getViewcell(); +} diff --git a/Java/ZZViewComponent.java b/Java/ZZViewComponent.java new file mode 100644 index 0000000..42708ae --- /dev/null +++ b/Java/ZZViewComponent.java @@ -0,0 +1,287 @@ +/* +ZZViewComponent.java + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.awt.event.*; +import java.awt.*; +import java.util.*; + +/** A generic view as an AWT component. + */ +abstract public class ZZViewComponent extends Panel implements ZZView, + MouseListener, MouseMotionListener { +public static final String rcsid = "$Id: ZZViewComponent.java,v 1.48.2.4 2002/02/10 12:39:20 bfallenstein Exp $"; + static public boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + ZZCell viewCell;public ZZCell getViewcell() { return viewCell; } + ZZKeyBindings kb; + ZZView ctrlView, dataView; + + boolean needreraster = false; + boolean validraster = false; + + ZZViewComponent parentView; + + Component pushedViewPanel; + ZZViewComponent pushedView; + + /** ZZViewComponent per viewCell. + */ + static Hashtable cpts = new Hashtable(); + + static void redoCtrls(ZZCell vc) { + if(vc == null) throw new ZZError("vc == null"); + + if(vc.getRankLength("d.ctrlview") > 2) + throw new ZZError("d.ctrlview rank with more than two cells!"); + + ZZCell cc, dc; + if((cc = vc.s("d.ctrlview", -1)) != null) + dc = vc; + else if((dc = vc.s("d.ctrlview", 1)) != null) + cc = vc; + else + cc = (dc = vc); + + ZZViewComponent cv = (ZZViewComponent) cpts.get(cc); + ZZViewComponent dv = (ZZViewComponent) cpts.get(dc); + + if(cv == null || dv == null) + // other ZZViewComponent doesn't exist yet + cv = (dv = (ZZViewComponent) cpts.get(vc)); + + cv.setViewPair(dv, true); + dv.setViewPair(cv, false); + +/* // does somebody want it like this? --> + ZZCell h = vc.h("d.ctrlview", -1); + ZZViewComponent c = (ZZViewComponent)cpts.get(h); + if(c != null) { + while((h=h.s("d.ctrlview", 1)) != null) { + ZZViewComponent c1 = (ZZViewComponent)cpts.get(h); + if(c1 != null) + c1.setCtrl(c); + } + } +*/ + } + + public void setViewcell(ZZCell vc0) { + viewCell = vc0; + kb = new ZZKeyBindings1(); + cpts.put(vc0, this); + redoCtrls(viewCell); + } + public void setViewPair(ZZView other, boolean ctrl) { + if(ctrl) { + ctrlView = this; + dataView = other; + } else { + ctrlView = other; + dataView = this; + } + } + + ZZViewComponent(ZZCell viewCell0) { + this(); + setViewcell(viewCell0); + } + + ZZViewComponent() { + addFocusListener(new FocusListener() { + public void focusGained(FocusEvent e) { + p(this + " focusgained"); + repaint(); + } + public void focusLost(FocusEvent e) { + p(this + " focuslost"); + repaint(); + } + }); + + addMouseListener(this); + addMouseMotionListener(this); + + addComponentListener(new ComponentAdapter() { + public void componentResized(ComponentEvent e) { + re_raster_soon(); + } + }); + + enableEvents(AWTEvent.KEY_EVENT_MASK); + } + + public void addNotify() { + ZZUpdateManager.addView(this); + super.addNotify(); + } + + public void removeNotify() { + ZZUpdateManager.rmView(this); + super.removeNotify(); + } + + protected void processEvent(AWTEvent e) { + p("ProcessEvent: "+e); + super.processEvent(e); + } + + protected void processKeyEvent(KeyEvent e) { + p("ProcessKeyEvent: "+e); + + // Apply any necessary key event hacks to this event. + e = ZZKeyHacks.keyEventHack(e); + p("After KeyEventHack: "+e); + + int id = e.getID(); + + if(id == e.KEY_PRESSED) { + int kc = e.getKeyCode(); + // These sometimes caused unshifted characters to + // appear. Very odd. + if(kc == e.VK_SHIFT || kc == e.VK_CONTROL || kc == e.VK_ALT + || kc == e.VK_META) { + super.processKeyEvent(e); + return; + } + ZZUpdateManager.freeze(); + try { + //e.consume(); + if(kbd != null) + kb.perform(e, kbd.dataView, kbd.ctrlView, null); + else + kb.perform(e, dataView, ctrlView, null); + ZZObsTrigger.runObsQueue(); + } finally { ZZUpdateManager.thaw(); } + } + // We don't let it go upstairs... + // super.processKeyEvent(e); + } + + + public void mouseEntered(MouseEvent e) { + // XXX ??? + requestFocus(); + } + public void mouseExited(MouseEvent e) { + } + public void mousePressed(MouseEvent e) { + } + public void mouseReleased(MouseEvent e) { + } + public void mouseClicked(MouseEvent e) { + // System.out.println("MOUENT"); + // System.out.println(e); + // kb.perform(k, ZZView.this); + requestFocus(); + // System.out.println("MOURET"); + e.consume(); + } + + public void mouseDragged(MouseEvent e) { + } + public void mouseMoved(MouseEvent e) { + // XXX ??? + requestFocus(); + } + + public void destroy() { + ZZUpdateManager.rmView(this); + } + + ZZViewComponent kbd; + public void setKbdStandin(ZZViewComponent v) { + kbd = v; + } + public void re_raster_soon() { + // p(this + " RERASTERSOON"); + needreraster = true; + repaint(50); + } + + boolean wasInPaint; + float fract; + + boolean dblbuf = true; + private Image cache; + private Dimension cacheSize; + + /** Paint this component into the given graphics object, + * without consideration for double buffering. + */ + public abstract void paintInto(Graphics gr); + + // Paint into the buffer and then into gr. + public void paint(Graphics gr) { + if(dblbuf) { + // XXX Really necessary every time? + Dimension d = getSize(); + if(cache == null || + cacheSize == null || + !cacheSize.equals(d)) { + cacheSize = d; + p("Creating cache: "+d.width+" "+d.height); + cache=null; + if(d.width>0&&d.height>0) + cache = createImage(d.width, d.height); + } + if(cache == null) { + paintInto(gr); + } else { + try { + Graphics g = cache.getGraphics(); + paintInto(g); + // g.dispose() ??? + gr.drawImage(cache, 0, 0, null); + // Dispose this as well? + } catch(Throwable t) { + // FIXME ARGH! + cache = null; + paintInto(gr); + } + } + } else { + // Single-buffer. Flashes. + paintInto(gr); + } + } + public void update(Graphics gr) { paint(gr); } + + public void paintNow(float fract) { + wasInPaint = false; + this.fract = fract; + // p("Paintnow "+this+" "+parentView+" "+reraster+" "+anim); + + Graphics gr = getGraphics(); + if (gr == null) { + repaint(30); + return; + } + paint(gr); + } + +} + + + diff --git a/Java/ZZWindows.java b/Java/ZZWindows.java new file mode 100644 index 0000000..443b804 --- /dev/null +++ b/Java/ZZWindows.java @@ -0,0 +1,231 @@ +/* +ZZWindows.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka, killing by Antti-Juhani Kaijanaho, + * triggering and rootwin support by Rauli Ruohonen + */ + +package org.gzigzag; +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +public class ZZWindows { +public static final String rcsid = "$Id: ZZWindows.java,v 1.23 2001/01/03 16:47:50 raulir Exp $"; + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + /** Iff null, creates Frames at top level. */ + private static Container rootwin; + private static ZZSpace rspace; + private static Hashtable views, frames, ex; + private static ZZObs obs = new ZZObs() { public void chg() { update(); }}; + + /** Must be called before anything else. */ + public static void init(ZZSpace s,Container rootWin) { + rootwin=rootWin; + rspace=s; + if(views!=null) updateEnd(); + views=new Hashtable(); + frames=new Hashtable(); + ex=new Hashtable(); + ZZObsTrigger.chg(obs); + } + public static synchronized void update() { + p("update() start"); + ZZCell rcell=startCell(); + if(rcell==null) throw new ZZError("No 'Windows' cell found!"); + ZZCell s=rcell.getOrNewCell("d.1",1,obs); + if(rootwin!=null) updateRoot(s); + else updateFrames(s); + updateEnd(); + p("update() end"); + } + + // XXX Should create a ZZWindow class for operating on the structure? + public static Rectangle getBounds(ZZCell c, ZZObs obs) { + try { + int[] a=ZZUtil.getInts(c.s("d.1",-1),"d.bounds",false,4,4,obs); + return new Rectangle(a[0], a[1], a[2], a[3]); + } catch(ZZError e) { + return null; + } + } + public static Rectangle getBounds(ZZCell c) { return getBounds(c,null); } + public static void setBounds(ZZCell c, Rectangle r) { + Rectangle b=getBounds(c); + if(b!=null&&b.equals(r)) return; + ZZUtil.putInts(c.s("d.1",-1), "d.bounds", false, + new int[] { r.x, r.y, r.width, r.height }); + } + public static ZZCell startCell() { + return ZZDefaultSpace.findOnClientlist(rspace, "Windows", false); + } + public static synchronized ZZViewComponent getContent(ZZCell c) { + String txt = c.getText(obs); + if(txt.equals("Canvas")) { + ZZCanvasView v; + if(views.get(c) instanceof ZZCanvasView) + v = (ZZCanvasView) views.get(c); + else + views.put(c, v = new ZZCanvasView()); + ZZCell vcell = c.s("d.1", 1,obs); + if(vcell == null) return null; + v.setViewcell(vcell); + return v; + } + return null; + } + + private static void updateRoot(ZZCell s) { + ScalableFont.fmComp=rootwin; + updateWindowAttributes(s,rootwin); + updatePanels(s.s("d.2",1,obs),rootwin); + rootwin.validate(); + } + private static void updateFrames(ZZCell s) { + s=s.s("d.2",1,obs); + while(s!=null) { + boolean created=false; + ZZCell c=s.s("d.1",1,obs); + if(c!=null) { + Frame f=(Frame)frames.get(c); + if(f==null) { + created=true; + frames.put(c,f=new Frame()); + initWindow(c,f); + final ZZCell cell=c; + f.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + p("windowClosing()"); + ZZUpdateManager.freeze(); + try { + cell.s("d.1",-1).excise("d.2"); + ZZObsTrigger.runObsQueue(); + } finally { ZZUpdateManager.thaw(); } + } + }); + } + ScalableFont.fmComp=f; + ex.put(c,c); + Rectangle r=getBounds(c,obs); + if(r!=null&&!f.getBounds().equals(r)) f.setBounds(r); + f.setTitle(s.getText(obs)); + p("Frame name: "+f.getTitle()); + Container cont=getContent(c); + if(cont!=null) { + updateWindowAttributes(s,cont); + cont.removeAll(); // FIXME + updatePanels(c.s("d.2",1,obs),cont); + if(f.getComponentCount()!=1||f.getComponent(0)!=cont) { + p("Changing frame component and validating."); + f.removeAll(); + f.add(cont); + f.validate(); + } + } + if(created) f.setVisible(true); + } + s=s.s("d.2",1,obs); + } + } + private static void updatePanels(ZZCell s,Container parent) { + if(s==null) return; + // FIXME This kludge is here so that applets still work. The real + // functionality should be here Real Soon Now(TM). (Yeah, *right*) + parent.removeAll(); + Container cont=getContent(s.s("d.1",1,obs)); + updateWindowAttributes(s,cont); + parent.add(cont); + } + private static void initWindow(final ZZCell c,final Container w) { + w.addComponentListener(new ComponentAdapter() { + public void componentMoved(ComponentEvent e) { + ZZUpdateManager.freeze(); + try { + ZZObsTrigger.setEnabled(obs,false); + setBounds(c, w.getBounds()); + ZZObsTrigger.setEnabled(obs,true); + ZZObsTrigger.runObsQueue(); + } finally { ZZUpdateManager.thaw(); } + } + public void componentResized(ComponentEvent e) { + ZZUpdateManager.freeze(); + try { + ZZObsTrigger.setEnabled(obs,false); + setBounds(c, w.getBounds()); + ZZObsTrigger.setEnabled(obs,true); + ZZObsTrigger.runObsQueue(); + } finally { ZZUpdateManager.thaw(); } + } + }); + } + private static void updateWindowAttributes(ZZCell c,Container w) { + ZZCell col=c.s("d.color",1,obs); + if(col!=null) { + String colText = col.getText(obs); + + // See if it looks like an URL or a number. + if(Character.isDigit(colText.charAt(0)) || + colText.charAt(0) == '-') + w.setBackground( Color.decode(colText) ); + else { + ZZLogger.log("Not digit first! '"+colText+"'"); + // XXX Find image, store it in the right place (should be + // in content... + /* + URL url = null; + try { + url = new URL(cursor.h("d.photo", 1).getText()); + } catch(MalformedURLException e) { + String s= e.toString(); + g.drawString(s, 0, 0); + return; + } + if(!url.equals(cur)) { + cur = url; + img = getToolkit().getImage(url); + } + if(!g.drawImage(img, 0, 0, null)) { + repaint(1000); + } + */ + } + + if((col=col.s("d.color", 1,obs)) != null) + w.setForeground( Color.decode(col.getText(obs)) ); + } + } + private static void updateEnd() { + for (Enumeration e = views.keys(); e.hasMoreElements();) { + ZZCell cell = (ZZCell) e.nextElement(); + if(!ex.containsKey(cell)) views.remove(cell); + } + for (Enumeration e = frames.keys(); e.hasMoreElements();) { + ZZCell cell = (ZZCell) e.nextElement(); + if(ex.containsKey(cell)) continue; + Frame f = (Frame)frames.get(cell); + f.dispose(); + frames.remove(cell); + } + ex=new Hashtable(); + } +} diff --git a/Java/arch/java2d/ZZDrawingJ2D.java b/Java/arch/java2d/ZZDrawingJ2D.java new file mode 100644 index 0000000..eb27b2d --- /dev/null +++ b/Java/arch/java2d/ZZDrawingJ2D.java @@ -0,0 +1,167 @@ +/* +ZZDrawingJ2D.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.awt.*; +import java.awt.geom.*; + +/** An implementation of ZZDrawing for the Java2D API. + * This allows us to use Java2D's features if present, but + * not to depend on them. + */ + +public class ZZDrawingJ2D extends ZZDrawing { +public static final String rcsid = "$Id: ZZDrawingJ2D.java,v 1.21 2001/03/26 12:41:00 tjl Exp $"; + + public String getType() { + return "Java2D: antialias, alpha(if used), rotation"; + } + + public void setAlpha(Graphics g0, float alpha) { + Graphics2D g = (Graphics2D)g0; + g.setComposite(AlphaComposite.getInstance( + AlphaComposite.SRC_OVER, alpha)); + } + + public RenderingHints qualityHints = new RenderingHints(null); + { + qualityHints.put( + RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + + qualityHints.put( + RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + qualityHints.put(RenderingHints.KEY_RENDERING, + RenderingHints.VALUE_RENDER_QUALITY); + qualityHints.put(RenderingHints.KEY_STROKE_CONTROL, + RenderingHints.VALUE_STROKE_PURE); + + // qualityHints.put(RenderingHints.KEY_FRACTIONALMETRICS, + // RenderingHints.VALUE_FRACTIONALMETRICS_ON); + + } + public RenderingHints speedHints = new RenderingHints(null); + { + speedHints.put(RenderingHints.KEY_RENDERING, + RenderingHints.VALUE_RENDER_SPEED); + } + + public void setFIXME(boolean t) { + if (t) { + qualityHints.put(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + qualityHints.put(RenderingHints.KEY_RENDERING, + RenderingHints.VALUE_RENDER_QUALITY); + qualityHints.put(RenderingHints.KEY_STROKE_CONTROL, + RenderingHints.VALUE_STROKE_PURE); + } + else { + qualityHints.put(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_OFF); + qualityHints.put(RenderingHints.KEY_RENDERING, + RenderingHints.VALUE_RENDER_SPEED); + qualityHints.put(RenderingHints.KEY_STROKE_CONTROL, + RenderingHints.VALUE_STROKE_DEFAULT); + } + } + + public boolean enableQuality(boolean t) { + super.enableQuality(t); + return true; + } + + public void setQuality(Graphics g0) { + Graphics2D g = (Graphics2D)g0; + if (qualityEnabled()) g.setRenderingHints(qualityHints); + else g.setRenderingHints(speedHints); + } + + public void setDefaults(Graphics g0) { + //Graphics2D g = (Graphics2D)g0; + //g.rotate(0.1); + } + + /** A flob which shows the given ZZScene rotated by given angle. + */ + public class RotatedSceneFlob extends SceneFlob { + + double rot; + + public RotatedSceneFlob(int x, int y, int d, int w, int h, ZZCell c, FlobSet sc, + double rot) { + super(x,y,d,w,h,c, sc); + this.rot = rot; + } + + + public void transform(double[] srcPtr, double[]dstPts, boolean toExt) { + AffineTransform tr = + AffineTransform.getRotateInstance(rot, x+w/2, y+h/2); + try { + if(toExt) + tr.transform(srcPtr, 0, dstPts, 0, srcPtr.length); + else + tr.inverseTransform(srcPtr, 0, dstPts, 0, srcPtr.length); + } catch(Exception e) { + ZZLogger.exc(e); + } + } + + public Point transform(Point src, Point dst, boolean toExt) { + AffineTransform tr = + AffineTransform.getRotateInstance(rot, x+w/2, y+h/2); + try { + if(toExt) + tr.transform(src, dst); + else + tr.inverseTransform(src, dst); + } catch(Exception e) { + ZZLogger.exc(e); + } + return dst; + } + + void prepareGraphics(Graphics g0, float fract) { + Graphics2D g = (Graphics2D)g0; + if(fract == 0) { + if(rot != 0) + g.rotate(rot, x+w/2, y+h/2); + return; + } + if(!(interpTo instanceof RotatedSceneFlob)) return; // XXX? + double nrot = rot + fract*(((RotatedSceneFlob)interpTo).rot - rot); + if(nrot == 0) return; + g.rotate(nrot, + (int)((x+w/2)*(1-fract) + + fract * (interpTo.x + interpTo.w/2)), + (int)((y+h/2)*(1-fract) + + fract * (interpTo.y + interpTo.h/2)) + ); + } + + + } +} + + diff --git a/Java/arch/javadoc/ZobDoc.java b/Java/arch/javadoc/ZobDoc.java new file mode 100644 index 0000000..6907875 --- /dev/null +++ b/Java/arch/javadoc/ZobDoc.java @@ -0,0 +1,154 @@ +/* +ZobDoc.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.io.*; +import com.sun.javadoc.*; + +/** A javadoc doclet for extracting ZOb documentation. + * Note that compiling and running this file requires the tools.jar file + * from JDK 1.3. + */ + +public class ZobDoc extends Doclet { +public static final String rcsid = "$Id: ZobDoc.java,v 1.2 2000/11/05 18:22:54 tjl Exp $"; + + static String[][] lists = new String[][] { + { "org.gzigzag.FlobRaster", "Views", "views.html" }, + { "org.gzigzag.RasterFlobFactory", "CellViews", "cellviews.html" } + }; + + PrintWriter[] listpws = new PrintWriter[lists.length]; + + String outdir = null; + + public static boolean start(RootDoc root) { + ZobDoc zd = new ZobDoc(); + return zd.go(root); + } + + public boolean go(RootDoc root) { + try { + readOptions(root.options()); + + for(int i=0; i"+zobname+""); + pw.println("

    Description

    "); + pw.println(cl.commentText()); +// System.out.println(cl.commentText()); + + pw.println("

    Structural parameters

    "); + FieldDoc[] fields = cl.fields(); + for(int i=0; i"+f.name()+""); + pw.println(f.commentText()); + } +} + diff --git a/Java/arch/syslog/arch.mk b/Java/arch/syslog/arch.mk new file mode 100644 index 0000000..8004ec4 --- /dev/null +++ b/Java/arch/syslog/arch.mk @@ -0,0 +1,19 @@ + + +JNI_INCLUDE = /usr/include/kaffe/ + +all : arch/syslog/libgzigzag-syslog.so + +%.o : %.c + $(CC) $(CFLAGS) -I $(JNI_INCLUDE) -fPIC -c -o $@ $< + +arch/syslog/org_gzigzag_SysLogger.o : arch/syslog/org_gzigzag_SysLogger.c arch/syslog/org_gzigzag_SysLogger.h + +arch/syslog/org_gzigzag_SysLogger.h : org/gzigzag/SysLogger.class + javah -jni -d arch/syslog org.gzigzag.SysLogger + +arch/syslog/libgzigzag-syslog.so : arch/syslog/org_gzigzag_SysLogger.o + $(CC) -shared -o $@ $^ + +clean : + rm -f arch/syslog/libgzigzag-syslog.so arch/syslog/org_gzigzag_SysLogger.o arch/syslog/org_gzigzag_SysLogger.h diff --git a/Java/arch/syslog/org_gzigzag_SysLogger.c b/Java/arch/syslog/org_gzigzag_SysLogger.c new file mode 100644 index 0000000..4ba9ce2 --- /dev/null +++ b/Java/arch/syslog/org_gzigzag_SysLogger.c @@ -0,0 +1,46 @@ +/* +org_gzigzag_SysLogger.c + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ + +#include "org_gzigzag_SysLogger.h" +#include + +/* + * Class: org_gzigzag_SysLogger + * Method: openlog + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_gzigzag_SysLogger_openlog(JNIEnv * env, jclass class) { + openlog("gzigzag", LOG_CONS, LOG_DAEMON); +} + +/* + * Class: org_gzigzag_SysLogger + * Method: syslog + * Signature: (Ljava/lang/String;Z)V + */ +JNIEXPORT void JNICALL Java_org_gzigzag_SysLogger_syslog(JNIEnv * env, jclass class, jstring msg, jboolean verb) { + const char * s; + + jboolean isCopy = JNI_FALSE; + s = (*env)->GetStringUTFChars(env, msg, &isCopy); + syslog((verb == JNI_TRUE) ? LOG_NOTICE : LOG_INFO, s); + (*env)->ReleaseStringUTFChars(env, msg, s); +} diff --git a/Java/check.pl b/Java/check.pl new file mode 100644 index 0000000..a91eee5 --- /dev/null +++ b/Java/check.pl @@ -0,0 +1,26 @@ +# +# $Id: check.pl,v 1.2 2000/03/13 00:19:29 tjl Exp $ +# +# A small script to check some gzigzag coding rules. + +# Ouch -- fool RCS +$idstr = 'Id:.*'; + +for(@ARGV) { + /\.java/ or die "Sorry, only .java files"; + print "$_:\n"; + open F, "$_"; + my ($clsrcs, $ifrcs, $long, $length); + while() { + /^public static final String rcsid = "\$$idstr\$";/ + and $clsrcs = 1 and next; + /^String rcsid = "\$$idstr\$";/ + and $ifrcs = 1 and next; + s/\t/ /g; + chomp; + $length = length if length > $length; + } + print "\tNo RCS id\n" unless $clsrcs or $ifrcs; + print "\tOverlong line (longest $length)\n" if $length > 80; + +} diff --git a/Java/clang/Data.java b/Java/clang/Data.java new file mode 100644 index 0000000..dd173e9 --- /dev/null +++ b/Java/clang/Data.java @@ -0,0 +1,130 @@ +/* +Data.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ +package org.gzigzag; + +/** An immutable list of Clang data pieces. + * Each piece can be a cell, a string, an int, or a bool. Pieces are + * automatically converted if possible. That way, data can be stored + * virtually someplace, or in cells; from a list of cells, a Data object + * can be constructed which behaves just as a list of objects containing + * the data directly. E.g.: + * Data d = new Data("hi", new Integer(17), new Boolean(false)); + * can be stored as + * new Data(cell1, cell2, cell3); + * if these cells contain the strings "hi", "17", and "false". Saving + * a Data object into a strip of cells is simple: just do something like this: + * + * for(int i=0; i + * (s(i) is the method to get the ith element of a Data strip as a String.) + */ + +public final class Data { +String rcsid = "$Id: Data.java,v 1.3 2001/01/07 18:21:42 bfallenstein Exp $"; + + private Object[] obs; + + public Data() { obs = new Object[0]; } + public Data(Object o1) { obs = new Object[]{o1}; } + public Data(Object o1, Object o2) { + obs = new Object[]{o1,o2}; } + public Data(Object o1, Object o2, Object o3) { + obs = new Object[]{o1,o2,o3}; } + public Data(Object o1, Object o2, Object o3, Object o4) { + obs = new Object[]{o1,o2,o3,o4}; } + public Data(Object o1, Object o2, Object o3, Object o4, Object o5) { + obs = new Object[]{o1,o2,o3,o4,o5}; } + + public Data(Object[] o) { + obs = new Object[o.length]; + System.arraycopy(o, 0, obs, 0, o.length); + } + public Data(Data d, Object[] o) { + obs = new Object[d.obs.length + o.length]; + System.arraycopy(d.obs, 0, obs, 0, d.obs.length); + System.arraycopy(o, 0, obs, d.obs.length, o.length); + } + public Data(Data d1, Data d2) { + obs = new Object[d1.obs.length + d2.obs.length]; + System.arraycopy(d1.obs, 0, obs, 0, d1.obs.length); + System.arraycopy(d2.obs, 0, obs, d1.obs.length, d2.obs.length); + } + + public int len() { return obs.length; } + + public Object o(int at) { return obs[at]; } + public ZZCell c(int at) { return c(obs[at]); } + public String s(int at) { return s(obs[at]); } + public boolean b(int at) { return b(obs[at]); } + public int i(int at) { return i(obs[at]); } + + public static Object o(Object o) { return o; } + public static ZZCell c(Object o) { + if(!(o instanceof ZZCell)) + throw new ZZError("Wrong clang datum "+o+": not a cell"); + return (ZZCell)o; + } + public static String s(Object o) { + if(o instanceof String) + return (String)o; + else if(o instanceof Integer) + return ""+((Integer)o).intValue(); + else if(o instanceof ZZCell) + return ((ZZCell)o).getText(); + else if(o instanceof Boolean) { + if(((Boolean)o).booleanValue()) + return "true"; + else + return "false"; + } else + return o.toString(); // That's right, right? + // throw new ZZError("Wrong clang datum "+o+": not a str"); + } + public static boolean b(Object o) { + if(o instanceof Boolean) + return ((Boolean)o).booleanValue(); + else { + String str = s(o); + if(str.equals("true")) + return true; + else if(str.equals("false")) + return false; + else + throw new ZZError("Wrong clang datum " + o + ": " + + "not a boolean"); + } + } + public static int i(Object o) { + if(o instanceof Integer) + return ((Integer)o).intValue(); + else { + try { + return Integer.parseInt(s(o)); + } catch(NumberFormatException e) { + throw new ZZError("Wrong clang datum " + o + ": " + + "not an integer"); + } + } + } +} diff --git a/Java/clang/ZZClang1.java b/Java/clang/ZZClang1.java new file mode 100644 index 0000000..27927ae --- /dev/null +++ b/Java/clang/ZZClang1.java @@ -0,0 +1,186 @@ +/* +ZZClang1.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.clang; +import org.gzigzag.*; +import java.util.*; + +/** A primitive test version of Clang. + * NOT YET FINISHED! + *

    + * XXX - make use stack frames in the structure + */ + +public class ZZClang1 implements ZZClangContext /* , ZZClangOp */ { +public static final String rcsid = "$Id: ZZClang1.java,v 1.5 2000/10/18 14:35:31 tjl Exp $"; + public static final boolean dbg = true; + static final void p(String s) { if(dbg) System.out.println(s); } + + Hashtable specials; + Hashtable symtab; + ZZCursor cursor; + ZZCell viewspex; + + /** Execute a script in response to user action. + * This means that the language can have special key words to + * pass as parameters the key as a cell with a span etc. + */ + synchronized public void execUserAction(ZZCell code, ZZCell viewspex, + ZZCell clicked, String key) { + try { + specials = new Hashtable(); + if(key!=null) specials.put("UserAction.keyString", key); + if(clicked!=null) + specials.put("UserAction.clickedCell", clicked); + execEnv(code, viewspex); + } finally { + specials = null; + + } + } + + /** Execute a script in a fresh environment. + */ + synchronized public void execEnv(ZZCell code, ZZCell viewspex2) { + symtab = new Hashtable(); + viewspex = viewspex2; + ZZCursor realcursor = new ZZCursorReal(viewspex); + // Speed & space hack + cursor = new ZZCursorVirtual(realcursor.get()); + + exec(code); + + realcursor.set(cursor.get()); + } + + /** Execute starting from a cell. + * Should not be used from outside except in special cases. + */ + synchronized public void exec(ZZCell code) { + p("CLANG exec "+code); + + for(ZZCell current = code; + current != null; + current = current.s("d.2", 1)) { + // Find op. + ZZClangOp op = (ZZClangOp)funcs.get(current.getText()); + p("OP: op"); + if(op==null) + throw new ZZError("Unknown op '"+current.getText()+ "'"); + op.exec(current, cursor, this); + } + + } + +/* + // XXX allow VAR for local variables! + public void exec(ZZCell c, ZZCell it, ZZCell[] params) { + + // First, read the prototype and set the params + ZZCell[] p = c.readRank("d.1", 1, false); + if(p.length > params.length) + throw new ZZError("Insufficient params"); + for(int i=0; i + * However, may also be cloned with a new cursor cell as a subcontext. + * The subcontext is then totally independent of the parent, but starts + * out with the same values if null. + * NOT YET FINISHED! + *

    + * NOTE!!!!!!! getViewCell's viewcell may not be up to date with the ZZCursor + * operations, if code is compiled to pure java for speed. Sync op? + */ + +public interface ZZClangContext { +String rcsid = "$Id: ZZClangContext.java,v 1.3 2000/09/19 10:31:58 ajk Exp $"; + + /** Obtain a reference to the main cursor of this context. + * Ideally, + *

    +     *  clangcontext.getCursor() == ZZCursorReal(clangcontext.getViewcell())
    +     * 
    + * but this may be optimized away, especially for subcontexts, since + * the cursor is used a *lot*. + */ + ZZCursor getCursor(); + /** Obtain a reference to the main viewcell of this context. + */ + ZZCell getViewspex(); + + /** Get a ZZCell that gives the cell that the given parameter + * ultimately refers to. For example, the parameter could be + * a variable in which case this routine returns the cell that + * the variable is set to. Alternatively, the parameter could + * have an expression using cells in which case the result of + * the evaluated expression is given. + * For instance, if the given param is + * @param param The cell that represents the parameter in the clang script. + * @return The actual cell that the given parameter means in this + * context. + */ + ZZCell paramAsCell(ZZCell param); + + /** Get a cursor that represents the variable in the given parameter. + * @param param As for paramAsCell above. + * @return A cursor representing the given variable, or null + * if the param is not a variable. + */ + ZZCursor paramAsCursor(ZZCell param); + + /** Execute the given parameter cell. + * Used to implement routines such as if, case and loops. + * The code given is executed as if on the main level, so all changes + * to the cursor are reflected back after the code. + * @param param As for paramAsCell above. + */ + void execParam(ZZCell param); + + /** Break encapsulation. + * Obtain a special context thingy given to the implementation. + * Nasty optimization hack. + * XXX This should later be done with transient cells. + */ + Object getSpecial(Object which); + +// ZZClangContext getSubcontext(ZZCell startCursor); +} + + diff --git a/Java/clang/ZZClangContextReal.java b/Java/clang/ZZClangContextReal.java new file mode 100644 index 0000000..71be0de --- /dev/null +++ b/Java/clang/ZZClangContextReal.java @@ -0,0 +1,56 @@ +/* +ZZClangContextReal.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.clang; +import org.gzigzag.*; + +class EUNRNBRRV { +} + +/** A real viewspecs -context object for Clang. + */ + +/* +public class ZZClangContextReal implements ZZClangContext { +String rcsid = "$Id: ZZClangContextReal.java,v 1.5 2000/10/18 14:35:31 tjl Exp $"; + + ZZCell viewCell; + ZZClangContextReal(ZZCell vc) { viewCell = vc; } + + public ZZCursor getCursor() { return new ZZCursorReal(viewCell); } + public String getDimString(int n) { return getDim(n).get().getText(); } + + public ZZCursor getDim(int n) { + ZZCell d = viewCell; + for(int i=0; i + * The cursor crs may or may not be the actual cursor of the viewcell + * of the context: it may also be given negwards on d.1 from the object + * to allow ops to act on other cursors easily. + * @param c The cell that made this routine to be called. + * @param crs The main cursor + * @param ctxt The context of the operation. + * @return The it parameter for the next op. + */ + void exec(ZZCell c, ZZCursor crs, ZZClangContext ctxt); + + /* Be mentally prepared for something like + * + * void compile(ZZClangCompiler clc, ZZCell c, ZZClangContext ctxt); + * + * to appear in the future. + */ + + /** Return the name of this operation. + */ + String name(); +} diff --git a/Java/clang/ZZClangOps.pl b/Java/clang/ZZClangOps.pl new file mode 100644 index 0000000..9af1dfc --- /dev/null +++ b/Java/clang/ZZClangOps.pl @@ -0,0 +1,144 @@ +# +# $Id: ZZClangOps.pl,v 1.5 2000/11/03 08:25:16 ajk Exp $ +# +# Generate ZZClangOps.java for clang operations + +$file = $ARGV[0]; +$file = "ZZClangOps.java" if ($file eq ""); +open F, ">$file" or die "Can't open file $file"; +$rcsid = '$Id: ZZClangOps.pl,v 1.5 2000/11/03 08:25:16 ajk Exp $'; +print F <[0]; + @pars = split ' ',$_->[2]; + $npars = @pars; + my $ind = 1; + my %pars = map {($_ => $ind++)} @pars; + + $_->[3] =~ s/\$P\((.*?)\)/(ctxt.paramAsCell(c.s("d.1", $pars{$1}, null)))/g; + $_->[3] =~ s/\$CURS/ crs /g; + + $classes .= " + /** $_->[2] */ + static class $_->[0] implements ZZClangOp { + public String name() { return \"$lcname\"; } + $exec + { + /* if(params.length != $npars) + throw new ZZError(\"Wrong number of params for $lcname, got \"+ + params.length+\", was expecting $npars\"); + */ + $_->[3] + } + } + "; + push @arrays, " new $_->[0]() "; +} + +$ja = join ",\n",@arrays; + +print F <")) + return new Compare(-2); + if(id.equals("<")) + return new Compare(+2); + if(id.equals(">=")) + return new Compare(-1); + if(id.equals("<=")) + return new Compare(+1); + return null; + } + + static public class Plus extends Primitive { + protected Data execute(Data params) { + if(params.len() < 2) miscount(); + int res = params.i(0); + for(int i=1; i 0) { i0 = params.i(0); i1 = params.i(1); } + else { i0 = params.i(1); i1 = params.i(0); } + + boolean res; + if(weight==0) res = i0 == i1; + else if(weight*weight == 4) res = i0 < i1; + else res = i0 <= i1; + return new Data(new Boolean(res)); + } + } +} diff --git a/Java/clang/flowing/Flowing.java b/Java/clang/flowing/Flowing.java new file mode 100644 index 0000000..692ec84 --- /dev/null +++ b/Java/clang/flowing/Flowing.java @@ -0,0 +1,260 @@ +/* +Flowing.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ +package org.gzigzag.module; +import org.gzigzag.*; +import org.gzigzag.flowing.*; +import java.awt.*; + +/** A module interface to Flowing Clang. + */ + +public class Flowing { +public static final String rcsid = "$Id: Flowing.java,v 1.7.8.1 2001/08/16 13:40:44 bfallenstein Exp $"; + public static boolean dbg = true; + static final void p(String s) { if(dbg) ZZLogger.log(s); } + + static final void createdebugger(ZZCell debug) { + debug.getSpace().getHomeCell().h("d.2", 1).insert("d.2", 1, debug); + ZZCell normal = debug.N("d.1", 1); + normal.setText("Debug mode"); + ZZCell edit = normal.N("d.1", 1); + edit.setText("Text edit mode"); + ZZCell dim0 = edit.N("d.1", 1); + dim0.setText("d..flowing-frame"); + dim0.N("d.2", 1).setText("d.2"); + dim0.N("d.2", 1).setText("d..flowing-data"); + ZZCell dim1 = dim0.N("d.1", 1); + dim1.setText("d.1"); + dim1.N("d.2", 1).setText("d.clone"); + dim1.N("d.2", 1).setText("d.xeq"); + + // EDIT MODE + + ZZCell c = edit.N("d.2", 1); + c.setText("Tab"); + c.N("d.1", 1).setText("SWITCHOFFCURSMODE"); + normal.insert("d.3", 1, c.s("d.1")); + + c = c.N("d.2", 1); + c.setText("Esc"); + c.N("d.1", 1).setText("SWITCHOFFCURSMODE"); + normal.insert("d.3", 1, c.s("d.1")); + + c = c.N("d.2", 1); + ZZDefaultSpace.findOnSystemlist(c.getSpace(), "Bindings", false) + .s("d.1", 2).s("d.2", 1).insert("d.3", -1, c); + + // NORMAL MODE + + c = normal.N("d.2", 1); + c.setText(" "); + c.N("d.1", 1).setText("Flowing.D-STEP"); + + c = c.N("d.2", 1); + c.setText("Enter"); + c.N("d.1", 1).setText("Flowing.D-JUMP"); + + c = c.N("d.2", 1); + c.setText("Backspace"); + c.N("d.1", 1).setText("UNDO"); + + c = c.N("d.2", 1); + c.setText("Alt-Backspace"); + c.N("d.1", 1).setText("REDO"); + + c = c.N("d.2", 1); + c.setText("q"); + c.N("d.1", 1).setText("QUIT"); + + c = c.N("d.2", 1); + c.setText("Tab"); + c.N("d.1", 1).setText("SWITCHCURSMODE"); + edit.insert("d.3", 1, c.s("d.1")); + + c = c.N("d.2", 1); + c.setText("Left"); + c.N("d.1", 1).setText("CRSR X-"); + + c = c.N("d.2", 1); + c.setText("Right"); + c.N("d.1", 1).setText("CRSR X+"); + + c = c.N("d.2", 1); + c.setText("Up"); + c.N("d.1", 1).setText("CRSR Y-"); + + c = c.N("d.2", 1); + c.setText("Down"); + c.N("d.1", 1).setText("CRSR Y+"); + + c = c.N("d.2", 1); + c.setText("j"); + c.N("d.1", 1).setText("CRSR X-"); + + c = c.N("d.2", 1); + c.setText("l"); + c.N("d.1", 1).setText("CRSR X+"); + + c = c.N("d.2", 1); + c.setText("i"); + c.N("d.1", 1).setText("CRSR Y-"); + + c = c.N("d.2", 1); + c.setText(","); + c.N("d.1", 1).setText("CRSR Y+"); + + c = c.N("d.2", 1); + c.setText("K"); + c.N("d.1", 1).setText("CRSR Z-"); + + c = c.N("d.2", 1); + c.setText("k"); + c.N("d.1", 1).setText("CRSR Z+"); + + c = c.N("d.2", 1); + c.setText("s"); + c.N("d.1", 1).setText("CRSR CX-"); + + c = c.N("d.2", 1); + c.setText("f"); + c.N("d.1", 1).setText("CRSR CX+"); + + c = c.N("d.2", 1); + c.setText("e"); + c.N("d.1", 1).setText("CRSR CY-"); + + c = c.N("d.2", 1); + c.setText("c"); + c.N("d.1", 1).setText("CRSR CY+"); + + c = c.N("d.2", 1); + c.setText("D"); + c.N("d.1", 1).setText("CRSR CZ-"); + + c = c.N("d.2", 1); + c.setText("d"); + c.N("d.1", 1).setText("CRSR CZ+"); + } + + static public ZZModule module = new ZZModule() { + public void action(String id, + ZZCell code, + ZZCell target, + ZZView view, ZZView cview, String key, Point pt, ZZScene xi) { + if(id.equals("BIND") || id.equals("BINDREAL") || + id.equals("RUN") || id.equals("RUNREAL")) { + ZZCell prog; + if(id.indexOf("BIND") > -1) { + prog = code.s("d.2"); + if(prog == null) + throw new ZZError("Flowing.BIND without program"); + prog = prog.h("d.clone", -1, true); + if(prog == null) + throw new ZZError("Flowing.BIND prog must be cloned"); + } else { + prog = target; + if(prog == null) + prog = ZZCursorReal.get(view.getViewcell()); + } + boolean real = id.indexOf("REAL") > 0; + FlowingClang.run(prog, new Data(cview.getViewcell(), + view.getViewcell(), + key), real); + } else if(id.equals("DEBUG")) { + p("Create debugger:"); + ZZCell prog = + ZZCursorReal.get(view.getViewcell()).getRootclone(); + ZZCell debug = ZZDefaultSpace.findOnSystemlist( + view.getViewcell().getSpace(), "Flowing.Debugger", true); + if(debug.s("d.1") == null) createdebugger(debug); + ZZCell views = ZZDefaultSpace.findOnSystemlist( + view.getViewcell().getSpace(), "Views", false).s("d.1"); + + p("Start program."); + Data d = new Data(cview.getViewcell(), + view.getViewcell(), key); + ZZCell frame = FlowingClang.start(prog, d); + + p("Create windows."); + ZZCell frameview = ZZDefaultSpace.newToplevelView( + prog.getSpace(), "Flowing stack frame", + 20, 20, 400, 500, + views, debug.s("d.1"), + frame, null, + debug.s("d.1", 3).readRank("d.2", 1, true), + ZZUtil.perturb(Color.blue.brighter())); + ZZCursorReal.setColor(frameview, Color.blue.darker()); + + ZZCell progview = ZZDefaultSpace.newToplevelView( + prog.getSpace(), "Flowing program", + 440, 20, 400, 500, + views, debug.s("d.1"), + ZZCursorReal.get(frame), null, + debug.s("d.1", 4).readRank("d.2", 1, true), + ZZUtil.perturb(Color.red.brighter())); + ZZCursorReal.setColor(progview, Color.red.darker()); + + p("Connecting windows."); + frameview.connect("d.ctrlview", 1, progview); + ZZCell framecur = progview.N("d.2", 1); + framecur.setText("Flowing.StackFrame"); + ZZCursorReal.set(framecur, frame); + + p("Update windows."); + ZZWindows.update(); + } else if(id.indexOf("D-") > -1) { + ZZCell framecur = ZZDefaultSpace.findInheritableParam( + view.getViewcell(), "Flowing.StackFrame"); + if(framecur == null) + throw new ZZError("Flowing Clang debugging command on a " + + "non-debug view"); + ZZCell frame = ZZCursorReal.get(framecur); + StackFrameReal sf = new StackFrameReal(frame), nsf; + + if(id.equals("D-STEP")) + nsf = (StackFrameReal)FlowingClang.step(sf, true); + else if(id.equals("D-JUMP")) { + nsf = (StackFrameReal)FlowingClang.jump(sf); + } else + throw new ZZError("Unknown Flowing.XXX code"); + + if(nsf != null) { + if(nsf != sf) { + ZZCursorReal.set(framecur, nsf.main); + ZZCursorReal.set(cview.getViewcell(), nsf.main); + } + ZZCursorReal.set(view.getViewcell(), nsf.getPos()); + } else { + view.getViewcell().h("d.1").delete(); + cview.getViewcell().h("d.1").delete(); + ZZWindows.update(); + ZZCursorReal.delete(view.getViewcell()); + ZZCursorReal.delete(cview.getViewcell()); + } + } else + throw new ZZError("Unknown Flowing.XXX code"); + } + }; + +} + diff --git a/Java/clang/flowing/FlowingClang.java b/Java/clang/flowing/FlowingClang.java new file mode 100644 index 0000000..4b7522d --- /dev/null +++ b/Java/clang/flowing/FlowingClang.java @@ -0,0 +1,219 @@ +/* +FlowingClang.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written for Heraclitus Clang by Tuomas Lukka + * Adaption for Flowing Clang by Benjamin Fallenstein + */ +package org.gzigzag.flowing; +import org.gzigzag.*; +import java.util.*; + +/** A simple (imperative) clang passing values dataflow-like. + * Kind of a cross between a dataflow ("graphical") programming language and + * an assembler. On the one hand we have sequences of instructions, each with + * zero or more in- and output variables; variables are set and read; + * jmp-style branching. + *

    + * However, variables can only be set in one place + * * XXX not any more -- explain XXX + * (they can be set more than + * once by executing the same instruction multiple times). All references to + * the variable are clones; the original (rootclone) is the place where the + * variable is set. This means when you view d.clone, you can see how the + * data "flows" through the program (hence the language's name). + *

    + * Execution strictly proceeds on d.xeq. There are no blocks: when there's + * nothing more on d.xeq, the call returns. Until then, the return values + * (if any) have to be set. Primitives are called by putting their ID into + * a cell, putting the input values negwards and the variables to take the + * output poswards on d.1 from it. (XXX use a less string-based behavior?) + * Subroutines are called by cloning their maincell. Parameter passing and + * results work the same as with primitives. + *

    + * Primitives and subroutines are passed cells, and return cells. If in + * the "input zone" of for a cell or subroutine (neg on d.1) there's a + * cell which isn't cloned (and thus cannot be read as a variable, because + * it cannot have a value assigned), it is taken as literal and passed to + * the subroutine. Cloned cells (variables) are dereferenced in the stack frame + * for the current routine, which means they have to be set. What's passed to + * the subroutine or primitive is the cell which was formerly assigned to the + * variable, not the variable cell itself. + *

    + * To create a subroutine, create a non-clone cell with the routine's name. + * (Later, you clone this into other code.) Put its input variables + * negwards on d.1. Then put the subroutine on d.xeq. When you're done, + * clone the result variable(s) from the point where you set them in the + * routine to the right of the routine's maincell. + *

    + * To branch, create a cell with a question mark ("?") in a strip, put a value + * (variable or literal, but the latter doesn't make too much sense) in its + * "input zone" (neg on d.1), which contains a boolean value ("true" or "false" + * -- everything else is an error), and put a cell in what would usually be + * its "output zone" (pos on d.1). From there, hang a new strip. If the + * condition is true, execution proceeds on the new strip; if the condition + * is false, execution proceeds on the old strip. + *

    + * Blank cells in a strip are usually just ignored. However, a blank cell at + * the end of a strip works like a goto statement: if there's something + * poswards on d.1, the execution pointer jumps to the endcell on d.1 + * and proceeds execution on d.xeq. This is used when, after branching + * because of some condition, you want to unify your strips (i.e., you + * make a blank cell on the end of each one, connect them on d.1, and + * proceed programming on the posmost cell on d.1). + *

    + * Loops can be constructed by looping ZZ cells. You should take care to + * have a condition somewhere in the loop which can turn true. (XXX break + * infinite loops somehow!) + *

    + * The language only uses the d.1, d.xeq, and d.clone dimensions. The + * combinations d.1/d.xeq, d.1/d.clone, d.1/d.xeq/d.clone, d.1/d.clone/d.xeq + * all make sense to view, especially in the row and column views. + */ + +public class FlowingClang { +public static final String rcsid = "$Id: FlowingClang.java,v 1.7 2000/11/16 20:33:13 bfallenstein Exp $"; + public static boolean dbg = true; + static final void p(String s) { if(dbg) ZZLogger.log(s); } + + public static final String dim = "d.xeq"; + + static Hashtable pss = new Hashtable(); + static PrimitiveSet findPrimitiveSet(String set) { + Object o = pss.get(set); + if(o != null) return (PrimitiveSet)o; + try { + o = Class.forName("org.gzigzag.flowing."+set).newInstance(); + } catch(Exception e) { + ZZLogger.exc(e); + return null; + } + if(!(o instanceof PrimitiveSet)) return null; + pss.put(set, o); + return (PrimitiveSet)o; + } + + static Hashtable prims = new Hashtable(); + static Primitive findPrimitive(String s) { + Object o = prims.get(s); + if(o != null) return (Primitive)o; + + int ind = s.indexOf("."); + if(ind < 0) return null; + String set = s.substring(0, ind); + String id = s.substring(ind+1); + PrimitiveSet ps = findPrimitiveSet(set); + Primitive prim = ps.get(id); + if(prim != null) + prims.put(id, prim); + return prim; + } + + public static Data run(ZZCell c, Data d) { return run(c, d, false); } + + public static Data run(ZZCell c0, Data d, boolean real) { + p("Flowing Clang run: "+c0.getText()); + ZZCell c = c0.getRootclone(); + StackFrame frame; + if(real) frame = new StackFrameReal(c.getSpace()); + else frame = new StackFrameVirtual(); + frame.setPos(c); + frame.put(c, d, -1); + StackFrame f = frame; + try { + while(f != null) f = step(f, true); + } catch(Throwable t) { + ZZLogger.exc(t, "Exception in Flowing Clang run. "); + return null; + } + return frame.get(c, +1); + } + + public static ZZCell start(ZZCell c0, Data d) { + StackFrameReal frame = new StackFrameReal(c0.getSpace()); + frame.setPos(c0); + frame.put(c0, d, -1); + return frame.main; + } + + public static StackFrame jump(StackFrame frame) { + StackFrame f = frame; + do { + f = step(f, true); + } while(frame.parentof(f)); + return f; + } + + public static StackFrame step(StackFrame frame, boolean throwerrs) { + ZZCell cur = frame.getPos().s(dim); + if(cur == null) { // RETURN + p("Flowing clang return step"); + StackFrame ret = frame.ret(); + if(ret == null) return null; + ZZCell rpos = ret.getPos(); + ret.put(rpos, frame.get(rpos.getRootclone(), +1), +1); + frame.delete(); + return ret; + } + + p("Flowing Clang step: "+cur.getText()+" ("+cur.getID()+")"); + ZZCell root = cur.h("d.clone", -1, true); + String s = cur.getText(); + if(s.equals("") && root==null) { // GOTO + frame.setPos(cur.h("d.1", 1)); + return frame; + } + + Data d = frame.get(cur, -1); // IF + if(s.equals("?")) { + Primitive.count(d, 1); + if(d.b(0)) cur = cur.h("d.1", 1); + frame.setPos(cur); + return frame; + } + + Primitive p = findPrimitive(s); + if(p != null) { // PRIMITIVE + try { + d = p.execute(d, cur.getSpace()); + } catch(ZZError e) { + if(throwerrs) throw e; + ZZLogger.exc(e, "Exception in Flowing Clang step. "); + return frame; + } + frame.put(cur, d, +1); + frame.setPos(cur); + return frame; + } else if(root != null) { // FUNCTION CALL + frame.setPos(cur); + StackFrame called = frame.call(); + called.put(root, d, -1); + called.setPos(root); + return called; + } else { // UNKNOWN + if(throwerrs) + throw new ZZError("Not a primitive at " + cur.getID() + ": " + + cur.getText()); + ZZLogger.log("Flowing Clang step cannot be executed: Not a " + + "primitive at " + cur.getID() + ": " + cur.getText()); + return frame; + } + } +} + diff --git a/Java/clang/flowing/Primitive.java b/Java/clang/flowing/Primitive.java new file mode 100644 index 0000000..7c6a8a0 --- /dev/null +++ b/Java/clang/flowing/Primitive.java @@ -0,0 +1,64 @@ +/* +Primitive.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ +package org.gzigzag.flowing; +import org.gzigzag.*; + +/** An Flowing Clang primitive. + */ + +public abstract class Primitive { +String rcsid = "$Id: Primitive.java,v 1.3 2000/10/13 13:52:24 bfallenstein Exp $"; + + // In subclasses, override one of the following two: + protected Data execute(Data params) { return null; } + public Data execute(Data params, ZZSpace space) { + return execute(params); + } + + static public void count(Data pars, int n) { + if(n != pars.len()) miscount(); + } + static public void miscount() { throw new ZZError("Wrong parameter count"); } + + /** Read a direction or step count from a parameter array. + * If the pos is out of the bounds of the array, +1 is assumed, so that + * the dir can optionally be left out. + *

    + * (This, obviously, is just a convenience function.) + */ + static int readsteps(Data pars, int pos) { + if(pos < pars.len()) { + String stepstr = pars.s(pos); + if(stepstr.equals("+")) + return 1; + else if(stepstr.equals("-")) + return -1; + else + return pars.i(pos); + } else { + return 1; + } + } +} + + diff --git a/Java/clang/flowing/PrimitiveSet.java b/Java/clang/flowing/PrimitiveSet.java new file mode 100644 index 0000000..c8d231c --- /dev/null +++ b/Java/clang/flowing/PrimitiveSet.java @@ -0,0 +1,34 @@ +/* +PrimitiveSet.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka (for Heraclitus Clang) + */ +package org.gzigzag.flowing; +import org.gzigzag.*; + +/** A set of Flowing Clang primitives. + */ + +public abstract class PrimitiveSet { +String rcsid = "$Id: PrimitiveSet.java,v 1.3 2000/10/13 13:52:24 bfallenstein Exp $"; + public abstract Primitive get(String id); +} + + diff --git a/Java/clang/flowing/StackFrame.java b/Java/clang/flowing/StackFrame.java new file mode 100644 index 0000000..966093a --- /dev/null +++ b/Java/clang/flowing/StackFrame.java @@ -0,0 +1,117 @@ +/* +StackFrame.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ +package org.gzigzag.flowing; +import org.gzigzag.*; + +/** A stack frame for Flowing Clang. + */ + +public abstract class StackFrame { +String rcsid = "$Id: StackFrame.java,v 1.5 2000/11/16 20:33:13 bfallenstein Exp $"; + public static boolean dbg = true; + static final void p(String s) { if(dbg) ZZLogger.log(s); } + + // METHODS TO BE IMPLEMENTED BY SUBCLASSES + + /** Get the value associated with a cell. */ + public abstract Object getSingle(ZZCell c); + + /** Set the value associated with a cell. + * @param d The Data object in which the value to be set is found. + * @param at The value's position in the Data object. + */ + public abstract void setSingle(ZZCell c, Data d, int at); + + /** Get position of instruction pointer. */ + public abstract ZZCell getPos(); + /** Set position of instruction pointer. */ + public abstract void setPos(ZZCell c); + + /** Create a lower-level stackframe. */ + public abstract StackFrame call(); + + /** Return true if this stack frame is parent of given stack frame. */ + public abstract boolean parentof(StackFrame sf); + + /** Return to the next higher stackframe (disconnects this (lower) frame). + * Also sets instruction pointer to null, but keeps the values associated + * with cells, so that the returned data can be read. Call delete() when + * you're done with the values. + */ + public abstract StackFrame ret(); + + /** Delete the cells associated with the stackframe, if any. + * This renders the values of a structural stackframe inaccessible. + */ + public void delete() {} + + // METHODS StackFrame PROVIDES + + private static final ZZCell[] reverse(ZZCell[] arr) { + ZZCell[] res = new ZZCell[arr.length]; + for(int i=0; i 3) miscount(); + int steps = readsteps(params, 2); + String dim = params.s(1); + return new Data(params.c(0).s(dim, steps)); + } + } + + static public class End extends Primitive { + protected Data execute(Data params) { + if(params.len() < 2 || params.len() > 3) miscount(); + String dim = params.s(1); + return new Data(params.c(0).h(dim, readsteps(params, 2))); + } + } + + static public class Find extends Primitive { + protected Data execute(Data params) { + if(params.len() < 3 || params.len() > 4) miscount(); + String dim = params.s(1), txt; int dir; + if(params.len() == 3) { + dir = 1; + txt = params.s(2); + } else { + dir = readsteps(params, 2); + txt = params.s(3); + } + ZZCell c = params.c(0).findText(dim, dir, txt); + return new Data(c); + } + } + + static public class Original extends Primitive { + protected Data execute(Data params) { + count(params, 1); + return new Data(params.c(0).getRootclone()); + } + } + + static public class Cross extends Primitive { // i.e., intersect + protected Data execute(Data params) { + if(params.len() != 4 && params.len() != 6) miscount(); + ZZCell c0, c1; + String dim0, dim1; + int dir0, dir1; + + if(params.len() == 4) { + c0 = params.c(0); c1 = params.c(2); + dim0 = params.s(1); dim1 = params.s(3); + dir0 = 1; dir1 = 1; + } else { + c0 = params.c(0); c1 = params.c(3); + dim0 = params.s(1); dim1 = params.s(4); + dir0 = readsteps(params, 2); dir1 = readsteps(params, 5); + } + p("CROSS: "+c0.getText()+" "+dim0+" "+dir0+" "+ + c1.getText()+" "+dim1+" "+dir1); + return new Data(c0.intersect(dim0, dir0, c1, dim1, dir1)); + } + } + + static public class HomeCell extends Primitive { + public Data execute(Data params, ZZSpace space) { + count(params, 0); + return new Data(space.getHomeCell()); + } + } + + static public class Connect extends Primitive { + protected Data execute(Data params) { + if(params.len() < 3 || params.len() > 4) miscount(); + if(params.len() == 3) + params.c(0).connect(params.s(1), params.c(2)); + else + params.c(0).connect(params.s(1), readsteps(params, 2), + params.c(3)); + return null; + } + } + + static public class Insert extends Primitive { + protected Data execute(Data params) { + if(params.len() < 3 || params.len() > 4) miscount(); + if(params.len() == 3) + params.c(0).insert(params.s(1), 1, params.c(2)); + else + params.c(0).insert(params.s(1), readsteps(params, 2), + params.c(3)); + return null; + } + } + + static public class Disconnect extends Primitive { + protected Data execute(Data params) { + if(params.len() < 2 || params.len() > 3) miscount(); + params.c(0).disconnect(params.s(1), readsteps(params, 2)); + return null; + } + } + + static public class Hop extends Primitive { + protected Data execute(Data params) { + if(params.len() < 2 || params.len() > 3) miscount(); + params.c(0).hop(params.s(1), readsteps(params, 2)); + return null; + } + } + + static public class New extends Primitive { + public Data execute(Data params, ZZSpace space) { + if(params.len() == 1 || params.len() > 3) miscount(); + if(params.len() == 0) + return new Data(space.getHomeCell().N()); + else { + String dim = params.s(1); + return new Data(params.c(0).N(dim,readsteps(params, 2))); + } + } + } + + static public class Clone extends Primitive { + protected Data execute(Data params) { + count(params, 1); + return new Data(params.c(0).zzclone()); + } + } + + static public class Delete extends Primitive { + protected Data execute(Data params) { + count(params, 1); + params.c(0).delete(); + return null; + } + } + + static public class Same extends Primitive { + protected Data execute(Data params) { + count(params, 1); + return params; + } + } +} diff --git a/Java/clang/flowing/X.java b/Java/clang/flowing/X.java new file mode 100644 index 0000000..b0585a6 --- /dev/null +++ b/Java/clang/flowing/X.java @@ -0,0 +1,138 @@ +/* +X.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ +package org.gzigzag.flowing; +import org.gzigzag.*; +import java.util.*; + +/* + * The "X" (Cell Text) primitive set for Flowing clang. + */ + +public class X extends PrimitiveSet { +public static final String rcsid = "$Id: X.java,v 1.4 2000/10/20 15:16:54 bfallenstein Exp $"; + public static boolean dbg = true; + static final void p(String s) { if(dbg) ZZLogger.log(s); } + + public Primitive get(String id) { + if(id.equals("SET")) + return new Set(); + if(id.equals("+")) + return new Concat(); + if(id.equals("=")) + return new Equals(); + if(id.equals("LEN")) + return new Len(); + if(id.equals("PART")) + return new Part(); + if(id.equals("FIND")) + return new Find(); + if(id.equals("PUICOPY")) + return new PUICopy(); + if(id.equals("PUIPASTE")) + return new PUIPaste(); + if(id.equals("LOG")) + return new Log(); + return null; + } + + static public class Set extends Primitive { + protected Data execute(Data params) { + count(params, 2); + params.c(0).setText(params.s(1)); + return null; + } + } + + static public class Concat extends Primitive { + protected Data execute(Data params) { + if(params.len() < 2) miscount(); + String s = ""; + for(int i=0; i 3) miscount(); + String txt = params.s(0); int start = params.i(1); + if(params.len() == 2) { + txt = txt.substring(start); + } else { + txt = txt.substring(start, params.i(2)); + } + return new Data(txt); + } + } + + static public class Find extends Primitive { + protected Data execute(Data params) { + if(params.len() < 2 || params.len() > 3) miscount(); + String txt = params.s(0), sub = params.s(1); + int start; + if(params.len() == 3) start = params.i(2); + else start = 0; + return new Data(new Integer(txt.indexOf(sub, start))); + } + } + + static public class PUICopy extends Primitive { + protected Data execute(Data params) { + count(params, 1); + ZZUtil.puiCopy(params.s(0)); + return null; + } + } + + static public class PUIPaste extends Primitive { + public Data execute(Data params, ZZSpace space) { + count(params, 0); + return new Data(ZZUtil.puiGetClipText()); + } + } + + static public class Log extends Primitive { + protected Data execute(Data params) { + count(params, 1); + ZZLogger.log(params.s(0)); + return null; + } + } +} diff --git a/Java/clang/heraclitus/HeraclitusClang.java b/Java/clang/heraclitus/HeraclitusClang.java new file mode 100644 index 0000000..261e22c --- /dev/null +++ b/Java/clang/heraclitus/HeraclitusClang.java @@ -0,0 +1,108 @@ +/* +HeraclitusClang.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.heraclitus; +import org.gzigzag.*; +import java.util.*; + +/** A simple execution-based clang. + * Based on a cascading interpreter model, like #! in unix. + * Executables are given as parameters the cell they were referred + * to in (for structural params) and another cell, the parameter. + */ + +public class HeraclitusClang { +public static final String rcsid = "$Id$"; + public static boolean dbg = true; + static final void p(String s) { if(dbg) ZZLogger.log(s); } + + static Hashtable pss = new Hashtable(); + static PrimitiveSet findPrimitiveSet(String set) { + Object o = pss.get(set); + if(o != null) return (PrimitiveSet)o; + try { + o = Class.forName("org.gzigzag.heraclitus."+set).newInstance(); + } catch(Exception e) { + ZZLogger.exc(e); + return null; + } + if(!(o instanceof PrimitiveSet)) return null; + pss.put(set, o); + return (PrimitiveSet)o; + } + + static Hashtable prims = new Hashtable(); + static Primitive findPrimitive(ZZCell c) { + String s = c.getText(); + Object o = prims.get(s); + if(o != null) return (Primitive)o; + + int ind = s.indexOf("."); + if(ind < 0) return null; + String set = s.substring(0, ind); + String id = s.substring(ind+1); + PrimitiveSet ps = findPrimitiveSet(set); + Primitive prim = ps.get(id); + if(prim != null) + prims.put(id, prim); + return prim; + } + + /** Execute a heraclitus operation. + * @param op This cell gives the operation, either by + * being the clone of a Heraclitus primitive + * or by having its root clone have an "exe-type". + * @param param The parameter to be given for the + * execution. + */ + public static ZZCell execute(ZZCell op, ZZCell param) { + Primitive p = findPrimitive(op); + p("Heraclitus exec: "+p); + if(p == null) { + ZZCell n = op.h("d.clone", -1); + p = findPrimitive(n); + if(p == null) { + ZZCell nx = op.h("d.exe-type", -1, true); + if(nx == null) { + throw new ZZError("No executable primitive"); + } + // The core: create the new langcache level + ZZCell curs1 = op.getHomeCell().N(); + ZZCell curs2 = curs1.N("d.1", 1); + ZZCursorReal.set(curs1, op); + ZZCursorReal.set(curs2, param); + try { + p("Heraclitus recurse: "+nx); + return execute(nx, curs1); + } finally { + // XXX ZZCursorReal -delete as well?!?! + ZZCursorReal.delete(curs1); + ZZCursorReal.delete(curs2); + curs1.delete(); + curs2.delete(); + } + } + } + return p.execute(op, param); + } +} + diff --git a/Java/clang/heraclitus/HeraclitusCommand.zob b/Java/clang/heraclitus/HeraclitusCommand.zob new file mode 100644 index 0000000..a44c6c6 --- /dev/null +++ b/Java/clang/heraclitus/HeraclitusCommand.zob @@ -0,0 +1,79 @@ +/* +HeraclitusCommand.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ + +package org.gzigzag; +import java.awt.*; + +/** ZZCommand interface to Heraclitus Clang. + */ +class HeraclitusCommand extends ZZCommand implements ZOb { + public static boolean dbg = false; + static final void p(String s) { if(dbg) ZZLogger.log(s); } + static final void pa(String s) { ZZLogger.log(s); } + + STRUCTPARAMS { + /** Heraclitus operation cell. */ + ZZCell op + = null; + } + + INITIALIZE { + if(op == null) + throw new ZZError("Must specify Heraclitus Clang operation!"); + } + + public void exec(ZZCell param) { + throw new ZZError("exec not implemented yet"); + } + + + public void execCallback( + ZZCell target, + ZZView view, + ZZView cview, + String key, + Point pt, + ZZScene xi + ) { + ZZCell curspar = op.N(); + ZZCell curs1 = op.N(); + ZZCell curs2 = curs1.N("d.1", 1); + ZZCursorReal.set(curs1, cview.getViewcell()); + ZZCursorReal.set(curs2, view.getViewcell()); + ZZCursorReal.set(curspar, curs1); + try { + p("Enter heraclitus: "); + org.gzigzag.heraclitus.HeraclitusClang.execute(op, curspar); + p("Exit heraclitus"); + } finally { + ZZCursorReal.delete(curs1); + ZZCursorReal.delete(curs2); + ZZCursorReal.delete(curspar); + curs1.delete(); + curs2.delete(); + curspar.delete(); + } + + } + +} + +// vim: set syntax=java : diff --git a/Java/clang/heraclitus/PS1.java b/Java/clang/heraclitus/PS1.java new file mode 100644 index 0000000..754a7ad --- /dev/null +++ b/Java/clang/heraclitus/PS1.java @@ -0,0 +1,85 @@ +/* +PS1.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.heraclitus; +import org.gzigzag.*; +import java.util.*; + +/** + * The first primitive set for Heraclitus clang. + */ + +public class PS1 implements PrimitiveSet { +public static final String rcsid = "$Id$"; + public static boolean dbg = true; + static final void p(String s) { if(dbg) ZZLogger.log(s); } + + public Primitive get(String id) { + if(id.equals("Move1Test")) + return new Move1Test(); + return null; + } + + /** First test: move a HERA1 (see ZZPrimitiveActions) datacursor one + * step pos on d.1. + */ + static public class Move1Test implements Primitive { + public ZZCell execute(ZZCell primitive, ZZCell cursorparam) { + p("Move1test"); + ZZCell c0 = ZZCursorReal.get(cursorparam); + ZZCell c = c0.s("d.1", 1); + ZZCell v = ZZCursorReal.get(c); + ZZCell t0 = ZZCursorReal.get(v); + ZZCell t = t0.s("d.1", 1); + p("M1T: "+cursorparam+" "+c0+" "+c+" "+t0+" "+t); + ZZCursorReal.set(v, t); + return cursorparam; + } + } + + /** A text translator: translates fixed strings into other fixed + * strings. + */ + + + /** Dereference the cursorparameter: expects the cursorparameter + * to point to another cursor, and makes it point to the place + * the other cursor pointed to. + */ + static public class Deref1 implements Primitive { + public ZZCell execute(ZZCell primitive, ZZCell cursorparam) { + ZZCell c = ZZCursorReal.get(cursorparam); + if(c == null) return null; + ZZCursorReal.set(cursorparam, ZZCursorReal.get(c)); + return cursorparam; + } + } + + /** Execute a sequence of cells with the same cursorparam. + */ + static public class Seq1 implements Primitive { + public ZZCell execute(ZZCell primitive, ZZCell cursorparam) { + // ZZCell root = cursorParam. + return cursorparam; + } + } +} diff --git a/Java/clang/heraclitus/Primitive.java b/Java/clang/heraclitus/Primitive.java new file mode 100644 index 0000000..f852745 --- /dev/null +++ b/Java/clang/heraclitus/Primitive.java @@ -0,0 +1,41 @@ +/* +Primitive.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.heraclitus; +import org.gzigzag.*; + +/** An Heraclitus Clang primitive. + * A primitive, just like a subroutine, executes one cell with another + * as a parameter, and returns another cell. + */ + +public interface Primitive { +String rcsid = "$Id$"; + /** Execute this primitive. + * @param instance The cell instance (clone) that was originally + * requested to be executed. + * @param param The parameter given to the execution. + */ + ZZCell execute(ZZCell instance, ZZCell param); +} + + diff --git a/Java/clang/heraclitus/PrimitiveSet.java b/Java/clang/heraclitus/PrimitiveSet.java new file mode 100644 index 0000000..766277c --- /dev/null +++ b/Java/clang/heraclitus/PrimitiveSet.java @@ -0,0 +1,34 @@ +/* +PrimitiveSet.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.heraclitus; +import org.gzigzag.*; + +/** A set of Heraclitus Clang primitives. + */ + +public interface PrimitiveSet { +String rcsid = "$Id$"; + Primitive get(String id); +} + + diff --git a/Java/clang/thales/DimensionNames.java b/Java/clang/thales/DimensionNames.java new file mode 100644 index 0000000..5c43abb --- /dev/null +++ b/Java/clang/thales/DimensionNames.java @@ -0,0 +1,52 @@ +/* +DimensionNames.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho. + */ + +package org.gzigzag.clang.thales; + +import org.gzigzag.*; + +/** Parametrized names of Thales Clang special dimensions. This class + allows easy renaming of these dimensions should one become + necessary. */ +class DimensionNames { + // Note: the members should not be final! (Allows substituting + // this class alone to a precompiled GZigZag.) + + // syntax + public static String sequence = "d.thales-sequence"; + public static String literal = "d.thales-literal"; + public static String argument = "d.thales-argument"; + public static String procedure = "d.thales-procedure"; + public static String primitives = "d.thales-internal-primitives"; + public static String primbinding = "d.thales-internal-binding"; + public static String syntaxform = "d.thales-internal-syntactic-form"; + public static String syntaxformlist = "d.thales-internal-syntactic-form-list"; + + // runtime + public static String tasks = "d.thales-rt-active-tasks"; + public static String stack = "d.thales-rt-stack"; + public static String stackptr = "d.thales-rt-stackptr"; + public static String activations = "d.thales-rt-denoter-activations"; + public static String environment = "d.thales-rt-environment"; + public static String applicable = "d.thales-rt-applicable"; + +} + diff --git a/Java/clang/thales/Environment.java b/Java/clang/thales/Environment.java new file mode 100644 index 0000000..82577a1 --- /dev/null +++ b/Java/clang/thales/Environment.java @@ -0,0 +1,109 @@ +/* +Task.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho. + */ + + +package org.gzigzag.clang.thales.*; + +import org.gzigzag.*; + +/** A runtime environment. It contains runtime instances of cell + denoters. Remember to register/unregister references (that are in + the structure (not Java references)). */ +class Environment implements Refcounted { + private ZZCell cell; + + public Environment(ZZCell cell) { + this.cell = cell.h(DimensionNames.environment); + } + + public Environment(ZZCell firstparam, Environment parent) { + cell = firstparam.N(DimensionNames.activations, 1); + ZZCell prev = cell; + for (ZZCell c = cell.s(DimensionNames.argument, 1); + c != null; + c = c.s(DimensionNames.argument, 1)) { + ZZCell nc = c.N(DimensionNames.activations, 1); + prev.connect(DimensionNames.environment, 1, nc); + prev = nc; + } + if (parent != null) ZZCursorReal.set(first, parent.getCell()); + cell.setReferenceCount("0"); + parent.registerReference(); + } + + public ZZCell getCell() { return cell; } + + protected int getReferenceCount() { + String text = cell.getText(); + return Integer.parseInt(text); + } + + protected void setReferenceCount(int rc) { + cell.setText("" + rc); + } + + public void registerReference() { + setReferenceCount(getReferenceCount() + 1); + } + + public void unregisterReference() { + setReferenceCount(getReferenceCount() - 1); + if (getReferenceCount() < 1) delete(); + } + + public void delete() { + ZZCell parent = ZZCursorReal.get(cell); + ZZCell c = cell; + while (c != null) { + ZZCell tmp = c; + c = c.s(DimensionNames.environment, 1); + tmp.delete(); + } + if (parent != null) parent.unregisterReference(); + } + + protected ZZCell getDenoterInstance(ZZCell denoter) { + ZZCell ecell = cell; + ZZCell rv = null; + while (rv == null) { + rv = denoter.intersect(DimensionNames.activations, 1, + ecell, DimensionNames.environment, 1); + if (rv == null) { + ecell = ZZCursorReal.get(ecell); + if (ecell == null) { + throw new ZZError("accessing inaccessible denoter"); + } + } + } + return rv; + } + + public ZZCell getDenoterValue(ZZCell denoter) { + ZZCell dc = getDenoterInstance(denoter); + return ZZCursorReal.get(dc); + } + + public void setDenoterValue(ZZCell denoter, ZZCell value) { + ZZCell dc = getDenoterInstance(denoter); + ZZCursorReal.set(dc, value); + } + +} diff --git a/Java/clang/thales/Evaluator.java b/Java/clang/thales/Evaluator.java new file mode 100644 index 0000000..1d68c3a --- /dev/null +++ b/Java/clang/thales/Evaluator.java @@ -0,0 +1,62 @@ +/* +Evaluator.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho. + */ + + +package org.gzigzag.clang.thales.*; + +import org.gzigzag.*; + +public class Evaluator { + + private Task task; + + public Evaluator() { this(null); } + public Evaluator(Task task) { this.task = task; } + + public Environment getCurrentEnvironment() { + return task.getCurrentEnvironment(); + } + + public void setCurrentEnvironment(Environment e) { + task.setCurrentEnvironment(e); + } + + public void request(SyntaxForm sf) { + task.push(sf.getCell()); + sf.registerReference(); + } + + public void finish_eval(SyntaxForm sf) { + task.remove(sf.getCell()); + sf.unregisterReference(); + } + + private final void eval_iter() { + ZZCell c = task.peek(); + SyntaxForm sf = SyntaxForm.rt_instantiate(c, this); + sf.eval_iteration(); + } + + public void eval_iteration() { eval_iter(); } + + public void eval() { while (!task.empty()) eval_iter(); } + +} diff --git a/Java/clang/thales/PrimitiveOperation.java b/Java/clang/thales/PrimitiveOperation.java new file mode 100644 index 0000000..2789240 --- /dev/null +++ b/Java/clang/thales/PrimitiveOperation.java @@ -0,0 +1,32 @@ +/* +PrimitiveOperation.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho. + */ + +package org.gzigzag.clang.thales; + +import org.gzigzag.*; + +interface PrimitiveOperation { + + int parameterCount(); + + ZZCell invoke(ZZCell[] arguments); + +} diff --git a/Java/clang/thales/README b/Java/clang/thales/README new file mode 100644 index 0000000..59e75c2 --- /dev/null +++ b/Java/clang/thales/README @@ -0,0 +1,4 @@ +This directory contains the reference implementation of Thales Clang. + +Talk to Antti-Juhani Kaijanaho before making any +nontrivial changes. diff --git a/Java/clang/thales/Refcounted.java b/Java/clang/thales/Refcounted.java new file mode 100644 index 0000000..99ea57f --- /dev/null +++ b/Java/clang/thales/Refcounted.java @@ -0,0 +1,28 @@ +/* +Task.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho. + */ + + +package org.gzigzag.clang.thales.*; + +interface Refcounted { + void registerReference(); + void unregisterReference(); +} diff --git a/Java/clang/thales/SyntaxForm.java b/Java/clang/thales/SyntaxForm.java new file mode 100644 index 0000000..435de4a --- /dev/null +++ b/Java/clang/thales/SyntaxForm.java @@ -0,0 +1,168 @@ +/* +SyntaxForm.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho. + */ + +package org.gzigzag.clang.thales; + +import org.gzigzag.*; +import java.lang.reflect.*; + +/** Syntax form. Subclasses must have at least two constructors: one + taking a ZZCell as an argument (the cell must be used to deduce + existing runtime state) and another taking two ZZCells as + arguments (the first cell must be used for parsing the expression, + the other cell must be understood to mean the cell that should be + updated to point to the result of the expression). */ +public abstract class SyntaxForm implements Refcounted { + + static protected ZZCell newRT(ZZSpace space, Class cl) { + String name = cl.getName(); + name = name.substring(name.lastIndexOf(".")+1); + ZZCell home = space.getHomecell(); + ZZCell namec = home.findText(DimensionNames.syntaxformlist, 1, name); + if (namec == null) { + namec = home.N(DimensionNames.syntaxformlist, 1); + namec.setText(name); + } + return namec.zzclone(); + } + + static public SyntaxForm rt_instantiate(ZZCell c, Evaluator etor) { + ZZCell sfc = c.h("d.clone"); + + if (sfc == null) throw new ZZError("no d.clone headcell"); + + if (sfc.h(DimensionNames.syntaxformlist) != sfc.getHomecell()) { + throw new ZZError("not in syntax form list"); + } + + Object o; + + try { + Class cl = Class.forName("org.gzigzag.clang.thales.syntaxform" + + name); + Class cellcl = Class.forName("org.gzigzag.ZZCell"); + Constructor ctor = cl.getConstructor(new Class[] { cellcl }); + o = ctor.newInstance(new Object[] { c } ); + } catch (ClassNotFoundException e) { + throw new ZZError("syntax form not found (" + e + ")"); + } catch (InstantiationException e) { + throw new ZZError("problems instantiating syntax form: " + e); + } catch (IllegalAccessException e) { + throw new ZZError("" + e); + } + + if (!(o instanceof SyntaxForm)) throw new InvalidException(); + + SyntaxForm rv = (SyntaxForm) o; + + rv.etor = etor; + + return rv; + } + + static public SyntaxForm code_instantiate(ZZCell code, ZZCell rv, + Evaluator etor) { + ZZCell sfc = code.h(DimensionNames.syntaxform); + + if (sfc == null) throw new ZZError("invalid syntax form"); + + Object o; + + try { + Class cl = Class.forName("org.gzigzag.clang.thales.syntaxform" + + sfc); + Class cellcl = Class.forName("org.gzigzag.ZZCell"); + Constructor ctor = cl.getConstructor(new Class[] { cellcl, cellcl }); + o = ctor.newInstance(new Object[] { c, rv } ); + } catch (ClassNotFoundException e) { + throw new ZZError("syntax form not found (" + e + ")"); + } catch (InstantiationException e) { + throw new ZZError("problems instantiating syntax form: " + e); + } catch (IllegalAccessException e) { + throw new ZZError("" + e); + } + + if (!(o instanceof SyntaxForm)) throw new InvalidException(); + + SyntaxForm rv = (SyntaxForm)o; + rv.etor = etor; + return rv; + } + + private ZZCell base; + private Evaluator etor = null; + + /** Construct oneself using an existing syntax form runtime + cell. */ + protected SyntaxForm(ZZCell c) { + base = c; + } + + /** Construct oneself using a new syntax form runtime cell. */ + protected SyntaxForm(ZZSpace s) { + this(SyntaxForm.newRT(s, this.getClass())); + } + + protected SyntaxForm code_instantiate(ZZCell code, ZZCell rv) { + SyntaxForm.code_instantiate(code, rv, etor); + } + + protected final ZZCell getBaseCell() { return base; } + protected final void requestEval(SyntaxForm sf) { etor.request(sf); } + protected final void finishEval() { etor.finishEval(this); } + protected final void setCurrentEnvironment(Environment e) { + etor.setCurrentEnvironment(e); + } + protected final Environment getCurrentEnvironment() { + return etor.getCurrentEnvironment(); + } + + public abstract void evalIteration(); + + /** Delete the runtime representation unconditionally. */ + protected abstract void delete(); + + private int getReferenceCount() { + String text = cell.getText(); + if (text.equals("")) { + setReferenceCount(0); + return getReferenceCount(); + } + return Integer.parseInt(text); + } + + private void setReferenceCount(int rc) { + cell.setText("" + rc); + } + + public final void registerReference() { + setReferenceCount(getReferenceCount() + 1); + } + + public final void unregisterReference() { + setReferenceCount(getReferenceCount() - 1); + if (getReferenceCount() < 1) { + delete(); + cell.delete(); + } + } + +} diff --git a/Java/clang/thales/Task.java b/Java/clang/thales/Task.java new file mode 100644 index 0000000..77f1d13 --- /dev/null +++ b/Java/clang/thales/Task.java @@ -0,0 +1,81 @@ +/* +Task.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho. + */ + +package org.gzigzag.clang.thales.*; + +import org.gzigzag.*; + +class Task { + private ZZCell cell; + + public Environment getCurrentEnvironment() { + return new Environment(ZZCursorReal.get(cell)); + } + + public void setCurrentEnvironment(Environment e) { + ZZCursorReal.set(cell, e.getCell()); + } + + public void push(ZZCell c) { + ZZCell ct = peek(); + if (ct != null) { + c.connect(DimensionNames.stack, 1, ct); + cell.disconnect(DimensionNames.stackptr, 1); + } + cell.connect(DimensionNames.stackptr, 1, c); + } + + public void pop() { + ZZCell ct = peek(); + if (ct == null) throw ZZError("empty Thales Clang runtime stack"); + ZZCell nt = ct.s(DimensionNames.stack, 1); + cell.disconnect(DimensionNames.stackptr, 1); + if (nt != null) cell.connect(DimensionNames.stackptr, 1, nt); + nt.disconnect(DimensionNames.stack, -1); + } + + public ZZCell peek() { + return cell.s(DimensionNames.stackptr, 1); + } + + public void remove(ZZCell c) { + { + ZZCell nei = c.s(DimensionNames.stackptr, -1); + if (nei.equals(cell)) { + pop(); + return; + } + } + + for (ZZCell i = peek(); i != null && !i.equals(c); + i = i.s(DimensionNames.stack, 1)) { + // nothing + } + if (i == null) throw ZZError("cannot remove that which is not there"); + + c.deleteFromRank(DimensionNames.stack); + } + + public boolean empty(ZZCell c) { + return peek() == null; + } + +} diff --git a/Java/clang/thales/ThalesClang.java b/Java/clang/thales/ThalesClang.java new file mode 100644 index 0000000..908c0f4 --- /dev/null +++ b/Java/clang/thales/ThalesClang.java @@ -0,0 +1,46 @@ +/* +ThalesClang.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho. + */ + +package org.gzigzag.module; + +import org.gzigzag.*; +import java.awt.*; +import org.gzigzag.clang.thales.*; + +public class ThalesClang { + static public ZZModule module = new ZZModule() { + public void action(String id, + ZZCell code, + ZZCell target, + ZZView view, ZZView cview, + String key, Point pt, ZZScene xi) { + ZZSpace space = code.getSpace(); + if (id.equals("RELOAD")) { + Primitive.readPrimitivesFromStructure(code.getSpace()); + } else if (id.equals("INITIALIZE")) { + Primitive.register(space, "If"); + } else { + throw new ZZError("unknown ThalesClang module command"); + } + } + + }; +} diff --git a/Java/clang/thales/ThalesProgram.zob b/Java/clang/thales/ThalesProgram.zob new file mode 100644 index 0000000..9e4cc4c --- /dev/null +++ b/Java/clang/thales/ThalesProgram.zob @@ -0,0 +1,45 @@ +/* +ThalesProgram.zob + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho. + */ + +package org.gzigzag.*; + +import org.gzigzag.clang.thales.*; + +class ThalesProgram extends ZZCommand implements ZOb { + + STRUCTPARAM { + + ZZCell body; + + } + + public void execCallback( + ZZCell target, + ZZView view, + ZZView cview, + String key, + Point pt, + ZZScene xi + ) { + + } + +} diff --git a/Java/clang/thales/primitives/If.java b/Java/clang/thales/primitives/If.java new file mode 100644 index 0000000..fa183f4 --- /dev/null +++ b/Java/clang/thales/primitives/If.java @@ -0,0 +1,28 @@ +/* +If.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho. + */ + +package org.gzigzag.clang.thales.primitive; + +import org.gzigzag.clang.thales.*; + +public class If extends Primitive { + +} diff --git a/Java/clang/thales/syntaxforms/Abstraction.java b/Java/clang/thales/syntaxforms/Abstraction.java new file mode 100644 index 0000000..e6bba78 --- /dev/null +++ b/Java/clang/thales/syntaxforms/Abstraction.java @@ -0,0 +1,55 @@ +/* +Primitive.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho. + */ + +package org.gzigzag.clang.thales.syntaxform; + +import org.gzigzag.*; +import org.gzigzag.clang.thales.*; + +public class Abstraction extends SyntaxForm { +public static final String rcsid = "$Id: Abstraction.java,v 1.4 2000/10/18 14:35:31 tjl Exp $"; + + // Runtime representation basecell -> rvcc -> bodyc -> envc posward on d.1 + private final class Rep { + public ZZCell rvcc; + public ZZCell rvc; + public ZZCell bodyc; + public ZZCell body; + public ZZCell envc; // pointer to inherited environment + public Environment env; // dereferenced envc + + /** Create from existing structure. */ + public Rep() { + rvcc = getBaseCell().s("d.1", 1); + rvc = ZZCursorReal.get(rvcc); + bodyc = rvcc.s("d.1", 1); + body = ZZCursorReal.get(bodyc); + envc = bodyc.s("d.1", 1); + env = new Environment(ZZCursorReal.get(envc)); + } + + public Rep(ZZCell body, Environment env, ZZCell rvc + + } + + + +} diff --git a/Java/clang/thales/syntaxforms/CellDenoter.java b/Java/clang/thales/syntaxforms/CellDenoter.java new file mode 100644 index 0000000..844a342 --- /dev/null +++ b/Java/clang/thales/syntaxforms/CellDenoter.java @@ -0,0 +1,82 @@ +/* +CellDenoter.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho. + */ + +package org.gzigzag.clang.thales.syntaxform; + +import org.gzigzag.*; +import org.gzigzag.clang.thales.*; + +class CellDenoter extends SyntaxForm { + // Runtime representation: basecell -> rvcc -> instc on d.1 posward + private final class Rep { + public ZZCell rvcc; // pointer to return value pointer + public ZZCell rvc; // dereferenced rvcc + public ZZCell instc; // Pointer to runtime instance of the denoter + public ZZCell inst; // dereferenced instc + + /** Create from existing structure. */ + public Rep() { + rvcc = getBaseCell().s("d.1", 1); + rvc = ZZCursorReal.get(rvcc); + instc = rvcc.s("d.1", 1); + inst = ZZCursorReal.get(instc); + } + + public Rep(ZZCell inst, ZZCell rvc) { + this.rvc = rvc; + this.inst = inst; + rvcc = getBaseCell().N("d.1", 1); + instc = rvcc.N("d.1", 1); + ZZCursorReal.set(rvcc, rvc); + ZZCursorReal.set(instc, inst); + Environment env = new Environment(inst); + env.registerReference(); + } + + public void delete() { + rvcc.delete(); + instc.delete(); + Environment env = new Environment(inst); + env.unregisterReference(); + } + } + + public CellDenoter(ZZCell c, Evaluator etor) { super(c, etor); } + + public CellDenoter(ZZCell expr, ZZCell rvc, Evaluator etor) { + super(SyntaxForm.newRT(rvc.getSpace(), this.getClass()), etor); + Environment env = getCurrentEnvironment(); + ZZCell instance = env.getDenoterInstance(expr); + Rep rep(instance, rvc); + } + + public void evalIteration() { + Rep rep; + ZZCursorReal.set(rep.rvc, ZZCursorReal.get(rep.inst)); + finishEval(); + } + + public void delete() { + Rep rep; + rep.delete(); + } + +} diff --git a/Java/clang/thales/syntaxforms/CellLiteral.java b/Java/clang/thales/syntaxforms/CellLiteral.java new file mode 100644 index 0000000..95fc84b --- /dev/null +++ b/Java/clang/thales/syntaxforms/CellLiteral.java @@ -0,0 +1,75 @@ +/* +CellLiteral.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho. + */ + +package org.gzigzag.clang.thales.syntaxform; + +import org.gzigzag.*; +import org.gzigzag.clang.thales.*; + +class CellLiteral extends SyntaxForm { + // Runtime representation: basecell -> rvcc -> litc on d.1 posward + private final class Rep { + public ZZCell rvcc; // pointer to the return value pointer + public ZZCell rvc; // dereferenced rvcc + public ZZCell litc; // pointer to literal value + + /** Create from existing structure. */ + public Rep() { + rvcc = getBaseCell().s("d.1", 1); + rvc = ZZCursorReal.get(rvcc); + litc = rvcc.s("d.1", 1); + } + + /** Create also a new structure. */ + public Rep(ZZCell lit, ZZCell rvc) { + this.rvc = rvc; + rvcc = getBaseCell().N("d.1", 1); + ZZCursorReal.set(rvcc, rvc); + litc = rvcc.N("d.1", 1); + ZZCursorReal.set(litc, lit); + } + + public void delete() { + rvcc.delete(); + litc.delete(); + } + } + + public CellLiteral(ZZCell c, Evaluator etor) { + super(c, etor); + } + + public CellLiteral(ZZCell expr, ZZCell rvc, Evaluator etor) { + super(SyntaxForm.newRT(rvc.getSpace(), this.getClass()), etor); + Rep rep(ZZCursorReal.get(expr), rvc); + } + + public void evalIteration() { + Rep rep; + ZZCursorReal.set(rep.rvc, ZZCursorReal.get(rep.litc)); + finishEval(); + } + + protected void delete() { + Rep rep; + rep.delete(); + } +} diff --git a/Java/clang/thales/syntaxforms/Primitive.java b/Java/clang/thales/syntaxforms/Primitive.java new file mode 100644 index 0000000..d551a8e --- /dev/null +++ b/Java/clang/thales/syntaxforms/Primitive.java @@ -0,0 +1,191 @@ +/* +Primitive.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho. + */ + +package org.gzigzag.clang.thales.syntaxform; + +import org.gzigzag.*; +import org.gzigzag.clang.thales.*; +import java.util.*; + +public class Primitive extends SyntaxForm { +public static final String rcsid = "$Id: Primitive.java,v 1.7 2000/10/18 14:35:31 tjl Exp $"; + public static boolean dbg = false; + final static void p(String s) { if(dbg) System.out.println(s); } + final static void pa(String s) { System.out.println(s); } + + // Runtime representation basecell -> rvcc -> primc posward on d.1 + private final class Rep { + public ZZCell rvcc; // pointer to return value pointer + public ZZCell rvc; // dereferenced rvcc + public ZZCell primc; // pointer to the primitive cell + public ZZCell prim; // the primitive cell + + /** Create from existing structure. */ + public Rep() { + rvcc = getBaseCell().s("d.1", 1); + rvc = ZZCursorReal.get(rvcc); + primc = rvcc.s("d.1", 1); + prim = ZZCursorReal.get(rvc); + } + + /** Create also a new structure. */ + public Rep(ZZCell prim, ZZCell rvc) { + this.rvc = rvc; + rvcc = getBaseCell().N("d.1", 1); + ZZCursorReal.set(rvcc, rvc); + this.prim = prim; + primc = rvcc.N("d.1", 1); + ZZCursorReal.set(primc, prim); + } + + public void delete() { + rvcc.delete(); + primc.delete(); + } + } + + public Primitive(ZZCell c) { super(c); } + public Primitive(ZZCell expr, ZZCell rvc) { + super(rvc.getSpace()); + Rep rep(expr.h("d.clone", -1), rvc); + } + + public void evalIteration() { + Rep rep; + + ZZCell rv = rep.rvc.N(); + rv.connect(DimensionNames.applicable, 1, rep.prim); + ZZCursorReal.set(rep.rvc, rv); + finishEval(); + } + + public void delete() { + Rep rep; + rep.delete(); + } + + + + static private Hashtable prims = new Hashtable(); + static private Hashtable optocell = new Hashtable(); + + static public PrimitiveOperation get(ZZCell c) { + ZZCell id = c.h("d.clone", -1); + synchronized (prims) { + return (PrimitiveOperation) prims.get(id); + } + } + + static public class PrimitiveProblemException extends ZZError { + public PrimitiveProblemException(String s) { + super(s); + } + } + + static public class DuplicateException extends PrimitiveProblemException { + public DuplicateException() { + this("duplicate Thales Clang primitive cell"); + } + public DuplicateException(String s) { + super(s); + } + } + + static public class InvalidException extends PrimitiveProblemException { + public InvalidException() { + this("invalid Thales Clang primitive cell"); + } + public InvalidException(String s) { + super(s); + } + } + + static private void readAPrimitive(ZZCell c) { + ZZCell op = c.s(DimensionNames.primbinding, 1); + + if (op == null) throw new InvalidException(); + + Object o; + + try { + Class cl = Class.forName("org.gzigzag.clang.thales.primitive." + op.getText()); + o = cl.newInstance(); + } catch (ClassNotFoundException e) { + throw new InvalidException("primitive not found (" + e + ")"); + } catch (InstantiationException e) { + throw new InvalidException("problems instantiating primitive: " + e); + } catch (IllegalAccessException e) { + throw new InvalidException("" + e); + } + + if (!(o instanceof PrimitiveOperation)) throw new InvalidException(); + + // XXX: is this necessary or desirable? + if (optocell.containsKey(o)) throw new DuplicateException(); + + synchronized (prims) { + prims.put(c, o); + optocell.put(o, c); + } + } + + static public void readPrimitivesFromStructure(ZZSpace space) { + ZZCell home = space.getHomeCell(); + + synchronized (prims) { + for (ZZCell c = home.s(DimensionNames.primitives, 1); + c != null; + c = c.s(DimensionNames.primitives, 1)) { + try { + readAPrimitive(c); + } catch (PrimitiveProblemException e) { + pa("" + e); + } + } + } + } + + static public void register(ZZSpace space, String mc) { + ZZCell home = space.getHomeCell(); + + synchronized (prims) { + ZZCell id = home.N(); + ZZCell name = id.N(DimensionNames.primbinding, 1); + + name.setText(mc); + + try { + readAPrimitive(id); + } catch (ZZError e) { + id.delete(); + name.delete(); + throw e; + } + + home.insert(DimensionNames.primitives, 1, id); + } + } + +} + + + + diff --git a/Java/clang/thales/syntaxforms/Sequence.java b/Java/clang/thales/syntaxforms/Sequence.java new file mode 100644 index 0000000..8ea1c38 --- /dev/null +++ b/Java/clang/thales/syntaxforms/Sequence.java @@ -0,0 +1,95 @@ +/* +Sequence.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho. + */ + +package org.gzigzag.clang.thales.syntaxform; + +import org.gzigzag.*; +import org.gzigzag.clang.thales.*; + +class Sequence extends SyntaxForm { + // Runtime representation: basecell -> rvcc -> tmprc -> csec on + // d.1 posward + private final class Rep { + public ZZCell rvcc; // pointer to return value pointer + public ZZCell rvc; // dereferenced rvcc + public ZZCell tmprc; // temporary holder of component expression results + public ZZCell tmpr; // dereferenced tmprc + public ZZCell csec; // pointer to the current subexpression in code + public ZZCell cse; // current subexpression in code + + /** Create from existing structure. */ + public Rep() { + rvcc = getBaseCell().s("d.1", 1); + rvc = ZZCursorReal.get(rvcc); + tmprc = rvcc.s("d.1", 1); + tmpr = ZZCursorReal.get(tmprc); + csec = tmprc.s("d.1", 1); + cse = ZZCursorReal.get(csec); + } + + /** Create also a new structure. */ + public Rep(ZZCell fse, ZZCell rvc) { + rvcc = getBaseCell().N("d.1", 1); + ZZCursorReal.set(rvcc, rvc); + this.rvc = rvc; + tmprc = rvcc.N("d.1", 1); + tmpr = null; + csec = tmprc.N("d.1", 1); + ZZCursorReal.set(csec, fse); + cse = fse; + } + + public void delete() { + rvcc.delete(); + tmprc.delete(); + csec.delete(); + } + + public Sequence(ZZCell c) { super(c); } + + public Sequence(ZZCell expr, ZZCell rvc) { + super(rvc.getSpace()); + ZZCell fse = expr.s(DimensionNames.sequence, 1); + if (fse == null) { + throw new SyntaxError("sequence must have at least one element"); + } + Rep rep(fse, rvc); + } + + public void evalIteration() { + Rep rep; + + if (rep.cse == null) { + ZZCursorReal.set(rvc, tmpr); + finishEval(); + } + + SyntaxForm sf = code_instantiate(rep.cse, tmprc); + + requestEval(sf); + + ZZCursorReal.set(rep.csec, + rep.cse.s(DimensionNames.sequence, 1)); + } + + } + +} diff --git a/Java/d.java b/Java/d.java new file mode 100644 index 0000000..20b33f5 --- /dev/null +++ b/Java/d.java @@ -0,0 +1,47 @@ +/* +d.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; + +/** A funny hack to allow funny code. + * This class defines names for many of the common dimensions. If + * you have imported the package, you can then refer to d.clone + * as d.clone, without the quotation marks, and the constant in this + * class will be there. + *

    + * It is unfortunate that d.1 cannot be done with this, but this can + * be a blessing since code shouldn't usually be hard-coded to use + * the numbered dimensions. + *

    + * This class may have to be retired once dimensions are cells in order + * to allow different views to work on different dimensions. + * @deprecated Not useful any more. + */ + +public class d { +public static final String rcsid = "$Id: d.java,v 1.8 2000/10/26 18:09:29 tjl Exp $"; + public static final String clone="d.clone"; + public static final String mark="d.mark"; + public static final String cursor="d.cursor"; +// public static final String cursor-cargo="d.cursor-cargo"; + public static final String preflet="d.preflet"; +} diff --git a/Java/dump2java.pl b/Java/dump2java.pl new file mode 100644 index 0000000..7ffb2e1 --- /dev/null +++ b/Java/dump2java.pl @@ -0,0 +1,147 @@ +# +# dump2java.pl +# * +# * Copyright (c) 2000, Ted Nelson and Tuomas Lukka +# * +# * You may use and distribute under the terms of either the GNU Lesser +# * General Public License, either version 2 of the license or, +# * at your choice, any later version. Alternatively, you may use and +# * distribute under the terms of the XPL. +# * +# * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of +# * the licenses. +# * +# * This software is distributed in the hope that it will be useful, +# * but WITHOUT ANY WARRANTY; without even the implied warranty of +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README +# * file for more details. +# * +# */ +# /* +# * Written by Benjamin Fallenstein +# */ +# + +@ARGV == 2 or die "Two params: infile outfile"; + +$outfile = pop @ARGV; +$infile = $ARGV[0]; + +$declare = ""; +$create = ""; + +$str = join '', <>; +#$str =~ + # /HEADER\n\n((?:.+\n)*)\n\nCONTENTS\n\n((?:.+\n)*)\n\nCONNECTIONS\n\n((?:(?:.+\n)*\n)*)\nEND OF FILE/ + # or die("Bad .zzd file: $infile"); + +@parts = split "\n\n\n", $str; +($hdr, $ctnt, $conns) = @parts; + +foreach(split '\n', $hdr) { + ($var, $val) = split ': '; + if($var =~ /^Format/) { + die("Wrong Dump format: $infile") + unless $val == "Dump 2"; + } elsif($var =~ /^Title/) { + $title = $val; + } +} + +sub cref { + my $id = $_[0]; + if($id != 0 || $id eq "0") { + $id = "__cs[$id]"; + } + return $id; +} + +$no = 0; +%nos = (); +foreach(split '\n', $ctnt) { + $_ =~ /^(.*?) (.*)$/; + ($id, $ct) = ($1, $2); + $nos{$id} = $no; + $no++; + + $ct =~ s/"/\\"/; + $create_ctnt .= qq{ "$ct",\n}; + + if($id == 0 && $id ne "0" && $id ne "") { + $declare .= " ZZCell $id;\n"; + $create_vars .= " $id = __ct[$no];"; + } +} + +$dimno = 0; +foreach (split '\n\n', $conns) { + ($dim, @parts) = split '\n'; + $dim =~ s/"/\\"/; + $create_dims .= qq{ "$dim",\n}; + + foreach(@parts) { + ($id1, $id2) = split ' '; + $create_conns .= " { $dimno, " . + $nos{$id1} . ", " . $nos{$id2} . + " },\n"; + } + + $dimno++; +} + +$nu = <$outfile" or die "No out: '$outfile'"; +print OUT $nu; +#print $nu; +close OUT; diff --git a/Java/errors/MissingTermError.java b/Java/errors/MissingTermError.java new file mode 100644 index 0000000..1ea6440 --- /dev/null +++ b/Java/errors/MissingTermError.java @@ -0,0 +1,30 @@ +/* +MissingTermError.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein. + */ + +package org.gzigzag; + +import org.gzigzag.*; + +/** An error to indicate a term in a clang program is missing. + */ +public class MissingTermError extends SyntaxError { + public MissingTermError(String s) { super(s); } +} diff --git a/Java/errors/SyntaxError.java b/Java/errors/SyntaxError.java new file mode 100644 index 0000000..45adc03 --- /dev/null +++ b/Java/errors/SyntaxError.java @@ -0,0 +1,28 @@ +/* +SyntaxError.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho. + */ + +package org.gzigzag; + +import org.gzigzag.*; + +public class SyntaxError extends ZZError { + public SyntaxError(String s) { super(s); } +} diff --git a/Java/errors/ZZConnectWouldBreakError.java b/Java/errors/ZZConnectWouldBreakError.java new file mode 100644 index 0000000..8717087 --- /dev/null +++ b/Java/errors/ZZConnectWouldBreakError.java @@ -0,0 +1,34 @@ +/* +ZZConnectWouldBreakError.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; + +/** A connect operation would break an existing connection and is not + * allowed. + */ + +public class ZZConnectWouldBreakError extends ZZError { +public static final String rcsid = "$Id: ZZConnectWouldBreakError.java,v 1.3 2000/09/19 10:31:59 ajk Exp $"; + public ZZConnectWouldBreakError(String s) { super(s); } +} + diff --git a/Java/errors/ZZError.java b/Java/errors/ZZError.java new file mode 100644 index 0000000..7296565 --- /dev/null +++ b/Java/errors/ZZError.java @@ -0,0 +1,42 @@ +/* +ZZError.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +/* + * Things can happen to browsers in magical libraries that make + * having your face pulled off by tentacled monstrosities from + * the Dungeon Dimensions seem a mere light massage by comparison. + * - Terry Pratchett, Mort, p. 153 + */ + +package org.gzigzag; + +/** A relatively recoverable ZigZag error. + * Later on, this should be subclassed and specialized as necessary. + * Note that catching this is ok - it's just that normally + * when it happens, we want to just let it unwind the stack without + * having to declare "throws ZZException" everywhere. + */ + +public class ZZError extends Error { +public static final String rcsid = "$Id: ZZError.java,v 1.4 2000/09/19 10:31:59 ajk Exp $"; + public ZZError(String s) { super(s); } +} diff --git a/Java/errors/ZZFatalError.java b/Java/errors/ZZFatalError.java new file mode 100644 index 0000000..e0d98a8 --- /dev/null +++ b/Java/errors/ZZFatalError.java @@ -0,0 +1,40 @@ +/* +ZZFatalError.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +/* + * Things can happen to browsers in magical libraries that make + * having your face pulled off by tentacled monstrosities from + * the Dungeon Dimensions seem a mere light massage by comparison. + * - Terry Pratchett, Mort, p. 153 + */ + +package org.gzigzag; + +/** An irrecoverable ZZ error. Some consistency error that has + * made it dangerous to proceed: execution should be ceased at once. + * + */ + +public class ZZFatalError extends Error { +public static final String rcsid = "$Id: ZZFatalError.java,v 1.3 2000/09/19 10:31:59 ajk Exp $"; + public ZZFatalError(String s) { super(s); } +} diff --git a/Java/errors/ZZInfiniteLoop.java b/Java/errors/ZZInfiniteLoop.java new file mode 100644 index 0000000..5881e87 --- /dev/null +++ b/Java/errors/ZZInfiniteLoop.java @@ -0,0 +1,33 @@ +/* +ZZInfiniteLoop.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; + +/** An operation caused an infinite loop. + */ + +public class ZZInfiniteLoop extends ZZError { +public static final String rcsid = "$Id: ZZInfiniteLoop.java,v 1.3 2000/09/19 10:31:59 ajk Exp $"; + public ZZInfiniteLoop(String s) { super(s); } +} + diff --git a/Java/errors/ZZInvalidCursorPositionError.java b/Java/errors/ZZInvalidCursorPositionError.java new file mode 100644 index 0000000..1847dac --- /dev/null +++ b/Java/errors/ZZInvalidCursorPositionError.java @@ -0,0 +1,34 @@ +/* +ZZInvalidCursorPositionError.java + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; + +/** Tried to move a cursor to a place that can't have cursors on it. + * @deprecated Cursors can be anywhere, now. + */ + +public class ZZInvalidCursorPositionError extends ZZError { +public static final String rcsid = "$Id: ZZInvalidCursorPositionError.java,v 1.4 2000/10/26 18:09:29 tjl Exp $"; + public ZZInvalidCursorPositionError(String s) { super(s); } +} + diff --git a/Java/errors/ZZInvalidDimensionError.java b/Java/errors/ZZInvalidDimensionError.java new file mode 100644 index 0000000..f3e473a --- /dev/null +++ b/Java/errors/ZZInvalidDimensionError.java @@ -0,0 +1,33 @@ +/* +ZZInvalidDimensionError.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; + +/** A given dimension is invalid. + */ + +public class ZZInvalidDimensionError extends ZZError { +public static final String rcsid = "$Id: ZZInvalidDimensionError.java,v 1.3 2000/09/19 10:31:59 ajk Exp $"; + public ZZInvalidDimensionError(String s) { super(s); } +} + diff --git a/Java/exp/rast/vanishing.view b/Java/exp/rast/vanishing.view new file mode 100644 index 0000000..7d2f3bd --- /dev/null +++ b/Java/exp/rast/vanishing.view @@ -0,0 +1,107 @@ +# An attempt to describe vanishingview using +# CDTree raster in a hypothetical language. +# +# Python-like: syntax includes spaces +# a . b = vector product +# :f(...) = one-directional external function + +CDTree(3) + +Param + # the fraction the gap between cells is from the size + # of the larger one + float gfrac + + # Alignment point of node at given size + vec2 :align(node, vec2) + + # the size for node given fraction. + # If node is null, return a reasonable constant one + vec2 :fsize(node, float) + + # Reverse perspective + float revper + + # Whether cells' sizes should stretch + boolean varsize + + # How much to shrink cells along different axes + float shrink0 + float shrink1 + float shrink2 + + # The fract of the initial cell + float initmul + +Var + # The location of a cell + vec2 v(i) + + # The location of the point of alignment of a cell + vec2 av(i) + + # The location of a cell, without revper having been applied + vec2 rv(i) + + # The location of cell's alignpoint, without revper having been applied + vec2 rav(i) + + # Fraction for the font size + float fract(i) + + # Size of the cell + vec2 size(i) + + # The x and y gaps + vec2 gap(i) + + # The gap size between two cells. + vec2 gapb(i,j) + +Local(i) + av(i) = v(i) + :align(i, size(i)) + v(i) = revper * rv(i) + av(i) = revper * rav(i) + + if(varsize) + size(i) = :fsize(i, fract) + else + size(i) = :fsize(null, fract) + + gap(i) = gfrac * size(i) + +Neighbour + + # The shrinking size away from center + + out_0(i,j) => + fract(j) = shrink0 * fract(i) + out_1(i,j) => + fract(j) = shrink1 * fract(i) + out_2(i,j) => + fract(j) = shrink2 * fract(i) + + # Propagate the gap to between the cells + out_*(i,j) => + gapb(i,j) = gap(i) + + + # The positions of the cells + + pos_0(i,j) => + rv(j) . X = v(i) + size(i) . X + gapb(i,j) . X + rav(j) . Y = av(i) . Y + + pos_1(i,j) => + rv(j) . Y = v(i) + size(i) . Y + gapb(i,j) . Y + rav(j) . X = av(i) . X + + # We do z axis in a simplistic way until tested + pos_2(i,j) => + rv(j) = v(i) + size(i) + gapb(i,j) + +Init + av(origin) = vec2(0,0) + fract(origin) = initmul + + diff --git a/Java/flob/ArrowDecor.java b/Java/flob/ArrowDecor.java new file mode 100644 index 0000000..73bf477 --- /dev/null +++ b/Java/flob/ArrowDecor.java @@ -0,0 +1,134 @@ +/* +ArrwDecor.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +/** Arrows. + */ + +public class ArrowDecor extends CoordDecor { +public static final String rcsid = "$Id: ArrowDecor.java,v 1.4 2000/10/26 18:09:29 tjl Exp $"; + public static final boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + Color color; + + /** A simple class that knows how to efficiently build + * ArrowDecors. + */ + static public class Builder extends CoordDecor.Builder { + Color col; + public Builder(FlobSet into, Color col) { + super(into); + this.col = col; + } + /** Make a line. + */ + public final void ar(int x0, int y0, int x1, int y1) { + makeRoom(4); + p[curp] = x0; + p[curp+1] = y0; + p[curp+2] = x1; + p[curp+3] = y1; + curp += 4; + } + protected Renderable create() { + return new ArrowDecor(p, np, col, d); + } + + } + + public ArrowDecor(int[] coords, int n, int d) { + this(coords, n, null, d); + } + + /** Usual constructor. + * @param coords The coordinates for the lines, given as + * quadruplets x1, y1, x2, y2. + */ + public ArrowDecor(int[] coords, int n, Color color, int d) { + super(coords, n, d); + this.color = color; + } + + public ArrowDecor(int x1, int y1, int x2, int y2, Color color, int d) { + super(null, 4, d); + this.coords = new int[] { + x1, y1, x2, y2 + }; + this.color = color; + this.d = d; + } + + public void render(Graphics g) { + Color old = null; + if(color != null) { + old = g.getColor(); + g.setColor(color); + } + + for(int i=0; i+3 s.length()) { + // XXX What to do? + return x + xoffs + h + fm.stringWidth(s); + } + return x + xoffs + h + fm.stringWidth(s.substring(0, ind)) ; + } + + public void render(Graphics g, int mx, int my, int md, + int mw, int mh) { + int ty = my + (mh-fh)/2 + fasc; + Color bu = g.getColor(); + g.setColor(ballColor != null ? ballColor : Color.white); + g.fillOval(mx+yoffs, my+yoffs, mh-2*yoffs, mh-2*yoffs); + g.setFont(f); + int start = 0; + int end = -1; + while (end < s.length()) { // Split into lines + + do { + end = s.indexOf(' ', end + 1); + if (end == -1) break; + } while (fm.stringWidth(s.substring(start, end)) < mw); + + if (end == -1) + end = s.length(); + if (start < end) { + String line = s.substring(start, end); + + g.setColor(bgColor); + if (false && start != 0) { + g.fillRect(mx+xoffs + h - 2, ty - (fasc - (fh-fasc)), fm.stringWidth(line), fasc-(fh-fasc)); + } else { + g.drawString(line, mx+xoffs + h - 1, ty - 1); + g.drawString(line, mx+xoffs + h + 2, ty + 2); + } + + g.setColor(Color.white); + g.drawString(line, mx+xoffs + h + 1, ty + 1); + + g.setColor(bu); + g.drawString(line, mx+xoffs + h, ty); + ty += fasc; + } + start = end + 1; + } + + g.setColor(bu); + g.drawOval(mx+yoffs, my+yoffs, mh-2*yoffs, mh-2*yoffs); + } + + public BallCell(int x, int y, int d, int w, int h, + ZZCell c, ZZCell strCell, String s, + Font f, FontMetrics fm, FlobSet fs) { + super(x, y, d, w, h, c); + + // Not true, since c can be the flob cell and d the referring + // cell. + // this.s = c.getText(); + + this.s = (s==null? "" : s); + this.strCell = strCell; + + this.f = f; + this.fm = fm; + + this.fh = fm.getAscent()+fm.getDescent(); + this.fasc = fm.getAscent()+fm.getLeading(); + this.sw = fm.stringWidth(this.s); + + this.bgColor = fs.getBackground(); + } + + public Object hit(int x0, int y0) { + if(!insideRect(x0, y0)) return null; + // Search for the right position in the string. + // We return a virtual cursor. + int ind = ZZUtil.findStringHit(s, x0-x-xoffs-h, fm); + + return new ZZCursorVirtual(strCell, ind); + } + + public Point getCenter(Point p) { + p.x = x + h/2; + p.y = y + h/2; + return p; + } + +} + + diff --git a/Java/flob/BeamDecor.java b/Java/flob/BeamDecor.java new file mode 100644 index 0000000..3a7794d --- /dev/null +++ b/Java/flob/BeamDecor.java @@ -0,0 +1,107 @@ +/* +BeamDecor.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +/** A class for drawing beam decorations. + * Beams are currently irregular octagons. + * NOTE: Beams are rendered in reverse order: the first beam put in here + * becomes the topmost. + */ + +public class BeamDecor extends CoordDecor { +public static final String rcsid = "$Id: BeamDecor.java,v 1.4 2000/09/19 10:31:59 ajk Exp $"; + public static boolean dbg = false; + static void p(String s) { if(dbg) System.out.println(s); } + static void pa(String s) { System.out.println(s); } + + Color[] colors; + + /** A simple class that knows how to efficiently build + * these things. + */ + static public class Builder extends CoordDecor.Builder { + Color []col; + public Builder(FlobSet into) { + super(into); + } + + protected void makeRoom(int l) { + if(col != null && nth >= col.length) + endl(); + super.makeRoom(l); + } + + protected void alloc() { + super.alloc(); + col = new Color[np/16]; + } + /** Make a beam. + * Coords: first 8x, then 8y. + */ + public final void b(int []xy, Color c) { + makeRoom(16); + p("beam: "+p+" "+col+" "+curp+" "+nth); + for(int i=0; i<16; i++) + p[curp+i] = xy[i]; + col[nth] = c; + curp += 16; + nth++; + } + protected Renderable create() { + Color[] col2 = col; + col = null; + return new BeamDecor(p, np, d, col2); + } + + } + + public BeamDecor(int[] coords, int n, int d, Color[] cols) { + super(coords, n, d); + this.colors = cols; + } + + + public void render(Graphics g) { + Color old = null; + old = g.getColor(); + + int[] x = new int[8]; + int[] y = new int[8]; + for(int i=(n-16)-n%16; i>=0; i-=16) { + for(int k = 0; k<8; k++) + x[k] = coords[i+k]; + for(int k = 0; k<8; k++) + y[k] = coords[i+8+k]; + + g.setColor(colors[i/16]); + g.fillPolygon(x, y, 8); + } + + g.setColor(old); + } + +} diff --git a/Java/flob/BoxType.java b/Java/flob/BoxType.java new file mode 100644 index 0000000..b2ca204 --- /dev/null +++ b/Java/flob/BoxType.java @@ -0,0 +1,90 @@ +/* +BoxType.java + * + * Copyright (c) 2001, Ted Nelson and Tuomas Lukka + * Copyright (c) 2001, Benja Fallenstein + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benja Fallenstein + */ + +package org.gzigzag; +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +/** A type of boxes to be drawn around vobs (like the CellBgFlob backgrounds). + * Default: render nothing. + */ + +public class BoxType { +public static final String rcsid = "$Id: BoxType.java,v 1.2 2001/03/18 17:50:16 bfallenstein Exp $"; + public static final boolean dbg = true; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + protected Color bg = Color.white; + public void setBg(Color c) { if( c != null ) bg = c; } + + protected void renderBg(Graphics g, BoxedFlob f, int mx, int my, + int md, int mw, int mh) {} + + protected void renderFrame(Graphics g, BoxedFlob f, int mx, int my, + int md, int mw, int mh) {} + + /** Render the background behind the flob. + */ + public void renderBg(Graphics g, Flob f) { + renderBg(g, (BoxedFlob)f, f.x, f.y, f.d, f.w, f.h); + } + + /** Render the frame around the flob. + */ + public void renderFrame(Graphics g, Flob f) { + renderFrame(g, (BoxedFlob)f, f.x, f.y, f.d, f.w, f.h); + } + + /** Render the interpolated background behind the flob. + */ + public void renderBg(Graphics g, Flob f, float fract) { + // XXX the interpolation path isn't necessarily linear! + Flob r = f.interpTo; + renderBg(g, (BoxedFlob)f, + (int)(f.x + fract*(r.x-f.x)), + (int)(f.y + fract*(r.y-f.y)), + (int)(f.d + fract*(r.d-f.d)), + (int)(f.w + fract*(r.w-f.w)), + (int)(f.h + fract*(r.h-f.h)) + ); + } + + /** Render the interpolated frame around the flob. + */ + public void renderFrame(Graphics g, Flob f, float fract) { + // XXX the interpolation path isn't necessarily linear! + Flob r = f.interpTo; + renderFrame(g, (BoxedFlob)f, + (int)(f.x + fract*(r.x-f.x)), + (int)(f.y + fract*(r.y-f.y)), + (int)(f.d + fract*(r.d-f.d)), + (int)(f.w + fract*(r.w-f.w)), + (int)(f.h + fract*(r.h-f.h)) + ); + } +} + + diff --git a/Java/flob/BoxedFlob.java b/Java/flob/BoxedFlob.java new file mode 100644 index 0000000..ae82aac --- /dev/null +++ b/Java/flob/BoxedFlob.java @@ -0,0 +1,83 @@ +/* +BoxedFlob.java + * + * Copyright (c) 2001, Ted Nelson and Tuomas Lukka + * Copyright (c) 2001, Benja Fallenstein + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka, adapted by Benja Fallenstein + */ + +package org.gzigzag; +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +/** A flob which gets rendered by FlobSet with a background. + * XXX support for different shapes than rectangular? + * XXX replace Colorer entirely by this? + * XXX renderer must know whether background is transparent! + * XXX move needsBox here and default to true?!? replace by instanceof Boxed? + */ + +public class BoxedFlob extends Flob implements Colorer { +public static final String rcsid = "$Id: BoxedFlob.java,v 1.1 2001/03/20 11:08:36 ajk Exp $"; + public static final boolean dbg = true; +// static final void p(String s) { if(dbg) System.out.println(s); } +// static final void pa(String s) { System.out.println(s); } + +// XXX need this? boolean drawBorder = true; + + public boolean needsBox() { return true; } + + int nsolids = 0; + Color[] solids; + protected Color bg = Color.white; + + public Object hit(int x0, int y0) { + if( x0 >= x && y0 >= y && x0 < x+w && y0 < y+h ) + return c; + return null; + } + + public void setBg(Color c){ if( c != null ) bg = c; } + + /** Adds one more solid color to be drawn inside + * the cell. + */ + public boolean addColor(Color c) { + if(solids == null || nsolids >= solids.length) { + Color[] n= new Color[nsolids + 10]; + if(solids != null) System.arraycopy(solids, 0, n, 0, nsolids); + solids = n; + } + solids[nsolids++] = c; + return false; + } + /** The currently put solid colors. + * null = none. There may be null references near the end + * of the array. Mostly useful for checking for nullness. + */ + public Color[] getSolidColors() { return solids; } + + public BoxedFlob(int x, int y, int d, int w, int h, + ZZCell c) { + super(x, y, d, w, h, c); + } +} + + diff --git a/Java/flob/CellBgFlob.java b/Java/flob/CellBgFlob.java new file mode 100644 index 0000000..e52d533 --- /dev/null +++ b/Java/flob/CellBgFlob.java @@ -0,0 +1,118 @@ +/* +CellBgFlob.java + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +/** A flob for the cell background. + * Draws a filled (possibly with several colors) background rectangle, + * surrounded by a rectangle of the current foreground color. + */ + +public class CellBgFlob extends Flob implements Colorer { +public static final String rcsid = "$Id: CellBgFlob.java,v 1.16 2001/02/26 18:03:29 raulir Exp $"; + public static final boolean dbg = true; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + boolean drawBorder = true; + + int nsolids = 0; + Color[] solids; + protected Color bg = Color.white; + + public Object hit(int x0, int y0) { + if( x0 >= x && y0 >= y && x0 < x+w && y0 < y+h ) + return c; + return null; + } + + public void setBg(Color c){ if( c != null ) bg = c; } + + /** Override this in subclasses to render something inside the cell. + */ + protected void renderContent(Graphics g, int mx, int my, int mw, int mh) { + } + + public void render(Graphics g, int mx, int my, int md, int mw, int mh) { + + // p("ZZCC1 render: "+g+" "+mx+" "+my+" "+mw+" "+mh); + Color oldfg = g.getColor(); + Shape oldclip = g.getClip(); + + // XXX save font? + + g.clipRect(mx, my, mw, mh); + + if(solids != null) { + for(int i=0; i= 14) { + g.drawRect(mx+1, my+1, mw-3, mh-3); + } + } + g.setClip(oldclip); + } + + /** Adds one more solid color to be drawn inside + * the cell. + */ + public boolean addColor(Color c) { + if(solids == null || nsolids >= solids.length) { + Color[] n= new Color[nsolids + 10]; + if(solids != null) System.arraycopy(solids, 0, n, 0, nsolids); + solids = n; + } + solids[nsolids++] = c; + return false; + } + /** The currently put solid colors. + * null = none. There may be null references near the end + * of the array. Mostly useful for checking for nullness. + */ + public Color[] getSolidColors() { return solids; } + + public CellBgFlob(int x, int y, int d, int w, int h, + ZZCell c) { + super(x, y, d, w, h, c); + } +} + + diff --git a/Java/flob/CellFlob1.java b/Java/flob/CellFlob1.java new file mode 100644 index 0000000..531e1a7 --- /dev/null +++ b/Java/flob/CellFlob1.java @@ -0,0 +1,105 @@ +/* +CellFlob1.java + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +public class CellFlob1 extends BoxedFlob { +public static final String rcsid = "$Id: CellFlob1.java,v 1.16 2001/03/18 17:50:16 bfallenstein Exp $"; + public static final boolean dbg = true; + + String s; + Font f; + // XXX Should this *really* need to be stored here? + FontMetrics fm; + + /** Font height. */ + int fh; + int fasc; + /** String width. */ + int sw; + + ZZCell strCell; + + int xoffs = 0; // Previously, these margins where three, but at the moment + int yoffs = 0; // margins are cared for by the BoxTypes + + static public final Dimension getSize(FontMetrics fm, String str, + int xoffs, int yoffs) { + int w = fm.stringWidth(str) + xoffs * 2 + 2; + int h = fm.getHeight() + 2*yoffs; + if(w < h) w = h; + return new Dimension( w, h ); + } + + public int getStrX(int ind) { + if(fm == null) throw new Error("No fontmetrics"); + if(ind > s.length()) { + // XXX What to do? + return x + xoffs + fm.stringWidth(s); + } + return x + xoffs + fm.stringWidth(s.substring(0, ind)) ; + } + + public void render(Graphics g, int mx, int my, int md, int mw, int mh) { + Shape oldClip = g.getClip(); + g.clipRect(mx, my, mw, mh); + int ty = my + (mh-fh)/2 + fasc; + g.setFont(f); + g.drawString(s, mx+xoffs, ty); + g.setClip(oldClip); + } + + public CellFlob1(int x, int y, int d, int w, int h, + ZZCell c, ZZCell strCell, String s, + Font f, FontMetrics fm) { + super(x, y, d, w, h, c); + + // Not true, since c can be the flob cell and d the referring + // cell. + // this.s = c.getText(); + + this.s = (s==null? "" : s); + this.strCell = strCell; + + this.f = f; + this.fm = fm; + + this.fh = fm.getAscent()+fm.getDescent(); + this.fasc = fm.getAscent()+fm.getLeading(); + this.sw = fm.stringWidth(this.s); + } + + public Object hit(int x0, int y0) { + if(!insideRect(x0, y0)) return null; + // Search for the right position in the string. + // We return a virtual cursor. + int ind = ZZUtil.findStringHit(s, x0-x-xoffs, fm); + + return new ZZCursorVirtual(strCell, ind); + } + +} + diff --git a/Java/flob/CellFlobFactory1.zob b/Java/flob/CellFlobFactory1.zob new file mode 100644 index 0000000..a52648a --- /dev/null +++ b/Java/flob/CellFlobFactory1.zob @@ -0,0 +1,205 @@ +/* +RasterFactory1.zob + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** A simple cell factory that gives the cells as one-line strings. + * Variable length is possible. + */ + +public class CellFlobFactory1 implements FlobFactory, ZOb { +public static final String rcsid = "$Id$"; + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + STRUCTPARAMS { + + /** The string to use to get the default cell width. */ + String widthstr + = "0000000000"; + + /** The default background color. + * XXX Currently, because of color mixing, the foreground + * comes from FlobSet. This should maybe change - check later. + */ + Color bg + = Color.white; + + /** The font for the default enlargement. */ + ScalableFont font + = new ScalableFont("SansSerif", Font.PLAIN, 12); + + /** Whether the font changes size with the enlargement. */ + boolean zoomfont + = true; + + /** Whether the font can get bigger than the default font. + * Ignored (or rather, doesn't have any effect) when zoomfont is false. + */ + boolean enlargefont + = true; + + /** The x and y margins + */ + int[] margins + = new int[] {2, 1}; + + /** Whether to produce BallCells instead? + */ + boolean ball + = false; + } + +/* + RasterCellFactory1(Component c) { + comp = c; + } +*/ + + protected Font fon(int scale) { return font.getFont(scale); } + protected FontMetrics fonmet(int scale) { + return font.getFontMetrics(scale); + } + protected int getScale(float fract) { return getScale(fract,false); } + protected int getScale(float fract,boolean real) { + if(!enlargefont && !real && fract>=1.0) return 1000; + return (int)(fract*1000); + } + + public Dimension getSize(ZZCell c, float fract) { + String str = widthstr; + if(c != null) str = c.getText(); + if(str == null) str = ""; + FontMetrics fm = fonmet(getScale(fract,true)); + if(ball) + return BallCell.getSize(fm, str, margins[0], margins[1]); + else + return CellFlob1.getSize(fm, str, margins[0], margins[1]); + } + + public Flob makeFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, + int x, int y, int d, int w, int h) { + int scale = getScale(fract); + Font f = fon(scale); + FontMetrics fm = fonmet(scale); + if(ball) { + BallCell cf = new BallCell(x, y, d, w, h, handleCell, c, + c.getText(), f, fm, into); + cf.xoffs = margins[0]; + cf.yoffs = margins[1]; + addSolidColors(into, cf, cf); + into.add(cf); + return cf; + } else { + CellFlob1 cf = new CellFlob1(x, y, d, w, h, handleCell, c, + c.getText(), f, fm); + cf.bg = bg; + cf.xoffs = margins[0]; + cf.yoffs = margins[1]; + addSolidColors(into, cf, cf); + into.add(cf); + return cf; + } + } + public Flob placeFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, + int x, int y, int depth, + float xfract, float yfract) { + Dimension d = getSize(c, fract); + return makeFlob(into, c, handleCell, fract, + (int)(x-xfract*d.width), + (int)(y-yfract*d.height), + depth, d.width, d.height); + } + + public Flob centerFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, Point p, int xalign, int yalign, + int depth, Dimension d) { + if(d == null) d = getSize(c, fract); + int x, y; + if(ball) { + x = p.x - d.height/2; y = p.y - d.height/2; + } else { + x = p.x - d.width/2; y = p.y - d.height/2; + } + if(xalign < 0) x = p.x; + if(xalign > 0) x = p.x - d.width; + if(yalign < 0) y = p.y; + if(yalign > 0) y = p.y - d.height; + p("centerFlob "+p+" "+d+" at "+x+" "+y+" align "+xalign+" "+yalign); + return makeFlob(into, c, handleCell, fract, x, y, + depth, d.width, d.height); + } + public Flob centerFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, Point p, int xalign, int yalign, int depth) { + return centerFlob(into, c, handleCell, fract, p, xalign, yalign, + depth, null); + } + + /** A routine to add solid background colors according to scheme 1. + * No better place to put it right now, but this routine can be + * called from anywhere to color the background of a cellbgflob + * as requested. + * Also adds line cursors, if any. + */ + static public void addSolidColors(FlobSet into, Flob f, Colorer col) { + // Special case check: Is this a cursor or a cursor's clone? + ZZCell orig = f.c.h("d.clone", -1); + if(orig.h("d.cursor-list", -1).s("d.cursor", -1) + != null) { + col.addColor(ZZCursorReal.getColorOrWhite(orig)); + return; // XXX should draw line cursors! + } + + Enumeration e = ZZCursorReal.getPointers(f.c); + while(e.hasMoreElements()) { + ZZCell cu = (ZZCell)e.nextElement(); + Color color = ZZCursorReal.getColor(cu); + if(color != null) if(col.addColor(color)) return; + if(!(f instanceof CellFlob1)) continue; + int offs = ZZCursorReal.getOffs(cu); + if(offs == ZZCursor.NO_OFFSET) continue; + int x = ((CellFlob1)f).getStrX(offs); + into.add(new LineDecor(x, f.y, x, f.y+f.h, + Color.black, f.d)); + } + + // XXX Does not check whose mark it is - should! + if(f.c.s("d.mark-set", 1)!=null) + if(col.addColor(Color.red)) return; + + if(f.c.s("d.clone", -1) != null) + if(col.addColor(Color.yellow)) return; + else if(f.c.s("d.clone", 1) != null) + if(col.addColor(new Color(255, 255, 192))) return; + + } + +} + + +// vim: set syntax=java : diff --git a/Java/flob/CellFlobFactory2.zob b/Java/flob/CellFlobFactory2.zob new file mode 100644 index 0000000..7c6fd82 --- /dev/null +++ b/Java/flob/CellFlobFactory2.zob @@ -0,0 +1,207 @@ +/* +RasterFactory2.zob + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka, multiline by Benjamin Fallenstein + */ + +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** A simple cell factory that gives the cells as one-line strings. + * Variable length is possible. + * XXX This class is a bad copy of RasterCellFactory 1. + * Inheritance should be rather used, but doesn't work yet with ZObs. + */ + +public class CellFlobFactory2 implements FlobFactory, ZOb { +public static final String rcsid = "$Id$"; + public static boolean dbg = false; + private static final void p(String s) { if(dbg) System.out.println(s); } + private static final void pa(String s) { System.out.println(s); } + + STRUCTPARAMS { + + /** The string to use to get the default cell width. */ + String widthstr + = "0000000000"; + + /** The default background color. + * XXX Currently, because of color mixing, the foreground + * comes from FlobSet. This should maybe change - check later. + */ + Color bg + = Color.white; + + /** The font for the default enlargement. */ + ScalableFont font + = new ScalableFont("SansSerif", Font.PLAIN, 12); + + /** Whether the font changes size with the enlargement. */ + boolean zoomfont + = true; + + /** Whether the font can get bigger than the default font. + * Ignored (or rather, doesn't have any effect) when zoomfont is false. + */ + boolean enlargefont + = true; + + /** The x and y margins + */ + int[] margins + = new int[] {3, 2}; + + ZOb ftextlayouter + = new FTextLayouter(); + + } + + protected Font fon(int scale) { return font.getFont(scale); } + protected FontMetrics fonmet(int scale) { + return font.getFontMetrics(scale); + } + protected int getScale(float fract) { return getScale(fract, false); } + protected int getScale(float fract, boolean real) { + if(!enlargefont && !real && fract>=1.0) return 1000; + return (int)(fract*1000); + } + + public Dimension getSize(ZZCell c, float fract) { + String str = widthstr; + if(c != null) str = c.getText(); + if(str == null) str = ""; + FontMetrics fm = fonmet(getScale(fract, true)); + return CellFlob1.getSize(fm, str, margins[0]*2, margins[1]*2); + } + + public Flob makeFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, int x, int y, int d, int w, int h) { + int scale = getScale(fract); + Font f = fon(scale); + FontMetrics fm = fonmet(scale); + CellBgFlob cf = new CellBgFlob(x, y, d, w, h, c); + Point p = cf.getPoint(1, 1); + p = cf.getPoint(-1, -1); + cf.bg = bg; + int xm = margins[0], ym = margins[1]; + addSolidColors(into, cf); + + FText ftxt = new FText(new FText.Part[] { + new FText.CellPart(c, 0, -1, f, fm, null, null) + }); + Rectangle rect = new Rectangle(x+xm, y+ym, w-xm-xm, h-ym-ym); + +// XXX -- make this work! (shall place cursor in middle if text too long) +// int offs = -1; +// for(Enumeration e=ZZCursorReal.getPointers(c); e.hasMoreElements();) { +// int offs0 = ZZCursorReal.getOffs((ZZCell)e.nextElement()); +// if(offs0 != ZZCursorReal.NO_OFFSET) { offs = offs0; break; } +// } + + FTextLayouter ftl = (FTextLayouter)ftextlayouter; + ftl.firstCap = false; +// if(offs < 0) + ftl.place(into, ftxt, rect, d, 1, rect.y+1, 0, true, cf); +// else +// ftl.place(into, ftxt, rect, d, 0, +// rect.y+rect.height/2-fm.getHeight()/2, offs, true, cf); + + into.add(cf); + return cf; + } + public Flob placeFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, + int x, int y, int depth, + float xfract, float yfract) { + Dimension d = getSize(c, fract); + return makeFlob(into, c, handleCell, fract, + (int)(x-xfract*d.width), + (int)(y-yfract*d.height), + depth, d.width, d.height); + + } + + public Flob centerFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, Point p, int xalign, int yalign, + int depth, Dimension d) { + if(d == null) d = getSize(c, fract); + int x, y; + x = p.x - d.width/2; y = p.y - d.height/2; + if(xalign < 0) x = p.x - d.width; + if(xalign > 0) x = p.x; + if(yalign < 0) y = p.y - d.height; + if(yalign > 0) y = p.y; + return makeFlob(into, c, handleCell, fract, x, y, + depth, d.width, d.height); + } + public Flob centerFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, Point p, int xalign, int yalign, int depth) { + return centerFlob(into, c, handleCell, fract, p, xalign, yalign, + depth, null); + } + + /** A routine to add solid background colors according to scheme 1. + * No better place to put it right now, but this routine can be + * called from anywhere to color the background of a cellbgflob + * as requested. + * Also adds line cursors, if any. + */ + static public void addSolidColors(FlobSet into, CellBgFlob f) { + // Special case check: Is this a cursor or a cursor's clone? + ZZCell orig = f.c.h("d.clone", -1); + if(orig.h("d.cursor-list", -1).s("d.cursor", -1) + != null) { + f.addColor(ZZCursorReal.getColorOrWhite(orig)); + return; // XXX should draw line cursors! + } + + ZZCell cu = f.c.s("d.cursor", 1); + + while(cu != null) { + Color color = ZZCursorReal.getColor(cu); + if(color != null) f.addColor(color); +// String txt = cu.getText(); +// if(txt != null && !txt.equals("") && f instanceof CellBgFlob) { +// try { +// int ind = Integer.parseInt(txt); +// int x = ((CellBgFlob)f).getStrX(ind); +// into.add(new LineDecor(x, f.y, x, f.y+f.h, +// Color.black, f.d)); +// } catch(NumberFormatException e) { +// } +// } + cu = cu.s("d.cursor-list", 1); + } + // XXX Does not check whose mark it is - should! + if(f.c.s("d.mark-set", 1)!=null) + f.addColor(Color.red); + + if(f.c.s("d.clone", -1) != null) + f.addColor(Color.yellow); + else if(f.c.s("d.clone", 1) != null) + f.addColor(new Color(255, 255, 192)); + + } + +} + + +// vim: set syntax=java : diff --git a/Java/flob/Colorer.java b/Java/flob/Colorer.java new file mode 100644 index 0000000..166447d --- /dev/null +++ b/Java/flob/Colorer.java @@ -0,0 +1,41 @@ +/* +Colorer.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.awt.*; + +/** An interface for coloring cell background -like things. + * The information about how many colors are appropriate should + * move separately from this. + */ + +public interface Colorer { +String rcsid = "$Id: Colorer.java,v 1.1 2000/10/26 18:15:05 tjl Exp $"; + /** Add the given color to the set of colors to be shown in the background, + * or whatever. + * It is assumed that the colors come more significant first, so that + * Colorers are free to take any number of the first ones and ignore + * the rest. + * @return Whether the rest of the colors will be ignored. + */ + boolean addColor(Color c); +} diff --git a/Java/flob/CombinedView.zob b/Java/flob/CombinedView.zob new file mode 100644 index 0000000..fe40934 --- /dev/null +++ b/Java/flob/CombinedView.zob @@ -0,0 +1,58 @@ +/* +CombinedView.zob + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ + +package org.gzigzag; +import java.awt.*; + +/** A view that shows all views of the accursed cell next to each other. + */ + +public class CombinedView implements FlobView, ZOb { +public static final String rcsid = "$Id: CombinedView.zob,v 1.6 2000/12/31 15:15:50 bfallenstein Exp $"; + /** Should we print out debugging info? */ + public static boolean dbg = false; + static final void p(String s) { if(dbg) pa(s); } + static final void pa(String s) { System.out.println(s); } + + STRUCTPARAMS {} + + public void raster(FlobSet into, FlobFactory fact, + ZZCell win, String[] dims, ZZCell accursed) { + ZZCell[] apps = ApplitudeMgr.getApplitudes(accursed); + if(apps.length == 0) + apps = new ZZCell[] { ApplitudeMgr.getFallback(win.getSpace()) }; + int n = apps.length; + + ZZCell pref = ApplitudeMgr.getWindowApp(win); + Dimension size = new Dimension(into.getSize()); + if(pref != null) + fact.centerFlob(into, pref, pref, (float)1.5, + new Point(size.width, size.height), 1, 1, 1); + size.width = size.width / n; + + for(int i=0; i-" + + conns[i].c2.getID());*/ + + Vector dims = new Vector(); // Dims to be drawn + Vector pos = new Vector(); // Cells to positive directions to be drawn + Vector neg = new Vector(); // Cells to negative directions to be drawn + + ZZCell dim, pc, nc; + dim=stdim; + do { // Go through the DimList starting from the x-axis dimension + String cdim = dim.getText(); + p("Found dim: "+cdim); + pc = accursed.s(cdim, 1); + nc = accursed.s(cdim, -1); + if(nc != null || pc != null) { + dims.addElement(cdim); + pos.addElement(pc); + neg.addElement(nc); + } + dim = dim.s("d.2", 1); + } while(dim != stdim); // Do until loop closes + + int numdirs = pos.size()+neg.size(); // Number of cells and thus sectors + if(numdirs == 0) + return; // No cells to draw + double angle = 2 * Math.PI / (numdirs); + int l = (int) ((d.height < d.width ? d.height : d.width) / 2 * 0.5); + + fact.makeFlob(into, accursed, accursed, 1, + (d.width-cw) / 2, (d.height-ch) / 2, 1, cw, ch); + + int i = 0; + LineDecor.Builder nldb = new LineDecor.Builder(into, Color.black); + LineDecor.Builder pldb = new LineDecor.Builder(into, Color.red); + nldb.startl(numdirs/2*4, 12); + pldb.startl(numdirs/2*4, 12); + + double a = (double)-2/3*Math.PI; // Begin placing positive cells top left + while (i < numdirs/2) { + int dx = x(a, l); + int dy = y(a, l); + + if(pos.elementAt(i)!=null) { + fact.makeFlob(into, (ZZCell)pos.elementAt(i), (ZZCell)pos.elementAt(i), + (float) 0.7, + midx + dx-cw/2, midy + dy-ch/2, + 1, cw, ch); + pldb.l(midx, midy, midx + dx, midy + dy); + into.add(new TextDecor( + midx+dx+cw/2-dfm.stringWidth("+"+(String)dims.elementAt(i)), + midy+dy-ch/2, "+"+(String)dims.elementAt(i), Color.red, dfont)); + } + if(neg.elementAt(i)!=null) { + fact.makeFlob(into, (ZZCell)neg.elementAt(i), (ZZCell)neg.elementAt(i), + (float) 0.7, + midx -dx -cw/2, midy -dy -ch/2, + 1, cw, ch); + nldb.l(midx, midy, midx -dx, midy -dy); + into.add(new TextDecor( + midx-dx-cw/2, midy-dy+ch/2+dfonth, + "-"+(String)dims.elementAt(i), Color.black, dfont)); + } + + i++; + a += angle; // Rotate clockwise + } + nldb.endl(); + pldb.endl(); + } + + protected int x(double angle, int length) { + return (int) (Math.cos(angle) * length); + } + + protected int y(double angle, int length) { + return (int) (Math.sin(angle) * length); + } +} + +// vim: set syntax=java : diff --git a/Java/flob/ConnectionLineDecor.java b/Java/flob/ConnectionLineDecor.java new file mode 100644 index 0000000..a1ac9f5 --- /dev/null +++ b/Java/flob/ConnectionLineDecor.java @@ -0,0 +1,174 @@ +/* +ConnectionLineDecor.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +/** A decoration of lines connecting flobs to each other. + * Interpolation is done by this class. The coordinates are + * given as points inside the flob's rectangle. + */ + +public class ConnectionLineDecor extends Flob { +public static final String rcsid = "$Id: ConnectionLineDecor.java,v 1.5 2000/09/19 10:31:59 ajk Exp $"; + public static final boolean dbg = true; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + /** A class that incrementally builds these. + */ + static public class Builder { + FlobSet into; + int curp; int np; + Flob[] flobs; + int[] p; + Color col; + int d; + public Builder(FlobSet into, Color col) { + this.into = into; + this.col = col; + } + public final void startl(int n, int d) { + if(curp != 0) endl(); + this.d = d; + curp = 0; + np = n; + p = null; + flobs = null; + } + public final void l(Flob f0, int x0, int y0, Flob f1, int x1, int y1) { + if(p==null) { + p = new int[np * 4]; + flobs = new Flob[np * 2]; + } else if(curp >= np) { + endl(); + p = new int[np * 4]; + flobs = new Flob[np * 2]; + curp = 0; + } + flobs[curp*2 + 0] = f0; + flobs[curp*2 + 1] = f1; + p[curp*4 + 0] = x0; + p[curp*4 + 1] = y0; + p[curp*4 + 2] = x1; + p[curp*4 + 3] = y1; + curp ++; + } + public void endl() { + if(p==null) return; + into.add(new ConnectionLineDecor(flobs, p, curp, col, d)); + p = null; flobs = null; curp = 0; + } + } + + Color color; + int n; + Flob[] flobs; + int[] coords; // 256th parts + + public ConnectionLineDecor(Flob[] flobs, int[] coords, int n, int d) { + this(flobs, coords, n, null, d); + } + + /** Usual constructor. + * @param coords The coordinates for the lines, given as + * quadruplets x1, y1, x2, y2. + */ + public ConnectionLineDecor(Flob[] flobs, int[] coords, int n, Color color, int d) { + // XXX Is size 0x0 right? + super(0, 0, d, 0, 0, null); + this.flobs = flobs; + this.coords = coords; + this.n = n; + this.color = color; + } + + public void render(Graphics g) { + Color old = null; + if(color != null) { + old = g.getColor(); + g.setColor(color); + } + g.setColor(Color.black); + p("Drawing flobconns"); + + for(int i=0; i p.length) + endl(); + if(p==null) + alloc(); + } + /** Allocate the arrays. */ + protected void alloc() { + p = new int[np]; + curp = 0; + nth = 0; + } + public void endl() { + if(p==null) return; + into.add(create()); + p = null; curp = 0; + } + abstract protected Renderable create(); + + } + + public CoordDecor(int[] coords, int n, int d) { + this.coords = coords; + this.n = n; + this.d = d; + if(coords != null && coords.length < n) + throw new Error("CoordDecor: less length than n!!!"); + } + + abstract public void render(Graphics g); + + public boolean translate(int x, int y) { + for(int i=0; i maxdepth) return; + + if (drawn.containsKey(centercell)) return; + + Vector pointers = new Vector(); + + { + Dimension s = fact.getSize(null, 1); + int width = (int) (s.width * sfactor); + int height = (int) (s.height * sfactor); + int x = centerpoint.x - width / 2; + int y = centerpoint.y - height / 2; + p("radius = " + radius + ", x = " + x + ", y = " + + y + ", width = " + width + ", height = " + + height + ", centercell = " + centercell); + Flob fl = fact.makeFlob(into, centercell, centercell, 1, + x, y, level, width, height); + drawn.put(centercell, centercell); + } + + for (Enumeration e = ZZCursorReal.getPointers(centercell); + e.hasMoreElements();) { + ZZCell c = (ZZCell) e.nextElement(); + pointers.addElement(c); + p("Found cursor " + c); + } + + int n = pointers.size(); + p("n = " + n); + + if (n == 0) return; + + int prad = (int) (pointerradius * radius); + + double baseangle = Math.PI / (n + 1); + + int newradius; + { + double a = prad - prad * Math.cos(baseangle); + double b = prad * Math.sin(baseangle); + newradius = (int) Math.sqrt(a * a + b * b); + p("a = " + a + ", b = " + b + ", newradius = " + newradius); + } + + for (int i = 0; i < n; i++) { + ZZCell c = (ZZCell) pointers.elementAt(i); + if (ZZCursorReal.get(c) != centercell) pa("WRONG CURSOR CELL FOUND!!!"); + double angle = (i + 1) * baseangle; + p("angle = " + angle + " rad, " + angle * 180 / Math.PI + " deg"); + int x = (int)(centerpoint.x + prad * Math.cos(angle)); + int y = (int)(centerpoint.y + prad * Math.sin(angle)); + drawPointerCells(into, fact, c, new Point(x, y), newradius, + level + 1, sfactor * sizefactor); + } + + + + } + + public void raster(final FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed) { + ZZCell c = accursed; + Point pt = new Point(into.getSize().width / 2, + into.getSize().width / 2); + ZZCell ccand = ZZCursorReal.get(c); + if (ccand != null) { + c = ccand; + pt.y /= 2; + } + drawn = new Hashtable(); + drawPointerCells(into, fact, c, pt, + into.getSize().width, initdepth, 1); + + // Draw the cursor arrows + into.iterDepth(new FlobSet.DepthIter() { + public void act(Flob[] flobs, int start, int n) { + for(int i = start; i < start+n; i++) { + ZZCell pointer = flobs[i].c; + if (pointer == null) continue; + ZZCell pointee = ZZCursorReal.get(pointer); + if (pointee == null) continue; + p("pointer = " + pointer + ", pointee = " + pointee); + Flob from = flobs[i]; + Flob[] tos = into.findFlobs(null, pointee); + for (int j = 0; j < tos.length; j++) { + Flob to = (Flob) tos[j]; + int[] cs = new int[16]; + // we make the arrow body in two parts: + // one from head to arrow point and one + // from arrow point to tail + cs[0] = from.x + from.w / 2; + cs[1] = from.y; + cs[2] = to.x + to.w / 2; + cs[3] = to.y + to.h; + double or1 = (cs[0] + cs[2]) / 2; + double or2 = (cs[1] + cs[3]) / 2; + cs[6] = cs[2]; + cs[7] = cs[3]; + cs[2] = (int) (or1 + 0.5); + cs[3] = (int) (or2 + 0.5); + cs[4] = cs[2]; + cs[5] = cs[3]; + double v1 = cs[0] - cs[2]; + double v2 = cs[1] - cs[3]; + double vlen = Math.sqrt(v1*v1 + v2*v2); + v1 = v1 / vlen; + v2 = v2 / vlen; + cs[8] = (int) (or1 + 0.5); + cs[9] = (int) (or2 + 0.5); + cs[10] = (int) (v1 * a00 + v2 * a01 + or1 + 0.5); + cs[11] = (int) (v1 * a10 + v2 * a11 + or2 + 0.5); + cs[12] = (int) (or1 + 0.5); + cs[13] = (int) (or2 + 0.5); + cs[14] = (int) (v1 * b00 + v2 * b01 + or1 + 0.5); + cs[15] = (int) (v1 * b10 + v2 * b11 + or2 + 0.5); + into.add(new LineDecor(cs, cs.length, + linecolor, + (from.d + to.d) / 2)); + } + + } + } + }, true); + + + } + + +} + + + diff --git a/Java/flob/FTextCellView.zob b/Java/flob/FTextCellView.zob new file mode 100644 index 0000000..8db134f --- /dev/null +++ b/Java/flob/FTextCellView.zob @@ -0,0 +1,179 @@ +/* +FTextCellView.zob + * + * Copyright (c) 2001, Benja Fallenstein + * Copyright (c) 2000-2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benja Fallenstein + */ + +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** A cell view showing some FText. + * This class exists in order to make it easy to create cell views which + * just take an FText for a cell somehow and then render it on the screen. + * Subclasses have to implement getFText(ZZCell, int). Default: render the + * cell's content in the specified string. + *

    + * XXX Don't use scene flobs. Instead, just place the split cell flobs in the + * higher level flob set and create a BoxedFlob 'round them. + */ + +public class FTextCellView implements FlobFactory, ZOb { +public static final String rcsid = "$Id: FTextCellView.zob,v 1.4 2001/04/02 20:20:54 bfallenstein Exp $"; + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + // WHAT SUBCLASSES NEED TO OVERRIDE + + /** Get the FText for this cell at the given scale. + * scale == fract * 1000. + */ + protected FText getFText(ZZCell c, int scale) { + return new FText(new FText.Part[] { + new FText.CellPart(c, 0, -1, f(scale), fm(scale), null, null) + }); + } + + + + // IMPLEMENTATION + + /** Get the font for a given scale. */ + protected final Font f(int sc) { return font.getFont(sc); } + + /** Get the font metrics for a given scale. */ + protected final FontMetrics fm(int sc) { return font.getFontMetrics(sc); } + + STRUCTPARAMS { + /** The string to use to get the default cell width. */ + String widthstr + = "0000000000"; + + /** The default background color. + * XXX Currently, because of color mixing, the foreground + * comes from FlobSet. This should maybe change - check later. + */ + Color bg + = Color.white; + + /** The font for the default enlargement. */ + ScalableFont font + = new ScalableFont("SansSerif", Font.PLAIN, 12); + + ZOb ftextlayouter + = new FTextLayouter(false); + + /** The x and y margins + */ + int[] margins + = new int[] {2, 1}; + } + + protected int getScale(float fract) { + return (int)(fract*1000); + } + + public Dimension getSize(ZZCell c, float fract) { + if(c != null) { + FText ftxt = getFText(c.getRootclone(), getScale(fract)); + return new Dimension(FText.Part.width(ftxt.parts) + margins[0]*2, + FText.Part.height(ftxt.parts) + margins[1]*2); + } else { + String str = widthstr; + if(str == null) str = ""; + FontMetrics fm = fm(getScale(fract)); + return CellFlob1.getSize(fm, str, margins[0], margins[1]); + } + } + + public Flob getFlob(FlobSet into, ZZCell c, FText ftxt, + int x, int y, int d, int w, int h) { + int xm = margins[0], ym = margins[1]; + + BoxedFlob box = new BoxedFlob(x, y, d, w, h, c); + + CellFlobFactory1.addSolidColors(into, box, box); + + Rectangle rect = new Rectangle(x+xm, y+ym, w-xm, h-ym); + ((FTextLayouter)ftextlayouter).place(into, ftxt, rect, d, 1, y+ym, 0, + true, box); + + // Add the box last, so that it is shown under the text. + into.add(box); + return box; + } + + public Flob makeFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, int x, int y, int d, int w, int h) { + FText ftxt = getFText(c.getRootclone(), getScale(fract)); + return getFlob(into, c, ftxt, x, y, d, w, h); + } + + public Flob placeFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, + int x, int y, int depth, + float xfract, float yfract) { + FText ftxt = getFText(c.getRootclone(), getScale(fract)); + int w = FText.Part.width(ftxt.parts) + margins[0]*2; + int h = FText.Part.height(ftxt.parts) + margins[1]*2; + return getFlob(into, c, ftxt, + (int)(x-xfract*w), + (int)(y-yfract*h), + depth, w, h); + } + + public Flob centerFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, Point p, int xalign, int yalign, + int depth, Dimension d) { + if(d == null) return centerFlob(into, c, handleCell, fract, p, xalign, + yalign, depth); + int x, y; + x = p.x - d.width/2; y = p.y - d.height/2; + + if(xalign < 0) x = p.x; + if(xalign > 0) x = p.x - d.width; + if(yalign < 0) y = p.y; + if(yalign > 0) y = p.y - d.height; + p("centerFlob "+p+" "+d+" at "+x+" "+y+" align "+xalign+" "+yalign); + return makeFlob(into, c, handleCell, fract, x, y, + depth, d.width, d.height); + } + public Flob centerFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, Point p, int xalign, int yalign, int depth) { + int x, y; + + FText ftxt = getFText(c.getRootclone(), getScale(fract)); + int w = FText.Part.width(ftxt.parts) + margins[0]*2; + int h = FText.Part.height(ftxt.parts) + margins[1]*2; + + x = p.x - w/2; y = p.y - h/2; + if(xalign < 0) x = p.x; + if(xalign > 0) x = p.x - w; + if(yalign < 0) y = p.y; + if(yalign > 0) y = p.y - h; + p("centerFlob "+p+" at "+x+" "+y+" "+w+" "+h+" align "+xalign+" "+yalign); + + return getFlob(into, c, ftxt, x, y, depth, w, h); + } +} + +// vim: set syntax=java : diff --git a/Java/flob/FTextLayouter.zob b/Java/flob/FTextLayouter.zob new file mode 100644 index 0000000..f19d335 --- /dev/null +++ b/Java/flob/FTextLayouter.zob @@ -0,0 +1,253 @@ +/* +FTextLayouter.java + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ + +package org.gzigzag; +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +/** A layouter for flowing formatted text in a fixed-width rectangle. + * @see FText + */ + +public class FTextLayouter implements ZOb { +public static final String rcsid = "$Id: FTextLayouter.zob,v 1.10 2001/03/30 16:19:37 bfallenstein Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + public FTextLayouter() {} + public FTextLayouter(boolean firstCap) { this.firstCap = firstCap; } + + STRUCTPARAMS { + /** Capitalize any letter after two spaces. + * This allows simple rearrangement of text without having + * to think about capitalization at all times by ending + * each sentence with the period/question/... and two spaces. + * XXX Maybe this shouldn't be here after all - maybe + * separate FText.Part firstcap completely from rendering + * to a separate call?? + */ + boolean firstCap + = true; + + } + + /** (Internal convenience) Place a number of lines from an array, + * given first and last line. + */ + void placeLines(FlobSet into, + FText.Part[][] lines, + int[] heights, + Rectangle rect, + int first, + int last, + int depth, + boolean cursors, + Flob fparent) { + int y = rect.y, maxx = rect.x + rect.width; + p("FTextLayouter placeLines first "+first+" last "+last+" length "+lines.length); + + Renderable prev = null; + for(int linenr=first; linenr<=last; linenr++) { + FText.Part[] line = lines[linenr]; + int x = rect.x; + y += heights[linenr]; + + for(int partnr = 0; partnr rect.x + rect.width) { + p("FTL clip: "+f.x+" "+f.w+" in "+rect.x+" "+rect.width+" at "+f.c); + f.w = rect.x + rect.width - f.x; + if(f instanceof SplitCellFlob1) + ((SplitCellFlob1)f).doClip = true; + } + if(f.w < 0) f.w = 0; + } + into.add(prev); + } + + x += w; + if(x > maxx) break; + } + } + } + + /** (Internal convenience) Find the correct span of lines to layout. + * Returns an array with two ints: the last line number and the height. + */ + int[] layout(FText.Part[][] lines, + int[] heights, + int start, + int dir, + int maxh) { + int height = 0, i = start; + for(; i>=0 && i maxh) return new int[] { i-dir, height }; + height += lineh; + } + return new int[] { i-dir, height }; + } + + + public Rectangle place(FlobSet into, FText txt, Rectangle rect, + int direction, int initY, + int middleoffs, + boolean cursors) { + return place(into, txt, rect, 100, + direction, initY, middleoffs, cursors, (Flob)null); + } + + /** To be deprecated -- DON'T USE! */ + public Rectangle place(FlobSet into, FText txt, Rectangle rect, + int direction, int initY, + int middleoffs, + boolean cursors, + boolean[] beginningSentence) { + return place(into, txt, rect, 100, + direction, initY, middleoffs, cursors, (Flob)null); + } + + /** To be deprecated -- DON'T USE! */ + public Rectangle place(FlobSet into, FText txt, Rectangle rect, + int depth, + int direction, int initY, + int middleoffs, + boolean cursors, + boolean[] beginningSentence) { + return place(into, txt, rect, depth, + direction, initY, middleoffs, cursors, (Flob)null); + } + + public Rectangle place(FlobSet into, FText txt, Rectangle rect, + int depth, + int direction, int initY, + int middleoffs, + boolean cursors) { + return place(into, txt, rect, depth, + direction, initY, middleoffs, cursors, (Flob)null); + } + + /** Place a piece of formatted text into a fixed-width rectangle. + * @param into The flobset to place the text into. + * @param txt The formatted text object + * @param rect The rectangle to fit things into. This is used for + * both stopping rendering at the upper and lower edges + * and for the margin widths. + * (XXX How to i18nize this for other directions?!?!) + * @param depth The depth at which to place the flobs. + * @param direction The direction we're moving. + * 0 = starting from the middle of a paragraph, + * 1 = down, -1 = up + * @param initY The y coordinate to place the middle/first/last line + * of text at, depending on direction. + * @param middleoffs If direction==0, the offset that should be at initY. + * @param cursors Whether to draw cursors. + * @param fparent The flob parent. + */ + public Rectangle place(FlobSet into, FText txt, Rectangle rect, + int depth, + int direction, int initY, + int middleoffs, + boolean cursors, + Flob fparent) { + if(firstCap) txt.capitalize(); + FText.Part[][] lines = txt.getLines(rect.width); + if(lines.length == 0) + return new Rectangle(rect.x, initY, rect.width, 0); + + /** The height of each line. */ + int[] heights = new int[lines.length]; + + /** The first and last lines to place. */ + int first, last; + + Rectangle res; + + if(direction < 0) { + last = lines.length-1; + int[] lay = layout(lines, heights, last, -1, + initY-rect.y); + + + first = lay[0]; last = lines.length-1; + res = new Rectangle(rect.x, initY-lay[1], rect.width, lay[1]); + } else if(direction > 0) { + first = 0; + int[] lay = layout(lines, heights, first, 1, + rect.y + rect.height - initY); + last = lay[0]; + res = new Rectangle(rect.x, initY, rect.width, lay[1]); + } else { + int middle = FText.findLine(lines, middleoffs); + // Make it the middle of the middle line. + initY -= FText.Part.height(lines[middle])/2; + + int[] lay1 = layout(lines, heights, middle-1, -1, + rect.y + rect.height - initY); + int[] lay2 = layout(lines, heights, middle, 1, initY-rect.y); + + first = lay1[0]; last = lay2[0]; + res = new Rectangle(rect.x, initY-lay1[1], rect.width, + lay1[1]+lay2[1]); + } + + placeLines(into, lines, heights, res, first, last, depth, + cursors, fparent); + return res; + } + + // XXX make more efficient: do cursor search only for parent sf + public static void addCurs(FlobSet into, SplitCellFlob1 sf) { + + Enumeration e = ZZCursorReal.getPointers(sf.getCell()); + while(e.hasMoreElements()) { + ZZCell c = (ZZCell)e.nextElement(); + + int ind = ZZCursorReal.getOffs(c); + if(ind == ZZCursorReal.NO_OFFSET) continue; + if(!(ind >= sf.start && ind <= sf.start + sf.n)) + continue; + int x = sf.getStrX(ind); + if(x >= 0 && into != null) + into.add(new LineDecor(x, sf.y, x, sf.y+sf.h, + Color.black, sf.d)); + } + } +} + +// vim: set syntax=java : diff --git a/Java/flob/Flob.java b/Java/flob/Flob.java new file mode 100644 index 0000000..f45030e --- /dev/null +++ b/Java/flob/Flob.java @@ -0,0 +1,202 @@ +/* +Flob.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** An abstract class to represent a flob shown on screen. + * Flobs are constant read-only objects like Strings. + *

    + * Flobs should be able to render themselves quickly for animations; + * caching relevant + * information in this structure is therefore a good idea. + *

    + * The minimal flob implementation simply implements the + * render(Graphics, int, int, int, int, int) method. + */ + +public abstract class Flob extends Renderable { +public static final String rcsid = "$Id: Flob.java,v 1.18 2001/03/17 23:08:23 bfallenstein Exp $"; + public int x, y, w, h; + + /** The identifier of the place this flob is. + * This is used to create a possibly hierarchical + * system so that animation doesn't confuse two + * instances of the same cell. + * deprecated Use setParent() / getParent(). + */ + public String flobPath = ""; + + /** The cell associated with this flob. + * This may be set to null for things that are - well - just + * things rendered. But those should be in a minority always. + */ + public ZZCell c; + + /** The flob we are interpolating with. + * Storing it here is a pure speed hack: in reality it'd belong in + * a hashtable somewhere. But this is crucial for the frame rate. + */ + protected Flob interpTo; + + /** The parent of this flob. + * Only flobs with no parents and flobs whose parents are interpolated + * to each other are interpolated to each other. + *

    + * set/get by setParent() / getParent() + */ + private Flob flobparent = null; + + /** The applitude that has placed this flob. + * When the views of different applitudes are combined, this field is set + * by the combining view. When a flob is clicked upon, the field is read, + * the applitude is made the window's prefered applitude, and the mouse + * binding is executed according to the bindings of that applitude. + */ + public ZZCell applitude = null; + + public void setParent(Flob p) { + flobparent = p; + flobPath = p.flobPath + "-" + p; + } + + public Flob getParent() { return flobparent; } + + /** Return true if a box should be drawn around this flob. + */ + public boolean needsBox() { return false; } + + public Flob(int x, int y, int d, int w, int h, ZZCell c) { + this.x = x; + this.y = y; + this.w = w; + this.h = h; + this.d = d; + this.c = c; + } + + /** Get a point aligned in a cell. + * getPoint(-1, 0) --> left/middle + * getPoint(1, 1) --> right/lower + * etc. -- middle means visual center (getCenter()). + */ + public Point getPoint(Point p, int xa, int ya) { + getCenter(p); + if(xa < 0) p.x = x; + if(xa > 0) p.x = x+w; + if(ya < 0) p.y = y; + if(ya > 0) p.y = y+h; + return p; + } + public Point getPoint(int xo, int yo) { + return getPoint(new Point(), xo, yo); + } + + /** Get the visual center of this flob. + */ + public Point getCenter(Point p) { + p.x = x+w/2; p.y = y+h/2; + return p; + } + + /** Get the visual center of this flob. + */ + public Point getCenter() { + return getCenter(new Point()); + } + + /** Render this flob at the given coordinates. + * Default: render nothing. + * You may override either this function or one or both of + * render(Graphics) and renderInterp(Graphics, float). + */ + public void render(Graphics g, int mx, int my, int md, + int mw, int mh) { + } + + /** Render this flob. + * May be overridden; default implementation uses render(g, x, y, w, h, d); + */ + public void render(Graphics g) { + render(g, x, y, d, w, h); + } + /** Render an interpolated version of this flob. + * Default implementation uses render(g, x, y, w, h, d) with linearly + * interpolated coordinates. + */ + public void renderInterp(Graphics g, float fract) { + Flob r = interpTo; + if(r==null) return; + render(g, + (int)(x + fract*(r.x-x)), + (int)(y + fract*(r.y-y)), + (int)(d + fract*(r.d-d)), + (int)(w + fract*(r.w-w)), + (int)(h + fract*(r.h-h)) + ); + } + + /** If there is a XOR-cursor associated with this flob, + * render it. + * This can be made to e.g. follow the mouse cursor to + * show where the click would land. + * Default implementation: do nothing, return + *

     hit(x,y)!=null 
    + * @return Whether the coordinates hit this flob, i.e. + * whether the system should stop looking for the + * XOR curser. + */ + public boolean renderXOR(Graphics g, int x, int y) { + return hit(x,y) != null; + } + + /** Whether it would make visually sense to interpolate + * this flob. + * Default implementation: whether the sum of the squares of + * the differences of the coordinates and widths is more than 100. + * Not a terribly useful measure but good enough. + */ + public boolean isInterpUseful() { + Flob r = interpTo; + if(r==null) return false; + return (r.x - x) * (r.x - x) + + (r.y - y) * (r.y - y) + + (r.w - w) * (r.w - w) + + (r.h - h) * (r.h - h) > 100; + } + + + /** Returns an object telling what was hit. + * Default implementation: returns null. + */ + public Object hit(int x, int y) { return null; } + + /** A convenience routine to check whether a point + * is inside the defining rectangle. + * If the flob is (as many are) rectangular, this routine can + * be used to check the hit. + */ + public final boolean insideRect(int x0, int y0) { + return x0 >= x && y0 >= y && x0 < x+w && y0 < y+h; + } +} diff --git a/Java/flob/FlobDecorator.java b/Java/flob/FlobDecorator.java new file mode 100644 index 0000000..9533d6a --- /dev/null +++ b/Java/flob/FlobDecorator.java @@ -0,0 +1,39 @@ +/* +FlobDecorator.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +/** An interface for classes that decorate FlobSets by drawing connections + * or so. + */ + +public interface FlobDecorator { +String rcsid = "$Id: FlobDecorator.java,v 1.6 2000/10/26 18:09:29 tjl Exp $"; + /** Add Renderables or Flobs to the given flobset, + * based on the flobs already in there. + */ + void decorate(FlobSet f, String path, ZZCell view); +} diff --git a/Java/flob/FlobFactory.java b/Java/flob/FlobFactory.java new file mode 100644 index 0000000..c77f1db --- /dev/null +++ b/Java/flob/FlobFactory.java @@ -0,0 +1,89 @@ +/* +RasterFlobFactory.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** An interface to generate flobs to put in a raster. + * This is for abstracting out what the cells look like. + * The "CellViews" in ZZDefaultSpace corresponds to classes + * implementing this interface. + */ + +public interface FlobFactory { +String rcsid = "$Id$"; + /** Get the default dimensions for the given cell and fraction. + * @param c The cell. If null, the default dimensions overall are returned. + * @param fract The magnification fraction. + */ + Dimension getSize(ZZCell c, float fract); + + /** Create a 2-D flob. + * This call creates the flob and places it into the given FlobSet. + * @param c The cell for the flob + * @param handleCell The cell from which to show e.g. cursor. + * This mechanism may change. + */ + Flob makeFlob(FlobSet f, + ZZCell c, ZZCell handleCell, + float fract, int x, int y, int d, int w, int h); + + /** Place a flob. + * Here, the size can vary freely: the flob is placed so that + * the point (x,y) is at (xfract, yfract) in the unit coordinate + * system stretched to fit inside. E.g. if (xfract, yfract)==(0,1) + * then (x,y) will be the lower left corner. + * The reason for this call is that it may be almost twice as fast + * as doing getSize() and makeFlob() since both may have to do some + * of the same calculations (e.g. line breaking). + *

    + * This call should give the same results as + *

    +     *		Dimension d = getSize(c, fract);
    +     *		return makeFlob(c, fract, 
    +     *			(int)(x-xfract*d.width),
    +     *			(int)(y-yfract*d.height),
    +     *			depth, d.width, d.height);
    +     * 
    + */ + Flob placeFlob(FlobSet f, + ZZCell c, ZZCell handleCell, + float fract, + int x, int y, int depth, + float xfract, float yfract); + + + // should call centerFlob(..., null) + Flob centerFlob(FlobSet f, + ZZCell c, ZZCell handleCell, + float fract, Point p, int xalign, int yalign, + int depth); + + // if d==null, use what getSize would return + Flob centerFlob(FlobSet f, + ZZCell c, ZZCell handleCell, + float fract, Point p, int xalign, int yalign, + int depth, Dimension d); +} + + diff --git a/Java/flob/FlobSet.java b/Java/flob/FlobSet.java new file mode 100644 index 0000000..806e45e --- /dev/null +++ b/Java/flob/FlobSet.java @@ -0,0 +1,521 @@ +/* +FlobSet.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** A set of flobs, i.e.things that are rendered to screen associated + * with cells. + * Flobs are stored with depths, which are stably sorted in the end + * so that the flobs placed later are on top. + */ + +public class FlobSet implements ZZScene { +public static final String rcsid = "$Id: FlobSet.java,v 1.41.2.1 2002/03/07 21:02:41 bfallenstein Exp $"; + + public static final boolean dbg = true; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + Dimension size; + public Dimension getSize() { + return size; + } + Color fg, bg; + Component cpt; + + public SceneFlob sflob = null; + public BoxType box = new SimpleBoxType(); + + public FlobSet(Dimension size, Color foreground, Color background, + Component cpt) { + this.size = size; + this.bg = background; + this.fg = foreground; + this.cpt = cpt; + } + public Component getComponent() { return cpt; } + public Color getForeground() { return fg; } + public Color getBackground() { return bg; } + + + private Hashtable c2ph; + private Hashtable nph; // Hashtable for flobs w/o parents + + private final Hashtable getPH(Flob parent) { + if(parent == null) + return nph; + Hashtable res = (Hashtable)c2ph.get(parent); + if(res == null) + c2ph.put(parent, res=new Hashtable()); + return res; + } + + private int nflobs; + private Flob[] flobs = new Flob[30]; + boolean fsorted = false; + boolean ftagged = false; + + + private int nrend; + /** Decorations. + */ + private Renderable[] rends = new Renderable[10]; + boolean rsorted = false; + + private int maxdepth = 0; + + public void add(Renderable r) { + // Check: if it happens to be a flob, then put + // it as a flob. + if(r instanceof Flob) { + add((Flob)r); + return; + } + + if(r.d > maxdepth) maxdepth = r.d; + if(nrend >= rends.length) { + Renderable[] n = new Renderable[nrend + 50]; + System.arraycopy(rends, 0, n, 0, nrend); + rends = n; + } + rends[nrend++] = r; + rsorted = false; + } + + /** Add a flob into the flobset. + * Note that flobPath might not be set yet. + * It is therefore used only when the flobs are being sorted. + */ + public void add(Flob f) { + // p("AddFlob "+f.x+" "+f.y+" "+f.w+" "+f.h+" "+f.d); + if(f.d <= 0) + throw new ZZError("Negative or zero depth for flob!"); + if(f.d > maxdepth) maxdepth = f.d; + // if(f.c != null) + // getPH(f.flobPath).put(f.c, f); + if(nflobs >= flobs.length) { + Flob[] n = new Flob[nflobs + 100]; + System.arraycopy(flobs, 0, n, 0, nflobs); + flobs = n; + } + flobs[nflobs++] = f; + fsorted = false; + ftagged = false; + if(sflob != null && f instanceof SceneFlob) + ((SceneFlob)f).parent = sflob; + } + + public final void tag() { + if(ftagged) return; + c2ph = new Hashtable(); nph = new Hashtable(); + for(int i=0; i maxdepth) + throw new ZZError("Too strange. "+depth+" "+maxdepth); + int fract = (256*(depth-1)) / (maxdepth + maxdepth / 10); + Color ncol = ZZUtil.mix(fg, bg, fract); + g.setColor(ncol); + // p("Color: "+fract+" "+d+" "+maxdepth+" "+ncol); + } + + public void render(Graphics g) { + render(g, g); + } + public void render(Graphics g, Graphics orig) { + + // ZZDrawing.instance.setAlpha(g, (float)0.5); + ZZDrawing.instance.setDefaults(g); + ZZDrawing.instance.setQuality(g); + + int f=nflobs-1; + int r=nrend-1; + int oldd = -1; + sort(); + // p("StartColors"); + while(f >= 0 || r >= 0) { + // Stagger the two arrays. Always render decorations of the same + // depth last + while(f >= 0 && + ( r < 0 || rends[r].d <= flobs[f].d)) { + if(flobs[f].d != oldd) + depthColor(g, oldd = flobs[f].d); + if(!flobs[f].needsBox()) + flobs[f--].render(g, orig); + else { + Flob fl = flobs[f--]; + box.renderBg(g, fl); + fl.render(g, orig); + box.renderFrame(g, fl); + } + } + while(r >= 0 && + ( f < 0 || rends[r].d > flobs[f].d)) { + if(rends[r].d != oldd) + depthColor(g, oldd = rends[r].d); + rends[r--].render(g, orig); + } + } + renderDC(g); + } + + FlobSet interpPrepared = null; + public void renderInterp(Graphics g, ZZScene other0, + float fract) { + + ZZDrawing.instance.setDefaults(g); + + sort(); + FlobSet other = (FlobSet)other0; + if(interpPrepared != other) { + prepareInterp(other); + } + renderInterp(g, fract); + } + + public void renderInterp(Graphics g, float fract) { + int oldd = -1; + for(int i=nflobs-1; i>=0; i--) { + if(flobs[i].d != oldd) + depthColor(g, oldd = flobs[i].d); + if(flobs[i].interpTo == null || !flobs[i].needsBox()) + flobs[i].renderInterp(g, fract); + else { + // XXX the interpolation path isn't necessarily linear! + box.renderBg(g, flobs[i], fract); + flobs[i].renderInterp(g, fract); + box.renderFrame(g, flobs[i], fract); + } + } + } + + public boolean isInterpUseful(ZZScene other0) { + FlobSet other = (FlobSet)other0; + return prepareInterp(other); + } + + /** Find flobs for this parent and cell. + * @returns null if no flobs are found (empty array would be inefficient) + */ + public Flob[] findFlobs(Flob parent, ZZCell c) { + tag(); + Hashtable hash = getPH(parent); + Object o = hash.get(c); + if(o == null) return null; + else if(o instanceof Flob) return new Flob[] { (Flob)o }; + else if(o instanceof Flob[]) return (Flob[])o; + + // Now, we have a Vector. Convert to array. + Vector v = (Vector)o; + Flob[] res = new Flob[v.size()]; + for(int i=0; i=0; i--) { + if(flat && flobs[i] instanceof SceneFlob) { + di.act(flobs, i+1, cur-i, sflob); + ((SceneFlob)flobs[i]).getFlobSet().iterDepth(di, true, true); + cur = i; curd = flobs[i].d; + } if(curd != flobs[i].d) { + di.act(flobs, i+1, cur-i, sflob); + cur = i; + curd = flobs[i].d; + } + } + di.act(flobs, 0, cur+1); + } + } + + /** Iterate a routine over blocks of same-depth flobs. + * Does not include flobs inside SceneFlobs. + */ + public void iterDepth(DepthIter di, boolean frontFirst) { + iterDepth(di, frontFirst, false); + } + + DragCursor dc; int dcx, dcy; + public void setDragCursor(DragCursor dc, int x, int y) { + this.dc = dc; this.dcx = x; this.dcy = y; + } + public interface DragCursor { + boolean accept(Object o); + } + + /** Render the current dragCursor. + */ + private void renderDC(Graphics g) { + if(dc == null) return; + Flob[] which = new Flob[1]; + Object co = getObjectAt(dcx, dcy, which); + if(co == null) return; + if(!dc.accept(co)) return; + which[0].renderXOR(g, dcx, dcy); + } + + public int fetch(FlobSet from, int x, int y, int d) { + return fetch(from, x, y, d, null); + } + + /** Fetch the contents of another FlobSet and translate coordinates. + * Takes all flobs and rends, adds x, y and do to their coordinates, + * and puts them in this set. This is used to combine views. + * @param Whenever a flob's applitude field contains null, it is set + * to this value (which may be null in itself). + * @returns The highest depth used (or d, if there weren't any flobs). + */ + public int fetch(FlobSet from, int x, int y, int d, ZZCell applitude) { + int res = d; + for(int i=0; i res) res = f.d; + if(f.applitude == null) f.applitude = applitude; + add(f); + } + for(int i=0; i res) res = r.d; + add(r); + } + return res; + } + + /** Get a new FlobSet like this, just with a different size. + * Used to combine views. + */ + public FlobSet create(Dimension size) { + return new FlobSet(size, fg, bg, cpt); + } + +} diff --git a/Java/flob/FlobView.java b/Java/flob/FlobView.java new file mode 100644 index 0000000..18f4ff4 --- /dev/null +++ b/Java/flob/FlobView.java @@ -0,0 +1,57 @@ +/* +FlobRaster.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** A fairly general interface for drawing a structure + * on the screen using flobs. + * The parameters have been read through the ZOb interface so + * we don't need to worry about those here. + */ + +public interface FlobView { +String rcsid = "$Id$"; + /** Draw a representation of the structure into the FlobSet. + * An implementation of this routine will usually place a number + * of Flobs and Renderables into + * The parameters dims and accursed are redundant but since they + * are used so often, it's just good to have them. + * @param into The FlobSet to place the flobs and decorations into. + * @param fact A factory for constructing flobs. This may be used + * or ignored by the FlobRaster. In general, it should + * be used to draw the "run-of-the-mill" flobs. + * @param view The viewspecs cell in the structure. + * @param dims Three first dims + * @param accursed The cell that the cursor is on + * @see Flob + * @see Renderable + * @see FlobSet + * @see RasterFlobFactory + */ + void raster(FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed); +} + + + + diff --git a/Java/flob/GridGeom.java b/Java/flob/GridGeom.java new file mode 100644 index 0000000..c9156df --- /dev/null +++ b/Java/flob/GridGeom.java @@ -0,0 +1,51 @@ +/* +GridGeom.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.awt.*; + +/** An object that describes the geometry of a rectangular grid. + * The grid is assumed to have a center cell i.e. to have an odd + * number of cells. + */ + +public abstract class GridGeom { +String rcsid = "$Id: GridGeom.java,v 1.1 2000/10/21 23:07:35 tjl Exp $"; + /** Initialize the sizes of this grid. + * @param normalcell The size of a "normal" cell. + * @param canvas The size of the whole rectangle this grid is placed + * into + * @return the number of cells in the grid in X and Y directions. + */ + public abstract Dimension setSizes(Dimension normalcell, Dimension canvas); + /** Returns the rectangle corresponding to the given cell. + */ + public final Rectangle getCell(int x, int y) { + return getCell(x, y, new Rectangle()); + } + /** Returns the rectangle corresponding to the given cell, + * placed into the given Rectangle object. + */ + public abstract Rectangle getCell(int x, int y, Rectangle rect); +} + +// vim: set syntax=java : diff --git a/Java/flob/ICView.zob b/Java/flob/ICView.zob new file mode 100644 index 0000000..d483768 --- /dev/null +++ b/Java/flob/ICView.zob @@ -0,0 +1,71 @@ +/* +ICView.zob + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.awt.*; + +/** An integrated-circuit view. Currently we show only + * dimensions. + */ + +public class ICView implements FlobView, ZOb { +public static final String rcsid = "$Id: ICView.zob,v 1.3 2000/11/07 12:38:27 ajk Exp $"; + + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + STRUCTPARAMS { + } + + public void raster(FlobSet into, FlobFactory fact, ZZCell view, + String[]vds, ZZCell accursed) { + Dimension d = into.getSize(); + + Dimension c = fact.getSize(null, 1); + int cw = c.width; + int ch = c.height; + + ZZCell dimhead = ZZCursorReal.get(view.s("d.dims")).h("d.2"); + + fact.makeFlob(into, accursed, accursed, 1, + (d.width-cw) / 2, 0, 1, cw, ch); + int cury = ch+2; + p("ic loop"); + for(ZZCell cur = dimhead; cur != null; ) { + if(accursed.s(cur.t()) != null || + accursed.s(cur.t(),-1) != null) { + fact.makeFlob(into, cur, cur, 1, (d.width-cw) / 2, + cury, 1, cw, ch); + cury += ch+2; + } + cur = cur.s("d.2"); + if(cur == dimhead) break; + p("ic "+cur); + } + p("Out of ic"); + + } + + +} +// vim: set syntax=java : diff --git a/Java/flob/IdiosyncraticFlobFactory.zob b/Java/flob/IdiosyncraticFlobFactory.zob new file mode 100644 index 0000000..f1d7eb7 --- /dev/null +++ b/Java/flob/IdiosyncraticFlobFactory.zob @@ -0,0 +1,98 @@ +/* +IdiosyncraticFlobFactory.zob + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** A flob factory that shows each cell with its own view, if + * desired. + * The view should be connected negwards of the cell on + * d.cellview, as a FlobFactory (CellView) ZOb. + */ + +public class IdiosyncraticFlobFactory implements FlobFactory, ZOb { +public static final String rcsid = "$Id: IdiosyncraticFlobFactory.zob,v 1.5 2001/03/18 10:38:26 bfallenstein Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + + STRUCTPARAMS { + ZOb def + = null; + } + + public FlobFactory getIdiosyncraticCellView(ZZCell c) { + ZZCell h = c.getRootclone().h("d.cellview", true); + if(h == null) return null; + // XXX We *WILL* need a cache of ZObs... + return (FlobFactory)ZZDefaultSpace.readZOb(h); + } + + /** Get the idiosyncratic or default cell view. + * Never returns null. + */ + public FlobFactory getCellView(ZZCell c) { + FlobFactory cv = getIdiosyncraticCellView(c); + if(cv == null) cv = (FlobFactory)def; + if(cv == null) + throw new ZZError("No default view!"); + return cv; + } + + + public Dimension getSize(ZZCell c, float fract) { + if(c == null) + return ((FlobFactory)def).getSize(null, fract); + return getCellView(c).getSize(c, fract); + } + + public Flob makeFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, + int x, int y, int d, int w, int h) { + return getCellView(c).makeFlob(into, c, handleCell, + fract, x, y, d, w, h); + } + public Flob placeFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, + int x, int y, int depth, + float xfract, float yfract) { + return getCellView(c).placeFlob(into, c, handleCell, + fract, x, y, depth, xfract, yfract); + } + + public Flob centerFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, Point p, int xalign, int yalign, + int depth, Dimension d) { + return getCellView(c).centerFlob(into, c, handleCell, fract, p, + xalign, yalign, depth, d); + } + public Flob centerFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, Point p, int xalign, int yalign, int depth) { + return getCellView(c).centerFlob(into, c, handleCell, fract, p, + xalign, yalign, depth); + } + +} + + +// vim: set syntax=java : diff --git a/Java/flob/Level.java b/Java/flob/Level.java new file mode 100644 index 0000000..7c8e2c5 --- /dev/null +++ b/Java/flob/Level.java @@ -0,0 +1,193 @@ +/* +Level.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ + +package org.gzigzag.module; +import org.gzigzag.*; +import java.awt.*; + +/** Primitive actions for use with LevelRaster. + * XXX join with LevelRaster? + */ + +public class Level { +public static final String rcsid = "$Id: Level.java,v 1.6 2000/11/07 12:38:27 ajk Exp $"; + public static boolean dbg = false; + static void p(String s) { if(dbg) System.out.println(s); } + static void pa(String s) { System.out.println(s); } + + // A "direction" in the ZZ space + static class DimVector { + String dim; + int dir; + DimVector rev; // The reverse vector + + DimVector(String dim, int dir) { + this.dim = dim; this.dir = dir; rev = new DimVector(this); + } + DimVector(DimVector rev) { dim=rev.dim; dir=-rev.dir; this.rev=rev; } + + ZZCell get(ZZCell c) { return c.s(dim, dir); } + ZZCell end(ZZCell c) { return c.h(dim, dir); } + ZZCell end(ZZCell c, boolean ensuremove) { + return c.h(dim, dir, ensuremove); + } + ZZCell create(ZZCell c) { return c.N(dim, dir); } + ZZCell[] rank(ZZCell c, boolean includeThis) { + return c.readRank(dim, dir, includeThis); + } + } + + + /** A set of dimension vectors: linkdim, targetdim and tunneldim. + */ + static class DimSet { + DimVector linkdim; + DimVector targetdim; + DimVector tunneldim; + DimSet rev; + + DimSet(String dims[]) { + linkdim = new DimVector(dims[0], 1); + targetdim = new DimVector(dims[1], 1); + tunneldim = new DimVector(dims[2], 1); + rev = new DimSet(this); + } + + DimSet(DimSet rev) { + linkdim = rev.targetdim.rev; + targetdim = rev.linkdim.rev; + tunneldim = rev.tunneldim.rev; + this.rev = rev; + } + + DimSet(ZZCell viewc) { + ZZCell[] dimcurs = viewc.readRank("d.dims", 1, false); + linkdim = new DimVector( + ZZCursorReal.get(dimcurs[0]).getText(), 1); + targetdim = new DimVector( + ZZCursorReal.get(dimcurs[1]).getText(), 1); + tunneldim = new DimVector( + ZZCursorReal.get(dimcurs[2]).getText(), 1); + rev = new DimSet(this); + } + + boolean islink(ZZCell c) { + return targetdim.get(c) != null || rev.targetdim.get(c) != null; + } + } + + static class Performer { + ZZCell viewc, c; + DimSet ds; + boolean lnk; + String act; + + Performer(ZZCell viewc) { + this.viewc = viewc; c = ZZCursorReal.get(viewc); + ds = new DimSet(viewc); + lnk = ds.islink(c); + // XXX why doesn't this work: + // act = ZZDefaultSpace.getDirActionWaitingAndClear(viewc); + ZZCell nac = ZZDefaultSpace + .findOnClientlist(c.getSpace(), "NextAction", true); + nac = nac.getOrNewCell("d.1", 1, null); + act = nac.getText(); + nac.setText(""); + } + + public void perf(ZZCell to, DimVector dim) { perf(to, dim, c); } + + public void perf(ZZCell to, DimVector dim, ZZCell from) { + // XXX Extend to HOP and NEW! + // HOP just uses dim; NEW needs to check if link AFTER INSERT + if(act.equals("")) + ZZCursorReal.set(viewc, to); + else if(act.equals("HOP")) { + if(!lnk || dim == null) return; + to.insert(dim.dim, dim.dir, from); + } else if(act.equals("NEW")) { + if(dim == null) return; + ZZCell nc = dim.create(from); + if(ds.islink(nc)) { + if(ds.targetdim.get(nc) == null) ds.targetdim.create(nc); + else ds.rev.targetdim.create(nc); + } + } else + System.out.println("Level module can't do "+act); + } + + public void dir(int d, int b) { + DimSet ds = d < 0 ? this.ds.rev : this.ds; + ZZCell to; + if(lnk) { + if(b == 0) { perf(ds.targetdim.end(c), null); return; } + else if(b < 0) { + to = ds.targetdim.get(c); + if(to != null && ds.targetdim.get(to) != null) + perf(to, ds.targetdim); + } else { + to = ds.targetdim.rev.get(c); + if(to != null) perf(to, ds.targetdim.rev); + } + } else { + if(b < 0) { + perf(ds.linkdim.get(c), ds.linkdim); + } else if(b == 0) { + to = ds.tunneldim.get(c); + ZZCell[] rnk = ds.linkdim.rank(c, false); + if(to == null && rnk.length > 0) + to = rnk[rnk.length / 2]; + perf(to, ds.tunneldim); + } else { + to = ds.linkdim.end(c); + perf(to, ds.linkdim, to); + } + } + } + } + + static public ZZModule module = new ZZModule() { + public void action(String id, + ZZCell code, + ZZCell target, + ZZView view, ZZView cview, String key, Point pt, ZZScene xi) { + + Performer p = new Performer(view.getViewcell()); + + if(id.equals("UpLeft")) p.dir(-1, -1); + else if(id.equals("Up")) p.dir(-1, 0); + else if(id.equals("UpRight")) p.dir(-1, 1); + else if(id.equals("DownLeft")) p.dir(1, -1); + else if(id.equals("Down")) p.dir(1, 0); + else if(id.equals("DownRight")) p.dir(1, 1); + else System.out.println("Level module: Unknown code '"+id+"'"); + } + + public ZOb newZOb(String id) { + if(id.equals("Raster")) return new LevelView(); + return null; + } + }; +} + + diff --git a/Java/flob/LevelView.zob b/Java/flob/LevelView.zob new file mode 100644 index 0000000..2773b1f --- /dev/null +++ b/Java/flob/LevelView.zob @@ -0,0 +1,492 @@ +/* +LevelRaster.zob + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ + +package org.gzigzag; +import java.awt.*; +import java.util.*; + +/** A raster for multiple-level structures. + * Interprets two dimensions as many-to-many relationship. Also interprets + * third dimension as one-to-one relationships which are shown the same way + * as the many-to-many relationships. For many-to-many relationships with + * link cells, shows the link cells. + */ + +/* Some XXX'es: + - fix the damn occupiedbreadth bug!!! + - should move the parentlinks in the right place + - primitive actions for leveled visualization (including move) + - loose linking so that new links can be created? or: new link creates + new target, too? or maybe: in loose mode, links w/o target are shown as + that, links w/o target? yeah, way to go. (anyways, should new link also + create new target or not? pbly yes, eh?) + - gaps that shrink; think depthwise gapping through again + */ + +public class LevelView implements FlobView, ZOb { +public static final String rcsid = "$Id$"; + public static boolean dbg = false ; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + STRUCTPARAMS { + /** The size factor applied to cells. */ + float initmul + = (float)1.6; + + /** How many recursion levels shall we render (on both sides of the + * root)? */ + int maxdepth + = 4; + + /** The breadth distance between neigbouring cells. */ + int bgap + = 15; + + /** The depth distance between a cell and a link */ + int dgap + = 10; + + /** The factor of enlargement of cells as they move away + depthwise from the accursed cell. Element 0 is + horizontal, element 1 is vertical. */ + float shrink + = (float)0.7; + + /** The enlargement factor applied to link cells. Think linkshrink! */ + float linkshrink + = (float)0.25; + + /** Should the tree be shown "depthhorizontal", ie. depth rightwards? */ + boolean depthhorizontal + = false; + + /** Should the headcell be used on both dimensions? + * Normally on target dim, tailcell is used. */ + boolean bothhead + = false; + + /** Are links without targets interpreted as targets? + * If two elements are given, the first is used for upstream- and the + * second for downstream connections. */ + boolean[] loose // 1..2 + = new boolean[] { false, false }; + } + + INITIALIZE { + if(loose.length == 1) + loose = new boolean[] { loose[0], loose[0] }; + } + + DimVector[] dims; + Coordinates treegap; // gap converted to a Coordinates instance + Coordinates linkgap; // same with linkshrink applied + Coordinates[] cellsizes; + boolean looseup, loosedown; // XXX ??? + + + // A "direction" in the ZZ space + static class DimVector { + String dim; + int dir; + DimVector rev; // The reverse vector + + DimVector(String dim, int dir) { + this.dim = dim; this.dir = dir; rev = new DimVector(this); + } + DimVector(DimVector rev) { dim=rev.dim; dir=-rev.dir; this.rev=rev; } + + ZZCell get(ZZCell c) { return c.s(dim, dir); } + ZZCell end(ZZCell c) { return c.h(dim, dir); } + ZZCell end(ZZCell c, boolean ensuremove) { + return c.h(dim, dir, ensuremove); + } + ZZCell[] rank(ZZCell c, boolean includeThis) { + return c.readRank(dim, dir, includeThis); + } + } + + class Coordinates { + public int breadth; + public int depth; + + public int x() { return depthhorizontal ? depth : breadth; } + public int y() { return depthhorizontal ? breadth : depth; } + + public void set(int setx, int sety) { + if(depthhorizontal) { + depth = setx; breadth = sety; + } else { + breadth = setx; depth = sety; + } + } + + Coordinates(Dimension d) { set(d.width, d.height); } + Coordinates(int b, int d) { breadth = b; depth = d; } + Coordinates(int i, int j, boolean treecoords) { + if(treecoords) { breadth = i; depth = j; } + else set(i, j); + } + Coordinates(Coordinates c, float fract) { + breadth = (int) (c.breadth * fract); + depth = (int) (c.depth * fract); + } + } + + DimVector[] directeddims(boolean upwards) { + return new DimVector[] { + upwards ? dims[1].rev : dims[0], + upwards ? dims[0].rev : dims[1], + upwards ? dims[2].rev : dims[2] + }; + } + + // STEP 1: Tree generation. This may be overridden + // Note that "children" are cells away from root, and "parents" are + // cells towards root. Only the links to the parents are drawn. + CellInfo connectCell(ZZCell c, ZZCell linkc, ZZCell parentc, + int steps, boolean upwards) { + CellInfo r = new CellInfo(c, linkc, parentc, steps, upwards); + boolean more = steps < maxdepth - 1; + + DimVector[] ds = directeddims(upwards); + DimVector linkdim = ds[0]; + DimVector targetdim = ds[1]; + DimVector tunneldim = ds[2]; + + ZZCell target, parent; + if((target=tunneldim.get(c)) != null && more) + r.childinfo.addElement(connectCell(target, null, c, + steps+1, upwards)); + if((parent=tunneldim.rev.get(c)) != null) + r.parentlinks.addElement(parent); + + ZZCell[] links = linkdim.rank(c, true); + for(int i=0; more && i tdepth ? fdepth : tdepth; + Coordinates size = new Coordinates(cellsizes[depth-1], + linkshrink); + Coordinates fpos = getpos(link.fromc); + Coordinates fsize = getsize(link.fromc); + Coordinates tpos = getpos(link.toc); + Coordinates tsize = getsize(link.toc); + Coordinates pos = new Coordinates( + (fpos.breadth + (fsize.breadth/2) + + tpos.breadth + (tsize.breadth/2) - size.breadth) / 2, + (fpos.depth + fsize.depth + tpos.depth - size.depth) / 2); + boolean succ = put(link.linkc, pos, size, depth, false); + p((succ ? "S" : "Uns")+"uccessfully positioned link cell: "+ + link.linkc.getText()); + } + } + + // STEP 5: Raster the continuum into a flob set + public void raster(FlobSet into, FlobFactory fact, ZZCell view) { + for(Enumeration e = posns.keys(); e.hasMoreElements();) { + ZZCell c = (ZZCell)e.nextElement(); + Coordinates pos = getpos(c); + Coordinates size = getsize(c); + int depth = getdepth(c); + fact.makeFlob(into, c, c, 1, pos.x(), pos.y(), depth, + size.x(), size.y()); + } + for(Enumeration e = linksmalls.elements(); e.hasMoreElements();) { + Link link = (Link)e.nextElement(); + putlink(link.fromc, null, link.toc); + } + for(Enumeration e = links.elements(); e.hasMoreElements();) { + Link link = (Link)e.nextElement(); + int fdepth = getdepth(link.fromc); + int tdepth = getdepth(link.toc); + int depth = fdepth > tdepth ? fdepth : tdepth; + Coordinates fpos = getpos(link.fromc); + Coordinates fsize = getsize(link.fromc); + Coordinates tpos = getpos(link.toc); + Coordinates tsize = getsize(link.toc); + + Coordinates from = new Coordinates( + fpos.breadth + fsize.breadth/2, fpos.depth + fsize.depth); + Coordinates to = new Coordinates( + tpos.breadth + tsize.breadth/2, tpos.depth); + + into.add(new LineDecor(from.x(), from.y(), to.x(), to.y(), + Color.red, depth)); + } + } + } + + + public void initdims(String[] dims) { + this.dims = new DimVector[] { + new DimVector(dims[0], 1), + new DimVector(dims[1], bothhead ? -1 : 1), + new DimVector(dims[2], 1), + }; + } + + public ZZCell look(ZZCell c, int x, int y) { + Coordinates co = new Coordinates(x, y, false); + DimVector d=null, t=null; + if(co.depth == 0) + return null; + else if(co.depth < 0) { + d = dims[0]; + t = dims[3]; + } else { + d = dims[1].rev; + t = dims[3].rev; + } + + if(co.breadth < 0) + return d.get(c); + else if(co.breadth > 0) + return d.end(c, true); + else { + if(t.get(c) != null) return t.get(c); + ZZCell[] rank = d.rank(c, false); + if(rank.length == 0) return null; + return rank[rank.length / 2]; + } + } + + + public void raster(FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell c) { + Dimension cs = fact.getSize(null, initmul); + cellsizes = new Coordinates[maxdepth]; + cellsizes[0] = new Coordinates(cs); + for(int i=1; i 1; xw += 2*cur+2*gap[0]) { + ret.width +=2; + cur = (int)(cur * shrink[0]); + } + if(fit) { + xw -= 2*cur+2*gap[0]; + ret.width -= 2; + } + + xs = new int[ret.width + 1]; + cur = (int)(normalcell.width * initmul[0]); + xs[ret.width / 2] = cur; + for(int i=1; i 1; yw += 2*cur+2*gap[1]) { + ret.height +=2; + cur = (int)(cur * shrink[1]); + } + if(fit) { + yw -= 2*cur+2*gap[1]; + ret.height -= 2; + } + + ys = new int[ret.height + 1]; + cur = (int)(normalcell.height * initmul[1]); + ys[ret.height / 2] = cur; + for(int i=1; i2; nx++) { + xw += 2 * (int)curl; + curl *= shrink[0]; + } + + int ny = 0; + curl = maxsz.height; + for(int yw = 0; yw <= fs.height - maxsz.height && curl>2; ny++) { + yw += 2 * (int)curl; + curl *= shrink[1]; + } + + nx *= 2; + ny *= 2; + ZZCell[][] grid = new ZZCell[nx][ny]; + + int[] xsz = new int[nx+1]; + int[] ysz = new int[ny+1]; + + xsz[0] = maxsz.width / 2; + xsz[1] = maxsz.width; + ysz[0] = 2*maxsz.height; + ysz[1] = maxsz.height; + + curl = maxsz.width; + for(int i=0; i 0 && cur != null; x--) { ld.detect(cur); + cur = cur.s(dims[0], -1); if(cur == xhead) break; + grid[x][cy] = cur; + } + + ld.reset(); + cur = accursed; + for(int y = cy-1; y > 0 && cur != null; y--) { ld.detect(cur); + cur = cur.s(dims[1], -1); if(cur == yhead) break; + grid[cx][y] = cur; + } + + // Poswards + ld.reset(); + cur = accursed; + for(int x = cx+1; x < nx && cur != null; x++) { ld.detect(cur); + grid[x][cy] = cur = cur.s(dims[0], 1); + } + ld.reset(); + cur = accursed; + for(int y = cy+1; y < ny && cur != null; y++) { ld.detect(cur); + grid[cx][y] = cur = cur.s(dims[1], 1); + } + + + // Other headcells + for(int x = 1; x < nx; x ++) + if(grid[x][cy] != null) { + grid[x][0] = grid[x][cy].h(dims[1], -1); + if(grid[x][0]!=null) + heads.put(grid[x][0], new Integer(x)); + } + for(int y = 1; y < ny; y ++) + if(grid[cx][y] != null) { + ZZCell c = grid[0][y] = grid[cx][y].h(dims[0], -1); + if(c!=null) + heads.put(c, new Integer(0)); + c = c.s(dims[0], 1); + ld.reset(); + while(c!=null) { // Show other intersections + ld.detect(c); + Integer xpos = (Integer)heads.get(c.h(dims[1], -1)); + if(xpos!=null) + grid[xpos.intValue()][y] = c; + c = c.s(dims[0], 1); + } + } + + + LineDecor.Builder bdline = new LineDecor.Builder(into, Color.red); + bdline.startl(400, 1); + + // Find out which cells are shown + + Hashtable shown = new Hashtable(); + + for(int x = 0; x < nx; x++) { + for( int y = 0; y < ny; y++) { + if(grid[x][y]!=null) + shown.put(grid[x][y], grid[x][y]); + } + } + + // Render the flobs + + for(int x = 0; x < nx; x ++) { + for( int y = 0; y < ny; y ++) { + if(grid[x][y] == null) continue; + int xcoord = xsz[x]; + int ycoord = ysz[y]; + int width = xsz[x+1] - xcoord; + int height = ysz[y+1] - ycoord; + + if(x != 0 && y != 0 && heads.get(grid[x][y])!=null) + continue; + + Flob fl = fact.makeFlob(into, grid[x][y], grid[x][y], + initmul * height / (float)maxsz.height, + xcoord, ycoord, 1, width, height); + /* if(x == 0 || y == 0) + fl.flobPath="headcell";*/ + + // Place a red line if the neighbour isn't shown + ZZCell c = grid[x][y]; + for(int dx=-1;dx<=1;dx+=2) { + ZZCell n = c.s(dims[0], dx); + if(n!=null && shown.get(n)==null + && (y!=0 || (x+dx>0 && x+dx0 && y+dy=0; i--) { + cury -= getfontmet(getFontScale(i-ctr, doBillow)).getHeight(); + } + + res.x = startx; res.width = width; + res.y = cury; + + // Downwards from center. + // start-splitcellflob needs very careful attention. + + /** Current offset in the whole string. + */ + int curoffs = 0; + /** Current line. + */ + int curline = 0; + + /** Current X-coordinate. + */ + int curx = startx; + + int fi = getFontScale(curline - ctr, doBillow); + Font f = getfont(fi); + FontMetrics fm = getfontmet(fi); + + SplitCellFlob1 latest = null; + + first = true; + for(ZZCell h = head; + h != null && (first || h != head); h = h.s(dim, 1)) { + first = false; + + final String st = h.getText(); + final int len = st.length(); + int nth = 0; + SplitCellFlob1 parent = null; + + // Find the cursors on this cell. Only one is shown. + int curs = ZZCursorReal.NO_OFFSET; + ZZCell ccurs = h; + while((ccurs = ccurs.s("d.cursor", 1))!=null) { + curs = ZZCursorReal.getOffs(ccurs); + if(curs != ZZCursorReal.NO_OFFSET) break; + } + + if(h.s("d.cut", 1) != null) { + // There was a cut. + into.add(new LineDecor(curx, cury, curx, cury+fm.getHeight(), + Color.red, 1)); + } + + while(curoffs + len - nth > linestops[curline+1]) { + p("Parent: "+nth+" "+len+" "+curline+" "+linestops[curline+1]); + SplitCellFlob1 cur = new SplitCellFlob1( + curx, cury, 100, fm.stringWidth(st.substring(nth, + nth+ + (linestops[curline+1] - curoffs))), + fm.getHeight(), h, f, fm, parent, + nth, linestops[curline+1]-curoffs, xormode, bgcolor); + if(bgcolor == null) cur.showCursor(); + cur.setPrev(latest); latest = cur; + if(curs != ZZCursorReal.NO_OFFSET) + addCurs(into, cur, curs); + parent = cur; + into.add(cur); + + // Split it. + nth += linestops[curline+1] - curoffs; + curoffs = linestops[curline+1]; + curline ++; + cury += fm.getHeight(); + curx = startx; + fi = getFontScale(curline - ctr, doBillow); + f = getfont(fi); + fm = getfontmet(fi); + if(curline >= linestops.length - 1) { + p("LAST LINE: ALL OUT"); + break; + } + } + if(curline >= linestops.length - 1) + break; + + p("Last: "+nth+" "+len+" "+curline+" "+linestops[curline+1]+" "+ + st.length()); + int w = 0; + String substr = st.substring(nth, len); + p("Substr: "+substr); + SplitCellFlob1 last = new SplitCellFlob1( + curx, cury, 100, + (w = fm.stringWidth(substr)), + fm.getHeight(), h, f, fm, parent, nth, len-nth, xormode, bgcolor); + if(bgcolor == null) last.showCursor(); + last.setPrev(latest); latest = last; + + if(curs != ZZCursorReal.NO_OFFSET) + addCurs(into, last, curs); + curoffs += len-nth; + curx += w; + into.add(last); + } + p("FINISHED"); + res.height = cury - res.y + fm.getHeight(); + return res; + } + + public Rectangle raster(FlobSet into, ZZCell c, int offs, boolean doBillow, + int startx, int starty) { + return raster(into, c, offs, doBillow, startx, starty, + SplitCellFlob1.XOR_NO); + } + + private void addCurs(FlobSet into, SplitCellFlob1 sf, int ind) { + if(!(ind >= sf.start && ind <= sf.start + sf.n)) + return; + int x = sf.getStrX(ind); + if(x >= 0) + into.add(new LineDecor(x, sf.y, x, sf.y+sf.h, + Color.black, sf.d)); + } + + public void raster(FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed) { + ZZCell c = ZZCursorReal.get(view); + int offs = ZZCursorReal.getOffs(view); + int xormode = SplitCellFlob1.XOR_LINE; + if(offs == ZZCursor.NO_OFFSET) { + offs = 0; + xormode = SplitCellFlob1.XOR_SOLID; + } + + if(!xor) xormode = SplitCellFlob1.XOR_NO; + + Dimension d = into.getSize(); + int cy = d.height / 2; + + raster(into, c, offs, billow, 0, cy, xormode); + } + + // public VStreamRaster() { } + +} + +// vim: set syntax=java : diff --git a/Java/flob/Renderable.java b/Java/flob/Renderable.java new file mode 100644 index 0000000..cfb4749 --- /dev/null +++ b/Java/flob/Renderable.java @@ -0,0 +1,88 @@ +/* +Renderable.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.awt.*; + + +public abstract class Renderable { +public static final String rcsid = "$Id: Renderable.java,v 1.10 2001/03/17 20:13:08 bfallenstein Exp $"; + + public int d; + + /** Render this thing. + */ + abstract public void render(Graphics g); + + /** Render this thing. + * Simply calls render(g). + * @param orig The top-level graphics object without translations, + * clippings, rotations, etc. + */ + public void render(Graphics g, Graphics orig) { render(g); } + + /** Translate the coordinates of this Renderable by (x, y) + * I.e., add x from the x-coordinate and y from the y-coordinate. + * This is used to translate between coordinate systems. + * @returns False if translating is not supported. + */ + public boolean translate(int x, int y) { + return false; + } + + + /** Do a stable depth-sort of renderables. + * Of two renderables on the same depth, the relative order remains. + * Uses radix sort for extreme speed. + */ + static public void depthSort(Renderable[] it, int nit) { + Renderable[][] ftmp = new Renderable[][] { it, new Renderable[nit] }; + Renderable[][] ftmp2 = new Renderable[2][nit]; + Renderable[][] fs; + int[] n = new int[] { nit, 0 }; + int[] newn = new int[2]; + int[] nex = null; + int mx = 0; + for(int i=0; i mx) mx = it[i].d; + } + for(int bit = 1; mx >= bit && bit!=0; bit <<= 1) { + for(int bin=0; bin<2; bin++) { + for(int i=0; i= col.length) return false; + if(!repeat && done.get(c) != null) return false; + col[nth] = c; + done.put(c, c); + if(row) + geom.getCell(cother, nth, rect); + else + geom.getCell(nth, cother, rect); + place(fact, into, c, ideal, rect); + return true; + } + }); + + final int lother = (row ? gs.width : gs.height); + + for(int i = 0; i= lother) return false; + if(!repeat && done.get(c) != null) return false; + done.put(c, c); + if(row) + geom.getCell(nth, coord, rect); + else + geom.getCell(coord, nth, rect); + place(fact, into, c, ideal, rect); + return true; + } + }); + } + + linker.decorate(into, "", view); + } + + + +} +// vim: set syntax=java : diff --git a/Java/flob/SceneFlob.java b/Java/flob/SceneFlob.java new file mode 100644 index 0000000..5cfecfb --- /dev/null +++ b/Java/flob/SceneFlob.java @@ -0,0 +1,148 @@ +/* +SceneFlob.java + * + * Copyright (c) 2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** Flob which contains flobset, possibly transformed. + * This is subclassed by e.g. ZZDrawingJ2D. + */ + +public abstract class SceneFlob extends BoxedFlob { +public static final String rcsid = "$Id: SceneFlob.java,v 1.8 2001/03/18 17:50:16 bfallenstein Exp $"; + public static final boolean dbg = true; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + FlobSet sc; + + public SceneFlob(int x, int y, int d, int w, int h, ZZCell c, FlobSet sc) { + super(x,y,d,w,h,c); + this.sc = sc; + sc.sflob = this; + } + + /** The flobs that are important to interpolate + * even when level-of-detail is small + */ + Flob[] important; + + /** Set the important-to-interpolate flobs. + */ + public void setImportant(Flob[] what) { + important = what; + } + + /** Whether this is a focused sceneflob, i.e.whether level-of-detail + * is high. + */ + boolean focus; + + public void setFocus(boolean focus) { + this.focus = focus; + } + + /** The other sceneflob we are currently prepared to interpolate to. + */ + SceneFlob interpPrep; + + /** The scene flob this one is in. + * This is needed to convert coordinates to top-level; and that is needed + * to create connections between windows. + */ + SceneFlob parent; + + /** Transform the given points between the internal and external coordinates. + * @param toExt Whether to transform internal to external or vice versa. + */ + public abstract void transform(double[] srcPtr, double[]dstPts, boolean toExt); + + /** Transform the given point between the internal and external coordinates. + * @param toExt Whether to transform internal to external or vice versa. + */ + public abstract Point transform(Point src, Point dst, boolean toExt); + + /** Transform the given points between the internal and top-level coordinates. + * @param toTop Whether to transform internal to top-level or vice versa. + */ + public void transformTop(double[] srcPtr, double[] dstPts, boolean toTop) { + if(toTop) transform(srcPtr, dstPts, true); + if(parent != null) + parent.transformTop(srcPtr, dstPts, toTop); + if(!toTop) transform(srcPtr, dstPts, false); + } + + /** Transform the given point between the internal and top-level coordinates. + * @param toTop Whether to transform internal to top-level or vice versa. + */ + public Point transformTop(Point src, Point dst, boolean toTop) { + if(toTop) transform(src, dst, true); + if(parent != null) + parent.transformTop(src, dst, toTop); + if(!toTop) transform(src, dst, false); + return dst; + } + + /** Make this graphics so that we can render into it with the correct + * transformation. + */ + abstract void prepareGraphics(Graphics g, float interpFract); + + public void render(Graphics g0) { render(g0, g0); } + public void render(Graphics g0, Graphics orig) { + Graphics g = g0.create(); + prepareGraphics(g, 0); + sc.render(g, orig); + g.dispose(); + } + + public void renderInterp(Graphics g0, float fract) { + if(!(interpTo instanceof SceneFlob)) return; + // p("sceneflob renderinterp"); + // Here we test the level-of-detail stuff. + if(interpTo != interpPrep) { + interpPrep = (SceneFlob)interpTo; + // p("Prepinterp sceneflob: "+focus+" "+interpPrep.focus+" "+important); + if(focus || interpPrep.focus || important == null) + sc.prepareInterp(interpPrep.sc); + else + sc.prepareInterp(interpPrep.sc, important); + } + Graphics g = g0.create(); + prepareGraphics(g, fract); + sc.renderInterp(g, ((SceneFlob)interpTo).sc, fract); + g.dispose(); + } + + public boolean isInterpUseful() { return true; } + + public Object hit(int x, int y) { + Point p = new Point(x,y); + Point d = new Point(); + transform(p,d, false); + return sc.getObjectAt(d.x, d.y); + } + + public FlobSet getFlobSet(){ return sc;} + +} diff --git a/Java/flob/SimpleBeamer.zob b/Java/flob/SimpleBeamer.zob new file mode 100644 index 0000000..4415c0c --- /dev/null +++ b/Java/flob/SimpleBeamer.zob @@ -0,0 +1,256 @@ +/* +SimpleBeamer.zob + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + + +package org.gzigzag; +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +/** A decorator which draws beams between overlapping SpanFlobs. + * This is a tricky job: among other things, we are responsible for + * the overall aesthetic effect of beams. + * Currently, we try to draw the beams between the topmost + * flobs last so that the beams have a consistent ordering w.r.t. + * the Z axis. This is not trivial, since we also have to + * draw neighbouring beams using the same color. + */ + +public class SimpleBeamer implements FlobDecorator { +public static final String rcsid = "$Id: SimpleBeamer.zob,v 1.7 2000/09/19 10:31:59 ajk Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + STRUCTPARAMS { + + /** The depth where to put the beam graphics. + */ + int depth + = 1000; + + } + + // Used for checking whether the connection between two spans + // is handled already. + private class Pair { + Object a; Object b; + public Pair(Object a, Object b) { + this.a = a; + this.b = b; + } + public int hashCode() { + return a.hashCode() ^ b.hashCode(); + } + public boolean equals(Object o) { + Pair p = (Pair)o; + return (a==p.a && b==p.b) || (b==p.a && a==p.b); + } + } + + static public Color getSpanColor() { + return new Color( + (float)(Math.random() + 1) / 2, + (float)(Math.random() + 1) / 2, + (float)(Math.random() + 1) / 2 + ); + } + + int[] xy = new int[16]; + + protected void putBeam(BeamDecor.Builder bb, + SpanFlob[] sfs, Span[] sps, + Color c) { + p("Putbeam"); + int ssep = (int)(sps[0].getStartOffs() - sps[1].getStartOffs()); + int esep = (int)(sps[0].getEndOffs() - sps[1].getEndOffs()); + + int x0=0, x1=0, w0=(int)sps[0].length(), w1=(int)sps[1].length(); + + if(ssep > 0) x1 = ssep; + else x0 = -ssep; + + if(esep > 0) w0 -= esep; + else w1 += esep; + + Rectangle r0 = sfs[0].getRectangle(x0, w0); + Rectangle r1 = sfs[1].getRectangle(x1, w1); + + // Then, some difficult manipulation to get the points. + + Rectangle a=null; + + // left side + if(r0.x < r1.x) { a = r0; } else { a = r1; } + xy[0] = a.x; xy[8] = a.y; + xy[1] = a.x; xy[9] = a.y+a.height; + // bottom side + if(r0.y+r0.height > r1.y+r1.height) { a = r0; } else { a = r1; } + xy[2] = a.x; xy[10] = a.y+a.height; + xy[3] = a.x+a.width; xy[11] = a.y+a.height; + // right side + if(r0.x+r0.width > r1.x+r1.width) { a = r0; } else { a = r1; } + xy[4] = a.x+a.width; xy[12] = a.y+a.height; + xy[5] = a.x+a.width; xy[13] = a.y; + // top + if(r0.y < r1.y) { a = r0; } else { a = r1; } + xy[6] = a.x+a.width; xy[14] = a.y; + xy[7] = a.x; xy[15] = a.y; + + bb.b(xy, c); + + } + + /** Return: whether to continue. + */ + static boolean moveBack( SpanFlob[] sfs, + Span[] spans) { + long l1 = spans[0].getStartOffs(); + long l2 = spans[1].getStartOffs(); + if(l1 == l2) { + // Check if previous spans end at same point. + sfs[0] = sfs[0].getPrev(); if(sfs[0] == null) return false; + sfs[1] = sfs[1].getPrev(); if(sfs[1] == null) return false; + spans[0] = sfs[0].getSpan(); if(spans[0] == null) return false; + spans[1] = sfs[1].getSpan(); if(spans[1] == null) return false; + if(spans[0].getEndOffs() != spans[1].getEndOffs()) return false; + return true; + } + if(l1 > l2) { + Span tmp = spans[0]; + sfs[0] = sfs[0].getPrev(); if(sfs[0] == null) return false; + spans[0] = sfs[0].getSpan(); if(spans[0] == null) return false; + return spans[0].isAppendable(tmp); + } else { + Span tmp = spans[1]; + sfs[1] = sfs[1].getPrev(); if(sfs[1] == null) return false; + spans[1] = sfs[1].getSpan(); if(spans[1] == null) return false; + return spans[1].isAppendable(tmp); + } + } + static boolean moveForw( SpanFlob[] sfs, + Span[] spans) { + long l1 = spans[0].getEndOffs(); + long l2 = spans[1].getEndOffs(); + if(l1 == l2) { + // Check if previous spans end at same point. + sfs[0] = sfs[0].getNext(); if(sfs[0] == null) return false; + sfs[1] = sfs[1].getNext(); if(sfs[1] == null) return false; + spans[0] = sfs[0].getSpan(); if(spans[0] == null) return false; + spans[1] = sfs[1].getSpan(); if(spans[1] == null) return false; + if(spans[0].getStartOffs() != spans[1].getStartOffs()) return false; + return true; + } + if(l1 < l2) { + Span tmp = spans[0]; + sfs[0] = sfs[0].getNext(); if(sfs[0] == null) return false; + spans[0] = sfs[0].getSpan(); if(spans[0] == null) return false; + return tmp.isAppendable(spans[0]); + } else { + Span tmp = spans[1]; + sfs[1] = sfs[1].getNext(); if(sfs[1] == null) return false; + spans[1] = sfs[1].getSpan(); if(spans[1] == null) return false; + return tmp.isAppendable(spans[1]); + } + } + + public void decorate(final FlobSet into, final String path, + final ZZCell view) { + + p("Putting beams..."); + final BeamDecor.Builder bb = new BeamDecor.Builder(into); + + final SpanSet ss = new SpanTree(); + + final Hashtable done = new Hashtable(); + + final SpanFlob[] sfs = new SpanFlob[2]; + final Span[] sps = new Span[2]; + final Span[] sps0 = new Span[2]; + + // Starts from the surface, goes deeper. + // BeamDecor renders first-put ones last, which is + // exactly right for this. + + // XXX WRONG! + // ss gets added things so that the span gets + // drawn when the deeper one is reached, not earlier. + // hmm... + into.iterDepth(new FlobSet.DepthIter() { + public void act(Flob[] flobs, int start, int n) { + bb.startl((n+8)*4, depth); + for(int f = start; f 0) { + p("Obj: "+ovs[0]); + } else continue; + + + for(int i=0; i= 14) { + g.drawRect(mx-2, my-2, mw+2, mh+2); + } + } +} + + diff --git a/Java/flob/SimpleFlobConnector.zob b/Java/flob/SimpleFlobConnector.zob new file mode 100644 index 0000000..42a1169 --- /dev/null +++ b/Java/flob/SimpleFlobConnector.zob @@ -0,0 +1,109 @@ +/* +SimpleFlobConnector.zob + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** A simple but powerful raster which uses flob coordinates. + * Z is the selection dimension, X and Y are the flob dimension + * specifications. + */ + +public class SimpleFlobConnector implements FlobDecorator, ZOb { +public static final String rcsid = "$Id: SimpleFlobConnector.zob,v 1.9 2000/09/19 10:31:59 ajk Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + STRUCTPARAMS { + + /** Whether the selection dimension is always d.2 or + * whether it is the Z dimension. + */ + boolean selectd2 + = true; + + /** The path from one handle cell to another. + */ + ZZPath connection + = null; + } + + int count; + // public SimpleFlobConnector() { } + + // Always middle - to - middle. + public void decorate(final FlobSet f, final String path, + final ZZCell view) { + + p("SIMPLEFLOBCNNETOR DECORATE!"); + count = 0; + + final Hashtable done = new Hashtable(); + + if(connection == null) + throw new ZZError("Must provide value for FlobConnector connection"); + + final ConnectionLineDecor.Builder clb = new + ConnectionLineDecor.Builder(f, null); + clb.startl(100, 1); + + f.iterDepth(new FlobSet.DepthIter() { + public void act(Flob[] flobs, int start, int n) { + + for(int i=start; i + * XXX Rework the nextPart, parent, next, prev relation! + */ + +public class SplitCellFlob1 extends Flob implements SpanFlob { +public static final String rcsid = "$Id: SplitCellFlob1.java,v 1.36 2001/04/02 20:21:43 bfallenstein Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + // The XOR modes. + static public final int XOR_NO = 0; + static public final int XOR_LINE = 1; + static public final int XOR_FRAME = 2; + static public final int XOR_SOLID = 3; + + public int xormode = XOR_NO; + + + /** Whether to clip before drawing the contents of this flob. */ + public boolean doClip = false; + + /** The next part of this flob. */ + SplitCellFlob1 nextPart; + + /** The first of this chain. */ + public SplitCellFlob1 parent; + + /** Index of first character. */ + public int start; + + /** Number of characters. */ + public int n; + + /** The text in this flob (substring of c.getText()). + * This text is allowed to be modified from outside to allow e.g. for + * firstcap. Doing that in any way that does not retain the number + * and offsets of characters will screw up beams and many other + * things so don't do that ;) + */ + public String txt; + + public SpanFlob prev, next; + public SpanFlob getPrev() { return prev; } + public SpanFlob getNext() { return next; } + public void setPrev(SpanFlob sf) { + prev = sf; + if(prev != null) prev.setNext(this); + } + public void setNext(SpanFlob sf) { next = sf; } + + public Color bg, fg = Color.black; + + Font f; + FontMetrics fm; + + /** Set the background of this flob to the color of the topmost cursor. */ + public void showCursor() { + // Only take topmost cursor's color + ZZCell curs = getCell().s("d.cursor", 1); + if(curs != null) { + bg = ZZCursorReal.getColor(curs); + if(bg == null) + pa("No cursor color!"); + } else + p("No cursors on this cell."); + } + + static boolean intostr = false; + public String toString() { + if(intostr) return super.toString(); + intostr = true; + String ret = super.toString() + "(SPLCF1 bg="+bg+ + "Parent: ("+parent+") stn: "+start+" "+n+" Txt:'"+txt+"' Cell:"+c + +" next: "+nextPart + + " )"; + intostr = false; + return ret; + } + + public SplitCellFlob1(int x, int y, int d, int w, int h, + ZZCell c, Font f, FontMetrics fm, SplitCellFlob1 parent, + int start, int n) { + this(x, y, d, w, h, c, f, fm, parent, start, n, null); + } + + public SplitCellFlob1(int x, int y, int d, int w, int h, + ZZCell c, Font f, FontMetrics fm, SplitCellFlob1 parent, + int start, int n, Color bg) { + this(x, y, d, w, h, c, + c.getText().substring(start, start+n), + f, fm, parent, start, n, bg); + } + + public SplitCellFlob1(int x, int y, int d, int w, int h, + ZZCell c, String txt, Font f, FontMetrics fm, SplitCellFlob1 parent, + int start, int n, Color bg) { + + super(x, y, d, w, h, (parent==null ? c : null)); + p("SplitCellFlob: "+x+" "+y+" "+d+" "+w+" "+h+" "+c+" "+f+" "+ + fm+" "+parent+" "+start+" "+n+" "+bg); + this.f = f; this.fm = fm; + if(parent != null) { + if(!parent.c.equals(c)) + throw new ZZError( + "Parent and child splitcellflob must have same cell: "+c+ + " "+parent.c); + SplitCellFlob1 prev = parent; + while(prev.nextPart != null) prev = prev.nextPart; + prev.nextPart = this; + this.parent = (parent.parent == null ? parent : parent.parent); + } + this.start = start; this.n = n; + this.txt = txt; + this.bg = bg; + p("Created splitcellflob: "+this); + } + + public SplitCellFlob1(int x, int y, int d, int w, int h, + ZZCell c, Font f, FontMetrics fm, SplitCellFlob1 parent, + int start, int n, int xormode) { + this(x, y, d, w, h, c, f, fm, parent, start, n); + } + + public SplitCellFlob1(int x, int y, int d, int w, int h, + ZZCell c, Font f, FontMetrics fm, SplitCellFlob1 parent, + int start, int n, int xormode, Color bg) { + this(x, y, d, w, h, c, f, fm, parent, start, n, bg); + this.xormode = xormode; + } + + public final ZZCell getCell() { + return (parent==null ? c : parent.c); + } + + public Span getSpan() { + Span sp = getCell().getSpan(); + if(sp == null) return null; + // XXX test for samity + return sp.subSpan(start, start+n); + } + + public Rectangle getRectangle(Span s) { + Span t = getCell().getSpan(); + int so = (int)(s.getStart().getOffs() - t.getStart().getOffs()); + int eo = (int)(s.getEnd().getOffs() - t.getStart().getOffs()); + int sw = fm.stringWidth(txt.substring(0, so)); + int ew = fm.stringWidth(txt.substring(0, eo)); + return new Rectangle(x + sw, y, ew-sw, h); + } + public Rectangle getRectangle(int offs, int end) { + int sw = fm.stringWidth(txt.substring(0, offs)); + int ew = fm.stringWidth(txt.substring(0, end)); + return new Rectangle(x + sw, y, ew-sw, h); + } + + /* Very quick hack to interpolate from and to non-span flobs: + * let this read render(g0, x, y, d, w, h) instead of render(g0). Not at + * all what the interpolation SHOULD look like, but better than the + * nothing we've had before. + */ + public void render(Graphics g0, int x, int y, int d, int w, int h) { + int my = y + h - fm.getDescent(); + // p("SpliCellFlob drawString: '"+txt+"' "+x+" "+my+" "+fg+" "+bg); + + Graphics g = g0.create(); + Color bu = g.getColor(); + if (doClip) g.clipRect(x, y, w, h); + g.setFont(f); + if(bg != null) { + g.setColor(bg); + g.fillRect(x, y, w, h); + } + if(fg != null) g.setColor(fg); + else g.setColor(bu); + p("SpliCellFlob drawString: '"+txt+"' "+x+" "+my+" "+fg+" "+bg); + g.drawString(txt, x, my); + + g.dispose(); + + if(nextPart != null) + nextPart.render(g0); + } + + /** Render an interpolated version. + * This is the trickiest routine of this class since we do + * want to get the interpolation behaviour just right so that all text + * pieces flow to where they are supposed to. + */ + public void renderInterp(Graphics g0, float fract) { + if(interpTo==null) return; + if(!(interpTo instanceof SplitCellFlob1)) { + super.renderInterp(g0, fract); + return; + } + SplitCellFlob1 t = this; + SplitCellFlob1 r = (SplitCellFlob1)interpTo; + + Graphics g = g0.create(); + Shape clip = g.getClip(); + if(fg != null) g.setColor(fg); + + // Render the correct fragment of the two and advance. + while(t!=null && r!=null) { + if(t.start+t.n < r.start) { t = t.nextPart; continue; } + if(t.start > r.start+r.n) { r = r.nextPart; continue; } + int st = 0; + int en = 0; + if(t.start < r.start) st = r.start; + else st = t.start; + if(t.start+t.n < r.start+r.n) en = t.start+t.n; + else en = r.start+r.n; + int tx = t.getStrX(st); + int rx = r.getStrX(st); + int x = (int)(tx + (rx-tx)*fract); + int ty = t.y + t.h - t.fm.getDescent(); + int ry = r.y + r.h - r.fm.getDescent(); + int y = (int)(ty + (ry-ty)*fract); + int tw = t.getStrX(en) - tx; + int rw = r.getStrX(en) - rx; + int w = (int)(tw + (rw-tw)*fract); + int realy = (int)(t.y + (r.y-t.y)*fract); + if (doClip) { + g.clipRect(x, realy, w, t.h); + } + if(bg != null) { + Color col = g.getColor(); + g.setColor(bg); + g.fillRect(x, realy, tw, t.h); + g.setColor(col); + } + g.setFont(t.f); + g.drawString(t.txt.substring(st-t.start, en-t.start), x, y); + if (doClip) g.setClip(clip); + if(t.start+t.n < r.start+r.n) t = t.nextPart; + else r = r.nextPart; + } + g.dispose(); + } + + public boolean renderXORLine(Graphics g, int cx, int cy) { + ZZCursorVirtual vc = (ZZCursorVirtual)hit(cx, cy); + if(vc==null) return false; + g.setColor(Color.black); + g.setXORMode(Color.white); + int xo = fm.stringWidth(txt.substring(0, vc.getOffs()-start)); + g.drawLine(x+xo, y, x+xo, y+h); + return true; + } + + public void renderXORFrame(Graphics g, boolean left, boolean right) { + // XXX instead of using f.h-1 & f.y+1, just don't create overlapping + // XXX SplitCellFlobs any more? + g.setColor(Color.black); + g.setXORMode(Color.white); + SplitCellFlob1 f = parent != null ? parent : this; + if(left) g.drawLine(f.x, f.y+1, f.x, f.y+f.h-1); + while(true) { + g.drawLine(f.x, f.y+1, f.x+f.w, f.y+1); + g.drawLine(f.x, f.y+f.h-1, f.x+f.w, f.y+f.h-1); + if(f.nextPart != null) f = f.nextPart; + else break; + } + if(right) g.drawLine(f.x+f.w, f.y+1, f.x+f.w, f.y+f.h-1); + } + + public void renderXORSolid(Graphics g) { + g.setColor(Color.black); + g.setXORMode(Color.white); + SplitCellFlob1 f = parent != null ? parent : this; + for(; f != null; f = f.nextPart) { + g.fillRect(f.x, f.y, f.w, f.h); + } + } + + public boolean renderXOR(Graphics g, int cx, int cy) { + if(!insideRect(cx, cy)) return false; + if(xormode == XOR_NO) return true; // XXX or false? + else if(xormode == XOR_LINE) return renderXORLine(g, cx, cy); + else if(xormode == XOR_FRAME) renderXORFrame(g, true, true); + else if(xormode == XOR_SOLID) renderXORSolid(g); + else throw new ZZError("SplitCellFlob1: Unknown XOR mode"); + return true; + } + + /** Get the x-coordinate of a given letter. + * @param ind The index, given as starting from the beginning of the cell. + * Must satisfy start <= ind <= start+n + */ + public int getStrX(int ind) { + ind -= start; + return x + fm.stringWidth(txt.substring(0,ind)); + } + + public Object hit(int x, int y) { + if(!insideRect(x, y)) return null; + if(xormode == XOR_FRAME || xormode == XOR_SOLID) + return new ZZCursorVirtual(getCell(), ZZCursorVirtual.NO_OFFSET); + int ind = ZZUtil.findStringHit(txt, x-this.x, fm) + start; + return new ZZCursorVirtual(getCell(), ind); + } + + /** Add a line cursor at the given index into the given flobset. + */ + public void addCurs(FlobSet into, int ind, Color c) { + if(parent != null) + parent.addCurs0(into, ind, c); + else + addCurs0(into, ind, c); + } + private void addCurs0(FlobSet into, int ind, Color c) { + if(ind >= start && ind <= start + n) { + int x = getStrX(ind) - 1; + into.add(new LineDecor(x, y, x, y+h, + c, d)); + } + if(nextPart != null) + nextPart.addCurs0(into, ind, c); + } + +} diff --git a/Java/flob/SplitView.zob b/Java/flob/SplitView.zob new file mode 100644 index 0000000..3baecd9 --- /dev/null +++ b/Java/flob/SplitView.zob @@ -0,0 +1,78 @@ +/* +SplitView.zob + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ + +package org.gzigzag; +import java.awt.*; + +/** A view that shows the ctrl and data windows in one. */ + +public class SplitView implements FlobView, ZOb { +public static final String rcsid = "$Id: SplitView.zob,v 1.1 2000/12/26 15:20:42 bfallenstein Exp $"; + /** Should we print out debugging info? */ + public static boolean dbg = false; + static final void p(String s) { if(dbg) pa(s); } + static final void pa(String s) { System.out.println(s); } + + STRUCTPARAMS {} + + public void raster(FlobSet into, FlobFactory fact, + ZZCell win, String[] dims, ZZCell accursed) { + Dimension size = new Dimension(into.getSize()); + size.width = size.width / 2; + FlobSet set = into.create(size), otherset = into.create(size); + + FlobView view = new VanishingView(); + view.raster(set, fact, win, dims, accursed); + + boolean isctrl = false; + ZZCell otherwin = win.s("d.ctrlview", -1); + if(otherwin == null) { otherwin=win.s("d.ctrlview"); isctrl=true; } + if(otherwin == null) + throw new ZZError("SplitView invoked for a window which is " + + "not in a control/data pair!"); + + String[] otherdims = ZZDefaultSpace.getDimList(otherwin); + ZZCell otheracc = ZZCursorReal.get(otherwin); + + ZZCell c = ZZDefaultSpace.findInheritableParam(otherwin, "View"); + ZZCell rastname = ZZCursorReal.get(c); + + ZOb frz = ZZDefaultSpace.readZOb(rastname); + FlobView otherview = null; + if(frz != null && frz instanceof FlobView) { + otherview = (FlobView)frz ; + } else { + System.out.println("getScene: invalid type: "+frz); + otherview = new NullView(); + } + + otherview.raster(otherset, fact, otherwin, otherdims, otheracc); + + if(isctrl) { + FlobSet tmp = set; + set = otherset; + otherset = tmp; + } + + into.fetch(otherset, 0, 0, 0); + into.fetch(set, size.width, 0, 0); + } +} diff --git a/Java/flob/StdLinks.zob b/Java/flob/StdLinks.zob new file mode 100644 index 0000000..8979f20 --- /dev/null +++ b/Java/flob/StdLinks.zob @@ -0,0 +1,208 @@ +/* +StdLinks.zob + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +public class StdLinks implements FlobDecorator { +public static final String rcsid = "$Id: StdLinks.zob,v 1.13.10.1 2002/03/07 21:02:41 bfallenstein Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + STRUCTPARAMS { + + /** Whether to draw badly directioned links as splines. + */ + boolean splines + = true; + + /** Spline radius. + */ + float splinvec + = 50; + + /** Whether the tight-brick mode is used for cells with + * non-shown links. + */ + boolean tightDefault + = false; + + /** Whether to draw the links the old way, between corners. + */ + boolean useCorners + = false; + + } + + static int[] xoffs = new int[] {1, 0, 1}; + static int[] yoffs = new int[] {0, 1, 1}; + + public void decorate(final FlobSet f, final String path, + final ZZCell view) { + final String[] dims = ZZDefaultSpace.getDimList(view); + p("DECORATE STDLINKS"); + // Cells whose connections were done. + final Hashtable done = new Hashtable(); + final Point p1 = new Point(), p2 = new Point(); + + final LineDecor.Builder ldb = new LineDecor.Builder(f, null); + + f.iterDepth(new FlobSet.DepthIter() { + public void act(Flob[] flobs, int start, int n) { + p("STDLINKS ACT "+start+" "+n+" "+flobs[start].d); + + ldb.startl(4*n, flobs[start].d+1); + + for(int i=start; i= xoffs.length) break; + // p(" Dim: "+dims[d]); + + for(int dir=-1; dir<=1; dir += 2) { + ZZCell neigh = c.s(dims[d], dir); + p(" Neigh: "+neigh+" "+ + (neigh!=null?neigh.getText():"")+ + " "+(neigh==null? + "nothing" : done.get(neigh))); + if(neigh == null || + done.get(neigh) != null) continue; + Flob nfl = f.findFlob(path, neigh); + p(" Found: "+nfl); + if(nfl != null) + p(" ...path: "+nfl.flobPath); + // show connections to non-shown cells + // XXX: is this tight-brick? if so, this should be + // made conditional + if(nfl == null) { + // XXX UseCorners!!! + int xo = xoffs[d]; + int yo = yoffs[d]; + int xh = (xo==0 ? 1 : 0); + int yh = (yo==0 ? 1 : 0); + int df = (dir > 0 ? 1 : 0); + int x1 = cur.x + ((2*xo + xh)*cur.w) / 2; + int y1 = cur.y + ((2*yo + yh)*cur.h) / 2; + int len = 1; // Stub length + int wid = 5; // Stub width + if (dir < 0) { + int cx = cur.x + cur.w / 2; + int cy = cur.y + cur.h / 2; + x1 = x1 - 2 * (x1 - cx) + dir*xo; + y1 = y1 - 2 * (y1 - cy) + dir*yo; + } + int x2 = x1 + dir * xo * len ; + int y2 = y1 + dir * yo * len ; + ldb.l(x1, y1, x2, y2); + ldb.l(x2+dir*yo*wid/2, y2-dir*xo*wid/2, + x2-dir*yo*wid/2, y2+dir*xo*wid/2); + continue; + } + + // Now, find line coordinates. + Flob from=null, to=null; + if(dir > 0) { + from = cur; to = nfl; + } else { + from = nfl; to = cur; + } + if(useCorners) { + int xo = xoffs[d]; + int yo = yoffs[d]; + int xh = (xo==0 ? 1 : 0); + int yh = (yo==0 ? 1 : 0); + ldb.l( + from.x + (2*xo + xh)*from.w / 2, + from.y + (2*yo + yh)*from.h / 2, + to.x + (xh)*to.w / 2, + to.y + (yh)*to.h / 2 + ); + } else { + from.getCenter(p1); + to.getCenter(p2); + // Check the direction. + // XXX abstract out! + int dx = p2.x - p1.x; + int dy = p2.y - p1.y; + boolean curve = false; + if(splines) { + if(d == 0) { // X + curve = (dx/(2*dy+1) == 0 || dx < 0); + } else if(d == 1) { // Y + curve = (dy/(2*dx+1) == 0 || dy < 0); + } else if(d == 2) { // Z + curve = ( + dx / (2*dy+1) != 0 || + dy / (2*dx+1) != 0 || + dx < 0 || + dy < 0 + ); + } + } + if(curve) { + p("SPLINE! "+d+" "+dx+" "+dy); + int aw = from.w + to.w; + int ah = from.h + to.h; + aw *= 2; + ah *= 2; + int[] curv = ZZUtil.bulgeCurve( + p1.x, p1.y, + xoffs[d] * aw, yoffs[d] * ah, + p2.x, p2.y, -xoffs[d] * aw, + -yoffs[d] * ah, + 9 + ); + for(int p=2; p= maxdepth) return new Vector(); + + ++currdepth; + + Vector rv = new Vector(); + + py("start"); + + if (root == null) { + py("root is null"); + } else { + py("root is " + root.getID()); + } + + // position a cell not in the tree that lies left from the root + ZZCell cell = root == null ? null : breadth.getCellPredecessor(root); + if (cell != null && !cellpos.containsKey(cell)) { + Dimension s = smcsize[currdepth]; + Dimension pos = new Dimension(); + pos.width = currbcoord; + pos.height = dcoord[currdepth] + + csize[currdepth].height / 2 - s.height / 2; + cellpos.put(cell, pos); + celldepth.put(cell, new Integer(maxdepth + 1)); + cellsize.put(cell, s); + extracells.put(cell, cell); + currbcoord += s.width + gaps[currdepth].width; + } + + if (root != null && cellpos.containsKey(root)) py("root is known"); + + int count = 0; + for (cell = root; + cell != null && (!cellpos.containsKey(cell) + || extracells.containsKey(cell)); + cell = breadth.getCellSuccessor(cell)) { + + if (extracells.containsKey(cell)) extracells.remove(cell); + + py("cell " + cell.getID()); + cellpos.put(cell, new Dimension()); + + rv.addElement(cell); + + int startbcoord = currbcoord; + Vector children = place_tree_cells(depth.getCellSuccessor(cell)); + int endbcoord = currbcoord; + + cellchildren.put(cell, children); + + Dimension cs = csize[currdepth]; + + int dcorr = 0; + // contain too many siblings so that + // eg. d.cellcreation as breadth does not hang; + // however, we must go on until the accursed cell is + // with us. + if (count > canvaswidth / csize[currdepth].width + && cellpos.containsKey(accursed) && cell != accursed) { + cs = smcsize[currdepth]; + dcorr = csize[currdepth].height / 2 - cs.height / 2; + extracells.put(cell, cell); + } + cellsize.put(cell, cs); + + Dimension cpos = new Dimension((startbcoord + endbcoord - cs.width) / 2, + dcoord[currdepth] + dcorr); + + if (cpos.width < startbcoord) cpos.width = startbcoord; + + py("positioning cell " + cell.getID() + " at (" + cpos.width + "," + cpos.height + ")"); + cellpos.put(cell, cpos); + celldepth.put(cell, new Integer(currdepth)); + if (currbcoord < cpos.width + cs.width + gaps[currdepth].width) + currbcoord = cpos.width + cs.width + gaps[currdepth].width; + + // position a cell not in the tree that lies up from the root + ZZCell up = depth.getCellPredecessor(cell); + if (up != null && !cellpos.containsKey(up)) { + Dimension s = smcsize[currdepth]; + Dimension pos = new Dimension(); + pos.width = cpos.width + csize[currdepth].width / 2 - s.width / 2; + pos.height = cpos.height - s.height - gaps[currdepth].width / 2; + cellpos.put(up, pos); + celldepth.put(up, new Integer(maxdepth + 1)); + cellsize.put(up, s); + extracells.put(up, up); + } + + if (extracells.containsKey(cell)) break; + count++; + } + py("finish"); + --currdepth; + return rv; + } + + public PositionDecider(DimVector breadth, DimVector depth, + Dimension fs, FlobFactory fact, + ZZCell accursed) { + this.breadth = breadth; + this.depth = depth; + this.canvaswidth = fs.width; + + this.accursed = accursed; + + py("created"); + + gaps = new Dimension[maxdepth]; + csize = new Dimension[maxdepth]; + smcsize = new Dimension[maxdepth]; + dcoord = new int[maxdepth]; + + gaps[maxdepth/2] = new Dimension(gap[0], gap[1]); + csize[maxdepth/2] = new Dimension(fact.getSize(null, initmul)); + if (depthhorizontal) { + int tmp = csize[maxdepth/2].width; + csize[maxdepth/2].width = csize[maxdepth/2].height; + csize[maxdepth/2].height = tmp; + } + dcoord[maxdepth/2] = (depthhorizontal ? fs.width : fs.height) / 2; + for (int i = maxdepth / 2 - 1; i >= 0; i--) { + gaps[i] = new Dimension((int)(gaps[i+1].width * shrink[0]), + (int)(gaps[i+1].height * shrink[1])); + csize[i] = new Dimension((int)(csize[i+1].width * shrink[0]), + (int)(csize[i+1].height * shrink[1])); + dcoord[i] = dcoord[i+1] - (csize[i+1].height + gaps[i+1].height); + } + for (int i = maxdepth / 2 + 1; i < maxdepth; i++) { + gaps[i] = gaps[maxdepth - 1 - i]; + csize[i] = csize[maxdepth - 1 - i]; + dcoord[i] = dcoord[i-1] + csize[i-1].height + gaps[i-1].height; + } + for (int i = 0; i < maxdepth; i++) { + smcsize[i] = new Dimension(csize[i].width / 4, + csize[i].height / 4); + } + + } + public Enumeration getCells() { return cellpos.keys(); } + public Dimension getCellPosition(ZZCell c) { + return new Dimension((Dimension)cellpos.get(c)); + } + public int getCellDepth(ZZCell c) { + return ((Integer) celldepth.get(c)).intValue(); + } + public Dimension getCellSize(ZZCell c) { + return new Dimension((Dimension)cellsize.get(c)); + } + + public boolean existCell(ZZCell c) { + return cellpos.containsKey(c); + } + + public Enumeration getCellChildren(ZZCell c) { + Object o = cellchildren.get(c); + Vector v; + if (o == null) v = new Vector(); else v = (Vector)o; + return v.elements(); + } + } + + public void raster(FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed) { + + DimVector breadth = new DimVector(dims[0], 1); + DimVector depth = new DimVector(dims[1], 1); + + if (depthhorizontal) { + DimVector tmp = breadth; + breadth = depth; + depth = tmp; + } + + p("finding the root cell"); + ZZCell root; + { + ZZCell cell = accursed; + int count = 0; + Hashtable seen = new Hashtable(); + do { + root = cell; + seen.put(root, root); + cell = depth.getCellPredecessor(root); + boolean up = true; + if (cell == null) { + cell = breadth.getCellPredecessor(root); + up = false; + } + if (cell != null && seen.containsKey(cell)) cell = null; + if (cell != null && up) count++; + } while (cell != null && count < maxdepth / 2); + p("done finding the root cell"); + } + + PositionDecider pd = new PositionDecider(breadth, depth, + into.getSize(), + fact, accursed); + + pd.place_tree_cells(root); + + Dimension acpos; + if (pd.existCell(accursed)) { + acpos = pd.getCellPosition(accursed); + } else { + pa("FIXME: accursed cell not in modeled tree"); + acpos = into.getSize(); + acpos.width /= 2; + acpos.height /= 2; + } + + int bcorr = acpos.width - (depthhorizontal + ? into.getSize().height + : into.getSize().width) / 2; + + for (Enumeration e = pd.getCells(); e.hasMoreElements();) { + ZZCell cell = (ZZCell) e.nextElement(); + + Dimension pos = pd.getCellPosition(cell); + + pos.width -= bcorr; + + + if (depthhorizontal) { + int tmp = pos.width; + pos.width = pos.height; + pos.height = tmp; + } + + Dimension cs = pd.getCellSize(cell); + + if (depthhorizontal) { + int tmp = cs.width; + cs.width = cs.height; + cs.height = tmp; + } + + int d = pd.getCellDepth(cell); + + fact.makeFlob(into, cell, cell, 1, pos.width, pos.height, + d, cs.width, cs.height); + + // draw tree lines + if (treelines) { + for (Enumeration f = pd.getCellChildren(cell); + f.hasMoreElements();) { + ZZCell child = (ZZCell) f.nextElement(); + Dimension cpos = pd.getCellPosition(child); + cpos.width -= bcorr; + if (depthhorizontal) { + int tmp = cpos.width; + cpos.width = cpos.height; + cpos.height = tmp; + } + Dimension chs = pd.getCellSize(child); + if (depthhorizontal) { + int tmp = chs.width; + chs.width = chs.height; + chs.height = tmp; + } + if (depthhorizontal) { + into.add(new LineDecor(pos.width + cs.width, + pos.height + cs.height / 2, + cpos.width, + cpos.height + cs.height / 2, + Color.red, + (pd.getCellDepth(child) + d) / 2)); + } else { + into.add(new LineDecor(pos.width + cs.width / 2, + pos.height + cs.height, + cpos.width + chs.width / 2, + cpos.height, + Color.red, + (pd.getCellDepth(child) + d) / 2)); + } + } + } + + + } + + // XXX This should be a structparam later on. + (new StdLinks()).decorate(into, "", view); + + // Do the dimensions. XXX strings or cells? + if (true) { + Dimension s = fact.getSize(null, 1); + + ZZCell bdim = ZZCursorReal.get(view.s("d.dims", 1)); + ZZCell ddim = ZZCursorReal.get(view.s("d.dims", 1).s("d.dims", 1)); + + if (bdim == null || ddim == null) { + throw new ZZError("no dimensions"); + } + + Flob bfl = fact.makeFlob(into, bdim, bdim, 1, s.width, 0, + 1, s.width, s.height); + Flob dfl = fact.makeFlob(into, ddim, ddim, 1, 0, s.height, + 1, s.width, s.height); + bfl.flobPath = "dim"; + dfl.flobPath = "dim"; + + int wh = s.width / 2; + int hh = s.height / 2; + + into.add(new LineDecor(new int[] { wh, hh, wh, s.height, + wh, hh, s.width, hh }, + 8, Color.red, 1)); + } + } +} + +// vim: set syntax=java : diff --git a/Java/flob/VanishingView.zob b/Java/flob/VanishingView.zob new file mode 100644 index 0000000..e6e8787 --- /dev/null +++ b/Java/flob/VanishingView.zob @@ -0,0 +1,317 @@ +/* +VanishingView.zob + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + + +package org.gzigzag; +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +/** A reimplementation of the vanishing raster. + * Much simpler than the original one since this one does not try + * to do the hard rasters as well. + */ + +public class VanishingView implements FlobView, ZOb { +public static final String rcsid = "$Id: VanishingView.zob,v 1.9 2000/12/11 02:54:44 tjl Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + // Following are the parameters out of which the constructor + // is created. + + STRUCTPARAMS { + + /** The factor to shrink the cells with when moving away from + * center. + */ + float[] shrink // 2..2 + = new float[] {(float)0.9, (float)0.9}; + + /** The factor the center cell is enlarged with from default. + */ + float[] initmul // 2..2 + = new float[] {(float)1.6, (float)1.6}; + + /** The factor to enlarge the center cell on top of initmul. + * This only has an effect on the center cell whereas initmul + * affects all cells. + */ + float[] centermul // 2..2 + = new float[] {(float)1.0, (float)1.0}; + + /** The distance between neighbouring cells. + */ + int[] gap // 2..2 + = new int[] {5, 5}; + + /** The depth to raster to. + */ + int depth + = 5; + + /** The precedence order of dimensions. + */ + int[] pref // 2..5 + = new int[] {0, 1, 2}; + + /** Whether to allow cell sizes to vary. + */ + boolean varsize + = false; + + /** Whether alignment around visual flob center is to be used. + * If true, halign is ignored. + */ + boolean centeralign + = true; + + /** Distance reverse perspective. + */ + float revper + = (float)1.00; + + /** Horizontal alignment. + * 0 = center, -1 = left, 1 = right. + */ + int halign + = 0; + } + + // XXX This should be a structparam later on. + FlobDecorator linker = new StdLinks(); + + + // Offsets of x and y + static int[] xoffs = new int[] {1, 0, 1}; + static int[] yoffs = new int[] {0, 1, 1}; + + + public void raster(FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed) { + + Dimension fs = into.getSize(); + + // Precalculate sizes and gaps. + int[] xgap = new int[depth]; + int[] ygap = new int[depth]; + + int[] xsize = new int[depth+1]; + int[] ysize = new int[depth+1]; + float[] sizfact = new float[depth+1]; + + float xf = initmul[0]; + float yf = initmul[1]; + Dimension d0 = fact.getSize(null, yf); + Dimension d = (varsize ? fact.getSize(accursed, yf) : d0); + + xsize[0] = d.width; + ysize[0] = d.height; + sizfact[0] = yf; + float yf0 = yf, xf0=xf; + + for(int i=0; i= maxd) continue; + if(did[dim].get(curFlob[0].c) != null) continue; + did[dim].put(curFlob[0].c, curFlob[0].c); + + // Current depth + int curd = (curFlob[0].d - d1) / dm; + + ZZIter.NEnum rank = ZZIter.alternate(curFlob[0].c, false, dims[pref[dim]], 1); + ZZCell next; + while((next = rank.nextCell()) != null) { + int curind = (rank.nth() < 0 ? 0 : 1); + int dir = curind * 2 - 1; + int xdep = (rank.nth() < 0 ? -rank.nth() : rank.nth()); + Flob f = curFlob[curind]; + + if(cellsDone.get(next) != null || + curd + xdep >= depth) { + rank.stop(); + continue; + } + + cellsDone.put(next, next); + + if(centeralign) { + + // First, determine alignment. + int xalign = dir * xoffs[pref[dim]]; + int yalign = dir * yoffs[pref[dim]]; + + // Then, find alignment point in last cell, + // centered on center of screen + f.getPoint(aligned, xalign, yalign); + + // Using that, find alignment point + // in the next cell. + + aligned.x -= fs.width / 2; + aligned.x *= revper; + aligned.x += fs.width / 2; + + aligned.y -= fs.height / 2; + aligned.y *= revper; + aligned.y += fs.height / 2; + + aligned.x += xalign*xgap[curd+xdep-1]; + aligned.y += yalign*ygap[curd+xdep-1]; + + Dimension size = new Dimension(xsize[curd+xdep], + ysize[curd+xdep]); + f = curFlob[curind] = fact.centerFlob(into, next, next, + sizfact[curd+xdep], aligned, -xalign, -yalign, + d1 + dm * (curd + xdep), varsize ? null : size); + + } else { + + int x=0, y=0, w=0, h=0; + if(varsize) { + Dimension dvar = fact.getSize(next, sizfact[curd+xdep]); + w = dvar.width; + h = dvar.height; + } else { + w = xsize[curd+xdep]; + h = ysize[curd+xdep]; + } + + // A bit tricky due to flob coords being + // UL corner. + + // First, find alignment point in last cell, + // centered on center of screen + int alignedX = + f.x + (halign+1)*f.w/2 - fs.width/2; + int alignedY = + f.y + f.h/2 - fs.height/2; + + // Then, using that, find alignment point + // in the next cell. + int xof = xoffs[pref[dim]]; + alignedX += dir * xof * ( + xgap[curd+xdep-1] + (1-dir*halign) * f.w/2 + + (1+dir*halign) * w/2 + ); + alignedY += dir * yoffs[pref[dim]] * ( + ygap[curd+xdep-1] + f.h/2 + h/2 + ); + + // Expand the coordinate system around the + // origin + alignedX *= revper; + alignedY *= revper; + + // Finally, find upper left corner of next cell. + x = alignedX - (halign+1)*w/2 + fs.width/2; + y = alignedY - h/2 + fs.height/2; + + p("Vanishing: puttig "+next+ + x+" "+y+" "+w+" "+h); + + f = curFlob[curind] = fact.makeFlob(into, next, next, + sizfact[curd+xdep], x, y, + d1 + dm * (curd + xdep), w, h); + + } + + cur.addElement(f); + did[dim].put(f.c, f.c); + added = true; + } + } + // If we added cells, and we're not doing a hard + // raster, start doing dimensions all over again. + if(added) dim = -1; + } + + linker.decorate(into, "", view); + + // Do the dimensions. + if(true) + ZZUtil.showFlobDims(into, fact, view, 3); + } + +} + + +// vim: set syntax=java : diff --git a/Java/flob/VobSet.java b/Java/flob/VobSet.java new file mode 100644 index 0000000..15c06ab --- /dev/null +++ b/Java/flob/VobSet.java @@ -0,0 +1,73 @@ +/* +VobSet.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** A draft for a new interface to FlobSet. + * The point is that this interface can be implemented by several + * things and we can make dfferent views interact in interesting + * ways. + *

    + * A VobSet can be thought of as a window in some ways... + */ + +abstract public class VobSet implements ZZScene { +public static final String rcsid = "$Id: VobSet.java,v 1.1 2000/12/11 02:54:10 tjl Exp $"; + + public static final boolean dbg = true; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + abstract public Rectangle getBounds(); + abstract public int getDepth(); + + // XXX Make it use ZZDrawing2D to get the bg paint. + abstract public Color getBackground(); + + abstract public void add(Renderable r); + abstract public void add(Flob f); + + // ??? protected void depthColor(Graphics g, int depth) { + + abstract public void dump(); + + /** A callback interface for iterating over the Flobs + * in a FlobSet in depth order. + */ + public interface DepthIter { + void act(Flob[] flobs, int start, int n); + } + + /** Iterate a routine over a blocks of same-depth flobs. + */ + abstract public void iterDepth(DepthIter di, boolean frontFirst); + + + + // XXX Spanset? + // abstract public SpanFlob[] findFlobs(Span s); + + // abstract public + +} diff --git a/Java/flob/WindowCellView.zob b/Java/flob/WindowCellView.zob new file mode 100644 index 0000000..c7b016e --- /dev/null +++ b/Java/flob/WindowCellView.zob @@ -0,0 +1,129 @@ +/* +ClockCellView.zob + * + * Copyright (c) 2000-2001, Ted Nelson and Tuomas Lukka + * Copyright (c) 2001, Benja Fallenstein + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benja Fallenstein + */ + +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** A cell view that shows the contents of a window. + * Use this ZOb as the headcell on d.cellview from the window's cursor cell, + * and that cell will appear as the window's contents. + */ + +public class WindowCellView implements FlobFactory, ZOb { +public static final String rcsid = "$Id: WindowCellView.zob,v 1.3 2001/03/18 17:50:16 bfallenstein Exp $"; + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + STRUCTPARAMS { + } + + public Dimension getSize(ZZCell c, float fract) { + // XXX use the bounds as specified in the structure + return new Dimension((int)(500*fract), (int)(300*fract)); + } + + public Flob makeFlob(FlobSet into, ZZCell c0, ZZCell handleCell, + float fract, + int x, int y, int d, int w, int h) { + + FlobSet sc = into.create(new Dimension(w, h)); + SceneFlob sf = new SimpleSceneFlob(x, y, d, w, h, c0, sc); + CellFlobFactory1.addSolidColors(into, sf, sf); + into.add(sf); + + if(w+h < 100) return sf; + ZZCell view = c0.getRootclone(); + + ZZCell c = ZZDefaultSpace.findInheritableParam(view, "View"); + ZZCell rastname = ZZCursorReal.get(c); + + ZOb frz = ZZDefaultSpace.readZOb(rastname); + FlobView fr = null; + if(frz != null && frz instanceof FlobView) { + fr = (FlobView)frz ; + } else { + System.out.println("getScene: invalid type: "+frz); + fr = new NullView(); + } + // XXX Signal error + + c = ZZDefaultSpace.findInheritableParam(view, "CellView"); + + FlobFactory rff = null; + if(c != null) { + ZZCell cfact = ZZCursorReal.get(c); + + ZOb ffzob = ZZDefaultSpace.readZOb(cfact); + rff = (FlobFactory) ffzob; + } + + p("WindowCellView: prepare view"); + fr.raster(sc, rff, view, ZZDefaultSpace.getDimList(view), + ZZCursorReal.get(view)); + p("WindowCellView: view prepared"); + + if(rff != null) { + Flob rn = rff.placeFlob(sc, rastname, rastname, (float)1.5, w, 0, 1, 1, 0); + rn.flobPath="rastname"; + } + + return sf; + } + + public Flob placeFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, + int x, int y, int depth, + float xfract, float yfract) { + Dimension d = getSize(c, fract); + return makeFlob(into, c, handleCell, fract, + (int)(x-xfract*d.width), + (int)(y-yfract*d.height), + depth, d.width, d.height); + } + + public Flob centerFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, Point p, int xalign, int yalign, + int depth, Dimension d) { + if(d == null) d = getSize(c, fract); + int x, y; + x = p.x - d.width/2; y = p.y - d.height/2; + + if(xalign < 0) x = p.x; + if(xalign > 0) x = p.x - d.width; + if(yalign < 0) y = p.y; + if(yalign > 0) y = p.y - d.height; + p("centerFlob "+p+" "+d+" at "+x+" "+y+" align "+xalign+" "+yalign); + return makeFlob(into, c, handleCell, fract, x, y, + depth, d.width, d.height); + } + public Flob centerFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, Point p, int xalign, int yalign, int depth) { + return centerFlob(into, c, handleCell, fract, p, xalign, yalign, + depth, null); + } +} + +// vim: set syntax=java : diff --git a/Java/media/Address.java b/Java/media/Address.java new file mode 100644 index 0000000..ac3f06e --- /dev/null +++ b/Java/media/Address.java @@ -0,0 +1,95 @@ +/* +Address.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.util.*; + +/** An address in a stable media stream. + * Currently just a silly pointer but will be later extended + * to include full tumblers. + * Format: streamid.offset, where streamid is an alphanumeric string + * identifying a stream. + */ + +public class Address { +public static final String rcsid = "$Id: Address.java,v 1.3 2000/09/19 10:32:00 ajk Exp $"; + public static final boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + + Scroll scroll; + String stream; + long offset; + public static Address parse(String s) { + StringTokenizer st = new StringTokenizer(s, "."); + if(st.countTokens() != 2) { + throw new ZZError("Wrong number of toks in '"+s+"'"); + } + Address a = new Address(); + a.stream = st.nextToken(); + a.offset = Long.parseLong(st.nextToken()); + return a; + } + + public static Address streamOffs(String s, long offs) { + Address a = new Address(); + a.stream = s; + a.offset = offs; + return a; + } + public static Address scrollOffs(Scroll s, long offs) { + // return s.getId() + "." + offs; + Address a = new Address(); + a.stream = s.getId(); + a.offset = offs; + return a; + } + + public String getStream() { return stream; } + public Scroll getScroll(ZZSpace s) { + if(scroll==null) scroll = Scroll.obtain(s, stream); + return scroll; + } + public long getOffs() { return offset; } + + public String toString() { + return stream.toString() + "." + offset; + } + + public boolean lessThan(Address a) { + int c = stream.compareTo(a.stream); + if(c < 0) return true; + if(c > 0) return false; + if(offset < a.offset) return true; + return false; + } + + public Address addOffs(int o) { + Address a = new Address(); + a.scroll = scroll; + a.stream = stream; + a.offset = offset + o; + return a; + } + +} + diff --git a/Java/media/ByteScroll.java b/Java/media/ByteScroll.java new file mode 100644 index 0000000..9d80698 --- /dev/null +++ b/Java/media/ByteScroll.java @@ -0,0 +1,99 @@ +/* +ByteScroll.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.io.*; + +/** A scroll of bytes. May later have holes etc. from expunging, + * but basically the point is that the address to content mapping + * is stable and will not change whatever is done. + */ +public class ByteScroll extends Scroll{ +public static final String rcsid = "$Id: ByteScroll.java,v 1.4 2000/09/19 10:32:00 ajk Exp $"; + // Cheat: it's just a file + private RandomAccessFile f; + + private String encoding; + + private boolean readonly; + + public ByteScroll(String id, File fn, String mode, String encoding, + boolean ro) { + super(id); + this.encoding = encoding; + this.readonly = ro; + try { + f = new RandomAccessFile(fn, mode); + } catch(Exception e) { + ZZLogger.exc(e); + throw new NullPointerException("Can't get"); + } + } + + public synchronized byte[] get(long start, int n) { + try { + f.seek(start); + byte[] ret = new byte[n]; + int r = f.read(ret); + if(r!=n) + throw new NullPointerException("NOT ENOUGH!"); + return ret; + } catch(Exception e) { + ZZLogger.exc(e); + throw new NullPointerException("Can't get"); + } + } + + // XXX ENCODING + public String getString(long start, int n) { + byte[] b = get(start,n); + try { + return new String(b, "ISO8859_1"); + } catch(Exception e) { + ZZLogger.exc(e); + throw new NullPointerException("Can't get"); + } + } + + public long curEnd() { try { return f.length(); + } catch(Exception e) { + ZZLogger.exc(e); + throw new NullPointerException("Can't get"); + } + } + + public synchronized long append(byte[] bytes) { + if(readonly) throw new ZZError("Can't append to readonly scroll"); + try { + long offs = curEnd(); + f.seek(offs); + f.write(bytes); + return offs; + } catch(Exception e) { + ZZLogger.exc(e); + throw new NullPointerException("Can't get"); + } + } +} + + diff --git a/Java/media/Capitalizer.java b/Java/media/Capitalizer.java new file mode 100644 index 0000000..51e8c7d --- /dev/null +++ b/Java/media/Capitalizer.java @@ -0,0 +1,100 @@ +/* +Capitalizer.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Capitalizing code written by Tuomas Lukka + */ + +package org.gzigzag; +import java.awt.*; +import java.util.*; + +/** A class to capitalize first letters of sentences. + * A sentence is separated by two or more spaces. If you just need to + * capitalize one string, use the static method single(String). If you need + * to capitalize a number of concurrent strings, instantiate Capitalizer and + * run cap(String) over them, in order. + *

    + * The algorithm is tricky and probably needs a lot of adjustment. + * The first letters of sentences are currently identified by + * two spaces next to each other. + */ + +public class Capitalizer { +public static final String rcsid = "$Id: Capitalizer.java,v 1.1 2000/12/25 19:37:09 bfallenstein Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + /** Have we read a single space? */ + boolean hadSpace = false; + + /** Are we past a sentence boundary (two spaces)? */ + boolean boundary = true; + + public static String single(String s) { + return new Capitalizer().cap(s); + } + + public String cap(String s) { + int len = s.length(); + // Look for the first non-space character the hard way. + int i; + for(i=0; i 1) { + char c1 = s.charAt(len-1); + if(c1 == ' ') { + char c2 = s.charAt(len-2); + boundary = (c2 == ' '); + hadSpace = (c2 != ' '); + } + } + // Then, find the other occurrences. + int ind = i-1; + while((ind = s.indexOf(" ", ind+1)) >= 0) { + if(ind == s.length() - 2) break; + if(Character.isLetter(s.charAt(ind+2))) + s = s.substring(0, ind+2) + + Character.toUpperCase( s.charAt(ind+2)) + + s.substring(ind+3); + } + return s; + } +} \ No newline at end of file diff --git a/Java/media/CharScroll.java b/Java/media/CharScroll.java new file mode 100644 index 0000000..e5b03ae --- /dev/null +++ b/Java/media/CharScroll.java @@ -0,0 +1,109 @@ +/* +CharScroll.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.io.*; + +/** DEPRECATED FOR STRINGSCROLL + * A scroll of chars. May later have holes etc. from expunging, + * but basically the point is that the address to content mapping + * is stable and will not change whatever is done. + * XXX copied from ByteScroll - sad. + */ +public class CharScroll extends Scroll{ +public static final String rcsid = "$Id: CharScroll.java,v 1.5 2000/09/19 10:32:00 ajk Exp $"; + // Cheat: it's just a file + private RandomAccessFile f; + // public static final boolean dbg = true; + // static final void p(String s) { if(dbg) System.out.println(s); } + + + private boolean readonly; + + public CharScroll(String id, File fn, String mode, + boolean ro) { + super(id); + this.readonly = ro; + try { + f = new RandomAccessFile(fn, mode); + } catch(Exception e) { + ZZLogger.exc(e); + throw new NullPointerException("Can't get"); + } + } + + public synchronized char[] get(long start, int n) { + try { + f.seek(start*2); + byte[] ret = new byte[n*2]; + int r = f.read(ret); + if(r!=n*2) + throw new NullPointerException("NOT ENOUGH!"); + char[] c = new char[n]; + for(int i=0; i res) res = h; + } + return res; + } + public static int len(Part[] ps) { + int res = 0; + for(int i=0; i= at) { + return new int[] { i, p.n-(here-at) }; + } + } + return new int[] { parts.length-1, parts[parts.length-1].n }; + } + + /** Return lines laid out at a given width. + * The dimensions of the array are lines[line][part] + */ + public Part[][] getLines(int width) { + return FirstMatchBreaker.stupidBreak(this, width); + } + + public static int findLine(Part[][] lines, int offs) { + int here = 0; + for(int i=0; i= offs) return i; + } + return lines.length-1; + } + + /** Capitalize the sentences in the whole FText. */ + public void capitalize() { + Capitalizer c = new Capitalizer(); + for(int i=0; i= 0) { + char c = s.charAt(here); + v.addElement(new Word(p, last+1, here+1, c == '\n')); + last = here; + } + v.addElement(new Word(p, last+1, s.length(), false)); + } + + return v; + } + + /** Internal convenience: Vector to array. */ + private static FText.Part[] v2a(Vector v) { + concat(v); + FText.Part[] res = new FText.Part[v.size()]; + for(int i=0; i linestart && x > width) { + lineset.addElement(v2a(line)); + line.removeAllElements(); + x = w.width(); linestart = i; + } + line.addElement(w); + if(x > width || w.forced) { + /* w alone doesn't fit on our line, or forced break after w */ + lineset.addElement(v2a(line)); + line.removeAllElements(); + x = 0; linestart = i+1; + } + } + if(line.size() > 0) lineset.addElement(v2a(line)); + FText.Part[][] res = new FText.Part[lineset.size()][]; + for(int j=0; j + * Specific attention is paid to the billowing problem where + * we have to render a paragraph so that the cursor is at the line with + * the first line of the paragraph starts from the beginning of a line. + * This is achieved by specifying the cursor position (from where the lines + * should be counted) and the desired line number for that position. + * This can also be used to render the paragraph starting from the end. + */ + +public abstract class LineBreaker { +String rcsid = "$Id: LineBreaker.java,v 1.8.10.1 2001/08/16 13:50:01 bfallenstein Exp $"; + static private void pa(String s) { System.out.println(s); } + /** Break the lines between the given addresses. + * @return An array: the first element is the line index the rendering + * starts on, and from the second element onwards the end points of the + * lines are given. + */ + public abstract int[] breakLines(LineInfo li); + + static private void test(LineBreaker b, String str, int cursor, + SimpleLineInfo.Layout l) { + SimpleLineInfo inf = new SimpleLineInfo(str, cursor, l); + int[] foo = b.breakLines(inf); + pa("Tested '"+str+"'"); + for(int i=0; i= cur && xc <= cur+lenn) { + p("Cursor was on this line"); + // We hit the cursor here. + if(line > l) { + // line greater -> move upwards. This is a maximum. + startmax = curstart; gotmax = true; + curstart -= (line - l); + } else if(line < l) { + // line smaller -> move down. This is a min. + startmin = curstart; gotmin = true; + curstart += (l - line); + } + if(line == l) ret = true; + } + res.addElement(new Integer(cur + lenn)); + line ++; + } + + if(gotmin && gotmax && startmax - startmin < 2) { + ret = true; + curstart = startmin; + } else { + if(gotmin && curstart <= startmin) { + curstart = startmin + 1; + } + if(gotmax && curstart >= startmax) { + curstart = startmax - 1; + } + } + + p("Ret: curstart = "+curstart); + + if(ret) { + int[] r = new int[res.size() + 1]; + r[0] = curstart; + for(int i=1; i 1000) { + p("Too wide"); + maxn = guessn; + li.split(x0, guessn, x0+(guessn*1000/res[0]), res); + p("Split res: "+guessn+" "+res[0]+" "+minn); + if(guessn == res[0] || minn == guessn) return best; + guessn = res[0]; + splitpen = res[1]; + } else { + p("Too narrow"); + minn = guessn; + li.split(x0+guessn, maxn-guessn, + x0+guessn+ + ((1000000/(res[0]+1) - 1000) * (maxn-guessn))/1000, + res); + res[0] += guessn; + if(guessn == res[0] || maxn == guessn) return best; + guessn = res[0]; + splitpen = res[1]; + } + if(minn >= maxn || guessn <= minn || guessn >= maxn) return best;; + } + } + + +} diff --git a/Java/media/SimpleLineInfo.java b/Java/media/SimpleLineInfo.java new file mode 100644 index 0000000..f5b01e2 --- /dev/null +++ b/Java/media/SimpleLineInfo.java @@ -0,0 +1,91 @@ +/* +SimpleLineInfo.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.io.*; +import java.awt.*; + +/** A simple implementation of LineInfo, for plain strings in a list + * of fonts. + */ + +public class SimpleLineInfo implements LineInfo { +public static final String rcsid = "$Id: SimpleLineInfo.java,v 1.8 2000/09/19 10:32:00 ajk Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + + public interface Layout { + FontMetrics getFontMetrics(int line); + int getWidth(int line); + int getCenterLine(); + } + + String s; + Layout l; + int cursor; + + SimpleLineInfo(String s, int cursor, Layout l) { this.s = s; this.l = l; + this.cursor = cursor;} + + public int getMax() { return s.length(); } + public int getCursor() { return cursor; } + public int getCenterLine() { return l.getCenterLine(); } + + public void split(int x0, int n, int sug, int[] ret) { + int ind = s.indexOf(' ', x0+1); + + if(ind >= x0+n || ind < 0) { + // split word + ind = 1; + ret[0] = 1; + ret[1] = 500; + } else { + while(true) { + int ind2 = s.indexOf(' ', ind+1); + if(ind2 < 0) break; + if(ind2 >= x0+n) break; + if(ind2 >= sug) break; + ind = ind2; + } + ret[0] = ind - x0; + ret[1] = 0; + } + p("Split: "+x0+" "+n+" "+sug+" "+ret[0]+" "+ret[1]); + } + + public void widthPenalty(int x0, int n, int line, int[] ret) { + p("WP: "+x0+" "+n+" "+line); + String subs = s.substring(x0, x0+n).trim(); + int w = l.getFontMetrics(line).stringWidth(subs); + int want = l.getWidth(line); + ret[0] = (1000*w) / want; + if(w > want) { + ret[1] = (w-want) * (w-want) / 3; + } else { + ret[1] = (want - w) / 2; + } + p("WP: "+x0+" "+n+" "+line+" "+want+" "+w+" Ret: "+ret[0]+" "+ret[1]); + } +} + + diff --git a/Java/media/SoundScroll.java b/Java/media/SoundScroll.java new file mode 100644 index 0000000..146f93b --- /dev/null +++ b/Java/media/SoundScroll.java @@ -0,0 +1,63 @@ +/* +SoundScroll.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.io.*; +import java.util.*; + +/** A scroll of sound. + * The fact that you need to specify the duraction when creating is not good but + * we can fix that later somehow. + */ +public class SoundScroll extends Scroll { +public static final String rcsid = "$Id: SoundScroll.java,v 1.3 2000/09/19 10:32:00 ajk Exp $"; + + // public abstract void preparePlayer(); + /** XXX change to play(Span) and get the next at runtime? + */ + protected SoundScroll(String i) { super(i); } + + Vector obses = new Vector(); + public void addObs(SoundObs o) { + obses.addElement(o); + } + protected void inform(int event, long l) { + for(int i = 0; i + * Spans are immutable, just like Strings: all the verb-like method + * like join and split return new Span objects. + */ + +public class Span { +public static final String rcsid = "$Id: Span.java,v 1.9 2001/03/11 19:14:38 veparkki Exp $"; + public static final boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + Address a1; + Address a2; + + public Address getStart() { return a1; } + public Address getEnd() { return a2; } + public long getStartOffs() { return a1.offset; } + public long getEndOffs() { return a2.offset; } + + public static Span parse(String str) { + StringTokenizer st = new StringTokenizer(str, ":"); + if(st.countTokens() != 2) + throw new ZZError("Wrong number of ':' toks in '"+str+"'"); + Span s = new Span(); + s.a1 = Address.parse(st.nextToken()); + s.a2 = Address.parse(st.nextToken()); + if(!s.a1.getStream().equals(s.a2.getStream())) + throw new ZZError("Must be same stream for now '" + str + +"' '"+s.a1.getStream()+"' '"+s.a2.getStream()+"'"); + return s; + } + + public static Span create(Address i1, Address i2) { + Span s = new Span(); + s.a1 = i1; s.a2 = i2; + return s; + } + + public String toString() { + return a1+":"+a2; + } + + public boolean overlaps(Span s) { + if(a2.lessThan(s.a1) || s.a2.lessThan(a1)) return false; + return true; + } + + /** The string pointed to by the span. + */ + public String getString(ZZCell c) { + Scroll scr //= c.getSpace().getStringScroll(a1.getStream()); + = Scroll.obtain((c==null?null:c.getSpace()), + a1.getStream()); + p("Scroll: "+scr); + if(scr instanceof StringScroll) { + StringScroll s = (StringScroll) scr; + int o1 = (int)a1.getOffs(); + int o2 = (int)a2.getOffs(); + if(o1 > o2) { + // This is allowed + if(o1-o2 == 1) return ""; + // This is not + throw new ZZError("Too negative span "+ this); + } + return s.getString(a1.getOffs(), + (int)(o2-o1)+1); + } if(scr instanceof ByteScroll) { + ByteScroll s = (ByteScroll)scr; + return s.getString(a1.getOffs(), + (int)(a2.getOffs()-a1.getOffs())+1); + } + if(scr instanceof CharScroll) { + CharScroll s = (CharScroll)scr; + return s.getString(a1.getOffs(), + (int)(a2.getOffs()-a1.getOffs())+1); + } + if(scr instanceof SoundScroll) { + return "SND " + toString(); + } + return "???"; + } + + public Span adjustEdge(int edge, long units) { + Address adj = (edge==0?a1:a2); + adj = Address.streamOffs(adj.getStream(), adj.getOffs()+units); + Address x = (edge==0?adj:a1); + Address y = (edge==1?adj:a2); + return create(x,y); + } + public Span[] adjustEdgeLocked(long units, Span other, long allowfudge) { + Address adj = a2; + adj = Address.streamOffs(adj.getStream(), adj.getOffs()+units); + long d = adj.getOffs() - other.a1.getOffs(); + if(d<0) d = -d; + if(d>allowfudge) + return new Span[] { + create(a1, adj), other + }; + return new Span[] { + create(a1, adj), + create(Address.streamOffs(adj.getStream(), adj.getOffs()+1), + other.a2) + }; + + } + public Span[] splitInHalf() { + long off = (a1.getOffs() + a2.getOffs()) / 2; + return new Span[] { + create(a1, Address.streamOffs(a1.getStream(), off-1)), + create(Address.streamOffs(a1.getStream(), off), a2), + }; + } + public Span join(Span next, long allowfudge) { + if(! a2.getStream().equals(next.a1.getStream())) + return null; + long diff = a2.getOffs() - next.a1.getOffs(); + if(diff<0) diff = -diff; + if(diff > allowfudge) + return null; + return create(a1, next.a2); + } + + /** Does exactly what substring does to String. + * This is in opposition to the other span routines + * in which the last address is given, not one beyond! + */ + public Span subSpan(int o1, int o2) { + return create(a1.addOffs(o1), a1.addOffs(o2-1)); + } + public Span subSpan(int o1) { + return create(a1.addOffs(o1), a2); + } + + /** Whether this span can be joined with the other span. + */ + public boolean isAppendable(Span s) { + return a2.getStream().equals(s.a1.getStream()) + && a2.getOffs() == s.a1.getOffs()-1; + } + + // XXX Check? + public Span append(Span s) { + return create(a1, s.a2); + } + + + public long length() { + return a2.getOffs() - a1.getOffs() + 1; + } + +} diff --git a/Java/media/SpanSet.java b/Java/media/SpanSet.java new file mode 100644 index 0000000..bc59749 --- /dev/null +++ b/Java/media/SpanSet.java @@ -0,0 +1,45 @@ +/* +SpanSet.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** An interface to Flobs that contain spans. This is more a Map than + * a Set... + * XXX Extend with links, i.e. one-level indirection between + * overlaps. + */ + +public interface SpanSet { +String rcsid = "$Id: SpanSet.java,v 1.4 2000/09/19 10:32:00 ajk Exp $"; + /** Add a span. + */ + void addSpan(Span s, Object obj); + /** Get the objects corresponding to the spans entered that overlap + * the given span. XXX Should be enumeration? + */ + Object[] overlaps(Span s); +} + + + diff --git a/Java/media/SpanTree.java b/Java/media/SpanTree.java new file mode 100644 index 0000000..6e9cf49 --- /dev/null +++ b/Java/media/SpanTree.java @@ -0,0 +1,54 @@ +/* +SpanTree.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.util.*; + +/** A structure for putting spans in and obtaining the + * matching spans. Not actually a tree yet XXX! + */ + +public class SpanTree implements SpanSet { +public static final String rcsid = "$Id: SpanTree.java,v 1.4 2000/09/19 10:32:00 ajk Exp $"; + Vector v = new Vector(); + Vector vo = new Vector(); + public void addSpan(Span s, Object uo) { + v.addElement(s); + vo.addElement(uo); + } + public Object[] overlaps(Span s) { + Vector res = new Vector(); + int ind = 0; + for(Enumeration e = v.elements(); e.hasMoreElements();) { + Span s0 = (Span)e.nextElement(); + if(s.overlaps(s0)) { + res.addElement(vo.elementAt(ind)); + } + ind++; + } + Object[] r = new Object[res.size()]; + for(int i=0; i nc.getText().length() - + (lookingDir > 0 ? 1 : 0)) { + o -= nc.getText().length(); + prev = nc; + nc = nc.s(dim); + } + if(nc == null) { + if(o != 0) + return false; + else { + nc = prev; + o = nc.getText().length(); + } + } + if(o < 0) + throw new ZZError("WHAT? WHAT? WHAT? Neg offset in move"); + curs.set(nc); curs.setOffs(o); + return true; + } + + /** Find a position along a stream with the given string. + * Currently relatively inefficient, unless the cells are relatively + * long. + */ + static public boolean find(ZZCursor from, String dim, int dir, + boolean includeThis, String text) { + // First, see if there is a match inside the current cell, + // done carefully. + ZZCell c = from.get(); + int offs = from.getOffs(); + + p("Find: "+c+" "+offs+" "+dim+" "+dir+" "+includeThis+" '"+text+"'"); + + String txt = c.getText(); + char first = text.charAt(0); + + if(!includeThis) offs += dir; + + if(dir > 0) { + while(c != null) { + while((offs = txt.indexOf(first, offs)) >= 0) { + if(isMatch(c, offs, text, dim, from)) + return true; + offs ++; + } + c = c.s(dim, dir); + if(c != null) { + txt = c.getText(); + offs = 0; + } + } + } else { + while(c != null) { + p("Findnegloop: "+c); + while((offs = txt.lastIndexOf(first, offs)) >= 0) { + p("Findnegloop: try "+ offs); + if(isMatch(c, offs, text, dim, from)) + return true; + offs --; + } + c = c.s(dim, dir); + if(c != null) { + txt = c.getText(); + offs = txt.length()-1; + } + } + } + + p("Not found!"); + + // Then, we're looking at whole cells the rest of the way. + return false; + } + + /** Check to see whether the text in the stream is equal to this text. + */ + static public boolean isMatch(ZZCell c, int offs, String text, String dim) { + return isMatch(c, offs, text, dim, null); + } + + /** Check whether the match is correct and set the cursor if it is. + */ + static boolean isMatch(ZZCell c, int offs, String text, + String dim, ZZCursor from) + { + p("Match: "+c+" "+offs+" '"+text+"' "+dim); + p("Matching csubstr: '"+c.getText().substring(offs)+"'"); + ZZCell origc = c; + int origoffs = offs; + while(c != null) { + String ct = c.getText().substring(offs); + if(ct.length() >= text.length()) { + if(ct.substring(0, text.length()).equals(text)) { + if(from != null) { + from.set(origc); + from.setOffs(origoffs); + } + p("TRUE!"); + return true; + } else return false; + } + if(!text.substring(0, ct.length()).equals(ct)) return false; + text = text.substring(ct.length()); + c = c.s(dim); + offs = 0; + } + return false; + } + + static public String getString(ZZCursor curs, String dim, int n) { + ZZCell c = curs.get(); + int offs = curs.getOffs(); + StringBuffer res = new StringBuffer(); + while(n > 0) { + String txt = c.getText(); + if(offs > 0) txt = txt.substring(offs); + if(n <= txt.length()) { + res.append(txt.substring(0, n)); + return res.toString(); + } + res.append(txt); + n -= txt.length(); + offs = 0; + c = c.s(dim); + if(c == null) return null; + } + return null; + } + + /** A class for moving along the stream, collecting characters. + * Part of the interface might be abstracted to an interface like + * java.text.CharacterIterator, but in a slightly more restricted subset. + *

    + * This class considers the end of the stream the location when it + * can't return any characters any more + 1. + */ + static public class Iterator { + final ZZCursorVirtual c; + final String dim; + + Iterator(ZZCursorVirtual c, String dim) { this.c = c; this.dim = dim; } + + public void set(ZZCursor c) { this.c.set(c); } + + /** Get the current iterator position. + * @return The current position. The position should not be modified. + */ + public ZZCursor get() { return c; } + + public boolean move(int nsteps) { + if(!Stream.move(c, dim, nsteps)) return false; + if(c.get().s(dim) == null) + // XXX Is this right? + if(c.get().getText().length() <= c.getOffs()) + return false; + return true; + } + + public boolean move(int nsteps, int lookingDir) { + if(!Stream.move(c, dim, nsteps, lookingDir)) return false; + if(c.get().s(dim) == null) + if(c.get().getText().length() <= c.getOffs()) + return false; + return true; + } + + public void start() { + c.set(c.get().h(dim)); + c.setOffs(0); + } + + public void end() { + ZZCell cl = c.get().h(dim, 1); + c.set(cl); + c.setOffs(cl.getText().length()); + } + + public void end(int dir) { + if(dir < 0) start(); else end(); + } + + public boolean find(int dir, boolean includeThis, String text) { + return Stream.find(c, dim, dir, includeThis, text); + } + + /** Get the current character. + * Returns -1 for the end-of-stream. + */ + public char getChar() { + return getChar(0); + } + + public char getChar(int offs) { + ZZCursorVirtual c1 = new ZZCursorVirtual(c); + // Move even if zero, to get the right + // directional position. + if(!Stream.move(c1, dim, offs, 1)) return (char)-1; + String str = c1.get().getText(); + if(c1.getOffs() >= str.length()) return (char)-1; + return str.charAt(c1.getOffs()); + } + + public String getString(int n, int dir) { + // SLOW!!!! + ZZCursorVirtual c1 = new ZZCursorVirtual(c); + if(dir < 0) { + if(!Stream.move(c1, dim, -n)) return null; + } + return Stream.getString(c1, dim, n); + } + } + + static public Iterator getIterator(ZZCursor c, String dim) { + return new Iterator(new ZZCursorVirtual(c), dim); + } + +} + + + + + + diff --git a/Java/media/StringScroll.java b/Java/media/StringScroll.java new file mode 100644 index 0000000..100713b --- /dev/null +++ b/Java/media/StringScroll.java @@ -0,0 +1,310 @@ +/* +StringScroll.java + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka, + * multiformat and UTF-8 format support by Antti-Juhani Kaijanaho + */ +package org.gzigzag; +import java.util.*; +import java.io.*; + +/** A scroll of chars. May later have holes etc. from expunging, + * but basically the point is that the address to content mapping + * is stable and will not change whatever is done. + * + * The new StringScroll format is based on UTF-8. After the initial + * signature described shortly, the scroll writable is a plain UTF-8 + * sequence. The whole StringScroll should be + * + * The signature of the new StringSroll format is the octet sequence + * given in the "signature" attribute. + */ +public class StringScroll extends Scroll{ +public static final String rcsid = "$Id: StringScroll.java,v 1.8 2001/02/09 08:30:54 ajk Exp $"; + + /** Number of characters in a new-format "record". Records are + * implicit in the actual file; they are explicit only in the + * in-memory index. */ + static int recordsize = 1000; + + private Writable f; + private boolean readonly; + + private interface SSImpl { + char[] get(long start, int n); + long curEnd(); + long append(char[] bytes); + } + + private SSImpl ss; + + private byte[] signature = new byte[]{ (byte) 0xef, (byte) 0xbb, (byte) 0xbf, + (byte) 0x20, (byte) 0x20, (byte) 0x5a, + (byte) 0x5a, (byte) 0x53, (byte) 0x53, + (byte) 0x2d, (byte) 0x30, (byte) 0x0a }; + + private synchronized void determineFormat() { + boolean newformat; + if (f.length() == 0) { + if (readonly) { + newformat = false; + } else { + f.write(0, signature); + newformat = true; + } + } else if (f.length() < signature.length) { + newformat = false; + } else { + byte[] sig = f.read(0, signature.length); + // assume it's new format; check signature and note it's + // old format if signature does not match + newformat = true; + for (int i = 0; i < sig.length; i++) { + if (sig[i] != signature[i]) { + newformat = false; + break; + } + } + } + if (newformat) ss = new UTF8Format(); else ss = new OldFormat(); + } + + public StringScroll(String id, Writable w, boolean ro) { + super(id); + this.readonly = ro; + f = w; + determineFormat(); + } + + /** Get an array of characters of length n starting from the + * startth (or so) character. */ + public synchronized char[] get(long start, int n) { + return ss.get(start, n); + } + + // XXX ENCODING - currently 2 bytes / char :( + public String getString(long start, int n) { + char[] b = get(start,n); + String s = new String(b); + // p("GETS: "+start+" "+n+" "+b+" '"+s+"'"); + return s; + } + + public long curEnd() { + return ss.curEnd(); + } + + public synchronized long append(String b) { + p("Append - length: "+b.length()); + return append(b.toCharArray()); + } + + public synchronized long append(char[] bytes) { + return ss.append(bytes); + } + + private class UTF8Format implements SSImpl { + /** A private copy of recordsize in order to avoid changing + the parent recordsize from messing up the index. */ + private int recordsize; + + /** We store in the index the offset - counting from the + writable's start - of each recordsize character so that + index[n] contains the offset of the character at the + address n*recordsize. */ + private Vector index; + + /** Cache the address to be given to the next appended character. */ + private long nextAddr; + + /** Put an offset for an address (which must be a multiple of + * recordsize) into the index. */ + private void putOffs(long addr, long offs) { + if (addr % recordsize != 0) { + throw new ZZError("Address is not a record boundary"); + } + + // FIXME: Vector can index only using int's. This is bad. + long idx = addr / recordsize; + if (idx > Integer.MAX_VALUE) { + throw new ZZError("Internal error: idx too big"); + } + + if (idx >= index.size()) index.setSize((int) idx + 1); + + index.setElementAt(new Long(offs), (int)idx); + + // sanity check + if (lookupOffs(addr) != offs) { + throw new ZZError("Internal error: index add failure"); + } + } + + /** Look offset up by address (must be a multiple of + * recordsize). */ + private long lookupOffs(long addr) { + if (addr % recordsize != 0) { + throw new ZZError("Address is not in index"); + } + + // FIXME: Vector can index only using int's. This is bad. + long idx = addr / recordsize; + if (idx > Integer.MAX_VALUE) { + throw new ZZError("Internal error: idx too big"); + } + + return ((Long) index.elementAt((int) idx)).longValue(); + } + + public UTF8Format() { + index = new Vector(); + recordsize = StringScroll.this.recordsize; + + // Build the index by scanning the whole scroll + long offs = signature.length; + long addr = 0; + while (offs < f.length()) { + UTF8Char uc = new UTF8Char(f, offs); + + if (addr % recordsize == 0) { + putOffs(addr, offs); + } + + ++addr; + offs += uc.b.length; + } + nextAddr = addr; + } + + // Implementation of SSImpl + + public char[] get(long start, int n) { + char[] rv = new char[n]; + + int acc = 0; + // The loop body will read at most n characters starting + // from address start+acc by slurping the whole record and + // scanning there. The body is run repeatedly until we + // have exactly n characters in rv. + while (acc < n) { + // Step 1: Read the current record completely into memory + long recstart = (start + acc) - (start + acc) % recordsize; + long recoffs = lookupOffs(recstart); + byte[] record = f.read(recoffs, recordsize); + // Step 2: Scan the record for the start address + long sad = recstart; + long sof = 0; + while (sof < record.length) { + if (sad == start + acc) break; + UTF8Char uc = new UTF8Char(record, (int) sof); + sof += uc.b.length; + sad++; + } + // Step 3: Convert at most n bytes and at most to the + // end of the record from record[sad] into rv, using acc as + // the rv index. + for (int i = (int) sof; i < record.length;) { + if (acc == n) break; + UTF8Char uc = new UTF8Char(record, i); + rv[acc++] = uc.c; + i += uc.b.length; + } + } + + return rv; + } + + public long curEnd() { + return nextAddr; + } + + public long append(char[] chs) { + // We want to avoid doing unnecessary writes. Therefore, + // we first build an array of UTF-8 characters. Then we + // flatten it into an onedimensional array containing the + // UTF-8 representations in a row and write that. + UTF8Char[] ucs = new UTF8Char[chs.length]; + + long rv = nextAddr; + + int len = 0; + for (int i = 0; i < chs.length; i++) { + ucs[i] = new UTF8Char(chs[i]); + len += ucs[i].b.length; + } + + byte[] block = new byte[len]; + int bi = 0; + for (int i = 0; i < ucs.length; i++) { + // Update index + if ((nextAddr + i) % recordsize == 0) { + putOffs(nextAddr + i, f.length() + bi); + } + // Copy UTF-8 octets to block. + for (int j = 0; j < ucs[i].b.length; j++) { + block[bi++] = ucs[i].b[j]; + } + } + f.write(f.length(), block); + nextAddr += ucs.length; + + if (nextAddr - nextAddr % recordsize + != (index.size() - 1) * recordsize) { + throw new ZZError("Internal error: index not consistent"); + } + return rv; + } + + } + + private class OldFormat implements SSImpl { + public synchronized char[] get(long start, int n) { + byte[] b = f.read(start*2, n*2); + char[] c = new char[n]; + for(int i=0; i> 8) & 0xff); + byt[i*2+1] = (byte)((bytes[i] >> 0) & 0xff); + } + + // XXX race? + long c = f.length(); + if(c%1 != 0) throw new Error("Argh! Odd number of bytes"); + f.write(c, byt); + + return c / 2; + } + } +} + + + diff --git a/Java/media/TestLines.java b/Java/media/TestLines.java new file mode 100644 index 0000000..62e359b --- /dev/null +++ b/Java/media/TestLines.java @@ -0,0 +1,189 @@ +/* +TestLines.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.io.*; +import java.awt.*; + +/** Some tests for line breaking. + */ + +public class TestLines { +public static final String rcsid = "$Id: TestLines.java,v 1.10 2001/02/23 15:01:10 tjl Exp $"; + static final boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + + Frame f = new Frame(); + +/* Jikes won't eat this any more in new versions due to äö. + static final String str = "Pikku stringi testataksemme rivinpilkkomista. "+ +"Tällä kertaa kirjoitammekin sen suomeksi - englanninkielisiä lukijoitamme "+ +"varmaankin hämmästyttää. Etenkin ääkköset. Tämä merkkijono piirretään "+ +"näytölle monta kertaa erilaisena, siis \"kursori\" eri kohdalle laitettuna. "+ +"Tästä voidaan sitten nähdä, toimiiko rivien pilkkominen palasiksi oikein. " + +"Itse asiassa merkkijonoa tulee vielä jonkin verran pidentää koska muuten " + +"emme ehdi nähdä kaikkia efektejä. Hauskaahan tästä tulee vasta sitten " + +"kun voimme oikeasti muokata näin näytettyä tekstiä mutta tämä testi on " + +"tärkeä askel siihen suuntaan mentäessä." +; + +*/ + + static final String str = "lsjifs lefjis elfj sef jsle fjslf "; + + class MyLayout implements SimpleLineInfo.Layout { + int c; + MyLayout(int c) { this.c = c; } + public FontMetrics getFontMetrics(int line) { + return fm[find(c, line)]; + } + public int getWidth(int line) { + return width(c, line); + } + public int getCenterLine() { return 0; } + + } + + public static void main(String[] argv) { + TestLines t = new TestLines(); + t.br(); + } + + int NTESTS = 1; + + int[][] lines = new int[NTESTS][]; + Font[] fonts = new Font[64]; + FontMetrics[] fm = new FontMetrics[fonts.length]; + { for(int i=0; i 400) w = 400; + return w; + } else if(cas == 1) { + int w =300 - 20 * line; + if(w < 50) return 50; + return w; + } else if(cas == 2) { + return (int)(100 + 200.0 / (1 + (line * line)/40.0)); + } + return -1; + } + + int curs = 0; + int dir = 1; + +public TestLines() { +} + +public void br() { + + + Component cp; + f.add( + cp= new Component() { + Image cache; + public void paint(Graphics g0) { + Thread.dumpStack(); + if(lines == null) return; + if(cache==null) { + cache = createImage(800,800); + } + Graphics g = cache.getGraphics(); + g.setColor(getBackground()); + g.fillRect(0, 0, 800, 800); + for(int set = 0; set < lines.length; set++) { + if(lines[set] == null) return; + int cur = 0; + int x = 20 + 400 * set; + int y = 100; + int line = lines[set][0]; + for(int i=0; i= cur && curs < lines[set][i+1]) { + // Trim is wrong :( + int cw = metr.stringWidth(str.substring(cur, curs).trim()); + g.setColor(Color.blue); + g.drawLine(x+cw, y-metr.getAscent(), + x+cw, y+metr.getDescent()); + } + + g.setColor(Color.red); + g.drawLine(x+width(cas, line), y-metr.getAscent(), + x+width(cas,line), y+metr.getDescent()); + cur = lines[set][i+1]; + y += metr.getDescent(); + line ++; + } + } + g0.drawImage(cache, 0, 0, null); + } + }); + f.setSize(800,800); + + SimpleLineBreaker slb = new SimpleLineBreaker(); + f.show(); + + while(true) { + for(int i=0; i= str.length()-5) dir = -dir; + } + } +} +} diff --git a/Java/media/UTF8Char.java b/Java/media/UTF8Char.java new file mode 100644 index 0000000..cf23a7b --- /dev/null +++ b/Java/media/UTF8Char.java @@ -0,0 +1,245 @@ +/* +UTF8Char.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ +package org.gzigzag; + +import java.io.*; + +public class UTF8Char { +public static final String rcsid = "$Id: UTF8Char.java,v 1.3 2001/03/21 10:01:21 ajk Exp $"; + + public char c; + public byte[] b; + + /* UTF-8 <-> Java char conversion is table-driven. This code is + * adapted from CatDVI. */ + + private static class ConvOctet { + /** The number of variable bits, 1-8 */ + public int numbits; + /** The template for this octet */ + public byte octet; + + public ConvOctet(int n, byte o) { + numbits = n; + octet = o; + } + + public ConvOctet(int n, int o) { + this(n, (byte) o); + } + } + + private static class ConvEntry { + /** Maximum UCS-4 value encodable using this entry. */ + public char maxval; + /** Info on each octet. */ + ConvOctet[] template; + + public ConvEntry(char maxval, ConvOctet[] template) { + this.maxval = maxval; + this.template = template; + } + + public ConvEntry(int maxval, ConvOctet[] template) { + this((char) maxval, template); + } + + public final int len() { return template.length; } + } + + private static final ConvEntry[] convtbl = + new ConvEntry[] { + new ConvEntry (0x7f, + new ConvOctet[] { + new ConvOctet(7, 0) + }), + new ConvEntry (0x7ff, + new ConvOctet[] { + new ConvOctet(5, 0xc0), + new ConvOctet(6, 0x80) + }), + new ConvEntry (0xffff, + new ConvOctet[] { + new ConvOctet(4, 0xe0), + new ConvOctet(6, 0x80), + new ConvOctet(6, 0x80) + }), + new ConvEntry (0x1fffff, + new ConvOctet[] { + new ConvOctet(3, 0xf0), + new ConvOctet(6, 0x80), + new ConvOctet(6, 0x80), + new ConvOctet(6, 0x80) + }), + new ConvEntry (0x3ffffff, + new ConvOctet[] { + new ConvOctet(2, 0xf4), + new ConvOctet(6, 0x80), + new ConvOctet(6, 0x80), + new ConvOctet(6, 0x80), + new ConvOctet(6, 0x80) + }), + new ConvEntry (0x7fffffff, + new ConvOctet[] { + new ConvOctet(1, 0xfc), + new ConvOctet(6, 0x80), + new ConvOctet(6, 0x80), + new ConvOctet(6, 0x80), + new ConvOctet(6, 0x80), + new ConvOctet(6, 0x80), + }) + }; + + /** Convert a Java char into an UTF-8 octet stream. */ + public static byte[] charToUTF8(char c) { + // Stage 1: Determine which ConvEntry to use. We use the + // maxval attribute for this: the ConvEntry with smallest + // maxval where the char fits is used. + ConvEntry e = null; + for (int i = 0; i < convtbl.length; i++) { + if (c <= convtbl[i].maxval) { + e = convtbl[i]; + break; + } + } + if (e == null) throw new ZZError("character has no UTF-8 representation"); + + // Stage 2: Do the conversion from right to left. + byte[] rv = new byte[e.len()]; + for (int i = rv.length - 1; i >= 0; --i) { + /* At each iteration we first apply the initial bit + pattern and then patch the rest with the indicated + number of lower-order bits in code. When we are done, + we shift these out. */ + int numbits = e.template[i].numbits; + rv[i] = e.template[i].octet; + rv[i] |= ((1 << numbits) - 1) & c; + c = (char) (c >> numbits); + } + return rv; + } + + private static class UTF8ToCharRV { + public char c; + public int len; + public UTF8ToCharRV(char c, int len) { + this.c = c; + this.len = len; + } + } + + public static class InvalidChar extends ZZError { + public InvalidChar(String s) { super(s); } + } + + /** Determine the ConvEntry to be used. We determine this + using the first octet's template. */ + private static ConvEntry UTF8ConvEntry(byte o) { + for (int i = 0; i < convtbl.length; i++) { + byte b = (byte) (o & ~((1 << convtbl[i].template[0].numbits) - 1)); + if (convtbl[i].template[0].octet == b) { + return convtbl[i]; + } + } + return null; + } + /** Find out the length of an UTF-8 sequence based on the first + * octet. */ + public static int UTF8Len(byte o) { + ConvEntry e = UTF8ConvEntry(o); + if (e == null) throw new InvalidChar("this is no UTF-8 character"); + return e.len(); + } + + private static UTF8ToCharRV UTF8ToChar(byte[] array, int start) { + ConvEntry e = UTF8ConvEntry(array[start]); + if (e == null) return null; + + // Decode the octet stram. + char rv = 0; + for (int i = 0; i < e.template.length; i++) { + byte mask = (byte) ((1 << e.template[i].numbits) - 1); + byte fixed = (byte) (array[start + i] & ~mask); + byte bits = (byte) (array[start + i] & mask); + if (fixed != e.template[i].octet) throw new ZZError("Invalid UTF-8 character"); + rv = (char) ((rv << e.template[i].numbits) | bits); + } + return new UTF8ToCharRV(rv, e.template.length); + } + + private static void init(UTF8Char c, UTF8ToCharRV r, byte[] a, int start) { + if (r == null) throw new InvalidChar("Invalid UTF-8 character"); + c.c = r.c; + c.b = new byte[r.len]; + for (int i = 0; i < c.b.length; i++) { + byte b = a[start + i]; + c.b[i] = b; + } + } + + private UTF8Char(UTF8ToCharRV r, byte[] a, int start) { + init(this, r, a, start); + } + + public UTF8Char tryFromUTF8(byte[] a, int start) { + UTF8ToCharRV r = UTF8ToChar(a, start); + if (r == null) return null; + return new UTF8Char(r, a, start); + } + + /** Create an UTF-8 char from the byte stream (bytes after the + * character are ignored). You can determine how many bytes was + * used by invoking UTF8Len on the created object. */ + public UTF8Char(byte[] a) { this(a, 0); } + public UTF8Char(byte[] a, int start) { + init(this, UTF8ToChar(a, start), a, start); + } + + public UTF8Char(char c) { + this.c = c; + b = charToUTF8(c); + } + + public UTF8Char(Writable w, long offs) { + long len = (w.length() - offs < 6) ? w.length() - offs : 6; + byte[] a = w.read(offs, (int)len); + init(this, UTF8ToChar(a, 0), a, 0); + } + + static public void main(String argv[]) { + FileWritable fw; + try { + RandomAccessFile raf = new RandomAccessFile("test.utf8", "rw"); + fw = new FileWritable(raf); + } catch (IOException e) { + throw new ZZError("" + e); + } + + long offs = 0; + while (offs < fw.length()) { + UTF8Char uc = new UTF8Char(fw, offs); + System.out.println("H: " + (long) uc.c); + offs += uc.b.length; + } + + } +} + diff --git a/Java/media/VStream.java b/Java/media/VStream.java new file mode 100644 index 0000000..5e913e8 --- /dev/null +++ b/Java/media/VStream.java @@ -0,0 +1,655 @@ +/* +VStream.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** Utility functions for vstreams. + * NOTE! USE THE VirtualCursor OBJECTS ONLY SHORT-TERM, put stuff + * in the structure + * for longer term. + * ANY call to VStream.* routines invalidates all VirtualCursor objects pointing + * to that vstream. + *

    + * TODO: d.markup, active references to parts of another vstream + * (via including complete vstream objects!) + *

    + * The vstream format is simple: the headcell on d.2 is a dummy cell + * that is never moved (so that it remains easy to refer to the vstream). + * Note that cells with the span length of 0 (i.e. end less than start) + * are explicitly ALLOWED. + *

    + * Important policy decision pending: what to do about non-span cells + * in vstreams? + *

    + * In addition to pointers, we'll probably need spans (of vstream) to complement + * them, for formatting etc. + * @deprecated This is a bit old now - see e.g. Nile and Stream.java. + */ + +public class VStream { +public static final String rcsid = "$Id: VStream.java,v 1.28 2000/11/24 16:24:21 tjl Exp $"; + + public static final boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + + static String dim = "d.2"; + static public class Rend { + public Span[] spans; + public String[] strs; + public ZZCell[] cells; + public int[][] marks; + public ZZCell[][] markcells; + } + + static public final void assertOffs(ZZCursor c) { + if(c.getOffs() == c.NO_OFFSET) + throw new ZZError("Need cursor offset"); + } + + static public ZZCursorVirtual add(ZZCursor vc, int o) { + assertOffs(vc); + + ZZCell c = vc.get(); + o += vc.getOffs(); + + // XXX Do we need to enforce spans? + while(o < 0) { + c = c.s(dim, -1); + if(c == null || c.getSpan() == null) return null; + o += (int)c.getSpan().length(); + } + while(o > c.getSpan().length()) { + o -= (int)c.getSpan().length(); + c = c.s(dim, 1); + if(c == null || c.getSpan() == null) return null; + } + return new ZZCursorVirtual(c, o); + } + + static public String error(ZZCell c) { + ZZCell s = c.h(dim, -1); + if(s.getSpan() != null) return "First cell has span"; + while((s=s.s(dim, 1))!=null) { + if(s.getSpan() == null) + return "No span in cell!"; + } + return null; + } + static public void check(ZZCell c) { + if(!dbg) return; + String e = error(c); + System.out.println("VSTREAM DUMP"); + for(ZZCell s = c.h(dim, -1); s != null; + s = s.s(dim, 1)) { + System.out.println("'"+s.getText()+"' from span: "+s.getSpan()); + } + if(e == null) return; + throw new ZZError("VStream error in stream! '"+e+"' dumped"); + } + + // The first cell is the second of the rank. + static public ZZCursor start(ZZCell c) { + c = c.h(dim, -1).s(dim, 1); + if(c==null) return null; + return new ZZCursorVirtual(c, 0); + } + static public ZZCursor end(ZZCell c) { + c = c.h(dim, 1); + return new ZZCursorVirtual(c, c.getText().length()); + } + + static public void create(ZZCell c, String dim, int dir, Span s) { + ZZCell n = c.N(dim, dir).N("d.2", 1); + if(s != null) + n.setSpan(s); + } + /** Find the first instance of the given character + * that occurs at position p or after. + */ + static public ZZCursor findChar(char c, ZZCursor p) { + assertOffs(p); + + String s = p.get().getText(); + int io = s.indexOf(c, p.getOffs()); + if(io != -1) return new ZZCursorVirtual(p.get(), io); + ZZCell cur = p.get(); + while((cur = cur.s(dim, 1))!=null) { + io = cur.getText().indexOf(c); + if(io != -1) return new ZZCursorVirtual(cur, io); + } + return null; + } + /** Return the string between two positions, inclusive. + */ + static public String getStr(ZZCursor p1, ZZCursor p2) { + p("getStr: "+p1+" "+p2); + assertOffs(p1); assertOffs(p2); + + StringBuffer s = new StringBuffer(); + if(p1.get() == p2.get()) { + return p1.get().getText().substring(p1.getOffs(), p2.getOffs()+1); + } + s.append(p1.get().getText().substring(p1.getOffs())); + ZZCell c = p1.get(); + while((c=c.s(dim,1)) != null && c != p2.get()) { + s.append(c.getText()); + } + if(c!=null) { + String str = c.getText(); + // Have to check whether one past end or end + if(str.length() > p2.getOffs()) + s.append(str.substring(0, p2.getOffs()+1)); + else + s.append(str); + } + return s.toString(); + } + // XXX Join the next two methods + static public Span[] getSpans(ZZCursor p1, ZZCursor p2) { + Vector sp = new Vector(); + p("getspans: "+p1+" "+p2+" "+p1.get()+" "+p2.get()); + p("getspans1: "+p1.get().getText()); + p("getspans2: "+p1.get().getSpan()); + p("getspans3: "+p1.get().getSpan().subSpan(p1.getOffs())); + if(p1.get() == p2.get()) { + sp.addElement( + p1.get().getSpan().subSpan(p1.getOffs(), p2.getOffs()+1) + ); + } else { + sp.addElement( + p1.get().getSpan().subSpan(p1.getOffs()) + ); + ZZCell c = p1.get(); + while((c=c.s(dim,1)) != null && c != p2.get()) { + sp.addElement(c.getSpan()); + } + if(c!=null) + sp.addElement(c.getSpan().subSpan(0, p2.getOffs()+1)); + } + Span[] ret = new Span[sp.size()]; + for(int i=0; i= o1) && (o2<0 || i <= o2)) { + if(res==null) res = new Vector(); + res.addElement(new Integer(i-o1)); + res.addElement(c); + } + } catch(NumberFormatException e) { + // Nothin' + } + } + if(res!=null) { + int[] r = new int[res.size()/2]; + ZZCell[] rc = new ZZCell[res.size()]; + for(int i=0 ;i= offs0) && + (offs1 < -1 || of <= offs1)) { + rnk[i].setText(""+(of-offs0+noffs)); + r.insert("d.cursor", 1, rnk[i]); + } + } catch(NumberFormatException e) { + // Nothin' + } + } + + } + + /** Split a VStream at position, return the cell just BEFORE the + * split. XXX MAYBE ALL VSTREAMS SHOULD HAVE EMPTY CELL AT BEGINNING AND + * END. + */ + static private ZZCell splitAt(ZZCursor p) { + // If offs == 0, need to do nothing. + if(p.getOffs() == 0) return p.get().s(dim, -1); + + Span cur = p.get().getSpan(); + if(p.getOffs() == cur.length()) return p.get(); + // In the middle -> split and reposition cursors. + ZZCell n1 = p.get().N(dim, 1); + n1.setSpan(cur.subSpan(p.getOffs())); + p.get().setSpan(cur.subSpan(0, p.getOffs())); + + ZZCell[] rnk = p.get().readRank("d.cursor", 1, false); + for(int i=0; i= p.getOffs()) { + int nof = of-p.getOffs(); + rnk[i].setText(""+nof); + n1.insert("d.cursor", 1, rnk[i]); + } + } catch(NumberFormatException e) { + // Nothin' + } + } + return p.get(); + } + + /** Insert a cut mark at the given position. + */ + static public void cut(ZZCursor p) { + ZZCell prev = splitAt(p); + ZZCell n = prev.s(dim, 1); + n.disconnect("d.cut", 1); + + n.connect("d.cut", 1, n); + } + /** Clear the cuts in the given vstream. + */ + static public void clearcuts(ZZCursor p) { + if ( p == null ) return ; + for(ZZCell c = p.get().h(dim, -1); c!=null; + c = c.s(dim, 1)) + if(c.s("d.cut", 1) != null) + c.disconnect("d.cut", 1); + } + + static ZZCell findPrevCut(ZZCursor p) { + ZZCell prev; + for(prev=p.get(); prev != null && prev.s("d.cut", 1) == null; + prev = prev.s(dim, -1)); + return prev; + } + static ZZCell findNextCut(ZZCursor p) { + ZZCell next; + for(next=p.get().s(dim, 1); next != null && + next.s("d.cut", 1) == null; + next = next.s(dim, 1)); + return next; + } + + /** Create a new vstream between the given cut marks. + * XXX This is difficult since Pos doesn't have the forwards-backwards + * info - Swing positions do. This should probably be added... + * Imagine cutting apart at single character edges... + */ + static public ZZCell separate(ZZCursor p) { + ZZCell prev = findPrevCut(p); + ZZCell next = findNextCut(p); + ZZCell tmp; + // based on their nullness, find the section to cut. + if(prev == null && next == null) return null; // nothing. + if(prev == null) { + next.disconnect("d.cut", 1); + next.disconnect(dim, -1); + tmp = p.get().h(dim, -1); + tmp.disconnect(dim, 1); + tmp.connect(dim, 1, next); + return p.get().h(dim, -1).N(dim, -1); + } else { + if(next != null){ + //prev.s(dim, -1).connect(dim, 1, next); + next.disconnect(dim, -1); + tmp = prev.s(dim, -1); + tmp.disconnect(dim, 1); + tmp.connect(dim, 1, next); + } + prev.disconnect(dim, -1); + prev.disconnect("d.cut", 1); + return prev.N(dim, -1); + } + // return null; + } + + /** Copy the part of the vstream between the nearest cut marks + * into a new vstream. + */ + static public ZZCell separateCopy(ZZCursor p) { + ZZCell nhead = p.get().N("d.tmp",1); + nhead.excise("d.tmp"); + ZZCell prev = findPrevCut(p); + ZZCell next = findNextCut(p); + if(prev == null) prev = p.get().h(dim, -1).s(dim, 1); + ZZCell n = nhead; + for(ZZCell c = prev; c != null && c != next; c=c.s(dim, 1)) { + n = n.N(dim, 1); + n.setSpan(c.getSpan()); + } + return nhead; + } + + + /** Insert the given span. + * Cursors at the insertion point will be moved to AFTER the + * insertion. XXX Here's something where more flexibility + * is needed: does a cursor point forwards or backwards? + */ + static public void insert(ZZCursor p, Span s) { + ZZCell prev = splitAt(p); + + Span cur = prev.getSpan(); + if(prev.getSpan() != null && prev.getSpan().isAppendable(s)) { + int len = (int)prev.getSpan().length(); + moveCurs(prev, len, len, prev, (int)(len+s.length())); + prev.setSpan(prev.getSpan().append(s)); + return; + } + ZZCell n = prev.N(dim, 1); + n.setSpan(s); + + moveCurs(p.get(), p.getOffs(), p.getOffs(), n, 1); + } + + /** Assimilate a whole vstream in insertion. + * Also places cuts at the beginning and the end of the result... + * XXX should it just return the POSes? + * XXX Delete the empty cells at ends... + */ + static public void assimilate(ZZCursor p, ZZCell vstream) { + ZZCell prev = splitAt(p); + ZZCell next = prev.s(dim, 1); + ZZCell firstof = vstream.h(dim, -1).s(dim, 1); + ZZCell tail = firstof.h(dim, 1); + prev.disconnect(dim, 1); + firstof.disconnect(dim, -1); + prev.connect(dim, 1, firstof); + firstof.connect("d.cut", 1, firstof); + if(next != null) { + next.disconnect("d.cut", 1); + next.connect("d.cut", 1, next); + next.connect(dim, -1, tail); + } + } + + /** A convenience function: delete one character prior to p0. + */ + static public void backspace(ZZCursor p0) { + // while and not if: there might be null-length + // spans in there... + while(p0.getOffs() == 0) { + ZZCell c = p0.get().s(dim, -1); + if(c == null || c.getSpan() == null || c.getSpan().length() == 0) + return; + p0 = new ZZCursorVirtual(c, (int)c.getSpan().length()); + } + // Split if needed + if(p0.getOffs() != p0.get().getSpan().length()) { + ZZCell prev = splitAt(p0); + p0.set(prev); + } + // Now we know p0.offs == p0.get().getSpan().length()... + int l = (int)(p0.get().getSpan().length()); + if(l==1) { + // move cursors and delete cell + // XXX AUGH! Must move EITHER forwards or backwards, + // depending on which one is there... + ZZCell to = p0.get().s(dim, 1); int offs = 0; + if(to==null) { + to = p0.get().s(dim, -1); + offs = (int)to.getSpan().length(); + } + // Ouch... + moveCurs(p0.get(), 0, 0, to, offs); + moveCurs(p0.get(), 1, 1, to, offs); + p0.get().delete(); + return; + } + p0.get().setSpan(p0.get().getSpan().subSpan(0, l-1)); + moveCurs(p0.get(), l, l, p0.get(), l-1); + } + + + // XXX Maybe too heavy - always creates new cells. + // untested. + static public void delete(ZZCursor p0, ZZCursor p1) { + ZZCell[] rnk; + if(p0.get() == p1.get()) { + ZZCell n = p0.get().N(dim, 1); + p0.get().setSpan(p0.get().getSpan().subSpan(0, p0.getOffs())); + n.setSpan(p0.get().getSpan().subSpan(p1.getOffs()+1)); + // Then, redo cursors + rnk = p0.get().readRank("d.cursor", 1, false); + for(int i=0; i p1.getOffs()) { + int nof = of-p1.getOffs()-1; + rnk[i].setText(""+nof); + n.insert("d.cursor", 1, rnk[i]); + } else if(of >= p0.getOffs()) { + rnk[i].setText(""+p0.getOffs()); + } + } catch(NumberFormatException e) { + // Nothin' + } + } + } else { + // 1. first cell's span & cursors + p0.get().setSpan(p0.get().getSpan().subSpan(0, p0.getOffs())); + rnk = p0.get().readRank("d.cursor", 1, false); + for(int i=0; i= p0.getOffs()) { + rnk[i].setText(""+p0.getOffs()); + } + } catch(NumberFormatException e) { + // Nothin' + } + } + // Do the cells until we get to the second cell. + ZZCell c = p0.get(); + while((c = c.s(dim, 1)) != null && c != p1.get()) { + rnk = c.readRank("d.cursor", 1, false); + for(int i=0; i p1.getOffs()) { + int nof = of-p1.getOffs()-1; + rnk[i].setText(""+nof); + } else { + p0.get().insert("d.cursor", 1, rnk[i]); + rnk[i].setText(""+p0.getOffs()); + } + } catch(NumberFormatException e) { + // Nothin' + } + } + + } + } + /** Given a blank cell, set that cell's span and add extra + * cells as necessary to copy the span between p0 and p1. + */ + static public void copyNew(ZZCursor p0, ZZCursor p1, ZZCell blank) { + if(p0.get()==p1.get()) { + blank.setSpan(p0.get().getSpan().subSpan(p0.getOffs(), p1.getOffs()+1)); + } else { + // First cell + blank.setSpan(p0.get().getSpan().subSpan(p0.getOffs())); + // middle cells + ZZCell c = p0.get(); + ZZCell n = blank; + while((c = c.s(dim, 1)) != null && c != p1.get()) { + n = n.N("dim", 1); + n.setSpan(c.getSpan()); + } + // Last cell + if(c==null) return; + n = n.N("dim", 1); + n.setSpan(p1.get().getSpan().subSpan(0, p1.getOffs()+1)); + } + } +} + + + diff --git a/Java/media/ZZDefaultText.java b/Java/media/ZZDefaultText.java new file mode 100644 index 0000000..8773d2f --- /dev/null +++ b/Java/media/ZZDefaultText.java @@ -0,0 +1,100 @@ +/* +ZZDefaultText.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.awt.*; + +/** A simple implementation of ZZText. + */ + +public class ZZDefaultText extends ZZText { +String rcsid = "$Id: ZZDefaultText.java,v 1.2 2000/10/19 17:04:26 tjl Exp $"; + + public String getText(ZZCell c) { + return c.getText(); + } + + public void setText(ZZCell c, String s) { + c.disconnect("d.reftext", 1); + // XXX Delete all cells there too? + c.setText(s); + } + + public boolean isRef(ZZCell c) { + return c.s("d.reftext") != null; + } + + public void delete(ZZCell c, int start) { + // XXX faster + delete(c, start, getText(c).length()); + } + + public void delete(ZZCell c, int start, int end) { + if(isRef(c)) { + } else { + } + } + + public void insertNewRef(ZZCell c, String txt, int offs) { + ensureRef(c); + } + + public void insertRef(ZZCell c, Span sp, int offs) { + ensureRef(c); + } + + public Span[] getSpans(ZZCell c) { + LoopDetector ld = new LoopDetector(); + ZZCell v = c.s("d.reftext"); + return null; + } + public Span[] getSpans(ZZCell c, int start) { + LoopDetector ld = new LoopDetector(); + ZZCell v = c.s("d.reftext"); + return null; + } + public Span[] getSpans(ZZCell c, int start, int end) { + LoopDetector ld = new LoopDetector(); + ZZCell v = c.s("d.reftext"); + return null; + } + public void setSpans(ZZCell c, Span[] spans) { + } + + + Span makeSpan(ZZCell c, String s) { + StringScroll sc = c.getSpace().getStringScroll(); + long offs = sc.append(s); + return Span.create(Address.scrollOffs(sc, offs), + Address.scrollOffs(sc, offs+s.length()-1)); + } + + void ensureRef(ZZCell c) { + if(c.s("d.reftext") == null) { + Span sp = makeSpan(c, getText(c)); + ZZCell n = c.N("d.reftext", 1); + n.setSpan(sp); + } + } + +} + diff --git a/Java/media/ZZHumber.java b/Java/media/ZZHumber.java new file mode 100644 index 0000000..a29061c --- /dev/null +++ b/Java/media/ZZHumber.java @@ -0,0 +1,57 @@ +/* +ZZCellScroll.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; + +import java.io.*; + +/** A package for representing, reading and writing huge numbers. + * Humbers are described in Ted Nelson's Literary Machines. + * The ZZHumber objects are immutable, like the Java String class. + * XXX Not yet working + */ + +// Immutable +public class ZZHumber { +public static final String rcsid = "$Id: ZZHumber.java,v 1.3 2000/09/19 10:32:00 ajk Exp $"; + byte[] bytes; // The raw humber bytes. + public boolean equals(Object o) { + ZZHumber h = (ZZHumber) o; + if(h.bytes.length != bytes.length) return false; + for(int i=0; i + * Calling this function on a cell that only has text content + * makes the whole + * current text content referential as well. + */ + public abstract void insertNewRef(ZZCell c, String txt, int offs); + + /** Insert a referential span of text. + *

    + * Calling this function on a cell that only has text content + * makes the whole + * current text content referential as well. + */ + public abstract void insertRef(ZZCell c, Span sp, int offs); + + /** Obtain the referential contents of this cell. + * @return List of spans, or null if not referential. + */ + public abstract Span[] getSpans(ZZCell c); + public abstract Span[] getSpans(ZZCell c, int start); + public abstract Span[] getSpans(ZZCell c, int start, int end); + + /** Set the spans of the cell to the given spans. + */ + public abstract void setSpans(ZZCell c, Span[] spans); + + +} diff --git a/Java/mungencss.pl b/Java/mungencss.pl new file mode 100644 index 0000000..1bec803 --- /dev/null +++ b/Java/mungencss.pl @@ -0,0 +1,9 @@ +#!/usr/bin/perl -n + +# Don't include automatically generated subs +/\.readParams\b/ and next LINE; + +# Don't include Recs.java: both autogenerated and deprecated. +/\bRecs\b/ and next LINE; + +print; diff --git a/Java/net/Peer.java b/Java/net/Peer.java new file mode 100644 index 0000000..b37926d --- /dev/null +++ b/Java/net/Peer.java @@ -0,0 +1,61 @@ +/* +Peer.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* Written by Antti-Juhani Kaijanaho */ + +package org.gzigzag.net; + +import java.net.*; + +/** A networking peer: a pair (host, port). This is used by the + * reliable UDP scheme. */ +public final class Peer { + + private InetAddress host; + private int port; + + public Peer(InetAddress host, int port) { + this.host = host; + this.port = port; + } + + public InetAddress getHost() { + return host; + } + + public int getPort() { + return port; + } + + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof Peer)) return false; + + Peer p = (Peer)o; + + return host.equals(p.host) && port == p.port; + } + + public int hashCode() { + return host.hashCode() ^ port; + } + + public String toString() { + return host.toString() + ":" + port; + } + +} diff --git a/Java/net/ReliableUDPMessage.java b/Java/net/ReliableUDPMessage.java new file mode 100644 index 0000000..af39604 --- /dev/null +++ b/Java/net/ReliableUDPMessage.java @@ -0,0 +1,71 @@ +/* +ReliableUDPMessage.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* Written by Antti-Juhani Kaijanaho */ + +package org.gzigzag.net; +import java.text.*; +import java.util.*; + +/** An abstract superclass of all message classes for the Reliable UDP + * scheme. + * The message contains enough metainformation so that delivery + * can be guaranteed using an acknowledgment scheme. + *

    + * This superclass contains almost all functionality that + * ReliableUDPSocket needs from subclasses of this class; all + * subclasses need to do is implementing their own payload + * functionality. The only exception is that the subclass must take + * care of including the values from getSeq() and getAck() in the UDP + * payload. + */ +public abstract class ReliableUDPMessage { + private long seq = 0; + private long ack = 0; + private long timestamp = 0; + private Peer peer = null; + + static private DateFormat df = DateFormat.getDateInstance(); + + public final synchronized long getSeq() { return seq; } + public final synchronized long getAck() { return ack; } + public final synchronized long getTimestamp() { return timestamp; } + + public final synchronized void setSeq(long seq) { this.seq = seq; } + public final synchronized void setAck(long ack) { this.ack = ack; } + public final synchronized void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + public final synchronized Peer getPeer() { return peer; } + public final synchronized void setPeer(Peer p) { peer = p; } + + /** Return a fresh byte array usable as UDP packet payload. Note + * that the return value must encode seq and ack to work with a + * ReliableUDPSocket; timestamp is optional. */ + public abstract byte[] toByteArray(); + + /** Make a fresh copy of this message. */ + public abstract ReliableUDPMessage copy(); + + public synchronized String toString() { + return "[" + df.format(new Date(timestamp)) + + "] " + peer; + } + +} + diff --git a/Java/net/ReliableUDPMessageFactory.java b/Java/net/ReliableUDPMessageFactory.java new file mode 100644 index 0000000..0ac73f3 --- /dev/null +++ b/Java/net/ReliableUDPMessageFactory.java @@ -0,0 +1,40 @@ +/* +ReliableUDPMessageFactory.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* Written by Antti-Juhani Kaijanaho */ + +package org.gzigzag.net; + +/** A factory creating ReliableUDPMessage objects for the use of a + * ReliableUDPSocket. + * Typically each application of the reliable UDP + * scheme implements this interface along with subclassing + * ReliableUDPMessage. + */ +public interface ReliableUDPMessageFactory { + + /** Create a ReliableUDPMessage object from the bytes given. Note + * that the seq, ack and optionally timestamp fields in the + * ReliableUDPMessage need to be set from the message too. */ + ReliableUDPMessage makeMessage(byte[] message); + + /** Create a fresh ReliableUDPMessage that is a no-op to a + * receiver. The return value is used to a acknowledge packets + * when no payload is available for the ack message. */ + ReliableUDPMessage makeNoOp(); + +} diff --git a/Java/net/ReliableUDPSocket.java b/Java/net/ReliableUDPSocket.java new file mode 100644 index 0000000..b3f14a7 --- /dev/null +++ b/Java/net/ReliableUDPSocket.java @@ -0,0 +1,321 @@ +/* +ReliableUDPSocket.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* Written by Antti-Juhani Kaijanaho */ + +package org.gzigzag.net; + +import org.gzigzag.*; +import java.io.*; +import java.net.*; +import java.util.*; + + +/** A socket for sending and receiving reliable UDP messages. + * This + * reliable UDP scheme guarantees delivery of a message but does not + * guarantee order of delivery. + * It does not specify a format for the + * UDP payload. + * Users of this class must implement + * ReliableUDPMessageFactory and pass that implementation to the + * constructor. + */ +public class ReliableUDPSocket implements SafeExit.Cleanupable { +public static final String rcsid = "$Id: ReliableUDPSocket.java,v 1.3 2001/03/18 20:22:11 tjl Exp $"; + public static boolean dbg = false; + protected static void p(String s) { if(dbg) ZZLogger.log(s); } + protected static void pa(String s) { ZZLogger.log(s); } + + /** Construct a reliable UDP socket and bind it to some local + * port. */ + public ReliableUDPSocket(ReliableUDPMessageFactory fact) throws SocketException { + this(fact, new DatagramSocket()); + } + + /** Construct a reliable UDP socket and bind it to the given local + * port. */ + public ReliableUDPSocket(ReliableUDPMessageFactory fact, int port) throws SocketException { + this(fact, new DatagramSocket(port)); + } + + private ReliableUDPSocket(ReliableUDPMessageFactory fact, DatagramSocket socket) { + this.fact = fact; + this.socket = socket; + this.local = new Peer(socket.getLocalAddress(), socket.getLocalPort()); + qflusher.start(); + } + + /** Send the given message. */ + public void send(ReliableUDPMessage rum) { + p("==> " + rum); + ReliableUDPMessage m = rum.copy(); + m.setTimestamp(System.currentTimeMillis()); + PeerEntry pe = getPeer(m); + pe.setseq(m); + pe.enqueue(m); + } + + /** Receive a message. */ + public ReliableUDPMessage receive() throws IOException { + synchronized (buf) { + DatagramPacket packet = new DatagramPacket(buf, buf.length); + ReliableUDPMessage m; + PeerEntry pe; + do { + socket.receive(packet); + byte[] bytes = new byte[packet.getLength()]; + byte[] origbytes = packet.getData(); + for (int i = 0; i < bytes.length; i++) bytes[i] = origbytes[i]; + m = fact.makeMessage(bytes); + m.setPeer(new Peer(packet.getAddress(), packet.getPort())); + pe = getPeer(m); + pe.acknowledge(m); + pe.process_ack(m); + } while (pe.duplicate(m)); + p("<== " + m); + return m; + } + } + + /** Get the local address and port. */ + public Peer getLocal() { + return local; + } + + /** Get an array of currently active peers. */ + public Peer[] getActivePeers() { + synchronized (peers) { + Peer[] rv = new Peer[peers.size()]; + int i = 0; + for (Enumeration e = peers.elements(); e.hasMoreElements();) { + rv[i++] = (Peer)e.nextElement(); + } + return rv; + } + } + + /** Return a rough measure of the roundtrip time between us and + * the indicated peer, given in milliseconds. If the peer is not + * active, the return value is Long.MAX_VALUE. Note that this + * will not cause packets to be sent. */ + public long getPeerLag(Peer p) { + synchronized (peers) { + if (!peers.containsKey(p)) return Long.MAX_VALUE; + PeerEntry pe = getPeer(p); + return pe.getMeasAverage(); + } + } + + public void close() { + try { + socket.close(); + qflusher.interrupt(); + qflusher.join(); + qflusher = null; + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + public void cleanup() { + close(); + } + + // PRIVATE STUFF + + private final ReliableUDPMessageFactory fact; + private final DatagramSocket socket; + private final Peer local; + private final Hashtable peers = new Hashtable(); + private final byte[] buf = new byte[65536]; + private QueueFlusher qflusher = new QueueFlusher(); + + private final class PeerEntry { + private final class Outgoing { + public ReliableUDPMessage m; + public long time_entered = 0; + public long last_sent = 0; + } + + private Vector outgoing = new Vector(); + private Vector received = new Vector(); + private boolean needAck = false; + private long ack = 0; + private long seq = 1; + private Peer peer; + private long lastSend = 0; + + // for lag measurement + private long[] meas = new long[16]; // any number, really + private int measi = 0; + private int num_meas = 0; + + public PeerEntry(Peer peer) { this.peer = peer; } + + private synchronized void addReceived(Long l) { + received.addElement(l); + int n = received.size(); + int i; + for (i = n - 1; i >= 1; i++) { + Long a = (Long)received.elementAt(i - 1); + Long b = (Long)received.elementAt(i); + if (a.longValue() < b.longValue()) break; + received.setElementAt(a, i); + received.setElementAt(b, i - 1); + } + if (n >= 2 && received.elementAt(i).equals(received.elementAt(i+1))) { + received.removeElementAt(i+1); + } + } + + public synchronized boolean duplicate(ReliableUDPMessage rum) { + if (rum.getSeq() <= seq) return true; + if (received.contains(new Long(rum.getSeq()))) return true; + return false; + } + + private synchronized void addMeasurement(long m) { + meas[measi] = m; + measi = (measi + 1) % meas.length; + if (num_meas < meas.length) ++num_meas; + } + + public synchronized long getMeasAverage() { + if (num_meas == 0) return Long.MAX_VALUE; + long sum = 0; + for (int i = 0; i < num_meas; i++) { + sum += meas[i]; + } + return sum / num_meas; + } + + public synchronized void acknowledge(ReliableUDPMessage rum) { + needAck = true; + if (rum.getAck() > ack) addReceived(new Long(rum.getSeq())); + + int n = received.size(); + int i; + for (i = 0; i < n; i++) { + long l = ((Long)received.elementAt(i)).longValue(); + if (l != ack + i + 1) break; + } + Vector v = new Vector(); + ack += i; + for (int j = i; j < n; i++) { + v.addElement(received.elementAt(i)); + } + received = v; + } + + public synchronized void process_ack(ReliableUDPMessage rum) { + int n = outgoing.size(); + Vector v = new Vector(); + for (int i = 0; i < n; i++) { + Outgoing og = (Outgoing)outgoing.elementAt(i); + if (og.m.getSeq() > rum.getAck()) { + v.addElement(og); + } else if (og.m.getSeq() == rum.getAck()) { + addMeasurement(System.currentTimeMillis() - og.last_sent); + } + } + outgoing = v; + } + + public synchronized void enqueue(ReliableUDPMessage m) { + Outgoing og = new Outgoing(); + og.m = m; + og.time_entered = System.currentTimeMillis(); + og.last_sent = 0; + + outgoing.addElement(og); + trySend(og); + } + + public synchronized void setseq(ReliableUDPMessage rum) { + rum.setSeq(seq++); + } + + public synchronized void flush() { + int n = outgoing.size(); + for (int i = 0; i < n; i++) { + Outgoing og = (Outgoing)outgoing.elementAt(i); + trySend(og); + if (og.last_sent - og.time_entered > 10 * 60 * 1000) { + peers.remove(peer); + return; + } + } + if (needAck) { + Outgoing og = new Outgoing(); + og.m = fact.makeNoOp(); + og.m.setSeq(0); + trySend(og); + } + } + + private void trySend(Outgoing og) { + long now = System.currentTimeMillis(); + if (now - og.last_sent < 500) return; + og.m.setAck(ack); + needAck = false; + lastSend = now; + byte[] bytes = og.m.toByteArray(); + DatagramPacket dp = new DatagramPacket(bytes, bytes.length, + peer.getHost(), peer.getPort()); + try { + socket.send(dp); + } catch (IOException e) { + needAck = true; + } + og.last_sent = now; + } + + } + + private PeerEntry getPeer(ReliableUDPMessage rum) { + Peer p = rum.getPeer(); + return getPeer(p); + } + + private PeerEntry getPeer(Peer p) { + synchronized (peers) { + if (!peers.containsKey(p)) { + peers.put(p, new PeerEntry(p)); + } + return (PeerEntry)peers.get(p); + } + } + + private final class QueueFlusher extends Thread { + public void run() { + while (!isInterrupted()) { + try { + sleep(500); + Peer[] ps = getActivePeers(); + for (int i = 0; i < ps.length; i++) { + getPeer(ps[i]).flush(); + yield(); + } + } catch (InterruptedException e) { + interrupt(); + } + } + } + } + +} diff --git a/Java/p2p/P2PStorage.java b/Java/p2p/P2PStorage.java new file mode 100644 index 0000000..3e0d4fd --- /dev/null +++ b/Java/p2p/P2PStorage.java @@ -0,0 +1,82 @@ +/* +P2PStorage.java + * + * Copyright (c) 2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag.p2p; + +/** The physical layers of the mediaserver p2p layer. + * This is a mechanism layer; no policy is included here. + * For example, uncache unconditionally deletes the given span + * from the cache. Higher-up levels are expected to make e.g. reference + * counting functionality available to yet higher levels. + *

    + * This level simply associates unique ids to permanent, immutable + * blocks of bits: the important invariant is that + * get(id, offs, len) always returns either the same bits or + * an error if the bits are unobtainable at that time. + *

    + * Later on, digital signature functionality will be provided + * to help this. + */ + +interface P2PStorage { +public static final String rcsid = "$Id: P2PStorage.java,v 1.2 2001/04/02 17:23:44 tjl Exp $"; + + /** Convert a string to a unique id object. + */ + UniqueID str2id(String s); + + /** Get the length of the bits pointed to by the given id. + */ + long length(UniqueID id); + + /** Get the given bytes from the given id. + */ + byte[] get(UniqueID id, long offs, long len); + + /** Get an input stream from the given id. + */ + java.io.InputStream getInputStream(UniqueID id, long offs, long len); + + /** Store the given span in the cache. + */ + void cache(UniqueID id, long offs, long len); + + /** Remove the given span from the cache. + */ + void uncache(UniqueID id, long offs, long len); + + /** A structure showing a single cached entry. + */ + class InCache { + UniqueID id; + long offs, len; + } + /** Get a listing of the local cache/storage. + */ + InCache[] getDirectory(); + + /** Create a new globally unique id that can then be written to. + */ + UniqueID.Writable newUniqueID(); +} + diff --git a/Java/p2p/UniqueID.java b/Java/p2p/UniqueID.java new file mode 100644 index 0000000..4771e67 --- /dev/null +++ b/Java/p2p/UniqueID.java @@ -0,0 +1,54 @@ +/* +UniqueID.java + * + * Copyright (c) 2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag.p2p; + +/** A unique bit-block identifier. + * These identifiers are supposed to be globally unique and + * identify a single, continuous block of bits. + * @see Phys + */ + +interface UniqueID { +public static final String rcsid = "$Id: UniqueID.java,v 1.2 2001/04/02 17:23:44 tjl Exp $"; + + /** A simple representation of the whole ID as a string. + * Phys.str2id(s) is the inverse. + */ + String toString(); + + /** A writable version. + */ + interface Writable extends UniqueID { + /** Get a stream for writing into the object + * represented by this unique id. + * Naturally, this is only usable once; calling + * it more than once results in an exception. + * Closing the stream finalizes the object - + * it's not visible anywhere prior to that. + */ + java.io.OutputStream getOutputStream(); + } +} + + diff --git a/Java/part/BinaryTreePart.java b/Java/part/BinaryTreePart.java new file mode 100644 index 0000000..daf6e39 --- /dev/null +++ b/Java/part/BinaryTreePart.java @@ -0,0 +1,100 @@ +/* +BinaryTreePart.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** EXPERIMENTAL: A full binary tree spacepart demo. + * Supports two local dimensions: depth and breadth. + */ + +public class BinaryTreePart extends ZZROStrSpacePart { +public static final String rcsid = "$Id: BinaryTreePart.java,v 1.3 2000/11/06 12:39:39 tjl Exp $"; + + public BinaryTreePart(ZZSpace space, String id) { + super(space, id); + } + + public String homeID() { + return "1"; + } + + public String getText(ZZCellHandle c) { + return c.id.substring(c.id.length()-1); + } + + public ZZDimension getDim(String name) { + if(name.equals("depth")) return new Depth(); + if(name.equals("breadth")) return new Breadth(); + return null; + } + + public class Depth extends ZZRODimension { + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) { + // We can go one step + if(c.part == null && c.id.equals("1") && steps > 0) { + c = this.space.getCellByID(BinaryTreePart.this, "1", null); + steps --; + } + + if(c.part != BinaryTreePart.this) return null; + + while(steps > 0 && c != null) { + c = (ZZCellHandle)this.space.getCellByID(c.id+"0"); + steps--; + } + while(steps < 0 && c != null) { + if(c.part != BinaryTreePart.this) return null; + int len = c.id.length(); + if(c.id.charAt(len-1) == '0') + c = (ZZCellHandle)this.space.getCellByID(c.id.substring(0, len-1)); + else if(c.id.equals(id+":"+1)) + c = (ZZCellHandle)this.space.getCellByID("1"); + else + c = null; + steps++; + } + return c; + } + } + + public class Breadth extends ZZRODimension { + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) { + if(c.part != BinaryTreePart.this) return null; + + if(steps == 0) return c; + if(steps == 1) { + int len = c.id.length(); + if(c.id.charAt(len-1) == '0') + return (ZZCellHandle)this.space.getCellByID(c.id.substring(0, len-1)+"1"); + } else if(steps == -1) { + int len = c.id.length(); + if(c.id.charAt(len-1) == '1' && + c.id.charAt(len-2) != ':') + return (ZZCellHandle)this.space.getCellByID(c.id.substring(0, len-1)+"0"); + } + return null; + } + } + +} + diff --git a/Java/part/DoubleStepPart.java b/Java/part/DoubleStepPart.java new file mode 100644 index 0000000..9df100f --- /dev/null +++ b/Java/part/DoubleStepPart.java @@ -0,0 +1,64 @@ +/* +DoubleStepPart.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** EXPERIMENTAL: A dimension double-stepper part. + * This part, unlike most, has none of its own cells but simply + * provides for each dimension a doubling dimension. + */ + +public class DoubleStepPart extends ZZROStrSpacePart { +public static final String rcsid = "$Id: DoubleStepPart.java,v 1.1 2000/11/06 12:39:39 tjl Exp $"; + public static final boolean dbg = false; + static void p(String s) { if(dbg) System.out.println(s); } + + public DoubleStepPart(ZZSpace space, String id) { + super(space, id); + } + + public String homeID() { + return "1"; + } + + public String getText(ZZCellHandle c) { + return c.id.substring(c.id.length()-1); + } + + public ZZDimension getDim(String name) { + return new Dbl(space.d(name)); + } + + public class Dbl extends ZZRODimension { + ZZDimension dim; + public Dbl(ZZDimension dim) { + this.dim = dim; + } + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) { + ZZCellHandle hd = dim.s(c, steps*2, o); + p("Dbl: Step "+steps+" "+c+" "+hd); + return hd; + } + } +} + diff --git a/Java/part/GenTreePart.java b/Java/part/GenTreePart.java new file mode 100644 index 0000000..0f49501 --- /dev/null +++ b/Java/part/GenTreePart.java @@ -0,0 +1,160 @@ +/* +GenTreePart.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** EXPERIMENTAL: A tree implied by a sequence, done in a generic way. + * This is a tree implied by a structure, but in a generic way: an interface, + * GTreePartModel, is used to provide the tree structure. + *

    + * I still don't know whether Parsed helps... + * @see GenTreePart + */ + +public class GenTreePart extends ZZSpacePart { +public static final String rcsid = "$Id: GenTreePart.java,v 1.2 2000/11/16 21:01:56 tjl Exp $"; + + static public class Parsed { + String orig; + int depth; + } + + GenTreePartModel model; + + Depth dd = new Depth(); + Breadth db = new Breadth(); + + public GenTreePart(ZZSpace space, String id, GenTreePartModel model) { + super(space, id); + this.model = model; + } + + public ZZDimension getDim(String name) { + if(name.equals("depth")) return dd; + if(name.equals("breadth")) return db; + return null; + } + + public class Depth extends ZZRODimension { + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) { + if(steps == 0) return c; + + int level; + int maxlevel ; + + if(c.part == GenTreePart.this) { + Parsed par = (Parsed)c.parsedID; + level = par.depth; + c = (ZZCellHandle)this.space.getCellByID(par.orig); + maxlevel = model.depth(c); + } else { + // It's either beginning or also end of rank. + level = model.depth(c); + if(level == -1) return null; + maxlevel = level; + } + if(maxlevel < 0) return null; + level -= steps; + if(level < 0) return null; + if(level > maxlevel) return null; + if(level == maxlevel) return c; + return GenTreePart.this.space.getCellByID( + GenTreePart.this, + level + "-" + c.id); + + } + } + + public class Breadth extends ZZDimension { + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) { + if(steps == 0) return c; + ZZCell searchFrom; + int level; + if(c.part == GenTreePart.this) { + Parsed par = (Parsed)c.parsedID; + level = par.depth; + c = (ZZCellHandle)this.space.getCellByID(par.orig); + } else { + level = model.depth(c); + if(level < 0) return null; + } + + ZZCell n = model.getNext(level, c, steps); + if(n == null) return null; + int lastlevel = model.depth(n); + + // Return our cell: the cell we ended up at may be at higher level. + if(lastlevel > level) { + return GenTreePart.this.space.getCellByID( + GenTreePart.this, + level + "-" + n.getID()); + } else { + return (ZZCellHandle)n; + } + } + + public void disconnect(ZZCellHandle c, int dir) { + // Only do it negwards + if(dir > 0) { + ZZCellHandle c2 = s(c, 1); + if(c2 != null) + disconnect(c2, -1); + return; + } + // Get headcell + ZZCell ct = dd.h(c, -1); + model.disconnectNeg(ct); + } + public void connect(ZZCellHandle c, ZZCellHandle d) { + if(s(c, 1) != null) + throw new ZZConnectWouldBreakError("In gentreedepth"); + if(s(d, -1) != null) + throw new ZZConnectWouldBreakError("In gentreedepth2"); + ZZCell c1 = dd.h(c, -1); + ZZCell d1 = dd.h(d, -1); + model.connect(c1, d1); + } + } + + + public String getText(ZZCellHandle c) { + return "+"; + } + public void setContent(ZZCellHandle c, Object o) { + } + + public Object parseIDPart(String idPart) { + int min = idPart.indexOf("-"); + Parsed ret = new Parsed(); + ret.orig = idPart.substring(min+1); + ret.depth = Integer.parseInt(idPart.substring(0, min)); + return ret; + } + + public String generateIDPart(Object parsed) { + Parsed p = (Parsed)parsed; + return p.depth+"-"+p.orig; + } + +} + diff --git a/Java/part/GenTreePartModel.java b/Java/part/GenTreePartModel.java new file mode 100644 index 0000000..a3b6c44 --- /dev/null +++ b/Java/part/GenTreePartModel.java @@ -0,0 +1,77 @@ +/* +GTreePartModel.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** A tree model that provides enough information for GTreePart to + * make a tree appear in the structure. + * Assumes that a real (or at least not generated by this GTreePart) cell + * exists for each tree node or leaf. + * The depth in the tree is a constant, and depth is counted from leaves + * upwards, starting from 0, and the largest depth(cell) is depth()-1. + *

    + * This interface is heavily geared towards the thinking of having + * a single rank of cells, onto which the information about the levels + * of hierarchy is somehow connected. + * The same cell should not be given at different depths so + * using the marker cells is recommended. + *

    + * These are NOT documented clearly enough - see the sample implementation + * in ../Modules/nile or GTreePartTestModel. + * @see GenTreePart + */ + +public interface GenTreePartModel { +String rcsid = "$Id: GenTreePartModel.java,v 1.1 2000/11/16 00:25:10 tjl Exp $"; + /** The depth of the whole tree. + */ + int depth(); + + /** The depth of this cell. + * This method should return -1 if the cell does not belong + * to the tree properly. + */ + int depth(ZZCell c); + + /** Move N steps of at least this depth pos- or negwards. + */ + ZZCell getNext(int mindepth, ZZCell c, int steps); + + /** Disconnect negwards from the given cell. + */ + void disconnectNeg(ZZCell c); + + /** Connect the given cell poswards to the other. + */ + void connect(ZZCell c, ZZCell d); + + /** Set the depth of the given cell. + * This method should ONLY touch the depth of the given cell. + * Its virtual "children" will be handled by the GTreePart. + */ + void setDepth(ZZCell c, int d); +} + + + + diff --git a/Java/part/GenTreeTestModel.java b/Java/part/GenTreeTestModel.java new file mode 100644 index 0000000..73412c3 --- /dev/null +++ b/Java/part/GenTreeTestModel.java @@ -0,0 +1,83 @@ +/* +GTreePartTestModel.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** A simple model to test GenTreePart. + * The same model as ImpliedTreePart has, except that the depth + * numbers are reversed and are 0, 1, 2 and 3. + * The actual cells in the stream are not included in the tree, only + * the section marker cells. + * @see GenTreePart + */ + +public class GenTreeTestModel implements GenTreePartModel { +public static final String rcsid = "$Id: GenTreeTestModel.java,v 1.1 2000/11/16 00:25:10 tjl Exp $"; + public static boolean dbg = true; + final static void p(String s) { if(dbg) System.out.println(s); } + final static void pa(String s) { System.out.println(s); } + + public int depth() { + return 4; + } + + public int depth(ZZCell c) { + if(c.s("d.1") == null) + return -1; + // So the int it 0..3 + return Integer.parseInt(c.getText()); + } + + public ZZCell getNext(int mindepth, ZZCell c, int steps) { + if(steps == 0) return c; + c = c.s("d.1"); + int dir = (steps > 0 ? 1 : -1); + ZZCell lasthdr = null; + while(steps != 0 && c != null) { + c = c.s("d.2", dir); + if(c == null) return null; + lasthdr = c.s("d.1", -1); + if(lasthdr == null) continue; + if(depth(lasthdr) < mindepth) continue; + steps -= dir; + } + if(c == null) return null; + return lasthdr; + } + + public void disconnectNeg(ZZCell c) { + p("Model: disconnectneg "+c); + c.h("d.1", 1).disconnect("d.2", -1); + } + + public void connect(ZZCell c, ZZCell d) { + p("Model: connect "+c+" "+d); + c.h("d.1", 1).h("d.2", 1).connect("d.2", d.h("d.1", 1)); + } + + public void setDepth(ZZCell c, int d) { + if(depth(c) == 0) return; + c.setText(""+d); + } + +} diff --git a/Java/part/ImpliedTreePart.java b/Java/part/ImpliedTreePart.java new file mode 100644 index 0000000..d229c04 --- /dev/null +++ b/Java/part/ImpliedTreePart.java @@ -0,0 +1,173 @@ +/* +ImpliedTreePart.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** EXPERIMENTAL: A tree implied by a sequence. + * A proof of concept of having a straight + * stream of material with "tags" connected next to it imply + * a tree. + *

    + * Connect a bunch of stuff on d.2 and add cells with numbers connected + * negwards on d.1, then view on imptree:depth and imptree:breadth + *

    + * The number is the level of the heading, reverse from HTML + * (1 is next to text, 2 is next above etc). + * For a heading of level N, N-1 cells are generated. + * The IDs of the generated cells are of the form + * k-ID where k is the level from the text up. + * So a heading of level 4 (cell ID 26) would have the following + * cells connected along depth: 26, i:3-26, i:2-26 and i:1-26. + *

    + * One problem of space parts: changing the section depth deletes cells, + * and cursors on those cells should be notified! + */ + +public class ImpliedTreePart extends ZZROStrSpacePart { +public static final String rcsid = "$Id: ImpliedTreePart.java,v 1.3 2000/11/13 11:59:32 tjl Exp $"; + + public ImpliedTreePart(ZZSpace space, String id) { + super(space, id); + } + + public String getText(ZZCellHandle c) { + return c.id.substring(c.id.length()-1); + } + + Depth dd = new Depth(); + Breadth db = new Breadth(); + + public ZZDimension getDim(String name) { + if(name.equals("depth")) return dd; + if(name.equals("breadth")) return db; + return null; + } + + public class Depth extends ZZRODimension { + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) { + if(steps == 0) return c; + + int level; + + if(c.part == ImpliedTreePart.this) { + int col = c.id.indexOf(":"); + int min = c.id.indexOf("-"); + level = Integer.parseInt(c.id.substring(col+1, min)); + c = (ZZCellHandle)this.space.getCellByID(c.id.substring(min+1)); + } else { + // It's either beginning or end of rank. + if(c.s("d.1", 1) != null) { + level = posno(c); + } else { + if(steps > 0) return null; + c = (ZZCellHandle)c.s("d.1", -1); + if(c == null) return null; + level = 0; + } + } + int maxlevel = posno(c); + if(maxlevel < 0) return null; + level -= steps; + if(level < 0) return null; + if(level == 0) return (ZZCellHandle)c.s("d.1", 1); + if(level > maxlevel) return null; + if(level == maxlevel) return c; + return ImpliedTreePart.this.space.getCellByID( + ImpliedTreePart.this, + level + "-" + c.id); + + } + } + + int posno(ZZCell c) { + try { + return Integer.parseInt(c.getText().trim()); + } catch(NumberFormatException e) { + ZZLogger.log("Not a number! '"+c.getText()+"' "+c+" "+e); + return -1; + } + } + + public class Breadth extends ZZDimension { + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) { + if(steps == 0) return c; + ZZCell searchFrom; + int level; + if(c.part == ImpliedTreePart.this) { + int col = c.id.indexOf(":"); + int min = c.id.indexOf("-"); + level = Integer.parseInt(c.id.substring(col+1, min)); + c = (ZZCellHandle)this.space.getCellByID(c.id.substring(min+1)); + } else { + if(c.s("d.1", 1) == null) + return (ZZCellHandle)c.s("d.2", steps); + level = posno(c); + if(level < 0) return null; + } + searchFrom = c.s("d.1"); + if(searchFrom == null) return null; + + int dir = (steps > 0 ? 1 : -1); + int lastlevel = -1; + ZZCell lasthdr = null; + while(steps != 0) { + searchFrom = searchFrom.s("d.2", dir); + if(searchFrom == null) return null; + lasthdr = searchFrom.s("d.1", -1); + if(lasthdr == null) continue; + if((lastlevel = posno(lasthdr)) < level) continue; + steps -= dir; + } + + // Return our cell: the cell we ended up at is at higher level. + if(lastlevel > level) { + return ImpliedTreePart.this.space.getCellByID( + ImpliedTreePart.this, + level + "-" + lasthdr.getID()); + } else { + return (ZZCellHandle)lasthdr; + } + } + public void disconnect(ZZCellHandle c, int dir) { + if(dir > 0) { + ZZCellHandle c2 = s(c, 1); + if(c2 != null) + disconnect(c2, -1); + return; + } + ZZCell ct = dd.h(c, 1); + ct.disconnect("d.2", -1); + } + public void connect(ZZCellHandle c, ZZCellHandle d) { + if(s(c, 1) != null) + throw new ZZConnectWouldBreakError("In impliedtreedepth"); + if(s(d, -1) != null) + throw new ZZConnectWouldBreakError("In impliedtreedepth2"); + ZZCell c1 = dd.h(c, 1).h("d.2", 1); + ZZCell d1 = dd.h(d, 1).h("d.2", -1); + c1.connect("d.2", d1); + } + } + +} + diff --git a/Java/part/ImpliedTreePart2.java b/Java/part/ImpliedTreePart2.java new file mode 100644 index 0000000..3137857 --- /dev/null +++ b/Java/part/ImpliedTreePart2.java @@ -0,0 +1,192 @@ +/* +ImpliedTreePart2.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** EXPERIMENTAL: A tree implied by a sequence. + * Second version, to test the parsed space part stuff. + * A proof of concept of having a straight + * stream of material with "tags" connected next to it imply + * a tree. + *

    + * Connect a bunch of stuff on d.2 and add cells with numbers connected + * negwards on d.1, then view on imptree:depth and imptree:breadth + *

    + * The number is the level of the heading, reverse from HTML + * (1 is next to text, 2 is next above etc). + * For a heading of level N, N-1 cells are generated. + * The IDs of the generated cells are of the form + * k-ID where k is the level from the text up. + * So a heading of level 4 (cell ID 26) would have the following + * cells connected along depth: 26, i:3-26, i:2-26 and i:1-26. + *

    + * One problem of space parts: changing the section depth deletes cells, + * and cursors on those cells should be notified! + */ + +public class ImpliedTreePart2 extends ZZSpacePart { +public static final String rcsid = "$Id: ImpliedTreePart2.java,v 1.1 2000/11/13 11:59:48 tjl Exp $"; + + static public class Parsed { + String orig; + int depth; + } + + public ImpliedTreePart2(ZZSpace space, String id) { + super(space, id); + } + + public String getText(ZZCellHandle c) { + return c.id.substring(c.id.length()-1); + } + public void setContent(ZZCellHandle c, Object o) { + } + + public Object parseIDPart(String idPart) { + int min = idPart.indexOf("-"); + Parsed ret = new Parsed(); + ret.orig = idPart.substring(min+1); + ret.depth = Integer.parseInt(idPart.substring(0, min)); + return ret; + } + + public String generateIDPart(Object parsed) { + Parsed p = (Parsed)parsed; + return p.depth+"-"+p.orig; + } + + Depth dd = new Depth(); + Breadth db = new Breadth(); + + public ZZDimension getDim(String name) { + if(name.equals("depth")) return dd; + if(name.equals("breadth")) return db; + return null; + } + + public class Depth extends ZZRODimension { + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) { + if(steps == 0) return c; + + int level; + + if(c.part == ImpliedTreePart2.this) { + Parsed par = (Parsed)c.parsedID; + level = par.depth; + c = (ZZCellHandle)this.space.getCellByID(par.orig); + } else { + // It's either beginning or end of rank. + if(c.s("d.1", 1) != null) { + level = posno(c); + } else { + if(steps > 0) return null; + c = (ZZCellHandle)c.s("d.1", -1); + if(c == null) return null; + level = 0; + } + } + int maxlevel = posno(c); + if(maxlevel < 0) return null; + level -= steps; + if(level < 0) return null; + if(level == 0) return (ZZCellHandle)c.s("d.1", 1); + if(level > maxlevel) return null; + if(level == maxlevel) return c; + return ImpliedTreePart2.this.space.getCellByID( + ImpliedTreePart2.this, + level + "-" + c.id); + + } + } + + int posno(ZZCell c) { + try { + return Integer.parseInt(c.getText().trim()); + } catch(NumberFormatException e) { + ZZLogger.log("Not a number! '"+c.getText()+"' "+c+" "+e); + return -1; + } + } + + public class Breadth extends ZZDimension { + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) { + if(steps == 0) return c; + ZZCell searchFrom; + int level; + if(c.part == ImpliedTreePart2.this) { + Parsed par = (Parsed)c.parsedID; + level = par.depth; + c = (ZZCellHandle)this.space.getCellByID(par.orig); + } else { + if(c.s("d.1", 1) == null) + return (ZZCellHandle)c.s("d.2", steps); + level = posno(c); + if(level < 0) return null; + } + searchFrom = c.s("d.1"); + if(searchFrom == null) return null; + + int dir = (steps > 0 ? 1 : -1); + int lastlevel = -1; + ZZCell lasthdr = null; + while(steps != 0) { + searchFrom = searchFrom.s("d.2", dir); + if(searchFrom == null) return null; + lasthdr = searchFrom.s("d.1", -1); + if(lasthdr == null) continue; + if((lastlevel = posno(lasthdr)) < level) continue; + steps -= dir; + } + + // Return our cell: the cell we ended up at is at higher level. + if(lastlevel > level) { + return ImpliedTreePart2.this.space.getCellByID( + ImpliedTreePart2.this, + level + "-" + lasthdr.getID()); + } else { + return (ZZCellHandle)lasthdr; + } + } + public void disconnect(ZZCellHandle c, int dir) { + if(dir > 0) { + ZZCellHandle c2 = s(c, 1); + if(c2 != null) + disconnect(c2, -1); + return; + } + ZZCell ct = dd.h(c, 1); + ct.disconnect("d.2", -1); + } + public void connect(ZZCellHandle c, ZZCellHandle d) { + if(s(c, 1) != null) + throw new ZZConnectWouldBreakError("In impliedtreedepth"); + if(s(d, -1) != null) + throw new ZZConnectWouldBreakError("In impliedtreedepth2"); + ZZCell c1 = dd.h(c, 1).h("d.2", 1); + ZZCell d1 = dd.h(d, 1).h("d.2", -1); + c1.connect("d.2", d1); + } + } + +} + diff --git a/Java/part/VersionPart.java b/Java/part/VersionPart.java new file mode 100644 index 0000000..28786b2 --- /dev/null +++ b/Java/part/VersionPart.java @@ -0,0 +1,634 @@ +/* +VersionPart.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ +package org.gzigzag; +import java.util.*; + +/** EXPERIMENTAL: A space part showing past versions of a ZZCacheDimSpace. + */ + +public class VersionPart extends ZZROSpacePart { +public static final String rcsid = "$Id: VersionPart.java,v 1.15.2.1 2001/04/08 16:24:49 ajk Exp $"; + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + private static final Object nolla = new Object(); + + protected static final ZZObsTrigger ot = new ZZObsTrigger(); + + public static boolean regular_dimensions = false; + + protected Hashtable dimensions = new Hashtable(); + + protected String listDimensionName = "list"; + protected String activeDimensionName = "active"; + public VersionPart(ZZCacheDimSpace cds, String s) { + super(cds, s); + if (cds == null) throw new ZZError("null cds"); + dimensions.put(listDimensionName, new ListDimension()); + dimensions.put("home", new HomeDimension()); + dimensions.put(activeDimensionName, new ActiveDimension()); + dimensions.put("version-active", new ActiveCellVersionsDimension()); + } + + // spaces and stamps form a combined data structure where spaces + // provides fast lookup of SpaceElements based on space timestamps + // and stamps contains the active timestamps in ascending order. + private Hashtable spaces = new Hashtable(); + private Vector stamps = new Vector(); + + /** Show what's in stamps. This is a debugging method. */ + private void dump_stamps() { + if (!dbg) return; + + for (int i = 0; i < stamps.size(); i++) { + pa("stamps[" + i + "] == " + stamps.elementAt(i)); + } + } + + /** A set of data about one space. */ + private class SpaceElement { + /** The space timestamp. */ + Integer stampo; + /** Index of this SpaceElement in stamps. */ + int inx; + /** The space itself. */ + ZZCacheDimSpace space; + /** The cell that denotes this space in the version:list + * rank. */ + ZZDimSpace.DimCell cell; + + /** A cache of wrapper cells, keyed by unwrapped cell IDs, for + * this space. */ + private Hashtable wrappercells = new Hashtable(); + + /** A cache of wrapper dimensions, keyed by unwrapped + * dimension IDs, for this space. A key may map to "nolla", + * which means that the key does not denote an existing + * dimension. */ + private Hashtable wrapperdims = new Hashtable(); + + public void activate() { + if (space == null) { + space = new ZZCacheDimSpace((ZZCacheDimSpace)VersionPart.this.space, stampo.intValue()); + put(this); + } + } + + /** Get a wrapper cell for the cell "old". */ + public VersionCell getWrapperCell(ZZCellHandle old) { + return getWrapperCell(old, old.getID()); + } + + public VersionCell getWrapperCell(String oldid) { + return getWrapperCell((ZZCellHandle)space.getCellByID(oldid), oldid); + } + + public VersionCell getWrapperCell(ZZCellHandle old, String oldid) { + if (wrappercells.containsKey(oldid)) { + return (VersionCell)wrappercells.get(oldid); + } else { + VersionCell vc = new VersionCell(this, old); + wrappercells.put(oldid, vc); + return vc; + } + } + + /** Get a wrapper dimension for the dimension "dim". */ + public VersionDimension getWrapperDimension(String dim) { + if (wrapperdims.containsKey(dim)) { + Object o = wrapperdims.get(dim); + if (o == nolla) return null; + return (VersionDimension)o; + } else { + try { + wrapperdims.put(dim, new VersionDimension(this, dim)); + } catch (ZZError e) { + wrapperdims.put(dim, nolla); + } + return getWrapperDimension(dim); + } + } + + } + + /** Return a cell with this ID. */ + public ZZDimSpace.DimCell getCellByID(String s) { + ID id = (ID)parseIDPart(s); + SpaceElement se = getSpaceElement(id.stamp); + if (id.id == null) { + return se.cell; + } else { + se.activate(); + return se.getWrapperCell((ZZCellHandle)se.space.getCellByID(id.id)); + } + } + + /** Put se in spaces and update stamps. */ + private void put(SpaceElement se) { + synchronized (spaces) { + int i; + for (i = 0; i < stamps.size(); i++) { + if (((Integer)stamps.elementAt(i)).intValue() >= se.stampo.intValue()) break; + } + stamps.insertElementAt(se.stampo, i); + se.inx = i; + for (int j = i + 1; j < stamps.size(); j++) { + Integer stampo = (Integer)stamps.elementAt(j); + SpaceElement sep = (SpaceElement)spaces.get(stampo); + ++sep.inx; + } + spaces.put(se.stampo, se); + } + ot.chg(spaces); + } + + /** Get a SpaceElement corresponding to stamp. */ + protected SpaceElement getActiveSpaceElement(int stamp) { + return getActiveSpaceElement(new Integer(stamp)); + } + /** Get a SpaceElement corresponding to stampo and activate it. */ + protected SpaceElement getActiveSpaceElement(Integer stampo) { + synchronized (spaces) { + SpaceElement se = getSpaceElement(stampo); + se.activate(); + return se; + } + } + + /** Get a SpaceElement corresponding to stamp. */ + protected SpaceElement getSpaceElement(int stamp) { + return getSpaceElement(new Integer(stamp)); + } + + /** Get a SpaceElement corresponding to stampo. */ + protected SpaceElement getSpaceElement(Integer stampo) { + synchronized (spaces) { + if (spaces.containsKey(stampo)) { + return ((SpaceElement)spaces.get(stampo)); + } else { + SpaceElement se = new SpaceElement(); + se.inx = Integer.MAX_VALUE; + se.stampo = stampo; + se.space = null; + se.cell = new ListCell(se); + return se; + } + } + } + + + /** Return the space corresponding to stamp. */ + protected ZZCacheDimSpace getSpace(int stamp) { + return getActiveSpaceElement(stamp).space; + } + + /** Activate the space corresponding to stamp. */ + public void loadVersion(int stamp) { + if (stamp > ((ZZCacheDimSpace)space).timestamp) + stamp = ((ZZCacheDimSpace)space).timestamp; + getActiveSpaceElement(stamp); + } + + /** A parsed representation of a cell's or dimension's ID. */ + protected static class ID { + /** The wrapped dimension or cell's ID or null, if this is a list cell. */ + public final String id; + /** The space timestamp related to this cell or dimension. */ + public final int stamp; + + public ID(String id, int stamp) { + this.id = id; + this.stamp = stamp; + } + + public String toString() { + if (id == null) return "" + stamp; + return "" + stamp + "." + id; + } + } + + public ZZDimension getDim(String name) { + pa("VersionPart.getDim(" + name + ")"); + if (dimensions.containsKey(name)) return (ZZDimension)dimensions.get(name); + + if (name.substring(0, 2).equals("d.")) + return new AllVersionDimension(name); + + ID did = (ID)parseIDPart(name); + SpaceElement cds = getActiveSpaceElement(did.stamp); + + return cds.getWrapperDimension(did.id); + } + + /** A wrapper cell for cells in old space versions. */ + protected class VersionCell extends ZZDimSpace.DimCell { + final ZZCellHandle old; + + public VersionCell(SpaceElement se, ZZCellHandle old) { + VersionPart.this.space.super(VersionPart.this, + new ID(old.getID(), se.stampo.intValue())); + this.old = old; + } + + private boolean isIgnoredDim(String dim) { + return dim.equals("d.cursor") + || dim.equals("d.cursor-list") + || dim.equals("d.cursor-cargo") + || dim.indexOf(':') != -1; + } + + public ZZCell s(String dim, int dir, ZZObs o) { + ZZCell rv = s(dim, dir, o, new Object()); + p("(" + this + ").s(" + dim + ", " + dir + ", " + o + ") ==> " + rv); + return rv; + } + + private ZZCell s(String dim, int dir, ZZObs o, Object foo) { + if (!regular_dimensions || isIgnoredDim(dim)) + return super.s(dim, dir, o); + + // Connected in current version? If yes, use the connection. + ZZCell c = super.s(dim, dir, o); + if (c != null) return c; + + // No? Is there a connection in past active versions. + // If yes, use the newest. + synchronized (spaces) { + int n = stamps.size(); + for (int i = n - 1; i >= 0; --i) { + Integer stampo = (Integer)stamps.elementAt(i); + p("trying with " + stampo); + SpaceElement se = getActiveSpaceElement(stampo); + VersionDimension vd = se.getWrapperDimension(dim); + c = vd.s(this, dir, o); + if (c != null) return c; + } + } + + // No? Then there is no connection. + return null; + } + + public void disconnect(String dim, int dir) { + if (regular_dimensions && !isIgnoredDim(dim)) { + if (s(dim, dir, null) != null) { + throw new ZZError("immutable connection"); + } + } + + super.disconnect(dim, dir); + } + + + public void setText(String text) { + throw new ZZError("readonly cell"); + } + public void setSpan(Span text) { + throw new ZZError("readonly cell"); + } + public String getText(ZZObs o) { + return old.getText(o); + } + public Span getSpan(ZZObs o) { + return old.getSpan(o); + } + + public void delete() { + throw new ZZError("immutable cell"); + } + } + + /** A cell in the active spaces list. */ + protected class ListCell extends ZZDimSpace.DimCell { + SpaceElement se; + + public ListCell(SpaceElement se) { + VersionPart.this.space.super(VersionPart.this, + new ID(null, se.stampo.intValue())); + p("new ListCell, ID = " + getID()); + this.se = se; + } + + /** Create a new cell. If creating along version:list, we + * activate the next or previous space version. Otherwise we + * redelegate to the superclass. */ + public ZZCell N(String dim, int dir, ZZObs o, long flags) { + if (!dim.equals(VersionPart.this.id + ":" + activeDimensionName)) + return super.N(dim, dir, o, flags); + loadVersion(se.stampo.intValue() + dir); + return VersionPart.this.space.d(VersionPart.this.id + ":" + activeDimensionName).s(this, dir, o); + } + + public void setText(String text) { + throw new ZZError("readonly cell"); + } + public void setSpan(Span text) { + throw new ZZError("readonly cell"); + } + + public void delete() { + VersionPart.this.space.deleteCell(this); + se.space = null; + } + + } + + /** Dimension that lists all active versions. This dimension has + * funky semantics. First of all, there is always at most one + * nontrivial rank on this dimension. That rank's headcell is + * always the space homecell. The other cells are ListCells (ID + * of type "version:NUMBER") and they are listed on that rank in + * ascending numeric order on their content. The content always + * equals the NUMBER in the cell ID. If you connect some cell + * containing a number to this rank, the number is interpreted as + * a version and that version is activated. This means that + * instead of the cell appearing on that rank, a new cell appears + * in the right place and time. Disconnecting from this rank + * deactivates that version. One cannot connect to homecell's + * negative side or to other ranks on this dimension. */ + protected class ActiveDimension extends ZZDimension { + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs obs) { + ZZCellHandle rv; + // inx will first denote the index of c in stamps; steps + // will then be added to it to make it point to the index + // in staps of the return value (or off-bounds if we want + // to return null) + int inx = Integer.MIN_VALUE; + try { + synchronized (spaces) { + if (c.equals(VersionPart.this.space.getHomeCell())) { + // home cell's posward neighbour is stamps[0] + inx = -1; + } else { + ID id = (ID)parseID(c.getID()); + if (id.id != null) { + // not a home cell or a ListCell, so we + // want to end up out of bounds + inx = -2-steps; + } else { + // this is a ListCell, look up the index in stamps + SpaceElement se = ((ListCell)c).se; + inx = se.inx; + } + } + // now inx will index the return value + inx += steps; + if (inx == -1) { + // stamps[0]'s negward neighbour is the home cell + rv = (ZZCellHandle)VersionPart.this.space.getHomeCell(); + } else if (inx == stamps.size()) { + // We're technically out of bounds, but this + // is sooo useful! We'll have the last + // committed version always as the tailcell. + // Its presence as the tailcell does not + // necessarily mean it's activated, however; + // we want it to remain unactivated after a + // new commit if it has not been examined, but + // also we want it to magically be active + // after a commit otherwise. + Integer stampo = new Integer(((ZZCacheDimSpace)VersionPart.this.space).timestamp); + // Careful here! If the tailcell version is + // active, it is stamps[stamps.size()-1] and + // thus we must not give it a posward + // neighbour that it is itself (that would + // break rank invariants) + if (spaces.containsKey(stampo)) + rv = null; + else { + // Okay, it's unactivated. + rv = getSpaceElement(stampo).cell; + } + } else if (inx < -1 || inx > stamps.size()) { + // off-bounds means no cigar + rv = null; + } else { + // within bounds, so this is straightforward + Integer stampo = (Integer)stamps.elementAt(inx); + rv = getSpaceElement(stampo).cell; + } + } + } catch (SyntaxError e) { + rv = null; + } + p("ActiveDimension.s(" + c + ", " + steps + ") (inx == " + inx + ", stamps.size() == " + stamps.size() + ") ==> " + rv); + dump_stamps(); + + if (obs != null) { ot.addObs(spaces, obs); } + + return rv; + } + + /** Is this cell a ListCell? */ + private boolean isOurs(ZZCellHandle c) { + return c.equals(VersionPart.this.space.getHomeCell()) + || (c.part == VersionPart.this + && ((ID)c.parsedID).id == null); + } + + /** "Connect" two cells on this dimension. This is rather + * magical, see the class documentation. */ + public void connect(ZZCellHandle c, ZZCellHandle d) { + pa("c = " + c + ", d = " + d); + if (isOurs(c) && isOurs(d)) return; // already on the rank + if (isOurs(c)) loadVersion(Integer.parseInt(d.getText())); + else if (isOurs(d)) loadVersion(Integer.parseInt(c.getText())); + else throw new ZZError("cannot connect those cells"); + dump_stamps(); + } + + /** "Disconnect" two cells on this dimension. This is rather + * magical, see the class documentation. */ + public void disconnect(ZZCellHandle c, int dir) { + synchronized (spaces) { + if (c.part != VersionPart.this || ((ID)c.parsedID).id != null) return; + Integer stampo = new Integer(((ID)c.parsedID).stamp); + if (!spaces.containsKey(stampo)) return; + SpaceElement se = (SpaceElement)spaces.get(stampo); + spaces.remove(stampo); + int n = stamps.size(); + stamps.removeElementAt(se.inx); + for (int i = se.inx; i < stamps.size(); i++) { + Integer stampone = (Integer)stamps.elementAt(i); + SpaceElement sese = getActiveSpaceElement(stampone); + sese.inx = i; + } + dump_stamps(); + } + } + + } + + protected class ListDimension extends ZZRODimension { + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs obs) { + ZZCellHandle home = (ZZCellHandle)VersionPart.this.space.getHomeCell(); + int i; + if (c.equals(home)) { + i = 0; + } else { + if (c.part != VersionPart.this) return null; + ID id = (ID)c.parsedID; + if (id.id != null) return null; + i = id.stamp; + } + i += steps; + if (!(0 <= i && i <= ((ZZCacheDimSpace)VersionPart.this.space).timestamp)) return null; + if (obs != null) ot.addObs(dimensions, obs); + if (i == 0) return home; + return getSpaceElement(i).cell; + } + } + + /** This dimension connects ListCells to their spaces' homecells.*/ + protected class HomeDimension extends ZZRODimension { + // note, this dimension never triggers anything as it is truly RO + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) { + synchronized (spaces) { + if (c.part != VersionPart.this) return null; + ID id = (ID)c.parsedID; + if (id.id != null) { + if (!getSpace(id.stamp).getHomeCell().getID().equals(id.id)) { + return null; + } + if (steps != -1) return null; + return getActiveSpaceElement(id.stamp).cell; + } + if (steps != 1) return null; + return ((ListCell)c). + se.getWrapperCell((ZZCellHandle)getSpace(id.stamp).getHomeCell()); + } + } + } + + /** This dimension wraps around dimensions in old space versions. */ + protected class VersionDimension extends ZZRODimension { + SpaceElement se; + ZZDimension old; + public VersionDimension(SpaceElement se, String dim) { + this.se = se; + Object o = se.space.d(dim); + if (o == null) throw new ZZError("no such dimension"); + old = (ZZDimension)o; + } + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) { + p("VersionDimension(" + se.stampo + ").s, c = " + c + ", c.part = " + c.part + ", c.getClass() = " + c.getClass()); + if (c.part != VersionPart.this) return null; + ID id = (ID)c.parsedID; + if (id.id == null) return null; + if (!(c instanceof VersionCell)) return null; + ZZCellHandle oldc = ((VersionCell)c).old; + if (id.stamp != se.stampo.intValue()) { + se.activate(); + oldc = (ZZCellHandle)se.space.getCellByID(c.getID()); + } + ZZCellHandle oldrc = old.s(oldc, steps, o); + p("oldc = " + oldc + ", oldrc = " + oldrc); + if (oldrc == null) return null; + return se.getWrapperCell(oldrc); + } + } + + protected class AllVersionDimension extends ZZRODimension { + String name; + public AllVersionDimension(String name) { + this.name = name; + } + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) { + if(c.part != VersionPart.this) + return (ZZCellHandle)c.s(name, steps, o); + ID id = (ID)c.parsedID; + if(id == null) + return (ZZCellHandle)c.s(name, steps, o); + return getActiveSpaceElement(id.stamp) + .getWrapperDimension(name) + .s(c, steps, o); + } + } + + protected class ActiveCellVersionsDimension extends ZZRODimension { + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs obs) { + synchronized (spaces) { + String cid; + int inx; + if (c.part == VersionPart.this) { + ID id = (ID)c.parsedID; + if (id.id == null) return null; + SpaceElement se_cur = getActiveSpaceElement(id.stamp); + inx = se_cur.inx; + cid = id.id; + } else if (c.part == null) { + inx = stamps.size(); + cid = c.getID(); + } else { + return null; + } + inx -= steps; + if (inx == stamps.size()) + return (ZZCellHandle)VersionPart.this.space.getCellByID(cid); + if (inx < 0 || inx > stamps.size()) + return null; + Integer stampo = (Integer)stamps.elementAt(inx); + SpaceElement se_new = getActiveSpaceElement(stampo); + if (obs != null) ot.addObs(spaces, obs); + return se_new.getWrapperCell(cid); + } + } + } + + public Object parseIDPart(String s) { + int idx = s.indexOf("."); + if (idx == s.length() -1) { + throw new SyntaxError("syntax error in cell/dimension ID: missing period"); + } + String id; + if (idx == -1) { + id = null; + idx = s.length(); + } else { + id = s.substring(idx+1); + } + int stamp; + try { + stamp = Integer.parseInt(s.substring(0, idx)); + } catch (NumberFormatException e) { + throw new SyntaxError("syntax error in cell/dimension ID: " + e.getMessage()); + } + return new ID(id, stamp); + } + + public String generateIDPart(Object parsed) { + String rv = ((ID)parsed).toString(); + p("VersionPart.generateIDPart returns " + rv); + return rv; + } + + public String getText(ZZCellHandle c) { + ID id = (ID)parseID(c.getID()); + if (id.id != null) { + return getSpace(id.stamp).getText(id.id); + } + return ""+id.stamp; + } + + public void postCommitHook() { ot.chg(dimensions); } + +} + diff --git a/Java/part/ZZROSpacePart.java b/Java/part/ZZROSpacePart.java new file mode 100644 index 0000000..d7ebb43 --- /dev/null +++ b/Java/part/ZZROSpacePart.java @@ -0,0 +1,39 @@ +/* +ZZROSpacePart.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; + +/** EXPERIMENTAL: A read-only ZZSpacePart. + */ + +public abstract class ZZROSpacePart extends ZZSpacePart { +public static final String rcsid = "$Id: ZZROSpacePart.java,v 1.3 2000/11/06 12:39:39 tjl Exp $"; + + public ZZROSpacePart(ZZSpace space, String id) { + super(space, id); + } + + public void setContent(ZZCellHandle c, Object o) { + return; + } +} + diff --git a/Java/part/ZZROStrSpacePart.java b/Java/part/ZZROStrSpacePart.java new file mode 100644 index 0000000..2d75a03 --- /dev/null +++ b/Java/part/ZZROStrSpacePart.java @@ -0,0 +1,47 @@ +/* +ZZROStrSpacePart.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; + +/** EXPERIMENTAL: A read-only part of a ZZ space that only operates + * on IDs. + */ + +public abstract class ZZROStrSpacePart extends ZZROSpacePart { +public static final String rcsid = "$Id: ZZROStrSpacePart.java,v 1.3 2000/11/06 12:39:39 tjl Exp $"; + + public ZZROStrSpacePart(ZZSpace space, String id) { + super(space, id); + } + + public Object parseIDPart(String idPart) { + return null; + } + + public String generateID(Object parsed) { + return null; + } + public String generateIDPart(Object parsed) { + return null; + } +} + diff --git a/Java/script/Makefile b/Java/script/Makefile new file mode 100644 index 0000000..2397b86 --- /dev/null +++ b/Java/script/Makefile @@ -0,0 +1,53 @@ +PERLDIR=../../C++/script/Perl + + +IBMCFLAGS=-Dint64_t="long long" -Dlinux -g -I/BIG/ibmjdk/include -I/BIG/ibmjdk/include/linux -I../../C++ -I../../C++/script/Perl +CFLAGS=-g -I$(PERLDIR) + +IBMLDFLAGS=-L/BIG/ibmjdk/lib/linux/native_threads/ + +all: classes hdr jzigzag + +jzigzag: invoke.o zzfoo.o ZZScriptPerl.o ZZScriptAPI_1_JNI.o + gcc -o jzigzag -export-dynamic invoke.o zzfoo.o ZZScriptPerl.o ZZScriptAPI_1_JNI.o $(IBMLDFLAGS) -ljava `perl -MExtUtils::Embed -e ldopts` + +invoke.o: invoke.c + gcc $(IBMCFLAGS) -c invoke.c + +zzfoo.o: $(PERLDIR)/zzfoo.cpp + g++ $(CFLAGS) `perl -MConfig -e 'print "$$Config{ccflags} -I$$Config{installarchlib}/CORE"'` -c -o zzfoo.o -I../../C++ $(PERLDIR)/zzfoo.cpp + +ZZScriptPerl.o: ZZScriptPerl.cpp *.h + g++ $(IBMCFLAGS) -c -o ZZScriptPerl.o ZZScriptPerl.cpp + +ZZScriptAPI_1_JNI.o: ZZScriptAPI_1_JNI.cpp *.h + g++ $(IBMCFLAGS) -c -o ZZScriptAPI_1_JNI.o ZZScriptAPI_1_JNI.cpp + + +# all: classes hdr libZZScriptPerl.la + +classes: + javac -d .. *.java + +hdr: fi_iki_lukka_ZZScriptPerl.h + +fi_iki_lukka_ZZScriptPerl.h: ../fi/iki/lukka/ZZScriptPerl.class + javah -jni fi.iki.lukka.ZZScriptPerl + +# libZZScriptPerl.la: ZZScriptPerl.lo zzfoo.lo +# libtool g++ $(CFLAGS) -o libZZScriptPerl.la ZZScriptPerl.lo zzfoo.lo `perl -MConfig -e 'print "-L$$Config{installarchlib}/CORE -lperl $$Config{libs}"'` +# +# # Doesn't work due to DynaLoader! ARGH! +# #`perl -MExtUtils::Embed -e ccopts -e ldopts` +# +# zzfoo.lo: $(PERLDIR)/zzfoo.cpp +# libtool g++ $(CFLAGS) `perl -MConfig -e 'print "$$Config{ccflags} -I$$Config{installarchlib}/CORE"'` -c -o zzfoo.lo -I../../C++ $(PERLDIR)/zzfoo.cpp +# +# +# +# $(PERLDIR)/zzfoo.cpp: ../../C++/script/Perl/zzfoo.xs +# (cd $(PERLDIR); make zzfoo.cpp) +# +# +# ZZScriptPerl.lo: ZZScriptPerl.cpp *.h +# libtool g++ $(IBMCFLAGS) -c -o ZZScriptPerl.lo ZZScriptPerl.cpp diff --git a/Java/script/ZZId.h b/Java/script/ZZId.h new file mode 100644 index 0000000..94e346b --- /dev/null +++ b/Java/script/ZZId.h @@ -0,0 +1,12 @@ +#ifndef ZZID_H +#define ZZID_H + +// class _jobject; +// typedef _jobject* jobject; + +// #define ZZId jobject +// +// Arghh... +#define ZZId long + +#endif diff --git a/Java/script/ZZScriptAPI_1_JNI.cpp b/Java/script/ZZScriptAPI_1_JNI.cpp new file mode 100644 index 0000000..0ea5967 --- /dev/null +++ b/Java/script/ZZScriptAPI_1_JNI.cpp @@ -0,0 +1,31 @@ + +#include +#include "ZZId.h" +#include "ZZScriptAPI_1_JNI.h" +#include "zzfoo.h" + +const ZZScriptAPI_1_0_JNI::meth ZZScriptAPI_1_0_JNI::names[LASTMETH_] ; + /* + = { + { "getNeighbour", "(Ljava/lang/String;I)Lfi/iki/lukka/ZZCell;" }, + { "getHeadcell", "(Ljava/lang/String;I)Lfi/iki/lukka/ZZCell;" }, + { "newCell", "(Ljava/lang/String;I)Lfi/iki/lukka/ZZCell;" }, + { "delete", "()V" }, + { "connect", "(Ljava/lang/String;Lfi/iki/lukka/ZZCell;)V" }, + { "insert", "(Ljava/lang/String;ILfi/iki/lukka/ZZCell;)V" }, + { "disconnect", "(Ljava/lang/String;I)V" }, + { "getText", "()Ljava/lang/String;" }, + { "setText" "(Ljava/lang/String;)V" }, + }; */ + /* = { + { "getNeighbour", "(Ljava/lang/String;I)Lfi/iki/lukka/ZZCell;" }, + { "getHeadcell", "(Ljava/lang/String;I)Lfi/iki/lukka/ZZCell;" }, + { "newCell", "(Ljava/lang/String;I)Lfi/iki/lukka/ZZCell;" }, + { "delete", "()V" }, + { "connect", "(Ljava/lang/String;Lfi/iki/lukka/ZZCell;)V" }, + { "insert", "(Ljava/lang/String;ILfi/iki/lukka/ZZCell;)V" }, + { "disconnect", "(Ljava/lang/String;I)V" }, + { "getText", "()Ljava/lang/String;" }, + { "setText" "(Ljava/lang/String;)V" }, + }; */ + diff --git a/Java/script/ZZScriptAPI_1_JNI.h b/Java/script/ZZScriptAPI_1_JNI.h new file mode 100644 index 0000000..5f74cf9 --- /dev/null +++ b/Java/script/ZZScriptAPI_1_JNI.h @@ -0,0 +1,131 @@ +#ifndef ZZSCRIPT_API_1_JNI_H +#define ZZSCRIPT_API_1_JNI_H + +#define EXC() if(env->ExceptionOccurred()) {env->ExceptionDescribe(); env->FatalError("EXCEPTION");} + +// XXX ARGH +// #define MID(cell,id) (env->GetMethodID(env->GetObjectClass((jobject)cell), names[id].name, names[id].sig) || (env->FatalError("NoMethod"),(jmethodID)0)) +#define MID(cell,id) (env->GetMethodID(env->GetObjectClass((jobject)cell), names[id].name, names[id].sig)) + + +#include "ZZScriptAPI_1.h" + +class ZZScriptAPI_1_0_JNI : public ZZScriptAPI_1_0 { + protected: + JNIEnv *env; + jclass zzcell; + enum meths { + GETNEIGH, + HEADCELL, + NEWCELL, + DELETECELL, + CONNECTCELLS, + INSERTCELL, + DISCONNECT, + GETTEXT, + SETTEXT, + LASTMETH_ + }; + static const struct meth {char *name; char *sig;} names[LASTMETH_] + = { + { "getNeighbour", "(Ljava/lang/String;I)Lfi/iki/lukka/ZZCell;" }, + { "getHeadcell", "(Ljava/lang/String;I)Lfi/iki/lukka/ZZCell;" }, + { "newCell", "(Ljava/lang/String;I)Lfi/iki/lukka/ZZCell;" }, + { "delete", "()V" }, + { "connect", "(Ljava/lang/String;Lfi/iki/lukka/ZZCell;)V" }, + { "insert", "(Ljava/lang/String;ILfi/iki/lukka/ZZCell;)V" }, + { "disconnect", "(Ljava/lang/String;I)V" }, + { "getText", "()Ljava/lang/String;" }, + { "setText", "(Ljava/lang/String;)V" }, + }; + jmethodID mids[LASTMETH_]; + public: + ZZScriptAPI_1_0_JNI(JNIEnv *env0) { + utfref = 0; + strref = 0; + env = env0; + zzcell = env->FindClass("fi/iki/lukka/ZZCell"); + if(!zzcell) abort(); + zzcell = (jclass)env->NewGlobalRef(zzcell); + if(!zzcell) abort(); + for(int i=0; iGetMethodID(zzcell, names[i].name, names[i].sig); + if(!mids[i]) { + abort(); + } + } + } + + static const int verbose = 1; + + virtual ZZId get_cell (ZZId from, const char *dim, int dir) { + printf("CB GETCELL\n"); + long res = (long)env->CallObjectMethod((jobject)from, MID(from,GETNEIGH), + env->NewStringUTF(dim), (jint)dir); + EXC(); + return res; + }; + virtual ZZId get_headcell (ZZId from, const char *dim, int dir) + { + printf("CB HEADCELL\n"); + EXC(); + abort(); + }; + virtual ZZId new_cell (ZZId from, const char *dim, int dir) { + printf("CB NEWCELL\n"); + long res = (long)env->CallObjectMethod((jobject)from, MID(from,NEWCELL), + env->NewStringUTF(dim), (jint)dir); + EXC(); + return res; + } + virtual void delete_cell (ZZId cell) { + printf("CB DELCELL\n"); + env->CallVoidMethod((jobject)cell, MID(cell,DELETECELL)); + EXC(); + }; + virtual void connect_cells (ZZId from, const char *dim, ZZId to) { + printf("CB CONCELL\n"); + env->CallVoidMethod((jobject)from, MID(from,CONNECTCELLS), + env->NewStringUTF(dim), (jobject)to); + EXC(); + }; + virtual void insert_cell (ZZId where, const char *dim, int dir, ZZId what) { + printf("CB INSCELL\n"); + env->CallVoidMethod((jobject)where, MID(where,INSERTCELL), + env->NewStringUTF(dim), (jint)dir, (jobject)what); + EXC(); + }; + virtual void disconnect (ZZId from, const char *dim, int dir) { + printf("CB DISCELL\n"); + env->CallVoidMethod((jobject)from, MID(from,NEWCELL), + env->NewStringUTF(dim), (jint)dir); + EXC(); + }; + const char *utfref; + jstring strref; + virtual const char *get_text (ZZId cell) { + printf("CB GETTEXT\n"); + if(utfref) { + // XXX? + env->ReleaseStringUTFChars(strref, utfref); + } + strref = (jstring)env->CallObjectMethod((jobject)cell, MID(cell,GETTEXT)); + utfref = env->GetStringUTFChars(strref,0); + EXC(); + return utfref; + }; + virtual void set_text (ZZId cell, const char *str) { + printf("CB SETTEXT\n"); + env->CallVoidMethod((jobject)cell, MID(cell,SETTEXT), + env->NewStringUTF(str)); + EXC(); + printf("CB SETTEXT ret\n"); + }; + virtual int popup_warning (const char *text) { + abort(); + }; + + +}; + +#endif diff --git a/Java/script/ZZScriptPerl.cpp b/Java/script/ZZScriptPerl.cpp new file mode 100644 index 0000000..c17c867 --- /dev/null +++ b/Java/script/ZZScriptPerl.cpp @@ -0,0 +1,55 @@ +#include +#include "ZZId.h" +#include "ZZScriptAPI_1_JNI.h" +#include "zzfoo.h" + +static jclass zzspclass; +static jfieldID ptrid; + +extern "C" { +JNIEXPORT void JNICALL Java_fi_iki_lukka_ZZScriptPerl_init + (JNIEnv *env, jobject foo) +{ + if(!zzspclass) + zzspclass = (jclass)env->NewGlobalRef(env->GetObjectClass(foo)); + ptrid = env->GetFieldID(zzspclass, "ptr", "J"); + if(!ptrid) abort(); + ZZScriptAPI_1_0_JNI *j = new ZZScriptAPI_1_0_JNI(env); + zzperl_init(j); + env->SetLongField(foo, ptrid, (jlong)j); +} + +JNIEXPORT void JNICALL Java_fi_iki_lukka_ZZScriptPerl_call + (JNIEnv *env, jobject foo, jstring code0, jobject view0, jobject + cview0, jobject scr0, jobject cur0, jstring dimx0, jstring dimy0) +{ + printf("ENTERING PERLCALL\n"); + ZZScriptAPI_1_0_JNI *j = (ZZScriptAPI_1_0_JNI *) env->GetLongField(foo, ptrid); + if(!j) abort(); + char *code = (char *)env->GetStringUTFChars(code0, 0); + char *dimx = (char *)env->GetStringUTFChars(dimx0, 0); + char *dimy = (char *)env->GetStringUTFChars(dimy0, 0); + + zzperl_call(code, (long)view0, (long)cview0, (long)scr0, (long)cur0, dimx, dimy); + + env->ReleaseStringUTFChars(code0,code); + env->ReleaseStringUTFChars(dimx0,dimx); + env->ReleaseStringUTFChars(dimy0,dimy); + printf("RETURNING FROM PERLCALL\n"); + +} + +JNINativeMethod ms[2] = { +{ "init", "()V", Java_fi_iki_lukka_ZZScriptPerl_init }, +{ "call", "(Ljava/lang/String;Lfi/iki/lukka/ZZCell;Lfi/iki/lukka/ZZCell;Lfi/iki/lukka/ZZCell;Lfi/iki/lukka/ZZCell;Ljava/lang/String;Ljava/lang/String;)V", +Java_fi_iki_lukka_ZZScriptPerl_call } +}; + +void zsp_install(JNIEnv *env) { + zzspclass = env->FindClass("fi/iki/lukka/ZZScriptPerl"); + if(!zzspclass) abort(); + zzspclass = (jclass)env->NewGlobalRef(zzspclass); + env->RegisterNatives(zzspclass, ms, 2); +} + +} diff --git a/Java/script/ZZScriptPerl.java b/Java/script/ZZScriptPerl.java new file mode 100644 index 0000000..58ec097 --- /dev/null +++ b/Java/script/ZZScriptPerl.java @@ -0,0 +1,9 @@ +package org.gzigzag; + +public class ZZScriptPerl { + long ptr; + public ZZScriptPerl() { init(); }; + public native void init(); + public native void call(String code, ZZCell view, ZZCell controlView, + ZZCell script, ZZCell cur, String dimX, String dimY); +} diff --git a/Java/script/invoke.c b/Java/script/invoke.c new file mode 100644 index 0000000..2849ae6 --- /dev/null +++ b/Java/script/invoke.c @@ -0,0 +1,76 @@ +// Copied from +// http://java.sun.com/docs/books/tutorial/native1.1/invoking/example-1dot1/invoke.c + +#include + +#ifdef _WIN32 +#define PATH_SEPARATOR ';' +#else /* UNIX */ +#define PATH_SEPARATOR ':' +#endif + +// #define USER_CLASSPATH "." /* where Prog.class is */ + +extern void zsp_install(JNIEnv *env); + +main() { + JNIEnv *env; + JavaVM *jvm; + JDK1_1InitArgs vm_args; + jint res; + jclass cls; + jmethodID mid; + jstring jstr; + jobjectArray args; + char classpath[1024]; + + + /* IMPORTANT: specify vm_args version # if you use JDK1.1.2 and beyond */ + vm_args.version = 0x00010001; + + JNI_GetDefaultJavaVMInitArgs(&vm_args); + // Tjl + vm_args.classpath = getenv("CLASSPATH"); + +// /* Append USER_CLASSPATH to the end of default system class path */ +// sprintf(classpath, "%s%c%s", +// vm_args.classpath, PATH_SEPARATOR, USER_CLASSPATH); +// vm_args.classpath = classpath; + + /* Create the Java VM */ + res = JNI_CreateJavaVM(&jvm,&env,&vm_args); + if (res < 0) { + fprintf(stderr, "Can't create Java VM\n"); + exit(1); + } + + zsp_install(env); + + cls = (*env)->FindClass(env, "foo/Test1"); + if (cls == 0) { + fprintf(stderr, "Can't find foo/Test1 class\n"); + exit(1); + } + + mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V"); + if (mid == 0) { + fprintf(stderr, "Can't find Prog.main\n"); + exit(1); + } + + jstr = (*env)->NewStringUTF(env, " from C!"); + if (jstr == 0) { + fprintf(stderr, "Out of memory\n"); + exit(1); + } + args = (*env)->NewObjectArray(env, 1, + (*env)->FindClass(env, "java/lang/String"), jstr); + if (args == 0) { + fprintf(stderr, "Out of memory\n"); + exit(1); + } + (*env)->CallStaticVoidMethod(env, cls, mid, args); + + (*jvm)->DestroyJavaVM(jvm); +} + diff --git a/Java/storage/ContentStore.java b/Java/storage/ContentStore.java new file mode 100644 index 0000000..1f027b6 --- /dev/null +++ b/Java/storage/ContentStore.java @@ -0,0 +1,35 @@ +/* +ContentStore.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** An interface for storing contents info in. + * The Objects are supposed to be either String or Span type. + */ + +public interface ContentStore { +String rcsid = "$Id: ContentStore.java,v 1.4 2000/09/19 10:32:00 ajk Exp $"; + void put(String id1, Object what); + Object get(String id); +} + diff --git a/Java/storage/ContentStorer.java b/Java/storage/ContentStorer.java new file mode 100644 index 0000000..86b234d --- /dev/null +++ b/Java/storage/ContentStorer.java @@ -0,0 +1,36 @@ +/* +ContentStore.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** An interface for storing contents info. + * The difference with ContentStore is that this is analogous to + * ZZDimStorer whereas ContentStore is more like ZZDimension. + * The Objects are supposed to be either String or Span type. + */ + +public interface ContentStorer { +String rcsid = "$Id: ContentStorer.java,v 1.3 2000/09/19 10:32:00 ajk Exp $"; + void putContent(String id, Object what); +} + diff --git a/Java/storage/CountingStream.java b/Java/storage/CountingStream.java new file mode 100644 index 0000000..7edbb3b --- /dev/null +++ b/Java/storage/CountingStream.java @@ -0,0 +1,71 @@ +/* +CountingStream.java + * + * Copyright (c) 2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.awt.*; +import java.util.*; +import java.io.*; + +/** Something Java should have: we conut our position in the stream. + */ + +public class CountingStream extends FilterInputStream { + + int curPos = 0; + + public CountingStream(InputStream is) { + super(is); + } + + public int read() throws IOException { + int c = super.read(); + curPos++; + return c; + } + + public int read(byte b[]) throws IOException { + int n = super.read(b); + if(n < 0) return n; + curPos += n; + return n; + } + + public int read(byte b[], + int off, + int len) throws IOException { + int n = super.read(b, off, len); + if(n < 0) return n; + curPos += n; + return n; + } + + public long skip(long n) throws IOException { + long ns = super.skip(n); + curPos += ns; + return ns; + } + + public int getCount() { + return curPos; + } + +} diff --git a/Java/storage/DimStore.java b/Java/storage/DimStore.java new file mode 100644 index 0000000..d4bc5f9 --- /dev/null +++ b/Java/storage/DimStore.java @@ -0,0 +1,33 @@ +/* +DimStore.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** An interface for storing dimension info in. + */ + +public interface DimStore { +String rcsid = "$Id: DimStore.java,v 1.3 2000/09/19 10:32:00 ajk Exp $"; + void put(String id1, String id2); + String get(String id, int dir); +} diff --git a/Java/storage/DirStreamSet.java b/Java/storage/DirStreamSet.java new file mode 100644 index 0000000..8833ccc --- /dev/null +++ b/Java/storage/DirStreamSet.java @@ -0,0 +1,91 @@ +/* +DirStreamSet.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka, locking by Antti-Juhani Kaijanaho + */ +package org.gzigzag; +import java.util.*; +import java.io.*; + +/** A directory implementation of StreamSet + */ + +public class DirStreamSet extends StreamSet { +public static final String rcsid = "$Id: DirStreamSet.java,v 1.5 2000/09/18 14:28:22 tjl Exp $"; + File dir; + + public InputStream getInputStream(String id) { + try { + File f = new File(dir, id); + if(!f.exists()) return null; + if(!f.canRead()) throw new ZZFatalError("Can't read file"); + return new BufferedInputStream( + new FileInputStream(f), 4096); + } catch(Exception e) { + ZZLogger.exc(e); + throw new ZZFatalError("File problem"); + } + } + + public OutputStream getAppendStream(String id) { + try { + File f = new File(dir, id); + return new BufferedOutputStream( + new FileOutputStream(f.getPath(), true)); + } catch(Exception e) { + ZZLogger.exc(e); + throw new ZZFatalError("File problem"); + } + } + public boolean exists(String id) { + File fn = new File(dir, id); + return fn.exists(); + } + + public Writable getWritable(String id) { + if(id == null || id.equals("")) + throw new ZZError("Can't use writables with null or empty name"); + try { + File fn = new File(dir, id); + final RandomAccessFile f = new RandomAccessFile(fn, "rw"); + return new FileWritable(f) ; + } catch(Exception e) { + ZZLogger.exc(e); + throw new ZZError(" "+e); + } + } + + public DirStreamSet(File dir0) { + try { + dir = dir0; + if(dir.exists() && !dir.isDirectory()) { + throw new ZZError("MUST BE DIRECTORY!!!! "+dir); + } + if(!dir.exists()) { + dir.mkdirs(); + } + } catch(Exception e) { + ZZLogger.exc(e); + throw new ZZError(" "+e); + } + } +} + + diff --git a/Java/storage/DummyStreamSet.java b/Java/storage/DummyStreamSet.java new file mode 100644 index 0000000..f2afe8c --- /dev/null +++ b/Java/storage/DummyStreamSet.java @@ -0,0 +1,50 @@ +/* +DummyStreamSet.java + * + * Copyright (c) 1999-2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ + +package org.gzigzag; + +import java.awt.*; +import java.applet.*; +import java.io.*; +import java.util.*; + +/** A dummy stream set for ZZ spaces. + * Save fails, mostly for applets and testing. + */ + +public class DummyStreamSet extends StreamSet { + public InputStream getInputStream(String id) { return null; } + public OutputStream getAppendStream(String id) { return null; } + public boolean exists(String id) { return false; } + + Hashtable ws = new Hashtable(); + public Writable getWritable(String id) { + Writable res = (Writable)ws.get(id); + if(res == null) { + res = new MemWritable(); + ws.put(id, res); + } + return res; + } +} + diff --git a/Java/storage/FileWritable.java b/Java/storage/FileWritable.java new file mode 100644 index 0000000..7c1c250 --- /dev/null +++ b/Java/storage/FileWritable.java @@ -0,0 +1,251 @@ +/* +FileWritable.java + * + * Copyright (c) 2000, Ted Nelson, Tuomas Lukka and Vesa Parkkinen + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka & Vesa Parkkinen + */ +package org.gzigzag; +import java.util.*; +import java.io.*; + +/** A Writable that is just a file. + * + * Default: caching off.. + */ + +// Beginning of block: +// long: index of next block +// long: offset in subfile0 to the name. + +public class FileWritable implements Writable { + public static final String rcsid = + "$Id: FileWritable.java,v 1.6 2000/09/19 10:32:00 ajk Exp $"; + public static final boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + public static final int BUF_SIZE = 512; + + RandomAccessFile f; + + byte[] r_buffer; + byte[] w_buffer; + + boolean cache; + boolean dirty; + + // read buffer offset + long off; + // write buffer offset + long w_off; + // read bytes in buffer + int r_size; + // bytes written + int written; + + /* + * XXX TODO: not quite there yet... + */ + public void write(long offset, byte[] data) { + //p("write"); + try { + if( ! cache ){ + f.seek(offset); + f.write(data); + return; + }else { + // clear read cache + if ( offset < off + r_size && + offset + data.length > off ) { + + off = 0; + r_size = 0; + } + + if ( data.length > BUF_SIZE ){ + //p(" > "); + flush(); + f.seek(offset); + f.write(data); + return; + } + if ( offset + data.length < w_off ){ + //p(" under "); + f.seek(offset); + f.write(data); + //return; + }else if ( offset > w_off + written ){ + //p(" over "); + flush(); + w_off = offset; + written = data.length; + System.arraycopy( data, 0, w_buffer, 0, written ); + dirty = true; + }else if ( offset < w_off && offset + data.length > w_off ){ + //p(" partial "); + flush(); + f.seek(offset); + f.write(data); + + } else if( offset == w_off + written && + BUF_SIZE - written > data.length ) { + //p(" hit: " + offset); + System.arraycopy( data, 0, w_buffer, written, data.length); + written += data.length; + //p(" written = " + written); + dirty = true; + }else { + //p(" other "); + flush(); + f.seek(offset); + f.write(data); + return; + } + + } + } catch(Exception e) { + ZZLogger.exc(e); + throw new ZZError(" "+e); + } + } + + + public byte[] read(long offset, int n) { + //p("read"); + try { + + byte[] b = new byte[n]; + + if( ! cache ){ + f.seek(offset); + f.read(b); + return b; + } else { + if( offset < w_off + written && + offset + n > w_off ) { + flush(); + } + if ( offset > off && offset - off + n < r_size ){ + + System.arraycopy(r_buffer, (int)(offset - off), b, 0, n ); + return b; + } + + f.seek(offset); + + r_size = f.read(r_buffer); + System.arraycopy(r_buffer, 0, b, 0, n ); + off = offset; + return b; + } + + } catch(Exception e) { + ZZLogger.exc(e); + throw new ZZError(" read "+offset+" "+n+" "+e); + } + } + + + public void read(long offset, byte b[], int o, int n) { + //p("read2"); + try { + if (! cache ){ + f.seek(offset); + f.read(b, o, n); + }else { + if( offset + o < w_off + written && + offset + o + n > w_off ) { + flush(); + } + + if ( offset + o> off && offset + o - off + n < r_size ){ + + System.arraycopy(r_buffer, (int)(offset + o - off), + b, o, n ); + }else { + f.seek(offset + o); + r_size = f.read(r_buffer); + System.arraycopy(r_buffer, 0, b, o, n ); + off = offset + o; + } + } + + } catch(Exception e) { + ZZLogger.exc(e); + throw new ZZError(" read " +e); + } + + } + + public long length() { + try { + return f.length(); + + } catch(Exception e) { + ZZLogger.exc(e); + throw new ZZError(" "+e); + } + } + + + public void flush() { + if ( ! cache ) return; + if( ! dirty || written == 0) return; + + try{ + + f.seek(w_off); + f.write(w_buffer, 0, written); + dirty = false; + //p("FLUSH " + written); + written = 0; + + } catch(Exception e) { + ZZLogger.exc(e); + throw new ZZError(" "+e); + } + + } + + public FileWritable(RandomAccessFile f) { + + /* + * set this to true, if you want to test caching + */ + this(f, false); + } + + public FileWritable(RandomAccessFile f, boolean b) { + //p("FW: create"); + this.f = f; + cache = b; + + if ( cache ){ + r_buffer = new byte[BUF_SIZE]; + w_buffer = new byte[BUF_SIZE]; + }else{ + r_buffer = null; + } + dirty = false; + r_size = 0; + } +} + + + diff --git a/Java/storage/Flushable.java b/Java/storage/Flushable.java new file mode 100644 index 0000000..d5e847f --- /dev/null +++ b/Java/storage/Flushable.java @@ -0,0 +1,39 @@ +/* +Flushable.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** An interface for things that can be flushed. + * Mostly for determining if e.g. a ZZSpace needs flushing. + */ + +public interface Flushable { +String rcsid = "$Id: Flushable.java,v 1.3 2000/09/19 10:32:00 ajk Exp $"; + /** Flush the contents not yet flushed to disk. + */ + void flush(); + /** Whether this object is in fact in a cache-keeping mode. + */ + boolean isCaching(); +} + diff --git a/Java/storage/GZZ0.java b/Java/storage/GZZ0.java new file mode 100644 index 0000000..dc28667 --- /dev/null +++ b/Java/storage/GZZ0.java @@ -0,0 +1,191 @@ +/* +GZZ0.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.io.*; + +/** An implementation of the GZZ0 file format. + */ + +public class GZZ0 { +String rcsid = "$Id: GZZ0.java,v 1.7 2001/03/01 13:53:53 ajk Exp $"; + public static boolean dbg = false; + final static void p(String s) { if(dbg) System.out.println(s); } + final static void pa(String s) { System.out.println(s); } + + final int magic = 0x475a5a30; // "GZZ0" + final int version = 0; + final byte rTime = 116; + + public interface Runner { + /** Returns the GZZ0 content type of this runner. + */ + int getContentType(); + /** Returns the GZZ0 content version of this runner. + */ + int getContentVersion(); + /** Read a run. + */ + void readRun(InputStream is); + /** Start writing. + */ + void startWrite(OutputStream os); + /** Finish writing. + */ + void endWrite(); + + } + + StreamSet ss; + String id; + + public GZZ0(StreamSet ss, String id) { + this.ss = ss; this.id = id; + } + + /** Read the latest dataset into the given runner. + * @param r The runner into which to give the runs + * @param maxtimestamp The maximum timestamp whose changes to include. + * @return The latest timestamp read. + */ + public int read(Runner r, int maxtimestamp) { + InputStream is = ss.getInputStream(id); + CountingStream counts = null; + if(dbg) { + is = counts = new CountingStream(is); + } + DataInputStream dis = new DataInputStream(is); + + // Read header + try { + int i = dis.readInt(); + if(i != magic) + throw new ZZFatalError("Invalid file format! Doesn't begin with GZZ0 magic"); + i = dis.readInt(); + if(i != version) + throw new ZZFatalError("Invalid file version! Not "+version); + i = dis.readInt(); + if(i != r.getContentType()) + throw new ZZFatalError("Wrong content type!"); + i = dis.readInt(); + if(i != r.getContentVersion()) + throw new ZZFatalError("Wrong content version!"); + } catch(IOException e) { + ZZLogger.exc(e); + throw new ZZFatalError("Reading file"); + } + + // Read body. + + int lastTime = -1; + boolean eofOk = true; + byte[] byt = new byte[4096]; + try { + while(true) { + eofOk = true; + byte rectype = dis.readByte(); + eofOk = false; + if(rectype != rTime) + throw new ZZFatalError("Invalid timestamp record! " + id + " " + + (counts != null ? counts.getCount() : -1)); + lastTime = dis.readInt(); + int nbytes = dis.readInt(); + + if(maxtimestamp > 0 && lastTime > maxtimestamp) { + dis.close(); + return lastTime; + } + + if(nbytes > byt.length) + byt = new byte[nbytes]; + + dis.readFully(byt, 0, nbytes); + ByteArrayInputStream bis = + new ByteArrayInputStream(byt, 0, nbytes); + r.readRun(bis); + } + } catch(EOFException e) { + if(!eofOk) + throw new ZZFatalError("Unexpected eof in simpledimfile"); + } catch(IOException e) { + ZZLogger.exc(e); + throw new ZZFatalError("Reading file"); + } + return lastTime; + } + + ByteArrayOutputStream outputStream; + DataOutputStream dos; + Runner runner; + int timestamp; + + /** Write the changes back. + * XXX Should check runner's type... + */ + public void startWrite(int timestamp, Runner r) { + + outputStream = new ByteArrayOutputStream(); + this.timestamp = timestamp; + this.runner = r; + + runner.startWrite(new DataOutputStream(outputStream)); + } + + /** Finish writing. */ + public void endWrite(boolean forceStamp) { + boolean ex = ss.exists(id); + runner.endWrite(); + + try { + OutputStream os = ss.getAppendStream(id); + dos = new DataOutputStream(os); + if(!ex) { + // Write header. + dos.writeInt(magic); + dos.writeInt(version); + dos.writeInt(runner.getContentType()); + dos.writeInt(runner.getContentVersion()); + dos.flush(); + } + byte[] byt = outputStream.toByteArray(); + if(byt.length == 0 && !forceStamp) { + pa("Not writing "+id); + return; + } + pa("Writing "+id+" "+byt.length); + + dos.writeByte(rTime); + dos.writeInt(timestamp); + dos.writeInt(byt.length); + dos.write(byt); + dos.flush(); + dos = null; + outputStream = null; + runner = null; + } catch(IOException e) { + ZZLogger.exc(e); + throw new ZZFatalError("Writing file"); + } + } + +} diff --git a/Java/storage/MemWritable.java b/Java/storage/MemWritable.java new file mode 100644 index 0000000..b882c4d --- /dev/null +++ b/Java/storage/MemWritable.java @@ -0,0 +1,76 @@ +/* +MemWritable.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ +package org.gzigzag; +import java.util.*; + +/** A writable that stores its contents in memory. + * Used to make scrolls work in applets. Not necessarily very efficient; + * however, I don't think that's so much of an issue in applets, where we + * won't save a lot of data anyway. + */ + +public class MemWritable implements Writable { +String rcsid = "$Id: MemWritable.java,v 1.1 2000/12/26 22:48:37 bfallenstein Exp $"; + + /** The size of the chunks in which memory is allocated. */ + final int CHUNK = 500; + + /** The data. */ + byte[] d = new byte[CHUNK]; + + /** The length of the data actually used. + * len-1 is the highest index of any data ever written. + */ + int len = 0; + + public void extend() { + byte[] nu = new byte[d.length + CHUNK]; + System.arraycopy(d, 0, nu, 0, len); + d = nu; + } + + public void write(long offset0, byte[] data) { + int offset = (int)offset0; + int n = data.length; + while(offset + n >= d.length) extend(); + System.arraycopy(data, 0, d, offset, n); + if(offset + n > len) len = offset + n; + } + public byte[] read(long offset0, int n) { + byte[] res = new byte[n]; + read(offset0, res, 0, n); + return res; + } + public void read(long offset0, byte b[], int off, int n){ + System.out.println("MemWritable.read "+d.length+" "+len+" params "+ + offset0+" "+b.length+" "+off+" "+n); + int offset = (int)offset0; + while(offset + n >= d.length) extend(); + System.arraycopy(d, offset, b, off, n); + } + public long length() { + return len; + } + public void flush() {} +} + diff --git a/Java/storage/Recs.pl b/Java/storage/Recs.pl new file mode 100644 index 0000000..07dd0b9 --- /dev/null +++ b/Java/storage/Recs.pl @@ -0,0 +1,232 @@ +# +# $Id: Recs.pl,v 1.8 2001/03/06 13:44:39 ajk Exp $ +# +# Generate Recs.java for record types for file formats. +# +# Java Serializable is CLOSE but not quite close enough to what we need +# (e.g. it would write out the "offset" field) +# AND we want a standard binary format. + + +$file = $ARGV[0]; +$file = "Recs.pl" if ($file eq ""); +open F, ">$file" or die "Can't open file $file"; +$rcsid = '$Id: Recs.pl,v 1.8 2001/03/06 13:44:39 ajk Exp $'; +print F <[2]; + my $len = join '+', + " super.length() ", + map { + $_->[0] eq "long" and 8 + or $_->[0] eq "int" and 4 + or $_->[0] eq "short" and 2 + or $_->[0] eq "boolean" and 1 + or $_->[0] eq "String" and + " (2 + $_->[1].getBytes(\"UTF8\").length) " + or die "Invalid type $_->[0]" + } @f; + + my $write = join '', + map { + $_->[0] eq "String" and + "{ + byte[] bt = $_->[1].getBytes(\"UTF8\"); + s.writeShort(bt.length); + s.write(bt, 0, bt.length); + } + " + # or $_->[0] eq "bool" and "s.writeBoolean($_->[1]);" + or "s.write".(ucfirst $_->[0])."($_->[1]);"; + } @f; + + my $read = join '', + map { + $_->[0] eq "String" and + "{ + short l = s.readShort(); + byte[] bt = new byte[l]; + int n = s.read(bt); + if(n!=l) throw new ZZError(\"NOT ENOUGH DATA\"); + $_->[1] = new String(bt, \"UTF8\"); + } + " + # or $_->[0] eq "bool" and "$_->[1] = s.readBoolean();" + or "$_->[1] = s.read".(ucfirst $_->[0])."();"; + } @f; + + my $tostring = join '', + map { + qq( + " $_->[1]: "+$_->[1]+"\\n" ) + } @f; + + + print F <[0] extends $_->[1] { + $_->[2]; + public int length() { + try { + return $len; + } catch(Exception e) { + ZZLogger.exc(e); + throw new ZZError("ARGH"); + } + } + public short getTypeNo() { return $_->[3]; } + public void write_data(DataOutputStream s) throws IOException { + super.write_data(s); + $write + } + public void read_data(long offs, DataInputStream s) + throws IOException { + super.read_data(offs, s); + $read + } + public String toString() { + return "$_->[0]:\\n" + $tostring + + super.toString(); + } + } +END +} + +print F qq[ + static public Record createRecord(int typ) { + $rettype + throw new ZZError("Invalid record type "+typ); + } +} +]; diff --git a/Java/storage/SimpleContentFile.java b/Java/storage/SimpleContentFile.java new file mode 100644 index 0000000..f5ffc10 --- /dev/null +++ b/Java/storage/SimpleContentFile.java @@ -0,0 +1,129 @@ +/* +SimpleContentFile.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.io.*; + +/** A simple content file format. + * The format consists of records: s(cell)(string), S(cell)(span), + * t(time4). Currently spans are stored in their stringized format + * but this may be changed later. + *

    + * The record types are defined by the ASCII values of the above characters. + *

    + * Note the similarity with SimpleDimFile. + */ + +public class SimpleContentFile implements ContentStorer, GZZ0.Runner { +public static final String rcsid = "$Id: SimpleContentFile.java,v 1.6 2000/09/19 10:32:00 ajk Exp $"; + + final byte rString = 115; + final byte rSpan = 83; + + ContentStorer sto; + public void startRead(ContentStorer sto) { + this.sto = sto; + } + public void endRead() { + sto = null; + } + + public int getContentType() { + return 43; + } + public int getContentVersion() { + return 0; + } + + + public void readRun(InputStream is) { + DataInputStream dis = new DataInputStream(is); + boolean eofOk = true; + try { + while(true) { + eofOk = true; + byte rectype = dis.readByte(); + eofOk = false; + switch(rectype) { + case rString: { + String id = dis.readUTF(); + String ct = dis.readUTF(); + sto.putContent(id, ct); } + break; + case rSpan: { + String id = dis.readUTF(); + String cts = dis.readUTF(); + Span sp = Span.parse(cts); + sto.putContent(id, sp); } + break; + default: + throw new ZZFatalError("Invalid record"); + } + } + } catch(EOFException e) { + if(!eofOk) + throw new ZZError("Unexpected eof in simpledimfile"); + } catch(IOException e) { + ZZLogger.exc(e); + throw new ZZFatalError("Reading file"); + } + } + + DataOutputStream dos; + + public void putContent(String id, Object ct) { + if(ct == null) + throw new ZZFatalError("Tried to store null content!"); + try { + if(ct instanceof String) { + dos.writeByte(rString); + dos.writeUTF(id); + dos.writeUTF((String)ct); + } else if(ct instanceof Span) { + dos.writeByte(rSpan); + dos.writeUTF(id); + dos.writeUTF(((Span)ct).toString()); + } else { + throw new ZZFatalError("Can't put odd object: "+ct); + } + } catch(IOException e) { + ZZLogger.exc(e); + throw new ZZFatalError("Reading file"); + } + } + + public void startWrite(OutputStream dos) { + this.dos = new DataOutputStream(dos); + } + + public void endWrite() { + try { + dos.flush(); + dos = null; + } catch(IOException e) { + ZZLogger.exc(e); + throw new ZZFatalError("Reading file"); + } + } + +} diff --git a/Java/storage/SimpleDimFile.java b/Java/storage/SimpleDimFile.java new file mode 100644 index 0000000..546fac7 --- /dev/null +++ b/Java/storage/SimpleDimFile.java @@ -0,0 +1,137 @@ +/* +SimpleDimFile.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.io.*; + +/** A simple dimension file format. + * The format consists of records: c(cell)(cell), d+(cell), d-(cell), + * Later to be extended with h(cell) which defines the + * given cell to be the headcell of its rank. + *

    + * The record types are defined by the ASCII values of the above characters. + *

    + */ + +public class SimpleDimFile implements ZZDimStorer, GZZ0.Runner{ +public static final String rcsid = "$Id: SimpleDimFile.java,v 1.6 2000/09/19 10:32:00 ajk Exp $"; + + final byte rConn = 99; + final byte rDisc = 100; + final byte rPlus = 43; + final byte rMinus = 45; + + + + ZZDimStorer sto; + public void startRead(ZZDimStorer sto) { + this.sto = sto; + } + public void endRead() { + sto = null; + } + + public int getContentType() { + return 42; + } + public int getContentVersion() { + return 0; + } + + public void readRun(InputStream is) { + DataInputStream dis = new DataInputStream(is); + boolean eofOk = true; + try { + while(true) { + eofOk = true; + byte rectype = dis.readByte(); + eofOk = false; + switch(rectype) { + case rConn: + String id1 = dis.readUTF(); + String id2 = dis.readUTF(); + sto.storeConnect(id1, id2); + break; + case rDisc: + byte bdir = dis.readByte(); + int dir; + if(bdir == rPlus) + dir = 1; + else if(bdir == rMinus) + dir = -1; + else + throw new ZZFatalError("Invalid directon"); + String id = dis.readUTF(); + sto.storeDisconnect(id, dir); + break; + default: + throw new ZZFatalError("Invalid record"); + } + } + } catch(EOFException e) { + if(!eofOk) + throw new ZZFatalError("Unexpected eof in simpledimfile"); + } catch(IOException e) { + ZZLogger.exc(e); + throw new ZZFatalError("Reading file"); + } + } + + DataOutputStream dos; + + public void storeConnect(String a, String b) { + try { + dos.writeByte(rConn); + dos.writeUTF(a); + dos.writeUTF(b); + } catch(IOException e) { + ZZLogger.exc(e); + throw new ZZFatalError("Writing file"); + } + } + public void storeDisconnect(String a, int dir) { + try { + dos.writeByte(rDisc); + dos.writeByte(dir > 0 ? rPlus : rMinus); + dos.writeUTF(a); + } catch(IOException e) { + ZZLogger.exc(e); + throw new ZZFatalError("Writing file"); + } + } + + public void startWrite(OutputStream dos) { + this.dos = new DataOutputStream(dos); + } + + public void endWrite() { + try { + dos.flush(); + dos = null; + } catch(IOException e) { + ZZLogger.exc(e); + throw new ZZFatalError("Reading file"); + } + } + +} diff --git a/Java/storage/Sliced.java b/Java/storage/Sliced.java new file mode 100644 index 0000000..9c9b953 --- /dev/null +++ b/Java/storage/Sliced.java @@ -0,0 +1,87 @@ +/* +Sliced.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +class FEIHFSEHFSHFSMEKFMESKUFMSEF { } + +/** EXPERIMENTAL, NOT FUNCTIONAL: A dimension created by splicing + * together several other + * dimensions. Inter-dimension connections are stored locally and + * in preflets. + *

    + * This class extends ZZLocalDimension, which is used for caching + * accesses. + *

    + * What makes things easier here is that the slice definition guarantees + * that all ranks that do not come from s.0 remain untouched. All alterations + * are insertions of ranks from the other slices + * in the middle of ranks from s.0 (of course, removing preflets and the like) + */ + +/* +public class Sliced extends ZZDimension { +public static final String rcsid = "$Id: Sliced.java,v 1.8 2000/11/07 23:07:34 tjl Exp $"; + + ZZDimension[] slices; + + ZZSlicedDimSpace sds; + + Sliced(ZZSlicedDimSpace ss, ZZDimension[] s) { + sds = ss; + slices = s; + } + + public String s(String c, int steps, ZZObs o) { + String oid = sds.getOrigID(c); + int sli = sds.getSliceID(c); + ZZDimension slice = slices[sli]; + String ores = slice.s(oid, steps, o); + if(ores==null) return null; + return sds.getConvID(sli, ores); + } + public String h(String c, int dir, ZZObs o) { + String oid = sds.getOrigID(c); + int sli = sds.getSliceID(c); + ZZDimension slice = slices[sli]; + String ores = slice.h(oid, dir, o); + if(ores==null) return null; + return sds.getConvID(sli, ores); + } + public void connect(String c, String d) { + int ci = sds.getSliceID(c); + int di = sds.getSliceID(d); + // Silently fail + if(sds.getSliceID(c) != sds.getSliceID(d)) + return; + String cor = sds.getOrigID(c); + String dor = sds.getOrigID(d); + slices[ci].connect(cor, dor); + } + public void disconnect(String c, int dir) { + String oid = sds.getOrigID(c); + int sli = sds.getSliceID(c); + slices[sli].disconnect(oid, dir); + } +} +*/ diff --git a/Java/storage/SlicedCursor.java b/Java/storage/SlicedCursor.java new file mode 100644 index 0000000..8d055ec --- /dev/null +++ b/Java/storage/SlicedCursor.java @@ -0,0 +1,149 @@ + +/* +SlicedCursor.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import org.gzigzag.*; +import java.util.*; + +/** A dimension for the sliced space cursor. + */ + +class KUHELFMSKUFHSUKFMSEF { } + +/* +public class SlicedCursor extends Sliced { +public static final String rcsid = "$Id: SlicedCursor.java,v 1.7 2000/11/07 23:07:34 tjl Exp $"; + + static boolean dbg = true; + static final void p(String s) { if(dbg) System.out.println(s); } + + String prefletdim; + + // Need several mappings: + // Our cells to preflet cells in s0. + Hashtable our2prefs = new Hashtable(); + // Preflet cells to our cells. + Hashtable pref2ours = new Hashtable(); + + SlicedCursor(ZZSlicedDimSpace ss, ZZDimension[] s, + String prefletdim) { + super(ss, s); + this.prefletdim = prefletdim; + ZZCell pr = sds.slices[0].getHomeCell(); + while((pr = pr.s(prefletdim, 1)) != null) { + loadPref(pr); + } + } + + // This cell is from the subspace. + void loadPref(ZZCell c) { + String t = c.getText(); + String i = sds.getConvID(0, c.getID()); + our2prefs.put(t, i); + pref2ours.put(i, t); + } + + public String s(String c, int steps, ZZObs o) { + // Do one by one + // VERY unoptimized. + String orig = c; + if(o != null) triggers.addObs(orig, o); + int origsteps = steps; + if(steps > 0) { + while(--steps >= 0) { + String n = getOneStepPos(c, o); + if(n==null) return null; + if(o != null) triggers.addObs(n, o); + c=n; + } + } else { + while(++steps <= 0) { + String n = getOneStepNeg(c, o); + if(n==null) return null; + if(o != null) triggers.addObs(n, o); + c=n; + } + } + p("Cursor getsteps: "+orig+" "+steps+" "+c); + return c; + } + + String getOneStepNeg(String c, ZZObs o) { + // First, if there is a real connection + String s = super.s(c, -1, o); + if(s == null) return null; + + // Then, this might be a preflet. + // Then, if it's in either hashtable + String p = (String)pref2ours.get(s); + if(p != null) + return p; + return s; + } + + String getOneStepPos(String c, ZZObs o) { + String s = (String)our2prefs.get(c); + if(s != null) { + s = super.s(s, 1, o); + // But if there's nothing, don't. + if(s != null) return s; + } + // It was not *that* special case. Now, + s = super.s(c, 1, o); + return s; + } + + public void insert(String c, int dir, String d) { + throw new ZZError("No direct insert along d.cursor allowed!"); + } + + public void connect(String c, String d) { + int ci = sds.getSliceID(c); + int di = sds.getSliceID(d); + if(ci == di) { + slices[ci].connect(sds.getOrigID(c), sds.getOrigID(d)); + return; + } + if(di != 0) + throw new ZZError("SlicedStpr: can't use non-slice0 cursors"); + String pref = (String)our2prefs.get(c); + if(pref == null) { + // No preflet, have to create our own. + ZZCell pr = sds.slices[0].getHomeCell().N(prefletdim, 1); + pr.setText(c); + loadPref(pr); + pref = pr.getID(); + } + slices[0].connect(sds.getOrigID(pref), sds.getOrigID(d)); + triggers.chg(c); + triggers.chg(d); + } + public void disconnect(String c, int dir) { + if(dir < 0) { + slices[0].disconnect(sds.getOrigID(c), -1); + } else { + throw new ZZError("Can't disconnect poswards in slicedcursor"); + } + } +} +*/ diff --git a/Java/storage/SlicedHomes.java b/Java/storage/SlicedHomes.java new file mode 100644 index 0000000..eb3fb33 --- /dev/null +++ b/Java/storage/SlicedHomes.java @@ -0,0 +1,59 @@ +/* +SlicedHomes.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import org.gzigzag.*; +import java.util.*; + +/** A simple class to connect the sliced home cells together. + * There must be a way to move between the spaces, right? + */ + +class EKUEHFKUEHFMEUFHMSEFS { } + +/* +public class SlicedHomes extends ZZRODimension { +public static final String rcsid = "$Id: SlicedHomes.java,v 1.7 2000/11/07 23:07:34 tjl Exp $"; + ZZSlicedDimSpace ss; + + Hashtable homeinds = new Hashtable(); + + SlicedHomes(ZZSlicedDimSpace ss) { + this.ss = ss; + for(int i=0; i= ss.slices.length) + return null; + return ss.getConvID(i, ss.slices[i].getHomeCellID()); + } + +} +*/ diff --git a/Java/storage/SlicedSame.java b/Java/storage/SlicedSame.java new file mode 100644 index 0000000..962d446 --- /dev/null +++ b/Java/storage/SlicedSame.java @@ -0,0 +1,50 @@ +/* +SlicedSame.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import org.gzigzag.*; +import java.util.*; + +/** A simple dimension to connect cells with the same ID in sliced + * spaces together. + */ + +class ELIJSEFIEHSFSHFSEF { } + +/* +public class SlicedSame extends ZZRODimension { + ZZSlicedDimSpace ss; + SlicedSame(ZZSlicedDimSpace ss) { + this.ss = ss; + } + + public String s(String c, int steps, ZZObs o) { + int si = ss.getSliceID(c); + String s = ss.getOrigID(c); + si += steps; + if(si < 1 || si >= ss.slices.length) + return null; + if(ss.slices[si].getCellByID(s) == null) return null; + return ss.getConvID(si, s); + } +} +*/ diff --git a/Java/storage/StreamSet.java b/Java/storage/StreamSet.java new file mode 100644 index 0000000..0a504e4 --- /dev/null +++ b/Java/storage/StreamSet.java @@ -0,0 +1,63 @@ +/* +StreamSet.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.io.*; + +/** A multi-file or multi-stream. + * Used for reading and writing multiple, named streams. + * They may be stored as a directory or as a single file, interleaved. + * Make sure you call close() after done with a stream. + */ + +public abstract class StreamSet { +String rcsid = "$Id: StreamSet.java,v 1.5 2000/09/18 14:28:22 tjl Exp $"; + + /** Obtain the inputstream associated with the given id. + * @return The input stream, or null if it doesn't exist. + */ + public abstract InputStream getInputStream(String id); + + /** Obtain an OutputStream for appending to the given id's stream. + */ + public abstract OutputStream getAppendStream(String id); + + /** Whether a stream exists. + */ + public abstract boolean exists(String id); + + /** Obtain a writable for a given id. + * This is so that string scrolls can work for now - they should + * be changed to use the usual routines. + */ + public abstract Writable getWritable(String id); + + /** Obtain a streamset for the given file. + * NOT IMPLEMENTED. Should return either directory or single-file + * stream set. + */ + static public StreamSet get(File f) { + return null; + } +} + + diff --git a/Java/storage/Writable.java b/Java/storage/Writable.java new file mode 100644 index 0000000..b5c7360 --- /dev/null +++ b/Java/storage/Writable.java @@ -0,0 +1,37 @@ +/* +Writable.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** A part of a multi-file or other nearly append-only storage. + */ + +public interface Writable { +String rcsid = "$Id: Writable.java,v 1.5 2000/09/19 10:32:01 ajk Exp $"; + void write(long offset, byte[] data); + byte[] read(long offset, int n); + void read(long offset, byte b[], int off, int len); + long length(); + void flush(); +} + diff --git a/Java/storage/ZZCacheContentStore.java b/Java/storage/ZZCacheContentStore.java new file mode 100644 index 0000000..8326cc0 --- /dev/null +++ b/Java/storage/ZZCacheContentStore.java @@ -0,0 +1,122 @@ +/* +ZZCacheContentStore.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** A locally cached content storage, which tracks text changes. + */ +public class ZZCacheContentStore implements ContentStore, + ContentStorer { +public static final String rcsid = "$Id: ZZCacheContentStore.java,v 1.7 2000/09/19 10:32:01 ajk Exp $"; + public static boolean dbg = false; + final static void p(String s) { if(dbg) System.out.println(s); } + final static void pa(String s) { System.out.println(s); } + + UndoList undo; + public void setUndoList(UndoList l) { undo = l; } + + ZZCacheDimSpace ds; + public void setSpace(ZZCacheDimSpace s) { ds = s; } + + /** The current contents. */ + Hashtable c = new Hashtable(); + + /** The earlier connection on each cell's poswards or negwards + * direction at commit time. + * This list is created at commit time by reversing all operations + * so we can then compare these values and the current values to + * see which have changed. + * Hmm.. do we really even need comm? + */ + Hashtable com; + + static final Object nolla = new Object(); + + synchronized public void startCommit() { + com = new Hashtable(); + } + + synchronized public void endCommit(ContentStorer sto) { + for(Enumeration e = com.keys(); + e.hasMoreElements();) { + String id = (String)e.nextElement(); + Object chgfrom = com.get(id); + Object chgto = c.get(id); + if(chgfrom == nolla) chgfrom = null; + if(chgfrom == chgto || + (chgfrom != null && chgfrom.equals(chgto))) + continue; + sto.putContent(id, chgto); + } + com = null; + } + + /** The abstracted operation of connecting two cells. + * Parameters: cell1 cell2. + * The cells are explicitly assumed to be not connected before + * this. + */ + protected class ChangeContent implements UndoList.Op { + public void undo(Object[] list, int nth) { + String id = (String)list[nth+1]; + Object before = list[nth+2]; + Object after = list[nth+3]; + if(before == null) + c.remove(id); + else + c.put(id, before); + ds.invalidateText(id); + } + public void redo(Object[] list, int nth) { + String id = (String)list[nth+1]; + Object before = list[nth+2]; + Object after = list[nth+3]; + c.put(id, after); + ds.invalidateText(id); + } + public void commit(Object[] list, int nth) { + String id = (String)list[nth+1]; + Object before = list[nth+2]; + Object after = list[nth+3]; + if(before == null) + com.put(id, nolla); + else + com.put(id,before); + } + } + + protected ChangeContent mychange = new ChangeContent(); + + public Object get(String id) { + return c.get(id); + } + public void put(String id, Object o) { + undo.add(mychange, id, c.get(id), o); + p("SetText: "+id+" '"+o+"'"); + c.put(id, o); + } + public void putContent(String id, Object o) { + c.put(id, o); + } + +} diff --git a/Java/storage/ZZCacheDimSpace.java b/Java/storage/ZZCacheDimSpace.java new file mode 100644 index 0000000..41f870d --- /dev/null +++ b/Java/storage/ZZCacheDimSpace.java @@ -0,0 +1,249 @@ +/* +ZZCacheDimSpace.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.io.*; +import java.lang.reflect.*; + +/** A dimspace that uses a StreamSet to be persistent. + * XXX Triggers to undo events?!?!? Existing ZZCells deleted?? + */ + +public class ZZCacheDimSpace extends ZZDimSpace { +public static final String rcsid = "$Id: ZZCacheDimSpace.java,v 1.28 2001/03/08 13:54:20 ajk Exp $"; + + protected int maxtimestamp; + + StreamSet strs; + + // XXX Stamps! + UndoList ul = new UndoList(2935); + ZZCacheContentStore ct = new ZZCacheContentStore(); + + Hashtable scrolls = new Hashtable(); + int timestamp = 1; + + synchronized public int stamp() { return ul.stamp(); } + synchronized public void undo() { ul.undo(); } + synchronized public void redo() { ul.redo(); } + synchronized public int commit() { + if (readonly) return timestamp; + p("COMMIT!"); + // Put in time of last save. Not used anywhere yet. + ct.put("savetime", ""+System.currentTimeMillis()); + for(Enumeration e = dims.keys(); + e.hasMoreElements(); ) { + String dname = (String)e.nextElement(); + ZZDimension d = (ZZDimension)dims.get(dname); + if(d instanceof ZZCacheDimension) { + ZZCacheDimension cd = (ZZCacheDimension)d; + cd.startCommit(); + } + } + ct.startCommit(); + ul.commit(); + int stmp = ++timestamp; + SimpleDimFile outf = new SimpleDimFile(); + for(Enumeration e = dims.keys(); + e.hasMoreElements(); ) { + String dname = (String)e.nextElement(); + ZZDimension d = (ZZDimension)dims.get(dname); + if(d instanceof ZZCacheDimension) { + ZZCacheDimension cd = (ZZCacheDimension)d; + + GZZ0 writ = new GZZ0(strs, dname); + + writ.startWrite(stmp, outf); + cd.endCommit(outf); + writ.endWrite(false); + } + } + SimpleContentFile coutf = new SimpleContentFile(); + GZZ0 cwrit = new GZZ0(strs, "CONTENT"); + cwrit.startWrite(stmp, coutf); + ct.endCommit(coutf); + cwrit.endWrite(true); + for (Enumeration e = spaceParts.keys(); e.hasMoreElements();) { + String s = (String)e.nextElement(); + ZZSpacePart sp = (ZZSpacePart)spaceParts.get(s); + sp.postCommitHook(); + } + return stmp; + } + + public ZZCacheDimSpace(StreamSet w) { + this(w, -1); + } + + public ZZCacheDimSpace(ZZCacheDimSpace cds, int tstamp) { + this(cds.strs, tstamp); + } + + public ZZCacheDimSpace(StreamSet w, int tstamp) { + this(w, tstamp, (tstamp != -1)); + } + + public ZZCacheDimSpace(StreamSet w, int tstamp, boolean readonly) { + super(readonly); + + strs = w; + + ct.setUndoList(ul); + ct.setSpace(this); + + maxtimestamp = tstamp; + + if(strs.exists("CONTENT")) { + SimpleContentFile cinf = new SimpleContentFile(); + GZZ0 crea = new GZZ0(strs, "CONTENT"); + cinf.startRead(ct); + timestamp = crea.read(cinf, tstamp); + cinf.endRead(); + } else { + // The id of the next free cell must be stored in the space, + // this is a kludge. + ct.put("nextfreeid", nextID); + // The home cell is called HOME + ct.put("1", "HOME"); + } + nextID = (String)ct.get("nextfreeid"); + + spaceParts.put("bintree", new BinaryTreePart(this, "bintree")); + spaceParts.put("imptree", new ImpliedTreePart(this, "imptree")); + spaceParts.put("imptree2", new ImpliedTreePart2(this, "imptree2")); + spaceParts.put("doubler", new DoubleStepPart(this, "doubler")); + spaceParts.put("version", new VersionPart(this, "version")); + + spaceParts.put("gentreetest", new GenTreePart(this, "gentreetest", + new GenTreeTestModel())); + + try { + spaceParts.put("nile1str", new GenTreePart(this, "nile1str", + (GenTreePartModel) + Class.forName("org.gzigzag.module.Nile1GenTreeModel"). + newInstance())); + } catch(Exception e) { + p("Nile module not found - this is not fatal unless you know what nile is. Don't worry."); + } + + try { + Class ztp = Class.forName("org.zaubertrank.ZaubertrankPart"); + Class zzsp = Class.forName("org.gzigzag.ZZSpace"); + Constructor ztpc = ztp.getConstructor(new Class[] { + zzsp, "".getClass() }); + ZZSpacePart sp = (ZZSpacePart) + ztpc.newInstance(new Object[] { this, "zaubertrank" }); + spaceParts.put("zaubertrank", sp); + } catch (ClassNotFoundException e) { + // ignore: that Zaubertrank stack trace is annoying + } catch(Throwable t) { + ZZLogger.exc(t); + // the zaubertrank isn't compiled by standard, so don't tell + } + + } + + protected void setNextID(String s) { + super.setNextID(s); + ct.put("nextfreeid", nextID); + } + + protected Span getSpan(String id) { + Object o = ct.get(id); + if(!(o instanceof Span)) + return null; + return (Span)o; + } + protected String getText(String id) { + Object o = ct.get(id); + if(o==null) return ""; + if(o instanceof Span) + o = ((Span)o).getString(getHomeCell()); + return (String)o; + } + + protected void setText(String id, Object cont) { + if (readonly) throw new ZZError("readonly space"); + ct.put(id, cont); + } + + + + protected ZZDimension createDimension(String s) { + if(!validDim(s)) return null; + if(s.indexOf(':') != -1) return createPartDimension(s); + + + ZZDimension d; + if(s.equals("d.cellcreation")) { + d = new IDDimension(); + } else { + ZZCacheDimension dim = new ZZCacheDimension(readonly); + dim.setUndoList(ul); + InputStream is = strs.getInputStream(s); + if(strs.exists(s)) { + SimpleDimFile inf = new SimpleDimFile(); + inf.startRead(dim); + GZZ0 rea = new GZZ0(strs, s); + rea.read(inf, maxtimestamp); + inf.endRead(); + } + d = dim; + } + d.setSpace(this); + return d; + } + + + public String getIDOrNull() { + Object o = ct.get("spaceid"); + if (!(o instanceof String)) { + return null; + } + return (String)o; + } + + + + public void setID(String id) { + if (readonly) throw new ZZError("readonly space"); + ct.put("spaceid", id); + } + + public StringScroll getStringScroll() { + return getStringScroll("text"); + } + public StringScroll getStringScroll(String name) { + StringScroll scr; + if((scr = (StringScroll)scrolls.get(name)) == null) { + Writable wr = strs.getWritable("STRSCR_"+name); + scr = new StringScroll(name, wr, readonly); + // XXX ??? + Scroll.register(name, scr); + scrolls.put(name, scr); + } + return scr; + } + + +} diff --git a/Java/storage/ZZCacheDimension.java b/Java/storage/ZZCacheDimension.java new file mode 100644 index 0000000..97cfae5 --- /dev/null +++ b/Java/storage/ZZCacheDimension.java @@ -0,0 +1,281 @@ +/* +ZZCacheDimension.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** Dimension-centric implementation of a locally + * cached dimension. + * This class may be used as a cache to + * a dimension stored on disk, and includes facilities for tracking + * the changes. + * XXX Look into replacing hashtable with a more memory-saving constructions? + *

    + * This, uglily, shares some code with ZZLocalDimension but making + * this an inheritance relationship would have been difficult, and + * the point is to keep ZZLocalDimension a truly simple basic + * example implementation of a dimension. + *

    + * The mechanism for the undolist is quite interesting: + * we save each connect / disconnect operation with the two cells, + * so we know the inverse of each operation. + * We can then, at commit time, build a hash table by taking the first + * operation and seeing if it cancels an earlier operation (undolist does + * commits in reverse order) and if it does, we do nothing. + * This allows the user to move the cursor without wasting storage on all + * positions. + * Interestingly, although we store all connections bidirectionally as + * connect/disconnect pairs in the undolist, we cannot save them like that + * after compression: they must be saved as single-sided disconnects and + * pair connects. + */ +public class ZZCacheDimension extends ZZDimension implements ZZDimStorer { +public static final String rcsid = "$Id: ZZCacheDimension.java,v 1.11 2001/02/23 08:33:37 ajk Exp $"; + public static final boolean dbg = true; + final static void p(String s) { if(dbg) System.out.println(s); } + final static void pa(String s) { System.out.println(s); } + + UndoList undo; + public void setUndoList(UndoList l) { undo = l; } + + protected boolean readonly; + + public ZZCacheDimension() { this(false); } + public ZZCacheDimension(boolean readonly) { + this.readonly = readonly; + } + + /** Connections to the positive direction. */ + Hashtable cp = new Hashtable(); + /** Connections to the negative direction. */ + Hashtable cm = new Hashtable(); + + /** The earlier connection on each cell's poswards or negwards + * direction at commit time. + * This list is created at commit time by reversing all operations + * so we can then compare these values and the current values to + * see which have changed. + * Hmm.. do we really even need comm? + */ + Hashtable comp; + Hashtable comm; + + /** A null marker for the hashtables. */ + static final Object nolla = new Object(); + + synchronized public void startCommit() { + if (readonly) throw new ZZError("readonly dimension"); + comp = new Hashtable(); + comm = new Hashtable(); + } + + synchronized public void endCommit(ZZDimStorer sto) { + if (readonly) throw new ZZError("readonly dimension"); + for(Enumeration e = comp.keys(); + e.hasMoreElements();) { + String id = (String)e.nextElement(); + Object oidto = comp.get(id); + String idto = (oidto == nolla ? null : (String)oidto); + String idwasto = (String)cp.get(id); + // If it's the same, then nevermind. + if(idto == idwasto || ( + idto != null && idto.equals(idwasto))) + continue; + if(idwasto != null) + sto.storeConnect(id, idwasto); + else + sto.storeDisconnect(id, 1); + + } + for(Enumeration e = comm.keys(); + e.hasMoreElements();) { + String id = (String)e.nextElement(); + Object oidto = comm.get(id); + String idto = (oidto == nolla ? null : (String)oidto); + String idwasto = (String)cm.get(id); + // If it's the same, then nevermind. + if(idto == idwasto || ( + idto != null && idto.equals(idwasto))) + continue; + if(idwasto == null) + sto.storeDisconnect(id, -1); + // Not here: we only call connect once. + // else + // sto.connect(id, -1, idto); + + } + comp = null; + comm = null; + } + + ZZCellHandle ch(Object o) { + if(o instanceof ZZCellHandle) return (ZZCellHandle)o; + return (ZZCellHandle)space.getCellByID((String)o); + } + String cid(Object o) { + if(o instanceof ZZCellHandle) return ((ZZCellHandle)o).id; + return (String)o; + } + + /** The abstracted operation of connecting two cells. + * Parameters: cell1 cell2. + * The cells are explicitly assumed to be not connected before + * this. + */ + protected class Connect implements UndoList.Op { + public void undo(Object[] list, int nth) { + String c1 = (String)list[nth+1]; + String c2 = (String)list[nth+2]; + if(!s((ZZCellHandle)space.getCellByID(c1), 1, null).id.equals(c2)) + throw new ZZError( + "Error when undoing change: disconnect assertion broken"); + cp.remove(c1); + cm.remove(c2); + triggers.chg(c1); + triggers.chg(c2); + } + public void redo(Object[] list, int nth) { + String c1 = (String)list[nth+1]; + String c2 = (String)list[nth+2]; + if(cp.get(c1) != null || + cm.get(c2) != null) + throw new ZZError( + "Error when redoing change: unconnected assertion broken"); + cp.put(c1, c2); + cm.put(c2, c1); + triggers.chg(c1); + triggers.chg(c2); + } + public void commit(Object[] list, int nth) { + String c1 = (String)list[nth+1]; + String c2 = (String)list[nth+2]; + comp.put(c1, nolla); + comm.put(c2, nolla); + } + } + + + /** The abstracted operation of disconnecting two cells. + * Parameters: cell1 cell2. + */ + protected class Disconnect implements UndoList.Op { + public void undo(Object[] list, int nth) { + String c1 = (String)list[nth+1]; + String c2 = (String)list[nth+2]; + // Note we can't use disconnect() since that would make + // new undolist entries. + if(cp.get(c1) != null || + cm.get(c2) != null) + throw new ZZError( + "Error when undoing change: unconnected assertion broken"); + cp.put(c1, c2); + cm.put(c2, c1); + triggers.chg(c1); + triggers.chg(c2); + } + public void redo(Object[] list, int nth) { + String c1 = (String)list[nth+1]; + String c2 = (String)list[nth+2]; + if(!s((ZZCellHandle)space.getCellByID(c1), 1, null).id.equals(c2)) + throw new ZZError( + "Error when redoing change: disconnect assertion broken"); + cp.remove(c1); + cm.remove(c2); + triggers.chg(c1); + triggers.chg(c2); + } + public void commit(Object[] list, int nth) { + String c1 = (String)list[nth+1]; + String c2 = (String)list[nth+2]; + comp.put(c1, c2); + comm.put(c2, c1); + } + } + + Connect myconnect = new Connect(); + Disconnect mydisconnect = new Disconnect(); + + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) { + String s = c.id; + if(o != null) triggers.addObs(s, o); + if(steps>0) + while(steps-- > 0 && s != null) { + s = (String)cp.get(s); + if(o != null && s!=null) triggers.addObs(s, o); + } + else + while(steps++ < 0 && s != null) { + s = (String)cm.get(s); + if(o != null && s!=null) triggers.addObs(s, o); + } + if(s==null) return null; + return (ZZCellHandle)space.getCellByID(s); + } + + public void connect(ZZCellHandle c0, ZZCellHandle d0) { + if (readonly) throw new ZZError("readonly dimension"); + String c = c0.id; + String d = d0.id; + disconnect(c0, 1); + disconnect(d0, -1); + cp.put(c, d); + cm.put(d, c); + undo.add(myconnect, c, d); + triggers.chg(c); + triggers.chg(d); + } + + public void disconnect(ZZCellHandle c0, int dir) { + if (readonly) throw new ZZError("readonly dimension"); + String c = c0.id; + String o; + if(dir>0) { + o = (String)cp.get(c); + if(o!=null) { + undo.add(mydisconnect, c, o); + cp.remove(c); + cm.remove(o); + } + } else { + o = (String)cm.get(c); + if(o!=null) { + undo.add(mydisconnect, o, c); + cm.remove(c); + cp.remove(o); + } + } + triggers.chg(c); + if(o!=null) triggers.chg(o); + } + + // ZZDimStorer implementation + + public void storeConnect(String a, String b) { + cp.put(a, b); + cm.put(b, a); + } + public void storeDisconnect(String a, int dir) { + Hashtable h = (dir > 0 ? cp : cm); + h.remove(a); + } + +} diff --git a/Java/storage/ZZDimStorer.java b/Java/storage/ZZDimStorer.java new file mode 100644 index 0000000..27e294a --- /dev/null +++ b/Java/storage/ZZDimStorer.java @@ -0,0 +1,47 @@ +/* +ZZDimStorer.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.awt.*; +import java.util.*; +import java.io.*; + +/** A simple interface between persistent and temporary storage. + * This class is used simply for transmitting information about + * connections. + *

    + * The speciality of this class is that the operations need not make + * sense atomically: only the end result of several operations counts. + * So if a is connected to b, then connect(b, -, c), disconnect(a, +), + * is perfectly valid. + * All disconnections must be given in both directions; connects + * only once (that's why there's no dir there). + *

    + * If the above seems unclear, just see how it's used and where + * it's not used: the class that is used for the on-line dims is ZZDimension. + */ + +public interface ZZDimStorer { +String rcsid = "$Id: ZZDimStorer.java,v 1.4 2000/09/19 10:32:01 ajk Exp $"; + void storeConnect(String a, String b); + void storeDisconnect(String a, int dir); +} diff --git a/Java/transform/ChangeDim.java b/Java/transform/ChangeDim.java new file mode 100644 index 0000000..21334d5 --- /dev/null +++ b/Java/transform/ChangeDim.java @@ -0,0 +1,58 @@ +/* +ChangeDim.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuukka Hastrup + */ +package org.gzigzag.transform; +import java.util.*; +import org.gzigzag.*; + +/** ZZspace dimension changer - substitute a dimension name with another + */ + +public class ChangeDim { +String rcsid = "$Id: ChangeDim.java,v 1.5 2000/10/18 14:35:32 tjl Exp $"; + String olddim, newdim; + ZZSpace space; +/** Constructs dimension changer for a space + * @param od The old dimension + * @param nd The new dimension + * @param s The space to convert + */ + public ChangeDim(String od, String nd, ZZSpace s) { + olddim = od; + newdim = nd; + space = s; + } + +/** Performs the actual transformation. All connections along the old + * dimension are disconnected and new ones connected along the new dimension. + */ + public void transform() { + Enumeration e=space.cells(); + ZZCell c, n; + while(e.hasMoreElements()) { + c = (ZZCell)e.nextElement(); + n = c.s(olddim, 1); + if(n!=null) { + c.disconnect(olddim, 1); + c.connect(newdim, 1, n); + } + } + } +} diff --git a/Java/transform/ClearDim.java b/Java/transform/ClearDim.java new file mode 100644 index 0000000..c5a5fc2 --- /dev/null +++ b/Java/transform/ClearDim.java @@ -0,0 +1,55 @@ +/* +ClearDim.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuukka Hastrup + */ +package org.gzigzag.transform; +import java.util.*; +import org.gzigzag.*; + +/** ZZspace dimension clearer - disconnects every connection along a dimension + */ + +public class ClearDim { +String rcsid = "$Id: ClearDim.java,v 1.4 2000/10/18 14:35:32 tjl Exp $"; + String dim; + ZZSpace space; +/** Constructs dimension changer for a space + * @param od The old dimension + * @param nd The new dimension + * @param s The space to convert + */ + public ClearDim(String d, ZZSpace s) { + dim = d; + space = s; + } + +/** Performs the actual transformation. All connections along the + * dimension are simply disconnected. + */ + public void transform() { + Enumeration e=space.cells(); + ZZCell c, n; + while(e.hasMoreElements()) { + c = (ZZCell)e.nextElement(); + if(c.s(dim, 1)!=null) { + c.disconnect(dim, 1); + } + } + } +} diff --git a/Java/transform/CopyDim.java b/Java/transform/CopyDim.java new file mode 100644 index 0000000..51f2e52 --- /dev/null +++ b/Java/transform/CopyDim.java @@ -0,0 +1,58 @@ +/* +CopyDim.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuukka Hastrup + */ +package org.gzigzag.transform; +import java.util.*; +import org.gzigzag.*; + +/** ZZspace dimension copier - duplicate connections of a dimension into + * another dimension + */ + +public class CopyDim { +String rcsid = "$Id: CopyDim.java,v 1.4 2000/10/18 14:35:32 tjl Exp $"; + String olddim, newdim; + ZZSpace space; +/** Constructs dimension changer for a space + * @param od The old dimension + * @param nd The new dimension + * @param s The space to convert + */ + public CopyDim(String od, String nd, ZZSpace s) { + olddim = od; + newdim = nd; + space = s; + } + +/** Performs the actual transformation. All connections along the old + * dimension are recreated along the new dimensions. + */ + public void transform() { + Enumeration e=space.cells(); + ZZCell c, n; + while(e.hasMoreElements()) { + c = (ZZCell)e.nextElement(); + n = c.s(olddim, 1); + if(n!=null) { + c.connect(newdim, 1, n); + } + } + } +} diff --git a/Java/transform/FoldDim.java b/Java/transform/FoldDim.java new file mode 100644 index 0000000..3b100ef --- /dev/null +++ b/Java/transform/FoldDim.java @@ -0,0 +1,76 @@ +/* +FoldDim.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + * (Borrowing heavily from ReverseDim.java by Tuukka Hastrup) + */ +package org.gzigzag.transform; +import java.util.*; +import org.gzigzag.*; + +/** "Fold" a dimension into two new ones + * Take one start and two result dimensions. Target dim + */ + +public class FoldDim { +String rcsid = "$Id: FoldDim.java,v 1.4 2000/10/18 14:35:32 tjl Exp $"; + public static final boolean dbg = false; + void p(String s) { if (dbg) System.out.println(s); } + void pa(String s) { System.out.println(s); } + + String dim, hdim; // Headcell dim + ZZSpace space; + + public FoldDim(String d, String h, ZZSpace s) { + dim=d; hdim=h; space=s; + } + + public void transform() { + Enumeration e=space.cells(); + ZZCell c; + Hashtable donecells = new Hashtable(); // Cells on the folded ranks + while(e.hasMoreElements()) { // Do ranks + c = (ZZCell)e.nextElement(); + if(c.s(dim, -1)==null) { + if (c.s(dim, 1)!=null) { + if(!donecells.containsKey(c)) { + ZZCell next = c.s(dim, 1); + c.disconnect(dim, 1); c.connect(hdim, 1, next); + donecells.put(c, c); + for(; next != null; next=next.s(dim, 1)) + donecells.put(next, next); + p("Folded rank beginning from cell #"+c.getID()); + } + else + p("Rank beginning from cell #"+c.getID()+" already done"); + } + else + p("Cell #"+c.getID()+" not placed on "+dim); + donecells.put(c, c); // This cell is not in loop + } // Negwards connected cells will be done later + } + e = space.cells(); + while(e.hasMoreElements()) { // Detect loops + c = (ZZCell)e.nextElement(); + if(!donecells.containsKey(c)) { // If it wasn't rank, then it's loop + pa("FoldDim couldn't convert cell on loop, #"+c.getID()+ + ", '"+c.getText()+"'"); + } + } + } +} \ No newline at end of file diff --git a/Java/transform/ReverseDim.java b/Java/transform/ReverseDim.java new file mode 100644 index 0000000..17c7976 --- /dev/null +++ b/Java/transform/ReverseDim.java @@ -0,0 +1,96 @@ +/* +ReverseDim.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuukka Hastrup + */ +package org.gzigzag.transform; +import java.util.*; +import org.gzigzag.*; + +/** ZZspace dimension changer - reverse positive and negative directions. + */ + +public class ReverseDim { +String rcsid = "$Id: ReverseDim.java,v 1.6 2000/10/18 14:35:32 tjl Exp $"; + public static final boolean dbg = false; + void p(String s) { if (dbg) System.out.println(s); } + String dim; + ZZSpace space; +/** Constructs direction changer for a dimension in a space + * @param d The dimension + * @param s The space to convert + */ + public ReverseDim(String d, ZZSpace s) { + dim = d; + space = s; + } + +/** Performs the actual transformation. All connections along the dimension + * are disconnected and new ones connected in reverse direction. + */ + public void transform() { + Enumeration e=space.cells(); + ZZCell c; + Hashtable donecells = new Hashtable(); // Cells on the reversed ranks + while(e.hasMoreElements()) { // Do ranks + c = (ZZCell)e.nextElement(); + if(c.s(dim, -1)==null) { + if (c.s(dim, 1)!=null) { + if(!donecells.containsKey(c)) { + swapRank(c, donecells); + p("Swapped rank beginning from cell #"+c.getID()); + } + else + p("Rank beginning from cell #"+c.getID()+" already done"); + } + else + p("Cell #"+c.getID()+" not placed on "+dim); + donecells.put(c, c); // This cell is not in loop + } // Negwards connected cells will be done later + } + e = space.cells(); + while(e.hasMoreElements()) { // Do loops + c = (ZZCell)e.nextElement(); + if(!donecells.containsKey(c)) { // If it wasn't rank, then it's loop + c.disconnect(dim, -1); // Cut into a rank + c.connect(dim, 1, swapRank(c, donecells)); // Flip and join + } + } + } + + // Swap the cells in a rank. Return the new headcell. + protected ZZCell swapRank(ZZCell head, Hashtable done) + { + ZZCell newrank = head; // The latest cell in the new rank + ZZCell curr = head.s(dim, 1); // The head of the old one + head.disconnect(dim, 1); + ZZCell next; + while (curr != null) { + next = curr.s(dim, 1); + if(next!=null) { + curr.disconnect(dim, 1); + } + curr.connect(dim, 1, newrank); + done.put(curr, curr); + newrank = curr; + curr = next; + }; + return newrank; + } +} + diff --git a/Java/transform/Version0.java b/Java/transform/Version0.java new file mode 100644 index 0000000..5ab67cc --- /dev/null +++ b/Java/transform/Version0.java @@ -0,0 +1,66 @@ +/* +Version0.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuukka Hastrup + */ +package org.gzigzag.transform; +import java.util.*; +import org.gzigzag.*; + +/** ZZspace version changer - from version 0 to version 1. + */ + +public class Version0 implements VersionChanger { +String rcsid = "$Id: Version0.java,v 1.7 2000/10/18 14:35:32 tjl Exp $"; + static public final void pa(String s) { System.out.println(s); } + static public final void pan(String s) { System.out.print(s); } +/** Change the space from version 0 to version 1 to make it compatible: + *

      + *
    • d.mycursor is renamed to d.cursor-cargo + *
    • d.cursor-cargo and d.cursor directions are reversed + *
    • System cell "FlobCanvasRasters" is renamed as "FlobRasters" + *
    + * Note that flobs will not work before a new client space is created + * with command line options new and dcold. + * @param s The space to convert + */ + public int changeVersion(ZZSpace s) { + pa("Converting from version 0 to version 1:"); + pa("Cursor dimensions rearranged for consistency."); + pan("Changing d.mycursor connections to d.cursor-cargo:"); + (new ChangeDim("d.mycursor", "d.cursor-cargo", s)).transform(); + pa(" Name changed."); + pan("Reversing connections along d.cursor and d.cursor-cargo:"); + (new ReverseDim("d.cursor", s)).transform(); + (new ReverseDim("d.cursor-cargo", s)).transform(); + pa(" Headcell (negend) now accursed."); + pa("The new flob code won't work unless you create " + + "new client space (options -new and -dcold)."); + pa("Changing the system cell \"FlobCanvasRasters\" " + + "to \"Flobrasters\" to respect code changes."); + ZZCell frasters = s.getHomeCell() + .findText("d.2", 1, "FlobCanvasRasters"); + if(frasters != null) { + frasters.setText("FlobRasters"); + frasters.disconnect("d.1", 1); + frasters.N("d.1", 1).setText("dummy"); + } + return 1; + } +} + diff --git a/Java/transform/Version1.java b/Java/transform/Version1.java new file mode 100644 index 0000000..ad470ec --- /dev/null +++ b/Java/transform/Version1.java @@ -0,0 +1,56 @@ +/* +Version0.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ +package org.gzigzag.transform; +import java.util.*; +import org.gzigzag.*; + +/** ZZspace version changer - from version 1 to version 2. + */ + +public class Version1 implements VersionChanger { +String rcsid = "$Id: Version1.java,v 1.3 2000/09/19 10:32:01 ajk Exp $"; + static public final void pa(String s) { System.out.println(s); } + static public final void pan(String s) { System.out.print(s); } +/** Change the space from version 1 to version 2 to make it compatible. + * Change to 3-dimension cursing system, allowing every cell to be accursed: + *
      + *
    1. fold d.cursor's headcells onto TMPDIM + *
    2. change d.cursor to d.cursor-list + *
    3. change TMPDIM to d.cursor + *
    + * @param s The space to convert + */ + public int changeVersion(ZZSpace s) { + pa("Converting from version 1 to version 2:"); + pa("Change to 3-dimension cursing system."); + pan("Folding d.cursor's headcells to TMPDIM... "); + (new FoldDim("d.cursor", "TMPDIM", s)).transform(); + pa("done."); + pan("Renaming to d.cursor and d.cursor-list... "); + (new ChangeDim("d.cursor", "d.cursor-list", s)).transform(); + pan("d.cursor-list done... "); + (new ChangeDim("TMPDIM", "d.cursor", s)).transform(); + pa(" d.cursor done."); + pa("Converted to version 2."); + return 2; + } +} + diff --git a/Java/transform/Version2.java b/Java/transform/Version2.java new file mode 100644 index 0000000..d3f6eda --- /dev/null +++ b/Java/transform/Version2.java @@ -0,0 +1,44 @@ +/* +Version2.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.transform; +import java.util.*; +import org.gzigzag.*; + +/** ZZspace version changer - from version 2 to version 3. + * The change in the structure is that now rasters have names, + * and rasters are called views. + */ + +public class Version2 implements VersionChanger { +String rcsid = "$Id: Version2.java,v 1.3 2000/09/19 10:32:01 ajk Exp $"; + static public final void pa(String s) { System.out.println(s); } + static public final void pan(String s) { System.out.print(s); } +/** Change the space from version 2 to version 3 to make it compatible. + * Simply recreates the system part of the space, since we now use names for views. + */ + public int changeVersion(ZZSpace s) { + pa("Converting from version 2 to version 3:"); + pa("Recreating system space (not disconnecting old)"); + ZZDefaultSpace.create(s.getHomeCell(), false); + return 3; + } +} + diff --git a/Java/transform/VersionChanger.java b/Java/transform/VersionChanger.java new file mode 100644 index 0000000..488317c --- /dev/null +++ b/Java/transform/VersionChanger.java @@ -0,0 +1,37 @@ +/* +VersionChanger.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuukka Hastrup + */ +package org.gzigzag.transform; +import java.util.*; +import org.gzigzag.*; + +/** A general interface for changing ZZspaces between versions. + */ +public interface VersionChanger { +String rcsid = "$Id: VersionChanger.java,v 1.4 2000/09/19 10:32:01 ajk Exp $"; + /** Takes the space which conforms to client space version of the + * converter class. Needed transformations are then carried out + * to make the space conform to a newer version returned. + * @param s The space to convert + * @return The new version of the space + */ + int changeVersion(ZZSpace s); +} + diff --git a/Java/zob2java.pl b/Java/zob2java.pl new file mode 100644 index 0000000..4f58de0 --- /dev/null +++ b/Java/zob2java.pl @@ -0,0 +1,302 @@ +# +# zob2java.pl +# * +# * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka +# * +# * You may use and distribute under the terms of either the GNU Lesser +# * General Public License, either version 2 of the license or, +# * at your choice, any later version. Alternatively, you may use and +# * distribute under the terms of the XPL. +# * +# * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of +# * the licenses. +# * +# * This software is distributed in the hope that it will be useful, +# * but WITHOUT ANY WARRANTY; without even the implied warranty of +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README +# * file for more details. +# * +# */ +# /* +# * Written by Tuomas Lukka +# */ +# + +# $out = $ARGV[0]; +# $out =~ s/\.zob/\.java/ or die("Can't change filename for output file"); + +@ARGV == 2 or die "Two params: infile outfile"; + +$outfile = pop @ARGV; +$infile = $ARGV[0]; + +$init .= <; + +$str =~ s/\bFONTMETRICS\s*\((.*?)\)/(ScalableFont.fmComp.getFontMetrics($1))/g; + +# ZObs must implement ZOb themselves. +# +# $str =~ s/\b(implements\s+)/$1 ZOb, / +# or $str =~ s/(^[\w\s]*\bclass\b[\w\s]*)({)/$1 implements ZOb $2/ +# or die "Can't implement ZOb - didn't find subst place"; + +$str =~ s/INITIALIZE/protected void init__zob() / + and $doinit = "init__zob();"; + +# $structparre = 'STRUCTPARAMS;?(.*)END STRUCTPARAMS;?'; + +# $str =~ /$structparre/s; + +# $pars = $1; + +# FIXME: this parser takes into account braces in comments +sub parse_balanced { + my $str = $_[0]; + my $rv = ""; + my $level = 1; + + while ($level > 0) { + die "Unbalanced braces" if $str eq ""; + $str =~ /^([^{}]*)([{}])(.*)$/s; + my($brace1, $brace2, $rest) = ($1, $2, $3); + if ($brace2 eq "{") { ++$level; } + if ($brace2 eq "}") { --$level; } + $str = $rest; + $rv = $rv . $brace1 . $brace2; + } + return ($rv, $str); +} + +$str =~ /^(.*)STRUCTPARAMS *{(.*)$/s or die "No STRUCTPARAMS SECTION"; +$beforestructpars = $1; +($pars, $afterstructpars) = parse_balanced($2); +$pars =~ s/}$//s; + +@pars = map { /^\s*$/ ? () : $_ } split /\n\s*\n/, $pars; + +%gets = ( +"float" => '__TARG__ = (Float.valueOf(__SRC__)).floatValue();', +"double" => '__TARG__ = (Double.valueOf(__SRC__)).doubleValue();', +"int" => '__TARG__ = Integer.parseInt(__SRC__); ', +"boolean" => ' + if(__SRC__.equals("true")) __TARG__=true; + else if(__SRC__.equals("false")) __TARG__=false; + else { /* XXX ??? */ } +', +Font => ' + { + ZZCell c1 = c.s("d.1"); + int size = 12; + int style = Font.PLAIN; + if(c1 != null) { + size = Integer.parseInt(c1.getText()); + ZZCell c2 = c1.s("d.1"); + if(c2 != null) { + String sty = c2.getText(); + if(sty.equals("BOLD")) + style = Font.BOLD; + if(sty.equals("ITALIC")) + style = Font.ITALIC; + else { + // error... + } + } + } + __TARG__ = new Font(s, style, size); + } +', +ScalableFont => ' + { + ZZCell c1 = c.s("d.1"); + int size = 12; + int style = Font.PLAIN; + if(c1 != null) { + size = Integer.parseInt(c1.getText()); + ZZCell c2 = c1.s("d.1"); + if(c2 != null) { + String sty = c2.getText(); + if(sty.equals("BOLD")) + style = Font.BOLD; + if(sty.equals("ITALIC")) + style = Font.ITALIC; + else { + // error... + } + } + } + __TARG__ = new ScalableFont(s, style, size); + } +', +String => '__TARG__ = __SRC__; ', +Color => '__TARG__ = Color.decode(__SRC__); ', +ZZPath => ' + __TARG__ = ZZPath.createFromStructure1(__SRCCELL__.s("d.2")); +', +ZOb => ' + { + __TARG__ = ZZDefaultSpace.readZOb(__SRCCELL__); + // __TARG__ = ZZDefaultSpace.newZOb(__SRC__); + // __TARG__.readParams(__SRCCELL__.s("d.2")); + + } +', +ZZCell => ' + { + __TARG__ = __SRCCELL__; + } +', +); + +my $curbit = -1; + +# Remove comments +for(@pars) { + print "Par: $_"; + # Move comment + my $comment; + if(m|^(\s*/\*.*\*/)(.*)|s) { + $comment = $1; + $_ = $2; + } else { + # die "No comment for structparam '$_' in $infile"; + $comment = "/** UNDOCUMENTED. \n */"; + } + if(m|=(.*)|) { + my $def = $1; + print "DEFAULT: $def\n\n"; + $comment =~ s|\*/|\n *

    Default value:

    $def
    . \n */| + or die "Comment '$comment' not substitutable" ; + } else { + print "NO DEFAULT: $_\n\n"; + } + # Add new tag: structparam + $comment =~ s|\*/|\n * \@structparam 1 \n */ \n\n|g; + $publicpars .= $comment; + + $publicpars .= " public ".$_; + s|/\*.*?\*/||gs ; + s/^\s*//s; + s/\s*$//s; + m|^(\w+\s*(?:\[\s*\]\s*)*)\s* + (\w+)\s* + ((?://.*\n)?)\s* + |x or die "Invalid param: $_"; + # push @types, $1; + # push @names, $2; + # push @ranges, $3; + + my($type, $name, $range) = ($1, $2, $3); + + $type =~ s/\s+//g; + $type =~ /^(\w+)((?:\[\])?)$/ or die "Invalid type '$type'"; + + my $base = $1; + my $array = ($2 eq "[]"); + + $get = $gets{$base} or die "No get for '$base'"; + + if($array) { + $get =~ s/__TARG__/${name}\l[i]/g; + $get =~ s/__SRC__/s/g; + $get =~ s/__SRCCELL__/c/g; + $get = qq* + // count rank + int i=-1; + for(ZZCell c = n; c!=null; c=c.s("d.1")) i++; + // XXX check range + $name = new ${base}\l[i]; + i=0; + for(ZZCell c = n.s("d.1"); + c!=null; c=c.s("d.1")) { + s = c.getText(); + $get; + i++; + } + *; + } else { + $get =~ s/__TARG__/$name/g; + $get =~ s/__SRC__/s/g; + $get =~ s/__SRCCELL__/c/g; + $get = qq{ZZCell c = n.s("d.1"); s = c.getText(); $get }; + } + + $curbit ++; + $curmask = (1 << $curbit); + + $tests .= qq* + if(s.equals("$name")) { + mask |= $curmask; + try { + $get + } catch(Exception e) { + ZZLogger.exc(e); + } + } else + +*; +} + +$fullmask = (1<<($curbit+1))-1; + +# print "PARAMS: (",(join '||||||',@pars),")\n"; + +# limit of 31 variables for now. + +$code = <$outfile" or die "No out: '$outfile'"; +print OUT $str; +close OUT; diff --git a/LICENSE.lgpl b/LICENSE.lgpl new file mode 100644 index 0000000..92b8903 --- /dev/null +++ b/LICENSE.lgpl @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/LICENSE.xpl b/LICENSE.xpl new file mode 100644 index 0000000..388f365 --- /dev/null +++ b/LICENSE.xpl @@ -0,0 +1,16 @@ +This is version 0 of the Xanadu Public License (XPL). +This version of this license does not grant you any rights beyond +those you would have without it. There is no warranty, express or implied, +not even the warranty of merchantability or fitness for any particular +purpose. + +((Rationale, NOT PART OF THE ACTUAL LICENSE: +This is a placeholder for version 1 of the license which is going to +be Ted Nelson's transpublishing-based opensource license. +For the gzigzag package, the existence of this placeholder means two things: +1) Currently the distribution mode is exactly LGPL, due to the user's other +choice being this license which is currently nothing +2) When submitting contributions, you are implicitly agreeing that your +contributions will fall under the later versions of this license as well as +LGPL, when incorporated into gzigzag.)) + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9bf3735 --- /dev/null +++ b/Makefile @@ -0,0 +1,97 @@ + +all : + @echo "Please cd to a subdirectory first (see README)." + @exit 1 + +CVS=cvs +Manifest: + rm -f $@.new $@.edi + ./cvsparser.pl | ./manifest-filter.pl > $@.edi + sort $@.edi -o $@.new + mv $@.new $@ + rm -f $@.edi + +VERSION=snapshot-`date -u +%Y%m%d` +TAG="Unofficial" + +dist : DISTDIR=gzigzag-$(VERSION) +dist : dist.tgz dist.zip + +dist.tgz : distdir + tar cf $(DISTDIR).tar $(DISTDIR) + gzip -9vf $(DISTDIR).tar + +dist.zip : distdir + zip -r9 $(DISTDIR).zip $(DISTDIR) + +release : DISTDIR=gzigzag-$(VERSION) +release : modulesupport.jar + $(MAKE) dist + $(MAKE) -C Java MODULESUPPORT=$(shell pwd)/modulesupport.jar \ + BUILD_TAG="$(TAG) $(VERSION) (with modules)" \ + JARNAME=$(DISTDIR)-with-modules.jar jar + mv Java/$(DISTDIR)-with-modules.jar . + $(MAKE) -C Java MODULES="" \ + BUILD_TAG="$(TAG) $(VERSION) (without modules)" \ + JARNAME=$(DISTDIR)-without-modules.jar jar + mv Java/$(DISTDIR)-without-modules.jar . + $(MAKE) -C Documentation dist + mv Documentation/docdisttree $(DISTDIR)-doc + tar cf $(DISTDIR)-doc.tar $(DISTDIR)-doc + gzip -9vf $(DISTDIR)-doc.tar + zip -r9 $(DISTDIR)-doc.zip $(DISTDIR)-doc + rm -f $(DISTDIR).md5sums.new + set -e; for f in $(DISTDIR)-without-modules.jar \ + $(DISTDIR)-with-modules.jar \ + $(DISTDIR).tar.gz \ + $(DISTDIR).zip \ + $(DISTDIR)-doc.tar.gz \ + $(DISTDIR)-doc.zip; \ + do \ + sum=$$(md5sum $$f | awk '{ print $$1; }'); \ + size=$$(ls -l $$f | awk '{ print $$5; }'); \ + echo "$$sum $$size $$f" >> $(DISTDIR).md5sums.new; \ + done + mv $(DISTDIR).md5sums.new $(DISTDIR).md5sums + rm -rf docdisttree + +CVSTAG=none +official-release : VERSION=$(shell echo $(CVSTAG) \ + | sed -e 's/^rel_//' -e 's/_/./g') +official-release : grbdir=gzigzag-release-build +official-release : modulesupport.jar + rm -rf $(grbdir) + set -e ;\ + if $$(echo $(VERSION) \ + | egrep '^[0-9]+\.[0-9]+\.(pre)?[0-9]+$$' >/dev/null);\ + then\ + :; \ + else \ + echo "Bad VERSION"; \ + exit 1; \ + fi + cvs -z3 -d$(shell cat CVS/Root) checkout -r $(CVSTAG) \ + -d $(grbdir) gzigzag + ln modulesupport.jar $(grbdir) + make -C $(grbdir) VERSION=$(VERSION) TAG="Official" release + ln -f $(grbdir)/gzigzag-$(VERSION)-with-modules.jar + ln -f $(grbdir)/gzigzag-$(VERSION)-without-modules.jar + ln -f $(grbdir)/gzigzag-$(VERSION).tar.gz + ln -f $(grbdir)/gzigzag-$(VERSION).zip + ln -f $(grbdir)/gzigzag-$(VERSION)-doc.tar.gz + ln -f $(grbdir)/gzigzag-$(VERSION)-doc.zip + ln -f $(grbdir)/gzigzag-$(VERSION).md5sums + rm -rf $(grbdir) + + +DISTDIR=gzigzag-dist +distdir: + ./makedist.sh $(DISTDIR) + +CVS2CL=cvs2cl + +ChangeLog :: + CVS_RSH=ssh $(CVS2CL) -U changelog-authors -l -d'2001-01-01\ + +GZigZag + + + +Unbelievably cool GZigZag demo. + + + + + diff --git a/Modules/awtool/AwtCursor.java b/Modules/awtool/AwtCursor.java new file mode 100644 index 0000000..72ec672 --- /dev/null +++ b/Modules/awtool/AwtCursor.java @@ -0,0 +1,36 @@ +/* +AwtCursor.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Kimmo Wideroos + */ + +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.awt.*; + +public class AwtCursor { + Color color; + boolean shared; + public AwtCursor(Color cursorColor, boolean shared) { + color = cursorColor; + this.shared = shared; + } +} diff --git a/Modules/awtool/AwtLink.java b/Modules/awtool/AwtLink.java new file mode 100644 index 0000000..0153902 --- /dev/null +++ b/Modules/awtool/AwtLink.java @@ -0,0 +1,176 @@ +/* DO NOT EDIT THIS FILE. THIS FILE WAS GENERATED FROM ../Modules/awtool/AwtLink.zob, + * EDIT THAT FILE INSTEAD! + * All changes to this file will be lost. + */ +/* +AwtLink.zob + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Kimmo Wideroos + */ + +package org.gzigzag.module; +import org.gzigzag.*; +import java.awt.*; +import java.util.*; + + +public class AwtLink extends ZObCellRepr implements ZOb { + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + + /** UNDOCUMENTED. + + *

    Default value:

     0.0;
    . + + * @structparam 1 + */ + + public + double x + = 0.0;/** UNDOCUMENTED. + + *

    Default value:

     0.0;
    . + + * @structparam 1 + */ + + public double y + = 0.0;/** UNDOCUMENTED. + + *

    Default value:

     false;
    . + + * @structparam 1 + */ + + public boolean fixed + = false; + + + /* AUTOGENERATED! */ + static final private int fullmask = 7; + + /* AUTOGENERATED! */ + public String readParams(ZZCell start) { + int m = 0; + try { + if(start != null) + m = readParams(start, 0); + } catch(Throwable t) { + ZZLogger.exc(t); + } finally { + + } + if((m & fullmask) != fullmask) { + // not all parameters present - no problem right now. + } + return ""; + } + + /* AUTOGENERATED! */ + private int readParams(ZZCell start, int mask) { + ZZCell n = start; + while(n != null) { + String s = n.getText(); + // Tests autogenerated from members. + + if(s.equals("x")) { + mask |= 1; + try { + ZZCell c = n.s("d.1"); s = c.getText(); x = (Double.valueOf(s)).doubleValue(); + } catch(Exception e) { + ZZLogger.exc(e); + } + } else + + + if(s.equals("y")) { + mask |= 2; + try { + ZZCell c = n.s("d.1"); s = c.getText(); y = (Double.valueOf(s)).doubleValue(); + } catch(Exception e) { + ZZLogger.exc(e); + } + } else + + + if(s.equals("fixed")) { + mask |= 4; + try { + ZZCell c = n.s("d.1"); s = c.getText(); + if(s.equals("true")) fixed=true; + else if(s.equals("false")) fixed=false; + else { /* XXX ??? */ } + + } catch(Exception e) { + ZZLogger.exc(e); + } + } else + + + { } // grab that last "else" + ZZCell h = n.h("d.3"); + if(h != null && h != n) { + // recurse + mask |= readParams(h, mask); + } + n = n.s("d.2"); + } + return mask; + } + + + + public boolean isFixed() { return fixed; } + + public void setX(double x) { this.x = x; } + public void setY(double y) { this.y = y; } + + public double getX() { return x; } + public double getY() { return y; } + + public ZZCell toHeadCell() { + return getCell().h(AwtUtil.d_from, 1).h(AwtUtil.d_clone); + } + + public ZZCell fromHeadCell() { + return getCell().h(AwtUtil.d_to).h(AwtUtil.d_clone); + } + + public String getZObName() { + return "Link"; + } + + public String cellRepr(ZZCell start, boolean clone) + { + ZZCell c = start.getOrNewCell("d.1"); + c.setText(getZObClassName()); + c = c.getOrNewCell("d.1"); + c.setText("x"); + c.getOrNewCell("d.1").setText(""+getX()); + c = c.getOrNewCell("d.2"); + c.setText("y"); + c.getOrNewCell("d.1").setText(""+getY()); + return ""; + } +} + +// vim: set syntax=java : diff --git a/Modules/awtool/AwtLink.zob b/Modules/awtool/AwtLink.zob new file mode 100644 index 0000000..f6d307d --- /dev/null +++ b/Modules/awtool/AwtLink.zob @@ -0,0 +1,80 @@ +/* +AwtLink.zob + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Kimmo Wideroos + */ + +package org.gzigzag.module; +import org.gzigzag.*; +import java.awt.*; +import java.util.*; + + +public class AwtLink extends ZObCellRepr implements ZOb { + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + STRUCTPARAMS { + double x + = 0.0; + + double y + = 0.0; + + boolean fixed + = false; + } + + public boolean isFixed() { return fixed; } + + public void setX(double x) { this.x = x; } + public void setY(double y) { this.y = y; } + + public double getX() { return x; } + public double getY() { return y; } + + public ZZCell toHeadCell() { + return getCell().h(AwtUtil.d_from, 1).h(AwtUtil.d_clone); + } + + public ZZCell fromHeadCell() { + return getCell().h(AwtUtil.d_to).h(AwtUtil.d_clone); + } + + public String getZObName() { + return "Link"; + } + + public String cellRepr(ZZCell start, boolean clone) + { + ZZCell c = start.getOrNewCell("d.1"); + c.setText(getZObClassName()); + c = c.getOrNewCell("d.1"); + c.setText("x"); + c.getOrNewCell("d.1").setText(""+getX()); + c = c.getOrNewCell("d.2"); + c.setText("y"); + c.getOrNewCell("d.1").setText(""+getY()); + return ""; + } +} + +// vim: set syntax=java : diff --git a/Modules/awtool/AwtMetrics.java b/Modules/awtool/AwtMetrics.java new file mode 100644 index 0000000..b7a352e --- /dev/null +++ b/Modules/awtool/AwtMetrics.java @@ -0,0 +1,502 @@ +/* DO NOT EDIT THIS FILE. THIS FILE WAS GENERATED FROM ../Modules/awtool/AwtMetrics.zob, + * EDIT THAT FILE INSTEAD! + * All changes to this file will be lost. + */ +/* +AwtMetrics.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Kimmo Wideroos + */ + +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.awt.*; + +/** Abstract class for different metrics (in order to get different + * focus+context effects) + */ + +public abstract class AwtMetrics extends ZObCellRepr implements ZOb { + public static boolean dbg = true; + static void p(String s) { if(dbg) System.out.println(s); } + static void pa(String s) { System.out.println(s); } + + + /** UNDOCUMENTED. + + *

    Default value:

     { 400, 400 };
    . + + * @structparam 1 + */ + + public + int[] RealView + = { 400, 400 };/** UNDOCUMENTED. + + *

    Default value:

     { 400, 400 };
    . + + * @structparam 1 + */ + + public int[] VirtualView + = { 400, 400 };/** UNDOCUMENTED. + + *

    Default value:

     { 0.0, 0.0 };
    . + + * @structparam 1 + */ + + public double[] Origo + = { 0.0, 0.0 };/** UNDOCUMENTED. + + *

    Default value:

     { 200, 200 };
    . + + * @structparam 1 + */ + + public int[] FocusOrigo + = { 200, 200 };/** UNDOCUMENTED. + + *

    Default value:

     true;
    . + + * @structparam 1 + */ + + public boolean GridOn + = true; + + /* AUTOGENERATED! */ + static final private int fullmask = 31; + + /* AUTOGENERATED! */ + public String readParams(ZZCell start) { + int m = 0; + try { + if(start != null) + m = readParams(start, 0); + } catch(Throwable t) { + ZZLogger.exc(t); + } finally { + + } + if((m & fullmask) != fullmask) { + // not all parameters present - no problem right now. + } + return ""; + } + + /* AUTOGENERATED! */ + private int readParams(ZZCell start, int mask) { + ZZCell n = start; + while(n != null) { + String s = n.getText(); + // Tests autogenerated from members. + + if(s.equals("RealView")) { + mask |= 1; + try { + + // count rank + int i=-1; + for(ZZCell c = n; c!=null; c=c.s("d.1")) i++; + // XXX check range + RealView = new int[i]; + i=0; + for(ZZCell c = n.s("d.1"); + c!=null; c=c.s("d.1")) { + s = c.getText(); + RealView[i] = Integer.parseInt(s); ; + i++; + } + + } catch(Exception e) { + ZZLogger.exc(e); + } + } else + + + if(s.equals("VirtualView")) { + mask |= 2; + try { + + // count rank + int i=-1; + for(ZZCell c = n; c!=null; c=c.s("d.1")) i++; + // XXX check range + VirtualView = new int[i]; + i=0; + for(ZZCell c = n.s("d.1"); + c!=null; c=c.s("d.1")) { + s = c.getText(); + VirtualView[i] = Integer.parseInt(s); ; + i++; + } + + } catch(Exception e) { + ZZLogger.exc(e); + } + } else + + + if(s.equals("Origo")) { + mask |= 4; + try { + + // count rank + int i=-1; + for(ZZCell c = n; c!=null; c=c.s("d.1")) i++; + // XXX check range + Origo = new double[i]; + i=0; + for(ZZCell c = n.s("d.1"); + c!=null; c=c.s("d.1")) { + s = c.getText(); + Origo[i] = (Double.valueOf(s)).doubleValue();; + i++; + } + + } catch(Exception e) { + ZZLogger.exc(e); + } + } else + + + if(s.equals("FocusOrigo")) { + mask |= 8; + try { + + // count rank + int i=-1; + for(ZZCell c = n; c!=null; c=c.s("d.1")) i++; + // XXX check range + FocusOrigo = new int[i]; + i=0; + for(ZZCell c = n.s("d.1"); + c!=null; c=c.s("d.1")) { + s = c.getText(); + FocusOrigo[i] = Integer.parseInt(s); ; + i++; + } + + } catch(Exception e) { + ZZLogger.exc(e); + } + } else + + + if(s.equals("GridOn")) { + mask |= 16; + try { + ZZCell c = n.s("d.1"); s = c.getText(); + if(s.equals("true")) GridOn=true; + else if(s.equals("false")) GridOn=false; + else { /* XXX ??? */ } + + } catch(Exception e) { + ZZLogger.exc(e); + } + } else + + + { } // grab that last "else" + ZZCell h = n.h("d.3"); + if(h != null && h != n) { + // recurse + mask |= readParams(h, mask); + } + n = n.s("d.2"); + } + return mask; + } + + + + static ZZCell FocusedCell = null; + + double FocusCoefficient = focusCoefficientMinimum(); + + abstract double focusCoefficientMinimum(); + abstract double focusCoefficientMaximum(); + + public double[] RealViewd() { + return new double[] { (double)RealView[0], (double)RealView[1] }; + } + + public double[] RealViewHalfd() { + return new double[] { (double)RealView[0]*0.5, (double)RealView[1]*0.5 }; + } + + public void setRealView(int x, int y, boolean adjustFocus) { + if(adjustFocus) { + double[] rvd = RealViewd(); + double newfox = ((double)(x*FocusOrigo[0]))/rvd[0]; + double newfoy = ((double)(y*FocusOrigo[1]))/rvd[1]; + setFocusOrigo((int)newfox, (int)newfoy); + } + RealView[0] = x; RealView[1] = y; + } + + public void setRealView(Dimension d, boolean adjustFocus) { + setRealView(d.width, d.height, adjustFocus); + } + public double[] VirtualViewd() { + return new double[] { (double)VirtualView[0], (double)VirtualView[1] }; + } + + public double[] VirtualViewHalfd() { + return new double[] { (double)VirtualView[0]*0.5, (double)VirtualView[1]*0.5 }; + } + + public void setVirtualView(int x, int y) { + VirtualView[0] = x; VirtualView[1] = y; + } + + public void setOrigo(double ox, double oy) { + Origo[0] = ox; + Origo[1] = oy; + } + + public void moveOrigo(double dox, double doy) { + Origo[0] += dox; + Origo[1] += doy; + } + + public double[] FocusOrigod() { + return new double[] { (double)FocusOrigo[0], (double)FocusOrigo[1] }; + } + + + public void setFocusOrigo(int fox, int foy) { + setFocusOrigo(fox, foy, null); + } + + public void setFocusOrigo(int fox, int foy, ZZCell focusCell) { + FocusOrigo[0] = fox; + FocusOrigo[1] = foy; + if(focusCell != null && focusCell == FocusedCell) { + FocusCoefficient += 1.0; + if(FocusCoefficient > focusCoefficientMaximum()) + FocusCoefficient = focusCoefficientMaximum(); + } else { + FocusCoefficient = focusCoefficientMinimum(); + FocusedCell = focusCell; + } + } + + + public void init(ZZCell start, Dimension rv, Dimension vv, + double ox, double oy) { + setCell(start); + setRealView(rv.width, rv.height, false); + setVirtualView(vv.width, vv.height); + setOrigo(ox, oy); + setFocusOrigo(rv.width>>1, rv.height>>1); + } + + public AwtMetrics() { } + + public AwtMetrics(ZZCell start, Dimension rv, Dimension vv, + double ox, double oy) + { + init(start, rv, vv, ox, oy); + + } + + private Point mapToUnfocusedRealView(double x, double y) { + int rx, ry; + double[] vvhd = VirtualViewHalfd(), rvhd = RealViewHalfd(); + rx = (int)(( (x-Origo[0]) * vvhd[0]) + rvhd[0]); + ry = (int)(( (y-Origo[1]) * vvhd[1]) + rvhd[1]); + return new Point(rx, ry); + } + + /** mapping from 'virtualview' (=modelview, coordinates + * -1.0 focusCoefficientMaximum()) + FocusCoefficient = focusCoefficientMaximum(); + } else { + FocusCoefficient = focusCoefficientMinimum(); + FocusedCell = focusCell; + } + } + + + public void init(ZZCell start, Dimension rv, Dimension vv, + double ox, double oy) { + setCell(start); + setRealView(rv.width, rv.height, false); + setVirtualView(vv.width, vv.height); + setOrigo(ox, oy); + setFocusOrigo(rv.width>>1, rv.height>>1); + } + + public AwtMetrics() { } + + public AwtMetrics(ZZCell start, Dimension rv, Dimension vv, + double ox, double oy) + { + init(start, rv, vv, ox, oy); + + } + + private Point mapToUnfocusedRealView(double x, double y) { + int rx, ry; + double[] vvhd = VirtualViewHalfd(), rvhd = RealViewHalfd(); + rx = (int)(( (x-Origo[0]) * vvhd[0]) + rvhd[0]); + ry = (int)(( (y-Origo[1]) * vvhd[1]) + rvhd[1]); + return new Point(rx, ry); + } + + /** mapping from 'virtualview' (=modelview, coordinates + * -1.0-1) { + dx = x2; + } else { + dx = x2*x2; + dx = x2>0 ? dx : -dx; + } + + if(y2<1 && y2>-1) { + dy = y2; + } else { + dy = y2*y2; + dy = y2>0 ? dy : -dy; + } + + return new double[] { dx/focusCoeff, dy/focusCoeff }; + } + + public double[] inverseTransformAtFocusNbhood(double x, double y, double focusCoeff) { + double dx, dy, x2, y2; + + x2 = x*focusCoeff; + y2 = y*focusCoeff; + + if(x2<1 && x2>-1) { + dx = x2; + } else { + dx = (x2>0) ? Math.sqrt(x2) : -Math.sqrt(-x2); + } + + if(y2<1 && y2>-1) { + dy = y2; + } else { + dy = (y2>0) ? Math.sqrt(y2) : -Math.sqrt(-y2); + } + + return new double[] { dx/focusCoeff, dy/focusCoeff }; + } + + public double transformScalingValue(double s) { return 1.0/s; } + + public double focusCoefficientMinimum() { return 4.0; } + public double focusCoefficientMaximum() { return 8.0; } + + public AwtMetricsFC() { super(); } + + public AwtMetricsFC(ZZCell start, Dimension rv, Dimension vv, + double ox, double oy) { + super(start, rv, vv, ox, oy); + } +} + diff --git a/Modules/awtool/AwtMetricsFC2.java b/Modules/awtool/AwtMetricsFC2.java new file mode 100644 index 0000000..252357c --- /dev/null +++ b/Modules/awtool/AwtMetricsFC2.java @@ -0,0 +1,94 @@ +/* +AwtMetricsFC2.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Kimmo Wideroos + */ + +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.awt.*; + +/** Focus+context metrics2 + */ + + +public class AwtMetricsFC2 extends AwtMetrics { + public String getZObName() { + return "Focus+Context (2)"; + } + + public double[] transformAtFocusNbhood(double x, double y, double focusCoeff) { + double dx, dy, x2, y2; + + x2 = x*focusCoeff; + y2 = y*focusCoeff; + + if(x2<1 && x2>-1) { + dx = x2; + } else { + dx = (x2>0) ? Math.sqrt(x2) : -Math.sqrt(-x2); + } + + if(y2<1 && y2>-1) { + dy = y2; + } else { + dy = (y2>0) ? Math.sqrt(y2) : -Math.sqrt(-y2); + } + + return new double[] { dx/focusCoeff, dy/focusCoeff }; + } + + public double[] inverseTransformAtFocusNbhood(double x, double y, double focusCoeff) { + double dx, dy, x2, y2; + + x2 = x*focusCoeff; + y2 = y*focusCoeff; + + if(x2<1 && x2>-1) { + dx = x2; + } else { + dx = x2*x2; + dx = x2>0 ? dx : -dx; + } + + if(y2<1 && y2>-1) { + dy = y2; + } else { + dy = y2*y2; + dy = y2>0 ? dy : -dy; + } + + return new double[] { dx/focusCoeff, dy/focusCoeff }; + } + + public double transformScalingValue(double s) { return s; } + + public double focusCoefficientMinimum() { return 4.0; } + public double focusCoefficientMaximum() { return 8.0; } + + public AwtMetricsFC2() { super(); } + + public AwtMetricsFC2(ZZCell start, Dimension rv, Dimension vv, + double ox, double oy) { + super(start, rv, vv, ox, oy); + } +} + diff --git a/Modules/awtool/AwtMetricsNormal.java b/Modules/awtool/AwtMetricsNormal.java new file mode 100644 index 0000000..bbc6680 --- /dev/null +++ b/Modules/awtool/AwtMetricsNormal.java @@ -0,0 +1,58 @@ +/* +AwtMetricsNormal.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Kimmo Wideroos + */ + +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.awt.*; + +/** Default metrics: Euclidean, no focus+context (no scaling) + */ + + +public class AwtMetricsNormal extends AwtMetrics { + public String getZObName() { + return "Normal(Euclidean)"; + } + + public double[] transformAtFocusNbhood(double x, double y, double focusCoeff) { + return new double[] { x, y }; + } + + public double[] inverseTransformAtFocusNbhood(double x, double y, double focusCoeff) { + return new double[] { x, y }; + } + + public double transformScalingValue(double s) { return 1.0; } + + public double focusCoefficientMinimum() { return 1.0; } + public double focusCoefficientMaximum() { return 1.0; } + + public AwtMetricsNormal() { super(); } + + public AwtMetricsNormal(ZZCell start, Dimension rv, Dimension vv, + double ox, double oy) { + super(start, rv, vv, ox, oy); + } +} + diff --git a/Modules/awtool/AwtNileView.java b/Modules/awtool/AwtNileView.java new file mode 100644 index 0000000..e73b4f3 --- /dev/null +++ b/Modules/awtool/AwtNileView.java @@ -0,0 +1,110 @@ +/* +AwtNileView.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Nile1View.java written by Tuomas Lukka, + * AwtNileView - localization for Awtool by Kimmo Wideroos + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.awt.*; +import java.io.*; + +/** A view for nile streams. + */ + +public class AwtNileView extends Nile1View { +public static final String rcsid = ""; + public static boolean dbg = false; + static void p(String s) { if(dbg) System.out.println(s); } + static void pa(String s) { System.out.println(s); } + + public AwtNileView() { + init__zob(); + } + + public void awtNileRaster(FlobSet into, ZZCell view, ZZCell accursed, + Rectangle rect) { + int[] offs = new int[1]; + + LoopDetector ld = new LoopDetector(); + + ZZCursor selectEnd = null; + ZZCell sele = view.s("d.nile-sel"); + if(sele != null) { + selectEnd = ZZCursorVirtual.createFromReal(sele); + } + + // Do the center paragraph first. + ZZCell firstpara = Nile2Iter.findStruct(accursed, -1, true); + ZZCell nextpara = Nile2Iter.findStruct(accursed, 1, false); + + FText ft = paragraph(firstpara, nextpara, new ZZCursorReal(view), + offs, selectEnd); + + Dimension size = new Dimension(rect.width, rect.height); + //Rectangle rect = new Rectangle(0, 0, size.width, size.height); + + Rectangle ctr = placeParagraph(into, ft, firstpara, rect, + 0, rect.y+rect.height/2, + ZZCursorReal.getVisualTextOffset(view)); + + // Go into positive direction. + Rectangle r = ctr; + while(nextpara != null) { + ld.detect(nextpara); + ZZCell next = Nile2Iter.findStruct(nextpara, 1, false); + ft = paragraph(nextpara, next, null, null, selectEnd); + + r = placeParagraph(into, ft, nextpara, rect, + 1, r.y+r.height + paraskip, 0); + + nextpara = next; + + if(r.y + r.height > size.height) break; + } + + // And negative. + r = ctr; + while(true) { + ZZCell prev = firstpara; + firstpara = Nile2Iter.findStruct(firstpara, -1, false); + if(firstpara == null) break; + ld.detect(firstpara); + + ft = paragraph(firstpara, prev, null, null, null); + + beginningSentence[0] = true; + r = placeParagraph(into, ft, firstpara, rect, + -1, r.y - paraskip, 0); + + if(r.y < 0) break; + } + // into.dump(); + Flob cursf = into.findFlob(null, accursed); + // p("Cursf: "+cursf); + if(cursf != null) + ((SplitCellFlob1)cursf).addCurs(into, ZZCursorReal.getOffs(view), + Color.red); + } +} + + +// vim: set syntax=java : diff --git a/Modules/awtool/AwtNote.java b/Modules/awtool/AwtNote.java new file mode 100644 index 0000000..d04bdf9 --- /dev/null +++ b/Modules/awtool/AwtNote.java @@ -0,0 +1,212 @@ +/* DO NOT EDIT THIS FILE. THIS FILE WAS GENERATED FROM ../Modules/awtool/AwtNote.zob, + * EDIT THAT FILE INSTEAD! + * All changes to this file will be lost. + */ +/* +Awtnote.java + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Kimmo Wideroos + */ + +package org.gzigzag.module; +import org.gzigzag.*; +import java.awt.*; +import java.util.*; + +/** this is for awt content. change 'AwtNote' => 'AwtContent' +*/ + + +public class AwtNote extends ZObCellRepr implements ZOb { + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + + /** UNDOCUMENTED. + + *

    Default value:

     0.1;
    . + + * @structparam 1 + */ + + public + double width + = 0.1;/** UNDOCUMENTED. + + *

    Default value:

     0.07;
    . + + * @structparam 1 + */ + + public double height + = 0.07; + + + /* AUTOGENERATED! */ + static final private int fullmask = 3; + + /* AUTOGENERATED! */ + public String readParams(ZZCell start) { + int m = 0; + try { + if(start != null) + m = readParams(start, 0); + } catch(Throwable t) { + ZZLogger.exc(t); + } finally { + + } + if((m & fullmask) != fullmask) { + // not all parameters present - no problem right now. + } + return ""; + } + + /* AUTOGENERATED! */ + private int readParams(ZZCell start, int mask) { + ZZCell n = start; + while(n != null) { + String s = n.getText(); + // Tests autogenerated from members. + + if(s.equals("width")) { + mask |= 1; + try { + ZZCell c = n.s("d.1"); s = c.getText(); width = (Double.valueOf(s)).doubleValue(); + } catch(Exception e) { + ZZLogger.exc(e); + } + } else + + + if(s.equals("height")) { + mask |= 2; + try { + ZZCell c = n.s("d.1"); s = c.getText(); height = (Double.valueOf(s)).doubleValue(); + } catch(Exception e) { + ZZLogger.exc(e); + } + } else + + + { } // grab that last "else" + ZZCell h = n.h("d.3"); + if(h != null && h != n) { + // recurse + mask |= readParams(h, mask); + } + n = n.s("d.2"); + } + return mask; + } + + + + // category link + private AwtLink cLink = null; + double x = Double.NaN; + double y = Double.NaN; + + public void setCell(ZZCell c) { + super.setCell(c); + ZZCell cc, nCategoryCell = AwtUtil.getNoteCellCategory(c); + if(nCategoryCell != null) { + cc = c.s(AwtUtil.d_from, -1); + if(cc.s("d.1") != null) + cLink = (AwtLink)AwtUtil.readZObClone(cc); + else + cLink = new AwtLink(); + cLink.setCell(cc); + } else { + cLink = new AwtLink(); + } + } + + public double getWidth() { return width; } + public double getHeight() { return height; } + + public double[] getDimension() { return new double[] { width, height }; } + public void setDimension(double w, double h) { + width = w; + height = h; + } + + public AwtLink getCategoryLink() { + return cLink; + } + + public void setCategoryLink(AwtLink cl) { + cLink = cl; + } + + public void setCoord(double x, double y) { + cLink.setX(x); + cLink.setY(y); + } + + public void setX(double x) { + cLink.setX(x); + } + + public void setY(double y) { + cLink.setY(y); + } + + public double[] getCoord() { + return new double[] { cLink.getX(), cLink.getY() }; + } + + public double getX() { + return cLink.getX(); + } + public double getY() { + return cLink.getY(); + } + + public String getZObName() { + return "Note"; + } + + /** method for storing ZOb back to structure. + * @param start quess;) + * @param clone whether or not to make the new central cell a clone of + * this.cell (default is true). + */ + public String cellRepr(ZZCell start, boolean clone) + { + ZZCell c = start.getOrNewCell("d.1"); + c.setText(getZObClassName()); + c.setText("AwtNote"); + c = c.getOrNewCell("d.1"); + c.setText("width"); + c.getOrNewCell("d.1").setText(""+getWidth()); + c = c.getOrNewCell("d.2"); + c.setText("height"); + c.getOrNewCell("d.1").setText(""+getHeight()); + if(clone && !start.equals(getCell())) { + getCell().connect(AwtUtil.d_clone, start); + } + if(cLink.getCell() != null) cLink.cellRepr(); + return ""; + } +} + +// vim: set syntax=java : diff --git a/Modules/awtool/AwtNote.zob b/Modules/awtool/AwtNote.zob new file mode 100644 index 0000000..6b47d30 --- /dev/null +++ b/Modules/awtool/AwtNote.zob @@ -0,0 +1,135 @@ +/* +Awtnote.java + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Kimmo Wideroos + */ + +package org.gzigzag.module; +import org.gzigzag.*; +import java.awt.*; +import java.util.*; + +/** this is for awt content. change 'AwtNote' => 'AwtContent' +*/ + + +public class AwtNote extends ZObCellRepr implements ZOb { + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + STRUCTPARAMS { + double width + = 0.1; + + double height + = 0.07; + } + + // category link + private AwtLink cLink = null; + double x = Double.NaN; + double y = Double.NaN; + + public void setCell(ZZCell c) { + super.setCell(c); + ZZCell cc, nCategoryCell = AwtUtil.getNoteCellCategory(c); + if(nCategoryCell != null) { + cc = c.s(AwtUtil.d_from, -1); + if(cc.s("d.1") != null) + cLink = (AwtLink)AwtUtil.readZObClone(cc); + else + cLink = new AwtLink(); + cLink.setCell(cc); + } else { + cLink = new AwtLink(); + } + } + + public double getWidth() { return width; } + public double getHeight() { return height; } + + public double[] getDimension() { return new double[] { width, height }; } + public void setDimension(double w, double h) { + width = w; + height = h; + } + + public AwtLink getCategoryLink() { + return cLink; + } + + public void setCategoryLink(AwtLink cl) { + cLink = cl; + } + + public void setCoord(double x, double y) { + cLink.setX(x); + cLink.setY(y); + } + + public void setX(double x) { + cLink.setX(x); + } + + public void setY(double y) { + cLink.setY(y); + } + + public double[] getCoord() { + return new double[] { cLink.getX(), cLink.getY() }; + } + + public double getX() { + return cLink.getX(); + } + public double getY() { + return cLink.getY(); + } + + public String getZObName() { + return "Note"; + } + + /** method for storing ZOb back to structure. + * @param start quess;) + * @param clone whether or not to make the new central cell a clone of + * this.cell (default is true). + */ + public String cellRepr(ZZCell start, boolean clone) + { + ZZCell c = start.getOrNewCell("d.1"); + c.setText(getZObClassName()); + c.setText("AwtNote"); + c = c.getOrNewCell("d.1"); + c.setText("width"); + c.getOrNewCell("d.1").setText(""+getWidth()); + c = c.getOrNewCell("d.2"); + c.setText("height"); + c.getOrNewCell("d.1").setText(""+getHeight()); + if(clone && !start.equals(getCell())) { + getCell().connect(AwtUtil.d_clone, start); + } + if(cLink.getCell() != null) cLink.cellRepr(); + return ""; + } +} + +// vim: set syntax=java : diff --git a/Modules/awtool/AwtUtil.java b/Modules/awtool/AwtUtil.java new file mode 100644 index 0000000..f1e7d4d --- /dev/null +++ b/Modules/awtool/AwtUtil.java @@ -0,0 +1,329 @@ +/* +AwtUtil.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Kimmo Wideroos + */ + +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.awt.*; + +/** Some general stuff + */ + +public class AwtUtil { + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + public static String d_to="d.map-1"; + public static String d_from="d.map-2"; + public static String d_categories="d.categories"; + public static String d_notes="d.notes"; + public static String d_awtool="d.awtool"; + + public static String d_clone="d.clone"; + + public static ZZCell addDims(ZZCell defaultDimsBegin) { + Hashtable awtDims = new Hashtable(); + + awtDims.put(d_to, d_to); + awtDims.put(d_from, d_from); + awtDims.put(d_categories, d_categories); + awtDims.put(d_notes, d_notes); + awtDims.put(d_awtool, d_awtool); + + String dim; + + for(ZZCell c = defaultDimsBegin; c != null; c = c.s("d.2") ) { + dim = c.getText(); + if(awtDims.containsKey(dim)) + awtDims.remove(dim); + if(c.equals(defaultDimsBegin.s("d.2", -1))) break; + } + + for(Enumeration e = awtDims.keys(); e.hasMoreElements(); ) { + dim = (String)e.nextElement(); + defaultDimsBegin.N("d.2", -1).setText(dim); + } + return defaultDimsBegin; + } + + /** return awt system list roocell + */ + public static ZZCell getAwtSysList(ZZCell vc) { + ZZCell awtc = ZZDefaultSpace.findInheritableParam(vc, "AwtSystemList"); + if(awtc == null) return null; + return ZZCursorReal.get(awtc); + } + + /** return active metrics + */ + public static AwtMetrics getAwtMetrics(ZZCell awtsyslist) { + ZZCell metr = getCursoredCell(Awtool.c_metrics, awtsyslist); + if(metr==null) { + metr = awtsyslist.findText(d_awtool, 1, "Metrics"); + if(metr!=null) metr = metr.s("d.1"); + } + if(metr == null) throw new ZZError("Awtool: Couldn't initialize metrics!!"); + AwtMetrics M = (AwtMetrics)readZObClone(metr); + M.setCell(metr); + return M; + } + + public static ZZCell getCursoredCell(AwtCursor acur, ZZCell viewcellOrAwtsyslist) { + String cursorName = acur.color.toString(); + ZZCell awtsyslist, vc, cur=null, cursors; + + // scrutinize 'viewcellOrAwtsyslist' + if(viewcellOrAwtsyslist.getRankLength(d_awtool)>1) { + awtsyslist = viewcellOrAwtsyslist; + vc = null; + } else { + vc = viewcellOrAwtsyslist; + awtsyslist = getAwtSysList(vc); + } + + // shared cursors belongs to all awtool views + if(!acur.shared) { + cursors = awtsyslist.findText(d_awtool, 1, "Cursors").s("d.1"); + cur = cursors.findText("d.2", 1, cursorName); + } else { + ZZCell scursors, win, vcShared; + ZZCell[] wins; + ZZSpace sp = vc.getSpace(); + win = ZZDefaultSpace.findOnSystemlist(sp, "Windows", false); + win = win.s("d.1"); + wins = AwtUtil.findAll(win, "d.2", 1, "awtool"); + if(wins==null) throw new ZZError("Awtool: No awtool window found!!"); + for(int i=0; i1) { + awtsyslist = viewcellOrAwtsyslist; + vc = null; + } else { + vc = viewcellOrAwtsyslist; + awtsyslist = getAwtSysList(vc); + } + + // shared cursors belongs to all awtool views + if(!acur.shared) { + cursors = awtsyslist.findText(d_awtool, 1, "Cursors").s("d.1"); + cur = cursors.findText("d.2", 1, cursorName); + } else { + ZZCell win, vcShared; + ZZCell[] wins; + ZZSpace sp = vc.getSpace(); + win = ZZDefaultSpace.findOnSystemlist(sp, "Windows", false); + win = win.s("d.1"); + wins = AwtUtil.findAll(win, "d.2", 1, "awtool"); + if(wins==null) throw new ZZError("Awtool: No awtool window found!!"); + for(int i=0; i=0; i--) { + fc[i] = (ZZCell)found.elementAt(i); + } + return fc; + } + + public interface ObjectComparator { + int compare(Object o1, Object o2); + } + + public static void quickSort(Vector a, int lo0, int hi0, ObjectComparator c) { + int lo = lo0; + int hi = hi0; + + if (lo >= hi) + return; + + Object mid = a.elementAt((lo + hi) / 2); + while (lo < hi) { + while (lo 0) + hi--; + if (lo < hi) { + Object T = a.elementAt(lo); + a.setElementAt(a.elementAt(hi), lo); + a.setElementAt(T, hi); + lo++; + hi--; + } + } + if (hi < lo) { + int T = hi; + hi = lo; + lo = T; + } + quickSort(a, lo0, lo, c); + quickSort(a, lo == lo0 ? lo+1 : lo, hi0, c); + } + + /** Construct and return a ZOb of the given type. + */ + public static ZOb newModuleZOb(String id) { + // XXX Figure out if we can cache something. + // XXX Should ZOb be able to reset? Easier or less easy than + // recreate? At least ZObs should cache... + try { + Class z = Class.forName("org.gzigzag.module."+id); + return (ZOb)Class.forName("org.gzigzag.module."+id).newInstance(); + } catch(Exception e) { + ZZLogger.exc(e); + return null; + } + } + + /** Construct a ZOb corresponding to a cell and read the params. + * DOES NOT Go to the rootclone, takes the next cell on d.1 as the ZOb's name, + * and takes the NEXT cell on d.1 as the head of the list from which to + * read the structparams. + */ + static public ZOb readZObClone(ZZCell start) { + //ZZCell c = start.h("d.clone", -1).s("d.1", 1); + + if(start.s("d.1") == null) start = start.h("d.clone", -1); + ZZCell c = start.s("d.1", 1); + if(c == null) + throw new ZZError("Error reading ZOb from cell "+start.getText()); + ZOb z = newModuleZOb(c.getText()); + z.readParams(c.s("d.1", 1)); + return z; + } + + /** return category cell of the note c + */ + static public ZZCell getNoteCellCategory(ZZCell c) { + ZZCell qwerty = c.s(d_from, -1); + if(qwerty == null) return null; + if(qwerty.equals(qwerty.h(d_to, -1))) return null; + qwerty = qwerty.h(d_to, -1); + if(qwerty.getRankLength(d_categories) == 1) return null; + return qwerty; + } + + static public AwtNote createNewNote(ZZCell c, double[] ncenter, + double[] ndim) { + AwtNote newNote = new AwtNote(); + newNote.setCell(c); + newNote.setCoord(ncenter[0], ncenter[1]); + newNote.setDimension(ndim[0], ndim[1]); + newNote.cellRepr(); + return newNote; + } + + public void deleteNote(ZZCell nc) { + // should delete ZOb structures ... in future + // ZObCellRepr will have 'deleteZOb' method. + ZZCell hc = nc.h(d_clone); + nc.delete(); + if(hc.getRankLength(d_clone)==1) { + hc.delete(); + } + } + + static public void createNewLink(ZZCell from, ZZCell to) { + ZZCell newLinkCell = from.h(AwtUtil.d_to, 1).N(AwtUtil.d_to, 1); + to.h(AwtUtil.d_from, -1).connect(AwtUtil.d_from, -1, newLinkCell); + AwtLink al = new AwtLink(); + al.setCell(newLinkCell); + al.cellRepr(); + } + + static public void renderGrid(FlobSet into, AwtMetrics M, double x1, double + y1, double x2, double y2, Color color, int density) + { + double[] coord = new double[2], cstart = new double[2], cinc = new double[2], + d = new double[2], dh = new double[2]; + Point p1, p2; + int i, j, a, b; + cstart[0] = (x1 < x2) ? x1 : x2; + cstart[1] = (y1 < y2) ? y1 : x2; + cinc[0] = Math.abs((x2-x1) / ((double)density + 1.0)); + cinc[1] = Math.abs((y2-y1) / ((double)density + 1.0)); + d[0] = cinc[0] / 5.0; + d[1] = cinc[1] / 5.0; + dh[0] = d[0]/2.0; + dh[1] = d[1]/2.0; + + for(a=0; a<2; a++) { + b = (a==0) ? 1 : 0; + coord[a] = cstart[a]; + for(i=0; i<=density+1; i++) { + coord[b] = cstart[b]+dh[b]/2.0; + for(j=1; j<=(density+1)*5; j++) { + p1 = M.mapToRealView(coord); + coord[b] += dh[b]; + p2 = M.mapToRealView(coord); + coord[b] += dh[b]; + into.add(new LineDecor(p1.x, p1.y, p2.x, p2.y, color, 2)); + } + coord[a] += cinc[a]; + } + } + } +} + + + + + + diff --git a/Modules/awtool/AwtView1.java b/Modules/awtool/AwtView1.java new file mode 100644 index 0000000..e3bf3be --- /dev/null +++ b/Modules/awtool/AwtView1.java @@ -0,0 +1,341 @@ +/* +AwtView1.zob + * + * Copyright (c) 2000-2001 Ted Nelson and Tuomas Lukka + * Copyright (c) 2000-2001 Kimmo Wideroos + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Kimmo Wideroos + */ + +/** View for a(ssociative) writing tool +*/ + +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.awt.*; +//import java.lang.reflect.*; + +public class AwtView1 extends Awtool { + + static AwtNileView awtNile = new AwtNileView(); + + class AwtBgFlob extends CellBgFlob { + + public AwtBgFlob(int x, int y, int d, int w, int h, ZZCell c) { + super(x, y, d, w, h, c); + } + + public void render(Graphics g, int mx, int my, int md, int mw, int mh) { + + Color[] solids = getSolidColors(); + int nsolids = 0; + + if(solids!=null) nsolids = solids.length; + + Color oldfg = g.getColor(); + Shape oldclip = g.getClip(); + + g.clipRect(mx, my, mw, mh); + + if(solids != null) { + int iq=0, id=0; + for(int i=0; i0 && mh-iq-5>0) { + g.drawRect(mx+id+1, my+id+1, mw-iq-3, mh-iq-3); + g.drawRect(mx+id+2, my+id+2, mw-iq-5, mh-iq-5); + id += 2; + iq += 4; + } + g.setColor(bg); + g.fillRect(mx+id+1, my+id+1, mw-iq-3, mh-iq-3); + //g.fillRect(mx+(mw*i)/nsolids, my, mw/nsolids+1, mh); + } + } else { + g.setColor(bg); + g.fillRect(mx, my, mw, mh); + } + + g.setColor(oldfg); + + renderContent(g, mx, my, mw, mh); + + // XXX Span indication??? + + g.drawRect(mx, my, mw-1, mh-1); + + g.setClip(oldclip); + } + } + + class AwtLinkFlob extends CellBgFlob { + + Point from, to; + + AwtLinkFlob(Point from, Point to, ZZCell c) { + super((from.x+to.x)>>1, (from.y+to.y)>>1, Math.abs(from.x-to.x), + Math.abs(from.y-to.y), 2, c); + this.from = from; + this.to = to; + //super((from.x+to.x)>>1, (from.y+to.y)>>1, w, h, 2, c); + } + + public void render(Graphics g, int mx, int my, int md, + int mw, int mh) { + + Color[] solids = getSolidColors(); + int nsolids = 0; + + if(solids!=null) nsolids = solids.length; + + Color oldfg = g.getColor(); + //Shape oldclip = g.getClip(); + + // XXX save font? + + //g.clipRect(mx, my, mw, mh); + + if(solids != null) { + int lx, ly, dw, dh; + lx = from.x; + ly = from.y; + dw = lx - to.x; + dh = ly - to.y; + for(int i=0; i= 0) + nileOn = true; + } + + Dimension nDim; + Point nCoord = new Point(); + Rectangle rect; + + // if note is dragged, draw only that one + if(Awtool.dragNote != null) { + nCoord = M.mapToRealView(dragNote.getX(), dragNote.getY()); + nDim = M.getRealDimension(dragNote.getX(), dragNote.getY(), dragNote.getDimension()); + rect = new Rectangle(nCoord.x-(nDim.width>>1), nCoord.y-(nDim.height>>1), + nDim.width, nDim.height); + makeAwtNote(into, view, dragNote.getCell(), rect, nileOn); + return; + } + + + + ZZCell activeCategory = + AwtUtil.getCursoredCell(Awtool.c_activeCategory, awtsyslist); + //view.getSpace().getCellByID("1051"); //getActiveCategory(view); + if(activeCategory==null) { + activeCategory = + awtsyslist.h(AwtUtil.d_categories,1). + s(AwtUtil.d_categories, -1). + getOrNewCell(AwtUtil.d_categories); + AwtUtil.setCursor(Awtool.c_activeCategory, activeCategory, awtsyslist); + } + Categories C = new Categories(activeCategory); + + AwtNote[] validNotes = C.getValidNotes(); + + // 'renderedNotes': key = notecell, value = {int x, y, w, h} + Hashtable renderedNotes = new Hashtable(); + + Vector notFixedNotes = new Vector(); + ZZCell noteCell, noteParams, categoryLinkCell; + AwtLink catlink; + AwtNote note; + int[] noteSize; + double y, x, yRowMax=0.0, w, h, gap=0.1; + + for(int i=0; i>1), nCoord.y-(nDim.height>>1), + nDim.width, nDim.height); + makeAwtNote(into, view, noteCell, rect, nileOn); + + } + + AwtUtil.quickSort(notFixedNotes, 0, notFixedNotes.size()-1, + new AwtUtil.ObjectComparator() { + public int compare(Object o1, Object o2) { + return (( ((AwtNote)o1).getHeight() < + ((AwtNote)o2).getHeight() ) ? 1 : 0 ); + } + }); + + y = 1.0-gap; x = gap; + for(Enumeration e=notFixedNotes.elements(); e.hasMoreElements();){ + note = (AwtNote)e.nextElement(); + noteCell = note.getCell(); + w = note.getWidth(); + if(x+w>1.0-gap) { + x = gap; + y += yRowMax; + yRowMax = 0; + } + h = note.getHeight(); + note.setCoord(x+(w/2.0), y+(h/2.0)); + x += (w+gap); + if(h>yRowMax) yRowMax = h; + + + nCoord = M.mapToRealView(note.getX(), note.getY()); + + nDim = M.getRealDimension(note.getX(), note.getY(), note.getDimension()); + + // importtant: notes' headcells as keys + renderedNotes.put(noteCell.h(AwtUtil.d_clone), + new int[] { nCoord.x, nCoord.y, nDim.width, nDim.height }); + + rect = new Rectangle(nCoord.x, nCoord.y, nDim.width, + nDim.height); + makeAwtNote(into, view, noteCell, rect, nileOn); + //fact.centerFlob(into, noteCell, noteCell, 1, + // nCoord, 0, 0, 1, nDim); + } + + // render links + + int[] toField, fromField; + ZZCell toc, fromc; + AwtLink al; + AwtLink[] validLinks = C.getAllValidLinks(true, true); + + for(int i=0; iDefault value:
     600;
    . + + * @structparam 1 + */ + + public + int viewWidth + = 600; + int viewHeight + = 600; + int viewX + = 100; + int viewY + = 100; + + + /* AUTOGENERATED! */ + static final private int fullmask = 1; + + /* AUTOGENERATED! */ + public String readParams(ZZCell start) { + int m = 0; + try { + if(start != null) + m = readParams(start, 0); + } catch(Throwable t) { + ZZLogger.exc(t); + } finally { + + } + if((m & fullmask) != fullmask) { + // not all parameters present - no problem right now. + } + return ""; + } + + /* AUTOGENERATED! */ + private int readParams(ZZCell start, int mask) { + ZZCell n = start; + while(n != null) { + String s = n.getText(); + // Tests autogenerated from members. + + if(s.equals("viewWidth")) { + mask |= 1; + try { + ZZCell c = n.s("d.1"); s = c.getText(); viewWidth = Integer.parseInt(s); + } catch(Exception e) { + ZZLogger.exc(e); + } + } else + + + { } // grab that last "else" + ZZCell h = n.h("d.3"); + if(h != null && h != n) { + // recurse + mask |= readParams(h, mask); + } + n = n.s("d.2"); + } + return mask; + } + + + + + + static boolean NileOn = false; + static AwtNote dragNote; + static Point dragOffs = new Point(0, 0); + static Point dragCoord = new Point(0, 0); + + static boolean creatingNote = false; + + static long focusChangedLastTime = -1; // millisecs + + static AwtCursor c_cursor1 = new AwtCursor(Color.red, true); + static AwtCursor c_cursor2 = new AwtCursor(Color.gray, true); + static AwtCursor c_activeCategory = new AwtCursor(Color.orange, false); + static AwtCursor c_metrics = new AwtCursor(Color.white, false); + + public boolean accept(Object o) { + if(!(o instanceof ZZCell)) return false; + return true; + } + + static public Hashtable categ; + static public Hashtable notes; + static public Hashtable validNotes; + + static class NotemapBM extends BooleanMesh { + public NotemapBM(ZZCell bStructure) { super(bStructure); } + public boolean testBelonging(ZZCell nhc, ZZCell category) { + for(ZZCell l=category.h(AwtUtil.d_clone).s(AwtUtil.d_to); l != null; l=l.s(AwtUtil.d_to) ) + if(l.h(AwtUtil.d_from,1).h(AwtUtil.d_clone).equals(nhc)) return true; + return false; + } + } + + + + /* categories are a kind of layers containing notes (i.e. (text) elements). + * this class provides with logical operations for categories (AND, OR). + * the resulting categories should be able to store permanently in zzspace. + * heavily under construction ... + */ + public class Categories extends ZObCellRepr { + private Hashtable AllNoteHeadCells = null; + private Hashtable AllNotes = null; + private Hashtable AllValidNotes = null; + private Hashtable ValidNotes = null; + private Hashtable K = new Hashtable(); + private NotemapBM bm; + private String categoryName = "SCRATCH"; + + public boolean isCategory(ZZCell c) { + return (c.h(AwtUtil.d_clone).getRankLength(AwtUtil.d_categories)>1); + } + + public Categories(ZZCell bStructure) { + setCell(bStructure); + _findCategories(bStructure); + bm = new NotemapBM(bStructure); + + AllNotes = new Hashtable(); + AllNoteHeadCells = new Hashtable(); + AllValidNotes = new Hashtable(); + ValidNotes = new Hashtable(); + + ZZCell note, chc, nhc; + for(Enumeration e = K.keys(); e.hasMoreElements(); ) { + // chc = category headcell + chc = ((ZZCell)e.nextElement()); + for(ZZCell linkc = chc.s(AwtUtil.d_to); linkc != null; + linkc = linkc.s(AwtUtil.d_to) ) + { + note = linkc.h(AwtUtil.d_from, 1); + nhc = note.h(AwtUtil.d_clone); + AllNotes.put(note, nhc); + if(!AllNoteHeadCells.containsKey(nhc)) + // AllNoteHeadCells must keep track of all note headcells + AllNoteHeadCells.put(nhc, note); + if(AllValidNotes.containsKey(nhc)) + // AllValidNotes store valid headcells AND clones + // all together + AllValidNotes.put(note, nhc); + else if(bm.evaluate(nhc)) AllValidNotes.put(note, nhc); + if(AllValidNotes.containsKey(note)) { + // If there exist 2 or more valid note clones, ValidNotes + // store note headcell (otherwise note clone). + if(ValidNotes.containsKey(nhc)) ValidNotes.put(nhc, nhc); + else ValidNotes.put(nhc, note); + } + } + } + } + + private void _findCategories(ZZCell bStructure) { + if(isCategory(bStructure)) { + K.put(bStructure.h(AwtUtil.d_clone), bStructure); + return; + } else + { + _findCategories(bStructure.s("d.1")); + _findCategories(bStructure.s("d.2")); + } + } + + public ZZCell[] getNoteCells() { + ZZCell[] n = new ZZCell[AllNotes.size()]; + Enumeration e = AllNotes.elements(); + int i = 0; + while (e.hasMoreElements()) { + n[i] = (ZZCell)e.nextElement(); i++; + } + return n; + } + public AwtNote[] getNotes() { + AwtNote[] n = new AwtNote[AllNotes.size()]; + Enumeration e = AllNotes.elements(); + ZZCell ncell; + int i = 0; + while (e.hasMoreElements()) { + ncell = (ZZCell)e.nextElement(); + n[i] = (AwtNote)AwtUtil.readZObClone(ncell); + n[i].setCell(ncell); + i++; + } + return n; + } + + public ZZCell[] getAllValidNoteCells() { + ZZCell[] ln = new ZZCell[AllValidNotes.size()]; + int i = 0; + for(Enumeration e=AllValidNotes.keys(); e.hasMoreElements();) { + ln[i] = (ZZCell)e.nextElement(); + i++; + } + return ln; + } + + public AwtNote[] getAllValidNotes() { + AwtNote[] ln = new AwtNote[AllValidNotes.size()]; + ZZCell ncell; + int i = 0; + for(Enumeration e=AllValidNotes.keys(); e.hasMoreElements();) { + ncell = (ZZCell)e.nextElement(); + ln[i] = (AwtNote)AwtUtil.readZObClone(ncell); + ln[i].setCell(ncell); + i++; + } + return ln; + } + + public ZZCell[] getValidNoteCells() { + ZZCell[] ln = new ZZCell[ValidNotes.size()]; + int i = 0; + for(Enumeration e=ValidNotes.elements(); e.hasMoreElements(); ) { + ln[i] = (ZZCell)e.nextElement(); + i++; + } + return ln; + } + + public AwtNote[] getValidNotes() { + AwtNote[] ln = new AwtNote[ValidNotes.size()]; + ZZCell ncell; + int i = 0; + for(Enumeration e=ValidNotes.elements(); e.hasMoreElements(); ) { + ncell = (ZZCell)e.nextElement(); + ln[i] = (AwtNote)AwtUtil.readZObClone(ncell); + ln[i].setCell(ncell); + i++; + } + return ln; + } + + public ZZCell[] getK() { + ZZCell[] cat = new ZZCell[K.size()]; + Enumeration e = K.elements(); + int i = 0; + while (e.hasMoreElements()) + cat[i] = (ZZCell)e.nextElement(); i++; + return cat; + } + + public ZZCell[] getAllValidLinkCells(boolean internal, boolean external) { + return _getvalidlinks(internal, external, AllValidNotes.keys()); + } + + public AwtLink[] getAllValidLinks(boolean internal, boolean external) + { + ZZCell[] linkcells = _getvalidlinks(internal, external, AllValidNotes.keys()); + AwtLink[] links = new AwtLink[linkcells.length]; + for(int i = 0; i=0; i--) { + note = validNotes[i]; + catlink.setX(note.getX()); catlink.setY(note.getY()); + catlink.cellRepr(catCell, false); + // note's centralcell is a clone of its (ZOb's) original + // central cell; that's why '...im2), true);' + note.cellRepr(catCell.getOrNewCell(AwtUtil.d_from), true); + catCell = catCell.getOrNewCell(AwtUtil.d_to); + } + return ""; + } + } + + /** return note cell, if possible + */ + static ZZCell getNoteCellOrCursor(Object ob) { + ZZCell c = null; + if(ob instanceof ZZCursor) c = ((ZZCursor)ob).get(); + else if(ob instanceof ZZCell) c = (ZZCell)ob; + else return null; + ZZCell link = c.s(AwtUtil.d_from, -1); + if(link == null) return null; + if(link.s(AwtUtil.d_to, -1) == null) return null; + return c; + } + + static public void nile_action(String id, ZZCell vc1, ZZCell vc2, String key, + ZZCursor cur) { + + boolean split = false; + + ZZCell viewCell = vc1; + ZZCell otherCell = vc2; + + p("Nile action: id: '"+id+"' key: '"+key); + + StringTokenizer st = new StringTokenizer(id); + String[] toks = new String[st.countTokens()]; + for(int i=0; i 1) { + if(toks[1].equals("+")) dir = 1; + else if(toks[1].equals("-")) dir = -1; + + if(toks.length > 2) { + if(toks[2].equals("CHAR")) + unit = new Nile2Unit.Char(); + else if(toks[2].equals("WORD")) + unit = new Nile2Unit.Word(); + else if(toks[2].equals("SENT")) + unit = new Nile2Unit.Sentence(); + else if(toks[2].equals("PARA")) + unit = new Nile2Unit.Paragraph(); + } + } + + id = toks[0]; + + if(id.equals("Cursor")) { + p("Cursor: "+dir); + Nile2Ops.moveCursor(unit, viewCell, dir); + ZZUpdateManager.setFast(null); + } + else if(id.equals("AdjLeft")) { + Nile2Ops.adjust(unit, viewCell, -1, dir); + ZZUpdateManager.setFast(null); + } + else if(id.equals("AdjRight")) { + Nile2Ops.adjust(unit, viewCell, 1, dir); + ZZUpdateManager.setFast(null); + } + else if(id.equals("Hop")) { + Nile2Ops.hop(unit, viewCell, dir); + } + else if(id.equals("Mode")) { + Nile2Ops.setCursor(unit, viewCell, null); + if(split) + Nile2Ops.setCursor(unit, otherCell, null); + } + else if(id.equals("Insert")) { + Nile2Ops.insert(viewCell, key); + + // Set the selection of other half to char mode, too + if(split) + Nile2Ops.setCursor(new Nile2Unit.Char(), otherCell, null); + } + else if(id.equals("BackSpace")) { + Nile2Ops.backspace(unit, viewCell); + } + else if(id.equals("Delete")) { + Nile2Ops.del(unit, viewCell); + } + else if(id.equals("BreakParagraph")) { + Nile2Ops.breakParagraph(unit, viewCell); + } + else if(id.equals("Tunnel")) { + if(otherCell != null) { + Nile2Ops.tunnel(unit, otherCell, viewCell, dir, false); + } + } + else if(id.equals("Transcopy")) { + if(otherCell != null) { + Nile2Ops.tunnel(unit, otherCell, viewCell, dir, true); + } + } + else if(id.equals("PUICopy")) { + ZZCell c = ZZCursorReal.get(viewCell); + String s = Nile2Ops.stringify(c); + ZZUtil.puiCopy(s); + } + /* + else if(id.equals("TraverseTranscopies")) { + Nile2Ops.traverseTranscopies(viewCell, dir); + } + */ + + //Object ob = null; + //if(pt != null) + // ob = xi.getObjectAt(pt.x, pt.y); + + if(id.equals("MouseSetCursor") && cur!=null) { + p("Setting cursor from mouse! Unit: "+unit); + if(cur.get().h("d.nile").equals(viewCell)) { + Nile2Ops.setCursor(unit, viewCell, cur); + } else + if(cur.get().h("d.nile").equals(otherCell)) { + Nile2Ops.setCursor(unit, otherCell, cur); + } + } + } + + + abstract public void raster(FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed); + + static public ZZModule module = new ZZModule() { + public void action(String id, + ZZCell code, + ZZCell target, + ZZView view, ZZView cview, String key, Point pt, ZZScene xi) { + + ZZUpdateManager.setFast(view); + Object ob = null; + AwtNote note = null; + AwtMetrics M; + ZZCell nc; + Point noteRVCoord = null; + double[] noteVVCoord = null; + double deltaX, deltaY; + + if(pt != null && xi != null) ob = xi.getObjectAt(pt.x, pt.y); + + nc = getNoteCellOrCursor(ob); + + if(nc != null) { + note = (AwtNote)AwtUtil.readZObClone(nc); + note.setCell(nc); + } + + boolean forceOrigoChange = false; + ZZCell AwtSystemList; + ZZCell vc = view.getViewcell(); + + pa("NOTECELL: "+nc); + + pa("Note action! '"+id+"' key: "+key); + + // is nile mode on? + boolean nileOn = false; + ZZCell curb = vc.h("d.bind", 1, true); + if(curb!=null) { + String mode = ZZCursorReal.get(curb).getText(); + if(mode.indexOf("Nile") >= 0) + nileOn = true; + } + pa("OBJECT: "+ob); + boolean isC = false; + if(ob instanceof ZZCursor) isC = true; + pa("IS CURSOR?: "+isC); + // if we have object which is not cursor, then nile action is impossible + if(nileOn && !(!(ob instanceof ZZCursor) && (ob != null)) ) { + ZZCell nvc1 = AwtUtil.getCursoredCell(c_cursor1, vc); + ZZCell nvc2 = AwtUtil.getCursoredCell(c_cursor2, vc); + if(nvc1==null) return; + + if(nvc1.s("d.cursor-cargo", -1)==null) { + ZZCursorReal.set(nvc1, nvc1); + ZZCursorReal.setOffs(nvc1, 0); + } + if(nvc2!=null) + if(nvc2.s("d.cursor-cargo", -1)==null) { + ZZCursorReal.set(nvc2, nvc2); + ZZCursorReal.setOffs(nvc2, 0); + } + + nile_action(id, nvc1, nvc2, key, (ZZCursor)ob); + //Nile1.module.action(id,code,target,nview,cview,key,pt,xi); + return; + } + + if(id.equals("TESTWIN")) { + AwtSystemList = target; + + // set awt dims + AwtUtil.addDims(ZZDefaultSpace.findDefaultDimlist(code.getHomeCell())); + + // Cursors + ZZCell curs = AwtSystemList.findText(AwtUtil.d_awtool, 1, "Cursors"); + if(curs == null) { + ZZCell nCurs1, nCurs2, cat1; + ZZCell cursors = AwtSystemList.N(AwtUtil.d_awtool); + cursors.setText("Cursors"); + cursors.N("d.1"); + } + + // View + ZZCell rastname, rl, rc = AwtSystemList.findText(AwtUtil.d_awtool, 1, "View"); + if(rc == null) { + rc = AwtSystemList.N(AwtUtil.d_awtool); + rc.setText("View"); + rl = rc.N("d.1"); + rl.connect("d.2", 1, rl); + rl.setText("Awtool"); + rastname = rl.N("d.1"); + rastname.setText("Awtool.View1"); + } else { + rl = rc.s("d.1"); + rastname = rl.s("d.1"); + } + + + // Bindings + ZZCell bindhome = AwtSystemList.findText(AwtUtil.d_awtool, 1, "Bind"); + if(bindhome == null) { + bindhome = AwtSystemList.N(AwtUtil.d_awtool); + bindhome.setText("Bind"); + bindhome = bindhome.N("d.1", 1); + + //ZZDefaultSpace.mkCorner(bindhome, actions); + actions(bindhome.h("d.2", 1)); + } else { + bindhome = bindhome.s("d.1"); + } + // View metrics + ZZCell metr = AwtSystemList.findText(AwtUtil.d_awtool, 1, "Metrics"); + if(metr == null) { + Dimension RV = new Dimension(400, 400); + Dimension VV = new Dimension(1000, 1000); + // create 'metrics collection' + metr = AwtSystemList.N(AwtUtil.d_awtool); + metr.setText("Metrics"); + ZZCell mnew, metrList; + + mnew = metrList = metr.N("d.1"); + + M = new AwtMetricsNormal(mnew, RV, VV, 0.0,0.0); + M.cellRepr(); + + mnew = mnew.N("d.2"); + M = new AwtMetricsFC(mnew, RV, VV, 0.0, 0.0); + M.cellRepr(); + + mnew = mnew.N("d.2"); + M = new AwtMetricsFC2(mnew, RV, VV, 0.0, 0.0); + M.cellRepr(); + + // make circle + mnew.connect("d.2", 1, metrList); + AwtUtil.setCursor(c_metrics, metrList, AwtSystemList); + + + } else { + ZZCell currentMetrics = + AwtUtil.getCursoredCell(c_metrics, AwtSystemList); + if(currentMetrics == null) { + currentMetrics = metr.s("d.1"); + AwtUtil.setCursor(c_metrics, currentMetrics, AwtSystemList); + } + M = (AwtMetrics)AwtUtil.readZObClone(currentMetrics); + M.setCell(currentMetrics); + } + + // searching for active category ... + ZZCell ac = AwtUtil.getCursoredCell(c_activeCategory, AwtSystemList); + if(ac == null) { + if(AwtSystemList.getRankLength(AwtUtil.d_categories)>1) { + ac = AwtSystemList.s(AwtUtil.d_categories); + } else { + ac = AwtSystemList.N(AwtUtil.d_categories); + ac.setText("* SCRATCH *"); + } + AwtUtil.setCursor(c_activeCategory, ac, AwtSystemList); + } + + ZZCell v = ZZDefaultSpace.newToplevelView(rc.getSpace(), + "awtool", 0, 0, M.RealView[0], M.RealView[1], + rl, null, + null, null, + null, + new Color(0xFFFFB1)); + + // Then, set bindings + ZZCell bcurs = v.getOrNewCell("d.bind", 1); + ZZCursorReal.set(bcurs, bindhome); + ZZCursorReal.setColor(bcurs, Color.black); + + + ZZCell awtc = v.h("d.2", 1).N("d.2"); + awtc.setText("AwtSystemList"); + ZZCursorReal.set(awtc, AwtSystemList); + // init shared cursors + ZZCell scursors = v.h("d.2",1).N("d.2"); + scursors.setText("SharedCursors"); + scursors.N("d.1"); + + return; + } + + AwtSystemList = AwtUtil.getAwtSysList(view.getViewcell()); + if(AwtSystemList == null && !id.equals("TESTWIN")) { + throw new ZZError("Awtool: AwtSystemList missing!!"); + } + + M = AwtUtil.getAwtMetrics(AwtSystemList); + + if(id.equals("StartDrag")) { + if(note != null) { + dragNote = note; + noteRVCoord = M.mapToRealView(note.getX(), note.getY()); + dragOffs.x = noteRVCoord.x - pt.x; + dragOffs.y = noteRVCoord.y - pt.y; + } + } else + + if(id.equals("StopDrag") && dragNote != null) { + noteVVCoord = M.mapToVirtualView(pt.x + dragOffs.x, pt.y + dragOffs.y); + dragNote.setCoord(noteVVCoord[0], noteVVCoord[1]); + dragNote.cellRepr(); + dragOffs.x = 0; dragOffs.y = 0; + dragNote = null; + } else + + if(id.equals("Dragged") && dragNote != null) { + noteVVCoord = M.mapToVirtualView(pt.x + dragOffs.x, pt.y + dragOffs.y); + dragNote.setCoord(noteVVCoord[0], noteVVCoord[1]); + ZZUpdateManager.chg(); + //dragNote.cellRepr(); + } else + + + if(id.equals("StartResize")) { + if(note != null) { + dragNote = note; + noteRVCoord = M.mapToRealView(note.getX(), note.getY()); + dragOffs.x = noteRVCoord.x - pt.x; + dragOffs.y = noteRVCoord.y - pt.y; + } + } else + + if(id.equals("StopResize") && dragNote != null) { + noteVVCoord = M.mapToVirtualView(pt.x + dragOffs.x, pt.y + dragOffs.y); + dragNote.setCoord(noteVVCoord[0], noteVVCoord[1]); + dragNote.cellRepr(); + dragOffs.x = 0; dragOffs.y = 0; + dragNote = null; + } else + + if(id.equals("Resizing") && dragNote != null) { + } else + + if(id.equals("StartCreatingNote")) { + dragCoord = pt; + // this is chanced to 'true' when dragging occurs + creatingNote = false; + } else + + if(id.equals("CreatingNote")) { + creatingNote = true; + } else + + if(id.equals("StopCreatingNote") && creatingNote) { + ZZCell newNoteCell; + AwtNote newNote; + int cx = (dragCoord.x+pt.x)>>1; + int cy = (dragCoord.y+pt.y)>>1; + double[] ndim, nvcenter = M.mapToVirtualView(cx, cy); + Dimension nd = new Dimension(Math.abs(dragCoord.x-pt.x), Math.abs(dragCoord.y-pt.y)); + ndim = M.getVirtualDimension(cx, cy, nd); + + ZZCell ac = AwtUtil.getCursoredCell(c_activeCategory, vc); + + ZZCell noteCell = + ac.h(AwtUtil.d_to).N(AwtUtil.d_to).N(AwtUtil.d_from); + + AwtUtil.createNewNote(noteCell, nvcenter, ndim); + // attach new note also to 'notes' dimension along + // active category cell. + ac.h(AwtUtil.d_notes, 1).connect(AwtUtil.d_notes, 1, noteCell); + dragCoord.x = 0; + dragCoord.y = 0; + creatingNote = false; + + } else + + if(id.equals("SetCursor1") && nc != null) { + ZZCell red = AwtUtil.getCursoredCell(c_cursor1, vc); + if(red.equals(nc)) return; + AwtUtil.setCursor(c_cursor2, red, vc); + AwtUtil.setCursor(c_cursor1, nc, vc); + if(red!=null) { + red.excise("d.nile-wins"); + nc.connect("d.nile-wins", 1, red); + nc.connect("d.nile-wins", -1, red); + } + } else + + if(id.equals("SetCursor2") && nc != null) { + ZZCell gray = AwtUtil.getCursoredCell(c_cursor2, vc); + if(gray.equals(nc)) return; + AwtUtil.setCursor(c_cursor1, gray, vc); + AwtUtil.setCursor(c_cursor2, nc, vc); + if(gray!=null) { + gray.excise("d.nile-wins"); + nc.connect("d.nile-wins", 1, gray); + nc.connect("d.nile-wins", -1, gray); + } + + } else + + if(id.equals("NewLink")) { + ZZCell c1, c2; + c1 = AwtUtil.getCursoredCell(c_cursor1, vc); + c2 = AwtUtil.getCursoredCell(c_cursor2, vc); + if(c1 != null && c2 != null && c1 != c2) { + AwtUtil.createNewLink(c1, c2); + } + } else + + if(id.equals("ChangeMetrics")) { + // save current metrics (focus, origo, etc.) + M.cellRepr(); + ZZCell mc = AwtUtil.getCursoredCell(c_metrics, vc); + mc = mc.s("d.2"); + AwtUtil.setCursor(c_metrics, mc, vc); + M = (AwtMetrics)AwtUtil.readZObClone(mc); + M.setCell(mc); + ZZUpdateManager.chg(); + } else + + if(id.equals("ResetOrigo")) { + //pa("ORIGO RESET!"); + M.setOrigo(0.0, 0.0); + ZZUpdateManager.chg(); + } else + + if(id.equals("GridOnOff")) { + //pa("GRID ON/OFF!"); + boolean gon = M.GridOn; + M.GridOn = gon ? false : true; + if(M.GridOn != gon) { + M.cellRepr(); + } + ZZUpdateManager.chg(); + } else + + if(id.equals("FocusOrigoAndSelect")) { + long elapsedTime = Long.MAX_VALUE; + long cur = System.currentTimeMillis(); + double[] vf1, vf2; + + vf1 = M.mapToVirtualView(pt.x, pt.y); + M.setFocusOrigo(pt.x, pt.y, nc); + vf2 = M.mapToVirtualView(pt.x, pt.y); + M.moveOrigo(vf1[0]-vf2[0], vf1[1]-vf2[1]); + M.cellRepr(); + + if(focusChangedLastTime > 0) { + elapsedTime = cur - focusChangedLastTime; + focusChangedLastTime = -1; + } else { + focusChangedLastTime = cur; + } + + pa("ELAPSED_TIME: "+elapsedTime); + + if(elapsedTime < 1500) { + // 'doubleclick'-focus should change also origo + // this does not work reasonably + // forceOrigoChange = true; + forceOrigoChange = false; + } else { ZZUpdateManager.chg(); } + } + + + if(id.equals("ChangeOrigo") || forceOrigoChange) { + double[] vvp = M.mapToVirtualView(pt.x, pt.y); + // new origo is wanted to be in the center of realview + double[] realOrigo = M.mapToVirtualView(M.RealView[0]>>1, + M.RealView[1]>>1); + M.moveOrigo(vvp[0]-realOrigo[0], vvp[1]-realOrigo[1]); + M.cellRepr(); + ZZUpdateManager.chg(); + } + } + + public ZOb newZOb(String id) { + if(id.equals("View1")) + return new AwtView1(); + else + return null; + } + }; + + // This is really hacky part... + static ZZCell curAct; + static void a(String key, String act) { a(key, act, null); } + static void a(String key, String act, ZZCell next) { + curAct = curAct.N("d.2", 1); + curAct.setText(key); + ZZCell n = curAct.N("d.1", 1); + n.setText("Awtool." + act); + if(next != null) + next.insert("d.3", 1, n); + } + + static void actions(ZZCell start) { + ZZCell awtact = start; awtact.setText("Awtool mode"); + ZZCell nchar = awtact.N("d.1",1); nchar.setText("Nile char"); + ZZCell nword = nchar.N("d.1", 1); nword.setText("Nile word"); + ZZCell nsent = nword.N("d.1", 1); nsent.setText("Nile sent"); + ZZCell npara = nsent.N("d.1", 1); npara.setText("Nile para"); + + ZZCell ncommon = npara.N("d.1", 1); ncommon.setText("Nile common"); + + + + curAct = nword; + // Annoying - these should be structurally + // describable!!! + a("MouseClicked1", "MouseSetCursor 0 WORD"); + a("Backspace", "BackSpace 0 WORD"); + a("Delete", "Delete 0 WORD"); + a("Alt-Backspace", "Delete 0 WORD"); + a("Ctrl-P", "Tunnel - WORD"); // P for pull + a("Ctrl-T", "Transcopy - WORD"); + a("Left", "Cursor - WORD"); + a("Right", "Cursor + WORD"); + a("Shift-Left", "AdjLeft - WORD"); + a("Shift-Right", "AdjRight + WORD"); + a("Ctrl-Left", "AdjRight - WORD"); + a("Ctrl-Right", "AdjLeft + WORD"); + a("Alt-Left", "Hop - WORD"); + a("Alt-Right", "Hop + WORD"); + a("Enter", "BreakParagraph 0 WORD"); + + a("Up", "Cursor - SENT"); + a("Down", "Cursor + SENT"); + a("Alt-Up", "Hop - SENT"); + a("Alt-Down", "Hop + SENT"); + + a("INSERT", "Insert", nchar); + a("Tab", "Mode 0 SENT", nsent); + // awtool specific + a("Alt-N", "NileOnOff", awtact); + + curAct = nsent; + a("MouseClicked1", "MouseSetCursor 0 SENT"); + a("Backspace", "BackSpace 0 SENT"); + a("Delete", "Delete 0 SENT"); + a("Alt-Backspace", "Delete 0 SENT"); + a("Ctrl-P", "Tunnel - SENT"); // P for push + a("Ctrl-T", "Transcopy - SENT"); + a("Left", "Cursor - SENT"); + a("Right", "Cursor + SENT"); + a("Shift-Left", "AdjLeft - SENT"); + a("Shift-Right", "AdjRight + SENT"); + a("Ctrl-Left", "AdjRight - SENT"); + a("Ctrl-Right", "AdjLeft + SENT"); + a("Alt-Left", "Hop - SENT"); + a("Alt-Right", "Hop + SENT"); + a("Enter", "BreakParagraph 0 SENT"); + + a("Up", "Cursor - PARA"); + a("Down", "Cursor + PARA"); + a("Alt-Up", "Hop - PARA"); + a("Alt-Down", "Hop + PARA"); + + a("INSERT", "Insert", nchar); + a("Tab", "Mode 0 CHAR", nchar); + // awtool specific + a("Alt-N", "NileOnOff", awtact); + +/* + curAct = npara; + a("MouseClicked1", "MouseSetCursor 0 PARA"); + a("Backspace", "BackSpace 0 PARA"); + a("Delete", "Delete 0 PARA"); + a("Alt-Backspace", "Delete 0 PARA"); + a("Left", "Cursor - PARA"); + a("Right", "Cursor + PARA"); + a("Shift-Left", "AdjLeft - PARA"); + a("Shift-Right", "AdjRight + PARA"); + a("Ctrl-Left", "AdjRight - PARA"); + a("Ctrl-Right", "AdjLeft + PARA"); + a("Alt-Left", "Hop - PARA"); + a("Alt-Right", "Hop + PARA"); + + a("INSERT", "Insert"); + a("Tab", "Mode 0 CHAR", nchar); + */ + + curAct = nchar; + a("MouseClicked1", "MouseSetCursor 0 CHAR"); + a("Left", "Cursor - CHAR"); + a("Right", "Cursor + CHAR"); + a("Backspace", "BackSpace 0 CHAR"); + a("Delete", "Delete 0 CHAR"); + a("Alt-Backspace", "Delete 0 CHAR"); + a("INSERT", "Insert"); + a("Tab", "Mode 0 WORD", nword); + a("Enter", "BreakParagraph 0 CHAR"); + + a("Ctrl-C", "PUICopy 0 CHAR"); + + a("Up", "Cursor - WORD"); + a("Down", "Cursor + WORD"); + // awtool specific + a("Alt-N", "NileOnOff", awtact); + + // awtool acts + curAct = awtact; + a("MouseStartDrag", "StartDrag"); + a("MouseDragged1", "Dragged"); + a("MouseReleased1", "StopDrag"); + a("Shift-MouseStartDrag", "StartCreatingNote"); + a("Shift-MouseDragged1", "CreatingNote"); + a("Shift-MouseReleased1", "StopCreatingNote"); + a("Shift-MouseClicked3", "ChangeOrigo"); + a("MouseClicked3", "FocusOrigoAndSelect"); + a("Shift-MouseClicked1", "SetCursor2"); + a("MouseClicked1", "SetCursor1"); + a("l", "NewLink"); + a("m", "ChangeMetrics"); + a("g", "GridOnOff"); + a("r", "ResetOrigo"); + a("Alt-N", "NileOnOff", nchar); + + } +} diff --git a/Modules/awtool/Awtool.zob b/Modules/awtool/Awtool.zob new file mode 100644 index 0000000..a6dca86 --- /dev/null +++ b/Modules/awtool/Awtool.zob @@ -0,0 +1,955 @@ +/* +Awtool.zob + * + * Copyright (c) 2000-2001 Ted Nelson and Tuomas Lukka + * Copyright (c) 2000-2001 Kimmo Wideroos + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Kimmo Wideroos (inspired by Benjamin Fallenstein's notemap module) + */ + +/** Awt = A(ssociative) writing tool -demo +*/ + +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.awt.*; + +public abstract class Awtool implements FlobView, FlobSet.DragCursor, ZOb { +public static final String rcsid = ""; + public static boolean dbg = true; + static void p(String s) { if(dbg) System.out.println(s); } + static void pa(String s) { System.out.println(s); } + + STRUCTPARAMS { + /** View dimension (not in use now...) */ + int viewWidth + = 600; + int viewHeight + = 600; + int viewX + = 100; + int viewY + = 100; + } + + + + static boolean NileOn = false; + static AwtNote dragNote; + static Point dragOffs = new Point(0, 0); + static Point dragCoord = new Point(0, 0); + + static boolean creatingNote = false; + + static long focusChangedLastTime = -1; // millisecs + + static AwtCursor c_cursor1 = new AwtCursor(Color.red, true); + static AwtCursor c_cursor2 = new AwtCursor(Color.gray, true); + static AwtCursor c_activeCategory = new AwtCursor(Color.orange, false); + static AwtCursor c_metrics = new AwtCursor(Color.white, false); + + public boolean accept(Object o) { + if(!(o instanceof ZZCell)) return false; + return true; + } + + static public Hashtable categ; + static public Hashtable notes; + static public Hashtable validNotes; + + static class NotemapBM extends BooleanMesh { + public NotemapBM(ZZCell bStructure) { super(bStructure); } + public boolean testBelonging(ZZCell nhc, ZZCell category) { + for(ZZCell l=category.h(AwtUtil.d_clone).s(AwtUtil.d_to); l != null; l=l.s(AwtUtil.d_to) ) + if(l.h(AwtUtil.d_from,1).h(AwtUtil.d_clone).equals(nhc)) return true; + return false; + } + } + + + + /* categories are a kind of layers containing notes (i.e. (text) elements). + * this class provides with logical operations for categories (AND, OR). + * the resulting categories should be able to store permanently in zzspace. + * heavily under construction ... + */ + public class Categories extends ZObCellRepr { + private Hashtable AllNoteHeadCells = null; + private Hashtable AllNotes = null; + private Hashtable AllValidNotes = null; + private Hashtable ValidNotes = null; + private Hashtable K = new Hashtable(); + private NotemapBM bm; + private String categoryName = "SCRATCH"; + + public boolean isCategory(ZZCell c) { + return (c.h(AwtUtil.d_clone).getRankLength(AwtUtil.d_categories)>1); + } + + public Categories(ZZCell bStructure) { + setCell(bStructure); + _findCategories(bStructure); + bm = new NotemapBM(bStructure); + + AllNotes = new Hashtable(); + AllNoteHeadCells = new Hashtable(); + AllValidNotes = new Hashtable(); + ValidNotes = new Hashtable(); + + ZZCell note, chc, nhc; + for(Enumeration e = K.keys(); e.hasMoreElements(); ) { + // chc = category headcell + chc = ((ZZCell)e.nextElement()); + for(ZZCell linkc = chc.s(AwtUtil.d_to); linkc != null; + linkc = linkc.s(AwtUtil.d_to) ) + { + note = linkc.h(AwtUtil.d_from, 1); + nhc = note.h(AwtUtil.d_clone); + AllNotes.put(note, nhc); + if(!AllNoteHeadCells.containsKey(nhc)) + // AllNoteHeadCells must keep track of all note headcells + AllNoteHeadCells.put(nhc, note); + if(AllValidNotes.containsKey(nhc)) + // AllValidNotes store valid headcells AND clones + // all together + AllValidNotes.put(note, nhc); + else if(bm.evaluate(nhc)) AllValidNotes.put(note, nhc); + if(AllValidNotes.containsKey(note)) { + // If there exist 2 or more valid note clones, ValidNotes + // store note headcell (otherwise note clone). + if(ValidNotes.containsKey(nhc)) ValidNotes.put(nhc, nhc); + else ValidNotes.put(nhc, note); + } + } + } + } + + private void _findCategories(ZZCell bStructure) { + if(isCategory(bStructure)) { + K.put(bStructure.h(AwtUtil.d_clone), bStructure); + return; + } else + { + _findCategories(bStructure.s("d.1")); + _findCategories(bStructure.s("d.2")); + } + } + + public ZZCell[] getNoteCells() { + ZZCell[] n = new ZZCell[AllNotes.size()]; + Enumeration e = AllNotes.elements(); + int i = 0; + while (e.hasMoreElements()) { + n[i] = (ZZCell)e.nextElement(); i++; + } + return n; + } + public AwtNote[] getNotes() { + AwtNote[] n = new AwtNote[AllNotes.size()]; + Enumeration e = AllNotes.elements(); + ZZCell ncell; + int i = 0; + while (e.hasMoreElements()) { + ncell = (ZZCell)e.nextElement(); + n[i] = (AwtNote)AwtUtil.readZObClone(ncell); + n[i].setCell(ncell); + i++; + } + return n; + } + + public ZZCell[] getAllValidNoteCells() { + ZZCell[] ln = new ZZCell[AllValidNotes.size()]; + int i = 0; + for(Enumeration e=AllValidNotes.keys(); e.hasMoreElements();) { + ln[i] = (ZZCell)e.nextElement(); + i++; + } + return ln; + } + + public AwtNote[] getAllValidNotes() { + AwtNote[] ln = new AwtNote[AllValidNotes.size()]; + ZZCell ncell; + int i = 0; + for(Enumeration e=AllValidNotes.keys(); e.hasMoreElements();) { + ncell = (ZZCell)e.nextElement(); + ln[i] = (AwtNote)AwtUtil.readZObClone(ncell); + ln[i].setCell(ncell); + i++; + } + return ln; + } + + public ZZCell[] getValidNoteCells() { + ZZCell[] ln = new ZZCell[ValidNotes.size()]; + int i = 0; + for(Enumeration e=ValidNotes.elements(); e.hasMoreElements(); ) { + ln[i] = (ZZCell)e.nextElement(); + i++; + } + return ln; + } + + public AwtNote[] getValidNotes() { + AwtNote[] ln = new AwtNote[ValidNotes.size()]; + ZZCell ncell; + int i = 0; + for(Enumeration e=ValidNotes.elements(); e.hasMoreElements(); ) { + ncell = (ZZCell)e.nextElement(); + ln[i] = (AwtNote)AwtUtil.readZObClone(ncell); + ln[i].setCell(ncell); + i++; + } + return ln; + } + + public ZZCell[] getK() { + ZZCell[] cat = new ZZCell[K.size()]; + Enumeration e = K.elements(); + int i = 0; + while (e.hasMoreElements()) + cat[i] = (ZZCell)e.nextElement(); i++; + return cat; + } + + public ZZCell[] getAllValidLinkCells(boolean internal, boolean external) { + return _getvalidlinks(internal, external, AllValidNotes.keys()); + } + + public AwtLink[] getAllValidLinks(boolean internal, boolean external) + { + ZZCell[] linkcells = _getvalidlinks(internal, external, AllValidNotes.keys()); + AwtLink[] links = new AwtLink[linkcells.length]; + for(int i = 0; i=0; i--) { + note = validNotes[i]; + catlink.setX(note.getX()); catlink.setY(note.getY()); + catlink.cellRepr(catCell, false); + // note's centralcell is a clone of its (ZOb's) original + // central cell; that's why '...im2), true);' + note.cellRepr(catCell.getOrNewCell(AwtUtil.d_from), true); + catCell = catCell.getOrNewCell(AwtUtil.d_to); + } + return ""; + } + } + + /** return note cell, if possible + */ + static ZZCell getNoteCellOrCursor(Object ob) { + ZZCell c = null; + if(ob instanceof ZZCursor) c = ((ZZCursor)ob).get(); + else if(ob instanceof ZZCell) c = (ZZCell)ob; + else return null; + ZZCell link = c.s(AwtUtil.d_from, -1); + if(link == null) return null; + if(link.s(AwtUtil.d_to, -1) == null) return null; + return c; + } + + static public void nile_action(String id, ZZCell vc1, ZZCell vc2, String key, + ZZCursor cur) { + + boolean split = false; + + ZZCell viewCell = vc1; + ZZCell otherCell = vc2; + + p("Nile action: id: '"+id+"' key: '"+key); + + StringTokenizer st = new StringTokenizer(id); + String[] toks = new String[st.countTokens()]; + for(int i=0; i 1) { + if(toks[1].equals("+")) dir = 1; + else if(toks[1].equals("-")) dir = -1; + + if(toks.length > 2) { + if(toks[2].equals("CHAR")) + unit = new Nile2Unit.Char(); + else if(toks[2].equals("WORD")) + unit = new Nile2Unit.Word(); + else if(toks[2].equals("SENT")) + unit = new Nile2Unit.Sentence(); + else if(toks[2].equals("PARA")) + unit = new Nile2Unit.Paragraph(); + } + } + + id = toks[0]; + + if(id.equals("Cursor")) { + p("Cursor: "+dir); + Nile2Ops.moveCursor(unit, viewCell, dir); + ZZUpdateManager.setFast(null); + } + else if(id.equals("AdjLeft")) { + Nile2Ops.adjust(unit, viewCell, -1, dir); + ZZUpdateManager.setFast(null); + } + else if(id.equals("AdjRight")) { + Nile2Ops.adjust(unit, viewCell, 1, dir); + ZZUpdateManager.setFast(null); + } + else if(id.equals("Hop")) { + Nile2Ops.hop(unit, viewCell, dir); + } + else if(id.equals("Mode")) { + Nile2Ops.setCursor(unit, viewCell, null); + if(split) + Nile2Ops.setCursor(unit, otherCell, null); + } + else if(id.equals("Insert")) { + Nile2Ops.insert(viewCell, key); + + // Set the selection of other half to char mode, too + if(split) + Nile2Ops.setCursor(new Nile2Unit.Char(), otherCell, null); + } + else if(id.equals("BackSpace")) { + Nile2Ops.backspace(unit, viewCell); + } + else if(id.equals("Delete")) { + Nile2Ops.del(unit, viewCell); + } + else if(id.equals("BreakParagraph")) { + Nile2Ops.breakParagraph(unit, viewCell); + } + else if(id.equals("Tunnel")) { + if(otherCell != null) { + Nile2Ops.tunnel(unit, otherCell, viewCell, dir, false); + } + } + else if(id.equals("Transcopy")) { + if(otherCell != null) { + Nile2Ops.tunnel(unit, otherCell, viewCell, dir, true); + } + } + else if(id.equals("PUICopy")) { + ZZCell c = ZZCursorReal.get(viewCell); + String s = Nile2Ops.stringify(c); + ZZUtil.puiCopy(s); + } + /* + else if(id.equals("TraverseTranscopies")) { + Nile2Ops.traverseTranscopies(viewCell, dir); + } + */ + + //Object ob = null; + //if(pt != null) + // ob = xi.getObjectAt(pt.x, pt.y); + + if(id.equals("MouseSetCursor") && cur!=null) { + p("Setting cursor from mouse! Unit: "+unit); + if(cur.get().h("d.nile").equals(viewCell)) { + Nile2Ops.setCursor(unit, viewCell, cur); + } else + if(cur.get().h("d.nile").equals(otherCell)) { + Nile2Ops.setCursor(unit, otherCell, cur); + } + } + } + + + abstract public void raster(FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed); + + static public ZZModule module = new ZZModule() { + public void action(String id, + ZZCell code, + ZZCell target, + ZZView view, ZZView cview, String key, Point pt, ZZScene xi) { + + ZZUpdateManager.setFast(view); + Object ob = null; + AwtNote note = null; + AwtMetrics M; + ZZCell nc; + Point noteRVCoord = null; + double[] noteVVCoord = null; + double deltaX, deltaY; + + if(pt != null && xi != null) ob = xi.getObjectAt(pt.x, pt.y); + + nc = getNoteCellOrCursor(ob); + + if(nc != null) { + note = (AwtNote)AwtUtil.readZObClone(nc); + note.setCell(nc); + } + + boolean forceOrigoChange = false; + ZZCell AwtSystemList; + ZZCell vc = view.getViewcell(); + + pa("NOTECELL: "+nc); + + pa("Note action! '"+id+"' key: "+key); + + // is nile mode on? + boolean nileOn = false; + ZZCell curb = vc.h("d.bind", 1, true); + if(curb!=null) { + String mode = ZZCursorReal.get(curb).getText(); + if(mode.indexOf("Nile") >= 0) + nileOn = true; + } + pa("OBJECT: "+ob); + boolean isC = false; + if(ob instanceof ZZCursor) isC = true; + pa("IS CURSOR?: "+isC); + // if we have object which is not cursor, then nile action is impossible + if(nileOn && !(!(ob instanceof ZZCursor) && (ob != null)) ) { + ZZCell nvc1 = AwtUtil.getCursoredCell(c_cursor1, vc); + ZZCell nvc2 = AwtUtil.getCursoredCell(c_cursor2, vc); + if(nvc1==null) return; + + if(nvc1.s("d.cursor-cargo", -1)==null) { + ZZCursorReal.set(nvc1, nvc1); + ZZCursorReal.setOffs(nvc1, 0); + } + if(nvc2!=null) + if(nvc2.s("d.cursor-cargo", -1)==null) { + ZZCursorReal.set(nvc2, nvc2); + ZZCursorReal.setOffs(nvc2, 0); + } + + nile_action(id, nvc1, nvc2, key, (ZZCursor)ob); + //Nile1.module.action(id,code,target,nview,cview,key,pt,xi); + return; + } + + if(id.equals("TESTWIN")) { + AwtSystemList = target; + + // set awt dims + AwtUtil.addDims(ZZDefaultSpace.findDefaultDimlist(code.getHomeCell())); + + // Cursors + ZZCell curs = AwtSystemList.findText(AwtUtil.d_awtool, 1, "Cursors"); + if(curs == null) { + ZZCell nCurs1, nCurs2, cat1; + ZZCell cursors = AwtSystemList.N(AwtUtil.d_awtool); + cursors.setText("Cursors"); + cursors.N("d.1"); + } + + // View + ZZCell rastname, rl, rc = AwtSystemList.findText(AwtUtil.d_awtool, 1, "View"); + if(rc == null) { + rc = AwtSystemList.N(AwtUtil.d_awtool); + rc.setText("View"); + rl = rc.N("d.1"); + rl.connect("d.2", 1, rl); + rl.setText("Awtool"); + rastname = rl.N("d.1"); + rastname.setText("Awtool.View1"); + } else { + rl = rc.s("d.1"); + rastname = rl.s("d.1"); + } + + + // Bindings + ZZCell bindhome = AwtSystemList.findText(AwtUtil.d_awtool, 1, "Bind"); + if(bindhome == null) { + bindhome = AwtSystemList.N(AwtUtil.d_awtool); + bindhome.setText("Bind"); + bindhome = bindhome.N("d.1", 1); + + //ZZDefaultSpace.mkCorner(bindhome, actions); + actions(bindhome.h("d.2", 1)); + } else { + bindhome = bindhome.s("d.1"); + } + // View metrics + ZZCell metr = AwtSystemList.findText(AwtUtil.d_awtool, 1, "Metrics"); + if(metr == null) { + Dimension RV = new Dimension(400, 400); + Dimension VV = new Dimension(1000, 1000); + // create 'metrics collection' + metr = AwtSystemList.N(AwtUtil.d_awtool); + metr.setText("Metrics"); + ZZCell mnew, metrList; + + mnew = metrList = metr.N("d.1"); + + M = new AwtMetricsNormal(mnew, RV, VV, 0.0,0.0); + M.cellRepr(); + + mnew = mnew.N("d.2"); + M = new AwtMetricsFC(mnew, RV, VV, 0.0, 0.0); + M.cellRepr(); + + mnew = mnew.N("d.2"); + M = new AwtMetricsFC2(mnew, RV, VV, 0.0, 0.0); + M.cellRepr(); + + // make circle + mnew.connect("d.2", 1, metrList); + AwtUtil.setCursor(c_metrics, metrList, AwtSystemList); + + + } else { + ZZCell currentMetrics = + AwtUtil.getCursoredCell(c_metrics, AwtSystemList); + if(currentMetrics == null) { + currentMetrics = metr.s("d.1"); + AwtUtil.setCursor(c_metrics, currentMetrics, AwtSystemList); + } + M = (AwtMetrics)AwtUtil.readZObClone(currentMetrics); + M.setCell(currentMetrics); + } + + // searching for active category ... + ZZCell ac = AwtUtil.getCursoredCell(c_activeCategory, AwtSystemList); + if(ac == null) { + if(AwtSystemList.getRankLength(AwtUtil.d_categories)>1) { + ac = AwtSystemList.s(AwtUtil.d_categories); + } else { + ac = AwtSystemList.N(AwtUtil.d_categories); + ac.setText("* SCRATCH *"); + } + AwtUtil.setCursor(c_activeCategory, ac, AwtSystemList); + } + + ZZCell v = ZZDefaultSpace.newToplevelView(rc.getSpace(), + "awtool", 0, 0, M.RealView[0], M.RealView[1], + rl, null, + null, null, + null, + new Color(0xFFFFB1)); + + // Then, set bindings + ZZCell bcurs = v.getOrNewCell("d.bind", 1); + ZZCursorReal.set(bcurs, bindhome); + ZZCursorReal.setColor(bcurs, Color.black); + + + ZZCell awtc = v.h("d.2", 1).N("d.2"); + awtc.setText("AwtSystemList"); + ZZCursorReal.set(awtc, AwtSystemList); + // init shared cursors + ZZCell scursors = v.h("d.2",1).N("d.2"); + scursors.setText("SharedCursors"); + scursors.N("d.1"); + + return; + } + + AwtSystemList = AwtUtil.getAwtSysList(view.getViewcell()); + if(AwtSystemList == null && !id.equals("TESTWIN")) { + throw new ZZError("Awtool: AwtSystemList missing!!"); + } + + M = AwtUtil.getAwtMetrics(AwtSystemList); + + if(id.equals("StartDrag")) { + if(note != null) { + dragNote = note; + noteRVCoord = M.mapToRealView(note.getX(), note.getY()); + dragOffs.x = noteRVCoord.x - pt.x; + dragOffs.y = noteRVCoord.y - pt.y; + } + } else + + if(id.equals("StopDrag") && dragNote != null) { + noteVVCoord = M.mapToVirtualView(pt.x + dragOffs.x, pt.y + dragOffs.y); + dragNote.setCoord(noteVVCoord[0], noteVVCoord[1]); + dragNote.cellRepr(); + dragOffs.x = 0; dragOffs.y = 0; + dragNote = null; + } else + + if(id.equals("Dragged") && dragNote != null) { + noteVVCoord = M.mapToVirtualView(pt.x + dragOffs.x, pt.y + dragOffs.y); + dragNote.setCoord(noteVVCoord[0], noteVVCoord[1]); + ZZUpdateManager.chg(); + //dragNote.cellRepr(); + } else + + + if(id.equals("StartResize")) { + if(note != null) { + dragNote = note; + noteRVCoord = M.mapToRealView(note.getX(), note.getY()); + dragOffs.x = noteRVCoord.x - pt.x; + dragOffs.y = noteRVCoord.y - pt.y; + } + } else + + if(id.equals("StopResize") && dragNote != null) { + noteVVCoord = M.mapToVirtualView(pt.x + dragOffs.x, pt.y + dragOffs.y); + dragNote.setCoord(noteVVCoord[0], noteVVCoord[1]); + dragNote.cellRepr(); + dragOffs.x = 0; dragOffs.y = 0; + dragNote = null; + } else + + if(id.equals("Resizing") && dragNote != null) { + } else + + if(id.equals("StartCreatingNote")) { + dragCoord = pt; + // this is chanced to 'true' when dragging occurs + creatingNote = false; + } else + + if(id.equals("CreatingNote")) { + creatingNote = true; + } else + + if(id.equals("StopCreatingNote") && creatingNote) { + ZZCell newNoteCell; + AwtNote newNote; + int cx = (dragCoord.x+pt.x)>>1; + int cy = (dragCoord.y+pt.y)>>1; + double[] ndim, nvcenter = M.mapToVirtualView(cx, cy); + Dimension nd = new Dimension(Math.abs(dragCoord.x-pt.x), Math.abs(dragCoord.y-pt.y)); + ndim = M.getVirtualDimension(cx, cy, nd); + + ZZCell ac = AwtUtil.getCursoredCell(c_activeCategory, vc); + + ZZCell noteCell = + ac.h(AwtUtil.d_to).N(AwtUtil.d_to).N(AwtUtil.d_from); + + AwtUtil.createNewNote(noteCell, nvcenter, ndim); + // attach new note also to 'notes' dimension along + // active category cell. + ac.h(AwtUtil.d_notes, 1).connect(AwtUtil.d_notes, 1, noteCell); + dragCoord.x = 0; + dragCoord.y = 0; + creatingNote = false; + + } else + + if(id.equals("SetCursor1") && nc != null) { + ZZCell red = AwtUtil.getCursoredCell(c_cursor1, vc); + if(red.equals(nc)) return; + AwtUtil.setCursor(c_cursor2, red, vc); + AwtUtil.setCursor(c_cursor1, nc, vc); + if(red!=null) { + red.excise("d.nile-wins"); + nc.connect("d.nile-wins", 1, red); + nc.connect("d.nile-wins", -1, red); + } + } else + + if(id.equals("SetCursor2") && nc != null) { + ZZCell gray = AwtUtil.getCursoredCell(c_cursor2, vc); + if(gray.equals(nc)) return; + AwtUtil.setCursor(c_cursor1, gray, vc); + AwtUtil.setCursor(c_cursor2, nc, vc); + if(gray!=null) { + gray.excise("d.nile-wins"); + nc.connect("d.nile-wins", 1, gray); + nc.connect("d.nile-wins", -1, gray); + } + + } else + + if(id.equals("NewLink")) { + ZZCell c1, c2; + c1 = AwtUtil.getCursoredCell(c_cursor1, vc); + c2 = AwtUtil.getCursoredCell(c_cursor2, vc); + if(c1 != null && c2 != null && c1 != c2) { + AwtUtil.createNewLink(c1, c2); + } + } else + + if(id.equals("ChangeMetrics")) { + // save current metrics (focus, origo, etc.) + M.cellRepr(); + ZZCell mc = AwtUtil.getCursoredCell(c_metrics, vc); + mc = mc.s("d.2"); + AwtUtil.setCursor(c_metrics, mc, vc); + M = (AwtMetrics)AwtUtil.readZObClone(mc); + M.setCell(mc); + ZZUpdateManager.chg(); + } else + + if(id.equals("ResetOrigo")) { + //pa("ORIGO RESET!"); + M.setOrigo(0.0, 0.0); + ZZUpdateManager.chg(); + } else + + if(id.equals("GridOnOff")) { + //pa("GRID ON/OFF!"); + boolean gon = M.GridOn; + M.GridOn = gon ? false : true; + if(M.GridOn != gon) { + M.cellRepr(); + } + ZZUpdateManager.chg(); + } else + + if(id.equals("FocusOrigoAndSelect")) { + long elapsedTime = Long.MAX_VALUE; + long cur = System.currentTimeMillis(); + double[] vf1, vf2; + + vf1 = M.mapToVirtualView(pt.x, pt.y); + M.setFocusOrigo(pt.x, pt.y, nc); + vf2 = M.mapToVirtualView(pt.x, pt.y); + M.moveOrigo(vf1[0]-vf2[0], vf1[1]-vf2[1]); + M.cellRepr(); + + if(focusChangedLastTime > 0) { + elapsedTime = cur - focusChangedLastTime; + focusChangedLastTime = -1; + } else { + focusChangedLastTime = cur; + } + + pa("ELAPSED_TIME: "+elapsedTime); + + if(elapsedTime < 1500) { + // 'doubleclick'-focus should change also origo + // this does not work reasonably + // forceOrigoChange = true; + forceOrigoChange = false; + } else { ZZUpdateManager.chg(); } + } + + + if(id.equals("ChangeOrigo") || forceOrigoChange) { + double[] vvp = M.mapToVirtualView(pt.x, pt.y); + // new origo is wanted to be in the center of realview + double[] realOrigo = M.mapToVirtualView(M.RealView[0]>>1, + M.RealView[1]>>1); + M.moveOrigo(vvp[0]-realOrigo[0], vvp[1]-realOrigo[1]); + M.cellRepr(); + ZZUpdateManager.chg(); + } + } + + public ZOb newZOb(String id) { + if(id.equals("View1")) + return new AwtView1(); + else + return null; + } + }; + + // This is really hacky part... + static ZZCell curAct; + static void a(String key, String act) { a(key, act, null); } + static void a(String key, String act, ZZCell next) { + curAct = curAct.N("d.2", 1); + curAct.setText(key); + ZZCell n = curAct.N("d.1", 1); + n.setText("Awtool." + act); + if(next != null) + next.insert("d.3", 1, n); + } + + static void actions(ZZCell start) { + ZZCell awtact = start; awtact.setText("Awtool mode"); + ZZCell nchar = awtact.N("d.1",1); nchar.setText("Nile char"); + ZZCell nword = nchar.N("d.1", 1); nword.setText("Nile word"); + ZZCell nsent = nword.N("d.1", 1); nsent.setText("Nile sent"); + ZZCell npara = nsent.N("d.1", 1); npara.setText("Nile para"); + + ZZCell ncommon = npara.N("d.1", 1); ncommon.setText("Nile common"); + + + + curAct = nword; + // Annoying - these should be structurally + // describable!!! + a("MouseClicked1", "MouseSetCursor 0 WORD"); + a("Backspace", "BackSpace 0 WORD"); + a("Delete", "Delete 0 WORD"); + a("Alt-Backspace", "Delete 0 WORD"); + a("Ctrl-P", "Tunnel - WORD"); // P for pull + a("Ctrl-T", "Transcopy - WORD"); + a("Left", "Cursor - WORD"); + a("Right", "Cursor + WORD"); + a("Shift-Left", "AdjLeft - WORD"); + a("Shift-Right", "AdjRight + WORD"); + a("Ctrl-Left", "AdjRight - WORD"); + a("Ctrl-Right", "AdjLeft + WORD"); + a("Alt-Left", "Hop - WORD"); + a("Alt-Right", "Hop + WORD"); + a("Enter", "BreakParagraph 0 WORD"); + + a("Up", "Cursor - SENT"); + a("Down", "Cursor + SENT"); + a("Alt-Up", "Hop - SENT"); + a("Alt-Down", "Hop + SENT"); + + a("INSERT", "Insert", nchar); + a("Tab", "Mode 0 SENT", nsent); + // awtool specific + a("Alt-N", "NileOnOff", awtact); + + curAct = nsent; + a("MouseClicked1", "MouseSetCursor 0 SENT"); + a("Backspace", "BackSpace 0 SENT"); + a("Delete", "Delete 0 SENT"); + a("Alt-Backspace", "Delete 0 SENT"); + a("Ctrl-P", "Tunnel - SENT"); // P for push + a("Ctrl-T", "Transcopy - SENT"); + a("Left", "Cursor - SENT"); + a("Right", "Cursor + SENT"); + a("Shift-Left", "AdjLeft - SENT"); + a("Shift-Right", "AdjRight + SENT"); + a("Ctrl-Left", "AdjRight - SENT"); + a("Ctrl-Right", "AdjLeft + SENT"); + a("Alt-Left", "Hop - SENT"); + a("Alt-Right", "Hop + SENT"); + a("Enter", "BreakParagraph 0 SENT"); + + a("Up", "Cursor - PARA"); + a("Down", "Cursor + PARA"); + a("Alt-Up", "Hop - PARA"); + a("Alt-Down", "Hop + PARA"); + + a("INSERT", "Insert", nchar); + a("Tab", "Mode 0 CHAR", nchar); + // awtool specific + a("Alt-N", "NileOnOff", awtact); + +/* + curAct = npara; + a("MouseClicked1", "MouseSetCursor 0 PARA"); + a("Backspace", "BackSpace 0 PARA"); + a("Delete", "Delete 0 PARA"); + a("Alt-Backspace", "Delete 0 PARA"); + a("Left", "Cursor - PARA"); + a("Right", "Cursor + PARA"); + a("Shift-Left", "AdjLeft - PARA"); + a("Shift-Right", "AdjRight + PARA"); + a("Ctrl-Left", "AdjRight - PARA"); + a("Ctrl-Right", "AdjLeft + PARA"); + a("Alt-Left", "Hop - PARA"); + a("Alt-Right", "Hop + PARA"); + + a("INSERT", "Insert"); + a("Tab", "Mode 0 CHAR", nchar); + */ + + curAct = nchar; + a("MouseClicked1", "MouseSetCursor 0 CHAR"); + a("Left", "Cursor - CHAR"); + a("Right", "Cursor + CHAR"); + a("Backspace", "BackSpace 0 CHAR"); + a("Delete", "Delete 0 CHAR"); + a("Alt-Backspace", "Delete 0 CHAR"); + a("INSERT", "Insert"); + a("Tab", "Mode 0 WORD", nword); + a("Enter", "BreakParagraph 0 CHAR"); + + a("Ctrl-C", "PUICopy 0 CHAR"); + + a("Up", "Cursor - WORD"); + a("Down", "Cursor + WORD"); + // awtool specific + a("Alt-N", "NileOnOff", awtact); + + // awtool acts + curAct = awtact; + a("MouseStartDrag", "StartDrag"); + a("MouseDragged1", "Dragged"); + a("MouseReleased1", "StopDrag"); + a("Shift-MouseStartDrag", "StartCreatingNote"); + a("Shift-MouseDragged1", "CreatingNote"); + a("Shift-MouseReleased1", "StopCreatingNote"); + a("Shift-MouseClicked3", "ChangeOrigo"); + a("MouseClicked3", "FocusOrigoAndSelect"); + a("Shift-MouseClicked1", "SetCursor2"); + a("MouseClicked1", "SetCursor1"); + a("l", "NewLink"); + a("m", "ChangeMetrics"); + a("g", "GridOnOff"); + a("r", "ResetOrigo"); + a("Alt-N", "NileOnOff", nchar); + + } +} diff --git a/Modules/awtool/BooleanMesh.java b/Modules/awtool/BooleanMesh.java new file mode 100644 index 0000000..3a6a309 --- /dev/null +++ b/Modules/awtool/BooleanMesh.java @@ -0,0 +1,78 @@ +/* +BooleanMesh.java + * + * Copyright (c) 2000-2001 Ted Nelson and Tuomas Lukka + * Copyright (c) 2000-2001 Benjamin Fallenstein + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Kimmo Wideroos + */ + +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; + +public abstract class BooleanMesh { + public static boolean dbg = false; + static void p(String s) { if(dbg) System.out.println(s); } + static void pa(String s) { System.out.println(s); } + + static String d_1 = "d.1"; static String d_2 = "d.2"; + static public ZZCell bStructure = null; + static public Hashtable bOperators = new Hashtable(); + + /* + */ + public BooleanMesh(ZZCell bs) { + bStructure = bs; + bOperators.put("AND", new boolean[][]{{false, false}, {false, true}}); + bOperators.put("OR", new boolean[][]{{false, true}, {true, true}}); + bOperators.put("XOR", new boolean[][]{{false, true}, {true, false}}); + } + + public boolean evaluate(ZZCell nhc) { return evaluate(bStructure, nhc); } + + private boolean evaluate(ZZCell bElem, ZZCell nhc) { + String bt = bElem.getText(); + p("belem:"+bt+" c:"+nhc.getText()); + ZZCell arg1, arg2; + int i = 0, j = 0; + if(bOperators.containsKey(bt)) { + // add exception handling here! + arg1 = bElem.s(d_1); arg2 = bElem.s(d_2); + p("arg1:"+arg1.getText()); + p("arg2:"+arg2.getText()); + if(evaluate(arg1, nhc)) i = 1; + if(evaluate(arg2, nhc)) j = 1; + p("i:"+i+" j:"+j); + boolean retv = ((boolean[][])bOperators.get(bt))[i][j]; + p("RETV: "+retv); + return retv; + } else { + // compare bElem (=categoryname) and c + p("TEST! "+nhc.getText()+" =?= "+bElem.getText()); + return testBelonging(nhc, bElem); + } + } + + public abstract boolean testBelonging(ZZCell c, ZZCell category); + +} + + + + diff --git a/Modules/awtool/README b/Modules/awtool/README new file mode 100644 index 0000000..4a6ee0d --- /dev/null +++ b/Modules/awtool/README @@ -0,0 +1,58 @@ + +A(ssociative) writing tool -demo +-------------------------------- + +Althought you cannot actually write with this demo at the moment, +it is (however) possible to + +- create new notes by dragging mouse and keeping + mouse1-key pressed +- drag and drop notes created before +- link notes by attaching cursors (click mouse1 / shift-mouse1 + on a note) to a pair of notes and pressing 'l' (uncapitalized 'L') +- change metrics by pressing 'm' (currently 3 possibilities) +- change focus (click mouse3-button) +- change origo (click shift-mouse3) + +To start: +- create new action 'Awtool.TESTWIN' in zz-system +- use it to invoke awtool + +About the view: +- Real view (rendered part) is mutable +- Virtual view is fixed, all objects' places + are based on virtual view coordinates (-1.0= 0; i--) + r.run(); + long t1 = System.currentTimeMillis(); + nt *= 2; + diff = t1 - t0; + } while(diff < 1500); + p(s+": "+nt+" iter, "+diff+" ms, per iter: "+ + (long)(1000000 * diff / (float)nt) + " ns"); + } + + /** Run the given tests, time them and print out the results. + * Each test should be relatively fast to execute. + * @param tests Triplets of String, String, Runnable: + * first string is a unique ID for the test, + * second string a human-readable explanation (without newlines) + * and the Runnable is the test itself. + */ + public void run(Object[] tests) { + for(int i=0; i"); + // Create people rank in alphabetical order + rs = st.executeQuery("select * from members order by name"); + ZZCell prev = null; + while(rs.next()) { + ZZCell curr = (ZZCell)id2mem.get(rs.getString(1)); + + if(prev != null) prev.connect("d.people", 1, curr); + prev = curr; + } + + // Create sig rank in alphabetical order + rs = st.executeQuery("select * from sigs order by name"); + prev = null; + while(rs.next()) { + ZZCell curr = (ZZCell)id2sig.get(rs.getString(1)); + + if(prev != null) prev.connect("d.insigs", 1, curr); + prev = curr; + } + + + + + p("Rels: "); + + // Insert relcells after the positions table + rs = st.executeQuery("select * from positions"); + while(rs.next()) { + String pers = rs.getString(1); + String sig = rs.getString(2); +// p("Rel: "+pers+" "+sig); + ZZCell pc = (ZZCell)id2mem.get(pers); + ZZCell sc = (ZZCell)id2sig.get(sig); + if(pc == null || sc == null) + throw new Error("No such relation "+pers+" "+sig); + ZZCell relc = pc.N("d.insigs",1); + sc.insert("d.people", 1, relc); + relc.setText("+"); + } + rs.close(); + + // Sort the ranks of the in-which-sigs tables. + + for(Enumeration e = id2mem.elements(); + e.hasMoreElements(); ) { + ZZCell c = (ZZCell)e.nextElement(); + ZZUtil.sortRank(c, "d.insigs", 1, + new DHeadComp("d.people"), false); + } + + for(Enumeration e = id2sig.elements(); + e.hasMoreElements(); ) { + ZZCell c = (ZZCell)e.nextElement(); + ZZUtil.sortRank(c, "d.people", 1, + new DHeadComp("d.insigs"), false); + } + + st.close(); + db.close(); + + } + } /* else if(id.equals("IMPORT")) { + // XXX How to give 2 arguments: the file name and the home cell + (new XML()).load(new File(target.getText()), + }*/ + } catch(SQLException e) { + System.out.println(e); + e.printStackTrace(); + } catch(ClassNotFoundException e) { + System.out.println(e); + e.printStackTrace(); + } + } + }; +} diff --git a/Modules/database/createscript.pl b/Modules/database/createscript.pl new file mode 100644 index 0000000..a05ccd8 --- /dev/null +++ b/Modules/database/createscript.pl @@ -0,0 +1,68 @@ +#!/usr/bin/perl +# +# Create a sample database. +# Use the linux kernel CREDITS file as input. + + +print <<'STOP'; +DROP TABLE members; +DROP TABLE positions; +DROP TABLE sigs; + +CREATE TABLE members ( + id INT4, + name TEXT, + address TEXT, + phone TEXT, + email TEXT, + PRIMARY KEY(id) +); + +CREATE TABLE positions ( + person INT4, + sig INT4 +/* type TEXT */ +); + +CREATE TABLE sigs ( + id INT4, + name TEXT, + PRIMARY KEY(id) +); +STOP + +$/ = "\n\n"; + +$id = 0; + + +while(<>) { + /^\s*N:/ or next; + s/'//g; + my %h; + for(split "\n") { + /^([A-Z]): (.*)$/ or next; + push @{$h{$1}}, $2; + } + $phone = int(1000000 + rand 9000000); + $phone =~ s/(...)(....)/\1-\2/g; + print "INSERT INTO members VALUES ($id, '$h{N}[0]', '$h{S}[0]', '$phone', '$h{E}[0]');\n"; + $id++; + last if $id > 100; +} + +$sid = 0; +for(qw/filesys mm drivers boot console vfs/) { + print "INSERT INTO sigs VALUES ($sid, '$_');\n"; + $sid++; +} + +my %pos; + +for(1..120) { + $pers = int rand $id; + $sig = int rand $sid; + next if $pos{$pers}{$sig}++; + print "INSERT INTO positions VALUES ($pers, $sig);\n"; +} + diff --git a/Modules/database/zz.queries b/Modules/database/zz.queries new file mode 100644 index 0000000..6253521 --- /dev/null +++ b/Modules/database/zz.queries @@ -0,0 +1,18 @@ + +-- Taulut + +SELECT * FROM members; + +SELECT * FROM positions; + +SELECT * FROM sigs; + +-- Kaikkien tekijöiden kaikki projektit + +SELECT members.name,sigs.name FROM members, positions, sigs WHERE members.id = positions.person AND sigs.id = positions.sig ORDER BY members.name, sigs.name; + +-- Kaikkien projektien kaikki tekijät + +SELECT sigs.name,members.name FROM members, positions, sigs WHERE members.id = positions.person AND sigs.id = positions.sig ORDER BY sigs.name, members.name; + + diff --git a/Modules/database/zz.sql b/Modules/database/zz.sql new file mode 100644 index 0000000..1c60f0e --- /dev/null +++ b/Modules/database/zz.sql @@ -0,0 +1,29 @@ + +CREATE TABLE members ( + id INT4, + fname TEXT, + lname TEXT, + address TEXT, + phone TEXT, + email TEXT, + PRIMARY KEY(id) +); + +CREATE TABLE positions ( + person INT4, + sig INT4 +/* type TEXT */ +); + +CREATE TABLE sigs ( + id INT4, + name TEXT, + PRIMARY KEY(id) +); + +INSERT INTO members VALUES + (1,'Henna','Koskinen','Kuusikkokuja 4','321-564356','henna43@hotmail.com'); +INSERT INTO sigs VALUES + (1,'helicopters'); +INSERT INTO positions VALUES + (1,1); diff --git a/Modules/daytimedemo/Calendar2.zob b/Modules/daytimedemo/Calendar2.zob new file mode 100644 index 0000000..12ee2cb --- /dev/null +++ b/Modules/daytimedemo/Calendar2.zob @@ -0,0 +1,162 @@ +/* +Calendar2.zob + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.awt.*; +import java.util.*; +import java.io.*; + +public class Calendar2 implements FlobView, ZOb { + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + static public ZZModule module = new ZZModule() { + public ZOb newZOb(String id) { + if(id.equals("R")) + return new Calendar2(); + return null; + } + }; + + STRUCTPARAMS { + Font nfont + = new Font("SansSerif", Font.PLAIN, 16); + + Font bfont + = new Font("SansSerif", Font.BOLD, 16); + } + + FontMetrics nfm, bfm; + + INITIALIZE { + nfm = FONTMETRICS(nfont); + bfm = FONTMETRICS(bfont); + } + + final String[] txts = new String[] { + "Vk", "M", "T", "K", "T", "P", "L", "S" + }; + + public void raster(FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed) { + + Dimension s = into.getSize(); + + final int x = s.width/2 / 10; + final int y = s.height / 10; + final int w = s.width/2 - 2 * x; + final int h = s.height - 2 * y; + + final int x2 = x + s.width/2; + + final int xm = w / 8; + final int ym = h / 7; + + Dimension c = fact.getSize(null, 1); + int cw = c.width; + int ch = c.height; + + // Find the first day of the month + + ZZCell curday = accursed.h("d.event").h("d.events"); + ZZCell mfirst = curday.h("d.day"); + + + + + if(mfirst.s("d.weekday") == null) { + into.add(new Renderable() { + { d = 1; } + public void render(Graphics g) { + g.setColor(Color.red); + g.setFont(new Font("SansSerif", Font.BOLD, 32)); + g.drawString("Not calendar data", 20, 40); + } + }); + return; + } + int day = Integer.parseInt(mfirst.s("d.weekday").t()); + final int week = Integer.parseInt(mfirst.s("d.weekday",2).t()); + + into.add(new Renderable() { + { d = 50; } + public void render(Graphics g) { + Color old = g.getColor(); + g.setColor(Color.gray); + g.setFont(nfont); + g.drawRect(x, y, w, h); + g.drawLine(x+xm, y, x+xm, y+h); + g.drawLine(x, y+ym, x+w, y+ym); + int fh = nfm.getHeight(); + for(int i=0; i<8; i++) { + int tw = nfm.stringWidth(txts[i]); + g.drawString(txts[i], x+(xm-tw)/2+i*xm, y+(ym+fh)/2); + } + for(int i=0; i<6; i++) { + int tw = nfm.stringWidth(""+(i+week)); + g.drawString(""+(i+week), x+(xm-tw)/2, y+(ym+fh)/2+(i+1)*ym); + } + g.setColor(new Color(0xb0b0b0)); + for(int i=0; i<5; i++) { + g.drawLine(x, y+(2+i)*ym, x+w, y+(2+i)*ym); + } + } + }); + + LoopDetector l = new LoopDetector(); + int row = 0; + for(ZZCell mday = mfirst; mday != null; mday = mday.s("d.day")) { + l.detect(mday); + boolean hasEv = (mday.s("d.events") != null); + + fact.makeFlob(into, mday, mday, (hasEv ? (float)1.8 : 1), + x+1+(1+day)*xm, y+1+(1+row)*ym, 2, xm-2, ym-2); + + if(mday == curday) { + // Ring it + + } + day += 1; + if(day >= 7) row ++; + day %= 7; + } + + row = 0; + int fh = nfm.getHeight(); + for(ZZCell curev = curday.s("d.events"); + curev != null && curev != curday; + curev = curev.s("d.events")) { + fact.makeFlob(into, curev, curev, 1, + x2 + 10, y + (ch+2)*row, 1, w-10-cw, ch); + ZZCell txt = curev.s("d.event"); + fact.makeFlob(into, txt, txt, 1, + x2 + w - cw, y + (ch+2)*row, 1, cw, ch); + row ++; + } + + + } +} +// vim: set syntax=java : + diff --git a/Modules/daytimedemo/ClockCellView.zob b/Modules/daytimedemo/ClockCellView.zob new file mode 100644 index 0000000..81efbd9 --- /dev/null +++ b/Modules/daytimedemo/ClockCellView.zob @@ -0,0 +1,116 @@ +/* +ClockCellView.zob + * + * Copyright (c) 2001, Benja Fallenstein + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benja Fallenstein + */ + +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.awt.*; + +/** A cell view that shows the daytime demo clock, using a scene flob. + * For use with ideosyncratic cell view. Create the cell to be shown as a + * clock. Posward on d.3, connect the clock cell to a d.2 rank of appointments + * in the regular DayTimeDemo structure (see DayTimeDemo.zob and the + * CyberText article pictures). Then, from the clock cell negwards on + * d.cellview create a new cell and write the cell view's name, e.g. + * "Clock Cellview," in it. From that cell, create a new cell poswards on d.1 + * and write "DayTimeDemo.C" (of course w/o quotes) in it. Use F2 to switch + * to the ideosyncratic cell view, and the clock cell should change its + * appereance to a DayTimeDemo clock. (Best viewed with StretchVanishing or + * Quad view, so that it's not shown that small.) + */ + +public class ClockCellView implements FlobFactory, ZOb { +public static final String rcsid = "$Id: ClockCellView.zob,v 1.3 2001/03/18 17:50:16 bfallenstein Exp $"; + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + STRUCTPARAMS { + Font txtfont + = new Font("Serif", Font.BOLD, 14); + + Font clkfont + = new Font("SansSerif", Font.PLAIN, 11); + } + + public Dimension getSize(ZZCell c, float fract) { + return new Dimension((int)(150*fract), (int)(150*fract)); + } + + DayTimeDemo dtd = new DayTimeDemo(); + + INITIALIZE { + dtd.txtfont = txtfont; + dtd.clkfont = clkfont; + dtd.txtfm = FONTMETRICS(txtfont); + dtd.clkfm = FONTMETRICS(clkfont); + } + + public Flob makeFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, + int x, int y, int d, int w, int h) { + + FlobSet sc = new FlobSet(new Dimension(w, h), Color.white, Color.black, + ScalableFont.fmComp); + dtd.raster(sc, null, null, null, c.getRootclone().h("d.3", 1)); + + SceneFlob sf = new SimpleSceneFlob(x, y, d, w, h, c, sc); + CellFlobFactory1.addSolidColors(into, sf, sf); + into.add(sf); + return sf; + } + + public Flob placeFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, + int x, int y, int depth, + float xfract, float yfract) { + Dimension d = getSize(c, fract); + return makeFlob(into, c, handleCell, fract, + (int)(x-xfract*d.width), + (int)(y-yfract*d.height), + depth, d.width, d.height); + } + + public Flob centerFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, Point p, int xalign, int yalign, + int depth, Dimension d) { + if(d == null) d = getSize(c, fract); + int x, y; + x = p.x - d.width/2; y = p.y - d.height/2; + + if(xalign < 0) x = p.x; + if(xalign > 0) x = p.x - d.width; + if(yalign < 0) y = p.y; + if(yalign > 0) y = p.y - d.height; + p("centerFlob "+p+" "+d+" at "+x+" "+y+" align "+xalign+" "+yalign); + return makeFlob(into, c, handleCell, fract, x, y, + depth, d.width, d.height); + } + public Flob centerFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, Point p, int xalign, int yalign, int depth) { + return centerFlob(into, c, handleCell, fract, p, xalign, yalign, + depth, null); + } +} + +// vim: set syntax=java : diff --git a/Modules/daytimedemo/DayTimeDemo.zob b/Modules/daytimedemo/DayTimeDemo.zob new file mode 100644 index 0000000..efcc1e2 --- /dev/null +++ b/Modules/daytimedemo/DayTimeDemo.zob @@ -0,0 +1,174 @@ +/* +DayTimeDemo.zob + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.awt.*; +import java.util.*; +import java.io.*; + +/** A simple raster showing times of day along a circle. + * The structure is described along three dimensions: + * hierarchy, sibling and cross-reference (d.1, d.2 and d.3 by default). + * On these, the hierarchy is arranged as a corner list with an empty + * corner cell, and the cross-references are simply siblings + * connected. + *

    + * The structure is specified as a rank on d.2 of d.1 lists: + * start, end, type, text. Type's root clone will have the color + * of the type on d.1. + *

    + * The whole rank on d.2 is read. + */ + +public class DayTimeDemo implements FlobView, ZOb { + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + static public ZZModule module = new ZZModule() { + public ZOb newZOb(String id) { + if(id.equals("R")) + return new DayTimeDemo(); + if(id.equals("C")) + return new ClockCellView(); + return null; + } + }; + + STRUCTPARAMS { + Font txtfont + = new Font("Serif", Font.BOLD, 14); + + Font clkfont + = new Font("SansSerif", Font.PLAIN, 11); + } + + FontMetrics txtfm, clkfm; + + INITIALIZE { + txtfm = FONTMETRICS(txtfont); + clkfm = FONTMETRICS(clkfont); + } + + static final String next = "d.2"; + static final String hier = "d.1"; + static final String cross = "d.3"; + + static final int time2deg(String time) { + int i = time.indexOf(":"); + if(i < 0) return 0; + String t1 = time.substring(0,i); + String t2 = time.substring(i+1); + int h = -1; + int m = -1; + try { + h = Integer.parseInt(t1); + m = Integer.parseInt(t2); + } catch(NumberFormatException e) { + System.out.println("Exc: "+e); + } + return -(int)(360 * (h*60.0 + m) / (24*60)) - 90; + } + + static final Point deg2pt(int deg, int w, int h) { + return new Point((int)(w/2*Math.cos(deg * Math.PI / 180)), + -(int)(h/2*Math.sin(deg * Math.PI / 180))); + } + + public void raster(FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed) { + + Dimension s = into.getSize(); + + final int x = s.width / 10; + final int y = s.height / 10; + final int w = s.width - 2 * x; + final int h = s.height - 2 * y; + + // Clock face. + into.add(new Renderable() { + { d = 50; } + public void render(Graphics g) { + Color old = g.getColor(); + g.setColor(Color.black); + g.setFont(clkfont); + for(int i=0; i<24; i++) { + int and = time2deg(i+":00"); + // g.fillArc(x, y, w, h, and, 1); + Point p = deg2pt(and, w, h); + p.x *= 1.05; + p.y *= 1.05; + p.translate(x+w/2, y+h/2); + g.drawLine(x+w/2, y+h/2, p.x, p.y); + if(i % 2 == 0) { + String str = i+":00"; + g.drawString(str, p.x - clkfm.stringWidth(str)/2 , p.y); + } + } + g.setColor(old); + } + }); + + for( + ZZCell cur = accursed.h("d.1", -1).h("d.2", -1); + cur != null; + cur = cur.s("d.2", 1)) { + ZZCell c = cur; + String start = c.getText(); c = c.s("d.1", 1); + String end = c.getText(); c = c.s("d.1", 1); + ZZCell meet = c.h("d.clone", -1).s("d.1", 1); + String col = "0xffffff"; + if(meet != null) col = meet.getText(); + c = c.s("d.1", 1); + + final String text = c.getText(); + final int sang = time2deg(start); + final int eang = time2deg(end); + final Color color = Color.decode(col); + + // now, render it. + into.add(new Renderable() { + { d = 50; } + public void render(Graphics g) { + g.setColor(color); + g.fillArc(x, y, w, h, sang, eang-sang); + }}); + into.add(new Renderable() { + { d = 45; } + public void render(Graphics g) { + g.setFont(txtfont); + Point p = deg2pt((sang+eang)/2, w, h); + p.x *= 0.8; + p.y *= 0.8; + p.translate(x+w/2, y+h/2); + g.setColor(Color.black); + g.drawString(text, p.x, p.y); + g.fillOval(p.x-8, p.y-8, 8, 8); + }}); + + + } + + } +} +// vim: set syntax=java : diff --git a/Modules/extern/Extern.java b/Modules/extern/Extern.java new file mode 100644 index 0000000..5372662 --- /dev/null +++ b/Modules/extern/Extern.java @@ -0,0 +1,83 @@ +/* +Extern.java + * + * Copyright (c) 2000, Ted Nelson, Tuomas Lukka and Vesa Parkkinen + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Vesa Parkkinen + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.io.*; +import java.awt.*; + +/** + * Module to handle external commands. At the moment only + * EXECBROWSER is implemented. To start netscape execbrowser with + * empty target cell. If there is text in the target cell, + * netscape -remote openURL("") is executed. + */ +public class Extern { + + public static final String rcsid = "$Id: Extern.java,v 1.4 2000/09/19 10:32:02 ajk Exp $"; + public static final boolean dbg = true; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + + static public ZZModule module = new ZZModule() { + public void action(String id, ZZCell code, + ZZCell target, + ZZView v, ZZView cv, + String key, Point pt, + ZZScene xi) { + + + try { + p("Extern ACTION!"); + /* + * XXX: + * Add a chech to see whether a netscape or mozilla + * is running. + * + */ + if(id.equals("EXECBROWSER")) { + Process p = null; + String s = target.getText(); + if ( ! s.equals( "" ) ){ + p("netscape -remote openURL(" + s + ")" ); + p = Runtime.getRuntime().exec( + "netscape -remote openURL(" + s + ") "); + p("" + p); + + } + else { + Runtime.getRuntime().exec("netscape"); + } + } else { + pa("NO SUCH METHOD!! "); + } + + } + catch (IOException ex){ + p("" + ex); + } + } + + }; +} diff --git a/Modules/hypergenealogy/HyperGenealogy.zob b/Modules/hypergenealogy/HyperGenealogy.zob new file mode 100644 index 0000000..491d5cc --- /dev/null +++ b/Modules/hypergenealogy/HyperGenealogy.zob @@ -0,0 +1,283 @@ +/* +HyperGenealogy.zob + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.awt.*; +import java.util.*; +import java.io.*; + +/** A simple keyframe-based lifeline/meeting tracer. + * There is: one cell for each meeting, one cell for each person + * and one cell for each person of a meeting. + * We plot the cells of the people and meetings. + * The meeting cell can have a short label. The fuller explanation + * should be elsewhere. + *

    + * Dimension names give the dimension along which to find the cell + * with the number, except "time", which shows the keyframes. + *

    + * All numbers are floats between 0 and 1. + *

    + * There must be a root cell which starts the list of all persons + * on d.persons and the timeline on d.events. + */ + +public class HyperGenealogy implements FlobView, ZOb { + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + static public ZZModule module = new ZZModule() { + public ZOb newZOb(String id) { + if(id.equals("R")) + return new HyperGenealogy(); + return null; + } + public void action(String id, + ZZCell code, + ZZCell target, + ZZView view, ZZView cview, String key, Point pt, ZZScene xi) { + } + }; + + STRUCTPARAMS { + Font meetfont + = new Font("Serif", Font.BOLD, 11); + + } + + FontMetrics meetfm; + + INITIALIZE { + meetfm = FONTMETRICS(meetfont); + } + + + static public class dc { + /** The dimension from the meeting cell to the participants, + * and from the root to the peoples' cells. + */ + final String persons = "d.persons"; + /** The dimension from the person's cell to the events in his life, + * and from the root cell to all timeline cells. + * All these cells should go forwards in the "time" dimension. + */ + final String events = "d.events"; + /** The dimension from a timeline cell to meeting cell. + */ + final String at = "d.at"; + } + static dc d = new dc(); + + public float tofloat(ZZCell c) throws NumberFormatException { + return (Float.valueOf(c.getText())).floatValue(); + } + + /** Return the value the given cell has for the particular dimension. + * This routine understands the special dimension time, + * which it takes to mean the number at the headcell of + * d.persons + * and d.at. That cell is assumed to be on the timeline. + */ + public float dim(ZZCell c, String dimname) { + try { + ZZCell dc; + if(dimname.equals("time")) { + dc = c.h(d.persons, -1).h(d.at, -1); + if(dc == c) dc = null; + } else { + dc = c.s(dimname, 1); + } + if(dc == null) return -1; + return tofloat(dc); + } catch(NumberFormatException e) { + return -1; + } + } + + + /** + * @param from Meeting cell + */ + public void place(FlobSet into, int x, int y, int w, int h, + FlobFactory fact, + String[] dims, ZZCell from, int depthleft) { + + from = from.h(d.persons); + + for(ZZCell c = from.s(d.persons, 1); + c != null; + c = c.s(d.persons, 1)) { + + if(into.findFlob("", c) != null) + return; + + float dx = dim(c, dims[0]); + if(dx < 0) return; + float dy = dim(c, dims[1]); + if(dy < 0) return; + + Flob flob = fact.placeFlob(into, from, c, + 1, + (int)(x + dx * w), (int)(y + dy * h), + 1, + (float)0.5, (float)0.5); + Flob f2 = fact.placeFlob(into, c.h(d.events), c, + 1, + (int)(x + dx * w), (int)(y + dy * h + flob.h/2), + 1, + (float)0.5, (float)0.0); + f2.flobPath = "evPers"; + + if(depthleft <= 0) continue; + ZZCell n = c.s(d.events, 1); + if(n != null) + place(into, x, y, w, h, fact, dims, n, depthleft-1); + n = c.s(d.events, -1); + if(n != null) + place(into, x, y, w, h, fact, dims, n, depthleft-1); + } + } + + /** Place the cells at a given instant of time. + */ + public void placeTime(FlobSet into, int x, int y, int w, int h, + FlobFactory fact, + String[] dims, ZZCell from, float at) { + // This assumes the root... + ZZCell root = from; + LoopDetector ld = new LoopDetector(); + p("Placetime"); + for(ZZCell p = root.s(d.persons); p != null; p = p.s(d.persons)) { + ld.detect(p); + // Find the right time interval. Move poswards until greater + // or eq than current. + ZZCell prevev = null; + float prevt = 0; + float t = 0; + ZZCell ev; + p("Pt1: "+p); + for(ev = p.s(d.events); ev != null; ev = ev.s(d.events)) { + t = dim(ev, "time"); + p("Pt2: "+ev+" "+t); + if(t >= at) break; + prevev = ev; + prevt = t; + } + p("Pt3: "+prevev+" "+ev+" "); + + float dx, dy; + if(ev == null) continue; + + if(prevev == null) { + if(t > at) continue; + dx = dim(ev, dims[0]); if(dx < 0) continue; + dy = dim(ev, dims[1]); if(dy < 0) continue; + } else { + float f = 1 - (at - prevt) / (t - prevt); + // Now we've got it in the aim... get the coordinates + // and interpolate. + float dx0 = dim(prevev, dims[0]); if(dx0 < 0) continue; + float dx1 = dim(ev, dims[0]); if(dx1 < 0) continue; + float dy0 = dim(prevev, dims[1]); if(dy0 < 0) continue; + float dy1 = dim(ev, dims[1]); if(dy1 < 0) continue; + + + dx = f * dx0 + (1-f) * dx1; + dy = f * dy0 + (1-f) * dy1; + } + + Flob flob = fact.placeFlob(into, p, p, + 1, + (int)(x + dx * w), (int)(y + dy * h), + 1, + (float)0.5, (float)0.5 + ); + + // ZZCell + } + } + + // If accursed cell is a timeline cell, do all persons + public void raster(final FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed) { + + Dimension s = into.getSize(); + + int x = s.width / 10; + int y = s.height / 10; + int w = s.width - 2 * x; + int h = s.height - 2 * y; + + if(accursed.s(d.at, 1) != null) { + placeTime(into, x, y, w, h, fact, dims, + accursed.h(d.events), tofloat(accursed)); + } else { + place(into, x, y, w, h, fact, dims, accursed.h(d.persons), 3); + } + + // selection: 3 next/prev meetings of current person, + // 1 next/prev of those he met. + + final LineDecor.Builder ldb = new LineDecor.Builder(into, null); + final LineDecor.Builder ldbm = new LineDecor.Builder(into, Color.red); + final Hashtable done = new Hashtable(); + + into.iterDepth(new FlobSet.DepthIter() { + final void dline(Flob from, String dim, int dir, + LineDecor.Builder bu) { + ZZCell c = from.c.s(dim, dir); + if(c == null) return; + if(done.get(c) != null) return; + Flob to = into.findFlob("", c); + if(to == null) return; + //draw the line + bu.l(from.x, from.y+from.h/2, to.x, to.y+to.h/2); + } + public void act(Flob[] flobs, int start, int n) { + ldb.startl(4*n, flobs[start].d); + ldbm.startl(4*n, flobs[start].d); + for(int i=start; i 1) { + higherdim++; + p("no el on hdim "+higherdim); + if(higherdim == dim) higherdim++; + } + if(level == 1 || higherdim >= dims.length) { + p("Iter.Dims -- no higher dim on dim "+dim); + dim++; + higherdim = 0; + if(dim >= dims.length) { + p("Iter.Dims -- no dim on level "+level); + level++; + if(level > maxlevel) return null; + dim = 0; higherdim = 1; + p("Iter.Dims level: "+level); + boolean doContinue = false; + for(int d=0; d 0) doContinue = true; + higher[d] = curr[d]; + curr[d] = new Vector(); + } + if(!doContinue) return null; + } + } + if(level > 1) enum = higher[higherdim].elements(); + else enum = higher[0].elements(); + } + iter.start((Iter.Step)enum.nextElement(), dims[dim]); + } + + curr[dim].addElement(iter.here); + p("ret: "+iter.here.cell); + return iter.here; + } + + public void stop() { iter.stop(); } +} diff --git a/Modules/iter/EnumVanishingView.zob b/Modules/iter/EnumVanishingView.zob new file mode 100644 index 0000000..0519f19 --- /dev/null +++ b/Modules/iter/EnumVanishingView.zob @@ -0,0 +1,177 @@ +/* +EnumVanishingView.zob + * + * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein, based on VanishingView by Tuomas Lukka + */ + + +package org.gzigzag; +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +/** A reimplementation of the vanishing raster. + * Much simpler than the original one since this one does not try + * to do the hard rasters as well. + */ + +public class EnumVanishingView implements FlobView, ZOb { +public static final String rcsid = "$Id: EnumVanishingView.zob,v 1.1 2000/11/16 20:28:53 bfallenstein Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + // Following are the parameters out of which the constructor + // is created. + + STRUCTPARAMS { + + /** The factor to shrink the cells with when moving away from + * center. + */ + float[] shrink // 2..2 + = new float[] {(float)0.9, (float)0.9}; + + /** The factor the center cell is enlarged with from default. + */ + float[] initmul // 2..2 + = new float[] {(float)1.6, (float)1.6}; + + /** The factor to enlarge the center cell on top of initmul. + * This only has an effect on the center cell whereas initmul + * affects all cells. + */ + float[] centermul // 2..2 + = new float[] {(float)1.0, (float)1.0}; + + /** The distance between neighbouring cells. + */ + int gap + = 5; + + /** The depth to raster to. + */ + int depth + = 5; + + /** The precedence order of dimensions. + */ + int[] pref // 2..5 + = new int[] {0, 1, 2}; + + /** Whether to allow cell sizes to vary. + */ + boolean varsize + = false; + + } + + // XXX This should be a structparam later on. + FlobDecorator linker = new StdLinks(); + + public void raster(FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed) { + + Dimension fs = into.getSize(); + + // Precalculate sizes and gaps. + int[] gaps = new int[depth]; + Dimension[] size = new Dimension[depth+1]; + float[] sizfact = new float[depth+1]; + + float xf = initmul[0], xf0 = xf; + float yf = initmul[1], yf0 = yf; + sizfact[0] = yf; + Dimension d0 = fact.getSize(null, yf); + Dimension d = (varsize ? fact.getSize(accursed, yf) : d0); + + for(int i=0; i0 ? 1 : -1; + int dpt = once.here.nth; + + // Alignments + int fxa, fya, txa, tya; + if(dim.dim == 0) { fxa=dir; txa=-dir; fya=0; tya=0; } + else if(dim.dim == 1) { fxa=0; txa=0; fya=dir; tya=-dir; } + else { fxa=dir; fya=dir; txa=-dir; tya=-dir; } + + Point p = f.getPoint(fxa, fya); + Point q = ZZUtil.movePoint(p, fxa, fya, gaps[dpt]); + + Flob g = fact.centerFlob(into, c, c, sizfact[dpt], q, txa, tya, + d1+dpt*dm, size[dpt]); + once.here.info = g; + p("To "+once.here+" assign "+g); + } + + linker.decorate(into, "", view); + + // Do the dimensions. + if(true) + ZZUtil.showFlobDims(into, fact, view, 3); + } + +} \ No newline at end of file diff --git a/Modules/iter/Iter.java b/Modules/iter/Iter.java new file mode 100644 index 0000000..aedeca4 --- /dev/null +++ b/Modules/iter/Iter.java @@ -0,0 +1,212 @@ +/* +Iter.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ + +package org.gzigzag; +import java.util.*; + +/** Help for iterating along ranks in various ways. + * A proposed alternative to ZZIter. + * XXX make constructors work (how?) + * XXX remove verbose debugging messages + * XXX make MUCH faster! + */ + +public class Iter { +public static final String rcsid = "$Id: Iter.java,v 1.1 2000/11/16 20:28:53 bfallenstein Exp $"; + public static final boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + + static public class Step { + public ZZCell cell; + public Step from; + public int nth; + + public Object info; + + // Do not need to be set (then, dir == null). + public String dim = null; + public int dir; + + public Step(ZZCell c) { from = null; cell = c; nth = 0; } + public Step(Step f, ZZCell c, int n) { from = f; cell = c; nth = n; } + + public Step go(ZZCell c) { return new Step(this, c, nth+1); } + public Step go(String dim, int dir) { + p("step "+cell+" "+dim+" "+dir); + ZZCell tocell = cell.s(dim, dir); + p("tocell "+tocell); + if(tocell == null) return null; + Step res = go(tocell); + p("res.cell "+res.cell); + res.dim = dim; res.dir = dir; + return res; + } + + public String toString() { return "[Iter.Step for "+cell+"]"; } + } + + static public abstract class Any { + public Step here, root; + public boolean included; + + protected abstract Step getNext(); + protected void doStart() {} + +// public Any(boolean included) { this.included = included; } + public ZZCell start(Step s) { + here = s; root = s; + doStart(); + if(!included) next(); + return here != null ? here.cell: null; + } + public ZZCell next() { + if(here == null) return null; + here = getNext(); + return here != null ? here.cell : null; + } + public boolean more() { return here != null; } + public void stop() { here = null; } + } + + + static public abstract class Dim extends Any { + String dim; int fdir = 1; + +// public Dim(String dim, int fdir, boolean included) { +// this.dim = dim; +// this.fdir = fdir; +// this.included = included; +// } + + public void start(Step s, String dim) { + this.dim = dim; start(s); + } + public void start(Step s, String dim, int fdir) { + this.dim = dim; this.fdir = fdir; start(s); + } + } + + + static public class Rank extends Dim { + protected Step getNext() { return here.go(dim, fdir); } + } + + + static public class Alter extends Dim { + /** Current position negwards and poswards. */ + Step neg, pos; + + public int ind; + + public void doStart() { + neg = here.go(dim, -fdir); + pos = here.go(dim, fdir); + p("alter start: "+pos+" "+neg+" // "+(pos==root?"yes":"no")); + ind = 0; + } + protected Step getNext() { + if(neg == null && pos == null) { p("alter null"); return null; } + // Trick: always change ind, only after see if we have something + // to return. If not, recurse and get the next one from the other side. + Step res; + if(ind <= 0) { + ind = -ind; + ind ++; + if(pos == null) + return getNext(); + res = pos; + pos = pos.go(dim, fdir); + p("alter pos from "+res+" to "+pos); + } else { + ind = -ind; + if(neg == null) + return getNext(); + res = neg; + neg = neg.go(dim, -fdir); + p("alter neg from "+res+" to "+neg); + } + p("alter: "+res); + // Don't loop XXX doesn't work yet +// if(neg!=null && pos!=null && neg.cell==pos.cell) return null; + return res; + } + public void stop() { + if(ind > 0) neg = null; + else if(ind < 0) pos = null; + else super.stop(); + } + } + + + static public abstract class Filter extends Any { + protected Any iter; + + protected abstract boolean check(); + protected void accepted() {} + +// public Filter(Any iter) { this.iter = iter; } + public ZZCell start(Step s) { + iter.start(s); + here = iter.here; + doStart(); + return here.cell; + } + public ZZCell next() { + if(here == null) return null; + do { + p("Filter get next..."); + iter.next(); + here = iter.here; + p("Filter check: "+here); + if(here == null) return null; + } while(!check()); + accepted(); + p("Filter accept "+here); + return here.cell; + } + public void stop() { iter.stop(); } + protected Step getNext() { throw new ZZError("getNext on Filter"); } + } + + + static public class Once extends Filter { + protected Hashtable done; + + protected void doStart() { done = new Hashtable(); } + protected boolean check() { return done.get(here.cell) == null; } + protected void accepted() { done.put(here.cell, here.cell); } + } + + + static public class Limited extends Filter { + protected int n, donenum; + +// public Limited(Any iter, int n) { this.iter = iter; this.n = n; } + protected void doStart() { donenum = 0; } + protected boolean check() { + if(donenum > n*n*2) return false; + return iter.here.nth < n; + } + protected void accepted() { donenum++; } + } +} \ No newline at end of file diff --git a/Modules/iter/README b/Modules/iter/README new file mode 100644 index 0000000..ee62007 --- /dev/null +++ b/Modules/iter/README @@ -0,0 +1 @@ +Some experiments for advanced ways of iteration through the structure. diff --git a/Modules/joystick/LinuxJoystick.java b/Modules/joystick/LinuxJoystick.java new file mode 100644 index 0000000..95ce586 --- /dev/null +++ b/Modules/joystick/LinuxJoystick.java @@ -0,0 +1,91 @@ +/* +ZZMbox.java + * + * Copyright (c) 2000, Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.io.*; + +/** A simple class to use the Linux joystick API. + * A separate thread is used to read in the blocking mode from the + * joystick and the appropriate callbacks are made. + */ + +public class LinuxJoystick implements Runnable { +public static final String rcsid = "$Id: LinuxJoystick.java,v 1.3 2000/09/19 10:32:03 ajk Exp $"; + public static final boolean dbg = true; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + FileInputStream in; + Thread t = new Thread(this); + + public LinuxJoystick(File f) { + try { + in = new FileInputStream(f); + t.start(); + } catch(Exception e) { + throw new Error("Couldn't open joystick"); + } + } + + public synchronized void run() { + try { + byte[] bpacket = new byte[8]; + int[] packet = new int[8]; + while(true) { + int n = in.read(bpacket); + p("Read "+n); + for(int i=0; i<8; i++) { + packet[i] = bpacket[i]; + if(packet[i] < 0) packet[i] += 256; + } + p("R: "+ + packet[0]+" "+ + packet[1]+" "+ + packet[2]+" "+ + packet[3]+" "+ + packet[4]+" "+ + packet[5]+" "+ + packet[6]+" "+ + packet[7]); + + long ms = packet[0] + (packet[1]<<8) + (packet[2]<<16) + + (packet[3]<<24); + int value = packet[4]+((packet[5]&0x7F)<<8); + if((packet[5]&0x80)!=0) + value -= 32768; + int type = packet[6]; + int num = packet[7]; + + p("EV: "+ms+" "+value+" "+type+" "+num); + } + } catch(Exception e) { + throw new Error("Couldn't open joystick"); + } + } + + /** For testing. */ + static public void main(String argv[]) { + LinuxJoystick j = new LinuxJoystick(new File("/dev/js0")); + } + +} diff --git a/Modules/mbox/SingleMail.zob b/Modules/mbox/SingleMail.zob new file mode 100644 index 0000000..3bb5db4 --- /dev/null +++ b/Modules/mbox/SingleMail.zob @@ -0,0 +1,133 @@ +/* +SingleMail.zob + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuukka Hastrup + */ + +package org.gzigzag.module.mbox; + +import org.gzigzag.*; +import java.awt.*; + + + +/** A presentation of a single e-mail message. + */ + +public class SingleMail implements FlobView, ZOb { + public static final boolean dbg = true; + static final void p(String s) { if (dbg) System.out.println(s); } + + STRUCTPARAMS { + Font hfont = new Font("SansSerif", Font.PLAIN, 14); + Font dfont = new Font("SansSerif", Font.BOLD, 14); + Font bfont = new Font("Monospaced", Font.PLAIN, 12); + + int tabstop = 8; + } + + int headerh; + int bodyh; + FontMetrics hfm; + Color headerc, datac, bodyc; + String tabs[]; + + INITIALIZE { + headerh = (hfont.getSize() > dfont.getSize()? hfont.getSize() + : dfont.getSize()); + bodyh = bfont.getSize(); + hfm = FONTMETRICS(hfont); + headerc = datac = bodyc = Color.red; + + tabs = new String[tabstop + 1]; + tabs[0] = ""; + for (int i = 1; i < tabstop + 1; i++) + tabs[i] = tabs[i - 1] + '\t'; + } + + public void raster(FlobSet into, FlobFactory fact, + ZZCell view, String[]dims, ZZCell accursed) { + Dimension d = into.getSize(); + + ZZCell handle = accursed.h("d.ref", -1); + + ZZCell c = handle; + ZZCell f; + int y = 0; + c = c.s("d.handle", 1); + while (c != null && y <= d.height) { + f = c.s("d.1", 1); + if (f != null) // Header record + y = addHeader(into, y, c, f); + else + y = addBody(into, y, c); + c = c.s("d.handle", 1); + } + } + + int addHeader(FlobSet into, int y, ZZCell c, ZZCell d) { + p(into.toString() + y + c.toString() + d.toString()); + p("C: " + c.getID()); + p("D: " + d.getID()); + String field = c.getText(); + String data = d.getText(); + y += headerh; + into.add(new TextDecor(0, y, field, headerc, hfont)); + into.add(new TextDecor(hfm.stringWidth(field) + 10, y, + data, datac, dfont)); + return y; + } + + int addBody(FlobSet into, int y, ZZCell c) { + String body = c.getText(); + int start = 0; + int end = -1; + while (end < body.length()) { // Split into lines + end = body.indexOf('\n', end + 1); + if (end == -1) + end = body.length(); + y += bodyh; + if (start < end) { + String line = body.substring(start, end); + StringBuffer buf = new StringBuffer(); + int offs = 0; + int pos = 0; + int tab = -1; + while (tab < line.length()) { // Expand tabs + tab = line.indexOf('\t', tab + 1); + if (tab == -1) + tab = line.length(); + buf.append(line.substring(pos, tab)); + if (tab < line.length()) { + int tablen = tabstop - ((tab + offs) % tabstop); + p("Tab: " + tablen); + buf.append(tabs[tablen]); + offs = offs + tablen - 1; + } + pos = tab + 1; + } + into.add(new TextDecor(0, y, new String(buf), bodyc, bfont)); + } + start = end + 1; + } + return y; + } +} + + +// vim: set syntax=java : diff --git a/Modules/mbox/ZZDateParser.java b/Modules/mbox/ZZDateParser.java new file mode 100644 index 0000000..fc43c6a --- /dev/null +++ b/Modules/mbox/ZZDateParser.java @@ -0,0 +1,398 @@ +/** + * ZZDateParser.java + * Created: Wed Feb 9 08:20:13 2000 + * + * + * Copyright (c) 1999, Ted Nelson, Tuomas Lukka and Vesa Parkkinen + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + * + * @author Vesa Parkkinen + * @version 0.2 ( might even work, sometimes ) + * + */ + +package org.gzigzag.module; + +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.StringTokenizer; +import java.util.TimeZone; +import java.util.SimpleTimeZone; + +/** + * This class tries to parse RFC 822 formatted dates. + * I haven't yet seen the spec, but this seems to work with + * few strings taken from my mails. + * OK, now that i've seen the spec, this should pretty much be capable + * of parsing the dates. + * Except the zone name information is not used. + *

    + */ +public class ZZDateParser { +public static final String rcsid = "$Id: ZZDateParser.java,v 1.9 2000/09/19 10:32:03 ajk Exp $"; + public static final boolean dbg = true; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + /** + * Month names used in date string. + */ + static String[] months = { "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" }; + + static String[] days = { "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", + "Sun" }; + + /** + * Method for parsing RFC 822 formatted dates to calendar objects. + * @param String d Date string in RFC 822 format. + * @return Calendar calendar having the date and time from RFC 822 + * ERROR CHECKING IS MISSING ! + * Will be added someday soon. + */ + public static Calendar parse(String d){ + + int year = 1; + int month = 1; + int date = 1; + + String day; + + int time[]; + + int gmt_diff[]; + + d.trim(); + try{ + + /* check whether we have day name */ + StringTokenizer t = new StringTokenizer( d, " " ); + + //if ( t.countTokens() > 1 ){ + //day = t.nextToken(); + // t.nextToken( " " ); + //} + //String tok; + try { + day = t.nextToken( ); + date = (int) Integer.parseInt( day ); + } catch( NumberFormatException nfe ) { + //day = t.nextToken(); + //t.nextToken( ); + date = (int) Integer.parseInt( t.nextToken( ) ); + } + //try{ + String smonth = t.nextToken(); + + for ( int i = 0; i < 12 ; i++ ) + if( smonth.equals( months[ i ] ) ){ + month = i ; + break; + } + + year = (int) Integer.parseInt( t.nextToken() ); + + time = parseTime( t.nextToken() ); + + String[] id; + + String s; + + + int off = 0; + + if( t.hasMoreTokens() ) + gmt_diff = parseTz(t.nextToken()); + + //if( ! t.hasMoreTokens() ){ + if( t.hasMoreTokens() ){ + gmt_diff = parseTz(t.nextToken()); + + off = gmt_diff[0] * 60 * 60 * 1000 + gmt_diff[1] * 60 * 1000; + id = TimeZone.getAvailableIDs( off ); + if ( id.length > 0 ) + s = id[0]; + else s = ""; + } else { + + s = "GMT";//t.nextToken(); + + } + + Calendar + calendar = new GregorianCalendar( + new SimpleTimeZone( off, s ) ); + + calendar.set( year, month, date, + time[0], time[1], time[2] ); + + return calendar;} + catch (Exception e){ + pa("Not a rfc822 date! Fix it :" + e); + return new GregorianCalendar(); + } + } + + /** + * What we've got here is a method to parse + * Calendar to RFC 822 formatted date String. + * + * @param Calendar calendar having the date and time from RFC 822 + * @return String d Date string in RFC 822 format. + * + */ + public static String parse(Calendar c){ + String dateString = ""; + + /* parse day string */ + int d = c.get(Calendar.DAY_OF_WEEK); + + String day = ""; + + switch ( d ){ + case (Calendar.MONDAY): + day = days[0]; + break; + + case (Calendar.TUESDAY): + day = days[1]; + break; + + case (Calendar.WEDNESDAY): + day = days[2]; + break; + + case (Calendar.THURSDAY): + day = days[3];; + break; + + case (Calendar.FRIDAY): + day = days[4];; + break; + + case (Calendar.SATURDAY): + day = days[5];; + break; + + case (Calendar.SUNDAY): + day = days[6];; + break; + + default: + day = ""; + break; + } + //*/ + //day = days[d]; + if ( day.length() == 3 ) + dateString += day +", "; + + int dm = c.get(Calendar.DAY_OF_MONTH); + + if( dm < 1 || dm > 31 ) dm = 1; + + dateString += "" + dm + " " ; + + int m = c.get(Calendar.MONTH); + + String month = ""; + /* + switch ( m ){ + case (Calendar.JANUARY): + month = months[0]; + break; + case (Calendar.FEBRUARY): + month = months[1]; + break; + case (Calendar.MARCH): + month = months[2]; + break; + case (Calendar.APRIL): + month = months[3]; + break; + case (Calendar.MAY): + month = months[4]; + break; + case (Calendar.JUNE): + month = months[5]; + break; + case (Calendar.JULY): + month = months[6]; + break; + case (Calendar.AUGUST): + month = months[7]; + break; + case (Calendar.SEPTEMBER): + month = months[8]; + break; + case (Calendar.OCTOBER): + month = months[9]; + break; + case (Calendar.NOVEMBER): + month = months[10]; + break; + case (Calendar.DECEMBER): + month = months[11]; + break; + default: + month = months[0]; + } + */ + + month = months[m]; + + dateString += month + " "; + + int hour = c.get(Calendar.HOUR_OF_DAY); + + String hh = ""+ hour; + + hh = addZeros(hh,2); + + int min = c.get(Calendar.MINUTE); + + String mm = ""+ min; + + mm = addZeros(mm,2); + + int sec = c.get(Calendar.SECOND); + + String ss = ""+ sec; + + ss = addZeros(ss,2); + + dateString += hh +":" + mm + ":" + ss + " " ; + + // tz + + int tz = c.get(Calendar.ZONE_OFFSET); + + int tz_h = tz / ( 60 * 60 * 1000 ); + int tz_m = ( tz % ( 60 * 60 * 1000 ) ) / 60 * 1000; + String t = addZeros("" + Math.abs(tz_h), 2); + t += addZeros("" + tz_m, 2); + if( tz_h < 0 ) + dateString += "-"; + if( tz_h == 0 && tz_m == 0 ) + dateString += "GMT"; + else dateString += ""+ t; + + return dateString; + + } + + private static String addZeros(String s,int count){ + int l = s.length(); + if ( l < count ) + for ( int i = l; i < count;i++){ + s = "0" + s;} + return s; + } + + + private static int[] parseTime( String time ){ + + int[] comp = { 0, 0, 0 }; + + StringTokenizer tt = new StringTokenizer(time,":"); + + if( tt.hasMoreTokens() ) + comp[0] = (int)Integer.parseInt(tt.nextToken()); + else return comp; + + if( tt.hasMoreTokens() ) + comp[1] = (int)Integer.parseInt(tt.nextToken()); + else return comp; + + if( tt.hasMoreTokens() ) + comp[2] = (int)Integer.parseInt(tt.nextToken()); + + return comp; + } + + /* XXX TODO: add parsing of zone names if needed. */ + private static int[] parseTz( String tz ){ + + int[] comp = { 0, 0 }; + + int negative = 1; + + tz.trim(); + + if( tz.startsWith( "-" ) ){ + negative = -1; + } + + int l = tz.length(); + + String s; + + StringTokenizer tt = new StringTokenizer( tz.substring( 1, l ) ); + + if ( tt.hasMoreTokens() ) + s = tt.nextToken(); + else s = tz.substring( 1, l ); + + int aa; + + try { + aa = (int) Integer.parseInt( s ); + } + catch( Exception e ) { + return comp; + } + + comp[0] = negative * (int) aa / 100; + // do we need this + comp[1] =/* negative * */ (int) aa % 100; + + return comp; + + } + + /* + public static void main(String[] argv){ + //Calendar c = ZZDateParser.parse("Tue, 15 Feb 2000 23:57:42 GMT"); + Calendar c = ZZDateParser.parse("Mon, 14 Feb 2000 18:04 -0200"); + //Calendar c = ZZDateParser.parse("Sun, 13 Feb 2000 18:04:26 -0200"); + //System.out.println(c.toString()); + //System.out.println(c.getTime().getTime()); + //System.out.println(c.get(Calendar.DATE)); + //System.out.println(c.get(Calendar.MONTH)); + //System.out.println("ZONE_OFFSET: " + // + (c.get(Calendar.ZONE_OFFSET))); // in hours + //System.out.println("DST_OFFSET: " + // + (c.get(Calendar.DST_OFFSET))); // in hours + + System.out.println("***********************"); + System.out.println(parse(c)); + }*/ +} diff --git a/Modules/mbox/ZZMbox.java b/Modules/mbox/ZZMbox.java new file mode 100644 index 0000000..efa509e --- /dev/null +++ b/Modules/mbox/ZZMbox.java @@ -0,0 +1,742 @@ +/* +ZZMbox.java + * + * Copyright (c) 2000, Ted Nelson, Tuomas Lukka and Vesa Parkkinen + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka and Vesa Parkkinen + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.text.*; // DateFormat +import java.io.*; +import java.awt.*; +import gnu.regexp.*; + +/** A mailbox file reader. + *

    + * AAAAAAAARGGGGGGGGGGHHHHH!!!!!! How to do 8-bit cleanliness and + * internationalization correctly? It's still just a stream of bytes + * that we have underneath. Should probably use encoding when converting + * bytescroll stuff to strings. Gnnnh... + *

    + * The way to test this is: + *

    • Put a path to the mbox to a cell, put right-hand cursor in it and + * execute ZZMbox.READMBOX + *
    + *

    + * TODO:

    • put all headers somewhere (sorted)
    • + *
    • more ways to connect messages (references?)
    • + *
    • smart way to move in threads
    • + *
    + */ + +public class ZZMbox { +public static final String rcsid = "$Id: ZZMbox.java,v 1.32 2000/11/06 12:06:17 ajk Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) ZZLogger.log(s); } + static final void pa(String s) { ZZLogger.log(s); } + + static ZZCell byDate; + static ZZCell bySender; + static ZZCell bySubject; + static ZZCell byId; + + static Hashtable hash = new Hashtable(); + + static public ZZModule module = new ZZModule() { + public void action(String id, ZZCell code, + ZZCell target, + ZZView v, ZZView cv, + String key, Point pt, + ZZScene xi) { + try { + + ZZCell viewCell = v.getViewcell(); + ZZCell viewCursor = ZZCursorReal.get(viewCell); + + p("ZZMbox ACTION!"); + + if(id.equals("CREATEFLOBWINDOW")) { + // paths are: + // + // Date: + // handle -> Date: (d.handle) + // headcell(d.clone, -1) + // d.order +1 + // + // From: same + // Subject: same + + String[] fields = new String[] { + "Subject", "From", "Date", "ARDate" + }; + ZZCell mli = viewCell.getHomeCell().N("d.2", 1); + mli.setText("MailflobDims"); + + ZZCell dlc = mli.N("d.1", 1); + ZZCell odlc = dlc; + + ZZCell[] flobdims = new ZZCell[fields.length]; + + for(int i=0; i= scr.curEnd()) { + i = (int)(scr.curEnd()-offs-1); + } + s = scr.getString(offs, i); + ind = s.indexOf('\n'); + } + if(ind<0 && offs != scr.curEnd()) { + p("Problem: no newline at end!"); + //return null; + s = scr.getString(offs, (int)scr.curEnd()); + offs = scr.curEnd(); + return s; + + } + + s = s.substring(0, ind); // nl not included + offs += ind+1; + return s; + } + + long hlstart; + long hlend; + + String getHdrLine() throws Exception { + //p("Gethdrline"); + hlstart = offs; + long o0 = offs; + String s = getLine(); + if(s.equals("")) { // Start of body + return null; + } + if(startws==null) + startws = new RE("^\\s"); + if(startws.getMatch(s, 0, RE.REG_ANCHORINDEX)!=null) { + throw new ZZError("ARGH! Invalid header"); + } + + while(true) { + o0 = offs; + String extra = getLine(); + if(startws.getMatch(extra, 0, RE.REG_ANCHORINDEX) + == null) break; + s += extra; + p("Hdrline reloop "+extra); + } + //p("Hdrline end "+s); + offs = o0; + hlend = offs-2; + return s; + } + boolean was_empty = false; + String getBodyLine() throws Exception { + p("Getbody"); + long o0 = offs; + String s = getLine(); + if( s == null ) return null; + if(startfrom==null) + startfrom = + new RE("^From (.+) (... ... .. ..:..:.. ....)(.*)"); + if(startfrom.getMatch(s, 0, RE.REG_ANCHORINDEX)!=null && + was_empty) { + p("GETBODY: END BODY " + s); + offs = o0; + return null; + } + p("GETBODYRET: "+s); + if ( s.equals("")){ + was_empty = true; + } else { + was_empty = false; + } + return s; + } + + Span sp(long offs, REMatch m, int i) { + return sp(offs, m.getSubStartIndex(i), + m.getSubEndIndex(i)); + } + Span sp(long offs, long i1, long i2) { + return sp(i1+offs, i2+offs); + } + Span sp(long i1, long i2) { + return Span.create(Address.scrollOffs(scr, i1), + Address.scrollOffs(scr, i2)); + } + + void dohoriz(ZZCell c, long o, REMatch m, int n) { + for(int i=1; i\n"); + writer.write("\n"); + writer.write(target.getText()+"\n"); + writer.write("\n"); + writer.write("\n"); + + writer.write("

    " + target.getText() + "

    \n"); + + if (target.s("d.1", 1) != null) { + writer.write("\n"); + printHtmlTree("d.2", "d.1", "d.clone", target.s("d.1", 1), + writer, 1, 10, 2); + writer.write("\n"); + } + + writer.write("\n"); + writer.write("\n"); + writer.close(); + } else { + pa("UNKNOWN Mind COMMAND "+id); + } + } catch(Exception e) { + e.printStackTrace(); + throw new ZZError(""+e); + } + } + + }; + private static void printTextTree(String dim, String dimTop, ZZCell accursed, + BufferedWriter writer, int start, int end) { + + Vector cells = getAllCells(dim, accursed); + int i = 0; + try { + + while (i < cells.size()) { + if (!((ZZCell)cells.elementAt(i)).getText().equals("")) { + writer.write(/*"
  • "+*/((ZZCell)cells.elementAt(i)).getText()+"\n"); + } + if (((ZZCell)cells.elementAt(i)).s(dimTop, 1) != null) { + for (int j=0; j topics) writer.write("
      \n"); + while (i < cells.size()) { + if (!((ZZCell)cells.elementAt(i)).getText().equals("")) { + if (start > topics) { + writer.write("
    • "); + if (((ZZCell)cells.elementAt(i)).s(dimLink, -1) == null) { + if (((ZZCell)cells.elementAt(i)).s(dimLink, 1) != null) + writer.write(""); + writer.write(((ZZCell)cells.elementAt(i)).getText()); + } else { + writer.write(""); + writer.write(((ZZCell)cells.elementAt(i)).getText()+""); + } + writer.write("\n"); + } else { + writer.write(""); + if (((ZZCell)cells.elementAt(i)).s(dimLink, -1) == null) { + if (((ZZCell)cells.elementAt(i)).s(dimLink, 1) != null) + writer.write(""); + writer.write(((ZZCell)cells.elementAt(i)).getText()); + } else { + writer.write(""); + writer.write(((ZZCell)cells.elementAt(i)).getText()+""); + } + writer.write("\n"); + } + } + if (((ZZCell)cells.elementAt(i)).s(dimTop, 1) != null) { + writer.write("\n"); + if(start < end) printHtmlTree(dim, dimTop, dimLink, ((ZZCell)cells.elementAt(i)).s(dimTop, 1), writer, + start + 1, end, topics); + writer.write("\n"); + } + i++; + } + if (start > topics) writer.write("
    \n"); + } catch (IOException iOE) {} + } + + + + private static Vector getAllCells(String dim, ZZCell accursed) { + int LIMIT = 1000; + Vector cells = new Vector(); + ZZCell next = null; + + cells.addElement(accursed); + + int i = 1; + while (cells.size() < LIMIT ) { + next = accursed.s(dim, i++); + if(next != null && !cells.contains(next)) cells.addElement(next); + else break; + } + return cells; + } +} diff --git a/Modules/mind/MindSun.java b/Modules/mind/MindSun.java new file mode 100644 index 0000000..ac7a473 --- /dev/null +++ b/Modules/mind/MindSun.java @@ -0,0 +1,398 @@ +/* + * MindSun.java + * + * A View for GZZ 0.6.X. + * + * @author asko.soukka@iki.fi + * @version 0.1 + * + * I was not satisfied with MindSundiew view. It wasted too much space + * and still did not show enough information. So, I dropped using full circles. + * Still this view is optimized for cyclic structures. + * + * Copyright (c) 2002 Asko Soukka + * Contains a few parts of CompassView.java (c) 2002 Tuukka Hastrup + * GZigZag is written by Tuomas Lukka + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * See the LICENSE.lgpl for the specific terms of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + */ +/* +To do: + +Commenting code :) (javadoc-spesific) + +*/ + + +package org.gzigzag.module; + +import org.gzigzag.*; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Point; +import java.lang.Math; +import java.util.Vector; + +class MindSun implements FlobView, ZOb { + + /** */ + public static final String rcsid = "$Id: MindSun.java,v 1.1.2.3 2002/02/16 16:33:06 tuukkah Exp $"; + + public MindSun() {} + + /** + * @param + */ + public String readParams(ZZCell c) { return null; }; + + /** + * @param + * @param + * @param + * @param + * @param + */ + public void raster(FlobSet into, FlobFactory fact, ZZCell view, + String[] dims, ZZCell accursed) { + + /** */ + Dimension d = into.getSize(); + int midx = d.width / 2; + int midy = d.height / 2; + int r = d.width / 5; + + /** */ + ZZUtil.showFlobDims(into, fact, view, 3); + + /** */ + Vector cells = getAllCells(dims[1], accursed); + if (cells.size() > 0) { + drawCircle(midx, midy, into, fact, dims[1], cells, r, 1, false); + drawTopCurves(midx, midy, into, fact, dims, cells, r, 1.95 * Math.PI, 2, 4, true); + drawSubCurves(midx, midy, into, fact, dims, cells, r, 0.95 * Math.PI, 2.95 * Math.PI, 2, 3, true); + + /** */ + Dimension c = fact.getSize(null, 1); + int cw = c.width; + int ch = c.height; + + for (int i = 1; i < 4; i++) { + if (accursed.s(dims[2], -i) != null) { + fact.makeFlob(into, accursed.s(dims[2], -i), accursed.s(dims[2], -i), + (float)0.75, midx + x(1.95 * Math.PI, r)-cw/2, midy+y(1.95 * Math.PI, r)-ch/2*(i+1), i+1, + (int)(cw * 0.75), (int)(ch * 0.75)); + } + if (accursed.s(dims[2], i) != null) { + fact.makeFlob(into, accursed.s(dims[2], i), accursed.s(dims[2], i), + (float)0.75, midx + x(1.95 * Math.PI, r)-cw/2, midy+y(1.95 * Math.PI, r)-ch/3+ch/2*i, i+1, + (int)(cw * 0.75), (int)(ch * 0.75)); + } + } + } + } + + /** + * @param + * @param + */ + private Vector getAllCells(String dim, ZZCell accursed) { + /** */ + int LIMIT = 20; + + /** */ + Vector cells = new Vector(); + + /** */ + ZZCell next = null; + + /** */ + cells.addElement(accursed); + + /** */ + int i = 1; + do { + if (cells.size() > LIMIT / 2) break; + next = accursed.s(dim, i++); + if(next != null && !cells.contains(next)) cells.addElement(next); + else break; + } while (true); + + /** */ + i = -1; + do { + if (i < -LIMIT / 2) break; + next = accursed.s(dim, i--); + } while (next != null && !cells.contains(next)); + + /** */ + if (next != accursed) { + i += 2; + do { + if (cells.size() > LIMIT) break; + next = accursed.s(dim, i++); + if(next != null && !cells.contains(next)) cells.addElement(next); + else break; + } while (true); + } + + /** */ + return cells; + } + + /** + * @param + * @param + * @param + * @param + * @param + * @param + * @param + * @param + */ + private void drawTopCurves(int midx, int midy, FlobSet into, FlobFactory fact, String[] dims, Vector cells, + int r, double angle, int startLevel, int endLevel, boolean vanishing) { + /** */ + float factor = (float) (-Math.log(startLevel) / (-Math.log(startLevel)+2.7) + 1); + + /** */ + double angleStep = 2 * Math.PI / cells.size(); + + /** */ + for (int i=0; i= endAngle - angleStep / 3 * 2 + || cells.size()%2 != 0 && angle >= endAngle) + angle = (startAngle + (endAngle - startAngle) / 2) - (cells.size() - (i + 1)) * angleStep; + } + + /** */ + if (backup != null) cells.insertElementAt(backup, 0); + } + + /** + * @param + * @param + * @param + * @param + * @param + * @param + * @param + * @param + */ + private void drawCurve(int midx, int midy, FlobSet into, FlobFactory fact, Vector cells, + double startAngle, double endAngle, int r, int level, boolean vanishing) { + + /** */ + Dimension c = fact.getSize(null, 1); + int cw = c.width; + int ch = c.height; + + /** */ + double angle = startAngle + (endAngle - startAngle) / 2; + + /** */ + int i = 0; + ZZCell backup = null; + + /** */ + if (cells.elementAt(0) != null && ((ZZCell)cells.elementAt(0)).getText().equals("")) { + int dx = x(angle, r-cw/8); + int dy = y(angle, r-cw/8); + float factor = (float)-Math.log(level)/4+1; + fact.makeFlob(into, (ZZCell)cells.elementAt(i), (ZZCell)cells.elementAt(i), + factor, midx + dx-cw/2, midy+dy-ch/2, level+2, (int)(cw * factor), (int)(ch * factor)); + backup = (ZZCell)cells.elementAt(0); + cells.removeElementAt(0); + } + + /** */ + double angleStep; + if (cells.size()%2 == 0) angleStep = (endAngle - startAngle) / (cells.size() + 1); + else angleStep = (endAngle - startAngle) / cells.size(); + + /** */ + while (i < cells.size()) { + int dx = x(angle, r); + int dy = y(angle, r); + + /** */ + float factor; + if (i == 0) factor = (float)(-Math.log(level)/4+1.1); + else factor = (float)-Math.log(level)/4+1; + + if(cells.elementAt(i) != null) + fact.makeFlob(into, (ZZCell)cells.elementAt(i), (ZZCell)cells.elementAt(i), + factor, midx + dx-cw/2, midy+dy-ch/2, level, (int)(cw * factor), (int)(ch * factor)); + + /** */ + if (vanishing) { + if (i < cells.size() / 2) level ++; + else if (i > cells.size() / 2) level --; + } + i++; + + /** */ + angle += angleStep; + if (cells.size()%2 == 0 && angle >= endAngle - angleStep / 3 * 2 + || cells.size()%2 != 0 && angle >= endAngle) + angle = (startAngle + (endAngle - startAngle) / 2) - (cells.size() - i) * angleStep; + } + + /** */ + if (backup != null) cells.insertElementAt(backup, 0); + } + + /** + * @param + * @param + * @param + * @param + * @param + * @param + * @param + * @param + */ + private void drawCircle(int midx, int midy, FlobSet into, FlobFactory fact, String dim, Vector cells, + int r, int level, boolean vanishing) { + + /** */ + LineDecor.Builder line = new LineDecor.Builder(into, Color.red); + line.startl(4, 1); + + /** */ + Dimension c = fact.getSize(null, 1); + int cw = c.width; + int ch = c.height; + + /** */ + double angleStep = 2 * Math.PI / cells.size(); + double angle = (double) 1.95 * Math.PI; + + /** */ + int i = 0; + while (i < cells.size()) { + int dx = x(angle, r); + int dy = y(angle, r); + + /** */ + float factor = (float)-Math.log(level)/4+1; + + if(cells.elementAt(i) != null) +/* fact.centerFlob(into, (ZZCell)cells.elementAt(i), (ZZCell)cells.elementAt(i), + factor, new Point(midx + dx-cw/2, midy+dy-ch/2), 0, 0, level);*/ + fact.makeFlob(into, (ZZCell)cells.elementAt(i), (ZZCell)cells.elementAt(i), + factor, midx + dx-cw/2, midy+dy-ch/2, level, (int)(cw * factor), (int)(ch * factor)); + + /** */ + if (vanishing) { + if (i < cells.size() / 2) level ++; + else if (i > cells.size() / 2) level --; + } + /** */ + angle += angleStep; + + /** */ + if (cells.elementAt(i)!=null && cells.size() > 1) { + if (((ZZCell)cells.elementAt(i)).s(dim, 1) == null) { + line.l(midx+x(angle - angleStep / 2 - 0.01, r-ch)-cw/2, midy+y(angle - angleStep / 2 - 0.01, r-ch)-ch/2, + midx+x(angle - angleStep / 2 - 0.01, r+ch)-cw/2, midy+y(angle - angleStep / 2 - 0.01, r+ch)-ch/2); + line.l(midx+x(angle - angleStep / 2 + 0.01, r-ch)-cw/2, midy+y(angle - angleStep / 2 + 0.01, r-ch)-ch/2, + midx+x(angle - angleStep / 2 + 0.01, r+ch)-cw/2, midy+y(angle - angleStep / 2 + 0.01, r+ch)-ch/2); + } + else if (i < cells.size() - 1) { + if (((ZZCell)cells.elementAt(i)).s(dim, 1) != (ZZCell)cells.elementAt(i+1)) + line.l(midx+x(angle - angleStep / 2, r-ch)-cw/2, midy+y(angle - angleStep / 2, r-ch)-ch/2, + midx+x(angle - angleStep / 2, r+ch)-cw/2, midy+y(angle - angleStep / 2, r+ch)-ch/2); + } else { + if (((ZZCell)cells.elementAt(i)).s(dim, 1) != (ZZCell)cells.elementAt(0)) { + line.l(midx+x(angle - angleStep / 2, r-ch)-cw/2, midy+y(angle - angleStep / 2, r-ch)-ch/2, + midx+x(angle - angleStep / 2, r+ch)-cw/2, midy+y(angle - angleStep / 2, r+ch)-ch/2); + line.l(midx+x(angle - angleStep / 2 + 0.01, r-ch)-cw/2, midy+y(angle - angleStep / 2 + 0.01, r-ch)-ch/2, + midx+x(angle - angleStep / 2 + 0.01, r+ch)-cw/2, midy+y(angle - angleStep / 2 + 0.01, r+ch)-ch/2); + } + } + } + /** */ + i++; + } + + /** */ + line.endl(); + } + + protected int x(double angle, int length) { + return (int)(Math.cos(angle) * length); + } + + protected int y(double angle, int length) { + return (int)(Math.sin(angle) * length); + } +} diff --git a/Modules/mind/MindSundew.java b/Modules/mind/MindSundew.java new file mode 100644 index 0000000..0091aec --- /dev/null +++ b/Modules/mind/MindSundew.java @@ -0,0 +1,247 @@ +/* + * MindSundew.java + * + * Ajatuskihokkipurkkaviritys GZZ 0.6.X:lle. + * Mindmap scribble for GZigZag 0.6.X. + * + * @author asko.soukka@iki.fi + * + * Copyright (C) 2001 Asko Soukka, based on CompassView.java by Tuukka Hastrup + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * See the LICENSE.lgpl for the specific terms of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + */ + +package org.gzigzag.module; + +import org.gzigzag.*; +import java.awt.Dimension; +import java.lang.Math; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.util.Vector; + +class MindSundew implements FlobView, ZOb { + + public static final String rcsid = "$Id: MindSundew.java,v 1.1.2.1 2002/02/16 15:19:25 tuukkah Exp $"; + private int level = 0; + private int levelA = 0; + private int levelB = 0; + + public MindSundew() {} + public String readParams(ZZCell c) { return null; }; + + public void raster(FlobSet into, FlobFactory fact, ZZCell view, + String[] dims, ZZCell accursed) { + + /* ---- alustetaan kaikenlaista ---- */ +// FlobDecorator linker = new StdLinks(); + ZZCell stdim = ZZCursorReal.get(view.s("d.dims", 1)); + + Dimension d = into.getSize(); + int midx = d.width / 2; + int midy = d.height / 2; + Dimension c = fact.getSize(null, 1); + int cw = c.width; + int ch = c.height; + + ZZUtil.showFlobDims(into, fact, view, 3); + /* ---------------------------------------------------- */ + + /* ---- piirretään ulottuvuuksien värit ylänurkkaan ---- */ + LineDecor.Builder line1 = new LineDecor.Builder(into, Color.black); + LineDecor.Builder line2 = new LineDecor.Builder(into, Color.gray); + LineDecor.Builder line3 = new LineDecor.Builder(into, Color.yellow); + + line1.startl(4, 1); + line2.startl(4, 1); + line3.startl(4, 1); + + line1.l(c.width/2, c.height/2, c.width*2, c.height/2); + line2.l(c.width/2, c.height/2, c.width/2, c.height*2); + line3.l(c.width/2, c.height/2, c.width*2, c.height*2); + + line1.endl(); + line2.endl(); + line3.endl(); + /* ---------------------------------------------------- */ + + /* ---- kutsutaan ensimmäistä piirtokierrosta ---- */ + drawLevel(into, fact, dims, accursed, d, c, stdim, midx, midy, cw, ch); + //linker.decorate(into, "", view); + /* ---------------------------------------------------- */ + + } + + private void drawLevel(FlobSet into, FlobFactory fact, String[] dims, ZZCell accursed, + Dimension d, Dimension c, ZZCell stdim, int midx, int midy, int cw, int ch) { + + /* ---- asetetaan piirtokierroksen tasokohtaiset ---- */ + level++; + float kerroin = 1; // käytetään solujen piirtokoossa + if (level > 1) { + kerroin = (float)0.7; + for (int i=2; i= this.x && hy >= this.y && hx < this.x+this.w + && hy < this.y+this.h) return handleCell; + return null; + } + }; + into.add(cf); + return cf; + } + + public Flob placeFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, int x, int y, int depth, float xfract, float yfract) + { + Dimension d = getSize(c, fract); + return makeFlob(into, c, handleCell, fract, + (int)(x-xfract*d.width), (int)(y-yfract*d.height), depth, d.width, d.height); + } + + public Flob centerFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, Point p, int xalign, int yalign, int depth, Dimension d) + { + if (d==null) d = getSize(c, fract); + int x, y; + x = p.x - d.height/2; y = p.y - d.height/2; + if (xalign<0) x = p.x; + if (xalign>0) x = p.x - d.width; + if (yalign<0) y = p.y; + if (yalign>0) y = p.y - d.height; + return makeFlob(into, c, handleCell, fract, x, y, depth, d.width, d.height); + } + + public Flob centerFlob(FlobSet into, ZZCell c, ZZCell handleCell, + float fract, Point p, int xalign, int yalign, int depth) + { + return centerFlob(into, c, handleCell, fract, p, xalign, yalign, depth, null); + } +} +// Local variables: +// tab-width: 4 +// End: diff --git a/Modules/multimedia/MediaFlobView.java b/Modules/multimedia/MediaFlobView.java new file mode 100644 index 0000000..e0c587d --- /dev/null +++ b/Modules/multimedia/MediaFlobView.java @@ -0,0 +1,40 @@ +/* +MediaFlobView.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tero Mäyränen + */ + +package org.gzigzag.module.multimedia; +import org.gzigzag.module.*; +import org.gzigzag.*; +import java.awt.*; + +public class MediaFlobView extends Default implements FlobView +{ + public static final String rcsid = "$Id: MediaFlobView.java,v 1.1 2001/03/05 08:44:14 deetsay Exp $"; + + private MediaFlobFactory mff = new MediaFlobFactory(); + + public void raster(FlobSet into, FlobFactory fact, ZZCell view, java.lang.String[] dims, + ZZCell accursed) + { + mff.placeFlob(into, accursed, accursed, 1, 0, 0, 1, 0, 0); + } +} diff --git a/Modules/multimedia/MediaMath.java b/Modules/multimedia/MediaMath.java new file mode 100644 index 0000000..5ee6368 --- /dev/null +++ b/Modules/multimedia/MediaMath.java @@ -0,0 +1,460 @@ +/* +MediaMath.java + * + * Copyright (c) 2000-2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tero Mäyränen + */ + +package org.gzigzag.module.multimedia; +import org.gzigzag.*; +import java.awt.*; +import java.awt.image.*; +import java.util.*; + +/** + * MediaMath is a collection of MediaZObs that do mathematical functions. + * If at all possible, in the future this should be done with some actual + * mathematical language designed for GZigZag... + */ + +public class MediaMath +{ + public static final String rcsid = "$Id: MediaMath.java,v 1.1 2001/03/05 08:44:14 deetsay Exp $"; + + public abstract class MathZOb extends MediaZOb + { + protected Pixels pix = null; + + protected Vector oldframes = new Vector(); + + /** + * The inputs for these are just lists of MediaZObs connected on d.2, + * unlike the normal way, which is a list of parameter names, which + * in turn are connected to ZObs on d.1........ + */ + protected Vector readInputPixels() + { + Vector v = new Vector(); + Pixels inpix; + ZZCell d = cell; + do + { + inpix = MediaZOb.newMediaZOb(d).getPixels(); + v.addElement(inpix); + d = d.s("d.2"); + } + while ((d != null) && (!d.equals(cell))); + return v; + } + + protected Vector readInputZObs() + { + Vector v = new Vector(); + MediaZOb mz; + ZZCell d = cell; + do + { + mz = MediaZOb.newMediaZOb(d); + v.addElement(mz); + d = d.s("d.2"); + } + while ((d != null) && (!d.equals(cell))); + return v; + } + + /** + * Allocate enough pixels to fit all inputs in their correct coordinate positions. + */ + protected void createPix(Vector inputs) + { + if (inputs.size() < 1) + { + pix = new Pixels(1, 1); + pix.getPixels()[0] = 0xff000000; + return; + } + + Pixels inpix = (Pixels)inputs.elementAt(0); + int w = inpix.getWidth(), h = inpix.getHeight(); + int x = inpix.getX(), y = inpix.getY(); + + for (int i=1; i (w + x)) + { + w = inpix.getWidth() + inpix.getX() - x; + } + if ((inpix.getHeight() + inpix.getY()) > (h + y)) + { + h = inpix.getHeight() + inpix.getY() - y; + } + } + if (pix == null) + { + pix = new Pixels(w, h); + } + else + { + pix.setSize(w, h); + } + pix.setX(x); + pix.setY(y); + } + } + + public class add extends MathZOb + { + public int getInt(int def) + { + Vector inputs = readInputZObs(); + if (inputs.size() < 1) return def; + int S = 0; + for (int i=0; i 0xff0000) r = 0xff0000; + g = (pp & 0xff00) + (ipp & 0xff00); + if (g > 0xff00) g = 0xff00; + b = (pp & 0xff) + (ipp & 0xff); + if (b > 0xff) b = 0xff; + p[pi++] = 0xff000000 | r | g | b; + } + pi += pix.getWidth() - inpix.getWidth(); + } + } + pix.setFrame(pix.getFrame()+1); + return pix; + } + } + + public class and extends MathZOb + { + public int getInt(int def) + { + Vector inputs = readInputZObs(); + if (inputs.size() < 1) return def; + int S = 0xffffffff; + for (int i=0; i> 12) & 0xff0) * ((ipp >> 12) & 0xff0)) & 0xff0000; + g = (((pp >> 8) & 0xff) * ((ipp >> 8) & 0xff)) & 0xff00; + b = ((pp & 0xff) * (ipp & 0xff)) >> 8; + p[pi++] = 0xff000000 | r | g | b; + } + pi += pix.getWidth() - inpix.getWidth(); + } + } + pix.setFrame(pix.getFrame()+1); + return pix; + } + } + + public class or extends MathZOb + { + public int getInt(int def) + { + Vector inputs = readInputZObs(); + if (inputs.size() < 1) return def; + int S = 0; + for (int i=0; i= 0) + { + mz = new image(); + mz.readParams(c); + return mz; + } + } + catch (Exception e) {} + + cc = c.s("d.1"); + + if (cc == null) return null; + + ZZCell macroCell = cc; + cc = macroCell.h("d.clone"); + if (macroCell.equals(cc)) macroCell = null; + + String t = cc.getText(); + int x; + + /* + * This is an unnecessary check just because + * you get some errors if you try newZOb() on an URL :-) + */ + if (t.indexOf("://") >= 0) return null; + + x = t.indexOf('.'); + if (x > 1) try + { + mz = (MediaZOb)ZZModule.getModule(t.substring(0, x)).newZOb(t.substring(x + 1)); + mz.readParams(cc.s("d.1")); + if (macroCell != null) mz.setMacro(macroCell); + return mz; + } + catch (Exception e) {} + + /* + * Mathematical functions are hidden inside MediaMath.. + */ + if (t.equals("+")) { mz = mediaMath.new add(); mz.readParams(cc.s("d.1")); return mz; } + if (t.equals("&")) { mz = mediaMath.new and(); mz.readParams(cc.s("d.1")); return mz; } + if (t.equals("*")) { mz = mediaMath.new mul(); mz.readParams(cc.s("d.1")); return mz; } + if (t.equals("|")) { mz = mediaMath.new or(); mz.readParams(cc.s("d.1")); return mz; } + if (t.equals("%")) { mz = mediaMath.new xor(); mz.readParams(cc.s("d.1")); return mz; } + + return null; + } + + static public MediaZOb newMediaZOb(ZZCell c) + { + MediaZOb mz = newMediaZObNoDefault(c); + if (mz == null) + { + mz = new Default(); + mz.readParams(c); + } + return mz; + } + + /** + * Find a parameter of this cell from the ZZ-structure, and + * return it as a MediaZOb. + * + * @param name is the name of the parameter that you hope to find. + */ + protected MediaZOb readParam(String name) + { + MediaZOb mz = null; + + if (cell == null) return nullZOb; + + mz = readParam(name, cell, null); + + return (mz == null ? nullZOb : mz); + } + + /** + * Recursive part of the previous method + */ + private MediaZOb readParam(String name, ZZCell key, ZZCell first) + { + if ((key == null) || key.equals(first)) return null; + + if (first == null) first = key; + + if ((name != null) && (name.equals(key.getText()))) + { + ZZCell value = key.s("d.1"); + + //------------------------------------------------- + // An acceptable way of passing macro parameters? + + if ((value != null) && (value.getText().equals("param"))) + { + MediaZOb mz = null; + ZZCell parname = value.s("d.1"); + if (parname != null) + { + if (callFrom != null) + mz = readParam(parname.getText(), callFrom.s("d.1"), null); + + if (mz == null) + mz = newMediaZOb(parname.s("d.1")); + + return mz; + } + } + //------------------------------------------------- + return newMediaZOb(value); + } + + return readParam(name, key.s("d.2"), first); + } + + /** + * Contents of cell as text. + * + * @param def Default value. + */ + public String getText(String def) + { + return (cell == null ? def : cell.getText()); + } + + /** + * Contents of cell as integer. + * + * @param def Default value. + */ + public int getInt(int def) + { + String t = getText(""); + // try to parse hex + try { if (t.substring(0, 2).equals("0x")) return Integer.parseInt(t.substring(2), 16); } + catch (Exception e) {} + // try to parse decimal + try { return Integer.parseInt(t); } catch (Exception e) {} + + return def; + } + + public abstract Pixels getPixels(); +} + +// Local variables: +// tab-width: 4 +// End: diff --git a/Modules/multimedia/Pixels.java b/Modules/multimedia/Pixels.java new file mode 100644 index 0000000..cf0fbfe --- /dev/null +++ b/Modules/multimedia/Pixels.java @@ -0,0 +1,163 @@ +/* +Pixels.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tero Mäyränen + */ + +package org.gzigzag.module.multimedia; +import java.awt.*; +import java.awt.image.*; +import java.util.*; + +/** + * The purpose of this class is to be the type of return value + * for MediaZOb's getPixels() method. + * + * @see MediaZOb + */ + +public class Pixels +{ + public static final String rcsid = "$Id: Pixels.java,v 1.2 2001/03/05 08:44:14 deetsay Exp $"; + + private int width, height, x, y; + private int allocatedSize; + private int pixels[]; + + private int frame = 0; + public int getFrame() { return frame; } + public void setFrame(int f) { frame = f; } + + public int getX() { return x; } + public int getY() { return y; } + public int getCenterX() { return x + (width >> 1); } + public int getCenterY() { return y + (height >> 1); } + + public void setX(int a) { x = a; } + public void setY(int a) { y = a; } + public void setCenterX(int a) { x = a - (width >> 1); } + public void setCenterY(int a) { y = a - (height >> 1); } + + public int getWidth() { return width; } + public int getHeight() { return height; } + + private void checkSize() + { + int newsize = width*height; + if (newsize > allocatedSize) + { + pixels = null; + allocatedSize = newsize; + pixels = new int[allocatedSize]; + } + } + public void setSize(int a, int b) + { + width = a; + height = b; + checkSize(); + } + public void setWidth(int a) + { + width = a; + checkSize(); + } + public void setHeight(int a) + { + height = a; + checkSize(); + } + public void setCenterWidth(int a) + { + x += ((width - a) >> 1); + width = a; + checkSize(); + } + public void setCenterHeight(int a) + { + y += ((height - a) >> 1); + height = a; + checkSize(); + } + + public int[] getPixels() { return pixels; } + + /** + * Thanks to this method there's no need to use MemoryImageSource + * to get an Image from pixel data. + */ + public ImageProducer getSource() + { + return new ImageProducer() + { + private Vector imageConsumers = new Vector(); + + public void addConsumer(ImageConsumer ic) + { + if ((ic != null) && (!isConsumer(ic))) + { + imageConsumers.addElement(ic); + } + } + public boolean isConsumer(ImageConsumer ic) + { + return imageConsumers.contains(ic); + } + public void removeConsumer(ImageConsumer ic) + { + imageConsumers.removeElement(ic); + } + public void requestTopDownLeftRightResend(ImageConsumer ic) + { + startProduction(ic); + } + public void startProduction(ImageConsumer ic) + { + addConsumer(ic); + + int i = 0; + ImageConsumer cons; + try + { + while (true) + { + cons = (ImageConsumer)imageConsumers.elementAt(i++); + cons.setDimensions(getWidth(), getHeight()); + cons.setHints(ImageConsumer.TOPDOWNLEFTRIGHT + | ImageConsumer.SINGLEFRAME | ImageConsumer.SINGLEPASS); + cons.setPixels(0, 0, getWidth(), getHeight(), ColorModel.getRGBdefault(), + getPixels(), 0, getWidth()); + cons.imageComplete(ImageConsumer.STATICIMAGEDONE); + } + } + catch (Exception e) {} + } + }; + } + + public Pixels(int w, int h) + { + x = 0; + y = 0; + width = w; + height = h; + pixels = new int[width*height]; + } +} diff --git a/Modules/multimedia/PolygonRenderer.java b/Modules/multimedia/PolygonRenderer.java new file mode 100644 index 0000000..ea47248 --- /dev/null +++ b/Modules/multimedia/PolygonRenderer.java @@ -0,0 +1,61 @@ +/* +PolygonRenderer.java + * + * Copyright (c) 2000-2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tero Mäyränen + */ + +package org.gzigzag.module.multimedia; +import org.gzigzag.*; +import java.awt.*; +import java.awt.image.*; +import java.util.*; + +/** + * unfinished.. + */ + +public class PolygonRenderer extends MediaZOb +{ + public static final String rcsid = "$Id: PolygonRenderer.java,v 1.1 2001/03/05 08:44:14 deetsay Exp $"; + + private Pixels pix; + + public Pixels getPixels() + { + int w = readParam("width").getInt(256); + int h = readParam("height").getInt(256); + if (pix == null) + { + pix = new Pixels(w, h); + } + else + { + pix.setSize(w, h); + } + int p[] = pix.getPixels(); + for (int i=0; i<(w*h); i++) p[i] = 0xff000000; + + /* sort polygons */ + + /* render */ + + return pix; + } +} diff --git a/Modules/multimedia/Polygons.java b/Modules/multimedia/Polygons.java new file mode 100644 index 0000000..3f01109 --- /dev/null +++ b/Modules/multimedia/Polygons.java @@ -0,0 +1,65 @@ +/* +Polygons.java + * + * Copyright (c) 2000-2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tero Mäyränen + */ + +package org.gzigzag.module.multimedia; +import org.gzigzag.*; +import java.awt.*; +import java.awt.image.*; +import java.util.*; + +/** + * unfinished + */ + +public class Polygons +{ + public static final String rcsid = "$Id: Polygons.java,v 1.1 2001/03/05 08:44:14 deetsay Exp $"; + + public class PolyPoint + { + public int x, y, z; + public int tx, ty, ex, ey, bx, by; + } + + public class Polygon + { + public PolyPoint points[]; + + public Polygon() + { + points = new PolyPoint[3]; + } + } + + private PolyPoint points[]; + private Polygon polygons[]; + + public PolyPoint[] getPoints() { return points; } + public Polygon[] getPolygons() { return polygons; } + + public Polygons(int npoints, int npolygons) + { + points = new PolyPoint[npoints]; + polygons = new Polygon[npolygons]; + } +} diff --git a/Modules/multimedia/adjust.java b/Modules/multimedia/adjust.java new file mode 100644 index 0000000..14b5253 --- /dev/null +++ b/Modules/multimedia/adjust.java @@ -0,0 +1,109 @@ +/* +adjust.java + * + * Copyright (c) 2000-2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tero Mäyränen + */ + +package org.gzigzag.module.multimedia; +import org.gzigzag.*; +import java.awt.*; +import java.awt.image.*; +import java.util.*; + +/** + * unfinished + */ + +public class adjust extends MediaZOb +{ + public static final String rcsid = "$Id: adjust.java,v 1.1 2001/03/05 08:44:14 deetsay Exp $"; + + private Pixels pix = null; + + private int oldframe=0, oldradj=0, oldgadj=0, oldbadj=0, oldhadj=0, oldsadj=0, oldbradj=0; + + public Pixels getPixels() + { + Pixels inpix = readParam("input").getPixels(); + + int radj = readParam("red").getInt(100); + int gadj = readParam("green").getInt(100); + int badj = readParam("blue").getInt(100); + + int hadj = readParam("hue").getInt(100); + int sadj = readParam("saturation").getInt(100); + int bradj = readParam("brightness").getInt(100); + + if (pix != null && inpix.getFrame() == oldframe + && radj == oldradj && gadj == oldgadj && badj == oldbadj + && hadj == oldhadj && sadj == oldsadj && bradj == oldbradj) + { + return pix; + } + oldradj = radj; oldgadj = gadj; oldbadj = badj; + oldhadj = hadj; oldsadj = sadj; oldbradj = bradj; + oldframe = inpix.getFrame(); + + int w = inpix.getWidth(); + int h = inpix.getHeight(); + int px = inpix.getX(); + int py = inpix.getY(); + + if (pix == null) + { + pix = new Pixels(w, h); + } + else + { + pix.setSize(w, h); + } + pix.setX(px); + pix.setY(py); + + float hsbvals[] = new float[3]; + int ip[] = inpix.getPixels(); + int pred, pgreen, pblue, prgb; + int op[] = pix.getPixels(); + for (int i=0; i<(w*h); i++) + { + prgb = ip[i]; + pred = ((prgb >> 16) & 0xff) * radj / 100; + pgreen = ((prgb >> 8) & 0xff) * gadj / 100; + pblue = (prgb & 0xff) * badj / 100; + + Color.RGBtoHSB( + (pred > 255 ? 255 : pred), + (pgreen > 255 ? 255 : pgreen), + (pblue > 255 ? 255 : pblue), + hsbvals); + + hsbvals[0] = hsbvals[0] * hadj / 100; + hsbvals[1] = hsbvals[1] * sadj / 100; + hsbvals[2] = hsbvals[2] * bradj / 100; + + op[i] = Color.HSBtoRGB( + (hsbvals[0] > 1 ? 1 : hsbvals[0]), + (hsbvals[1] > 1 ? 1 : hsbvals[1]), + (hsbvals[2] > 1 ? 1 : hsbvals[2])); + } + + return pix; + } +} diff --git a/Modules/multimedia/crop.java b/Modules/multimedia/crop.java new file mode 100644 index 0000000..95c93c6 --- /dev/null +++ b/Modules/multimedia/crop.java @@ -0,0 +1,94 @@ +/* +crop.java + * + * Copyright (c) 2000-2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tero Mäyränen + */ + +package org.gzigzag.module.multimedia; +import org.gzigzag.*; +import java.awt.*; +import java.awt.image.*; +import java.util.*; + +/** + * unfinished + */ + +public class crop extends MediaZOb +{ + public static final String rcsid = "$Id: crop.java,v 1.2 2001/03/05 08:44:14 deetsay Exp $"; + + private Pixels pix = null; + + private int oldframe=0, oldpw=0, oldph=0, oldpx=0, oldpy=0; + + public Pixels getPixels() + { + Pixels inpix = readParam("input").getPixels(); + + int iw = inpix.getWidth(); + int ih = inpix.getHeight(); + int ix = inpix.getX(); + int iy = inpix.getY(); + + int pw = readParam("width").getInt(iw); + int ph = readParam("height").getInt(ih); + int px = readParam("x").getInt(ix); + int py = readParam("y").getInt(iy); + + if (pix != null && inpix.getFrame() == oldframe + && pw == oldpw && ph == oldph && px == oldpx && py == oldpy) + { + return pix; + } + oldpw = pw; oldph = ph; oldpx = px; oldpy = py; oldframe = inpix.getFrame(); + + if (pix == null) + { + pix = new Pixels(pw, ph); + } + else + { + pix.setSize(pw, ph); + } + pix.setX(px); + pix.setY(py); + + int p[] = pix.getPixels(), ip[] = inpix.getPixels(); + int i = 0; + for (int y=py; y= iy + ih)) + { + for (int x=0; x= ix + iw)) p[i++] = 0xff000000; + else p[i++] = ip[ ((y-iy)*iw)+(x-ix) ]; + } + } + } + pix.setFrame(pix.getFrame()+1); + return pix; + } +} diff --git a/Modules/multimedia/dots.java b/Modules/multimedia/dots.java new file mode 100644 index 0000000..6841e8b --- /dev/null +++ b/Modules/multimedia/dots.java @@ -0,0 +1,58 @@ +/* +dots.java + * + * Copyright (c) 2000-2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tero Mäyränen + */ + +package org.gzigzag.module.multimedia; +import org.gzigzag.*; +import java.awt.*; +import java.awt.image.*; +import java.util.*; + +public class dots extends MediaZOb +{ + public static final String rcsid = "$Id: dots.java,v 1.2 2001/03/05 08:44:14 deetsay Exp $"; + + private Pixels pix = null; + + private void plot(int p[], int w, int h, int n) + { + + } + + public Pixels getPixels() + { + if (pix == null) + { + int w = readParam("width").getInt(64); + int h = readParam("height").getInt(64); + int c = readParam("bg").getInt(0); + pix = new Pixels(w, h); + int p[] = pix.getPixels(); + for (int i=0; i<(w*h); i++) + { + p[i] = 0xff000000 | c; + } + plot(p, w, h, readParam("dots").getInt(100)); + } + return pix; + } +} diff --git a/Modules/multimedia/image.java b/Modules/multimedia/image.java new file mode 100644 index 0000000..0d00a9f --- /dev/null +++ b/Modules/multimedia/image.java @@ -0,0 +1,102 @@ +/* +image.java + * + * Copyright (c) 2000-2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tero Mäyränen + */ + +package org.gzigzag.module.multimedia; +import org.gzigzag.*; +import java.awt.*; +import java.awt.image.*; +import java.util.*; +import java.net.*; + +/** Image mediazob. + * Images can be read from a different place by setting the property images.from, + * like + * java -Dimages.from=img:///=file:///home/antkaij/cvs/gzigzag-demo/Java/demospace-lomat.2.zz/ org.gzigzag.Main demospace-lomat.2.zz + */ + +public class image extends MediaZOb +{ + public static final String rcsid = "$Id: image.java,v 1.7 2001/02/28 05:16:55 tjl Exp $"; + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + private static Hashtable convert = null; + private Pixels pix = null; + + private static String doConvert(String str) { + if (convert == null) { + convert = new Hashtable(); + String prop = null; + try { + prop = System.getProperty("images.from"); + } catch(Throwable t) {} + if (prop != null) { + StringTokenizer tok = new StringTokenizer(prop, ";="); + while (tok.hasMoreTokens()) { + String a = tok.nextToken(); + String b = tok.nextToken(); + p(""+a+" => "+b); + convert.put(a, b); + } + } + } + for(Enumeration e = convert.keys(); e.hasMoreElements(); ) { + String from = (String)e.nextElement(); + p(""+str+"; "+from); + if (!str.startsWith(from)) continue; + String to = (String)convert.get(from); + p(""+str+" => "+to + str.substring(from.length())); + str = to + str.substring(from.length()); + return str; + } + p("Not converted: "+str); + return str; + } + public Pixels getPixels() + { + if (pix == null) + { + try + { + URL imgURL = new URL(doConvert(getText(""))); + p("URL: "+imgURL); + Image img = Toolkit.getDefaultToolkit().getImage(imgURL); + int w = img.getWidth(null); + int count = 2000000; + while ((w < 0) && (count-- > 0)) w = img.getWidth(null); + int h = img.getHeight(null); + + pix = new Pixels(w, h); + PixelGrabber pg = new PixelGrabber(img, 0, 0, w, h, pix.getPixels(), 0, w); + pg.grabPixels(); + } + catch (Exception e) {} + } + return pix; + } +} + +// Local variables: +// tab-width: 4 +// End: diff --git a/Modules/multimedia/mm.java b/Modules/multimedia/mm.java new file mode 100644 index 0000000..ce754e1 --- /dev/null +++ b/Modules/multimedia/mm.java @@ -0,0 +1,51 @@ +/* +mm.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tero Mäyränen + */ + +package org.gzigzag.module; +import org.gzigzag.module.multimedia.*; +import org.gzigzag.*; +import java.awt.*; + +/** + * Module for multimedia stuff. + */ +public class mm +{ + static public final String rcsid = "$Id: mm.java,v 1.3 2001/03/05 08:44:14 deetsay Exp $"; + + static public ZZModule module = new ZZModule() + { + public ZOb newZOb(String id) + { + try + { + return (ZOb)Class.forName("org.gzigzag.module.multimedia." + id).newInstance(); + } + catch (Exception e) + { + // ZZLogger.exc(e); + return null; + } + } + }; +} diff --git a/Modules/multimedia/move.java b/Modules/multimedia/move.java new file mode 100644 index 0000000..826cdeb --- /dev/null +++ b/Modules/multimedia/move.java @@ -0,0 +1,70 @@ +/* +move.java + * + * Copyright (c) 2000-2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tero Mäyränen + */ + +package org.gzigzag.module.multimedia; +import org.gzigzag.*; +import java.awt.*; +import java.awt.image.*; +import java.util.*; + +public class move extends MediaZOb +{ + public static final String rcsid = "$Id: move.java,v 1.2 2001/03/05 08:44:14 deetsay Exp $"; + + Pixels pix = null; + + private int oldframe=0, oldx=0, oldy=0; + + public Pixels getPixels() + { + Pixels inpix = readParam("input").getPixels(); + int x = readParam("x").getInt(0); + int y = readParam("y").getInt(0); + if (pix != null && inpix.getFrame() == oldframe && x == oldx && y == oldy) + { + return pix; + } + oldframe = inpix.getFrame(); oldx = x; oldy = y; + + int w = inpix.getWidth(); + int h = inpix.getHeight(); + + if (pix == null) + { + pix = new Pixels(w, h); + } + else + { + pix.setSize(w, h); + } + + pix.setX(inpix.getX() + x); + pix.setY(inpix.getY() + y); + + int p[] = pix.getPixels(), ip[] = inpix.getPixels(); + for (int i=0; i + +Multimedia module + + + + + +

    1. How to use MediaZObs

    + + + +

    2. How to use macros

    + +To define a macro: +
      +
    • Just use the MediaZOb you want to use ("mm.rect" below).

    • +
    • Replace some of the parameters with the word "param" :-)

    • +
    • To the cell next from "param" on "d.1" write the name of your +parameter. ("mywidth" below)

    • +
    • Optional: To the cell next on "d.1" write a default value.

    • +
    + + + +To use a macro: +
      +
    • Clone the name of the MediaZOb...

    • +
    • Give the clone some of the parameters you have used in your +macro definition.

    • +
    + + diff --git a/Modules/multimedia/rect.java b/Modules/multimedia/rect.java new file mode 100644 index 0000000..6ade2e0 --- /dev/null +++ b/Modules/multimedia/rect.java @@ -0,0 +1,122 @@ +/* +rect.java + * + * Copyright (c) 2000-2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tero Mäyränen + */ + +package org.gzigzag.module.multimedia; +import org.gzigzag.*; +import java.awt.*; +import java.awt.image.*; +import java.util.*; + +public class rect extends MediaZOb +{ + public static final String rcsid = "$Id: rect.java,v 1.4 2001/03/05 08:44:14 deetsay Exp $"; + + private Pixels pix = null; + + private int fade(int x, int fg, int bg) + { + int y = 0xff-x; + return 0xff000000 + | (((((fg & 0xff0000) * x) + ((bg & 0xff0000) * y)) >> 8) & 0xff0000) + | (((((fg & 0xff00) * x) + ((bg & 0xff00) * y)) >> 8) & 0xff00) + | (((((fg & 0xff) * x) + ((bg & 0xff) * y)) >> 8) & 0xff); + } + + private int oldw=0, oldh=0, oldbg=0, oldfg=0, oldstarsize=0; + private String oldmode=""; + + public Pixels getPixels() + { + int w = readParam("width").getInt(64); + int h = readParam("height").getInt(64); + int bg = readParam("bg").getInt(0); + int fg = readParam("fg").getInt(0xffffff); + int starsize = readParam("size").getInt(16); + if (starsize==0) starsize=1; + String mode = readParam("fillmode").getText("solid"); + + if (pix != null && oldw==w && oldh==h && oldbg==bg && oldfg==fg + && oldstarsize==starsize && mode.equals(oldmode)) + { + return pix; + } + oldw=w; oldh=h; oldbg=bg; oldfg=fg; oldstarsize=starsize; oldmode=mode; + + if (pix == null) + { + pix = new Pixels(w, h); + } + else + { + pix.setSize(w, h); + } + + int p[] = pix.getPixels(); + if (mode.equals("solid")) + { + for (int i=0; i<(w*h); i++) + { + p[i] = 0xff000000 | fg; + } + } + if (mode.equals("starburst")) + { + // älä optiomoi, vaihda algoritmia + int w2 = w >> 1; + int h2 = h >> 1; + int i = 0, j; + for (int y=-h2; y 0xff) j = 0xff; + p[i++] = fade(j, bg, fg); + } + } + } + if (mode.equals("radial")) + { + int w2 = w >> 1; + int h2 = h >> 1; + int i = 0, j = w, i2 = w*h, j2 = (w*h)-w, k; + for (int y=-h2; y<0; y++) + { + for (int x=-w2; x<0; x++) + { + k = ((int)(Math.atan(((double)x) / y) * 128 / Math.PI)) & 0x3f; + p[i++] = fade(k, bg, fg); + p[--j] = fade(k, fg, bg); + p[--i2] = fade(k | 0x80, bg, fg); + p[j2++] = fade(k | 0x80, fg, bg); + } + i += w2; + j += w + w2; + i2 -= w2; + j2 -= w + w2; + } + } + pix.setFrame(pix.getFrame()+1); + return pix; + } +} diff --git a/Modules/multimedia/sin.java b/Modules/multimedia/sin.java new file mode 100644 index 0000000..2ead486 --- /dev/null +++ b/Modules/multimedia/sin.java @@ -0,0 +1,42 @@ +/* +sin.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tero Mäyränen + */ + +package org.gzigzag.module.multimedia; +import org.gzigzag.module.*; +import org.gzigzag.*; +import java.awt.*; + +/** + */ + +public class sin extends Default +{ + public static final String rcsid = "$Id: sin.java,v 1.1 2001/03/05 08:44:14 deetsay Exp $"; + + public int getInt(int def) + { + int a = ((int)System.currentTimeMillis()) >> 7; + return ((int)(Math.sin(((double)a * readParam("speed").getInt(64)) / (Math.PI * 100)) + * readParam("amplitude").getInt(16))) + readParam("bias").getInt(64); + } +} diff --git a/Modules/nile/Nile1.java b/Modules/nile/Nile1.java new file mode 100644 index 0000000..15f3428 --- /dev/null +++ b/Modules/nile/Nile1.java @@ -0,0 +1,327 @@ +/* +Nile1.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.awt.*; +import java.io.*; + +/** A stream with parallel markup. + *

    + * Character-level formatting is currently done using B and I (as in HTML, + * for bold and italics). These are placed in cells whose headcell + * on d.nile-fmt-start is the cell in the stream that the + * markup starts from. Likewise, their headcell on d.nile-fmt-end + * is the last cell that does have this markup. + * This is a bit fragile with reordering but most effects can be limited by + * knowing that all formats are allowed to touch only things inside a paragraph + * and we can run a fixer script every once in a while. + *

    + * Paragraph-, section- and chapter -level markup is done by cells + * that say the level: P, H1..H6 on the dimension + * d.nile-struct. These are interpreted by the space part + * so that the HOP operation can be used to move things around easily. + * For higher-than-paragraph level sectioning, the part starting at + * the section, up to the next paragraph or section is considered the + * heading. + * So, in

    H1 foo H2 bar P ab H2 zzz P cd
    , + * the headings would be foo, bar and zzz. + */ + +public class Nile1 { +public static final String rcsid = "$Id: Nile1.java,v 1.10 2001/01/26 13:53:27 ajk Exp $"; + public static boolean dbg = false; + static void p(String s) { if(dbg) System.out.println(s); } + static void pa(String s) { System.out.println(s); } + + static public ZZModule module = new ZZModule() { + public void action(String id, + ZZCell code, + ZZCell target, + ZZView view, ZZView cview, String key, Point pt, ZZScene xi) { + ZZUpdateManager.setFast(view); + + ZZCell viewCell = view.getViewcell(); + ZZCell otherCell = viewCell.s("d.nile-wins"); + + boolean split = false; + ZZCell viewAcc = ZZCursorReal.get(viewCell); + ZZCell leftCell = viewAcc.s("d.nile-pair", -1); + ZZCell rightCell = viewAcc.s("d.nile-pair"); + if(leftCell != null || rightCell != null) { + split = true; + + if(leftCell != null) { + rightCell = viewAcc; + viewCell = rightCell; + otherCell = leftCell; + } else { + leftCell = viewAcc; + viewCell = leftCell; + otherCell = rightCell; + } + } + + p("Nile action: id: '"+id+"' key: '"+key+"' code: "+code); + + StringTokenizer st = new StringTokenizer(id); + String[] toks = new String[st.countTokens()]; + for(int i=0; i 1) { + if(toks[1].equals("+")) dir = 1; + else if(toks[1].equals("-")) dir = -1; + + if(toks.length > 2) { + if(toks[2].equals("CHAR")) + unit = new Nile2Unit.Char(); + else if(toks[2].equals("WORD")) + unit = new Nile2Unit.Word(); + else if(toks[2].equals("SENT")) + unit = new Nile2Unit.Sentence(); + else if(toks[2].equals("PARA")) + unit = new Nile2Unit.Paragraph(); + } + } + + id = toks[0]; + + if(id.equals("Cursor")) { + p("Cursor: "+dir); + Nile2Ops.moveCursor(unit, viewCell, dir); + ZZUpdateManager.setFast(null); + } + else if(id.equals("AdjLeft")) { + Nile2Ops.adjust(unit, viewCell, -1, dir); + ZZUpdateManager.setFast(null); + } + else if(id.equals("AdjRight")) { + Nile2Ops.adjust(unit, viewCell, 1, dir); + ZZUpdateManager.setFast(null); + } + else if(id.equals("Hop")) { + Nile2Ops.hop(unit, viewCell, dir); + } + else if(id.equals("Mode")) { + Nile2Ops.setCursor(unit, viewCell, null); + if(split) + Nile2Ops.setCursor(unit, otherCell, null); + } + else if(id.equals("Insert")) { + Nile2Ops.insert(viewCell, key); + + // Set the selection of other half to char mode, too + if(split) + Nile2Ops.setCursor(new Nile2Unit.Char(), otherCell, null); + } + else if(id.equals("BackSpace")) { + Nile2Ops.backspace(unit, viewCell); + } + else if(id.equals("Delete")) { + Nile2Ops.del(unit, viewCell); + } + else if(id.equals("BreakParagraph")) { + Nile2Ops.breakParagraph(unit, viewCell); + } + else if(id.equals("Tunnel")) { + if(otherCell != null) { + Nile2Ops.tunnel(unit, otherCell, viewCell, dir, false); + } + } + else if(id.equals("Transcopy")) { + if(otherCell != null) { + Nile2Ops.tunnel(unit, otherCell, viewCell, dir, true); + } + } + else if(id.equals("PUICopy")) { + ZZCell c = ZZCursorReal.get(viewCell); + String s = Nile2Ops.stringify(c); + ZZUtil.puiCopy(s); + } +/* + else if(id.equals("TraverseTranscopies")) { + Nile2Ops.traverseTranscopies(viewCell, dir); + } +*/ + + Object ob = null; + if(pt != null) + ob = xi.getObjectAt(pt.x, pt.y); + + if(id.equals("MouseSetCursor")) { + p("Setting cursor from mouse! Unit: "+unit); + if(split) { + // Brute force: was the click in left window half? + if(pt.x < ((FlobSet)xi).getSize().width/2) { + viewCell = leftCell; otherCell = rightCell; + } else { + viewCell = rightCell; otherCell = leftCell; + } + ZZCursorReal.set(view.getViewcell(), viewCell); + } + Nile2Ops.setCursor(unit, viewCell, (ZZCursor)ob); + } + } + + public ZOb newZOb(String id) { + if(id.equals("Normal")) { + return new Nile1View(); + } else if(id.equals("Parallel")) { + return new SplitNileView(); + } + return null; + } + }; + + + // This is really hacky part... + static ZZCell curAct; + static void a(String key, String act) { a(key, act, null); } + static void a(String key, String act, ZZCell next) { + curAct = curAct.N("d.2", 1); + curAct.setText(key); + ZZCell n = curAct.N("d.1", 1); + n.setText("Nile1." + act); + if(next != null) + next.insert("d.3", 1, n); + } + + static void actions(ZZCell start) { + start.setText("Nile char"); + ZZCell nchar = start; + ZZCell nword = nchar.N("d.1", 1); nword.setText("Nile word"); + ZZCell nsent = nword.N("d.1", 1); nsent.setText("Nile sent"); + ZZCell npara = nsent.N("d.1", 1); npara.setText("Nile para"); + + ZZCell ncommon = npara.N("d.1", 1); ncommon.setText("Nile common"); + + curAct = nword; + // Annoying - these should be structurally + // describable!!! + a("MouseClicked1", "MouseSetCursor 0 WORD"); + a("Backspace", "BackSpace 0 WORD"); + a("Delete", "Delete 0 WORD"); + a("Alt-Backspace", "Delete 0 WORD"); + a("Ctrl-P", "Tunnel - WORD"); // P for pull + a("Ctrl-T", "Transcopy - WORD"); + a("Left", "Cursor - WORD"); + a("Right", "Cursor + WORD"); + a("Shift-Left", "AdjLeft - WORD"); + a("Shift-Right", "AdjRight + WORD"); + a("Ctrl-Left", "AdjRight - WORD"); + a("Ctrl-Right", "AdjLeft + WORD"); + a("Alt-Left", "Hop - WORD"); + a("Alt-Right", "Hop + WORD"); + a("Enter", "BreakParagraph 0 WORD"); + + a("Up", "Cursor - SENT"); + a("Down", "Cursor + SENT"); + a("Alt-Up", "Hop - SENT"); + a("Alt-Down", "Hop + SENT"); + + a("INSERT", "Insert", nchar); + a("Tab", "Mode 0 SENT", nsent); + + curAct = nsent; + a("MouseClicked1", "MouseSetCursor 0 SENT"); + a("Backspace", "BackSpace 0 SENT"); + a("Delete", "Delete 0 SENT"); + a("Alt-Backspace", "Delete 0 SENT"); + a("Ctrl-P", "Tunnel - SENT"); // P for push + a("Ctrl-T", "Transcopy - SENT"); + a("Left", "Cursor - SENT"); + a("Right", "Cursor + SENT"); + a("Shift-Left", "AdjLeft - SENT"); + a("Shift-Right", "AdjRight + SENT"); + a("Ctrl-Left", "AdjRight - SENT"); + a("Ctrl-Right", "AdjLeft + SENT"); + a("Alt-Left", "Hop - SENT"); + a("Alt-Right", "Hop + SENT"); + a("Enter", "BreakParagraph 0 SENT"); + + a("Up", "Cursor - PARA"); + a("Down", "Cursor + PARA"); + a("Alt-Up", "Hop - PARA"); + a("Alt-Down", "Hop + PARA"); + + a("INSERT", "Insert", nchar); + a("Tab", "Mode 0 CHAR", nchar); + +/* + curAct = npara; + a("MouseClicked1", "MouseSetCursor 0 PARA"); + a("Backspace", "BackSpace 0 PARA"); + a("Delete", "Delete 0 PARA"); + a("Alt-Backspace", "Delete 0 PARA"); + a("Left", "Cursor - PARA"); + a("Right", "Cursor + PARA"); + a("Shift-Left", "AdjLeft - PARA"); + a("Shift-Right", "AdjRight + PARA"); + a("Ctrl-Left", "AdjRight - PARA"); + a("Ctrl-Right", "AdjLeft + PARA"); + a("Alt-Left", "Hop - PARA"); + a("Alt-Right", "Hop + PARA"); + + a("INSERT", "Insert"); + a("Tab", "Mode 0 CHAR", nchar); + */ + + curAct = nchar; + a("MouseClicked1", "MouseSetCursor 0 CHAR"); + a("Left", "Cursor - CHAR"); + a("Right", "Cursor + CHAR"); + a("Backspace", "BackSpace 0 CHAR"); + a("Delete", "Delete 0 CHAR"); + a("Alt-Backspace", "Delete 0 CHAR"); + a("INSERT", "Insert"); + a("Tab", "Mode 0 WORD", nword); + a("Enter", "BreakParagraph 0 CHAR"); + + a("Ctrl-C", "PUICopy 0 CHAR"); + + a("Up", "Cursor - WORD"); + a("Down", "Cursor + WORD"); + + } + + static String[][] actions = { + { "MouseClicked1", "Nile1.MouseSetCursor" }, + { "Left", "Nile1.Cursor -" }, + { "Right", "Nile1.Cursor +" }, + { "Shift-Left", "Nile1.AdjLeft -" }, + { "Shift-Right", "Nile1.AdjRight +" }, + { "Ctrl-Left", "Nile1.AdjRight -" }, + { "Ctrl-Right", "Nile1.AdjLeft +" }, + { "Alt-Left", "Nile1.Hop -" }, + { "Alt-Right", "Nile1.Hop +" }, + + { "INSERT", "Nile1.Insert" } + }; + +} + + +// vim: set syntax=java : diff --git a/Modules/nile/Nile1Div.java b/Modules/nile/Nile1Div.java new file mode 100644 index 0000000..f576dd4 --- /dev/null +++ b/Modules/nile/Nile1Div.java @@ -0,0 +1,71 @@ +/* +Nile1Div.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; + +/** A representation of a particular way of dividing up the nile stream. + * For instance, words, sentences, clauses, paragraphs or user-specified + * split points could be represented this way. + * It is allowed to have an non-zero-width break between the divisions. + *

    + * It is assumed that no elements will be zero-width. + */ + +public interface Nile1Div { +String rcsid = "$Id: Nile1Div.java,v 1.1 2000/11/20 17:36:13 tjl Exp $"; + + /** Find the next break. + * To iterate, over breaks, pass the start2 returned + * from the previous iteration + * as start to the next and set includeThis to false. + *

    + * An important property here is that the stream may be cut + * at any location returned in end2. + * + * @param start The location to start from + * @param dir The direction to move into, 1 or -1. + * @param includeThis Whether to exclude the break where + * @param start2 The cursor to store the start of the next break in. + * @param end2 The cursor to store the end of the next break in. + * @return true if next break found. + */ + boolean findBreak(ZZCursor start, + int dir, boolean includeThis, + ZZCursor start2, ZZCursor end2); + + /** Cut the stream at a boundary specified + * by this division. + * @param start An end of a break. This MUST have been returned by + * findBreak as start2 or end2. + */ + + /** Splice two pieces of the stream, so that between them a division + * of this level is maintained. + */ + ZZCell splice(ZZCell p1, ZZCell p2); +} + + + + diff --git a/Modules/nile/Nile1GenTreeModel.java b/Modules/nile/Nile1GenTreeModel.java new file mode 100644 index 0000000..7497e0a --- /dev/null +++ b/Modules/nile/Nile1GenTreeModel.java @@ -0,0 +1,81 @@ +/* +Nile1GenTreeModel.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; + +/** The nile1 structural model for GenTreePart. + * This implements the nile1 structural model from H1 to P levels as a + * tree using GenTreePart. + * @see GenTreePart + */ + +public class Nile1GenTreeModel implements GenTreePartModel { +public static final String rcsid = "$Id: Nile1GenTreeModel.java,v 1.3 2000/11/22 00:35:41 tjl Exp $"; + public static boolean dbg = true; + final static void p(String s) { if(dbg) System.out.println(s); } + final static void pa(String s) { System.out.println(s); } + + public int depth() { + return 7; + } + + public int depth(ZZCell c) { + if(c.s("d.nile-struct", -1) == null) return -1; + return Nile1Ops.getLevel(c); + } + + public ZZCell getNext(int mindepth, ZZCell c, int steps) { + if(steps == 0) return c; + c = c.s("d.nile-struct", -1); + int dir = (steps > 0 ? 1 : -1); + ZZCell lasthdr = null; + while(steps != 0 && c != null) { + c = c.s("d.nile", dir); + if(c == null) return null; + lasthdr = c.s("d.nile-struct", 1); + if(lasthdr == null) continue; + if(depth(lasthdr) < mindepth) continue; + steps -= dir; + } + if(c == null) return null; + return lasthdr; + } + + public void disconnectNeg(ZZCell c) { + p("Model: disconnectneg "+c); + c.s("d.nile-struct", -1).disconnect("d.nile", -1); + } + + public void connect(ZZCell c, ZZCell d) { + p("Model: connect "+c+" "+d); + c.s("d.nile-struct", -1).h("d.nile", 1).connect("d.nile", + d.s("d.nile-struct", -1)); + } + + public void setDepth(ZZCell c, int d) { + if(depth(c) < 0) return; + Nile1Ops.setLevel(c, d); + } + +} diff --git a/Modules/nile/Nile1Ops.java b/Modules/nile/Nile1Ops.java new file mode 100644 index 0000000..d804132 --- /dev/null +++ b/Modules/nile/Nile1Ops.java @@ -0,0 +1,479 @@ +/* +Nile1Ops.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; + +/** A library of routines for operating on Nile1 streams. + * @see Nile1 + * @deprecated Use Nile2Ops. + */ + +public abstract class Nile1Ops { +public static final String rcsid = "$Id: Nile1Ops.java,v 1.16 2000/12/07 00:37:19 tjl Exp $"; + public static boolean dbg = true; + static void p(String s) { if(dbg) System.out.println(s); } + static void pa(String s) { System.out.println(s); } + + /** Split the given cell into two at the offset offset. + * The original cell will remain the first. + * Returns the cell that is after the split. + * If offset is zero or greater than or equal to the number of characters + * in c, nothing is done and either the current cell or the next cell is + * returned. + *

    + * The most special case involves doing this at the very end of the stream, + * in which case an empty new cell is created and returned. + * @param c The cursor to split at + * @param always Whether to split even if the offset is at the beginning + * or end of a cell. Used e.g. for inserting a paragraph. + * @return Never null. + */ + static public ZZCell split(ZZCursor c, boolean always) { + // XXX Adjust cursors!!! + ZZCell c0 = c.get(); + int offs = c.getOffs(); + if(always) { + ZZCell c1 = c0.N("d.nile"); + String s = c0.getText(); + c0.setText(s.substring(0, offs)); + c1.setText(s.substring(offs)); + return c1; + } else { + if(offs == 0) return c0; + if(offs == c0.getText().length()) + return c0.getOrNewCell("d.nile"); + return split(c, true); + } + } + + /** Break a paragraph at the given position. + * Returns the first cell of the (possibly empty) new paragraph. + */ + static public ZZCell breakParagraph(ZZCursor c) { + ZZCell n = split(c, true); + if(n.s("d.nile-struct") != null) + throw new ZZError("split structure already!"); + ZZCell str = n.N("d.nile-struct"); + setStrLevel(str, 0); + return n; + } + + /** Change the structural level of a paragraph. + * @param c Any cell in the paragraph - does not need to be the first. + * @param level The new level. + */ + static public void setLevel(ZZCell c, int level) { + ZZCell para = findStruct(c, -1, true); + ZZCell str = para.s("d.nile-struct"); + if(str == null) return; + setStrLevel(str, level); + } + + /** Get the level of a paragraph. + * @param c Any cell in the paragraph - does not need to be the first. + */ + static public int getLevel(ZZCell c) { + ZZCell para = findStruct(c, -1, true); + ZZCell str = para.s("d.nile-struct"); + if(str == null) return 6; + return getStrLevel(str); + } + + /** Insert the given string into the stream at cursor. + */ + static public void insert(ZZCursor c, String txt) { + throw new ZZError("Not implemented"); + } + + + + + /** The level of structure the given structure cell is. + * Note that the levels are a bit interesting: it returns + * zero for paragraphs, 1 for H6, 2 for H5 and so on. + * -1 is returned for cells that are not at a structural border. + */ + static int getStrLevel(ZZCell str) { + String txt = str.getText(); + if(txt.equals("MP")) // Middle of paragraph - special level. + return -1; + if(txt.equals("P")) + return 0; + if(txt.equals("H1")) + return 6; + if(txt.equals("H2")) + return 5; + if(txt.equals("H3")) + return 4; + if(txt.equals("H4")) + return 3; + if(txt.equals("H5")) + return 2; + if(txt.equals("H6")) + return 1; + throw new ZZError("Invalid nile-struct "+txt); + } + + static String[] levels = new String[] { + "P", "H6", "H5", "H4", "H3", "H2", "H1" + }; + + /** Set the level of a structural cell. + */ + static void setStrLevel(ZZCell str, int level) { + if(level < 0 || level > levels.length) + throw new ZZError("Request to set invalid level! "+level); + str.setText(levels[level]); + } + + /** Find an angle in the rank, i.e.the next cell on a rank with + * a connection into a certain direction. + */ + static ZZCell findAngle(ZZCell c, String dim, int dir, + String adim, int adir, boolean includeThis) { + LoopDetector ld = new LoopDetector(); + if(includeThis && c.s(adim, adir) != null) return c; + c = c.s(dim, dir); + while(c != null) { + if(c.s(adim, adir) != null) return c; + ld.detect(c); + c = c.s(dim, dir); + } + return null; + } + + /** Find the next or previous cell that is a structural level element. + */ + static ZZCell findStruct(ZZCell c, int dir, boolean includeThis) { + ZZCell ret = findAngle(c, "d.nile", dir, "d.nile-struct", 1, includeThis); + if(ret == null && dir == -1) { + if(!includeThis && c.s("d.nile", -1) == null) + return null; + return c.h("d.nile", -1); + } + return ret; + } + + /** An editing mode, i.e.the definition of what are the breaks + * that are being operated on in this mode. + */ + public interface Mode { + /** Set the mode cursor, and possibly selection cursor, to the + * given cursor. + * This is called in response to e.g. mouse click, so the position + * may be adjusted to the beginning of the previous unit. + */ + void setCursor(ZZCell view, ZZCursor c); + + /** Move the cursor nsteps units. + */ + void moveCursor(ZZCell view, int nsteps); + + /** Extend/shrink the selection by n units in given direction. + */ + void adjust(ZZCell view, int end, int nsteps); + + /** Hop the selection. + */ + void hop(ZZCell view, int nsteps); + + /** Delete the current selection, move cursor backwards or forwerds. + */ + // void delete(ZZCell view, int movedir); + } + + public static class EdgeMode implements Mode { + Nile1Text.Edger edger; + EdgeMode(Nile1Text.Edger edger) { this.edger = edger; } + + public void setCursor(ZZCell view, ZZCursor c) { + Stream.Iterator iter = giter(c); + edger.edge(iter, true, -1, Nile1Text.START); + curs(view).set(iter.get()); + edger.edge(iter, false, 1, Nile1Text.END); + endcurs(view).set(iter.get()); + } + // Move from end of area if forwards, from start if backwards. + public void moveCursor(ZZCell view, int nsteps) { + if(nsteps <= 0) { + Stream.Iterator iter = giter(curs(view)); + if(!edger.edge(iter, false, nsteps, Nile1Text.START)) + return; + curs(view).set(iter.get()); + edger.edge(iter, false, 1, Nile1Text.END); + endcurs(view).set(iter.get()); + } else { + Stream.Iterator iter = giter(endcurs(view)); + if(!edger.edge(iter, false, nsteps, Nile1Text.END)) + return; + endcurs(view).set(iter.get()); + edger.edge(iter, false, -1, Nile1Text.START); + curs(view).set(iter.get()); + } + } + public void adjust(ZZCell view, int end, int nsteps) { + ZZCursor c1 = curs(view); + ZZCursor c2 = endcurs(view); + if(end < 0) { + Stream.Iterator iter = Stream.getIterator(c1, "d.nile"); + if(!edger.edge(iter, false, nsteps, Nile1Text.START)) + return; + ZZCursor curs = iter.get(); + if(!isOrdered(curs, c2)) return; + c1.set(curs); + } else { + Stream.Iterator iter = Stream.getIterator(c2, "d.nile"); + if(!edger.edge(iter, false, nsteps, Nile1Text.END)) + return; + ZZCursor curs = iter.get(); + if(!isOrdered(c1, curs)) return; + c2.set(curs); + } + // XXX Check that they do not cross... + } + public void hop(ZZCell view, int nsteps) { + p("Cut out the selection for hop"); + ZZCell selec = cutSelection(view); + if(selec == null) return; + + ZZCursor c1 = curs(view); + + p("Now, find place to paste at hopped location"); + Stream.Iterator iter = Stream.getIterator(c1, "d.nile"); + edger.edge(iter, false, nsteps, Nile1Text.START); + c1.set(iter.get()); + p("And paste"); + paste(view, selec, true); + + } + } + static Mode wordmode = new EdgeMode(new Nile1Text.WordEdger()); + static Mode sentencemode = new EdgeMode(new Nile1Text.SentenceEdger()); + + static public Mode getMode(ZZCell view) { + // return wordmode; + return sentencemode; + } + + // XXX + static ZZCell adjStart(ZZCell c, int adj) { + if(adj > 0) { + // XXX Easily screws up font change! + ZZCursor c1 = new ZZCursorVirtual(c, 0); + if(!Stream.move(c1, "d.nile", adj)) + throw new ZZError("ARRRRGH!"); + if(c1.get().equals(c)) { + c.setText(c.getText().substring(adj)); + } else { + c = split(c1, false); + c.disconnect("d.nile", -1); + } + } else if(adj < 0) { + // XXX Spans + String s = ""; + while(adj++ < 0) s = s + " "; // XXX + ZZCell n = c.N("d.nile", -1); + n.setText(s); + } + return c; + } + + static ZZCell adjEnd(ZZCell c, int adj) { + if(adj > 0) { + ZZCursor c1 = new ZZCursorVirtual(c, c.getText().length()); + if(!Stream.move(c1, "d.nile", -adj)) + throw new ZZError("ARRRRGH!"); + // XXX + + c = c1.get(); + c.setText(c.getText().substring(0, c1.getOffs())); + c.disconnect("d.nile", 1); + } else if(adj < 0) { + c.setText(c.getText()+" "); + } + return c; + } + + static void adjustSelection(Stream.Iterator start, Stream.Iterator end) { + Nile1Text.wordEdge(start, true, 1, Nile1Text.START); + Nile1Text.wordEdge(end, true, -1, Nile1Text.END); + } + + static ZZCell cutSelection(ZZCell view) { + ZZCursor curs1 = curs(view); + + p("Cut"); + dump(curs1.get()); + + ZZCursor curs2 = endcurs(view); + if(!isOrdered(curs1, curs2)) return null; + Stream.Iterator iter1 = Stream.getIterator(curs1, "d.nile"); + Stream.Iterator iter2 = Stream.getIterator(curs2, "d.nile"); + int[] adj = new int[2]; + Nile1Text.adjustCut(iter1, iter2, adj); + ZZCursor c1 = iter1.get(); + ZZCursor c2 = iter2.get(); + + ZZCell after = split(c2, false); + p("\nAFTER SPLIT:"); + dump(after); + + ZZCell first = split(c1, false); + p("\nFIRST SPLIT:"); + dump(first); + + + ZZCell prev = first.s("d.nile", -1); + ZZCell last = after.s("d.nile", -1); + after.disconnect("d.nile", -1); + first.disconnect("d.nile", -1); + + if(prev != null) prev.connect("d.nile", after); + + p("AFTER RECONNECT"); + dump(prev); + + curs(view).set(after); + curs(view).setOffs(0); + + // Now, if more characters need to be left out, do it. + first = adjStart(first, adj[0]); + last = adjEnd(last, adj[1]); + if(adj[1] != 0) throw new ZZError("End adj not implemented"); + + p("AFTER CUTADJ"); + dump(first); + + return first; + } + + /** Paste the given stream into the given cursor. + * The range and the text are adjusted for word-by-word + * insertion. + * @param view The viewcell that gives the location to + * paste into. Used later to set the new range, + * if desired. + * @param what The first cell of the stream to paste in. + * @param setRange Whether to set the selection of the given + * view to the pasted range afterwards. + */ + static void paste(ZZCell view, ZZCell what, boolean setRange) { + + ZZCursor v = curs(view); + + p("PASTE"); + dump(v.get()); + p("PASTING WHAT"); + dump(what); + + int[] adj = new int[2]; + Stream.Iterator to = Stream.getIterator(v, "d.nile"); + Stream.Iterator start = giter(new ZZCursorVirtual(what, 0)); + ZZCell last = what.h("d.nile", 1); + Stream.Iterator end = giter(new ZZCursorVirtual(last, + last.getText().length())); + + Nile1Text.adjustPaste(to, start, end, adj); + + what = adjStart(start.get().get(), adj[0]); + adjEnd(end.get().get(), adj[1]); + + p("WHAT ADJUSTED"); + dump(what); + + ZZCell after = split(v, false); + ZZCell before = after.s("d.nile", -1); + after.disconnect("d.nile", -1); + after.connect("d.nile", -1, what.h("d.nile", 1)); + if(before != null) + before.connect("d.nile", 1, what); + + if(setRange) { + v.set(what); + v.setOffs(0); + + start = giter(v); + + ZZCursor ev = endcurs(view); + ev.set(after); + ev.setOffs(0); + + end = giter(ev); + + adjustSelection(start, end); + + v.set(start.get()); + ev.set(end.get()); + } + + p("AFTER EVERYTHING"); + dump(what); + } + + // XXX Should use the tree for help... + static public boolean isOrdered(ZZCursor cu1, ZZCursor cu2) { + ZZCell c1 = cu1.get(); + ZZCell c2 = cu2.get(); + if(c1 == null || c2 == null) return false; + if(c1.equals(c2)) + return cu1.getOffs() <= cu2.getOffs(); + for(; c1 != null && !c1.equals(c2); c1 = c1.s("d.nile")); + if(c1 == null) return false; + return (c1.equals(c2)); + } + + // Shorthand... + static public ZZCursorReal curs(ZZCell view) { + return new ZZCursorReal(view); + } + static public Stream.Iterator giter(ZZCursor c) { + return Stream.getIterator(c, "d.nile"); + } + + static public ZZCursorReal endcurs(ZZCell view) { + ZZCell end = view.getOrNewCell("d.nile-sel"); + return new ZZCursorReal(end); + } + + static public void dump(ZZCell start) { + if(start == null) { + pa("Nile stream Null start!"); + return; + } + ZZCell init = start.h("d.nile", -1); + pa("Nile stream! "+start); + boolean first = true; + for(ZZCell c = init; c != null; c=c.s("d.nile")) { + pa((c.s("d.nile-struct") != null ? "***S*** " : " ") + + " Cell "+c+" "+ + (c.equals(start) ? " <----------------START" : "")); + if(!first && c.equals(init)) { + pa(" WAS A LOOOOOOOP!!!!!!!!!!"); + throw new ZZFatalError("LOOPING NILE STREAM! BAD BAD TROUBLE!"); + } + first = false; + } + } + +} diff --git a/Modules/nile/Nile1Text.java b/Modules/nile/Nile1Text.java new file mode 100644 index 0000000..52b30e3 --- /dev/null +++ b/Modules/nile/Nile1Text.java @@ -0,0 +1,356 @@ +/* +Nile1Text.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; + +/** A library of routines for operating on streams with Nile1 text model. + * @see Nile1 + * @deprecated Use Nile2Unit + */ + +public abstract class Nile1Text { +public static final String rcsid = "$Id: Nile1Text.java,v 1.9 2000/12/07 00:37:19 tjl Exp $"; + public static boolean dbg = true; + static void p(String s) { if(dbg) System.out.println(s); } + static void pa(String s) { System.out.println(s); } + + // Stream.Iterator iter = Stream.getIterator(start, "d.nile"); + + static public int START = 1; + static public int END = -1; + static public int ANY = 0; + + static boolean isWordBreak(Stream.Iterator iter, int edge) { + char cur = iter.getChar(); + if(cur == -1) return true; + if(!iter.move(-1)) return true; + char prev = iter.getChar(); + iter.move(1); + return isWordBreak(prev, cur, edge); + } + + static boolean isWordBreak(char prev, char cur, int edge) { + boolean ret = isWordBreak0(prev, cur, edge); + p("IsWordBreak: '"+prev+"' '"+cur+"' "+edge+ " RETURNING: "+ret); + return ret; + } + static boolean isWordBreak0(char prev, char cur, int edge) { + boolean curlet = Character.isLetterOrDigit(cur); + boolean curws = Character.isWhitespace(cur); + boolean prevlet = Character.isLetterOrDigit(prev); + boolean prevws = Character.isWhitespace(prev); + + if(!curlet && !curws) { + if(edge != END) return true; // punctuation -> break start + return prevlet || !prevws; // punct -> br end if prev ltr or punct + } + if(prevlet && curlet) return false; + if(prevlet && curws) return edge != START; + // --> prevlet == false + if(!prevws) { // previous was punctuation -> + if(edge != START) return true; + return curlet; // Starting edge only if this is a letter. + } + if(prevws && curws) return false; + if(prevws && curlet) return edge != END; + // shouldn't get here + throw new ZZError("isWordBreak logic error!"); + } + + /** Find the nsteps:th next wordbreak. + * Always alters iter. + *

    + * Characters are split into three categories: + * letter-or-digit, whitespace and other. + * whitespace is always a word boundary (but there is no + * word boundary between two whitespace characters). + * The characters in the other category are words by themselves. + * So basically there is a word break at character c, if + *

      + *
    • c is the first character in the stream. + *
    • c is one beyond the last character in the stream + *
    • c is punctuation + *
    • c is of a different category (see above) than + * the character just before it. + *
    + * @param nsteps The number of steps, a positive or negative number. + * @param edge Which edge of the word do we want: START, END or ANY. + */ + static public boolean wordEdge(Stream.Iterator iter, + boolean includeThis, int nsteps, + int edge) { + if(nsteps == 0) throw new ZZError("Can't step 0 words"); + int dir = (nsteps > 0 ? 1 : -1); + for(; nsteps != 0; nsteps -= dir) { + if(!wordEdge0(iter, includeThis, dir, edge)) + return false; + includeThis = false; + } + return true; + } + + static private boolean wordEdge0(Stream.Iterator iter, + boolean includeThis, int dir, + int edge) { + char prev = 0; + char cur = iter.getChar(); + + if(dir > 0) { + if(includeThis) { + if(!iter.move(-dir)) return true; + prev = iter.getChar(); + iter.move(dir); + if(isWordBreak(prev, cur, edge)) return true; + } + while(iter.move(dir)) { + prev = cur; + cur = iter.getChar(); + if(cur == -1) return true; // Ran into end of text. + if(isWordBreak(prev, cur, edge)) return true; + } + return (edge != START); + } else { + if(!includeThis) { + if(!iter.move(dir)) return false; + cur = iter.getChar(); + } + while(iter.move(dir)) { + prev = cur; + cur = iter.getChar(); + if(isWordBreak(cur, prev, edge)) { + iter.move(-dir); + return true; + } + } + return (edge != END); + } + } + + static public boolean sentenceEdge(Stream.Iterator iter, + boolean includeThis, int nsteps, int edge) { + if(nsteps == 0) throw new ZZError("Can't step 0 words"); + int dir = (nsteps > 0 ? 1 : -1); + for(; nsteps != 0; nsteps -= dir) { + if(!sentenceEdge0(iter, includeThis, dir, edge)) + return false; + includeThis = false; + } + return true; + } + + static public boolean sentenceEdge0(Stream.Iterator iter, + boolean includeThis, int dir, int edge) { + if(edge == 0) + throw new ZZError("Looking for either sentence edge not implemented"); + if(edge == START) { + // If we cannot move, we're at the beginning. + if(!iter.move(-1)) + if(dir < 0 || includeThis) return includeThis; + // Back out + iter.move(1); + // Back up two, one by one, and then search non-inclusive. + iter.move(-1); + iter.move(-1); + if(iter.find(dir, includeThis, " ")) { + iter.move(2); + return true; + } else { + // There is a start in the beginning, but not at the end. + iter.end(dir); + return (dir < 0); + } + } else { + if(!iter.move(1)) return includeThis; + iter.move(-1); + // Here we just find because end is at the found text + if(iter.find(dir, includeThis, " ")) + return true; + else { + iter.end(dir); + // There is an end in the end, but not at the beginning. + return (dir > 0); + } + } + } + + static boolean ws(char c) { return Character.isWhitespace(c); } + static boolean punct(char c) { + return (!Character.isWhitespace(c)) && (!Character.isLetterOrDigit(c)); + } + static boolean lett(char c) { return Character.isLetterOrDigit(c); } + + /** Adjust the locations to cut text from. + * Basically, cut one or two spaces after the latter location, + * and if none, and there is a single space preceding, + * cut it along. + *

    + * @param leaveout An output parameter: the values in the two-member + * array are set to the number of characters + * to leave out of the cut text. + * An important meaning is given to negative + * values: a negative value means "add this many + * spaces". + */ + static public void adjustCut(Stream.Iterator iter1, + Stream.Iterator iter2, + int[] leaveout) { + leaveout[0] = leaveout[1] = 0; + // First off, do not adjust if one of them is not word end. + if(!isWordBreak(iter1, START) || !(isWordBreak(iter2, END))) return; + + char c1 = iter2.getChar(0); + char c2 = iter2.getChar(1); + + // If there are one or two spaces afterwards, cut them along. + if(ws(c1)) { + iter2.move(1); + if(ws(c2)) + iter2.move(1); + } else { + // If there is one character before... + char b1 = iter1.getChar(-1); + char b2 = iter1.getChar(-2); + if(ws(b1) && !ws(b2)) { + // This is a tricky situation. What we have here is + // cutting off in + // word WORD, word + // without the comma. + // The space before WORD needs to be removed. + // This is what the leaveout means. + // + // Additionally, for pasting at the correct boundary + // to work right, we need to add a space *after* this + // word when pasting. See adjustPaste. + iter1.move(-1); + leaveout[0] = 1; + } + } + } + + /** The adjustment to a paste operation. + * @param adjust Analogour to the leaveout parameter of + * adjustCut. Positive values mean + * leaving this many characters out + * and negative values mean + * adding that many spaces. + */ + static public void adjustPaste(Stream.Iterator to, + Stream.Iterator start, + Stream.Iterator end, + int[] adjust) { + adjust[0] = adjust[1] = 0; + if(!isWordBreak(to, START)) return; + + // If to is at a letter-punct edge, make sure + // pasted text starts with space and does not end with one. + // Otherwise, make sure it ends with space but doesn't start + // with it. + + char c1 = to.getChar(-1); + char c2 = to.getChar(0); + if(lett(c1) && punct(c2)) { + // Now, start but don't end with space. + if(!ws(start.getChar(0))) adjust[0] = -1; + if(ws(end.getChar(-1))) adjust[1] = 1; + } else { + if(ws(start.getChar(0))) adjust[0] = 1; + if(!ws(end.getChar(-1))) adjust[1] = -1; + } + } + + static public boolean paragraphEdge(Stream.Iterator iter, + boolean includeThis, int nsteps, int edge) { + if(nsteps == 0) throw new ZZError("Can't step 0 paragraphs"); + int dir = (nsteps > 0 ? 1 : -1); + for(; nsteps != 0; nsteps -= dir) { + if(!paragraphEdge0(iter, includeThis, dir, edge)) + return false; + includeThis = false; + } + return true; + } + + static public boolean paragraphEdge0(Stream.Iterator iter, + boolean includeThis, int dir, int edge) { + ZZCell c = iter.get().get(); + int offs = iter.get().getOffs(); + boolean beg = (offs == 0); + boolean end = (offs == c.getText().length()); + if(edge == 0) + throw new ZZError("Can't look for paragraph end / begin"); + // XXX Should we set the end edge to point to negative + // direction? + // if(edge == START) { + if(dir > 0) { + if(!beg || !includeThis) c = c.s("d.nile"); + } else { + if(beg && !includeThis) c = c.s("d.nile", -1); + } + // Now we can go on, using includeThis always. + if(c == null) return false; + c = Nile1Ops.findStruct(c, dir, true); + if(c != null) { + iter.set(new ZZCursorVirtual(c, 0)); + if(edge == START) + iter.move(0, 1); + else + iter.move(0, -1); + return true; + } else { + if(edge == END && dir > 0) { + iter.end(); return true; + } + return false; + } + // } + } + + + public interface Edger { + boolean edge(Stream.Iterator iter, boolean includeThis, int nsteps, + int whichEdge); + } + + static public class WordEdger implements Edger { + public boolean edge(Stream.Iterator iter, boolean includeThis, + int nsteps, int whichEdge) { + return wordEdge(iter, includeThis, nsteps, whichEdge); + } + } + + static public class SentenceEdger implements Edger { + public boolean edge(Stream.Iterator iter, boolean includeThis, + int nsteps, int whichEdge) { + return sentenceEdge(iter, includeThis, nsteps, whichEdge); + } + } + + static public class ParagraphEdger implements Edger { + public boolean edge(Stream.Iterator iter, boolean includeThis, + int nsteps, int whichEdge) { + return paragraphEdge(iter, includeThis, nsteps, whichEdge); + } + } + +} diff --git a/Modules/nile/Nile1View.zob b/Modules/nile/Nile1View.zob new file mode 100644 index 0000000..a1ece1b --- /dev/null +++ b/Modules/nile/Nile1View.zob @@ -0,0 +1,311 @@ +/* +Nile1View.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.awt.*; +import java.io.*; + +/** A view for nile streams. + */ + +public class Nile1View implements FlobView, ZOb { +public static final String rcsid = "$Id: Nile1View.zob,v 1.4 2001/01/26 13:53:27 ajk Exp $"; + public static boolean dbg = false; + static void p(String s) { if(dbg) System.out.println(s); } + static void pa(String s) { System.out.println(s); } + + + STRUCTPARAMS { + /** The default font to use. + */ + Font font + = new Font("SansSerif", Font.PLAIN, 11); + + /** The distance between paragraphs. + */ + int paraskip + = 8; + + /** The left-side margin for normal text. + * Headings hang left of this margin. + */ + int lmargin + = 50; + + ZOb ftextlayouter + = new FTextLayouter(); + + /** Whether to use a special color for span (transcluded) cells. */ + boolean showcopy + = false; + } + + /** Bold and italic derivatives of the font given. + * The first index is the level of the text i.e. + * from paragraph to H1. + */ + Font[][][] bifonts; + FontMetrics[][][] bifontms; + + INITIALIZE { + bifonts = new Font[7][2][2]; + bifontms = new FontMetrics[7][2][2]; + for(int l = 0; l < bifonts.length; l++) { + int size = font.getSize(); + if(l > 0 && l < 5) size += l-1; + if(l == 5) size += 6; + if(l == 6) size += 9; + bifonts[l][1][0] = new Font(font.getName(), + Font.BOLD, size); + bifonts[l][1][1] = new Font(font.getName(), + Font.BOLD | Font.ITALIC, size); + + if(l == 0) { + bifonts[l][0][0] = new Font(font.getName(), 0, size); + bifonts[l][0][1] = new Font(font.getName(), + Font.ITALIC, size); + } else { // All bold for headers + bifonts[l][0][0] = bifonts[l][1][0]; + bifonts[l][0][1] = bifonts[l][1][1]; + } + for(int b = 0; b<2; b++) + for(int i = 0; i<2; i++) + bifontms[l][b][i] = FONTMETRICS(bifonts[l][b][i]); + } + } + + Color selcolor = Color.white; + Color copycolor = Color.yellow.darker().darker().darker().darker(); + + /** Return the formatted text object for one paragraph. + */ + FText paragraph(ZZCell start, ZZCell endBefore, ZZCursor offsetOfC, + int[]into, + ZZCursor selectEnd) + { + p("Paragraph! "+start+" "+endBefore+" "); + ZZCell selsc = null; + int selso = 0; + if(offsetOfC != null) { + selsc = offsetOfC.get(); + selso = offsetOfC.getOffs(); + } + ZZCell offsetOf = selsc; + ZZCell selec = null; + int seleo = 0; + if(selectEnd != null) { + selec = selectEnd.get(); + seleo = selectEnd.getOffs(); + } + boolean selected = (selsc == null && selec != null); + + if(selso == ZZCursor.NO_OFFSET || selec == null) { + selsc = null; + selec = null; + selected = false; + } + + FText.Part part = null; + + int level = Nile2Iter.getLevel(start); + int curOffs = 0; + int b = 0, i = 0; + Vector parts = new Vector(); + LoopDetector ld = new LoopDetector(); + LoopDetector ld2 = new LoopDetector(); + for(ZZCell c = start; c != null && c != endBefore; c = c.s("d.nile")) { + ld.detect(c); + for(ZZCell fs = c.s("d.nile-fmt-start"); fs != null; + fs = fs.s("d.nile-fmt-start")) { + ld.detect(fs); + if(fs.getText().equals("B")) b++; + else if(fs.getText().equals("I")) i++; + else p("Invalid format: "+fs.getText()); + } + int b0 = (b > 0 ? 1 : 0); + int i0 = (i > 0 ? 1 : 0); + int len = c.getText().length(); + + if(c == offsetOf && into != null) into[0] = curOffs; + int internoffs = 0; + if(c == selsc) { + if(selso > len) { + ZZLogger.log("Warning: start over length "+selso+" "+len); + selso = len; + } + part = new FText.CellPart( c, 0, selso, + bifonts[level][b0][i0], bifontms[level][b0][i0], + null, c.getSpan() == null ? null : copycolor); + parts.addElement(part); + internoffs = selso; + selected = true; + p("Start selection: "+selso+" "+selsc); + } + if(c == selec && seleo >= internoffs) { + if(seleo > len) { + ZZLogger.log("Warning: end over length "+seleo+" "+len); + seleo = len; + } + part = new FText.CellPart( c, internoffs, seleo-internoffs, + bifonts[level][b0][i0], bifontms[level][b0][i0], + selcolor, c.getSpan() == null ? null : copycolor); + parts.addElement(part); + internoffs = seleo; + selected = false; + selectEnd.set((ZZCell)null); + p("End selection: "+seleo+" "+selec); + } + + part = new FText.CellPart( c, internoffs, len-internoffs, + bifonts[level][b0][i0], bifontms[level][b0][i0], + selected ? selcolor : null, + c.getSpan() == null ? null : copycolor); + + parts.addElement(part); + curOffs += len; + + for(ZZCell fe = c.s("d.nile-fmt-end"); fe != null; + fe = fe.s("d.nile-fmt-start")) { + ld2.detect(fe); // Can't use same: same cell is start&end + if(fe.getText().equals("B")) b--; + else if(fe.getText().equals("I")) i--; + else p("Invalid format: "+fe.getText()); + } + } + return new FText(parts); + } + + Rectangle pmarg(Rectangle r, ZZCell para) { + int level = Nile2Iter.getLevel(para); + Rectangle ret = new Rectangle(r); + int w = (6 - level) * lmargin / 6; + ret.x += w; ret.width -= w; + return ret; + } + + boolean[] beginningSentence = new boolean[2]; + public Rectangle placeParagraph(FlobSet into, + FText ft, ZZCell para,Rectangle origrect, + int direction, int initY, int middleOffs) { + beginningSentence[0] = true; + beginningSentence[1] = false; + // Margins. + Rectangle rect = pmarg(origrect, para); + Rectangle ret = ((FTextLayouter)ftextlayouter).place(into, ft, rect, + 1, + direction, initY, middleOffs, false, + beginningSentence); + // Now, do the cool thing with the section headings: include + // previous and next section headings of the same level here. + if(Nile2Iter.getLevel(para) > 0) { + + ZZCell strcell = para.s("d.nile-struct"); + if(strcell == null) return ret; + + for(int dir = -1; dir <= 1; dir += 2) { + ZZCell prevsec = strcell.s("nile1str:breadth",dir); + if(prevsec == null) continue; + prevsec = prevsec.h("nile1str:depth").s("d.nile-struct", -1); + if(prevsec == null) continue; + beginningSentence[0] = true; + beginningSentence[1] = false; + FText nft = paragraph(prevsec, Nile2Iter.findStruct(prevsec, 1, false), + null, null, null); + ((FTextLayouter)ftextlayouter).place(into, nft, rect, 200, + dir, ret.y + (dir < 0 ? 0 : ret.height), + 0, false, beginningSentence); + } + } + return ret; + } + + + public void raster(FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed) { + int[] offs = new int[1]; + + LoopDetector ld = new LoopDetector(); + + ZZCursor selectEnd = null; + ZZCell sele = view.s("d.nile-sel"); + if(sele != null) { + selectEnd = ZZCursorVirtual.createFromReal(sele); + } + + // Do the center paragraph first. + ZZCell firstpara = Nile2Iter.findStruct(accursed, -1, true); + ZZCell nextpara = Nile2Iter.findStruct(accursed, 1, false); + + FText ft = paragraph(firstpara, nextpara, new ZZCursorReal(view), + offs, selectEnd); + + Dimension size = into.getSize(); + Rectangle rect = new Rectangle(0, 0, size.width, size.height); + + Rectangle ctr = placeParagraph(into, ft, firstpara, rect, + 0, rect.y+rect.height/2, + ZZCursorReal.getVisualTextOffset(view)); + + // Go into positive direction. + Rectangle r = ctr; + while(nextpara != null) { + ld.detect(nextpara); + ZZCell next = Nile2Iter.findStruct(nextpara, 1, false); + ft = paragraph(nextpara, next, null, null, selectEnd); + + r = placeParagraph(into, ft, nextpara, rect, + 1, r.y+r.height + paraskip, 0); + + nextpara = next; + + if(r.y + r.height > size.height) break; + } + + // And negative. + r = ctr; + while(true) { + ZZCell prev = firstpara; + firstpara = Nile2Iter.findStruct(firstpara, -1, false); + if(firstpara == null) break; + ld.detect(firstpara); + + ft = paragraph(firstpara, prev, null, null, null); + + beginningSentence[0] = true; + r = placeParagraph(into, ft, firstpara, rect, + -1, r.y - paraskip, 0); + + if(r.y < 0) break; + } + // into.dump(); + Flob cursf = into.findFlob(null, accursed); + // p("Cursf: "+cursf); + if(cursf != null) + ((SplitCellFlob1)cursf).addCurs(into, ZZCursorReal.getOffs(view), + Color.red); + } +} + + +// vim: set syntax=java : diff --git a/Modules/nile/Nile2Iter.java b/Modules/nile/Nile2Iter.java new file mode 100644 index 0000000..3dcc7c3 --- /dev/null +++ b/Modules/nile/Nile2Iter.java @@ -0,0 +1,589 @@ +/* +Nile2Iter.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag.module; +import org.gzigzag.*; + +/** A character-level iterator object that knows about + * paragraphs for a Nile stream. + * This object explicitly assumes no modifications to the + * stream while it is working. + */ + +public final class Nile2Iter implements Cloneable { +public static final String rcsid = "$Id: Nile2Iter.java,v 1.8 2000/12/20 22:26:35 bfallenstein Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + private ZZCell c; + private int offs; + + // Cache these for speed. + private String ctext; + private int clen; + + private void load(ZZCell c) { + this.c = c; + ctext = c.getText(); + clen = ctext.length(); + } + + private void load(ZZCell c, int offs) { + load(c); + if(offs == -1) this.offs = clen; + else this.offs = offs; + move(0); + } + + private void reload() { + load(c); + move(0); + } + + static private boolean isStruct(ZZCell c) { + if(c == null) + throw new ZZError("Null isStruct?"); + return c.s("d.nile-struct") != null; + } + + Nile2Iter() { } + public Nile2Iter(ZZCursor curs) { set(curs); } + + public void set(ZZCursor curs) { + load(curs.get()); + this.offs = curs.getOffs(); + // Ensure positive bias. + move(0); + } + + public void set(Nile2Iter iter) { + load(iter.c); + offs = iter.offs; + } + + /** Move n characters forwards or backwards within the current + * paragraph. + * If the offset given is out of bounds, moves as far as possible + * and returns false, otherwise returns true. + */ + public boolean move(int n) { + n += offs; + offs = 0; + + // Internally, we like to maintain positive bias always. + // Thus, the greater-OR-EQUALS sign. + while(n >= clen) { + n -= clen; + ZZCell nc = c.s("d.nile"); + if(nc == null || isStruct(nc)) { + // Only situation for negative bias: end of paragraph. + offs = clen; + if(n > 0) return false; + return true; + } + load(nc); + } + while(n < 0) { + ZZCell nc = c.s("d.nile", -1); + if(nc == null || isStruct(nc)) { + offs = 0; + return false; + } + load(nc); + n += clen; + } + + offs = n; + return true; + } + + /** Get the character at current offset. + * Returns -1 if out of bounds. + */ + public int cur() { + if(offs >= clen || offs < 0) return -1; + return ctext.charAt(offs); + } + public int get() { return cur(); } + + public int next() { + if(!move(1)) return -1; + return cur(); + } + + public int prev() { + if(!move(-1)) return -1; + return cur(); + } + + public int get(int at) { + ZZCell cache = c; + int offscache = offs; + int ret = -1; + if(move(at)) { + ret = cur(); + } + if(c != cache) + load(cache); + offs = offscache; + return ret; + } + + /** Move n paragraphs, moving as little as possible. + * This means that if we move backwards, we will be at the end + * of the paragraph and vice versa. + */ + public boolean shiftPara(int n) { + // XXX What about empty paragraphs? A LOT of trouble... + if(n == 0) return true; + int dir = (n > 0 ? 1 : -1); + ZZCell nc = c; + while(n != 0) { + nc = nc.s("d.nile", dir); + if(nc == null) return false; + if(isStruct(nc)) n -= dir; + } + // Now we are at the paragraph cell. + // Need to take one step. + nc = nc.s("d.nile", dir); + if(nc == null) { + return false; // XXX Should set position! + // throw new ZZError("AUGH! Para shifting null next"); + } + load(nc); + offs = (dir < 0 ? clen : 0); + return true; + } + + /** Shift to paragraph beginning or end. + */ + public boolean paraEnd(int dir) { + ZZCell nc = c; + ZZCell prev = nc; + while(nc != null && !isStruct(nc)) { + prev = nc; + nc = nc.s("d.nile", dir); + } + if(nc == null) { + nc = prev; + } else { + nc = nc.s("d.nile", -dir); + } + load(nc); + offs = (dir < 0 ? 0 : clen); + return true; + } + + public void streamEnd(int dir) { + // XXX When going to beginning, may set pos to struct! + ZZCell h = c.h("d.nile", dir); + paraEnd(dir); + } + + /** Get the current position with given bias. + * @param bias Whether we are looking into positive or negative + * direction. If the cursor is at an edge, + * this affects which cell is returned. + */ + public ZZCursor getCursor(int bias) { + // XXX Check para? + if(bias < 0 && offs == 0) { + ZZCell nc = c.s("d.nile", -1); + return new ZZCursorVirtual(nc, nc.getText().length()); + } + return new ZZCursorVirtual(c, offs); + } + public ZZCursor getCursor() { return getCursor(1); } + + + /** Cut the stream at this location. + * This pointer remains pointing to the prior space, + * and it returns a iter at the beginning of the new stream. + */ + public Nile2Iter cut() { + move(0); + Nile2Iter ni = new Nile2Iter(); + if(offs == 0) { + ZZCell prev = c.getOrNewCell("d.nile", -1); + prev.disconnect("d.nile", 1); + ni.load(c, 0); + load(prev); + offs = clen; + return ni; + } + if(offs == clen) { // must be very end. + ZZCell next = c.getOrNewCell("d.nile", 1); + ni.load(next, 0); + c.disconnect("d.nile", 1); + return ni; + } + ZZCell spl = split(c, offs, true); + c.disconnect("d.nile", 1); + reload(); + ni.load(spl, 0); + return ni; + } + + // XXX Cursors easily cut out! + + public void join(Nile2Iter to) { + c.h("d.nile", 1).connect("d.nile", to.c.h("d.nile", -1)); + reload(); + } + + public void adjustSpaceStart(int nstart) { + if(dbg) dumpStream(); + Nile2Iter ctr = (Nile2Iter)clone(); + int ncur = 0; + while(Nile2Unit.ws(ctr.get())) { + ncur ++; ctr.move(1); + } + if(nstart < ncur) { + move(ncur-nstart); + // XXX Cursors could go wild. + set(cut()); + } else if(nstart > ncur) { + StringBuffer buf = new StringBuffer(); + while(nstart-- > ncur) buf.append(' '); + ZZCell n = c.N("d.nile", -1); + n.setText(buf.toString()); + load(n, 0); + } + } + + public void adjustSpaceEnd(int nend) { + + Nile2Iter ctr = (Nile2Iter)clone(); + ctr.streamEnd(1); + int ncur = 0; + while(Nile2Unit.ws(ctr.get(-1))) { + ncur ++; ctr.move(-1); + } + if(nend < ncur) { + ctr.move(nend); // Move back forwards. + // XXX Cursors could go wild. + ctr.cut(); + } else if(nend > ncur) { + StringBuffer buf = new StringBuffer(); + while(nend-- > ncur) buf.append(' '); + ZZCell n = ctr.c.h("d.nile", 1).N("d.nile", 1); + n.setText(buf.toString()); + } + if(dbg) dumpStream(); + } + + public void adjustSpaces(int nstart, int nend) { + p("Adjustspaces: "+nstart+" "+nend); + adjustSpaceStart(nstart); + adjustSpaceEnd(nend); + + } + + public Object clone() { + try { + return super.clone(); + } catch(CloneNotSupportedException e) { + ZZLogger.exc(e); + return null; + } + } + + public void dumpStream() { + pa("Dumping Nile2Iter stream: at offs: "+offs); + dump(c); + } + + /** Returns true if this <= it. + * Throws an error if not in same stream. + */ + public boolean isOrdered(Nile2Iter it) { + if(c.equals(it.c)) { + return offs <= it.offs; + } else { + if(c.findCell("d.nile", 1, it.c)) return true; + if(!c.findCell("d.nile", -1, it.c)) + throw new ZZError("IsOrdered: not on same stream!"); + return false; + } + } + + public void insertInCell(String s) { + ZZCell spl = split(c, offs, true); + spl = spl.N("d.nile", -1); + spl.setText(s); + load(spl, -1); + } + + public void insert(String str) { + ZZCell n = c; + if(isStruct(c)) { + load(c.s("d.nile"), -1); + ZZCell d = n.N("d.nile"); + d.setText(str); + ZZLogger.log("AUGH! Insert at struct cell!"); + // throw new ZZError("Inserting"); + } else if((offs == 0 || offs == clen) && c.getSpan() == null) { + if(offs == clen) { + c.setText(c.getText() + str); + load(c, -1); + } else { // In this case, this iter doesn't move ;) + ZZCell prev = c.s("d.nile", -1); + if(isStruct(prev) || prev == null) + c.N("d.nile", -1).setText(str); + else + prev.setText(prev.getText() + str); + } + } else { + if(offs > 0 && offs < clen) split(c, offs, false); + ZZCell d = c.N("d.nile", offs > 0 ? 1 : -1); + d.setText(str); + load(d, -1); + } + } + + /** Make a cell's content into a span. */ + static public Span spanify(ZZCell c0) { + Span sp = c0.getSpan(); + if(sp != null) return sp; + + StringScroll sc = c0.getSpace().getStringScroll(); + String s = c0.getText(); + long soffs = sc.append(s); + sp = Span.create( + Address.scrollOffs(sc, soffs), + Address.scrollOffs(sc, soffs + s.length() - 1) + ); + c0.setSpan(sp); + return sp; + } + + /** Split the given cell into two at the offset offset. + * The original cell will remain the first. + * Returns the cell that is after the split. + * If offset is zero or greater than or equal to the number of characters + * in c, nothing is done and either the current cell or the next cell is + * returned. + *

    + * The most special case involves doing this at the very end of the stream, + * in which case an empty new cell is created and returned. + * @param c The cursor to split at + * @param always Whether to split even if the offset is at the beginning + * or end of a cell. Used e.g. for inserting a paragraph. + * @return Never null. + */ + static public ZZCell split(ZZCell c0, int offs, boolean always) { + // XXX Adjust cursors!!! + if(always) { + ZZCell c1 = c0.N("d.nile"); + if(c0.s("d.nile-transcluded") != null) { + c0.insert("d.nile-transcluded", 1, c1); + c0.insert("d.nile-transcluded-split", 1, c1); + } + Span sp = c0.getSpan(); + if(sp == null) { + String s = c0.getText(); + c0.setText(s.substring(0, offs)); + c1.setText(s.substring(offs)); + } else { + c0.setSpan(sp.subSpan(0, offs)); + c1.setSpan(sp.subSpan(offs)); + } + return c1; + } else { + if(offs == 0) return c0; + if(offs == c0.getText().length()) + return c0.getOrNewCell("d.nile"); + return split(c0, offs, true); + } + } + + /** Internal convenience: make a connection and a ring if it isn't yet + * This is part of a cheat to make jumping between transclusions work: + * we connect all transclusions of a cell on d.nile-transcluded, even + * if the transcluded spans do not overlap, and jump between them. + * Works because currently, a cell can contain only one span. + * XXX what to do when splitting ??? + * XXX if we cheat anyway, is it more appropriate to use zz clones? + */ + static private void transcluded(ZZCell from, ZZCell to) { + from.insert("d.nile-transcluded", 1, to); + if(from.s("d.nile-transcluded", -1) == null) + from.connect("d.nile-transcluded", -1, to); + } + + + /** Transcopy the part of the stream between two iters. + * Sets the iters to point to the beginning and the end of the transcopied + * stream. + */ + static public void copy(Nile2Iter start, Nile2Iter to) { + if(!start.isOrdered(to)) { + Nile2Iter tmp = to; + to = start; start = tmp; + } + + // First, spanify all cells. + ZZCell d = start.c; + while(true) { + if(!isStruct(d)) spanify(d); + p("Spanified "+d+" is span "+d.getSpan()); + if(d == to.c) break; + d = d.s("d.nile"); + } + + // Next, create the new stream. + ZZCell first, last; + if(start.c.equals(to.c)) { + first = start.c.N(); + last = first; + first.setSpan(start.c.getSpan().subSpan(start.offs, to.offs)); + transcluded(start.c, first); + } else { + first = start.c.N(); + first.setSpan(start.c.getSpan().subSpan(start.offs)); + transcluded(start.c, first); + + ZZCell prev = first; + ZZCell here = start.c.s("d.nile"); + while(here != to.c) { + prev = prev.N("d.nile"); + prev.setSpan(here.getSpan()); + transcluded(prev, here); + here = here.s("d.nile"); + } + + last = prev.N("d.nile"); + last.setSpan(to.c.getSpan().subSpan(0, to.offs)); + transcluded(to.c, last); + } + + // Finally, set the iters. + start.set(new ZZCursorVirtual(first, 0)); + to.set(new ZZCursorVirtual(last, last.getText().length() - 1)); + } + + static public void dump(ZZCell start) { + if(start == null) { + pa("Nile stream Null start!"); + return; + } + ZZCell init = start.h("d.nile", -1); + pa("Nile stream! "+start); + boolean first = true; + for(ZZCell c = init; c != null; c=c.s("d.nile")) { + pa((c.s("d.nile-struct") != null ? "***S*** " : " ") + + " Cell "+c+" "+ + (c.equals(start) ? " <----------------START" : "")); + if(!first && c.equals(init)) { + pa(" WAS A LOOOOOOOP!!!!!!!!!!"); + throw new ZZFatalError("LOOPING NILE STREAM! BAD BAD TROUBLE!"); + } + first = false; + } + } + + static String[] levels = new String[] { + "P", "H3", "H2", "H1" + }; + + static int getMaxLevel() { return levels.length - 1; } + + // XXX Should use clones. + /** Set the level of a structural cell. + */ + static void setStrLevel(ZZCell str, int level) { + if(level < 0 || level > levels.length) + throw new ZZError("Request to set invalid level! "+level); + str.setText(levels[level]); + } + + /** The level of structure the given structure cell is. + * Note that the levels are a bit interesting: it returns + * zero for paragraphs, 1 for H6, 2 for H5 and so on. + * -1 is returned for cells that are not at a structural border. + */ + static int getStrLevel(ZZCell str) { + String txt = str.getText(); + for(int i=0; i 0) { + iter = giter(endcurs(view)); + if(!unit.insertPos(iter, 1, true)) return; + } else { + iter = giter(curs(view)); + if(!unit.insertPos(iter, -1, false)) return; + } + curs(view).set(iter.getCursor()); + unit.end(iter, 1, false); + endcurs(view).set(iter.getCursor()); + } + + static public void adjust(Nile2Unit unit, ZZCell view, int end, int dir) { + clearSavedCursor(view); + Nile2Iter iter = giter(curs(view)); + Nile2Iter enditer = giter(endcurs(view)); + if(end > 0) { + if(!unit.end(enditer, dir, false)) return; + } else { + if(!unit.start(iter, dir, false)) return; + } + if(!iter.isOrdered(enditer)) + return; + curs(view).set(iter.getCursor()); + endcurs(view).set(enditer.getCursor()); + } + + static public void hop(Nile2Unit unit, ZZCell view, int dir) { + clearSavedCursor(view); + Nile2Iter iter = giter(curs(view)); + Nile2Iter enditer = giter(endcurs(view)); + // XXX Checkpoint for undo! + Nile2Iter pt = unit.cut(iter, enditer); + + unit.insertPos(pt, dir, false); + + unit.paste(pt, iter, enditer); + + curs(view).set(iter.getCursor()); + endcurs(view).set(enditer.getCursor()); + } + + /** Tunnel text from one nile window to another. + * The text can be copied or cut. + */ + static public void tunnel(Nile2Unit unit, ZZCell from, ZZCell to, + int dir, boolean copy) { + clearSavedCursor(from); clearSavedCursor(to); + Nile2Iter fiter = giter(curs(from)); + Nile2Iter fenditer = giter(endcurs(from)); + Nile2Iter titer = giter(curs(to)); + Nile2Iter pt = null; + + // XXX Checkpoint for undo! + if(copy) + unit.copy(fiter, fenditer); + else + pt = unit.cut(fiter, fenditer); + + // Insert exactly where we are -- is this o.k.? + // unit.insertPos(titer, dir, true); + + unit.paste(titer, fiter, fenditer); + + curs(to).set(fiter.getCursor()); + endcurs(to).set(fenditer.getCursor()); + + if(!copy) { + unit.start(pt, -1, false); + curs(from).set(pt.getCursor()); + unit.end(pt, 1, true); + endcurs(from).set(pt.getCursor()); + } + } + + static public boolean insert(ZZCell view, String key) { + clearSavedCursor(view); + if(key == null) + return false; + if(key.length() != 1) + return false; + Nile2Iter it = giter(curs(view)); + it.insert(key); + ZZCursor c = it.getCursor(); + curs(view).set(c); + endcurs(view).set(c); + return true; + } + + static public void backspace(Nile2Unit unit, ZZCell view) { + clearSavedCursor(view); + Nile2Iter iter = giter(curs(view)); + if(!unit.insertPos(iter, -1, false)) return; + Nile2Iter enditer = (Nile2Iter)iter.clone(); + if(!unit.end(enditer, 1, false)) return; + Nile2Iter cut = unit.cut(iter, enditer); + if(cut == null) + throw new ZZError("Couldn't cut!"); + setCursor(unit, view, cut.getCursor()); + } + + static public void del(Nile2Unit unit, ZZCell view) { + // XXX if nothing is selected -- delete unit right from ins cursor + unit.cut(giter(curs(view)), giter(endcurs(view))); + } + + static public void breakParagraph(Nile2Unit unit, ZZCell view) { + clearSavedCursor(view); + Nile2Iter it = giter(curs(view)); + it.breakParagraph(); + setCursor(unit, view, it.getCursor()); + } + + static public void traverseTranscopies(ZZCell view, int dir) { + clearSavedCursor(view); + ZZCell c0 = ZZCursorReal.get(view); + ZZCell c = c0.s("d.nile-transcluded"); + if(c == null) { + ZZLogger.log("Could not traverse transcopies because accused cell " + + "IS not transcopied"); + return; + } + ZZCell h0 = c0.h("d.nile-transcluded-split", true); + if(h0 != null) { // jump over splits + while(h0.equals(c.h("d.nile-transcluded-split"))) { + if(c.equals(c0)) + throw new ZZError("XXX! All transcluded cells are " + + "splits of the same cell! HELP!"); + c = c.s("d.nile-transcluded"); + } + } + ZZCursorReal.setOffs(view, 0); + ZZCursorReal.set(view, c); + } + + + + /** Get a whole Nile stream as a string, properly capitalized. + * Converts paragraph breaks (==struct cells) to double newlines.
    + * XXX a) It's no good this calls Nile2View, and it's even worse it does + * *line-breaking* to capitalize! I.e. move capitalization elsewhere + * (ZZUtil)
    + * XXX b) Do this for the text between two iters (a selection), not only + * for a whole stream.
    + * XXX c) Does this belong in this class? (It seemed to fit?) + * + * @param inStream Some cell inside the stream to be read. + */ + static public String stringify(ZZCell inStream) { + ZZCell hd = inStream.h("d.nile"); + Nile1View n1v = new Nile1View(); + n1v.init__zob(); + String s = ""; + ZZCell tail = Nile2Iter.findStruct(hd, 1, false); + while(hd != null) { + FText ft = n1v.paragraph(hd, tail, null, null, null); + ft.capitalize(); + s = s + FText.Part.join(ft.parts); + hd = tail; + if(hd != null) tail = Nile2Iter.findStruct(hd, 1, false); + s = s + "\n\n"; + } + return s; + } + + + + + // Shorthand... + static public ZZCursorReal curs(ZZCell view) { + return new ZZCursorReal(view); + } + static public Nile2Iter giter(ZZCursor c) { + return new Nile2Iter(c); + } + + static public ZZCursorReal endcurs(ZZCell view) { + ZZCell end = view.getOrNewCell("d.nile-sel"); + return new ZZCursorReal(end); + } + +} diff --git a/Modules/nile/Nile2Test.java b/Modules/nile/Nile2Test.java new file mode 100644 index 0000000..19b55cb --- /dev/null +++ b/Modules/nile/Nile2Test.java @@ -0,0 +1,152 @@ +/* +Nile2Test.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag.module; +import org.gzigzag.*; + +/** Some simple tests for Nile. + */ + +public final class Nile2Test { +public static final String rcsid = "$Id: Nile2Test.java,v 1.1 2000/12/07 00:37:19 tjl Exp $"; + public static boolean dbg = true; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + static final void pok(String id, boolean ok) { + if(ok) p("ok "+id); + else p("not ok "+id); + } + + public static void main(String[] argv) { + ZZSpace z = new ZZDimSpace(); + ZZCell home = z.getHomeCell(); + ZZCell stream = home.N("d.1", 1); + + stream.N("d.nile-struct", 1); // Beginning structural marker + stream = stream.N("d.nile", 1); // Can't be at same cell. + stream.setText("Hello world a! How's it going?"); + + Nile2Iter it = new Nile2Iter(new ZZCursorVirtual(stream, 4)); + + p("Got: "+it.get()); + + Nile2Iter nextpart = it.cut(); + it.dumpStream(); + nextpart.dumpStream(); + + p("Got: "+it.get()); + pok("Atend", it.get() == -1); + pok("Prev", it.get(-1) == 'l'); + + pok("foll", nextpart.get() == 'o'); + pok("atstart", nextpart.get(-1) == -1); + + it.dumpStream(); + p("Joining"); + it.join(nextpart); + + it.dumpStream(); + nextpart.dumpStream(); + + pok("GET1", it.get() == 'o'); + pok("NEXT1", it.next() == ' '); + pok("NEXT2", it.next() == 'w'); + pok("PREV1", it.prev() == ' '); + + // Next, test word boundaries. + + Nile2Unit un = new Nile2Unit.Word(); + pok("PREVWORD1", un.start(it, -1, false)); + pok("PREVWORD2", !un.start(it, -1, false)); + pok("Wordplace", it.get() == 'H' && it.get(1) == 'e'); + + pok("NEXTWORD1", un.start(it, 1, true)); + pok("Wordplace2", it.get() == 'H' && it.get(1) == 'e'); + pok("NEXTWORD2", un.start(it, 1, false)); + pok("Wordplace3", it.get() == 'w' && it.get(1) == 'o'); + pok("NEXTWORD2", un.start(it, 1, false)); + pok("Wordplace2.5", it.get() == 'a' && it.get(1) == '!'); + pok("NEXTWORD2", un.start(it, 1, false)); + pok("Wordplace3", it.get() == '!' && it.get(1) == ' '); + pok("NEXTWORD3", un.start(it, 1, false)); + pok("Wordplace4", it.get() == 'H' && it.get(1) == 'o'); + + + Nile2Unit un2 = new Nile2Unit.Sentence(); + pok("senst1", un2.start(it, -1, false)); + pok("senst2", !un2.start(it, -1, false)); + pok("Sen", it.get() == 'H' && it.get(1) == 'e'); + pok("senst3", un2.start(it, 1, false)); + pok("Sen", it.get() == 'H' && it.get(1) == 'o'); + it.dumpStream(); + pok("senst4", !un2.start(it, 1, false)); + it.dumpStream(); + pok("senst5", un2.start(it, -1, false)); + pok("senst6", un2.start(it, -1, false)); + pok("senst7", !un2.start(it, -1, false)); + // Now at beginning. + Nile2Iter end = (Nile2Iter)it.clone(); + pok("sene1", un2.end(end, 1, true)); + p("At end: "+(end.get(-1))+"||"+end.get()); + end.dumpStream(); + pok("sene2", end.get() == ' ' && end.get(-1) == '!'); + + Nile2Iter result = un2.cut(it, end); + + p("Start:"); + it.dumpStream(); + p("End:"); + end.dumpStream(); + p("Res:"); + result.dumpStream(); + + // Next, test adjustspaces. + + ZZCell n = stream.N("d.1", 1); + n.setText("d"); + it.set(new ZZCursorVirtual(n, 0)); + pok("as1", it.get(-1) == -1 && it.get() == 'd' && it.get(1) == -1); + it.adjustSpaces(0, 1); + p("Adjusted: "); + it.dumpStream(); + pok("as2", it.get(-1) == -1 && it.get() == 'd' && it.get(1) == ' '); + it.adjustSpaces(0, 0); + p("Adjusted3: "); + it.dumpStream(); + pok("as3", it.get(-1) == -1 && it.get() == 'd' && it.get(1) == -1); + it.adjustSpaces(1, 0); + pok("as4", it.get(-1) == -1 && it.get() == ' ' && it.get(1) == 'd' + && it.get(2) == -1); + it.adjustSpaces(0, 0); + p("Adjusted5: "); + it.dumpStream(); + pok("as5", it.get(-1) == -1 && it.get() == 'd' && it.get(1) == -1); + + + + pok("END", true); + System.exit(0); + } + +} diff --git a/Modules/nile/Nile2Unit.java b/Modules/nile/Nile2Unit.java new file mode 100644 index 0000000..fac6b63 --- /dev/null +++ b/Modules/nile/Nile2Unit.java @@ -0,0 +1,432 @@ +/* +Nile2Unit.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag.module; +import org.gzigzag.*; + +/** A nile unit of division. + */ + +public abstract class Nile2Unit { +public static final String rcsid = "$Id: Nile2Unit.java,v 1.5 2000/12/17 16:32:24 bfallenstein Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + + /** The previous or next position where + * this type of unit may be inserted. + */ + public abstract boolean insertPos(Nile2Iter iter, int dir, + boolean includeThis); + + /** The previous or next beginning position of this type of + * unit. + */ + public abstract boolean start(Nile2Iter iter, int dir, boolean includeThis); + + /** The previous or next ending position of this type of unit. + */ + public abstract boolean end(Nile2Iter iter, int dir, boolean includeThis); + + /** Cut the stream. + * This routine modifies the start and to iterators to point + * to the beginning and end of the modified stream. + * @return The pasted-together cutaway point, from which + * the insert position can be searched with !includeThis. + * + */ + public abstract Nile2Iter cut(Nile2Iter start, Nile2Iter to); + + /** Copy a part of the stream. + * First every cell is spanified, then a new stream with the same spans + * is created. + * This routine modifies the start and to iterators to point + * to the beginning and end of the copied stream. + * XXX any special copying rules to obey, like in cut? + */ + public void copy(Nile2Iter start, Nile2Iter to) { + this.start(start, -1, true); + this.end(to, 1, true); + Nile2Iter.copy(start, to); + } + + public abstract void paste(Nile2Iter at, Nile2Iter what, Nile2Iter whatEnd); + + + static public class Char extends Nile2Unit { + public boolean insertPos(Nile2Iter iter, int dir, + boolean includeThis) { + if(!includeThis) + if(!iter.move(dir)) + if(!iter.shiftPara(dir)) + return false; + return true; + } + public boolean start(Nile2Iter iter, int dir, + boolean includeThis) { + if(!includeThis) + if(!iter.move(dir)) + if(!iter.shiftPara(dir)) + return false; + if(iter.get() == -1) return false; + return true; + } + + public boolean end(Nile2Iter iter, int dir, + boolean includeThis) { + if(!includeThis) + if(!iter.move(dir)) + if(!iter.shiftPara(dir)) + return false; + if(iter.get(-1) == -1) return false; + return true; + } + + public Nile2Iter cut(Nile2Iter start, Nile2Iter to) { + Nile2Iter after = to.cut(); + start.cut(); + start.join(after); + return start; + } + + public void paste(Nile2Iter at, Nile2Iter what, Nile2Iter whatEnd) { + } + } + + + /** The word and sentence base class. + * Words and sentences obey the same rules for the insert point. + */ + static public abstract class WordOrsentence extends Nile2Unit { + public abstract boolean isStart(Nile2Iter iter); + public abstract boolean isEnd(Nile2Iter iter); + public abstract int nspacesAtEnd(); + + // As documented, + // word insert points are word starting points, as well as + // paragraph's ending points. + public boolean insertPos(Nile2Iter iter, int dir, + boolean includeThis) { + return startOrIns(iter, dir, includeThis, true); + } + + public boolean start(Nile2Iter iter, int dir, boolean includeThis) { + return startOrIns(iter, dir, includeThis, false); + } + + public boolean startOrIns(Nile2Iter iter, int dir, boolean includeThis, + boolean insert) { + // This way we can always assume includeThis later. + if(!includeThis) + if(!iter.move(dir)) { + if(!iter.shiftPara(dir)) + return false; + // If we were looking for an insert point, we just + // found it... + if(dir < 0 && insert) return true; + } + // Can optimize if necessary... + while(true) { + if(isStart(iter)) return true; + if(!iter.move(dir)) { + if(dir > 0 && insert) return true; + if(!iter.shiftPara(dir)) return false; + if(dir < 0 && insert) return true; + } + + } + } + + public boolean end(Nile2Iter iter, int dir, boolean includeThis) { + if(!includeThis) + if(!iter.move(dir)) { + if(!iter.shiftPara(dir)) return false; + // In forwards dir, just go to the beginning + // of the next paragraph. + // This way, cutting from the last insertpos until + // end() results in just the paragraph break being + // removed, which is just right. + return true; + } + while(true) { + if(isEnd(iter)) return true; + if(!iter.move(dir)) + if(!iter.shiftPara(dir)) + return false; + } + } + + public Nile2Iter cut(Nile2Iter start, Nile2Iter end) { + // Find first non-space character. + int nws = this.firstNonWs(start); + this.p("Cut Firstnonws: "+nws + " '"+(char)nws+"'"); + boolean startPunct = this.punct(nws); + + // cut all the space after end. + int ncut = 0; + Nile2Iter endclone = (Nile2Iter)end.clone(); + while(this.ws(end.get())) { end.move(1); ncut ++; } + // If we happen to have space before us, count that too! + int nspace = 0; + while(this.ws(endclone.prev())) nspace++; + + Nile2Iter rstart = null; + if(ncut + nspace == 0 || startPunct) { + // If no space at end, + // we must cut space from before this, if it + // is a single space. + if(this.ws(start.get(-1)) && !this.ws(start.get(-2))) + (rstart = (Nile2Iter)start.clone()). move(-1); + else + if(this.ws(start.get(-1)) && startPunct) { + (rstart = (Nile2Iter)start.clone()). move(-1); + // For the if down later + ncut = 1; + } + } + // Now, here's the cut. We take away the stuff from + // start to end and then remove from rstart + // We must cut starting from the end so as not to disturb + // things. + Nile2Iter after = end.cut(); + Nile2Iter first = start.cut(); + Nile2Iter before = (Nile2Iter)start.clone(); + start.set(first); // We want to return this in start. + // Finally, cut the other stuff. + if(rstart != null) { + rstart.cut(); + before = rstart; + } + before.join(after); + // This is a bit special rule. + if(startPunct && ncut + nspace > 0) + before.insertInCell(" "); + return before; + } + + public void paste(Nile2Iter at, Nile2Iter what, Nile2Iter whatEnd) { + // Check whether what has punctuation in the start... + int nws = this.firstNonWs(what); + this.p("Paste Firstnonws: "+nws + " '"+(char)nws+"'"); + boolean startPunct = this.punct(nws); + Nile2Iter after = null; + + if(dbg) { + this.p("PASTE!!!"); + at.dumpStream(); + what.dumpStream(); + } + + + if(startPunct) { + // If there is punctuation, we must start it with + // exactly the spaces that were there, UNLESS + // we are at the beginning of the sentence, in which + // case we shall have two spaces. + + if(this.ws(at.get(-1)) && this.ws(at.get(-2))) { + // Ok, now it's difficult. + // Leave these spaces, but remove one in the + // beginning of + what.adjustSpaceStart(0); + after = at.cut(); + } else { + if(this.ws(at.get(-1))) { + at.move(-1); + after = at.cut(); + after.move(1); + after = after.cut(); + } else { + after = at.cut(); + } + } + } else { + // pasting words is a bit tricky. + int prev = at.get(-1); + int cur = at.get(); + // Where do we want to ensure we have space. + boolean spaceEnd = false, spaceStart = false; + // If we are at start of paragraph, we ensure that + // a space is in the end. + if(prev == -1) spaceEnd = true; + else if(this.punct(cur)) { + // If we are at punctuation, we put a space after + // inserted text is there was a space before. + if(this.ws(prev)) spaceEnd = true; + else spaceStart = true; + } + else spaceEnd = true; + + what.adjustSpaces(spaceStart ? 1 : 0, + spaceEnd ? nspacesAtEnd() : 0); + + + after = at.cut(); + } + at.join(what); + whatEnd.set(what); + whatEnd.streamEnd(1); + whatEnd.join(after); + whatEnd.set(after); + } + } + + static public class Word extends WordOrsentence { + public boolean isStart(Nile2Iter iter) { return this.isWordStart(iter); } + public boolean isEnd(Nile2Iter iter) { return this.isWordEnd(iter); } + public int nspacesAtEnd() { return 1; } + } + + static public class Sentence extends WordOrsentence { + public boolean isStart(Nile2Iter iter) { return this.isSentenceStart(iter); } + public boolean isEnd(Nile2Iter iter) { return this.isSentenceEnd(iter); } + public int nspacesAtEnd() { return 2; } + } + + static public class Paragraph extends Nile2Unit { + // A paragraph may be inserted at the end of any paragraph, + // or in the very beginning of the stream. + // That requires special handling because + // Nile2Iter can't get there. + public boolean insertPos(Nile2Iter iter, int dir, + boolean includeThis) { + // XXX First, check if we *are* there already. + + if(!end(iter, dir, includeThis)) { + if(dir > 0) return false; + ZZCursor curs = iter.getCursor(1); + curs.set(curs.get().h("d.nile")); + curs.setOffs(0); + iter.set(curs); + } + return true; + } + public boolean start(Nile2Iter iter, int dir, boolean includeThis) { + if(!includeThis) { + if(!iter.move(dir)) { + // We were at the beginning + if(!iter.shiftPara(dir)) + return false; + } + } + return iter.paraEnd(-1); + } + public boolean end(Nile2Iter iter, int dir, boolean includeThis) { + if(!includeThis) { + if(!iter.move(dir)) { + // We were at the beginning + if(!iter.shiftPara(dir)) + return false; + } + } + return iter.paraEnd(1); + } + + public Nile2Iter cut(Nile2Iter start, Nile2Iter end) { + return null; + } + public void paste(Nile2Iter at, Nile2Iter what, Nile2Iter whatEnd) { + } + } + + // Something non-ws following to ws's. + static public boolean isSentenceStart(Nile2Iter iter) { + int cur = iter.get(); + if(cur == -1 || ws(cur)) return false; + int prev = iter.get(-1); + if(prev == -1) return true; + if(!ws(prev)) return false; + int prev2 = iter.get(-2); + if(prev2 == -1) return true; + if(!ws(prev2)) return false; + return true; + } + + // Something non-ws following to ws's. + static public boolean isSentenceEnd(Nile2Iter iter) { + int prev = iter.get(-1); + if(prev == -1 || ws(prev)) return false; + int cur = iter.get(); + if(cur == -1) return true; + if(!ws(cur)) return false; + int next = iter.get(1); + if(next == -1) return true; + if(!ws(next)) return false; + return true; + } + + static public boolean isWordStart(Nile2Iter iter) { + int cur = iter.get(); + if(punct(cur)) { +/* if(lett(punct.get(-1)) && lett(punct.get(1))) { + // Punctuation surrounded by two letters is NOT + // a word boundary. + return false; + } else XXX Must test in other cases!!! */ + + return true; + } + + int prev = iter.get(-1); + // This should also cover buffer start. + if(lett(cur) && !lett(prev)) return true; + return false; + } + static public boolean isWordEnd(Nile2Iter iter) { + int prev = iter.get(-1); + if(punct(prev)) +/* + if(lett(punct.get(-2)) && lett(punct.get(0))) { + // Punctuation surrounded by two letters is NOT + // a word boundary. + return false; + } else XXX Must test!!!! */ + return true; + + int cur = iter.get(); + if(lett(prev) && !lett(cur)) return true; + return false; + } + + // Shorthand. + // Exactly one of these must return true for every character. + // except -1, when all are false. + static boolean ws(int c) { return Character.isWhitespace((char)c); } + static boolean punct(int c) { + if(c == -1) return false; + return (!Character.isWhitespace((char)c)) && + (!Character.isLetterOrDigit((char)c)); + } + static boolean lett(int c) { return Character.isLetterOrDigit((char)c); } + + static int firstNonWs(Nile2Iter iter) { + int ch = 0; + // Use index, don't move. + for(int i=0; (ch=iter.get(i)) != -1; i++) { + if(!ws(ch)) return ch; + } + return -1; + } + +} diff --git a/Modules/nile/NileApplet.java b/Modules/nile/NileApplet.java new file mode 100644 index 0000000..fbfb3b8 --- /dev/null +++ b/Modules/nile/NileApplet.java @@ -0,0 +1,63 @@ +/* +NileApplet.java + * + * Copyright (c) 1999, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ + +package org.gzigzag; + +import java.awt.*; +import java.applet.*; +import java.io.*; +import java.util.*; + +/** An applet showing the split Nile view. + * This just takes a lot of code from ZZApplet -- bad style. Well, this is + * just an intermediate: When we start making real demos using the Dump + * stuff, ZZApplet probably needs to be rewritten, and NileApplet will be + * totally obsolete. + */ + +public class NileApplet extends Applet { + public static final String rcsid = "$Id: NileApplet.java,v 1.4 2001/01/03 16:47:50 raulir Exp $"; + + public void init() { + ZZSpace space = new ZZCacheDimSpace(new DummyStreamSet()); + ZZCell home=space.getHomeCell(); + home.N("d.1").setText("First text"); + home.N("d.1").setText("Second text"); + + ZZDefaultSpace.create(home); + setLayout(new BorderLayout()); + ZZWindows.init(space,this); + + ZZCell topl = ZZWindows.startCell().s("d.1", 1) + .s("d.2", 1); + ZZCell a = topl.s("d.1", 2); + ZZCell b = topl.s("d.2", 1).s("d.1", 1); + ZZCursorReal.set(a, home.s("d.1", 1)); + ZZCursorReal.set(b, home.s("d.1", 2)); + ZZCursorReal.setColor(a,Color.red); + ZZCursorReal.setColor(b,Color.yellow); + org.gzigzag.module.SplitNileDemo.updateSpace(a, a, b); + + ZZObsTrigger.runObsQueue(); + } +} diff --git a/Modules/nile/NileDemo.java b/Modules/nile/NileDemo.java new file mode 100644 index 0000000..2e34946 --- /dev/null +++ b/Modules/nile/NileDemo.java @@ -0,0 +1,143 @@ +/* +NileDemo.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.awt.*; +import java.io.*; + + +public class NileDemo { +public static final String rcsid = "$Id: NileDemo.java,v 1.3 2000/12/28 01:19:07 bfallenstein Exp $"; + public static boolean dbg = false; + static void p(String s) { if(dbg) System.out.println(s); } + static void pa(String s) { System.out.println(s); } + + /** Update the bindings etc.in the space. + * This is temporary and should go away once we have better + * space management. + */ + static void updateSpace(ZZCell code, ZZCell viewCell, ZZCell ctrlCell) { + // First, make sure the system list cell is ok + // and recreate actions. + + ZZSpace sp = code.getSpace(); + ZZCell t0 = ZZDefaultSpace.findOnSystemlist(sp, "Nile1", true); + ZZCell bind = t0.getOrNewCell("d.1", 1); + ZZCell rast = t0.getOrNewCell("d.2", 1); + + bind.disconnect("d.1", 1); + bind = bind.N("d.1", 1); + Nile1.actions(bind); + + rast.disconnect("d.1",1); + rast = rast.N("d.1"); + rast.setText("Nile1View"); + rast = rast.N("d.1"); + rast.setText("Nile1.Normal"); + rast = rast.s("d.1", -1); // go to the cell we need + + // Then, update windows. + + ZZCell datac = updateWin(sp, viewCell, rast, bind, false); + ZZCell ctrlc = updateWin(sp, ctrlCell, rast, bind, true); + if(datac != null && ctrlc != null) { + datac.excise("d.nile-wins"); ctrlc.excise("d.nile-wins"); + ctrlc.connect("d.nile-wins", 1, datac); + datac.connect("d.nile-wins", 1, ctrlc); + } + } + + static ZZCell updateWin(ZZSpace sp, ZZCell viewCell, ZZCell rast, + ZZCell bind, boolean ctrl) { + if(viewCell == null) return null; + + // Make sure we have a window and update its + // binding and raster. + + ZZCell win = null; + String title = ctrl ? "Nile1-Left" : "Nile1W"; + int round = 0; + while(win == null) { + if(round > 1) + throw new ZZError("Couldn't create window"); + round++; + + win = ZZDefaultSpace.findOnSystemlist(sp, "Windows", false); + win = win.s("d.1"); + win = win.findText("d.2", 1, title); + + if(win == null) + ZZDefaultSpace.newToplevelView(sp, + title, ctrl ? 0 : 400, 20, 400, 400, + null, null, null, viewCell, + null, new Color(0x819fff)); + } + + // Then, set window bindings + win = win.s("d.1", 2); + ZZCell bcurs = win.getOrNewCell("d.bind", 1); + ZZCursorReal.set(bcurs, bind); + ZZCell viewsel = win.findText("d.2", 1, "View"); + ZZCursorReal.set(viewsel, rast); + ZZCursorReal.setColor(viewsel, ZZUtil.perturb(Color.red)); + return win; + } + + static public ZZModule module = new ZZModule() { + public void action(String id, + ZZCell code, + ZZCell target, + ZZView view, ZZView cview, String key, Point pt, ZZScene xi) { + ZZUpdateManager.setFast(view); + + ZZCell viewCell = view.getViewcell(); + ZZCell otherCell = viewCell.s("d.nile-wins"); + + p("Nile action: "+id+" "+key); + + StringTokenizer st = new StringTokenizer(id); + String[] toks = new String[st.countTokens()]; + for(int i=0; i 1) + throw new ZZError("Couldn't create window"); + round++; + + win = ZZDefaultSpace.findOnSystemlist(sp, "Windows", false); + win = win.s("d.1"); + win = win.findText("d.2", 1, title); + + if(win == null) + ZZDefaultSpace.newToplevelView(sp, + title, 20, 20, 600, 400, + null, null, null, null, + null, new Color(0x819fff)); + } + + // Then, create the cursor pair and set the window cursor + win = win.s("d.1", 2); + ZZCell leftcurs = win.N(); + ZZCursorReal.attach(leftcurs, ctrlCell); + ZZCell rightcurs = leftcurs.N("d.nile-pair"); + ZZCursorReal.attach(rightcurs, viewCell); + ZZCursorReal.set(win, leftcurs); + + // Finally, set window bindings + ZZCell bcurs = win.getOrNewCell("d.bind", 1); + ZZCursorReal.set(bcurs, bind); + ZZCell viewsel = win.findText("d.2", 1, "View"); + ZZCursorReal.set(viewsel, rast); + ZZCursorReal.setColor(viewsel, ZZUtil.perturb(Color.red)); + } + + static public ZZModule module = new ZZModule() { + public void action(String id, + ZZCell code, + ZZCell target, + ZZView view, ZZView cview, String key, Point pt, ZZScene xi) { + ZZUpdateManager.setFast(view); + + // Update the Nile stuff to the latest bindings (defined + // unfortunately in this file -- oh how I long for the day + // when they are in a ZZ space as the definitive version) + if(id.equals("UPDATE")) { + updateSpace(code, view.getViewcell(), cview.getViewcell()); + } + } + }; +} diff --git a/Modules/nile/SplitNileView.zob b/Modules/nile/SplitNileView.zob new file mode 100644 index 0000000..536fdb0 --- /dev/null +++ b/Modules/nile/SplitNileView.zob @@ -0,0 +1,71 @@ +/* +SplitNileView.zob + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ + +package org.gzigzag.module; +import org.gzigzag.*; +import java.awt.*; + +/** A view that shows two Nile streams side-by-side. */ + +public class SplitNileView implements FlobView, ZOb { +public static final String rcsid = "$Id: SplitNileView.zob,v 1.1 2000/12/26 20:15:50 bfallenstein Exp $"; + /** Should we print out debugging info? */ + public static boolean dbg = false; + static final void p(String s) { if(dbg) pa(s); } + static final void pa(String s) { System.out.println(s); } + + STRUCTPARAMS { + /** The space to leave between the two Nile streams. */ + int margin + = 20; + } + + public void raster(FlobSet into, FlobFactory fact, + ZZCell win, String[] dims, ZZCell accursed) { + ZZCell leftc = accursed.s("d.nile-pair", -1); + ZZCell rightc = accursed.s("d.nile-pair"); + if(leftc != null && rightc == null) + rightc = accursed; + else if(leftc == null && rightc != null) + leftc = accursed; + else + throw new ZZError("HELP! Strange d.nile-pair arrangement XXX"); + + ZZCell leftacc = ZZCursorReal.get(leftc); + ZZCell rightacc = ZZCursorReal.get(rightc); + + Dimension size = new Dimension(into.getSize()); + size.width = (size.width - margin) / 2; + FlobSet left = into.create(size), right = into.create(size); + + Nile1View view = new Nile1View(); + view.init__zob(); + SimpleBeamer bmr = new SimpleBeamer(); + + view.raster(left, fact, leftc, dims, leftacc); + view.raster(right, fact, rightc, dims, rightacc); + + into.fetch(left, 0, 0, 0); + into.fetch(right, size.width + margin, 0, 0); + + bmr.decorate(into, "", null); + } +} diff --git a/Modules/nile/draft/Nile3Ops.java b/Modules/nile/draft/Nile3Ops.java new file mode 100644 index 0000000..4738cdd --- /dev/null +++ b/Modules/nile/draft/Nile3Ops.java @@ -0,0 +1,166 @@ +/* +Nile3Ops.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; + +/** A library of routines for operating on Nile streams. + * @see Nile1 + */ + +public abstract class Nile3Ops { +public static final String rcsid = "$Id: Nile3Ops.java,v 1.1 2001/01/07 18:59:06 bfallenstein Exp $"; + public static boolean dbg = false; + static void p(String s) { if(dbg) System.out.println(s); } + static void pa(String s) { System.out.println(s); } + + static public void saveCursor(ZZCell win) { + ZZCell s = win.getOrNewCell("d.nile-save", 1); + if(ZZCursorReal.get(s) == null) + ZZCursorReal.set(s, new ZZCursorReal(win)); + } + static public void clearSavedCursor(ZZCell win) { + ZZCell s = win.getOrNewCell("d.nile-save", 1); + if(ZZCursorReal.get(s) != null) + ZZCursorReal.set(s, (ZZCell)null); + } + static public ZZCursor getSavedCursor(ZZCell win) { + ZZCell s = win.getOrNewCell("d.nile-save", 1); + return new ZZCursorReal(s); + } + + static public void setCursor(Nile3Unit unit, ZZCell win, ZZCursor to) { + Nile3Pos pos = new Nile3Pos(to); + setPart(win, unit.extend(pos)); + } + + static public void moveCursor(Nile3Unit unit, ZZCell win, int dir) { + Nile3Part part = getPart(win); + if(!unit.step(part, dir)) return; + setPart(win, part); + } + + static public void adjust(Nile3Unit unit, ZZCell win, int end, int dir) { + Nile3Part part = getPart(win); + if(!unit.adjust(part, end, dir)) return; + setPart(win, part); + } + + static public void hop(Nile3Unit unit, ZZCell win, int dir) { + Nile3Part part = getPart(win); + Nile3Pos pos = part.side(dir); + if(!unit.insertPos(pos, dir, part, false)) return; + unit.move(part, pos, false); + setPart(win, part); + } + + /** Tunnel text from one nile window to another. + * The text can be copied or cut. + */ + static public void tunnel(Nile3Unit unit, ZZCell from, ZZCell to, + boolean copy) { + Nile3Part part = getPart(from); + Nile3Pos pos = getPart(to).start; + if(!unit.insertPos(pos, -1, part, true)) return; + unit.move(part, pos, copy); + setPart(to, part); + } + + static public boolean insert(ZZCell win, String key) { + if(key == null) + return false; + if(key.length() != 1) + return false; + Nile3Pos pos = getPart(win).start; + pos.insert(key, 1); + setPos(win, pos); + return true; + } + + static public void backspace(Nile3Unit unit, ZZCell win) { + Nile3Part orig = getPart(win); + Nile3Part part = new Nile3Part(orig.start, orig.start); + unit.edge(part.start, -1, -1, false); + unit.edge(part.end, 1, -1, true); + unit.cut(part); + } + + static public void del(Nile3Unit unit, ZZCell win) { + Nile3Pos pos = unit.cut(getPart(win)); + setPos(win, pos); + } + + static public void breakParagraph(Nile3Unit unit, ZZCell win) { + Nile3Part part = getPart(win); + part.start.breakParagraph(); + } + + + /** Get a whole Nile stream as a string, properly capitalized. + * Converts paragraph breaks (==struct cells) to double newlines.
    + * XXX a) It's no good this calls Nile1View.
    + * XXX b) Do this for a Nile3Part (a selection), not only + * for a whole stream.
    + * XXX c) Does this belong in this class? (It seemed to fit?) + * + * @param inStream Some cell inside the stream to be read. + */ + static public String stringify(ZZCell inStream) { + ZZCell hd = inStream.h("d.nile"); + Nile1View n1v = new Nile1View(); + n1v.init__zob(); + String s = ""; + ZZCell tail = Nile2Iter.findStruct(hd, 1, false); + while(hd != null) { + FText ft = n1v.paragraph(hd, tail, null, null, null); + ft.capitalize(); + s = s + FText.Part.join(ft.parts); + hd = tail; + if(hd != null) tail = Nile2Iter.findStruct(hd, 1, false); + s = s + "\n\n"; + } + return s; + } + + // Shorthand... + static public Nile3Part getPart(ZZCell win) { + ZZCursorReal start = new ZZCursorReal(win); + if(start.getOffs() == start.NO_OFFSET) + start = new ZZCursorReal(win.getOrNewCell("d.nile-save")); + ZZCursorReal end = new ZZCursorReal(win.getOrNewCell("d.nile-sel")); + return new Nile3Part(start, end); + } + + static public void setPart(ZZCell win, Nile3Part part) { + ZZCursor start = part.start.get(), end = part.end.get(); + ZZCursorReal.set(win, start.get()); + // if(ZZCursorReal.getOffs(win) != ZZCursorReal.NO_OFFSET) + ZZCursorReal.setOffs(win, start.getOffs()); + ZZCursorReal.set(win.getOrNewCell("d.nile-save"), start); + ZZCursorReal.set(win.getOrNewCell("d.nile-sel"), end); + } + + static public void setPos(ZZCell win, Nile3Pos pos) { + setPart(win, new Nile3Part(pos, pos)); + } +} diff --git a/Modules/nile/draft/Nile3Part.java b/Modules/nile/draft/Nile3Part.java new file mode 100644 index 0000000..77ade00 --- /dev/null +++ b/Modules/nile/draft/Nile3Part.java @@ -0,0 +1,132 @@ +/* +Nile3Part.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ + +package org.gzigzag.module; +import org.gzigzag.*; + +/** A Nile span, with a start and an end. + * This object explicitly assumes no modifications to the + * stream while it is working. + */ + +public final class Nile3Part implements Cloneable { +public static final String rcsid = "$Id: Nile3Part.java,v 1.1 2001/01/07 18:59:06 bfallenstein Exp $"; + public static boolean dbg = true; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + public final Nile3Pos start = new Nile3Pos(); + public final Nile3Pos end = new Nile3Pos(); + + public Nile3Part(Nile3Pos start, Nile3Pos end) { + this.start.set(start); this.end.set(end); + check(); + } + public Nile3Part(ZZCursor start, ZZCursor end) { + p(start + " " + end); + this.start.set(start); this.end.set(end); + check(); + } + + public Nile3Pos side(int dir) { + if(dir < 0) return start; + else return end; + } + + public Nile3Pos cut() { + if(isStream()) + return null; // XXX should this throw an error? + check(); + start.split(false, 1); + end.split(false, -1); + Nile3Pos before = (Nile3Pos)start.clone(); + Nile3Pos after = (Nile3Pos)end.clone(); + if(!before.bias(-1) || !after.bias(1)) + throw new ZZError("HELP! End of stream after split! XXX"); + start.c.disconnect("d.nile", -1); + end.c.disconnect("d.nile", 1); + before.c.connect("d.nile", 1, after.c); + return before; + } + + /** Make a cell's content into a span. */ + static public Span spanify(ZZCell c0) { + Span sp = c0.getSpan(); + if(sp != null) return sp; + + StringScroll sc = c0.getSpace().getStringScroll(); + String s = c0.getText(); + long soffs = sc.append(s); + sp = Span.create( + Address.scrollOffs(sc, soffs), + Address.scrollOffs(sc, soffs + s.length() - 1) + ); + c0.setSpan(sp); + return sp; + } + + public Nile3Part copy() { + check(); + start.split(false, 1); + end.split(false, -1); + ZZCell c = start.c; + ZZCell first = c.N(), last = first; + while(true) { + last.setSpan(spanify(c)); + if(c.equals(end.c)) break; + c = c.s("d.nile"); + last = last.N("d.nile"); + } + return new Nile3Part( + new ZZCursorVirtual(first, 0), + new ZZCursorVirtual(last, last.getText().length())); + } + + /** Return true if there's nothing before or after this. */ + public boolean isStream() { + return start.end(-1) && end.end(1); + } + + /** Check the integrity of this Nile3Part: start <= end? */ + public void check() { + boolean good = true; + if(start.c.equals(end.c)) { + good = start.offs <= end.offs; + p(start.offs + " " + end.offs); + } else { + good = start.c.findCell("d.nile", 1, end.c); + p(start.c + " " + end.c); + } + if(!good) + throw new ZZError("Malformed Nile3Part stream! XXX"); + } + + public Object clone() { + try { + return super.clone(); + } catch(CloneNotSupportedException e) { + ZZLogger.exc(e); + return null; + } + } +} \ No newline at end of file diff --git a/Modules/nile/draft/Nile3Pos.java b/Modules/nile/draft/Nile3Pos.java new file mode 100644 index 0000000..26381fa --- /dev/null +++ b/Modules/nile/draft/Nile3Pos.java @@ -0,0 +1,338 @@ +/* +Nile3Pos.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ + +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; + +/** A character-level iterator object that knows about + * paragraphs for a Nile stream. + * This object explicitly assumes no modifications to the + * stream while it is working. + * The position is between the characters, not on a character. + * Actually, it is between (a char | a para boundary) and + * (a char | a para boundary), i.e., it can be at the beginning or end + * of a para or between two paras. + */ + +public final class Nile3Pos implements Cloneable { +public static final String rcsid = "$Id: Nile3Pos.java,v 1.1 2001/01/07 18:59:06 bfallenstein Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + /** Returned by type() or read(), this denotes end/beginning of stream. */ + public static final int END = -1; + /** Returned by type() or read(), this denotes a paragraph break. */ + public static final int PARA = -2; + /** Returned by type(), this means punctuation. */ + public static final int PUNCT = -3; + /** Returned by type(), this means alphanumeric character. */ + public static final int ALPHA = -4; + /** Returned by type(), this means whitespace. */ + public static final int WS = -5; + /** Returned by read(), this means special thing (to type, it's PUNCT). */ + public static final int SPECIAL = -6; + + ZZCell c; + int offs; + + // Cache these for speed. + // Note: ctxt and cspan are only valid if NOT (isStruct || isSpecial)! + int clen; + String ctxt; + Span cspan; + + // Is this cell a struct cell, a text object? + private boolean isStruct, isSpecial; + + public Nile3Pos(Nile3Pos pos) { set(pos); } + public Nile3Pos(ZZCursor pos) { set(pos); } + Nile3Pos() {} + + public ZZCursor get() { return new ZZCursorVirtual(c, offs); }; + + + private void load(ZZCell c) { + this.c = c; + isStruct = (c.s("d.nile-struct", 1) != null); + isSpecial = (c.s("d.nile-special", 1) != null); + + if(isStruct || isSpecial) + clen = 1; + else { + ctxt = c.getText(); + cspan = c.getSpan(); + clen = ctxt.length(); + } + } + + public void set(Nile3Pos pos) { + load(pos.c); + offs = pos.offs; + } + public void set(ZZCursor pos) { + load(pos.get()); + offs = pos.getOffs(); + if(offs == pos.NO_OFFSET) offs = 0; + } + + /** Internal convenience: try to insert with bias, if can't, return */ + private boolean insert(String s, int side, int bias) { + if(!bias(bias)) return false; + if(cspan != null) return false; + + c.setText(ctxt.substring(0, offs) + s + ctxt.substring(offs)); + ZZCursorReal.adjustCursors(c, offs, s.length()); + if(side > 0) offs += s.length(); + return true; + } + + public void insert(String s, int side) { + if(insert(s, side, 1)) return; + if(offs == 0) + if(insert(s, side, -1)) return; + split(false, 1); + load(c.N("d.nile", -1)); + c.setText(s); + offs = (side < 0) ? (0) : (clen); + } + + public void insert(Nile3Part what, int side) { + if(!what.isStream()) + throw new ZZError("Can't insert non-stream Nile3Part!"); + split(false, side); + ZZCell other = c.s("d.nile", -side); + c.disconnect("d.nile", -side); + c.connect("d.nile", -side, what.side(side).c); + other.connect("d.nile", side, what.side(-side).c); + } + + public boolean delete(int bias) { + // First, ensure we are in the same cell as the character to delete. + if(!bias(bias)) return false; + + // Then, a special case check (also for isStruct and isSpecial cells) + if(clen == 1) { + ZZCell from = c; + if(c.s("d.nile") != null) { + load(c.s("d.nile")); + offs = 0; + } else if(c.s("d.nile", -1) != null) { + load(c.s("d.nile", -1)); + offs = clen; + } else { + load(c.N("d.nile")); + offs = 0; + } + Enumeration e = ZZCursorReal.getPointers(from); + while(e.hasMoreElements()) { + ZZCell curs = (ZZCell)e.nextElement(); + ZZCursorReal.setcursor(curs, c); + if(ZZCursorReal.getOffs(curs) != ZZCursorReal.NO_OFFSET) + ZZCursorReal.setOffs(curs, offs); + } + from.delete(); + return true; + } + + if(cspan == null) { + if(bias < 0) offs--; + c.setText(ctxt.substring(0, offs) + ctxt.substring(offs)); + ZZCursorReal.adjustCursors(c, offs, -1); + } else { + split(false, bias); + if(bias > 0) c.setSpan(cspan.subSpan(1)); + else c.setSpan(cspan.subSpan(0, clen-1)); + } + load(c); + return true; + } + + /** Split at the current position. + * The original cell will remain the first. + * If side is greater than zero, this pos will be set to the second cell; + * if side is less than zero, this pos will be set to the first cell. + * If offs is zero or equal to the number of characters in c, nothing is + * done and either the current cell or the next cell is returned. + *

    + * The most special case involves doing this at the very end of the stream, + * in which case an empty new cell is created and returned. + * @param side The side of the split to make this Nile3Pos point to. + * @param always Whether to split even if the offset is at the beginning + * or end of a cell. Used e.g. for inserting a paragraph. + */ + public void split(boolean always, int side) { + if(always) { + ZZCell c1 = c.N("d.nile"); + if(cspan == null) { + c.setText(ctxt.substring(0, offs)); + c1.setText(ctxt.substring(offs)); + } else { + c.setSpan(cspan.subSpan(0, offs)); + c1.setSpan(cspan.subSpan(offs)); + } + Enumeration e = ZZCursorReal.getPointers(c); + while(e.hasMoreElements()) { + ZZCell p = (ZZCell)e.nextElement(); + int poffs = ZZCursorReal.getOffs(p); + if(poffs != ZZCursorReal.NO_OFFSET && poffs > offs) { + ZZCursorReal.setcursor(p, c1); + ZZCursorReal.setOffs(p, poffs-offs); + } + } + if(side > 0) { load(c1); offs = 0; } + } else { + if(offs == 0) { + if(side < 0) { + load(c.getOrNewCell("d.nile", -1)); + offs = clen; + } + } else if(offs >= clen) { + if(side > 0) { + load(c.getOrNewCell("d.nile")); + offs = 0; + } + } else + split(true, side); + } + } + + public int type(int dir) { + int ch = read(dir); + if(ch < 0) return ch; + if(Character.isLetterOrDigit((char)ch)) return ALPHA; + if(Character.isWhitespace((char)ch)) return WS; + return PUNCT; + } + /** Return true if type() would return Nile3Pos.END. */ + public boolean end(int dir) { + return type(dir) == END; + } + /** Return true if type() would return Nile3Pos.PARA. */ + public boolean para(int dir) { + return type(dir) == PARA; + } + /** Return true if type() would return Nile3Pos.PUNCT. */ + public boolean punct(int dir) { + return type(dir) == PUNCT; + } + /** Return true if type() would return Nile3Pos.ALPHA. */ + public boolean alpha(int dir) { + return type(dir) == ALPHA; + } + /** Return true if type() would return Nile3Pos.WS. */ + public boolean ws(int dir) { + return type(dir) == WS; + } + /** Return true if boundary, i.e. if end() or para() would return true. */ + public boolean boundary(int dir) { + int t = type(dir); + return (t == END) || (t == PARA); + } + /** Return true if boundary() or ws() would test true. */ + public boolean bws(int dir) { + int t = type(dir); + return (t == WS) || (t == END) || (t == PARA); + } + + /** Read character in given direction. */ + public int read(int dir) { + if(!bias(dir)) return END; + if(isStruct) return PARA; + if(isSpecial) return SPECIAL; + return ctxt.charAt((dir < 0) ? (offs - 1) : (offs)); + } + + /** Move n characters forwards or backwards. + * If the offset given is out of bounds, moves as far as possible + * and returns false, otherwise returns true. In general, this moves as + * little as possible, i.e. if n was positive, bias is negative, and if + * n was negative, bias is positive after call. + */ + public boolean move(int n) { + n += offs; + offs = 0; + + while(n > clen) { + n -= clen; + ZZCell nc = c.s("d.nile"); + if(nc == null) { + // End of stream! + offs = clen; + if(n > 0) return false; + return true; + } + load(nc); + } + while(n < 0) { + ZZCell nc = c.s("d.nile", -1); + if(nc == null) { + offs = 0; + return false; + } + load(nc); + n += clen; + } + + offs = n; + return true; + } + /** (Convenience:) Move if doMove is true. + * This is used by Nile3Unit to make includeThis code simpler. + */ + public boolean move(boolean doMove, int n) { + if(doMove) return move(n); + else return true; + } + + /** Ensure bias in a given direction. + * This means that after bias(1), we are in the cell that contains the + * character in positive direction, and after bias(-1), same in negative + * direction.
    + * If we bump on the end of the stream, return false, else return true. + */ + boolean bias(int dir) { + if(offs + dir >= 0 && offs + dir <= clen) return true; + do { + ZZCell nc = c.s("d.nile", dir); + if(nc == null) return false; + load(nc); + } while(clen == 0); + return true; + } + + public void breakParagraph() { + split(false, 1); + c.N("d.nile", -1).N("d.nile-struct").setText("P"); + } + + public Object clone() { + try { + return super.clone(); + } catch(CloneNotSupportedException e) { + ZZLogger.exc(e); + return null; + } + } +} \ No newline at end of file diff --git a/Modules/nile/draft/Nile3Unit.java b/Modules/nile/draft/Nile3Unit.java new file mode 100644 index 0000000..9146e28 --- /dev/null +++ b/Modules/nile/draft/Nile3Unit.java @@ -0,0 +1,305 @@ +/* +Nile3Unit.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein, based on Nile2Unit by Tuomas Lukka + */ + +package org.gzigzag.module; +import org.gzigzag.*; + +/** A nile unit of division. + * Spaces between units may be non-zero-width. Units may be zero-width, if + * neighbouring units are separated by non-zero spaces. + */ + +public abstract class Nile3Unit { +public static final String rcsid = "$Id: Nile3Unit.java,v 1.1 2001/01/07 18:59:06 bfallenstein Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + + public static class Char extends Nile3Unit { + public boolean isEdge(Nile3Pos pos, int dir) { + return !pos.boundary(dir); + } + } + + public static class Word extends Nile3Unit { + /** An alphanumeric word. */ + static final int AWORD = 1; + /** A punctuation word, e.g. a smilie. */ + static final int PWORD = 2; + /** An A- or PWORD. */ + static final int WORD = AWORD | PWORD; + /** A piece of left-bound punctuation, like commas. */ + static final int LPUNCT = 4; + /** A piece of right-bound punctuation, like opening brackets. */ + static final int RPUNCT = 8; + /** A piece of left- or right-bound punctuation. */ + static final int BPUNCT = LPUNCT | RPUNCT; + /** A paragraph boundary or the end of the stream. */ + static final int BOUNDARY = 16; + + /** Not a correct combination of words. */ + static final int BAD = 0; + /** Correct combination iff no space in between. */ + static final int NSP = 1; + /** Correct combination iff space in between. */ + static final int SP = 2; + + /** The type of a joining position. */ + public static final int jointype(int lefttype, int righttype) { + if(lefttype & WORD > 0 && righttype & WORD > 0) + return SP; + else if(lefttype == AWORD && righttype == LPUNCT) + return NSP; + else if(lefttype == AWORD && righttype == RPUNCT) + return SP; + else if(lefttype == RPUNCT && righttype == AWORD) + return NSP; + else if(lefttype == LPUNCT && righttype == AWORD) + return SP; + else if(lefttype & BPUNCT > 0 && righttype == lefttype) + return NSP; + else if(lefttype == LPUNCT && righttype == RPUNCT) + return SP; + else if(lefttype == BOUNDARY && righttype == BOUNDARY) + return NSP; + else if(lefttype == BOUNDARY && righttype & WORD > 0) + return NSP; + else if(lefttype & WORD > 0 && righttype == BOUNDARY) + return NSP; + else if(lefttype == LPUNCT && righttype == BOUNDARY) + return NSP; + else if(lefttype == BOUNDARY && righttype == RPUNCT) + return NSP; + else + return BAD; + } + + /** Find out the types of the words next to a word boundary. + * This may only be called on what is known to be a word boundary. + * Else, its behavior is undefined. + */ + public static final int[] wordtype(Nile3Pos pos, int dir) { + int[] res = new int[2]; + + int lch = pos.type(-1), rch = pos.type(1); + boolean lp = pos.punct(-1), rp = pos.punct(1); + Nile3Pos lpos, rpos; + if(lp) { + lpos = (Nile3Pos)pos.clone(); + while(lpos.punct(-1)) lpos.move(-1); + } + if(rp) { + rpos = (Nile3Pos)pos.clone(); + while(rpos.punct(1)) rpos.move(1); + } + + if(!lp && !rp) { + if(pos. + } + + public void cleanJoin(Nile3Pos pos, int lefttype, int righttype) { + int type = jointype(lefttype, righttype); + if(jointype == NSP) { + while(pos.ws(-1)) pos.delete(-1); + while(pos.ws(1)) pos.delete(1); + } else if(jointype == SP) { + if(!pos.ws(-1) && !pos.ws(1)) pos.insert(" ", 1); + } else { + p("Nile3Unit.Word: Detected bad joining in cleanJoin"); + } + } + + public boolean isEdge(Nile3Pos pos, int dir) { + if(pos.punct(-dir)) return true; + if(pos.bws(dir) && pos.alpha(-dir)) return true; + return false; + } + + /** Can what be inserted at pos? */ + public boolean isInsertPos(Nile3Pos pos, Nile3Part what) { + if(!pos.boundary(1) && !isEdge(pos, -1)) return false; + if(what.start.punct(1) && !what.start.bws(-1)) { + } + if(what.end.punct(-1) && !what.end.bws(1)) { + if( + } + if(jointype(pos.-1, what.start.1) == BAD) return false; + if(jointype(pos.1, what.end.-1) == BAD) return false; + } + } + + public static class Sentence extends Nile3Unit { + public boolean isEdge(Nile3Pos pos, int dir) { + if(pos.ws(dir)) return false; + if(pos.boundary(-dir)) return true; + if(!pos.move(-dir)) return false; + if((pos.bws(-dir)) && pos.ws(dir)) return true; + pos.move(dir); + return false; + } + } + + // Ugh! Paragraph is *inefficient*! + // XXX is this a problem? in very long paragraphs maybe? + public static class Paragraph extends Nile3Unit { + public boolean isEdge(Nile3Pos pos, int dir) { + return pos.boundary(-dir); + } + } + + + public boolean step(Nile3Part part, int n) { + int abs = (n < 0) ? (-n) : (n); + int dir = (n < 0) ? (-1) : (1); + Nile3Pos pos = part.side(dir), other = part.side(-dir); + for(int i=0; i 0 ? 10 : -10; } + else if(dy == 0) { ax = dx > 0 ? 10 : -10; ay = 0; } + else { + double raise = dy / (double)dx; + ax = (int)Math.sqrt(100/(raise*raise+1)); + if(dx < 0) ax = -ax; + ay = (int)(raise*ax); + } + + fact.centerFlob(into, links[i].to, links[i].to, 1, p, 0, 0, 1); + lb.l(lx, ly, p.x, p.y); + + if(links[i].dir < 0) + ab.ar(mx+ax, my+ay, mx-ax, my-ay); + else if(links[i].dir > 0) + ab.ar(mx-ax, my-ay, mx+ax, my+ay); + + if(dpt < maxdepth) + part(into, fact, links[i].to, links[i].link, x0, y0, dpt+1, + p.x, p.y, arc, arc+arcd, xd, yd, false); + } + + lb.endl(); + ab.endl(); + } + + public void raster(FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed) { + Dimension size = into.getSize(); + int x0 = size.width/2, xd = size.width / (2 * maxdepth); + int y0 = size.height/2, yd = size.height / (2 * maxdepth); + fact.centerFlob(into, accursed, accursed, 1, + new Point(x0, y0), 0, 0, 1); + part(into, fact, accursed, null, x0, y0, 1, x0, y0, + -Math.PI/2, (Math.PI/2)*3, xd, yd, true); + } + + static public ZZModule module = new ZZModule() { + public void action(String id, + ZZCell code, + ZZCell target, + ZZView view, ZZView cview, String key, Point pt, ZZScene xi) { + if(id.equals("NEW")) { + ZZCell vc = view.getViewcell(); + ZZCell c = ZZCursorReal.get(vc).N(dim1).N(dim2, -1); + ZZCursorReal.set(vc, c); + } else if(id.equals("CNCT")) { + ZZCell vc = view.getViewcell(); + ZZCell acc = ZZCursorReal.get(vc); + ZZCell[] marks = vc.readRank("d.mark", 1, false); + for(int i=0; i +#include +#include +#include +// #include +#include + +extern "C"{ +#include "jni.h" +} +#include "fi_iki_lukka_ZZOpenGLGraphics.h" + +#include "gltt/FTEngine.h" +#include "gltt/FTFace.h" +#include "gltt/FTInstance.h" +#include "gltt/FTGlyph.h" +#include "gltt/FTGlyphBitmap.h" +#include "gltt/FTGlyphPixmap.h" +#include "gltt/FTBitmapFont.h" +#include "gltt/GLTTBitmapFont.h" +#include "gltt/GLTTPixmapFont.h" +#include "gltt/GLTTOutlineFont.h" +#include "gltt/GLTTFont.h" +#include "gltt/GLTTGlyphPolygonizer.h" +#include "gltt/GLTTGlyphTriangulator.h" + + + +#include +#include +#include +#include +#include +#include + + + +/*********************************************** + * useful little macros + ************************************************/ +#define GET_THIS() jclass zzthis = env->GetObjectClass( obj ); +#define FIELD_ID(_name, _sig) env->GetFieldID( zzthis, _name, _sig) +#define SET_INT_FIELD(_name, _value) \ + env->SetIntField( obj, FIELD_ID(_name, "I"), _value) +#define GET_INT_FIELD(_name) env->GetIntField( obj, FIELD_ID(_name, "I")) + +/****************************************************** + * GLOBALS + ******************************************************/ +/* these will be in java class */ +Display *disp; +Window win; +/***/ +GLboolean db = GL_TRUE; /* doublebuffering */ +GLint disp_list = 0; +XSizeHints sizeHints = { 0 }; +XEvent event; + +GLuint base; + +int args[] = { GLX_DOUBLEBUFFER, + GLX_RGBA, + GLX_DEPTH_SIZE, + 16, + None }; + +void makeRasterFont(Display *dpy) +{ + XFontStruct *fontInfo; + Font id; + unsigned int first, last; + fontInfo = XLoadQueryFont(dpy, + "-*-courier-medium-r-normal-*-*-100-*-*-m-*-iso8859-1"); + + + if (fontInfo == NULL) { + printf ("no font found\n"); + exit (0); + } + + id = fontInfo->fid; + first = fontInfo->min_char_or_byte2; + last = fontInfo->max_char_or_byte2; + + base = glGenLists(last+1); + + if (base == 0) { + printf ("out of display lists\n"); + + exit (0); + } + + glXUseXFont(id, first, last-first+1, base+first); + +} + +/****************************************************** + * printString + ******************************************************/ +void printString(const char *s) +{ + glListBase(base); + glCallLists(strlen(s), GL_UNSIGNED_BYTE, (unsigned char *)s); +} + + + + +/****************************************************** + * getColormap + ******************************************************/ +Colormap getColormap ( XVisualInfo *vis){ + Status stat; + XStandardColormap *sCm; + Colormap cm; + int i; + int numCmaps; + + if ( vis->c_class != TrueColor ){ + printf ("No support for TrueColor!"); + exit(1); + } + + stat = XmuLookupStandardColormap(disp, vis->screen, vis->visualid, + vis->depth,XA_RGB_DEFAULT_MAP, False, True); + if (stat == 1) { + stat = XGetRGBColormaps( disp, RootWindow(disp, vis->screen), + &sCm, &numCmaps, + XA_RGB_DEFAULT_MAP); + if (stat == 1) + for( i = 0; i < numCmaps; i++ ) + if( sCm[i].visualid == vis->visualid) { + cm = sCm[i].colormap; + XFree(sCm); + return cm; + } + } + + cm = XCreateColormap (disp, RootWindow(disp,vis->screen), + vis->visual, AllocNone); + return cm; +} + + +/****************************************************** + * openWindow + ******************************************************/ +JNIEXPORT void JNICALL +Java_fi_iki_lukka_ZZOpenGLGraphics_openWindow( JNIEnv *env, + jobject obj, + jint width, + jint height) +{ + + XVisualInfo *vi; + Colormap cm; + XSetWindowAttributes xswa; + XWMHints *wmHints; + Atom wmDeleteWindow; + GLXContext cx; + char *display = NULL; + + + /** connect to X server **/ + disp = XOpenDisplay(display); + // FIX ME + if ( disp == NULL ) exit(1); + printf("__C__: openWindow\n"); + /** check for glx */ + if ( ! glXQueryExtension(disp, NULL, NULL)) + // maybe should use some constants + return;// 2; + + /** visual & colormap **/ + vi = glXChooseVisual(disp, DefaultScreen(disp),args ); + if ( ! vi ){ + // no doublebuffering + vi = glXChooseVisual(disp, DefaultScreen(disp),&args[1] ); + if ( ! vi ) exit(1); + db = GL_FALSE; + } + + cm = getColormap(vi); + + /** GL rendering context **/ + cx = glXCreateContext(disp, vi, NULL, GL_TRUE); + if ( cx == NULL ) + exit(1); + + /* some hints etc */ + xswa.colormap = cm; + xswa.border_pixel = 0; + xswa.event_mask = ExposureMask|ButtonPressMask|KeyPressMask; + sizeHints.width = width; + sizeHints.height = height; + sizeHints.x = 10; + sizeHints.y = 10; + + win = XCreateWindow(disp, RootWindow(disp,vi->screen), + sizeHints.x, sizeHints.y, + width, height, 0, vi->depth, InputOutput, + vi->visual, CWEventMask|CWBorderPixel|CWColormap, &xswa); + + wmDeleteWindow = XInternAtom(disp, "WM_DELETE_WINDOW", False); + XSetWMProtocols(disp, win, &wmDeleteWindow,1); + XSetStandardProperties(disp, win, "test", "Testi", + None, None, None, &sizeHints); + + wmHints = XAllocWMHints(); + wmHints->initial_state = NormalState; + wmHints->flags = StateHint; + XSetWMHints(disp, win, wmHints); + + /* bind context to window */ + glXMakeCurrent(disp, win, cx); + + glEnable ( GL_DEPTH_TEST ); + glEnable ( GL_ALPHA_TEST ); + glDisable ( GL_DITHER ); + glDisable ( GL_LIGHTING ); + glDisable ( GL_FOG ); + + glDisable ( GL_TEXTURE_2D ); + + glDisable ( GL_CULL_FACE ); + glDisable ( GL_SCISSOR_TEST ); + glDisable ( GL_STENCIL_TEST ); + + glViewport(0, 0, width, height); + + glMatrixMode(GL_PROJECTION); + + glLoadIdentity(); + + gluPerspective(65, (GLfloat) width + / (GLfloat) height, 1, 1000); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + gluLookAt(0, 0, 100, 0, 0, 0, 0, 1, 0); + + glMatrixMode(GL_MODELVIEW); + + XMapWindow(disp,win); + + glXSwapBuffers(disp, win); + + makeRasterFont(disp); + +} + +/****************************************************** + * drawLine + ******************************************************/ +JNIEXPORT void JNICALL +Java_fi_iki_lukka_ZZOpenGLGraphics_drawLine(JNIEnv *env, jobject obj, + jint x1, jint y1, + jint x2, jint y2){ + printf("__C__: drawLine\n"); + glBegin(GL_LINES); + + glVertex3d( x1, y1, 0 ); + glVertex3d( x2, y2, 0 ); + + glEnd(); + +} + + +JNIEXPORT void JNICALL +Java_fi_iki_lukka_ZZOpenGLGraphics_drawRect(JNIEnv *env, jobject obj, + jint x, jint y, + jint width, jint height){ + + printf("__C__: drawRect\n"); + glBegin(GL_QUADS); + + glVertex3d( x, y, 0 ); + glVertex3d( x, y+height, 0 ); + glVertex3d( x+width, y+height, 0 ); + glVertex3d( x+width, y, 0 ); + glEnd(); + +} + + +JNIEXPORT void JNICALL +Java_fi_iki_lukka_ZZOpenGLGraphics_drawPoint(JNIEnv *env, jobject obj, + jint x, jint y); + + +JNIEXPORT void JNICALL +Java_fi_iki_lukka_ZZOpenGLGraphics_drawText(JNIEnv *env, jobject obj, + jint x, jint y, + jstring text, jint size){ + int s; + //int l; + const char *str = (const char *)env->GetStringUTFChars( text, 0 ); + + printf("str = %s\n", str); + + s = env->GetStringLength( text); + + // Check the size + printf("s = %d\n", s); + glLoadIdentity(); + + /* + // + // glut stroke fonts + glTranslatef(x,y,0); + glScalef(0.03,0.03,0.03); + + + + for(l = 0; l < s; l++){ + glutStrokeCharacter(GLUT_STROKE_ROMAN , str[l]); + glTranslatef(glutStrokeWidth(GLUT_STROKE_ROMAN,str[l]),0,0); + } + */ + printf("__C__: drawText\n"); + //glColor3f(1,1,1); + + glLoadIdentity(); + + FTFace face; + if( ! face.open("/dos/winnt/Fonts/couri.ttf") ){ + printf("unable to open ttf file"); + return ; + } + + GLTTOutlineFont font(&face); + + int point_size= size; + + if( ! font.create(point_size) ){ + printf("unable to create outline font"); + return ; + } + + glTranslatef(x,y,0); + //glRotatef(45,0,1,0); + //font.setPrecision(4); + font.output( str ); + + // bitmap fonts + //printString(str); + + glLoadIdentity(); + env->ReleaseStringUTFChars( text, 0); +} + + +JNIEXPORT void JNICALL +Java_fi_iki_lukka_ZZOpenGLGraphics_drawingColor(JNIEnv *env, jobject obj, + jdouble r, jdouble g, + jdouble b, jdouble a){ + glColor4d(r,g,b,a); +} + + +JNIEXPORT void JNICALL +Java_fi_iki_lukka_ZZOpenGLGraphics_drawArrow(JNIEnv *env, jobject obj, + jint x, jint y, + jint dx, jint dy, + jint dz){ + glLoadIdentity(); + glScalef(dx,dy,dz); + glBegin(GL_LINES); + + glVertex3f(x,y,0); + glVertex3f(x,y-1,0); + + glVertex3f(x,y,0); + glVertex3f(x+2,y-2,0); + + glVertex3f(x,y,0); + glVertex3f(x+1,y,0); + + glEnd(); + glLoadIdentity(); +} + +/****************************************************** + * swapBuffers + ******************************************************/ +JNIEXPORT void JNICALL +Java_fi_iki_lukka_ZZOpenGLGraphics_swapBuffers(JNIEnv *env, + jobject obj){ + printf("__C__: swapBuffers\n"); + + glXSwapBuffers(disp,win); + + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + + glMatrixMode(GL_MODELVIEW); + +} + + +/****************************************************** + * checkEvents + ******************************************************/ +JNIEXPORT void JNICALL +Java_fi_iki_lukka_ZZOpenGLGraphics_checkEvents( JNIEnv *env, jobject obj){ + + XKeyEvent *e_key; + + XButtonEvent *e_but; + + XConfigureEvent *e_conf; + + jclass cls = env->GetObjectClass( obj ); + + jmethodID key_id = env->GetMethodID( cls, + "addKeyEvent", "(II)V"); + + jmethodID button_id = env->GetMethodID( cls, + "addButtonEvent", "(IIII)V"); + + jmethodID conf_id = env->GetMethodID( cls, + "configureEvent", "(II)V"); + + printf("__C__: Check events\n"); + + if ( button_id == 0 || key_id == 0 ) { + printf ("no method id\n"); + return ; + } + + do{ + + int ch; + int type = 0; + + XEvent event; + + XNextEvent(disp, &event); + + switch ( event.type ){ + case ConfigureNotify: + printf("ConfNotify"); + + env->CallVoidMethod( obj, conf_id, + e_conf->width, e_conf->height); + break; + case ButtonPress: + + e_but = (XButtonEvent *) &event; + env->CallVoidMethod( obj, button_id, + e_but->button, e_but->x, e_but->y, 0); + break; + case KeyPress: + + e_key = (XKeyEvent *) &event; + ch = (int )XLookupKeysym(e_key,0); + + env->CallVoidMethod( obj, key_id, ch, type); + break; + default: + + ; + } + + } while( XPending( disp ) ); + + return ; +} diff --git a/Modules/openGL/ZZOpenGLGraphics.java b/Modules/openGL/ZZOpenGLGraphics.java new file mode 100644 index 0000000..29c9d48 --- /dev/null +++ b/Modules/openGL/ZZOpenGLGraphics.java @@ -0,0 +1,606 @@ +/* +ZZGraphics.java + * + * Copyright (c) 2000, Ted Nelson, Tuomas Lukka and Vesa Parkkinen + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Vesa Parkkinen + */ + +package org.gzigzag; +import java.awt.*; +import java.util.*; +import java.awt.event.*; + +/** A class that implements the ZZGraphics interface using OpenGL. + * Tjl's comments: + *

      + *
    • You DON'T want to derive everything from OGLColorThing: that + * slows down rendering. Note how it's done in ZZCanvas: there's + * a ColorThing which sets the foreground/background color which + * is then used. + * + * A state machine... Well, whatever you want. + * Doesn't that somewhat dictate the ordering of drawing, + * what if for some reason (optimization etc.) I want to + * draw the in different order ? I admit it slows rendering, + * but I still would like to have objects with color, not just + * global pens to use in drawing, at least in the object level. + * The implementation of rendering is a completely different thing, + * and shouldn't dictate design issues. + * The actual rendering is unbeliavably simple at the moment, + * but i just wanted to get the java-C-java pipeline to work. /vp + * + * Tjl: In that case, put in a reference to a reusable OGLColorThing + * (in Design Patterns, this is called a flyweight). + * the order of drawing is an excellent point: I was still thinking + * in terms of java.awt.Graphics where order is visible; if we have + * a Z-buffer, that's right. However, if we don't use a Z-buffer, the + * order of rendering is really important. + * + * OTOH: for drawing order, using the color makes sense since in + * some cases changing the color (or material) in OpenGL + * can be one of the slowest operations. + * + * vp: That's why I would like to have attributes of objects to be + * within objects, so i could _easily_ handle them in the order + * that makes most sense at that moment. + * + *
    • For Colors, extend java.awt.Color with alpha - in Java1.2, this + * is already done. + * + * Why ? I just need 4 doubles. Of course there will be methods + * to use Color, but internally i'd like to keep color as + * doubles /vp + * + * Tjl: double = 8 bytes. 4 doubles = 32 bytes. java.awt.Color = 4 bytes. + * first of all, we want to avoid float arithmetic so using bytes or + * an integer would be better. glColor3b can be much faster. + * + * vp: well it's pretty much same to me if it is a byte, float + * or double, but I would like to put it to the format it is used + * at creation time rather than in rendering time. + * + *
    • Why does colorthing have coordinates? + * + * Because a Thing is always in space somewhere. They are objects, + * not just some global "pen swithes". /vp + * + * Tjl: see above for how to handle ColorThing - that way it doesn't + * have coordinates. + * + * One big question is: *DO* we really want actual "models" or just + * drawing things? + * Both the layer above and the layer below are about drawing with a + * pen - why have a layer with models in between? + * + * vp: As long as we already have objects why don't use them. + * It gives much more flexibility when trying to do more complex + * things. BTW, What is the layer above that is about drawing with a + * pen? + * If we would strip the awt from zzcanvas, and added a simple way + * to use any ZZGraphics, then this wouldn't be an issue: you could + * do it the way you wanted in ZZCanvas. And that is the way I think + * it should be done. + * + * + *
    • Basically, check out how ZZCanvas does things and do the same. + * Actually, we might want to think about separating the class + * structure in a way as to have an abstract base class for graphic + * beams and then two implementations, one for opengl and the other + * for awt. Or even have things implement ZZOpenGLThing interface. + * ZZCanvas is pretty abstract. + * + * I don't think so, ZZCanvas is way + * too tightly connected to awt. If one could bring his own graphics, + * with some basic methods, drawCell, drawLink etc., then it would + * be good. In fact that is the way I think it should be done. /vp + * + * Tjl: Explain further. The connection to awt is actually limited to + * the methods render*. + * + * vp: Exactly. We should have ZZCanvas(zzgraphics g), so we could use + * zzcanvas with any graphics we would like to implement. All rendering + * would go through that zzgraphics. So every render method + * should have something like g.drawLine, where g is zzgraphics not + * graphics. + * + *
    • if you extend Component, do you need addKeyListener and + * addMouseListener? + * + * If I want to throw my own keyevents, yes./vp + * + * they are already implemented there. + * + * Is there somewhere a method to fire your own key & mouse events? /vp + * + * Alternatively, not deriving from Component might be good. + * + * I know, I should have added a Component and used that to fire + * those events... /vp + * + * java.awt.Component.processEvent(KeyEvent) /vp + * + *
    + */ + +public class ZZOpenGLGraphics extends Component implements ZZGraphics, Runnable { + String rcsid = "$Id: ZZOpenGLGraphics.java,v 1.9 2000/11/05 12:49:39 tjl Exp $"; + + public static final boolean dbg = true; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + + KeyListener actionListener = null; + + public void addKeyListener(KeyListener l) { + actionListener = AWTEventMulticaster.add(actionListener, l); + } + public void removeKeyListener(KeyListener l) { + actionListener = AWTEventMulticaster.remove(actionListener, l); + } + public void processKeyEvent(KeyEvent e) { + + if (actionListener != null) { + actionListener.keyPressed(e); + } + } + + MouseListener mouseListener = null; + + public void addMouseListener(MouseListener l) { + mouseListener = AWTEventMulticaster.add(mouseListener, l); + } + + public void removeMouseListener(MouseListener l) { + mouseListener = AWTEventMulticaster.remove(mouseListener, l); + } + + + public void processMouseEvent(MouseEvent e) { + + if (mouseListener != null){ + mouseListener.mouseClicked(e); + } + } + + int GLcontext = 0; + int window = 0; + int display = 0; + + int font_Size = 10; + + /* just testing */ + int cx = 0; + int cy = 0; + int cz = 50; + + + + Vector things = new Vector(); + + + public abstract class OGLThing { + + int x; + int y; + + OGLThing(int x, int y ){ + this.x = x; + this.y = y; + } + + OGLThing( ){ + x = 0; + y = 0; + } + + public void coords(int x, int y) { + this.x = x; + this.y = y; + } + + public int getX() { return x; } + + public int getYs() { return y; } + + // rendes to this context + public abstract void render(); + + } + + public class OGLColorThing extends OGLThing{ + + float r; + float g; + float b; + float a; + + OGLColorThing(int x, int y, float r, float g, float b, float a){ + super(x,y); + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + + OGLColorThing(){ + super(); + this.r = 1; + this.g = 1; + this.b = 1; + this.a = 1; + + } + + OGLColorThing(int x, int y){ + super(x,y); + this.r = 1; + this.g = 1; + this.b = 1; + this.a = 1; + + } + + OGLColorThing(Color c){ + super(0,0); + setColor(c); + + } + + public void setColor(Color c){ + + } + + public void setColor(int r, int g, int b, int a){ + this.r = r; + this.g = g; + this.b = b; + this.a = a; + + } + + public void render(){ + p("COLOR: RENDER\n"); + /* this is just a temporary solution, + add checking of color */ + drawingColor(r,g,b,a); + } + } + + public abstract class OGLCell extends OGLColorThing{ + + ZZCell c; + + public OGLCell(){ + super(); + c = null; + } + + public OGLCell(int x, int y, ZZCell c){ + super(x,y); + this.c = c; + } + public OGLCell( ZZCell c ){ + super(); + this.c = c; + } + + } + + public class OGL2DCell extends OGLCell { + + int width; + int height; + + + + public OGL2DCell(){ + super(); + width = 0; + height = 0; + } + + public OGL2DCell(int x, int y, int width, int height, ZZCell cell){ + super(x,y,cell); + this.width = width; + this.height = height; + + } + + public void render(){ + + super.render(); + + p("CELL: RENDER" + x + " " +y); + + drawRect(x,y,width,height); + + if( c != null ) { + drawingColor(0,0,0,1); + + drawText(x+2, y+2, c.getText(),10); + } + } + } + + public class OGLText extends OGLColorThing{ + int size; + String text; + + public OGLText(int x, int y, String txt){ + super(x,y); + text = txt; + size = 10; + } + + public void render(){ + //super.render(); + drawText(x, y, text, size ); + } + } + + public class OGLLink extends OGLColorThing{ + + int x2; + int y2; + + OGLLink(int x1, int y1, int x2, int y2){ + super(x1,y1); + this.x2 = x2; + this.y2 = y2; + } + + public void render(){ + super.render(); + drawLine(super.x,super.y, x2, y2); + } + + } + + public class OGLLine extends OGLColorThing{ + int x2; + int y2; + + OGLLine(int x1, int y1, int x2, int y2){ + super(x1,y1); + this.x2 = x2; + this.y2 = y2; + } + + public void render(){ + super.render(); + drawLine(super.x,super.y, x2, y2); + } + + } + + public class OGLMark extends OGLColorThing{ + + ZZCell c; + + int h; + + OGLMark(int x1, int y1, int h, ZZCell c){ + super(x1,y1); + this.c = c; + this.h = h; + } + + public void render(){ + super.render(); + drawLine(super.x,super.y, x, y+h); + } + + } + + + class OGLArrow extends OGLColorThing{ + // Hmm... + int dir_x; + int dir_y; + int dir_z; + + public OGLArrow(int x, int y){ + super(x,y); + dir_x = 2; + dir_y = 2; + dir_z = 1; + } + + public void render(){ + super.render(); + drawArrow(super.x,super.y, dir_x, dir_y, dir_z); + } + } + + public Dimension getSize(){ + return null; + } + + public Dimension getDefaultCellSize(ZZCell c){ + return null; + } + + public void putCell(ZZCell c, int x, int y, int w, int h, String style){ + things.addElement(new OGL2DCell(x,y,w,h,c)); + } + + public void putLinks(String dim, float dx, float dy){ + + } + +// public void putBeams(ZZCanvasTextSpanSet set1, ZZCanvasTextSpanSet set2){ +// +// } + + public void setColor(Color c){} + + public int getDefaultFontSize(){ return 0;} + + public FontMetrics getFontMetrics(Font f){ return null;} + + public void setFont(Font f){} + + public void putPolyLine(int x1, int y1, int x2, int y2, String style){} + + public void putText(String s, int x, int y){ + things.addElement(new OGLText(x,y,s)); + } + + public void putText(String s, int x, int y, int size){ + things.addElement(new OGLText(x,y,s)); + } + /* + public void putText(String s, int x, int y, int z){ + things.addElement(new OGLText(x,y,z,s)); + } + */ + + public Object putSpan(Span s, String str, ZZCell c, int x, int y, + int w, int h, int xoffs, int yoffs, + ZZCanvasTextSpanSet collect, + Object prev, + Font f, FontMetrics fm){ + return null;} + + public void putTextMark(int x, int y, int h, ZZCell mkc){ + things.addElement(new OGLMark(x,y,h, mkc)); + } + + public void putLine(int x1, int y1, int x2, int y2, String style){ + //drawLine(x1, y1, x2, y2); + things.addElement(new OGLLine(x1,y1,x2,y2)); + + } + + public void putCoordNames(String[] names){} + + public void putArrow( int x1, int y1, + int x2, int y2, + Color intern, String style){ + things.addElement(new OGLArrow(x1,y1)); + } + +// public void putDragCursor(ZZGraphics.DragCursor dc, int x, int y){} + + // public class OpenGLDragCursor implements ZZGraphics.DragCursor { +// public boolean accept(Object o){ return false; } + // } + + static { + System.loadLibrary("zz3d"); + } + + public void render(){ + p("RENDER:"); + + for (Enumeration e = things.elements() ; e.hasMoreElements() ;) { + ((OGLThing)e.nextElement()).render(); + } + + swapBuffers(); + + } + + private Thread thread = null; + + public void start() { + if (thread == null) { + thread = new Thread(this, "render"); + thread.start(); + } + } + + + public void run() { + + Thread myThread = Thread.currentThread(); + p("RUN:"); + + while (thread == myThread) { + checkEvents(); + render(); + try { + Thread.sleep(100); + } catch (InterruptedException e){ + // the VM doesn't want us to sleep anymore, + // so get back to work + } + } + } + + void addKeyEvent(int key, int type){ + p("KEY_EVENT: " + (char)key + " " + type); + // XXX add missing info: time, modifiers ... + processKeyEvent(new KeyEvent(this,1000,1,0,key,(char)key)); + } + + void addButtonEvent(int button, int x, int y, int modifiers){ + p("BUTTON_EVENT: " + button + " " + x + y); + processMouseEvent(new MouseEvent(this,1001,1,0,x,y,1,false)); + } + + void configureEvent(int x, int y){ + p("CONFIGURE_EVENT:" + x + " " + y); + } + + /******************/ + /* NATIVE METHODS */ + /******************/ + + /** + * This is supposed to create a native window, put right values + * to variales in this class, create glx context... + * + */ + public native void openWindow( int width, int height ); + + public native void drawLine( int x1, int y1, int x2, int y2 ); + + public native void draw3DLine( int x1, int y1, int z1, + int x2, int y2, int z2 ); + + public native void drawRect( int x, int y, int width, int height ); + + public native void draw2DPoint( int x, int y ); + + public native void draw3DPoint( int x, int y, int z ); + + public native void drawText( int x, int y, String text, int size ); + + public native void draw3DText( int x, int y, int z, + String text, int size ); + + public native void drawingColor( double r, double g, double b, double a ); + + public native void drawArrow(int x, int y, + int dir_x, int dir_y, int dir_z); + + public native void draw3DArrow(int x, int y, int z, + int dir_x, int dir_y, int dir_z); + + public native void swapBuffers(); + + public native void checkEvents(); + + public native void setCamera( int x, int y, int z, + int ex, int ey, int ez, + int lx, int ly, int lz ); +} + diff --git a/Modules/openGL/fi_iki_lukka_ZZOpenGLGraphics.h b/Modules/openGL/fi_iki_lukka_ZZOpenGLGraphics.h new file mode 100644 index 0000000..c733d44 --- /dev/null +++ b/Modules/openGL/fi_iki_lukka_ZZOpenGLGraphics.h @@ -0,0 +1,125 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class fi_iki_lukka_ZZOpenGLGraphics */ + +#ifndef _Included_fi_iki_lukka_ZZOpenGLGraphics +#define _Included_fi_iki_lukka_ZZOpenGLGraphics +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: fi_iki_lukka_ZZOpenGLGraphics + * Method: openWindow + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_fi_iki_lukka_ZZOpenGLGraphics_openWindow + (JNIEnv *, jobject, jint, jint); + +/* + * Class: fi_iki_lukka_ZZOpenGLGraphics + * Method: drawLine + * Signature: (IIII)V + */ +JNIEXPORT void JNICALL Java_fi_iki_lukka_ZZOpenGLGraphics_drawLine + (JNIEnv *, jobject, jint, jint, jint, jint); + +/* + * Class: fi_iki_lukka_ZZOpenGLGraphics + * Method: draw3DLine + * Signature: (IIIIII)V + */ +JNIEXPORT void JNICALL Java_fi_iki_lukka_ZZOpenGLGraphics_draw3DLine + (JNIEnv *, jobject, jint, jint, jint, jint, jint, jint); + +/* + * Class: fi_iki_lukka_ZZOpenGLGraphics + * Method: drawRect + * Signature: (IIII)V + */ +JNIEXPORT void JNICALL Java_fi_iki_lukka_ZZOpenGLGraphics_drawRect + (JNIEnv *, jobject, jint, jint, jint, jint); + +/* + * Class: fi_iki_lukka_ZZOpenGLGraphics + * Method: draw2DPoint + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_fi_iki_lukka_ZZOpenGLGraphics_draw2DPoint + (JNIEnv *, jobject, jint, jint); + +/* + * Class: fi_iki_lukka_ZZOpenGLGraphics + * Method: draw3DPoint + * Signature: (III)V + */ +JNIEXPORT void JNICALL Java_fi_iki_lukka_ZZOpenGLGraphics_draw3DPoint + (JNIEnv *, jobject, jint, jint, jint); + +/* + * Class: fi_iki_lukka_ZZOpenGLGraphics + * Method: drawText + * Signature: (IILjava/lang/String;I)V + */ +JNIEXPORT void JNICALL Java_fi_iki_lukka_ZZOpenGLGraphics_drawText + (JNIEnv *, jobject, jint, jint, jstring, jint); + +/* + * Class: fi_iki_lukka_ZZOpenGLGraphics + * Method: draw3DText + * Signature: (IIILjava/lang/String;I)V + */ +JNIEXPORT void JNICALL Java_fi_iki_lukka_ZZOpenGLGraphics_draw3DText + (JNIEnv *, jobject, jint, jint, jint, jstring, jint); + +/* + * Class: fi_iki_lukka_ZZOpenGLGraphics + * Method: drawingColor + * Signature: (DDDD)V + */ +JNIEXPORT void JNICALL Java_fi_iki_lukka_ZZOpenGLGraphics_drawingColor + (JNIEnv *, jobject, jdouble, jdouble, jdouble, jdouble); + +/* + * Class: fi_iki_lukka_ZZOpenGLGraphics + * Method: drawArrow + * Signature: (IIIII)V + */ +JNIEXPORT void JNICALL Java_fi_iki_lukka_ZZOpenGLGraphics_drawArrow + (JNIEnv *, jobject, jint, jint, jint, jint, jint); + +/* + * Class: fi_iki_lukka_ZZOpenGLGraphics + * Method: draw3DArrow + * Signature: (IIIIII)V + */ +JNIEXPORT void JNICALL Java_fi_iki_lukka_ZZOpenGLGraphics_draw3DArrow + (JNIEnv *, jobject, jint, jint, jint, jint, jint, jint); + +/* + * Class: fi_iki_lukka_ZZOpenGLGraphics + * Method: swapBuffers + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_fi_iki_lukka_ZZOpenGLGraphics_swapBuffers + (JNIEnv *, jobject); + +/* + * Class: fi_iki_lukka_ZZOpenGLGraphics + * Method: checkEvents + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_fi_iki_lukka_ZZOpenGLGraphics_checkEvents + (JNIEnv *, jobject); + +/* + * Class: fi_iki_lukka_ZZOpenGLGraphics + * Method: setCamera + * Signature: (IIIIIIIII)V + */ +JNIEXPORT void JNICALL Java_fi_iki_lukka_ZZOpenGLGraphics_setCamera + (JNIEnv *, jobject, jint, jint, jint, jint, jint, jint, jint, jint, jint); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Modules/panes/PaneView.zob b/Modules/panes/PaneView.zob new file mode 100644 index 0000000..acac4ed --- /dev/null +++ b/Modules/panes/PaneView.zob @@ -0,0 +1,76 @@ +/* +PaneView.zob + * + * Copyright (c) 2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** A view that shows different other views on different panes. + * Like the SplitNileView, but more generally useful. Currently, exactly two + * panes are shown. + */ + +public class PaneView implements FlobView, ZOb { +public static final String rcsid = "$Id: PaneView.zob,v 1.1 2001/01/20 08:52:40 bfallenstein Exp $"; + + public static final boolean dbg = true; + private static final void p(String s) { if(dbg) System.out.println(s); } + private static final void pa(String s) { System.out.println(s); } + + STRUCTPARAMS { + /** The space to leave between the two panes. */ + int space + = 20; + } + + public void raster(FlobSet into, FlobFactory fact, + ZZCell win, String[] dims, ZZCell accursed) { + ZZCell lpane = win.s("d.panes", 1); + ZZCell rpane = win.s("d.panes", 2); + if(rpane == null) + throw new ZZError("No panes found for PaneView"); + + ZZCell leftacc = ZZCursorReal.get(lpane); + ZZCell rightacc = ZZCursorReal.get(rpane); + + ZZCell lapp = lpane.h("d.pane-app"); + ZZCell rapp = rpane.h("d.pane-app"); + ZZCell linkapp = win.h("d.pane-link-app"); + + Dimension size = new Dimension(into.getSize()); + size.width = (size.width - space) / 2; + FlobSet left = into.create(size), right = into.create(size); + + FlobView view = ApplitudeMgr.getView(lapp); + view.raster(left, fact, lpane, dims, leftacc); + + view = ApplitudeMgr.getView(rapp); + view.raster(right, fact, rpane, dims, rightacc); + + into.fetch(left, 0, 0, 0); + into.fetch(right, size.width + space, 0, 0); + + view = ApplitudeMgr.getView(linkapp); + view.raster(into, fact, win, dims, accursed); + } + +} \ No newline at end of file diff --git a/Modules/prez/Prez.java b/Modules/prez/Prez.java new file mode 100644 index 0000000..658033d --- /dev/null +++ b/Modules/prez/Prez.java @@ -0,0 +1,51 @@ +/* +Prez.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.awt.*; +import java.util.*; +import java.io.*; + +/** A simple presentation module. + */ + +public class Prez { +public static final String rcsid = "$Id: Prez.java,v 1.4 2000/09/19 10:32:03 ajk Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + static public ZZModule module = new ZZModule() { + public void action(String id, + ZZCell code, + ZZCell target, + ZZView view, ZZView cview, String key, Point pt, ZZScene xi) { + } + public ZOb newZOb(String id) { + if(id.equals("R")) + return new PrezRaster(); + + return null; + } + }; +} diff --git a/Modules/prez/PrezRaster.zob b/Modules/prez/PrezRaster.zob new file mode 100644 index 0000000..5eda7f2 --- /dev/null +++ b/Modules/prez/PrezRaster.zob @@ -0,0 +1,173 @@ +/* +Prez.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka and Asko Soukka + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.awt.*; +import java.util.*; +import java.io.*; + +/** A simple presentation raster. + * The structure is described along three dimensions: + * hierarchy, sibling and cross-reference (x, y and z). + * On these, the hierarchy is arranged as a corner list with an empty + * corner cell, and the cross-references are simply siblings + * connected. + */ + +public class PrezRaster implements FlobView, ZOb { + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + STRUCTPARAMS { + /** The vstream raster used for the header. */ + ZOb hdrvs // VStreamRaster + = new RankTextView() {{ + width = 650; + dim = "d.foo"; + }}; + /** The vstream raster used for the items. */ + ZOb txtvs // RankTextView + = new RankTextView() {{ + width = 500; + dim = "d.foo"; + }}; + /** The vstream raster used for the crossrefs. */ + ZOb xrefvs // RankTextView + = new RankTextView() {{ + width = 500; + dim = "d.foo"; + }}; + + /** The amount to shift the header. */ + int hdrindent + = 30; + + /** The amount to shift the items. */ + int indent + = 50; + + /** The amount to space the items. */ + int space + = 30; + + int topmargin + = 120; + + int afterhdr + = 0; + + ScalableFont hdrfont + = new ScalableFont("SansSerif", Font.PLAIN, 32); + + ScalableFont txtfont + = new ScalableFont("SansSerif", Font.PLAIN, 24); + + ScalableFont xreffont + = new ScalableFont("SansSerif", Font.PLAIN, 10); + + int hdrwidth + = 650; + int txtwidth + = 500; + } + + String next = "d.2"; + String hier = "d.1"; + String cross = "d.3"; + + public void raster(FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed) { + + hier = dims[0]; + next = dims[1]; + cross = dims[2]; + + ZZCell hdr = null; + + /* Something to work with circular ranks. + * Goes rank backwards and gets the first available cell + * on the negative direction on the hier-dimension. + * Otherwise gets the accursed cell. */ + hdr = accursed.s(hier, -1); + int i = -1; + while (hdr == null) { + if (accursed.s(next, i) == null) break; + hdr = accursed.s(next, i).s(hier, -1); + if (i < -20) break; + i--; + } + + if (hdr == null) hdr = accursed; + + RankTextView hdrvs = (RankTextView)this.hdrvs; + RankTextView txtvs = (RankTextView)this.txtvs; + RankTextView xrefvs = (RankTextView)this.xrefvs; + + hdrvs.font = hdrfont; + txtvs.font = txtfont; + xrefvs.font = xreffont; + + hdrvs.width = hdrwidth; + txtvs.width = txtwidth; + + hdrvs.readParams(null); + txtvs.readParams(null); + xrefvs.readParams(null); + + int y = topmargin; + Rectangle bds = hdrvs.raster(into, hdr, 0, false, + hdrindent, y); + p("Raster 1: "+bds); + + y += bds.height + afterhdr; + + ZZCell cur = hdr.s(hier, 1); + if(cur == null) return; + + LoopDetector l = new LoopDetector(); + while(true) { + cur = cur.s(next, 1); + if(cur == null) break; + if(cur == hdr.s(hier, 1)) break; + l.detect(cur); + bds = txtvs.raster(into, cur, 0, false, indent, y); + p("Raster n: "+bds); + // indicate that there is more + if(cur.s(hier, 1) != null) { + into.add(new LineDecor(bds.x+bds.width, bds.y, + bds.x+bds.width, bds.y+bds.height, + Color.blue, 1)); + } + if(cur.s(cross, -1) != null) + xrefvs.raster(into, cur.s(cross,-1), + 0, false, 400, bds.y-15); + if(cur.s(cross, 1) != null) + xrefvs.raster(into, cur.s(cross,1), + 0, false, 400, bds.y+bds.height+5); + + y += bds.height + space; + } + } +} +// vim: set syntax=java : diff --git a/Modules/servlet/VCServlet.java b/Modules/servlet/VCServlet.java new file mode 100644 index 0000000..8b4b5a0 --- /dev/null +++ b/Modules/servlet/VCServlet.java @@ -0,0 +1,144 @@ +/* +VCServlet.java + * + * Copyright (c) 2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; +import java.io.*; + + +/** A Virtual Community demo servlet. + */ + +public class VCServlet extends ZZServlet { +public static final String rcsid = "$Id: VCServlet.java,v 1.2 2001/02/28 03:02:56 tjl Exp $"; + + String getURL(ZZCell c) { + return "org.gzigzag.module.VCServlet?"+c.getID(); + } + + void printAuthor(ZZCell txt, PrintWriter wr) { + ZZCell h = txt.h("d.author", true); + if(h != null) { + wr.print(""+h.getText()+""); + } + } + + void printmsg(ZZCell h, PrintWriter wr) { + printAuthor(h, wr); + wr.print(": "); + wr.print(""+ h.getText() + ""); + } + + void printRefs(ZZCell thing, PrintWriter wr) { + wr.print("

    Referenced in:

      "); + while((thing = thing.s("d.kahva")) != null) { + ZZCell h = thing.h("d.text"); + wr.print("
    • "); + printmsg(h, wr); + } + wr.print("
    \n"); + } + + void printAuthored(ZZCell thing, PrintWriter wr) { + wr.print("

    Messages written:

      "); + while((thing = thing.s("d.author")) != null) { + ZZCell h = thing.h("d.text"); + wr.print("
    • "); + wr.print(""+ h.getText() + ""); + } + wr.print("
    \n"); + } + + void printReplies(ZZCell thing, PrintWriter wr) { + thing = thing.s("d.replies"); + if(thing == null) return; + + wr.print("

    Replies:

      "); + while((thing = thing.s("d.replies-list")) != null) { + ZZCell h = thing.h("d.text"); + wr.print("
    • "); + printmsg(h, wr); + } + wr.print("
    \n"); + } + + + void printText(ZZCell start, PrintWriter wr) { + wr.print("

    "+start.getText()+"

    "); + ZZCell im = start.h("d.images", true); + if(im != null) { + wr.print(""); + } + printAuthor(start, wr); + wr.print("

    "); + ZZCell orig = start; + while((start = start.s("d.text")) != null) { + ZZCell h = start.h("d.kahva", true); + String txt = start.getText(); + if(h != null) { + txt = ""+ txt + ""; + } + wr.print(txt); + } + if(orig.s("d.author", -1) == null) + printAuthored(orig, wr); + ZZCell inreply = orig.h("d.replies-list").s("d.replies",-1); + if(inreply != null) { + wr.print("

    In reply to "); + printmsg(inreply, wr); + } + printReplies(orig, wr); + + printRefs(orig, wr); + } + + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException { + try { + synchronized(space) { + // resp.getWriter().print("HELLO\n\n!!\n\n"); + String s = req.getQueryString(); + PrintWriter wr = resp.getWriter(); + wr.print("HELLO\n\n!!\n\n Query: '"+s+"'\n"); + ZZCell c; + if(s == null || s.equals("")) + c = space.getHomeCell().s("d.1"); + else + c = space.getCellByID(s); + wr.print("
    Cell content: '"+c.getText()+"'\n"); + + printText(c, wr); + + wr.close(); + } + } catch(Exception e) { + throw new ServletException("doGet: ", e); + } + } + +} + + diff --git a/Modules/servlet/ZZServlet.java b/Modules/servlet/ZZServlet.java new file mode 100644 index 0000000..def768e --- /dev/null +++ b/Modules/servlet/ZZServlet.java @@ -0,0 +1,78 @@ +/* +ZZServlet.java + * + * Copyright (c) 2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; +import java.io.*; + + +/** A base class for servlets based on ZZ spaces. + */ + +public class ZZServlet extends HttpServlet { +public static final String rcsid = "$Id: ZZServlet.java,v 1.1 2001/01/17 14:27:20 tjl Exp $"; + + static Hashtable spaces = new Hashtable(); + static Object lock = new Object(); + + static ZZSpace getSpace(String name) { + synchronized(lock) { + ZZSpace s = (ZZSpace)spaces.get(name); + if(s == null) { + File f = new File(name); + s = new ZZCacheDimSpace(new DirStreamSet(f)); + spaces.put(name, s); + } + return s; + } + } + + + ZZSpace space; + + public void init(ServletConfig config) throws ServletException { + synchronized(lock) { + String s = config.getInitParameter("space"); + if(s == null) { + // throw new ServletException("No space specified!"); + s = "/tmp/testspace"; + } + space = getSpace(s); + } + } + + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException { + try { + synchronized(space) { + resp.getWriter().print("HELLO\n\n!!\n\n"); + } + } catch(Exception e) { + throw new ServletException("doGet: ", e); + } + } + +} + diff --git a/Modules/servlet/startjetty b/Modules/servlet/startjetty new file mode 100644 index 0000000..d99a6d6 --- /dev/null +++ b/Modules/servlet/startjetty @@ -0,0 +1,4 @@ +#!/bin/sh + +# java com.mortbay.HTTP.Configure.ServletServer 8080 . . +java com.mortbay.Jetty.Server ../Modules/servlet/zzserv2.prp diff --git a/Modules/servlet/zzserv.prp b/Modules/servlet/zzserv.prp new file mode 100644 index 0000000..11b00e7 --- /dev/null +++ b/Modules/servlet/zzserv.prp @@ -0,0 +1,42 @@ +*.CLASS : com.mortbay.HTTP.HttpServer +*.LISTENER.*.CLASS : com.mortbay.HTTP.HttpListener +*.*.Log.CLASS : com.mortbay.HTTP.Handler.LogHandler +*.*.Auth.CLASS : com.mortbay.HTTP.Handler.BasicAuthHandler +*.*.Alias.CLASS : com.mortbay.HTTP.Handler.TranslateHandler +*.*.Filter.CLASS : com.mortbay.HTTP.Handler.FilterHandler +*.*.Html.CLASS : com.mortbay.HTTP.Filter.HtmlFilter +*.*.Param.CLASS : com.mortbay.HTTP.Handler.ParamHandler +*.*.Session.CLASS : com.mortbay.HTTP.Handler.SessionHandler +*.*.Servlet.CLASS : com.mortbay.HTTP.Handler.ServletHandler +*.*.File.CLASS : com.mortbay.HTTP.Handler.FileHandler +*.*.Forward.CLASS : com.mortbay.HTTP.Handler.ForwardHandler +*.*.NotFound.CLASS : com.mortbay.HTTP.Handler.NotFoundHandler +*.*.Proxy.CLASS : com.mortbay.HTTP.Handler.ProxyHandler +*.*.DefaultEx.CLASS : com.mortbay.HTTP.Handler.DefaultExceptionHandler +*.*.TerseEx.CLASS : com.mortbay.HTTP.Handler.TerseExceptionHandler + +*.*.ZZServer.CLASS : org.gzigzag.module.ZZServlet +*.*.Servlet.PROPERTY.SERVLET.ZZServer.CLASS : org.gzigzag.module.ZZServlet +*.*.Servlet.PROPERTY.SERVLET.ZZServer.PROPERTY.space : /home/tjl/tspc +*.*.Servlet.PROPERTY.CLASSPATH : /home/tjl/gzigzag/Java/org/gzigzag:/home/tjl/gzigzag/Java/org/gzigzag/module:/home/tjl/gzigzag/Java/ + +SERVERS : main +main.root.PATHS : / + +main.LISTENER.all.ADDRS : 0.0.0.0:8080;127.0.0.1:8888 +main.LISTENERS : all +main.STACKS : root + + + +main.root.HANDLERS : Servlet;NotFound + +*.*.Servlet.PROPERTY.PATHS : / + +*.*.Servlet.PROPERTY.Loader : com.mortbay.HTTP.Handler.FileJarServletLoader +*.*.Servlet.PROPERTY.AutoReloadDynamicServlets : True +*.*.Servlet.PROPERTY.SERVLET.*.Initialize : False +*.*.Servlet.PROPERTY.SERVLET.Dump.Initialize : True +*.*.Filter.PROPERTY.Html.CLASS : com.mortbay.HTTP.Filter.HtmlFilter + + diff --git a/Modules/servlet/zzserv2.prp b/Modules/servlet/zzserv2.prp new file mode 100644 index 0000000..a22d05d --- /dev/null +++ b/Modules/servlet/zzserv2.prp @@ -0,0 +1,205 @@ +# ======================================================================== +# Abbreviated Configuration file for com.mortbay.Jetty.Demo +# +# The format of this file is parsed by the com.mortbay.Util.PropertyTree +# class and interpreted by the com.mortbay.Jetty.Server class to +# construct, configure and start 1 or more HttpServer instances. +# +# This configuration file is abbrevited using the features of +# com.mortbay.Util.PropertyTree. It can be run with the command +# java com.mortbay.Jetty.Server etc/JettyMinimalDemo.prp +# +# A none abbreviated version of this configuration can be seen in +# JettyDemo.prp and associated files +# ------------------------------------------------------------------------ + +# ======================================================================== +# Default CLASS definitions +# ------------------------------------------------------------------------ +*.CLASS : com.mortbay.HTTP.HttpServer +*.LISTENER.*.CLASS : com.mortbay.HTTP.HttpListener +*.*.Log.CLASS : com.mortbay.HTTP.Handler.LogHandler +*.*.Auth.CLASS : com.mortbay.HTTP.Handler.BasicAuthHandler +*.*.Alias.CLASS : com.mortbay.HTTP.Handler.TranslateHandler +*.*.Filter.CLASS : com.mortbay.HTTP.Handler.FilterHandler +*.*.Html.CLASS : com.mortbay.HTTP.Filter.HtmlFilter +*.*.Param.CLASS : com.mortbay.HTTP.Handler.ParamHandler +*.*.Session.CLASS : com.mortbay.HTTP.Handler.SessionHandler +*.*.Servlet.CLASS : com.mortbay.HTTP.Handler.ServletHandler +*.*.File.CLASS : com.mortbay.HTTP.Handler.FileHandler +*.*.Forward.CLASS : com.mortbay.HTTP.Handler.ForwardHandler +*.*.NotFound.CLASS : com.mortbay.HTTP.Handler.NotFoundHandler +*.*.Proxy.CLASS : com.mortbay.HTTP.Handler.ProxyHandler +*.*.DefaultEx.CLASS : com.mortbay.HTTP.Handler.DefaultExceptionHandler +*.*.TerseEx.CLASS : com.mortbay.HTTP.Handler.TerseExceptionHandler + +# ======================================================================== +# Default Servlet CLASS definitions +# ------------------------------------------------------------------------ +*.*.Servlet.PROPERTY.SERVLET.Dump.CLASS : com.mortbay.Servlets.Dump +*.*.Servlet.PROPERTY.SERVLET.Exit.CLASS : com.mortbay.Servlets.Exit +*.*.Servlet.PROPERTY.SERVLET.Session.CLASS : com.mortbay.Servlets.SessionDump +*.*.Servlet.PROPERTY.SERVLET.PropertyTree.CLASS: com.mortbay.Servlets.PropertyTreeEditor +*.*.Servlet.PROPERTY.SERVLET.Config.CLASS : com.mortbay.Servlets.ConfigDump +*.*.Servlet.PROPERTY.SERVLET.Debug.CLASS : com.mortbay.Servlets.DebugServlet +*.*.Servlet.PROPERTY.SERVLET.Laf.CLASS : com.mortbay.Servlets.LookAndFeelServlet +# ======================================================================== +# Default ServletHandler Properties +# ------------------------------------------------------------------------ +*.*.Servlet.PROPERTY.PATHS : /servlet/;/SERVLET/;/Servlet/ +*.*.Servlet.PROPERTY.CLASSPATH : ./servlets +*.*.Servlet.PROPERTY.Loader : com.mortbay.HTTP.Handler.FileJarServletLoader +*.*.Servlet.PROPERTY.AutoReloadDynamicServlets : True +*.*.Servlet.PROPERTY.SERVLET.*.Initialize : False +*.*.Servlet.PROPERTY.SERVLET.Dump.Initialize : True +*.*.Filter.PROPERTY.Html.CLASS : com.mortbay.HTTP.Filter.HtmlFilter + +# ======================================================================== +# Default FileHandler Properties +# ------------------------------------------------------------------------ +*.*.File.PROPERTY.AllowPut : False +*.*.File.PROPERTY.AllowDelete : False +*.*.File.PROPERTY.AllowDir : True +*.*.File.PROPERTY.Indexes : index.html;index.htm +*.*.File.PROPERTY.MaxCachedFiles : 100 +*.*.File.PROPERTY.MaxCachedFileSize : 8192 + + +# ======================================================================== +# Define the server instances to be configured by this file: +# SERVERS - list if defined server names +# PROPERTY.* - Definition of global properties +# PROPERTIES - File of globl properties +# servername.* - PropertyTree describing server "servername". +# +# Defined global properties are: +# DefaultPageType - The class name of the default com.mortbay.HTML.Page +# type. +# ------------------------------------------------------------------------ +SERVERS : main;proxy +PROPERTY.DefaultPageType : com.mortbay.Jetty.JettyLaF + +# ======================================================================== +# Define the server instance named "main" +# CLASS - The class name of the server. Must either be +# com.mortbay.HTTP.HttpServer or a decendant. +# LISTENER.name.CLASS - HttpListener classname or decendant +# LISTENER.name.ADDRS - List of addresses and ports to listen on +# STACKS - List of handler stack names. +# EXCEPTIONS - List of exception handler stack names. +# PROPERTY.* - Properties for this server +# PROPERTIES - File of properties for this server. +# +# Defined server properties are: +# SessionMaxInactiveInterval - Max idle time Ms before session death +# MinListenerThreads - Min listener threads per listener +# MaxListenerThreads - Max listener threads per listener +# MaxListenerThreadIdleMs - Max idle time Ms before listen thread +# death +# MimeMap - Property file of MIME mappings +# +# ------------------------------------------------------------------------ +main.LISTENERS : all +main.LISTENER.all.ADDRS : 0.0.0.0:8080;127.0.0.1:8888 +main.STACKS : root;files +main.EXCEPTIONS : defaultEx +main.PROPERTY.SessionMaxInactiveInterval : 3600 +main.PROPERTY.MinListenerThreads : 3 +main.PROPERTY.MaxListenerThreads : 20 +main.PROPERTY.MaxListenerThreadIdleMs : 60000 +# XXX +# main.PROPERTY.MimeMap : ./etc/Mime.prp + +# ======================================================================== +# Define the handler instances handler stack "root" in server "main" +# PATHS - List of PathMap path specifiactions for this stack +# HANDLERS - List of handler names for this stack. +# EXCEPTIONS - List of exception handler names for this stack. +# name.CLASS - The classname for the handler "name" +# name.PROPERTY.* - Properties defined for handler "name" +# name.PROPERTIES - file of properties defined for handler "name" +# ------------------------------------------------------------------------ +main.root.PATHS : / +main.root.HANDLERS : Log;Auth;Alias;Filter;Param;Session;Servlet;File;Forward;NotFound +main.root.Log.PROPERTY.File : ./log/demo.log +main.root.Log.PROPERTY.Append : False +main.root.Log.PROPERTY.LongForm : True +main.root.Log.PROPERTY.CountContentLength : False +main.root.Log.PROPERTY.DateFormat : dd/MMM/yyyy:HH:mm:ss +# main.root.Auth.PROPERTIES : ./etc/JettyDemoRealms.prp +# main.root.Alias.PROPERTIES : ./etc/JettyDemoAlias.prp +main.root.Filter.PROPERTY.Html.PATHS : / +main.root.Param.PROPERTY.CookiesAsParameters : False +# ------------------------------------------------------------------------ +main.root.Servlet.PROPERTY.SERVLET.Dump.PATHS : /Dump%;*.DUMP +main.root.Servlet.PROPERTY.SERVLET.Dump.CHUNK : True +main.root.Servlet.PROPERTY.SERVLET.Dump.PROPERTY.AttrX : ValueX +main.root.Servlet.PROPERTY.SERVLET.Dump.PROPERTY.AttrY : ValueY +main.root.Servlet.PROPERTY.SERVLET.Dump.PROPERTY.AttrZ : ValueZ +# main.root.Servlet.PROPERTY.SERVLET.Dump.PROPERTIES : ./etc/JettyDemoDump.prp +main.root.Servlet.PROPERTY.SERVLET.Exit.PATHS : /Exit +main.root.Servlet.PROPERTY.SERVLET.Session.PATHS : /SessionDump +main.root.Servlet.PROPERTY.SERVLET.PropertyTree.PATHS : /PropertyTree +main.root.Servlet.PROPERTY.SERVLET.Config.PATHS : /Config$ +main.root.Servlet.PROPERTY.SERVLET.Debug.PATHS : /Debug$ +main.root.Servlet.PROPERTY.SERVLET.Multi.PATHS : /Demo/push +main.root.Servlet.PROPERTY.SERVLET.Multi.CLASS : com.mortbay.Jetty.MultiPartCount +main.root.Servlet.PROPERTY.SERVLET.Gen.PATHS : /Demo/generate +main.root.Servlet.PROPERTY.SERVLET.Gen.CLASS : com.mortbay.Jetty.GenerateServlet +main.root.Servlet.PROPERTY.SERVLET.GenL.PATHS : /Demo/generateLaf +main.root.Servlet.PROPERTY.SERVLET.GenL.CLASS : com.mortbay.Jetty.GenerateLafServlet +main.root.Servlet.PROPERTY.SERVLET.Upload.PATHS : /Upload$ +main.root.Servlet.PROPERTY.SERVLET.Upload.CLASS : com.mortbay.Jetty.UploadServlet +main.root.Servlet.PROPERTY.SERVLET.Laf.PATHS : /Jetty/Demo/;/Jetty/Info/;/Jetty/Config/;/Jetty/Program/ +main.root.Servlet.PROPERTY.SERVLET.Laf.PROPERTY.ResourceBase: /laf +main.root.Servlet.PROPERTY.SERVLET.Index.PATHS : /Jetty|;/Jetty/Info|;/Jetty/Demo|;/Jetty/Program|;/Jetty/Config| +main.root.Servlet.PROPERTY.SERVLET.Index.CLASS : com.mortbay.Jetty.DemoIndex +# ------------------------------------------------------------------------ +main.root.File.PROPERTY.FILES.FileBase.PATHS : /;/FileBase% +main.root.File.PROPERTY.FILES.FileBase.DIRECTORY : ./FileBase +# ------------------------------------------------------------------------ +main.root.Forward.PROPERTY.FORWARD.demo.PATHS : /Forward% +main.root.Forward.PROPERTY.FORWARD.demo.URL : http://localhost:8080 +main.root.Forward.PROPERTY.FORWARD.proxy.PATHS : http +main.root.Forward.PROPERTY.FORWARD.proxy.URL : http://localhost:8081 + + +# ======================================================================== +# Exception handler stacks 'default' and 'terse' for server 'main' +# HANDLERS - List of exception handler names for each stack. +# PATHS - List of PathMap path specifiactions for each stack +# name.CLASS - The classname for the handler "name" +# ------------------------------------------------------------------------ +main.defaultEx.PATHS : / +main.defaultEx.HANDLERS : DefaultEx +main.defaultEx.DefaultEx.CLASS : com.mortbay.HTTP.Handler.DefaultExceptionHandler + + +# ======================================================================== +# Define the handler stack "files" in server "main" +# ------------------------------------------------------------------------ +main.files.HOSTS : +main.files.PATHS : /javadoc%;/laf% +main.files.HANDLERS : File;NotFound +main.files.File.PROPERTY.FILES.Laf.PATHS : /laf +main.files.File.PROPERTY.FILES.Laf.DIRECTORY : ./FileBase +main.files.File.PROPERTY.FILES.Javadoc.PATHS : /javadoc +main.files.File.PROPERTY.FILES.Javadoc.DIRECTORY : ./javadoc +main.files.File.PROPERTY.FILES.Servlet.PATHS : /javadoc/javax/servlet +main.files.File.PROPERTY.FILES.Servlet.DIRECTORY : ./src/javax/servlet/javadoc + + +# ======================================================================== +# Define the server instance named "proxy" +# ------------------------------------------------------------------------ +proxy.STACKS : root +proxy.LISTENER.all.ADDRS : 0.0.0.0:8081 + +# ======================================================================== +# Define the handler stack "root" in server "proxy" +# ------------------------------------------------------------------------ +proxy.root.HANDLERS : Log;Proxy;NotFound +proxy.root.PATHS : / +proxy.root.Log.PROPERTY.File : /tmp/demo.log +proxy.root.Log.PROPERTY.Append : True +proxy.root.Proxy.PROPERTY.PATHS : /;http;ftp diff --git a/Modules/sound/Player.java b/Modules/sound/Player.java new file mode 100644 index 0000000..05401ee --- /dev/null +++ b/Modules/sound/Player.java @@ -0,0 +1,37 @@ +/* +Player.java + * + * Copyright (c) 2001, Ted Nelson, Tuomas Lukka and Vesa Parkkinen + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Vesa Parkkinen + */ + +package org.gzigzag.module; + +/** A (sound/video) player that doesn't need to know + * anything about zz. + */ +public interface Player { + // this needs more stuff, hashtable ? + // XXX getLength!!! -tjl + void init(String file); + void play(long from, long to, boolean loop); + void stop(); + long getCurrentOffset(); + +} diff --git a/Modules/sound/Recorder.java b/Modules/sound/Recorder.java new file mode 100644 index 0000000..0ba70b7 --- /dev/null +++ b/Modules/sound/Recorder.java @@ -0,0 +1,37 @@ +/* +Recorder.java + * + * Copyright (c) 2000, Ted Nelson, Tuomas Lukka and Vesa Parkkinen + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Vesa Parkkinen + */ + +package org.gzigzag.module; + +public interface Recorder { + + // what is needed in here ??? + void init(String file, long offset); + + void start(); + + void stop(); + + long getCurrentOffset(); + +} diff --git a/Modules/sound/SimplePlayer.java b/Modules/sound/SimplePlayer.java new file mode 100644 index 0000000..1392f91 --- /dev/null +++ b/Modules/sound/SimplePlayer.java @@ -0,0 +1,65 @@ +/* +SimplePlayer.java + * + * Copyright (c) 2001, Ted Nelson, Tuomas Lukka and Vesa Parkkinen + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Vesa Parkkinen + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.io.*; +import java.net.*; +import java.awt.*; + +/** A linux sound Player using GSM compression. Requires the associated native + * library. + */ + +public class SimplePlayer implements Player { + + private int handle; + + public void init(String file){ + handle = player_init(file); + } + + public void play( long from, long to, boolean loop){ + player_start(handle, from, to); + } + + public void stop(){ + player_stop(handle); + } + + + + public long getCurrentOffset(){ + return player_getCurrentOffset(handle); + } + + static { + System.loadLibrary("recorder"); + } + + private native int player_init(String file); + private native void player_start(int handle, long from, long to); + private native long player_getCurrentOffset(int handle); + private native void player_stop(int handle ); + +} diff --git a/Modules/sound/SimpleRecorder.java b/Modules/sound/SimpleRecorder.java new file mode 100644 index 0000000..54bc358 --- /dev/null +++ b/Modules/sound/SimpleRecorder.java @@ -0,0 +1,68 @@ +/* +SimpleRecorder.java + * + * Copyright (c) 2000, Ted Nelson, Tuomas Lukka and Vesa Parkkinen + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Vesa Parkkinen + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.io.*; +import java.net.*; +import java.awt.*; + +/** + * Simple (linux) native recorder class to be used in + * sound stream handling in zz. + */ +public class SimpleRecorder implements Recorder { + + int handle = 0; + + // inits recorder with a output file name + public void init(String file, long offset){ + handle = recorder_init(file, offset); + } + + public void start(){ + recorder_start( handle ); + } + + + public void stop(){ + recorder_stop(handle); + } + + public long getCurrentOffset(){ + return recorder_getCurrentOffset(handle); + } + + + static { + System.loadLibrary("recorder"); + } + + private native void recorder_start(int handle); + + private native void recorder_stop(int handle ); + + private native int recorder_init(String file, long offset); + + private native long recorder_getCurrentOffset(int handle); +} diff --git a/Modules/sound/Sound.java b/Modules/sound/Sound.java new file mode 100644 index 0000000..ea65af3 --- /dev/null +++ b/Modules/sound/Sound.java @@ -0,0 +1,373 @@ +/* +Sound.java + * + * Copyright (c) 2000, Ted Nelson, Tuomas Lukka and Vesa Parkkinen + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Vesa Parkkinen + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.io.*; +import java.net.*; +import java.awt.*; + +/** + * Should be broken to smaller pieces. + * @author Vesa Parkkinen + * + */ +public class Sound { + public static final String rcsid = "$Id: Sound.java,v 1.2 2001/03/27 20:43:25 tjl Exp $"; + + /* debugging */ + public static boolean dbg = true; + static final void p(String s) { if(dbg) ZZLogger.log(s); } + static final void pa(String s) { ZZLogger.log(s); } + + /** + * Static module used in gzigzag module loading. + */ + static public ZZModule module = new ZZModule() { + public void action( String id, ZZCell code, + ZZCell target, + ZZView v, ZZView cv, + String key, Point pt, + ZZScene xi) { + + p("Sound.module.action() " + id); + if( id.equals("PLAY") ) { + p("PLAYing..."); + instance.play(target); + } else if( id.equals("RECORD")){ + p("RECORDing..."); + // what ehis should mean ? + instance.record(target); + } else if ( id.equals("STOP")) { + p("STOPing..."); + instance.stop(); + } else if ( id.equals("CUT")){ + p("CUTing..."); + instance.cut(); + } else if ( id.equals("TAG")) { + p("TAGing..."); + instance.tag(target); + } else if ( id.equals("INIT")) { + p("INITing..."); + instance.init(target); + } + } + public ZOb newZOb(String id) { + p("Sound.module.newZOb(" + id + ")"); + return null; + } + }; + + static String stream = "SNDSTR"; + static String file = "/tmp/soundscroll"; + + static String d = "d.sound"; + static String dtag = "d.handle"; + static String dspan = "d.sound-span"; + static String dsessions = "d.sound-sessions"; + + static long duration = 2000000; + static String mod = "Sound"; + + static String[] ops = { //"INIT", + "PLAY", + "RECORD", + "STOP", + "CUT", + "TAG" + }; + + Recorder recorder = new SimpleRecorder(); + + public Span getSpan(){ + return null; + } + + public ZZCell getSpanAsCell(){ + return null; + } + + //************************************************************************ + //* private variables + //************************************************************************ + + private static Sound instance; + + static { + instance = new Sound(); + } + + // current offset from the start of the session + private long offset = 0; + + // offset of the end of the last span + private long lastOffset = 0; + private long sessionStart = 0; + + // are we playing at the moment + private boolean playing = false; + + // are we recording at the moment + private boolean recording = false; + + private Player player = null; + + private ZZCell last = null; + private ZZCell spanCell = null; + private ZZCell sessionCell = null; + + // THESE SHOULD COME FROM STRUCTURE + + private SoundScroll soundScroll = null; + // the session this stream belongs to + private ZZCell session = null; + // the input device associated with this stream. + private ZZCell inDevice = null; + // the input device associated with this stream. + private ZZCell outDevice = null; + + private ZZCell offsetCell = null; + + public Sound(){ + //t.start(); + pa("CONSTRUCTOR!!!"); + } + + ZZCell scrollCell = null; + + private void init(ZZCell c){ + // TODO: + // create a new window + // with soundvie + ZZDefaultSpace.addDimensionToDefaultDimlist(c, d); + ZZDefaultSpace.addDimensionToDefaultDimlist(c, dspan); + ZZDefaultSpace.addDimensionToDefaultDimlist(c, dsessions); + ZZDefaultSpace.addDimensionToDefaultDimlist(c, "d.handle"); + //soundScroll = new SoundScroll(stream, file, 1000); + //Scroll.register(stream, soundScroll); + for(int i = 0; i < ops.length; i++){ + c = c.N("d.2", 1); + c.setText(mod+"."+ops[i]); + } + addScroll(c); + scrollCell = ZZDefaultSpace.findScrollCell(c.getHomeCell(), stream); + soundScroll = (SoundScroll)Scroll.obtain( c.getSpace(), + stream); + if( spanCell != null ) + spanCell = scrollCell.N(dspan,1); + + p("SOUNDSCROLL = " + soundScroll); + } + + private void addScroll(ZZCell c){ + if( c==null ) return; + ZZCell home = c.getHomeCell(); + ZZCell d = home.findText("d.2", -1, "Scrolls"); + if( d == null ) { + d = home.N("d.2",-1); + d.setText("Scrolls"); + } + ZZCell x = d.findText("d.1", 1, stream); + if( x != null ) return ; + d = d.N("d.1",1); + d.setText(stream); + d = d.N("d.2",1); + d.setText(file); + d = d.N("d.2",1); + d.setText("Sound"); + d = d.N("d.2",1); + d.setText("1000000"); + d = d.N("d.2",1); + d.setText("offset"); + d = d.N("d.1",1); + d.setText("0"); + offsetCell = d; + } + + + //************************************************************************ + //* public methods + //************************************************************************ + /** + * + */ + public void record(ZZCell session){ + if( playing || recording ) return; + p("not recording or playing"); + // create a new scroll + if( soundScroll == null ) + soundScroll = (SoundScroll)Scroll.obtain( session.getSpace(), + stream); + //file = soundScroll.getFile(file); + + p("SOUNDSCROLL: " + soundScroll); + + if( scrollCell == null ) { + scrollCell = ZZDefaultSpace.findScrollCell(session.getHomeCell(), + stream); + } + if( offsetCell == null) { + pa("SCRCELL = " + scrollCell); + offsetCell = scrollCell.findText("d.2", 1, "offset"); + offsetCell = offsetCell.s("d.1",1); + } + if( spanCell ==null ){ + spanCell = scrollCell.N(dspan,1); + } + if( sessionCell == null ){ + sessionCell = scrollCell.h(dsessions, 1); + sessionCell = sessionCell.N(dsessions,1); + } + last = sessionCell; + + final long scOffset = Long.parseLong(offsetCell.getText()); + offset = scOffset; + p("are we recording yet... " + recording); + p("initializing"); + // XXX chech the offset + recorder.init("/tmp/soundscroll", scOffset); + p("initalized..."); + Thread t = new Thread() { + public void run() { + p("S REC Thread"); + recorder.start(); + offset = recorder.getCurrentOffset(); + p("offset = " + offset); + offsetCell.setText(""+ offset); + Span s = Span.create( + Address.streamOffs(stream, 0), + Address.streamOffs(stream, offset) + ); + spanCell.setSpan(s); + sessionCell.setSpan(s = Span.create( + Address.streamOffs(stream, scOffset), + Address.streamOffs(stream, offset) + )); + last.setSpan(s); + lastOffset = offset; + } + }; + t.start(); + last = last.N(d,1); + recording = true; + } + + public void play(){ + play(0); + } + + public void play(long off){ + if( ! (playing || recording )) ; // start to play + } + + public void play(ZZCell from ){ + p("play " + from); + + Span s = from.getSpan(); + if( s == null ) { + pa("Not a span cell!!!"); + return; + } + if( soundScroll == null ) + soundScroll = (SoundScroll)s.getStart().getScroll(from.getSpace()); + // get these from factory??? + player = new SimplePlayer(); + File f = soundScroll.getFile(); + p("FILE = " + f); + p("FILE = " + f.toString()); + player.init(f.toString()); + p("initialized...\n"); + final ZZCell fc = from; + Thread t = new Thread() { + public void run() { + p("PlayerThread"); + player.play(fc.getSpan().getStart().getOffs(), + fc.getSpan().getEnd().getOffs(), false); + } + }; + t.start(); + playing = true; + + } + + public void play(ZZCell from, Dimension d, int dir ){ + + } + + /** + * Create a new span cell from last cut to this cut and connect + * new cell to the stream cells. + */ + public void cut(){ + offset = recorder.getCurrentOffset(); + p("offset = " + offset); + Span s = Span.create( + Address.streamOffs(stream, lastOffset), + Address.streamOffs(stream, offset) + ); + p("SPAN = " +s ); + p("span.getText(): " + s.getString(last)); + + last.setSpan(s); + lastOffset = offset; + last = last.N(d,1); + } + + public void tag(ZZCell t){ + p( "target: " + t); + last.insert(dtag,1, t); + } + + + public void pause(){ + if( playing ){ + player.stop(); + playing = false; + return ; + } + + if( recording ){ + player.stop(); + recording = false; + return ; + } + } + + public void stop() { + if( playing ){ + player.stop(); + p("player stopped\n"); + playing = false; + return ; + } + + if( recording ){ + p("stopping recorder..."); + recorder.stop(); + recording = false; + p("recorder stopped\n"); + return ; + } + } + +} diff --git a/Modules/sound/gsm_def.h b/Modules/sound/gsm_def.h new file mode 100644 index 0000000..7433f8e --- /dev/null +++ b/Modules/sound/gsm_def.h @@ -0,0 +1,2 @@ +#define GSM_SAMPLE 160 * 2 +#define GSM_FRAME 33 * 2 diff --git a/Modules/sound/gsm_player.c b/Modules/sound/gsm_player.c new file mode 100644 index 0000000..1733b8b --- /dev/null +++ b/Modules/sound/gsm_player.c @@ -0,0 +1,247 @@ +/* +gsm_player.c + * + * Copyright (c) 2000, Ted Nelson, Tuomas Lukka and Vesa Parkkinen + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Vesa Parkkinen + */ + + +/**************************************************** + * INCLUDES + ****************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "jni.h" +#include "org_gzigzag_module_SimplePlayer.h" +#include "gsm_def.h" + +/**************************************************** + * DEFINES + ****************************************************/ +#define DEVICE "/dev/dsp" +#define DEFAULT_DSP_SPEED 8000 +#define DEFAULT_DSP_FRAG 0 +#define DEFAULT_DSP_SAMPLE +#define PLAYS 10 + + +#ifndef uint +#define uint unsigned int +#endif + +#ifndef ulong +#define ulong unsigned long +#endif + +#ifndef DEBUG_SOUND +#define DEBUG_SOUND 0 +#endif +#define DEBUG(s) if(DEBUG_SOUND)printf(s); + +/**************************************************** + * STRUCTS + ****************************************************/ +/** + * playing + * Struct to hold infomation about playing. + */ +typedef struct { + char *file; // file to read from + int audio; // handle to audio device + int speed; + int samplesize; + int fragsize; + int channels; // mono 1, stereo 2 + long offset; // bytes from beginning + int stop; + int format; +} Playing; + + +Playing *pls[PLAYS]; + +int cur_play = 0; + +/** + * Error handling + */ +void per(char *str){ + printf("** player error: %s\n", str); + perror("ERROR: " ); +} + +/** + * Creates a new playing structure, and increments + * curr_play by 1. + * @return a pointer to new Playing struvct or NULL + */ +Playing *new_playing(int *rn){ + Playing *r = (Playing *) malloc(sizeof(Playing)); + cur_play++; + pls[cur_play] = r; + *rn = cur_play; + return r; +} + + +int init_playing(Playing *rec){ + rec->file = "/tmp/soundscroll"; + rec->audio = 0; + rec->speed = 8000; + rec->samplesize = 8; + rec->fragsize = 0; // not used at the moment + rec->channels = 1; + rec->offset = 0; + return 0; +} + +/** + * Initializes the recording device. + */ +int init_playing_device(const char *file){ + + int rn = 0; + Playing *r = new_playing(&rn); + init_playing(r); + r->file = strdup(file); + r->stop = -1; + r->offset = 0; + DEBUG("init device\n"); + + if ( (r->audio = open(DEVICE, O_WRONLY) ) < 0 ) { + per("OPEN FAILED"); + return 0; + } + DEBUG("opened device\n"); + + ioctl(r->audio, SNDCTL_DSP_SAMPLESIZE, &r->samplesize); + + if ( ioctl(r->audio, SNDCTL_DSP_SETFMT, + &r->format) == -1 ) { + perror("ioctl format"); + } + + if (ioctl (r->audio, SNDCTL_DSP_SPEED, &r->speed) == -1){ + per("set speed failed"); + } + + if (ioctl(r->audio, SNDCTL_DSP_CHANNELS, &r->channels) == -1) { + per("SNDCTL_DSP_CHANNELS"); + return 0; + } + + return rn; + +} + + +/******************************************************************* + * INIT * + *******************************************************************/ +JNIEXPORT jint JNICALL Java_org_gzigzag_module_SimplePlayer_player_1init +(JNIEnv *env, jobject obj, jstring file){ + int rv=0; + const char *fn = (const char *)(*env)->GetStringUTFChars(env, file, 0); + rv = init_playing_device(fn); + (*env)->ReleaseStringUTFChars(env, file, fn); + return rv; +} + + +/******************************************************************* + * STOP * + *******************************************************************/ +JNIEXPORT void JNICALL Java_org_gzigzag_module_SimplePlayer_player_1stop +(JNIEnv *env, jobject obj, jint handle){ + Playing *r = pls[handle]; + if ( r == NULL) return ; + DEBUG("native STOP\n"); + r->stop = 1; +} + +/******************************************************************* + * START * + *******************************************************************/ +JNIEXPORT void JNICALL Java_org_gzigzag_module_SimplePlayer_player_1start +(JNIEnv *env, jobject obj, jint handle, jlong from, jlong to){ + int fd = 0; + gsm_frame buf; + long f = from; + long t = to; + int g=0; + int i; + Playing *r = pls[handle]; + unsigned char accbuf[160]; + gsm gsm = gsm_create(); + gsm_signal gsm_out[160]; + + DEBUG("starting...\n"); + + if ((fd = open (r->file, O_RDONLY)) == -1){ + per("open failed"); + return; + } + + lseek(fd, f, SEEK_SET); + printf("to= %ld\n", t); + r->offset = f; + while (r->stop < 1 && r->offset < t){ + if (read (fd, (char *)buf, sizeof(buf)) != sizeof(buf)){ + per("read failed"); + close(fd); + close(r->audio); + return; + } + + if( gsm_decode(gsm, buf, gsm_out) < 0){ + perror("error decoding..."); + return ; + } + + for(g=0;g<160;g++){ + i=(int)gsm_out[g]+32768; + i>>=8; + /*gsm_out[g]=(unsigned char)i;*/ + accbuf[g]=(unsigned char)i; + } + + if ( (write (r->audio, accbuf, sizeof(accbuf))) != sizeof(accbuf)){ + per("write failed"); + close(fd); + close(r->audio); + return; + } + r->offset += sizeof(buf); + } /* While */ + + if (fd != 1) + close (fd); + + close( r->audio ); + + DEBUG("played\n"); +} diff --git a/Modules/sound/gsm_recorder.c b/Modules/sound/gsm_recorder.c new file mode 100644 index 0000000..1a824ed --- /dev/null +++ b/Modules/sound/gsm_recorder.c @@ -0,0 +1,240 @@ +/* +gsm_recorder.c + * + * Copyright (c) 2000, Ted Nelson, Tuomas Lukka and Vesa Parkkinen + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Vesa Parkkinen + */ +/** + * simple gsm recorder + */ + + +/**************************************************** + * INCLUDES + ****************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "jni.h" +#include "org_gzigzag_module_SimpleRecorder.h" +#include "gsm_def.h" + +/**************************************************** + * DEFINES + ****************************************************/ +#define DEVICE "/dev/dsp" +#define DEFAULT_DSP_SPEED 8000 +#define DEFAULT_DSP_FRAG 0 +#define DEFAULT_DSP_SAMPLE +#define RECS 10 +#define READ_BLOCK 1280 +#define BUFFER_SIZE 20 * READ_BLOCK +#define GSM_RECORDER_DEBUG 1 +//#define ENCODED_SIZE 20 * READ_BLOCK + +#ifndef uint +#define uint unsigned int +#endif + +#ifndef ulong +#define ulong unsigned long +#endif + +#ifndef DEBUG_SOUND +#define DEBUG_SOUND 0 +#endif + +#define DEBUG(s) if(DEBUG_SOUND)printf(s); +/**************************************************** + * STRUCTS + ****************************************************/ + +/** + * Recording + * Struct to hold infomation about recordings. + */ +typedef struct { + + char *file; // file to save to + int audio; // handle to audio device + int speed; + int samplesize; + int fragsize; + int channels; // mono 1, stereo 2 + ulong offset; // bytes from beginning + int format; + int stop; + +} Recording; + +Recording *recs[RECS]; +int cur_rec = 0; + +/** + * + */ +int init_recording(Recording *rec){ + rec->file = "/tmp/sndscroll"; + rec->audio = 0; + rec->speed = 8000; + rec->samplesize = 8; + rec->fragsize = 0; // not used at the moment + rec->channels = 1; + rec->offset = 0; + rec->stop = 0; + return 0; +} + +/** + * Creates a new recording structure, and increments + * curr_rec by 1. + * @return a pointer to new Recording struvct or NULL + */ +Recording *new_recording(int *rn){ + Recording *r = (Recording *) malloc(sizeof(Recording)); + cur_rec++; + recs[cur_rec] = r; + *rn = cur_rec; + return r; +} + +/** + * Initializes the recording device. + */ +int init_device(const char *file){ + int rn = 0; + Recording *r = new_recording(&rn); + init_recording(r); + r->file = strdup(file); + r->stop = -1; + + DEBUG("init device\n"); + + if ( (r->audio = open(DEVICE, O_RDONLY) ) < 0 ) { + perror("OPEN FAILED"); + } + + DEBUG("opened device\n"); + + if( ioctl(r->audio, SNDCTL_DSP_SAMPLESIZE, &r->samplesize) == -1){ + perror("SNDCTL_DSP_SAMPLESIZE"); + return -1; + } + + if (ioctl(r->audio, SNDCTL_DSP_CHANNELS, &r->channels) == -1) { + perror("SNDCTL_DSP_CHANNELS"); + return -1; + } + + if (ioctl (r->audio, SNDCTL_DSP_SPEED, &r->speed) == -1){ + perror("set speed failed"); + } + DEBUG("initialized device\n"); + return rn; +} + + +/******************************************************************* + * GET CURRENT OFFSET * + *******************************************************************/ +JNIEXPORT jlong JNICALL +Java_org_gzigzag_module_SimpleRecorder_recorder_1getCurrentOffset +(JNIEnv *env, jobject obj , jint handle){ + Recording *r = recs[handle]; + if( r == NULL ) return 0; + return r->offset; +} + +/******************************************************************* + * INIT * + *******************************************************************/ +JNIEXPORT jint JNICALL Java_org_gzigzag_module_SimpleRecorder_recorder_1init +(JNIEnv *env, jobject obj, jstring file, jlong offset){ + int rv=0; + const char *fn = (const char *)(*env)->GetStringUTFChars(env, file, 0); + rv = init_device(fn); + (*env)->ReleaseStringUTFChars(env, file, fn); + recs[rv]->offset = offset; + return rv; +} + +/******************************************************************* + * STOP * + *******************************************************************/ +JNIEXPORT void JNICALL Java_org_gzigzag_module_SimpleRecorder_recorder_1stop +(JNIEnv *env, jobject obj, jint handle){ + Recording *r = recs[handle]; + if ( r == NULL) return ; + r->stop = 1; +} + +/******************************************************************* + * START * + *******************************************************************/ +JNIEXPORT void JNICALL Java_org_gzigzag_module_SimpleRecorder_recorder_1start +(JNIEnv *env, jobject obj, jint handle){ + + int fd = 0; + char *audiobuf; + + gsm gsm = gsm_create(); + gsm_signal sample[160]; + gsm_frame frame; + + Recording *r = recs[handle]; + + if ((fd = open (r->file, O_WRONLY | O_CREAT, 0666)) == -1){ + perror("recorder start: open failed"); + return ; + } + + lseek(fd, r->offset, SEEK_SET); + + while ( r->stop < 1 ){ + read (r->audio, sample, sizeof(sample) ); + gsm_encode(gsm, sample, frame); + + // write + if (write (fd, frame, sizeof(frame)) != sizeof(frame)){ + perror("write failed"); + //exit (-1); + return ; + } + r->offset += sizeof(frame); + } + if (fd != 1) + close (fd); + + close( r->audio ); + + gsm_destroy(gsm); + + printf("recorded\n"); +} diff --git a/Modules/sound/org_gzigzag_module_SimplePlayer.h b/Modules/sound/org_gzigzag_module_SimplePlayer.h new file mode 100644 index 0000000..17e2db7 --- /dev/null +++ b/Modules/sound/org_gzigzag_module_SimplePlayer.h @@ -0,0 +1,45 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_gzigzag_module_SimplePlayer */ + +#ifndef _Included_org_gzigzag_module_SimplePlayer +#define _Included_org_gzigzag_module_SimplePlayer +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_gzigzag_module_SimplePlayer + * Method: player_init + * Signature: (Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_org_gzigzag_module_SimplePlayer_player_1init + (JNIEnv *, jobject, jstring); + +/* + * Class: org_gzigzag_module_SimplePlayer + * Method: player_start + * Signature: (IJJ)V + */ +JNIEXPORT void JNICALL Java_org_gzigzag_module_SimplePlayer_player_1start + (JNIEnv *, jobject, jint, jlong, jlong); + +/* + * Class: org_gzigzag_module_SimplePlayer + * Method: player_getCurrentOffset + * Signature: (I)J + */ +JNIEXPORT jlong JNICALL Java_org_gzigzag_module_SimplePlayer_player_1getCurrentOffset + (JNIEnv *, jobject, jint); + +/* + * Class: org_gzigzag_module_SimplePlayer + * Method: player_stop + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_org_gzigzag_module_SimplePlayer_player_1stop + (JNIEnv *, jobject, jint); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Modules/sound/org_gzigzag_module_SimpleRecorder.h b/Modules/sound/org_gzigzag_module_SimpleRecorder.h new file mode 100644 index 0000000..49f086c --- /dev/null +++ b/Modules/sound/org_gzigzag_module_SimpleRecorder.h @@ -0,0 +1,45 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_gzigzag_module_SimpleRecorder */ + +#ifndef _Included_org_gzigzag_module_SimpleRecorder +#define _Included_org_gzigzag_module_SimpleRecorder +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_gzigzag_module_SimpleRecorder + * Method: recorder_start + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_org_gzigzag_module_SimpleRecorder_recorder_1start + (JNIEnv *, jobject, jint); + +/* + * Class: org_gzigzag_module_SimpleRecorder + * Method: recorder_stop + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_org_gzigzag_module_SimpleRecorder_recorder_1stop + (JNIEnv *, jobject, jint); + +/* + * Class: org_gzigzag_module_SimpleRecorder + * Method: recorder_init + * Signature: (Ljava/lang/String;J)I + */ +JNIEXPORT jint JNICALL Java_org_gzigzag_module_SimpleRecorder_recorder_1init + (JNIEnv *, jobject, jstring, jlong); + +/* + * Class: org_gzigzag_module_SimpleRecorder + * Method: recorder_getCurrentOffset + * Signature: (I)J + */ +JNIEXPORT jlong JNICALL Java_org_gzigzag_module_SimpleRecorder_recorder_1getCurrentOffset + (JNIEnv *, jobject, jint); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Modules/test/README b/Modules/test/README new file mode 100644 index 0000000..2da6607 --- /dev/null +++ b/Modules/test/README @@ -0,0 +1,2 @@ +Some classes for testing various things. Mostly useful only for +developers. diff --git a/Modules/test/TestClang1.java b/Modules/test/TestClang1.java new file mode 100644 index 0000000..4af2c63 --- /dev/null +++ b/Modules/test/TestClang1.java @@ -0,0 +1,100 @@ +/* +TestClang1.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.module; +import org.gzigzag.*; +import org.gzigzag.clang.*; +import java.util.*; +import java.awt.*; + +class ELIFJSEF { +} + +/** A small tester for Clang. + */ + + +public class TestClang1 { +public static final String rcsid = "$Id: TestClang1.java,v 1.9 2000/10/18 14:35:32 tjl Exp $"; + public static final boolean dbg = true; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + static public ZZModule module = new ZZModule() { + public void action(String id, + ZZCell code, + ZZCell target, + ZZView view, ZZView cview, String key, Point pt, ZZScene xi) { + ZZCell viewCursor = ZZCursorReal.get(view.getViewcell()); + p("TESTCLANG ACTION!"); + if(id.equals("1")) { + test1(viewCursor); + } else { + pa("UNKNOWN TESTCLANG1 COMMAND "+id); + } + p("TESTCLANG ACTION RETURNS!"); + } + }; + + static void test1(ZZCell curs) { + + ZZClang1 clang = new ZZClang1(); + ZZClangOp[] ops = ZZClangOps.getOps1(); + for(int i = 0; i < ops.length; i++) + clang.addOp(ops[i]); + + ZZCell main = curs.N("d.2", 1); + // Goal of script: connect these two. + ZZCell c1 = main.N("d.1", 1); + c1.setText("c1"); + ZZCell c2 = c1.N("d.1", 1); + c1.setText("c2"); + + ZZCell func = main.N("d.2", 1); + func = func.N("d.1", 1); + func.setText("func"); + ZZCell par = func.N("d.1", 1); + par.setText("c"); + ZZCell cmd = func.N("d.2", 1); + cmd.setText("connect"); + ZZCell param = cmd.N("d.1", 1); + par.insert("d.clone", 1, param); + param = param.N("d.1", 1); + param.setText("d.2"); + param = param.N("d.1", 1); + par.insert("d.clone", 1, param); + param = param.N("d.2", 1); + param.setText("step"); + param = param.N("d.1", 1); + param.setText("d.1"); + param = param.N("d.1", 1); + param.setText("1"); + + p("TESTCLANG CLANGEXEC!"); + + // clang.exec(func, null, new ZZCell[] { c1 }); + + + } + +} + diff --git a/Modules/test/TestHuge.java b/Modules/test/TestHuge.java new file mode 100644 index 0000000..31a6e28 --- /dev/null +++ b/Modules/test/TestHuge.java @@ -0,0 +1,55 @@ +/* +TestHuge.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + + +package org.gzigzag.module; + +import org.gzigzag.*; +import java.util.*; +import java.awt.*; + +public class TestHuge { +public static final String rcsid = "$Id: TestHuge.java,v 1.4 2000/10/18 14:35:32 tjl Exp $"; + + static public ZZModule module = new ZZModule() { + public void action(String id, ZZCell code, + ZZCell target, + ZZView v, ZZView cv, + String key, Point pt, + ZZScene xi) { + if(id.equals("ADDTREE")) { + ZZCell h = target.getHomeCell(); + h = h.h("d.1", 1); + ZZCell n = null; + int nth = 1; + for(; h != null; h=h.s("d.2", 1)) { + ZZCell m = h.N("d.1", 1); + m.setText(""+(nth++)); + if(n != null) n.connect("d.2", 1, m); + n = m.N("d.2", 1); + n.setText(""+(nth++)); + } + } + } + }; +} diff --git a/Modules/test/TestUndo.java b/Modules/test/TestUndo.java new file mode 100644 index 0000000..657033a --- /dev/null +++ b/Modules/test/TestUndo.java @@ -0,0 +1,210 @@ +/* +TestUndo.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + +package org.gzigzag; +import java.io.*; + +public class TestUndo { +String rcsid = "$Id: TestUndo.java,v 1.8 2000/11/30 08:44:33 ajk Exp $"; + + public static final boolean dbg = true; + final static void p(String s) { if(dbg) System.out.println(s); } + + /* + + static void printdim(ZZDimension d, int max) { + for(int i=1; i<=max; i++) { + p(i+"\t+"+ d.s(""+i, 1, null)+ + "\t-"+ d.s(""+i, -1, null)); + } + p(""); + } + + static String ct2str(Object o) { + if(o instanceof String) + return "'"+o+"'"; + else if(o instanceof Span) + return "SPAN: "+o; + else if(o == null) + return "null"; + throw new Error("Invalid content "+o); + } + + static void printct(ContentStore st, int max) { + for(int i=1; i<=max; i++) { + p(i+"\t"+ct2str(st.get(""+i))); + } + p(""); + } + + public static void main(String[] argv) { + { + ZZCacheDimension d = new ZZCacheDimension(); + UndoList ul = new UndoList(42); + d.setUndoList(ul); + + ZZDimStorer pstor = new ZZDimStorer() { + public void storeConnect(String a, String b) { + p("Storeconn: "+a+" "+b); + } + public void storeDisconnect(String a, int dir) { + p("Storedisc: "+a+" "+dir); + } + }; + + ContentStorer cstor = new ContentStorer() { + public void putContent(String id, Object ct) { + p("StoreCont: "+id+" "+ct2str(ct)+""); + } + }; + + d.connect("1", "2"); + d.connect("3", "4"); + + ul.stamp(); + printdim(d, 4); + + ul.undo(); + p("undo:"); + printdim(d, 4); + + ul.redo(); + p("redo:"); + printdim(d, 4); + + p(" Next, more difficult test."); + + d.disconnect("1", 1); + d.connect("1", "3"); + + ul.stamp(); + printdim(d, 4); + + ul.undo(); + p("undo:"); + printdim(d, 4); + + ul.undo(); + p("undo:"); + printdim(d, 4); + + ul.redo(); + p("redo:"); + printdim(d, 4); + + ul.redo(); + p("redo:"); + printdim(d, 4); + + p("Next, whether commit does the right ops..."); + + d.startCommit(); + ul.commit(); + d.endCommit(pstor); + + p("Commit finished"); + + p("More edits"); + + d.disconnect("3", 1); + d.connect("2", "4"); + printdim(d, 4); + + p("Commit ops..."); + d.startCommit(); + ul.commit(); + d.endCommit(pstor); + p("Commit finished"); + + p("Next, we'll test the simple file format."); + + SimpleDimFile f = new SimpleDimFile(); + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + + f.startWrite(new DataOutputStream(bo)); + + f.storeConnect("Foo", "Bar"); + f.storeConnect("1", "2"); + f.storeDisconnect("a", 1); + f.storeDisconnect("b", -1); + f.storeDisconnect("3", 1); + f.endWrite(); + + byte[] bytes = bo.toByteArray(); + bo.reset(); + + p("Wrote ops. Now read."); + // f.read(new DataInputStream(new ByteArrayInputStream(bytes)), pstor); + + + p("Finally, test the content storage as well"); + + ZZCacheContentStore ccs = new ZZCacheContentStore(); + ccs.setUndoList(ul); + + ul.stamp(); + + ccs.put("1", "foo"); + ccs.put("2", "bar"); + ccs.put("3", Span.parse("1.5:1.8")); + + ul.stamp(); + ccs.put("2", "txt"); + ul.stamp(); + printct(ccs, 4); + + ul.undo(); + p("Undo: "); + printct(ccs, 4); + + ul.undo(); + p("Undo: "); + printct(ccs, 4); + + ul.redo(); + p("Redo: "); + printct(ccs, 4); + + ul.redo(); + p("Redo: "); + printct(ccs, 4); + + SimpleContentFile cf = new SimpleContentFile(); + cf.startWrite(new DataOutputStream(bo)); + + cf.putContent("A", "FOO"); + cf.putContent("B", "bar"); + cf.putContent("C", Span.parse("1.5:1.8")); + cf.endWrite(); + bytes = bo.toByteArray(); + bo.reset(); + + p("Wrote txts; read:"); + // cf.read(new DataInputStream(new ByteArrayInputStream(bytes)), cstor); + + + } + + } + */ +} diff --git a/Modules/textcloud/TextCloud.zob b/Modules/textcloud/TextCloud.zob new file mode 100644 index 0000000..990d1fc --- /dev/null +++ b/Modules/textcloud/TextCloud.zob @@ -0,0 +1,353 @@ +/* +TextCloud.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.awt.*; +import java.io.*; + +/** A text cloud. + */ + +public class TextCloud implements FlobView, FlobSet.DragCursor, ZOb { +public static final String rcsid = "$Id: TextCloud.zob,v 1.7 2000/12/11 09:03:03 raulir Exp $"; + public static boolean dbg = false; + static void p(String s) { if(dbg) System.out.println(s); } + static void pa(String s) { System.out.println(s); } + + static RankTextView vr; + static SimpleBeamer bmr; + + STRUCTPARAMS { + } + + /** The horizontal and vertical offsets of the insertion cursor when + * dragging. + */ + static final int vcursx = -16, vcursy = -16; + + static ZZCell dragItem; + static int dragXOffs; static int dragYOffs; + + + public boolean accept(Object o) { + if(!(o instanceof ZZCursor)) return false; + ZZCursor c = (ZZCursor) o; + if(c.getOffs() == c.NO_OFFSET) return false; + return true; + } + + public void raster(FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed) { + if(vr == null) { + vr = new RankTextView(); + vr.readParams(null); + + bmr = new SimpleBeamer(); + bmr.readParams(null); + } + + // ZZAbstractView + ZZCell cloudmain = ZZCursorReal.get(view); + ZZCell curs = ZZCursorReal.get(cloudmain); + // p("TEXTCLOUD RASTER"); + if(cloudmain == null) return; + for(ZZCell item = cloudmain.s("d.1", 1); + item != null; + item = item.s("d.1", 1)) { + int[] c = ZZDefaultSpace.paramIntA(item, "Coords", null, 2); + if(c==null) { + p("NULL COORDS!"); + continue; + } + ZZCell vstream = + item.s("d.2", 1).s("d.1",1); + VStream.check(vstream); + + vr.raster(into, vstream, 0, false, c[0], c[1]); + if(item == dragItem) { + // Draw the arrow + + into.add(new ArrowDecor(c[0], c[1], + c[0]+vcursx, c[1]+vcursy, Color.red, 1)); + into.setDragCursor(this, c[0]+vcursx, c[1]+vcursy); + } + } + + bmr.decorate(into, "", null); + } + + + + static void stopdrag(ZZScene xi) { + p("StopDrag: "+dragItem); + if(dragItem == null) return; + // Check if the virtual cursor falls on something. + // Use itemcoords to get the UL corner of the item + // instead of mouse. + Point it = itemCoords(dragItem); + if(it == null || xi == null) { // Something went out from under us + dragItem = null; + return; + } + Object ob = xi.getObjectAt(it.x+vcursx, it.y+vcursy); + p("StopDrag item: "+ob); + if(!(ob instanceof ZZCursor)) return; + + // YES! INSERT! Delete the dragged item first. + ZZCursor p = (ZZCursor)ob; + ZZCell vstr = itemVStream(dragItem); + dragItem.delete(); + dragItem = null; + + VStream.assimilate(p, vstr); + + // XXX Should surround the inserted piece with cuts + // so that it's easy to take out again. + } + + static public ZZModule module = new ZZModule() { + public void action(String id, + ZZCell code, + ZZCell target, + ZZView view, ZZView cview, String key, Point pt, ZZScene xi) { + + ZZCell viewCell = view.getViewcell(); + ZZCell cloudmain = ZZCursorReal.get(viewCell); + ZZCell viewCursor = null; + if(cloudmain!=null) viewCursor = ZZCursorReal.get(viewCell); + + Object ob = null; + if(pt != null && xi != null) + ob = xi.getObjectAt(pt.x, pt.y); + + + if(!id.equals("Dragged")) stopdrag(xi); + + p("Text action! '"+id+"' key: "+key); + if(id.equals("NEWITEM")) { + } else if(id.equals("TESTWIN")) { + + + ZZCell cloudhome = code.getHomeCell().N("d.2", -1); + cloudhome.setText("TextCloud"); + ZZCell n = newItem(cloudhome, 50,50, null); + ZZCell vs1 = n.s("d.2", 1).s("d.1", 1); + ZZCursor p = VStream.start(vs1); + VStream.insert(p,"TESTTEXT 1"); + p = VStream.start(vs1); + p = VStream.add(p, 4); + VStream.insert(p,"FOO"); + + ZZCell rc = code.getHomeCell().N("d.2", -1); + ZZCell rl = rc.N("d.1", 1); + rl.connect("d.2", 1, rl); + rl.setText("Textcloud"); + ZZCell rastname = rl.N("d.1", 1); + rastname.setText("TextCloud.Normal"); + + // Bindings + ZZCell bindhome = code.getHomeCell().N("d.2", -1); + bindhome.setText("TCBind"); + bindhome = bindhome.N("d.1", 1); + ZZDefaultSpace.mkCorner(bindhome, actions); + + + ZZCell v = ZZDefaultSpace.newToplevelView(rc.getSpace(), + "textcloud", 100, 100, 600, 600, + rl, bindhome, + null, null, + null, + new Color(0xFFFFB1)); + ZZCursorReal.set(v,cloudhome); + ZZCursorReal.set(cloudhome,vs1); + + } else + + // Now, the real actions + if(id.equals("NewOrCurs")) { + // Now, ob is either a Point or a ZZCursor - for other + // things we don't care. + // XXX This should be more OO!!! + if(ob == null && pt != null) { + p("Vc: "+viewCursor); + p("CM: "+cloudmain); + ZZCell item = newItem(cloudmain, pt.x, pt.y, null); + ZZCursor p = itemVStreamStart(item); + VStream.setCursorFromPos(cloudmain, p); + } else if(ob instanceof ZZCursor) { + VStream.setCursorFromPos(cloudmain, (ZZCursor) ob); + } else + p("Strange xi param "+ob); + + } else if(id.equals("Insert")) { + if(key == null) return; + if(key.length() > 1) { + p("Composite key: "+key); + return ; + } + VStream.insert(VStream.posFromCursor(cloudmain), key); + } else if(id.equals("StartDrag") + || id.equals("StartDragCopy")) { + if(!(ob instanceof ZZCursor)) { + dragItem = null; + return; + } + ZZCursor pos = (ZZCursor)ob; + // Now, if we can cut, we cut! + ZZCell nvstream = null; + if(id.equals("StartDragCopy")) + nvstream = VStream.separateCopy(pos); + else + nvstream = VStream.separate(pos); + if(nvstream != null) { + ZZCell item = newItem(cloudmain, pt.x-10, pt.y-10, nvstream); + // We did cut out a part. Whew! + dragXOffs = 0; + dragYOffs = 0; + dragItem = item; + } else { + dragItem = itemFromVStream(pos.get()); + } + + Point ip = itemCoords(dragItem); + if(ip==null) { p("No item coord"); return; } + if(pt==null) { p("No startdrag coord"); return; } + dragXOffs = ip.x - pt.x;; + dragYOffs = ip.y - pt.y;; + } else if(id.equals("Dragged")) { + if(dragItem == null) return; + if(pt==null) { p("No drag coord"); return; } + setItemCoords(dragItem, pt.x + dragXOffs, pt.y + dragYOffs); + + } else if(id.equals("StopDrag")) { + stopdrag(xi); + return; + } else if(id.equals("Cut")) { + if(!(ob instanceof ZZCursor)) return; + // Put in a cut mark. XXX HOW? + VStream.cut((ZZCursor)ob); + } else if(id.equals("Backspace")) { + VStream.backspace(VStream.posFromCursor(cloudmain)); + } else if(id.equals("ClearCuts")) { + VStream.clearcuts(VStream.posFromCursor(cloudmain)); + // p("Clear cuts: "+ob); + // if(!(ob instanceof ZZCursor)) return; + // VStream.clearcuts((ZZCursor)ob); + } else if(id.equals("DeleteItem")) { + if(!(ob instanceof ZZCursor)) return; + ZZCell item = itemFromVStream(((ZZCursor)ob).get()); + item.delete(); + } + + + } + + public ZOb newZOb(String id) { + if(id.equals("Normal")) { + return new TextCloud(); + } + return null; + } + }; + + static String[][] actions = { + { "MouseClicked1", "TextCloud.NewOrCurs" }, + { "MouseClicked3", "TextCloud.Cut" }, + { "Ctrl-MouseClicked3", "TextCloud.DeleteItem" }, + { "MouseStartDrag", "TextCloud.StartDrag" }, + { "Shift-MouseStartDrag", "TextCloud.StartDragCopy" }, + { "MouseDragged1", "TextCloud.Dragged" }, + { "Shift-MouseDragged1", "TextCloud.Dragged" }, + { "MouseReleased1", "TextCloud.StopDrag" }, + { "Shift-MouseReleased1", "TextCloud.StopDrag" }, + { "Backspace", "TextCloud.Backspace" }, + { "Esc", "TextCloud.ClearCuts" }, + { "DEFAULT", "TextCloud.Insert" } + }; + + static public ZZCell newItem(ZZCell cloud, int x, int y, ZZCell vstream) { + ZZCell item = cloud.N("d.1", 1); + ZZCell c = item.N("d.2", 1); + c.setText("Coords"); + ZZCell n1 = c.N("d.1", 1); + n1.setText(""+x); n1 = n1.N("d.1", 1); + n1.setText(""+y); + // Note now going up + c = c.N("d.2", -1); + Scroll s = cloud.getSpace().getStringScroll(); + // Width 0 - I wonder how this will work.. + if(vstream != null) { + c.connect("d.1", 1, vstream); + } else { + VStream.create(c, "d.1", 1, Span.create( + Address.scrollOffs(s, 1), + Address.scrollOffs(s, 0) + )); + } + return item; + } + + static Point itemCoords(ZZCell item) { + int[] c = ZZDefaultSpace.paramIntA(item, "Coords", null, 2); + if(c==null) { + p("NULL COORDS!"); + return null; + } + return new Point(c[0], c[1]); + } + static void setItemCoords(ZZCell item, int x, int y) { + ZZCell c = ZZDefaultSpace.findInheritableParam(item, "Coords"); + c = c.s("d.1", 1); c.setText(""+x); + c = c.s("d.1", 1); c.setText(""+y); + } + + static public ZZCell itemVStream(ZZCell item) { + return item.s("d.2", 1).s("d.1", 1); + } + static public ZZCursor itemVStreamStart(ZZCell item) { + return VStream.start(itemVStream(item)); + } + static public ZZCell itemFromVStream(ZZCell c) { + return c.h("d.2", -1) + .h("d.1", -1) + .h("d.2", -1); + } + + static public ZZCell cloudHomeFromVStream(ZZCell c) { + ZZCell cloudmain = c.h("d.2", -1) + .h("d.1", -1) + .h("d.2", -1) + .h("d.1", -1); + if(! cloudmain.getText().equals("TextCloud")) { + p("NOT CLOUD!"); + return null; + } + return cloudmain; + } + + +} + + +// vim: set syntax=java : diff --git a/Modules/virtualcommunity/MessageFlobFactory.zob b/Modules/virtualcommunity/MessageFlobFactory.zob new file mode 100644 index 0000000..377a438 --- /dev/null +++ b/Modules/virtualcommunity/MessageFlobFactory.zob @@ -0,0 +1,546 @@ +/* +MessageFlobFactory.zob + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Rauli Ruohonen + */ + +package org.gzigzag.module; +import org.gzigzag.module.multimedia.*; +import org.gzigzag.*; +import java.awt.*; +import java.util.*; + +public class MessageFlobFactory implements FlobFactory, ZOb { + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + private String d_image = "d.images"; + private String d_text = "d.text"; + private String d_author = "d.author"; + private String d_handle = "d.kahva"; + + private MediaFlobFactory mediafact=new MediaFlobFactory(); + private FTextLayouter ftext=new FTextLayouter(); + + SceneFlob mysflob = null; + + VirtualCommunity vc= null; + + STRUCTPARAMS { + /* In pixels. */ + int imgtxt_separator + = 0; + /* Originally 1/Ph = img_h/txt_h =~ 0.618. (Ph = Golden Ratio) */ + float imgtxt_min_ratio + = (float)(2.0/(Math.sqrt(5.0)+1.0)); + ScalableFont font + = new ScalableFont("SansSerif", Font.PLAIN, 12); + /* color of the author blob */ + Color authorColor + = Color.yellow.brighter(); + /* color of the message blob */ + Color messageColor + = new Color(0xffff8c); + Color auth_bg + = new Color(0xffff28); + int border + = 3; + int clipborder + = 2; + } + + public MessageFlobFactory(VirtualCommunity vc){ + + this.vc = vc; + } + public MessageFlobFactory(){ + + + } + + private Color back = Color.white; + + private FText makeFText(ZZCell c, ZZCell hc,float fract) { + Vector a=new Vector(); + int scale=(int)(fract*1000); + Font f=font.getFont(scale); + FontMetrics fm=font.getFontMetrics(scale); + Color fg=Color.black;//,bg=Color.white; + LoopDetector l=new LoopDetector(); + c = c.s(d_text,1); + Color fgt = fg; + while(c!=null) { + fgt = fg; + l.detect(c); + /*if( c.s(d_handle,1) != null || c.s(d_handle,-1) != null){ + fgt = Color.red; + }*/ + a.addElement(new FText.CellPart(c,c,0,-1,f,fm,back,fgt)); + //a.addElement(new FText.StringPart(c.getText(),f,fm,back,fgt)); + c=c.s(d_text); + } + return new FText(a); + } + + public SceneFlob getSFlob(){ + + return mysflob; + } + + private int cacheW = -1; + private Dimension cacheTxt; + private ZZCell cacheC; + private float cacheFract; + private void getSizes(ZZCell c,float fract,int w,int h,Dimension img, + Dimension txt) { + final int MAGIC=2147483647; + ZZCell imgc=c.h(d_image,true); + ZZCell textc=c.s(d_text); + img.width=0; img.height=0; txt.width=0; txt.height=0; + /* Calculate the maximum sizes for both image and text */ + if(imgc!=null) img.setSize(mediafact.getSize(imgc,fract)); + float aspect=img.width*1.0f/img.height; + if(textc!=null) { + if (cacheW == w && cacheFract == fract && c.equals(cacheC)) + txt.setSize(cacheTxt); + else { + cacheTxt = ftext.place(null,makeFText(c,c,fract), + new Rectangle(0,0,w,MAGIC), + 1,1,0,0xdeadbeef,false).getSize(); + cacheW = w; cacheC = c; cacheFract = fract; + txt.setSize(cacheTxt); + } + } + // Subj. + Auth. + txt.height += (font.getFontMetrics((int)(1000 * fract)). + getHeight())*2; + if (imgc == null) { + txt.height = h; + return; + } + if (textc == null) { + img.height=h-txt.height; + img.width=(int)(img.height*aspect); + if(img.width>w) { + img.width=w; + img.height=(int)(img.width/aspect); + } + txt.height = h-img.height; + return; + } + h-=imgtxt_separator; + float imgtxt_ratio=(h-txt.height)/txt.height; // Text size constant + p("it_rat="+imgtxt_ratio); + if(imgtxt_ratio 0) x = p.x - d.width; + if(yalign < 0) y = p.y; + if(yalign > 0) y = p.y - d.height; + return makeFlob(into, c, handleCell, fract, x, y, + depth, d.width, d.height); + } + + public Flob centerFlob(FlobSet into, + ZZCell c, ZZCell handleCell, + float fract, Point p, int xalign, int yalign, + int depth) { + return centerFlob(into, c, handleCell, fract, p, xalign, yalign, + depth, null); + } + + public Flob makeSubject(FlobSet into, + ZZCell c, ZZCell handleCell, + float fract, + int x, int y, int depth, + int w, Flob parent, int mh) { + + if (mh > 100) mh = 100; + Flob sc = new SubjCell(x,y,depth,w,mh,c, handleCell, fract); + sc.setParent(parent); + into.add(sc); + return sc; + + } + + public Flob makeAuthor(FlobSet into, + ZZCell c, ZZCell handleCell, + float fract, + int x, int y, int depth, int w, + float xfract, float yfract, Flob parent, int mh) { + + if (mh > 100) mh = 100; + Flob ac = new AuthCell(x,y,depth,w,mh,c, handleCell, fract); + ac.setParent(parent); + into.add(ac); + return ac; + + } + + /** + * Flob for message subjects + */ + class SubjCell extends Flob { + + int ascent; + float fr; + ZZCell handle; + + public SubjCell(int x, int y, int d, int w, int h, ZZCell c, ZZCell hc, + float fract){ + super(x,y,d,w,h,c); + Font f = font.getFont((int)(1000 * fract)); + FontMetrics fm = font.getFontMetrics((int)(1000 * fract)); + ascent = fm.getAscent(); + this.h = fm.getHeight(); + if (this.h > h) this.h = h; + //this.w = fm.stringWidth("Subject: " +c.getText()); + fr = fract; + handle = hc; + //p("FR = " + fr); + } + + public void renderInterp(Graphics g, float fract) { return; } + public void render(Graphics g, int mx, int my, int md, + int mw, int mh) { + /*ZZDrawingJ2D drw = null; + if (ZZDrawing.instance instanceof ZZDrawingJ2D) + drw = (ZZDrawingJ2D)ZZDrawing.instance; + if (drw != null) { + drw.setFIXME(false); + drw.setQuality(g); + }*/ + FontMetrics fm = font.getFontMetrics((int)(1000 * fr)); + Color old = g.getColor(); + g.setFont(font.getFont((int)(fr*1000))); + g.setColor(auth_bg); + Rectangle asd=g.getClipBounds(); + g.setClip(mx-clipborder,my-clipborder,mw+clipborder*2,mh+clipborder*2); + g.fillRect(mx,my,mw,mh); + g.setColor(old); + /*if (drw != null) { + drw.setFIXME(true); + drw.setQuality(g); + }*/ + if( fm.stringWidth("Subject: " + c.getText()) > mw ) + g.drawString( c.getText(), mx,my+ascent); + else g.drawString("Subject: " + c.getText(), mx,my+ascent); + //g.drawLine(mx, my+h, mx+w, my+h); + g.setClip(asd); + } + + public Object hit(int x0, int y0) { + if( x0 >= x && y0 >= y && x0 < x+w && y0 < y+h ) + return handle; + return null; + } + + } + + + /** + * Flob for message auth + */ + class AuthCell extends Flob { + + int ascent; + int height; + ZZCell handle; + + float fr = 1.0f; + + public AuthCell(int x, int y, int d, int w, int h, ZZCell c, ZZCell hc, + float fract){ + super(x,y,d,w,h,c); + Font f = font.getFont((int)(1000 * fract)); + FontMetrics fm = font.getFontMetrics((int)(1000 * fract)); + ascent = fm.getAscent(); + this.h = fm.getHeight(); + if (this.h > h) this.h = h; + //this.w = fm.stringWidth("Author: " + c.getText()); + fr = fract; + handle = hc; + } + + public void renderInterp(Graphics g, float fract) { return; } + public void render(Graphics g, int mx, int my, int md, + int mw, int mh) { + /*ZZDrawingJ2D drw = null; + if (ZZDrawing.instance instanceof ZZDrawingJ2D) + drw = (ZZDrawingJ2D)ZZDrawing.instance; + if (drw != null) { + drw.setFIXME(false); + drw.setQuality(g); + }*/ + Color old = g.getColor(); + FontMetrics fm = font.getFontMetrics((int)(1000 * fr)); + g.setFont(font.getFont((int)(1000 * fr))); + Rectangle asd=g.getClipBounds(); + g.setClip(mx-clipborder,my-clipborder,mw+clipborder*2,mh+clipborder*2); + g.setColor(auth_bg); + g.fillRect(mx,my,mw,mh); + g.setColor(old); + /*if (drw != null) { + drw.setFIXME(true); + drw.setQuality(g); + }*/ + if( fm.stringWidth("Author: " + c.getText()) < mw ) + g.drawString("Author: " + c.getText(), mx,my+ascent); + else g.drawString( c.getText(), mx,my+ascent); + g.drawLine(mx, my+mh-1, mx+mw, my+mh-1); + g.setClip(asd); + } + + public Object hit(int x0, int y0) { + if( x0 >= x && y0 >= y && x0 < x+w && y0 < y+h ) + return handle; + return null; + } + } +} + +// vim: set syntax=java : diff --git a/Modules/virtualcommunity/VCView1.java b/Modules/virtualcommunity/VCView1.java new file mode 100644 index 0000000..0905cbd --- /dev/null +++ b/Modules/virtualcommunity/VCView1.java @@ -0,0 +1,377 @@ +/* +VCView1.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Vesa Parkkinen and Tuomas Lukka + */ + +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.awt.*; + +/** First (bad) virtualcommunity view. + */ +public class VCView1 extends VirtualCommunity { + public static final String rcsid = "$Id: VCView1.java,v 1.4 2001/02/27 23:49:30 veparkki Exp $"; + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + public void raster( FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed){ + ZZCell hist = null, hilite = null; + if (!nohistory) { + hist = ZZDefaultSpace.findInheritableParam(view, "history"); + if (hist == null) { + hist = view.h("d.2",1).N("d.2"); + hist.setText("history"); + } + hilite = hist.h("d.1", 1, true); + } + accursed=accursed.h(text); + if (!nohistory) { + if (accursed.h("d.1").equals(hist)) { + hilite = accursed; + accursed = ZZCursorReal.get(accursed); + } + if (hilite == null) { + hilite = hist.N("d.1"); + ZZCursorReal.setcursor(hilite, accursed); + } + histobs.init(view, hilite); + hilite = histobs.histpos; + } + Dimension rd = into.getSize(); + int head = rd.height/15; + if (nohistory) head = 0; + Dimension d = new Dimension(rd.width,rd.height-head); + int w = (int)(d.width * right); + int h = (int)(d.height * middleHeight); + int cx = w/2; + int cy = (int)( (d.height - h) / 2); + int vUnit = (int)(cy / 13); + int lw = (int)(d.width * left); + // gapheight=1/13, line=3/13;4*gap+3*lines=1 + + int bc = 0; + + // pointer + ZZCell p = accursed; + // another pointer + ZZCell ptr = p; + // used to hold kahva cells + Hashtable handles = new Hashtable(); + Hashtable flobs = new Hashtable(); + + int fh = d.height; + int fw = (int) (right * d.width); + + Flob centerFlob = null; + + float fr = ((float)d.width) / 100000.0f; + + int magic = 20; + // Draw the history + int div = 1; + if (!nohistory) div = hist.getRankLength("d.1")-1; + if (div > magic) div = magic; + int hw = (d.width/div)-2, sep=2; + if (hw > head*3) { /*sep+=hw-head*3;*/ hw = head*3; } + int hx = d.width-1-hw; + ZZCell it = null; + if (!nohistory) hist.s("d.1"); + int cnt=0; + if (!nohistory) { + while (!it.equals(hilite)) { cnt++; it = it.s("d.1"); } + if (cnt*2+1 > magic) cnt = (magic-1)/2; + cnt++; + while (cnt++ < magic) { + if (it.s("d.1") != null) it = it.s("d.1"); + else break; + } + } + cnt = 0; + centerFlob = new Flob(0, 0, 1, d.width, head, hist) {}; + into.add(centerFlob); + if (!nohistory) + while (!it.equals(hist) && cnt++ < magic) { + ZZCell hit = ZZCursorReal.get(it); + int hy = 0; + if (hilite != null && it.equals(hilite)) hy = 5; + history.makeFlob(into, hit, it, cfr(fr*hw), hx, hy, 1, hw, head). + setParent(centerFlob); + it = it.s("d.1",-1); + hx -= sep+hw; + } + + //------------------------------------------- + // we have different possibilities: + // author cell + // - headcell in the author dim + // + // product cell + // - no author dim + // - head cell in the kahva dim + // + // message cell + // - have author, not the head cell + //------------------------------------------- + + //if ( fr > 1 ) fr = 1; + //if ( fr < 0.7 ) fr = 0.7f; + p("_____________fr = " +fr); + // make the big blob in the middle + centerFlob = center.makeFlob( into, accursed, accursed, cfr(fr*w), + cx, cy+head, 1, w, h , 0.0f, true); + + //------------------------------------------- + // handle the siblings, parent and children + //------------------------------------------- + + p = accursed; + + int cSibl = 0; + + int sY = cy; + int sX = cx; + + // siblings above the center blob + // calculate the room... + int rc = 0;//p.getRankLength(replies_list) -1; + while( ( p = p.s(replies_list, -1) ) != null ){ + rc++; + } + rc--; + + p("got " + rc + " siblings"); + + p = accursed; + + int sroom = (d.height - h)/2; + if( rc > 0 ) + sroom = sroom / rc; + //fr = (float)0.7; + while( ( p = p.s(replies_list, -1) ) != null && + !p.equals( p.h(replies_list, -1)) && ( cSibl < rc ) ) { + sY = sY - sroom+10; + + //sibl.makeFlob( into, p, p, (float)1.0, + // sX, sY, 1, w, 3*vUnit); + blobs.makeFlob( into, p, p, cfr(fr*w), + sX, sY+head, 1, w, sroom - 20, 0.1f); + + cSibl = cSibl + 1; + //fr -= 0.2; + } + + // parent + ZZCell parent = accursed.h(replies_list,-1); + if( !parent.equals(accursed)){ + int qx = sX-w/2 +2, qy = 5+head, qw = w/2-10, qh = sroom-20; + parent = parent.s(replies, -1); + sibl.makeFlob( into, parent, parent, cfr(fr*(w/2-10)), + qx + qw/2, qy + qh/2, 1, qw , qh, + -0.1f); + parent = parent.h(replies_list, -1, true); + if (parent != null) { + parent = parent.s(replies, -1); + sibl.makeFlob( into, parent, parent, cfr(fr*(w/2-10)), + qx - qw/4, qy - qh/4, 1, qw , qh, + 0.07f); + } + /*into.add(new LineDecor(cx,cy+h/2,sX-w/2+2+(w/2-10)/2, + 5+sroom-20,linecol,2));*/ + } + + p = accursed; + cSibl = 0; + + sY = cy + h + vUnit; + + rc = 0; + while( ( p = p.s(replies_list,1) ) != null ){ + rc++; + } + + p("got " + rc + " siblings"); + + sroom = (d.height - h)/2 - 6; + if( rc > 0 ) + sroom = sroom / rc; + + p = accursed; + + //fr = 0.7f; + + // child + ZZCell child = accursed.h(replies,1); + if( child != accursed ){ + int qx = sX+w+10, qy = sY+head, qw = w/2, qh = d.height-5-sY; + child = child.s(replies_list, 1); + if( child != null) { + ZZCell child2 = child.s(replies_list, 1); + if (child2 != null) { + sibl.makeFlob( into, child2, child2, cfr(fr*(w/2)), + qx+qw/8, qy-qh/2, 1, qw, qh); + } + sibl.makeFlob( into, child, child, cfr(fr*(w/2)), + qx, /*d.height - 3*vUnit-5*/ + qy-qh, 1, qw, qh/*3*vUnit*/); + } + //into.add(new LineDecor(cx+w/2,cy+h,sX+w+10,middle,linecol,2)); + } + + // siblings below the center blob + while( (p = p.s(replies_list, 1) ) != null && (cSibl < rc) ) { + blobs.makeFlob( into, p, p, cfr(fr*w), + sX, sY+10+head, 1, w, sroom-20); + cSibl = cSibl + 1; + sY = sY + sroom; + } + + int th = 0; + + //------------------------------------------- + // handle the other blobs + // depending on the center blob type + //------------------------------------------- + + //------------------------------------------- + // put all the handles to right side + // in every case + //------------------------------------------- + + // loop through the text cells, puts handle cells + // to handles + // XXX loop + p = accursed; + while( (p = p.s(text,1) ) != null){ + ptr = p.h(handle); + if( p.getRankLength(handle) > 1 ) { + handles.put( ""+bc, ptr); + bc++; + } + } + + if ( bc != 0 ) + fh= d.height / bc; + + // blobs on the right side + for( int i = 0; i < bc; i++ ){ + ptr = (ZZCell)handles.get(""+i); + p("th = " + th + " ptr " + ptr); + p("fw = " +fw ); + flobs.put(ptr, blobs.makeFlob( into, ptr, ptr, cfr(fr*(fw-2*xpad)), + d.width - fw-xpad, th+ypad+head, 1, + fw-2*xpad, fh-2*ypad)); + th += fh; + } + + //------------------------------------------- + // draw the links. + // not correct, but SFW, this is just a demo + //------------------------------------------- + for( int i = 0; i< bc; i++ ){ + Flob flo=(Flob)flobs.get(handles.get(""+i)); + Point pq = flo.getPoint(-1,0); + p("flo: " + flo + "p: " + pq); + Point pc = centerFlob.getPoint(1,0); + Flob l = new LinkFlob(pc.x,pc.y,pq.x,pq.y-flo.h/5,pq.x,pq.y+flo.h/5); + into.add(l); + } + + bc=0; + + //------------------------------------------- + // Depending the cell type, put the blobs + // on the left + //------------------------------------------- + + bc = 0; + handles = new Hashtable(); + p=accursed.h(author,-1); + + // author ? + if( accursed == p && p.getRankLength(author) > 1 ){ + p("AUTHOR DUDE"); + // XXX loop + while( (p = p.s(author,1) ) != null){ + //ptr = p.h(text, -1); + p("message"); + //if( p.getRankLength(handle) > 1 ) { + handles.put( ""+bc, p); + bc++; + } + + } else if ( accursed == (p=accursed.h(handle,-1)) && + p.getRankLength(handle) > 1){ + p("PRODUCT"); + // XXX loop + while( (p = p.s(handle,1) ) != null){ + ptr = p.h(text, -1); + //p("message"); + //if( p.getRankLength(handle) > 1 ) { + handles.put( ""+bc, ptr); + bc++; + } + + } + + p("BC = " + bc); + + th = 0; + if ( bc != 0 ) + fh= d.height / bc; + + // blobs on the right side + for( int i = 0; i < bc; i++ ){ + ptr = (ZZCell)handles.get(""+i); + p("flob message"); + p("th = " + th + " ptr " + ptr); + flobs.put(ptr,blobs.makeFlob( into, ptr, ptr, cfr(fr*(w-2*xpad)), + d.width-w-xpad, th+ypad+head, 1, + w-2*xpad, fh-2*ypad)); + th += fh; + } + + //------------------------------------------- + // draw the links. + // not correct, but SFW, this is just a demo + //------------------------------------------- + for( int i = 0; i< bc; i++ ){ + Flob flo=(Flob)flobs.get(handles.get(""+i)); + Point pq = flo.getPoint(-1,0); + p("flo: " + flo + "p: " + pq); + Point pc = centerFlob.getPoint(1,0); + Flob l = new LinkFlob(pc.x,pc.y,pq.x,pq.y-flo.h/5,pq.x,pq.y+flo.h/5); + into.add(l); + } + /* + // draw the links + FlobDecorator linker = new VCLinker(); + linker.decorate(into, "", view); + */ + + + + } + + +} diff --git a/Modules/virtualcommunity/VCView2.java b/Modules/virtualcommunity/VCView2.java new file mode 100644 index 0000000..2afe08d --- /dev/null +++ b/Modules/virtualcommunity/VCView2.java @@ -0,0 +1,263 @@ +/* +VCView2.java + * + * Copyright (c) 2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka and Vesa Parkkinen + */ + + +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.awt.*; + +/** Second, cardstack-like virtualcommunity view. + */ + +public class VCView2 extends VirtualCommunity { + public static final String rcsid = "$Id: VCView2.java,v 1.20 2001/02/28 10:18:20 tjl Exp $"; + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + public void childSeries( FlobSet into, ZZCell cur, int x, int y, + int w, float fract, int orot, int dir, int depth) { + ZZCell s; + + if(cur.s(replies) != null) { + s = cur.s(replies).s(replies_list); + if(s != null) + siblingSeries(into, s, x, y, + w, fract*magfract, orot, 1, depth+1); + } + } + + static int borderLimit = 10; + + final int rotinc = 1; + final int SCOFFS = 10; + + double[]sins = new double[SCOFFS * 2]; + double[]coss = new double[SCOFFS * 2]; + + // Point mkp( + + void addVert(Point p, double h, int rot) { + p("Addvert: "+p+" "+h+" "+rot); + p.x -= (int)(sins[rot+SCOFFS] * h); + p.y += (int)(coss[rot+SCOFFS] * h); + p("Ret: "+p); + } + + + void addHoriz(Point p, double w, int rot) { + p.x += (int)(coss[rot+SCOFFS] * w); + p.y += (int)(sins[rot+SCOFFS] * w); + } + + int getWid(int w, float fract) { + return (int)(w * Math.sqrt(fract)); + } + + int overlap = 10; + int bend = -5; + + public void siblingSeries( FlobSet into, ZZCell cur, int x, int y, + int w, + float fract, int orot, int dir, int depth) { + if(depth >= view2depth) return; + Dimension rd = into.getSize(); + ZZCell s; + int rot = 0;//orot; + + Point curpoint = new Point(x,y); + + Point upstart, downstart; + + Point tmp = new Point(); + + // We do things differently depending on where we are. + // If going to positive direction, first see if we have odd + // or even number of cells and either put a cell in the middle + // or not + + boolean domiddle = true; + + if(dir == 1) { + cur = cur.h(replies_list); + int count = cur.getRankLength(replies_list) - 1; + if(count % 2 == 0) { + domiddle = false; + } + // Either upper or middle + cur = cur.s(replies_list, (count+1)/2); + } + + int cw = getWid(w,fract); + + if(domiddle) { + int h = sibl.getHeight(cur, cfr(fract), cw); + // h /= depth+1; + // h = (int)(80*fract); + + // If not parent, put children for this center blob + if(dir >= 0) { + Point px = new Point(curpoint); + addHoriz(px, cw, rot); + childSeries(into, cur, + px.x, px.y, + w, fract, orot, 1, depth); + } + + addVert(curpoint, -h/2, rot); + sibl.makeFlob(into, cur, cur, cfr(fract), + curpoint.x, curpoint.y, 10, cw, h, + rotunit * orot, + (dir == 0)); + + upstart = new Point(curpoint); + downstart = new Point(curpoint); + addVert(downstart, h, rot); + + } else { + upstart = new Point(curpoint); + downstart = new Point(curpoint); + } + + float cf = fract; + + s=cur; + + if(domiddle) s = s.s(replies_list, -1); + for(; s != null; s = s.s(replies_list, -1)) { + + // if(cy <= borderLimit) break; + // Don't do relcell + if(s.s(replies_list, -1) == null) break; + cf *= magfract; + rot -= rotinc; + cw = getWid(w,cf); + + int ch = sibl.getHeight(s, cfr(cf), cw); + // ch /= depth+1; + // ch = (int)(80*cf); + addVert(upstart, -ch + overlap, rot); + addHoriz(upstart, bend, rot); + sibl.makeFlob(into, s, s, cfr(cf), + upstart.x, upstart.y, + 10, cw, ch, + rotunit * rot, + false); + tmp.setLocation(upstart); + addVert(tmp, ch/2, rot); + addHoriz(tmp, cw, rot); + childSeries(into, s, + tmp.x, tmp.y, + w, cf, rot, 1, depth); + } + + cf = fract; + + s=cur; + rot = orot; + while((s = s.s(replies_list, +1))!=null) { + // if(cy >= rd.height-borderLimit) break; + cf *= magfract; + rot += rotinc; + cw = getWid(w,cf); + + addHoriz(downstart, bend, rot); + addVert(downstart, - overlap, rot); + + int ch = sibl.getHeight(s, cfr(cf), cw); + // ch = (int)(80*cf); + // ch /= depth+1; + sibl.makeFlob(into, s, s, cfr(cf), + downstart.x, downstart.y, + 10, cw, ch, + rotunit * rot, + false); + tmp.setLocation(downstart); + addVert(tmp, ch/2, rot); + addHoriz(tmp, cw, rot); + + childSeries(into, s, + tmp.x, tmp.y, + w, cf, rot, 1, depth); + addVert(downstart, ch, rot); + } + + + // Parents + s = cur.h(replies_list).s(replies, -1); + if(dir <= 0 && s != null) + siblingSeries( + into, s, x - getWid(w, fract*magfract), + y, w, (float)(fract * magfract), + orot, -1, depth+1); + + + + + + + + } + + public void raster( FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed){ + accursed=accursed.h(text); + + Dimension rd = into.getSize(); + Dimension d = rd; + Dimension dprod = new Dimension(rd.width,70); + // Current rotation + double rot = 0; + + { + for(int i=0; i= 2) return; + ZZCell s; + + int upstartx, upstarty, downstartx, downstarty; + + // We do things differently depending on where we are. + // If going to positive direction, first see if we have odd + // or even number of cells and either put a cell in the middle + // or not + + boolean domiddle = true; + int count = 0; + if(dir == 1) { + count = cur.getRankLength(replies_list) - 1; + if(count % 2 == 0) { + domiddle = false; + } + // Either upper or middle + cur = cur.s(replies_list, count/2); + } + + int cw = (int)(w*fract); + + if(domiddle) { + + int h = sibl.getHeight(cur, cfr(fract), cw); + h /= depth+1; + // h = (int)(80*fract); + + sibl.makeFlob(into, cur, cur, cfr(fract), x, y-h/2, 1, cw, h, orot, + (dir == 0)); + + + // If not parent, put children for this center blob + if(dir >= 0) + childSeries(into, cur, x, y, w, fract, orot, 1, depth); + + upstartx = x; + upstarty = y - h/2; + + downstartx = x; + downstarty = y + h/2; + } else { + upstartx = x; + upstarty = y; + + downstartx = x; + downstarty = y; + } + + int cx = upstartx; + int cy = upstarty; + float cf = fract; + + s=cur; + //if(!domiddle) + // s = s.s(replies_list, 1); + double rot = orot; + rot = 0.0; + + + //--- + cx = downstartx; + cy = downstarty; + cf = fract; + + s=cur; + rot = orot; + + + count = cur.getRankLength(replies_list) - 1; + if( count > 0){ + FlobInfo[] fi = new FlobInfo[count]; + int flth=0; + pa("COUNT: " + count); + while((s = s.s(replies_list, +1))!=null ) { + cf *= magfract; + rot += 0.00; + cw = (int)(w*cf); + + int ch = sibl.getHeight(s, cfr(cf), cw); + // ch = (int)(80*cf); + ch /= depth+1; + fi[flth] = new FlobInfo(s,s,cfr(cf), cx,cy,1,cw,ch,rot); + pa("flth: " + flth); + //sibl.makeFlob(into, s, s, cfr(cf), cx, cy, 1, cw, ch, rot, + // false); + childSeries(into, s, cx, cy, w, fract, rot, 1, depth); + //cy += dy; + flth++; + } + + for( int i=1; i<= flth;i++){ + pa("i = " + i); + int mc = 4; + fi[flth-i].y += (flth-i)*(dy) + mc ; + fi[flth-i].x += (flth-i+1)*dx; + fi[flth-i].render(sibl,into); + } + } + cx = upstartx; + cy = upstarty; + cf = fract; + + s=cur; + rot = orot; + + + while(s != null && (s = s.s(replies_list, -1))!=null) { + // Don't do relcell + if(s.s(replies_list, -1) == null) break; + cf *= magfract; + rot = 0.00; + cw = (int)(w*cf); + + int ch = sibl.getHeight(s, cfr(cf), cw); + ch /= depth+1; + // ch = (int)(80*cf); + cy -= dy; + cx -= dx; + sibl.makeFlob(into, s, s, cfr(cf), cx, cy, 1, cw, ch, rot, + false); + childSeries(into, s, cx, cy, w, fract, rot, 1, depth); + } + + //-- + // Parents + s = cur.h(replies_list).s(replies, -1); + if(dir <= 0 && s != null) + siblingSeries( + into, s, x - (int)(w*fract*magfract), + y, w, (float)(fract * magfract), + orot, -1, depth+1); + } + + //} + + class FlobInfo { + int x; + int y; + int h; + int w; + int d; + ZZCell c; + ZZCell hc; + float fr; + double rot; + FlobInfo(ZZCell c, ZZCell hc, float fr, + int x, int y, int d, int w, int h, double rot){ + this.c = c; + this.h=h; + this.fr=fr; + this.x=x; + this.y=y; + this.d=d; + this.w=w; + this.hc=hc; + this.rot = rot; + } + void render(MessageFlobFactory mess, FlobSet into){ + mess.makeFlob(into, c, hc, fr, x, y, d, w, h, rot, + false); + } + + } + + + public void raster( FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed){ + accursed=accursed.h(text); + Dimension rd = into.getSize(); + Dimension d = rd; + + // Current rotation + double rot = 0; + + siblingSeries(into, accursed, 3*d.width/10, d.height/2, 2*d.width/5, + (float)1.0, 0, 0, 0); + + + } +} + + diff --git a/Modules/virtualcommunity/VCView4.java b/Modules/virtualcommunity/VCView4.java new file mode 100644 index 0000000..3901c2a --- /dev/null +++ b/Modules/virtualcommunity/VCView4.java @@ -0,0 +1,141 @@ +/* +VCView4.java + * + * Copyright (c) 2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ + + +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.awt.*; + +/** Second, cardstack-like virtualcommunity view. + */ + + +public class VCView4 extends VirtualCommunity { + public static final String rcsid = "$Id: VCView4.java,v 1.8 2001/02/28 10:18:20 tjl Exp $"; + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + int xstep = 40; + int ystep = 40; + + void mksideFlobs(FlobSet into, ZZCell cur, int x, int y, int w, int h, int d) { + cur = cur.s(replies); + if(cur == null) return; + y += 2*h/3; + h -= 2*h/3; + while((cur = cur.s(replies_list)) != null) { + if(into.findFlob(null, cur) != null) + return; + sibl.makeFlob(into, cur, cur, 0.5f, + x+w, y, d, w/3, h, 0, false); + y -= h/2; + h /= 2; + if(h == 0) return; + } + } + + Point singleSiblingSide(FlobSet into, ZZCell outside, int x, int y, + int w, float fract, int dir, int depth, int side) { + ZZCell cur = outside; + for(int i=1; (cur=cur.s(replies_list,side))!=null; i++) { + if(cur.s(replies_list, -1) == null) break; + float mult = fract / i; + x -= side * mult * xstep; + y += side * mult * ystep; + int h = sibl.getHeight(cur, cfr(fract), w); + sibl.makeFlob(into, cur, cur, cfr(fract), + x, y, 1+50*depth + 2*i, w, h, + 0, false); + mksideFlobs(into, cur, x, y, w+1, h, 1+50*depth); + } + return new Point(x,y); + } + + public void siblingSeries( FlobSet into, ZZCell cur, int x, int y, + int w, + float fract, int dir, int depth) { + // dept + int h = sibl.getHeight(cur, cfr(fract), w); + p("Sibser: "+cur+" "+h+" "+w+" "+x+" "+y); + sibl.makeFlob(into, cur, cur, cfr(fract), + x, y, 1+50*depth, w+1,h, + 0, (depth <= 2)); + if(depth > 2) + mksideFlobs(into, cur, x, y, w+1, h, 1+50*depth); + Point p0 = singleSiblingSide(into, cur, x, y, w, fract, dir, depth, 1); + Point p1 = singleSiblingSide(into, cur, x, y, w, fract, dir, depth, -1); + into.add(new LineDecor(p0.x, p0.y, p1.x, p1.y, Color.red, 1)); + } + + + public void raster( FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed){ + accursed=accursed.h(text); + Dimension rd = into.getSize(); + Dimension dprod = new Dimension(rd.width,70); + Dimension d = rd; + + ZZCell cur = accursed; + + int x = d.width / 3; + int y = d.height / 3; + int w = d.width / 3; + float fr = 1.3f; + + ZZCell child = accursed.s(replies, 1); + + if(child != null) { + child = child.s(replies_list, 1); + siblingSeries(into, child, 2 * d.width / 3, d.height / 2, w, + (float)(fr * 1.0), 0, 1); + } + + for(int pd = 0; pd<4 && cur != null; pd++) { + siblingSeries(into, cur, x, y, w, + fr, 0, 2 + pd); + cur = cur.h(replies_list).s(replies,-1); + fr *= 0.9; + w *= 0.9; + x -= 70; + y -= 70; + } + + if(isProd(accursed)){ + messagesFromProd(into,accursed,(float)1.0); + return; + } else if(isAuthor(accursed)){ + messagesFrom(into,accursed,(float)1.0, author); + return; + } + + addAuthor(into,accursed,1.0f); + + drawProducts(into, (float)1.0, dprod); + + } +} + + + diff --git a/Modules/virtualcommunity/VirtualCommunity.zob b/Modules/virtualcommunity/VirtualCommunity.zob new file mode 100644 index 0000000..bcb9353 --- /dev/null +++ b/Modules/virtualcommunity/VirtualCommunity.zob @@ -0,0 +1,444 @@ +/* +VirtualCommunity.zob + * + * Copyright (c) 2001 Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Vesa Parkkinen + */ + +package org.gzigzag.module; +import org.gzigzag.*; +import java.util.*; +import java.awt.*; + +/** A simple cell factory that gives the cells as one-line strings. + * Variable length is possible. + * UGLY: ALL PARAMS HERE. + */ + +public abstract class VirtualCommunity implements FlobView, ZOb { + public static final String rcsid = "$Id: VirtualCommunity.zob,v 1.36 2001/02/28 10:18:20 tjl Exp $"; + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + // some parameters would be needed, propably + STRUCTPARAMS { + Font font + = new Font("SansSerif", Font.PLAIN, 11); + + ZOb ftextlayouter + = new FTextLayouter(); + + double left + = 0.1; + + double middle + = 0.4; + + double right + = 0.3; + + double middleHeight + = 0.5; + + int xpad + = 5; + + int ypad + = 5; + + Color linecol + = Color.white; + + float magfract + = 0.8f; + + float rotunit + = 0.0f; + + int view2depth + = 4; + + float[] view2ctr // 2..2 + = new float[] {0.35f, 0.5f}; + + float view2wid + = 0.22f; + + float view2fract + = 1.4f; + + + } + + + /** Bold and italic derivatives of the font given. + * The first index is the level of the text i.e. + * from paragraph to H1. + */ + Font[][][] bifonts; + FontMetrics[][][] bifontms; + + INITIALIZE { + bifonts = new Font[7][2][2]; + bifontms = new FontMetrics[7][2][2]; + for(int l = 0; l < bifonts.length; l++) { + int size = font.getSize(); + if(l > 0 && l < 5) size += l-1; + if(l == 5) size += 6; + if(l == 6) size += 9; + bifonts[l][1][0] = new Font(font.getName(), + Font.BOLD, size); + bifonts[l][1][1] = new Font(font.getName(), + Font.BOLD | Font.ITALIC, size); + + if(l == 0) { + bifonts[l][0][0] = new Font(font.getName(), 0, size); + bifonts[l][0][1] = new Font(font.getName(), + Font.ITALIC, size); + } else { // All bold for headers + bifonts[l][0][0] = bifonts[l][1][0]; + bifonts[l][0][1] = bifonts[l][1][1]; + } + for(int b = 0; b<2; b++) + for(int i = 0; i<2; i++) + bifontms[l][b][i] = FONTMETRICS(bifonts[l][b][i]); + } + } + + Color linkcolor = Color.red; + Color default_bgcolor = Color.white; + + static String text = "d.text"; + static String handle = "d.kahva"; + static String author = "d.author"; + static String replies = "d.replies"; + static String replies_list = "d.replies-list"; + + static protected class Foobar implements ZZObs { + private void add() { + vc.h("d.cursor-cargo", -1, this). + h("d.cursor-list", -1, this).s("d.cursor", -1, this); + } + public void chg() { + ZZCell targ = ZZCursorReal.get(vc).h(text); + ZZCell hist = ZZDefaultSpace.findInheritableParam(vc,"history"); + if (targ.h("d.1").equals(hist)) { + p("Historical item"); + histpos = targ; + add(); + return; + } + ZZCell it = hist.s("d.1"); + while (!it.equals(histpos) && !ZZCursorReal.get(it).equals(targ)) + it = it.s("d.1"); + if (!it.equals(histpos)) { + histpos = it; + ZZCursorReal.set(vc, histpos); + } else if (!targ.equals(ZZCursorReal.get(histpos))) { + if (histpos.s("d.1") != null) histpos.disconnect("d.1",1); + histpos = histpos.N("d.1"); + ZZCursorReal.setcursor(histpos, targ); + } + add(); + } + public void init(ZZCell _vc, ZZCell hilite) { + if (inited == false || !_vc.equals(vc)) { + vc = _vc; + histpos = hilite; + inited = true; + } + add(); + } + boolean inited = false; + ZZCell vc; + public ZZCell histpos; + } + static protected Foobar histobs = new Foobar(); + + // flobFactories + MessageFlobFactory blobs = new MessageFlobFactory(); + MessageFlobFactory center = new MessageFlobFactory(); + MessageFlobFactory sibl = new MessageFlobFactory(this); + FlobFactory history = new MessageFlobFactory(); + boolean nohistory = true; + + /** Cut fracts into reasonable range. + */ + protected final float cfr(float fr) { + if (fr < 0.7f) return 0.7f; + if (fr > 2.0f) return 1.5f; + return fr; + } + + abstract public void raster( FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed); + static public ZZModule module = new ZZModule() { + public void action(String id, + ZZCell code, + ZZCell target, + ZZView view, ZZView cview, + String key, Point pt, ZZScene xi) { + if(id.equals("NEW")) { + + } else { + p("Unknown VC module action: "+id); + } + } + public ZOb newZOb(String id) { + if(id.equals("View")) + return new VCView2(); + if(id.equals("View2")) + return new VCView2(); + if(id.equals("View3")) + return new VCView3(); + if(id.equals("View4")) + return new VCView4(); + else + return null; + } + + + }; + + class VCLinker implements FlobDecorator{ + + public void decorate(FlobSet f, String path, ZZCell view) { + + + } + } + + class LinkFlob extends Flob { + int n = 4; + int[] xs = new int[n]; + int[] ys = new int[n]; + + // Color fg = new Color(0xa6dbac); + Color fg = new Color(0x86bbac); + + public LinkFlob(int x, int y, int x1, int y1, int x2, int y2) { + super(x,y,1,x1-x,y2-y1,null); + xs[0] = x; + xs[1] = x1; + xs[2] = x2; + + ys[0] = y; + ys[1] = y1; + ys[2] = y2; + + n = 3; + } + + public LinkFlob(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { + super(x,y,1,x1-x,y2-y1,null); + xs[0] = x; + xs[1] = x1; + xs[2] = x2; + xs[3] = x3; + + ys[0] = y; + ys[1] = y1; + ys[2] = y2; + ys[3] = y3; + + n = 4; + } + + + public void render(Graphics g, int mx, int my, int md, + int mw, int mh) { + Color old = g.getColor(); + g.setColor(fg ); + g.fillPolygon(xs, ys, n); + g.setColor(old); + } + + } + + + Hashtable prods; + + class Dfoo{ + int d; + Dfoo(int d){ + this.d = d; + } + } + + /** + * + */ + + void product(ZZCell c, Point p){ + if(c == null ) return; + if( prods == null) prods = new Hashtable(); + // XXX overwrites... + prods.put(c, p); + } + + + public void messagesFromProd(FlobSet into, ZZCell c, float fract){ + messagesFrom(into,c,fract,handle); + + } + + public void messagesFrom(FlobSet into, ZZCell c, float fract, + String dim){ + ZZCell d = c.h(text,-1); + + int xpad = 5; + int ypad = 5; + int y = ypad; + int w = 100; + int h = into.getSize().height; + int x = into.getSize().width - w - xpad; + int l = d.getRankLength(dim) -1; + pa("L = " + l); + + if( l < 1 ) return; + int hd = h/l; + hd -= ypad; + int depth = 1; + Flob flob = sibl.getSFlob().getFlobSet().findFlob(null,c); + Point pnt = flob.getPoint(1,0); + int cx = pnt.x;//into.getSize().width/2; + int cy = pnt.y; + + d = d.s(dim,1); + ZZCell tmp = d; + while(d != null){ + // make flob + tmp = d.h(text,-1); + sibl.makeFlob(into, tmp, tmp, cfr(fract), + x, y, depth, w,hd, + 0, false); + + // draw link + into.add(new LinkFlob(cx,cy, + x,y+ypad, + x,y+hd-ypad)); + + + d = d.s(dim,1); + y+=hd + ypad; + + } + } + + + + boolean isProd(ZZCell c){ + p("isProd: " + c); + c = c.h(text,-1); + if( c == null ) return false; + if( c.h(handle,-1) == c && c.s(handle,1) != null){ + p("TRUE"); + return true; + } + return false; + } + + boolean isAuthor(ZZCell c){ + + if( c.h(author,-1) == c && c.s(author,1) != null ) + return true; + + return false; + } + + + ZZCell getAuthor(ZZCell c){ + ZZCell d = c.h(text,-1); + d = d.h(author,-1); + return d; + } + + + void addAuthor(FlobSet into, ZZCell c, float fract){ + if( isAuthor(c) ) return; + p("add author"); + if( c==null) return; + ZZCell a = getAuthor(c); + if( a == null ) return; + Dimension d = into.getSize(); + int xpad = 5; + int ypad = 5; + int w = d.width / 5; + int h = d.height / 5; + int x = 0+xpad; + int y = d.height - h-ypad; + int depth = 1; + sibl.makeFlob(into,a,a, fract, + x,y,depth,w,h,0,false); + Flob fl = into.findFlob(null, c); + Point p = fl.getPoint(-1,0); + into.add(new LinkFlob(p.x+5, p.y, p.x,p.y, x+w, y,x+w+5,y)); + } + + + + /** + * + */ + public void drawProducts(FlobSet into, float fraction, + Dimension dp){ + // draw products from cells + p("cells"); + if( prods == null || prods.size() < 1 ) return ; + + int nprods = prods.size(); + + int upperH = dp.height; + int w = into.getSize().width; + int ypad = 5; + int y = ypad; + int xpad = 10; + int x = xpad/2; + int wd = w/(nprods); + int d = 1; + int dprod = 1; + if( wd > w/2 ) wd = w/2; + //FlobSet fs = sibl.getFlobSet(); + + wd -= xpad; + + for(Enumeration e = prods.keys(); + e.hasMoreElements();){ + + + ZZCell cell = (ZZCell)e.nextElement(); + Point p = (Point)prods.get(cell); + + //Dimension pd = blobs.getSize(cells[i], fraction); + //if ( pd == null ) continue; + sibl.makeFlob(into, cell, cell, fraction,x,y,d, + wd,upperH, 0, false); + + int center = x+wd/2; + + into.add(new LinkFlob(center+5, upperH, center, upperH, + p.x,p.y,p.x+5,p.y)); + + x += wd + xpad; + } + } +} + +// vim: set syntax=java : diff --git a/Modules/vob/Connection.java b/Modules/vob/Connection.java new file mode 100644 index 0000000..0b703a6 --- /dev/null +++ b/Modules/vob/Connection.java @@ -0,0 +1,47 @@ +/* +Vob.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** A connection to draw between two vobs. + * This doesn't need to store the vob coordinates, so the same Connection + * object can actually be used to draw many connections. + */ + +public abstract class Vob extends Renderable { +public static final String rcsid = "$Id: Connection.java,v 1.1 2001/01/20 08:56:19 bfallenstein Exp $"; + + /** Render this connection between the given vobs. + * Default: render nothing. + */ + public void render(Graphics g, Vob v1, int x1, int y1, + Vob v2, int x2, int y2) { + } + + /** Returns an object telling what was hit. + * Default implementation: returns null. + * XXX interaction with coords? + */ + public Object hit(Vob v1, Vob v2) { return null; } +} diff --git a/Modules/vob/View.java b/Modules/vob/View.java new file mode 100644 index 0000000..330c150 --- /dev/null +++ b/Modules/vob/View.java @@ -0,0 +1,38 @@ +/* +FlobRaster.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; + +/** A fairly general interface for drawing a structure + * on the screen using vobs. + * The parameters have been read through the ZOb interface so + * we don't need to worry about those here. + */ + +public abstract class View { +String rcsid = "$Id: View.java,v 1.1 2001/01/20 08:56:19 bfallenstein Exp $"; + /** Draw a representation of the structure into the VobSet. + */ + public abstract void raster(VobSet into, ZZCell what, CellView cv, + ZZCell win, String[] dims, ZZCell accursed); +} \ No newline at end of file diff --git a/Modules/vob/Vob.java b/Modules/vob/Vob.java new file mode 100644 index 0000000..c32c4d1 --- /dev/null +++ b/Modules/vob/Vob.java @@ -0,0 +1,142 @@ +/* +Vob.java + * + * Copyright (c) 2000, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuomas Lukka + */ +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** A vob or visual object shown on the screen. + * Vobs are constant read-only objects like Strings. + *

    + * Vobs should be able to render themselves quickly for animations; + * caching relevant information in this structure is therefore a good idea. + *

    + * The minimal vob implementation simply implements the + * render(Graphics, int, int, int, int, int) method. + */ + +public abstract class Vob extends Renderable { +public static final String rcsid = "$Id: Vob.java,v 1.1 2001/01/20 08:56:19 bfallenstein Exp $"; + + public int w, h; + + /** The cell associated with this vob. + * This may be set to null for things that are - well - just + * things rendered. But those should be in a minority always. + */ + public ZZCell c; + + /** The vob we are interpolating with. + * Storing it here is a pure speed hack: in reality it'd belong in + * a hashtable somewhere. But this is crucial for the frame rate. + */ + protected Vob interpTo; + + /** A 3-tuple with the global coordinates for this vob. + * Conceptually this belongs in the VobStore, but I can't think of a + * clean, not too wasteful implementation. + */ + protected int[] coords; + + /** The lowest-level VobSet this was placed into. + */ + public VobSet vobset; + + public Vob(ZZCell c) { + this.c = c; + } + + /** Get the visual center of this vob. + */ + public Point getCenter(Point p) { + p.x = w/2; p.y = h/2; + return p; + } + + /** Get the visual center of this vob. + */ + public Point getCenter() { + return getCenter(new Point()); + } + + /** Render this vob at the given coordinates. + * Default: render nothing. + * You may override either this function or one or both of + * render(Graphics, int, int) and renderInterp(Graphics, int, int, + int, int, float). + */ + public void render(Graphics g, int mx, int my, int md, + int mw, int mh) { + } + + /** Render this vob. + * May be overridden; default implementation uses render(g, x, y, w, h, d); + */ + public void render(Graphics g, x, y, d) { + render(g, x, y, d, w, h); + } + /** Render an interpolated version of this vob. + * Default implementation uses render(g, x, y, d, w, h) with linearly + * interpolated coordinates. + */ + public void renderInterp(Graphics g, float fract) { + Vob r = interpTo; + if(r==null) return; + render(g, + (int)(x + fract*(r.x-x)), + (int)(y + fract*(r.y-y)), + (int)(d + fract*(r.d-d)), + (int)(w + fract*(r.w-w)), + (int)(h + fract*(r.h-h)) + ); + } + + /** Whether it would make visually sense to interpolate + * this vob. + * Default implementation: whether the sum of the squares of + * the differences of the coordinates and widths is more than 100. + * Not a terribly useful measure but good enough. + */ + public boolean isInterpUseful() { + Vob r = interpTo; + if(r==null) return false; + return (r.x - x) * (r.x - x) + + (r.y - y) * (r.y - y) + + (r.w - w) * (r.w - w) + + (r.h - h) * (r.h - h) > 100; + } + + + /** Returns an object telling what was hit. + * Default implementation: returns null. + */ + public Object hit(int x, int y) { return null; } + + /** A convenience routine to check whether a point + * is inside the defining rectangle. + * If the vob is (as many are) rectangular, this routine can + * be used to check the hit. + */ + public final boolean insideRect(int x0, int y0) { + return x0 >= x && y0 >= y && x0 < x+w && y0 < y+h; + } +} diff --git a/Modules/vob/VobSet.java b/Modules/vob/VobSet.java new file mode 100644 index 0000000..c58e7ea --- /dev/null +++ b/Modules/vob/VobSet.java @@ -0,0 +1,66 @@ +/* +VobSet.java + * + * Copyright (c) 2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** A VobSet. + * This extends Vob in order to get interpolated. XXX is this right? + */ + +public class VobSet extends Vob { +public static final String rcsid = "$Id: VobSet.java,v 1.1 2001/01/20 08:56:19 bfallenstein Exp $"; + + public static final boolean dbg = true; + private static final void p(String s) { if(dbg) System.out.println(s); } + private static final void pa(String s) { System.out.println(s); } + + public VobStore store; + + public ZZCell applitude; + public static ZZCell getApplitude(Vob vob) { return null; } + + public void add(Vob vob, int vx, int vy, int vd) { + store.add(vob, vx+x, vy+y, vd+d, this); + } + + public void add(Connection c, Vob from, Vob to) { + store.add(c, from, to, this); + } + + /** Add a vob as a connection, i.e. in the middle between two other vobs. + * XXX how? + */ + public void add(Vob vob, Vob from, Vob to) { + } + + public void add(Decoration d) { + store.add(d); + } + + public int getX(Vob v) { return v.x - x; } + public int getY(Vob v) { return v.y - y; } + public int getD(Vob v) { return v.d - d; } + public int[] getCoords(Vob v) { return new int[] { v.x-x, v.y-y, v.d-d }; } + +} \ No newline at end of file diff --git a/Modules/vob/VobStore.java b/Modules/vob/VobStore.java new file mode 100644 index 0000000..1f5d7b9 --- /dev/null +++ b/Modules/vob/VobStore.java @@ -0,0 +1,64 @@ +/* +VobStore.java + * + * Copyright (c) 2001, Ted Nelson and Tuomas Lukka + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** A store for Vobs. + */ + +public class VobStore implements ZZScene { +public static final String rcsid = "$Id: VobStore.java,v 1.1 2001/01/20 08:56:19 bfallenstein Exp $"; + + public static final boolean dbg = true; + private static final void p(String s) { if(dbg) System.out.println(s); } + private static final void pa(String s) { System.out.println(s); } + + public boolean interpConns = false; + + /** Visual objects. + */ + private int nvobs; + private Vob[] vobs = new Vob[30]; + boolean vsorted = false; + boolean vtagged = false; + + /** Connections between vobs. + * These are rendered before (under) the vobs of the same depth. Note + * that they are interpolated if the interpConns flag is set. + */ + private int nconns; + private Connection[] conns = new Connection[30]; + boolean csorted = false; + + /** Decorations. + * These are always rendered last (above everything else). They are never + * interpolated. + */ + private int ndecors; + private Decoration[] decors = new Decoration[2]; + + // ??? private int maxdepth = 0; + +} + diff --git a/Modules/wordnet/conv.pl b/Modules/wordnet/conv.pl new file mode 100644 index 0000000..5f41174 --- /dev/null +++ b/Modules/wordnet/conv.pl @@ -0,0 +1,160 @@ +# A script to convert wordnet files to ZZ. +# Uses Lingua::Wordnet from CPAN. + +$N = 10000; +$NLETT = 3; + +use Lingua::Wordnet; + +$wn = new Lingua::Wordnet; + + +for my $k (keys %{$wn->{indexhash}}) { + print $k,"\n" if ++$n % 1000 == 0; + last if $n > $N; + local $_ = $k; + s/\%.*//; + # Only nouns. + @synsets = $wn->lookup_synset($_, "n"); + next if !@synsets; + push @words, $_; +} + +@words = sort @words; + +$id = 1; +$txt = ""; +$conns = ""; +$pref = ""; + +$hiercon = ""; +@hier = (); + +$conns .=qq{}; +# Cells for all words. +print "WORDS\n"; +undef $prev; +for(@words) { + my $prevhier; + if($pref ne substr $_, 0, $NLETT) { + for my $i (1..$NLETT) { + my $sub = substr($_, 0, $i); + if(substr($pref, 0, $i) ne $sub) { + $sub = qxml($sub); + $txt .= + qq{$sub\n}; + if(defined $hier[$i]) { + $conns .= qq{ + }; + } + $hier[$i] = $id; + if(defined $prevhier) { + $hiercon .= qq{ + }; + } + $prevhier = $id; + $id++; + } + } + $pref = substr $_, 0, $NLETT; + } + my $t = qxml($_); + $txt .= qq{$t\n}; + $conns .= qq{\n} if defined $prev; + if(defined $prevhier) { + $hiercon .= qq{ + \n}; + } + $prev = $id; + $words{$_} = $id++; +} +$conns .= qq{}; + +$conns .= qq{ $hiercon }; + +# Look for synsets. +print "SYNSETS\n"; +$conns .=qq{}; +for my $w (@words) { + @synsets = $wn->lookup_synset($w, "n"); + $prev = $words{$w}; + for my $synset (@synsets) { + my $offs = $synset->offset(); + if(!exists $synsets{$offs}) { + $gloss = qxml($synset->gloss()); + $txt .= qq{$gloss\n}; + $synsets{$offs} = $id++; + } + $txt .= qq{\n}; + $conns .= qq{\n}; + $prev = $id; + $ssw{$offs."%".$w} = $id++; + } +} +$conns .= qq{}; + +# Connect words inside synset. +print "WORDS IN SYNSETS\n"; +$conns .=qq{}; +for my $k (keys %synsets) { + $synset = $wn->lookup_synset_offset($k); + my @w = $synset->words(); + $prev = $synsets{$k}; + for my $w (@w) { + $w =~ s/\%.*//; + next unless exists $words{$w}; + $c = $ssw{$k."%".$w}; + die "NO SSW '$k' '$w'" unless defined $c; + $conns .= qq{\n}; + $prev = $c; + } +} +$conns .= qq{}; +undef %ssw; +undef @words; +undef %words; + +# Hypo- and hypernyms. +print "HYPO\n"; +$conns .=qq{}; +for my $k (keys %synsets) { + @hypos = $wn->lookup_synset_offset($k)->hyponyms(); + $prev = $synsets{$k}; + for my $h (@hypos) { + my $offs = $h->offset(); + next unless exists $synsets{$offs}; + $txt .= qq{\n}; + $conns .= qq{\n}; + $prev = $id; + $hyp{$offs."%".$k} = $id++; + } +} +$conns .= qq{}; + +print "HYPER\n"; +$conns .=qq{}; +for my $k (keys %synsets) { + @hyper = $wn->lookup_synset_offset($k)->hypernyms(); + $prev = $synsets{$k}; + for my $h (@hyper) { + $lid = $hyp{$k."%".$h->offset()}; + next unless defined $lid; + $conns .= qq{\n}; + $prev = $lid; + } +} +$conns .= qq{}; +undef %hyp; + + +open F, ">out.xml"; +print F qq{ }, $txt, $conns, ""; + +sub qxml { + local $_ = $_[0]; + s/&/&/g; + s//>/g; + s/"/"/g; + return $_; +} diff --git a/Modules/xml/XML.java b/Modules/xml/XML.java new file mode 100644 index 0000000..29779a5 --- /dev/null +++ b/Modules/xml/XML.java @@ -0,0 +1,276 @@ +/* +XML.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Tuukka Hastrup + * Very heavily modified by Tuomas Lukka + */ + +/** An XML importer/exporter. + *

    + * Export:

      + *
    • with data view cursor, point to a cell containing the filename + *
    • running the action XML.EXPORT will now export the whole space + *
    + *

    + * Import:

      + *
    • with data view cursor, point to a cell containing the filename + *
    • if there's a cell from that cell poswards on d.1, this cell + * will be used as a root for the imported space, otherwise a new + * cell is created there + *
    • running the action XML.IMPORT will now import the whole space. + * XXX Notice that if there was a connection from home cell + * negwards on d.1 to be imported, it's not there because that's where + * the filename cell is! + */ + +package org.gzigzag.module; + +import org.gzigzag.*; +import java.io.*; +import java.net.*; +import org.w3c.dom.*; +import org.xml.sax.*; +import org.xml.sax.helpers.*; +//import org.openxml.x3p.*; +import org.apache.xml.serialize.*; +import java.util.*; + +import java.awt.Point; + +public class XML { +public static final String rcsid = "$Id: XML.java,v 1.11 2000/11/03 08:01:05 ajk Exp $"; + + public static boolean dbg = true; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + static public XMLReader getXMLReader() { + return new org.apache.xerces.parsers.SAXParser(); + } + static public Document getDocument() { + return new org.apache.xerces.dom.DOMImplementationImpl(). + createDocument(null, "ZZSpace", null); + } + static public XMLSerializer getXMLSerializer(Writer writ) { + return getXMLSerializer(writ, "UTF-8"); + } + static public XMLSerializer getXMLSerializer(Writer writ, String enc) { + return new org.apache.xml.serialize.XMLSerializer(writ, + new org.apache.xml.serialize.OutputFormat("doc", + enc, true)); + } + + ZZSpace zz; + + static public ZZModule module = new ZZModule() { + public void action(String id, ZZCell code, + ZZCell target, + ZZView v, ZZView cv, + String key, Point pt, + ZZScene xi) { + if(id.equals("EXPORT")) { + synchronized(code.getSpace()) { + (new XML()).export(new File(target.getText()), code.getSpace()); + } + } else if(id.equals("IMPORT")) { + (new XML()).load(new File(target.getText()), target.getOrNewCell("d.1", 1)); + } + } + }; + + AttributesImpl ats(String[] a) { + AttributesImpl ai = new AttributesImpl(); + for(int i=0; i +# +# Description: +# =========== +# +# This is a simple script to port ZigZag (Andrew Pam's perl version) spaces +# to xml. +# +# Usage: +# ===== +# +# First convert zigzag file to ASCII using zzdump from . +# Then convert that file to XML using this script. +# +# zzdump oldfile > somefile +# old2xml.pl < somefile > newfile.xml +# +# +# +# WARNING: +# ======= +# +# This script leaves out all connections and cells that +# have anything to do with d.cursor !!! +# It also adds 1000 to cell ids, just to avoid collision with GZZ cell ids. +# ( This should be changed to something more elegant ) +# +# +############################################################################# + + +$_ = <>; + +#%names; +print qq( + + +); +my $buffer; +while (<>) { + #print "line: $_\n"; + s/ {2,}//; + + if (/'(\d+)'.*/ or /^(\d+).*/) { + + $cellno = $1; + + /.*=>(.*)/; + + $val = $1; + unless ( $val =~ /,/ ) { + $val .= "\n" . <>; + } + $val =~ s/'//g; + # ' + $val =~ s/,//g; + $val =~ s/^ //g; + $val =~ s/ $//g; + + #print "$val\n"; + $names{$cellno} = $val; + } else { + $buffer .= $_; + } + +} + +#while ( ($key, $value) = each %names) { +# print "KEY: $key = VALUE:$value\n"; +#} + +delete $names{0}; + +@lin = split /\n/,$buffer; + +print qq(home\n); + +#@lines = sort @lin; +@lines = @lin; +#print "lines = @lines"; + +foreach (@lines) { + + if (/d\.cursor/) { + goto NEW; + } + if (/'n' => 100/) { + goto NEW; + } + /'(\d+)(.)(.+)'\s+=>\s+(\d+)/; + + $cell = $1; + if ($2 eq "-"){ $dir = -1; } + else { + $dir = 1; + } + + $dim = $3; + $other = $4; + + $cc = $names{$other}; + $cc2 = $names{$cell}; + + $nother = $other + 1000; + $ncell = $cell + 1000; + #print "cc = $cc, cc2 = $cc2\n"; + if ($cc && ! $cc2) { + + print qq($cc\n); + delete $names{$other}; + + } elsif ( $cc2 ) { + + $new_buf .= $_ . "\n"; + + } + else { + $conn_buf .= $_ . "\n"; + } + NEW: +} + +while ($new_buf) { + + + @new_lines = split /\n/,$new_buf; + $new_buf = ""; + @new_lines = sort @new_lines; + #print "NEW_LINES @new_lines /NEWLINES\n"; + + foreach (@new_lines) { + + #print "LINE:$_\n"; + /'(\d+)(.)(.+)'\s+=>\s+(\d+)/; + #print "S1 = $1 S2 = $2 S3 = $3 S4 = $4\n"; + $cell = $1; + if ($2 eq "-"){ $dir = -1; } + else { + $dir = 1; + } + + $dim = $3; + $other = $4; + #print "S1 = $cell S2 = $dir S3 = $dim S4 = $other\n"; + $cc = $names{$other}; + $cc2 = $names{$cell}; + #print "CELLS:cc = $cc, cc2 = $cc2\n"; + $nother = $other + 1000; + $ncell = $cell + 1000; + +# if (! $cc || ! $cc2 ) { +# print "CELLS2:cc = $cc, cc2 = $cc2\n"; +# $new_buf .= $_ . "\n"; +# goto START; +# } + if ($cc && ! $cc2) { + + print qq($cc\n); + delete $names{$other}; + + } elsif ( $cc2 ) { + + $new_buf .= $_ . "\n"; + + } + else { + $conn_buf .= $_ . "\n"; + } + +# +# print qq($cc\n); +# delete $names{$other}; + START: + } +} + +if (! $conn_buf) { + goto END; +} + +@conn_lines = split /\n/,$conn_buf; + +foreach (@conn_lines) { + #print "$_\n"; + /'(\d+)(.)(.+)'\s+=>\s+(\d+)/; + #print "S1 = $1 S2 = $2 S3 = $3 S4 = $4\n"; + $cell = $1; + + if ($2 eq "-"){ $dir = -1; } + + else { + $dir = 1; + } + + $dim = $3; + $other = $4; + + + #print "S1 = $cell S2 = $dir S3 = $dim S4 = $other\n"; + $cc = $names{$other}; + $other = $other + 1000; + $cell = $cell + 1000; + + print qq(\n) +} + +END: +print "\n"; diff --git a/Modules/zaubertrank/README.html b/Modules/zaubertrank/README.html new file mode 100644 index 0000000..0669614 --- /dev/null +++ b/Modules/zaubertrank/README.html @@ -0,0 +1,111 @@ + + + The zaubertrank applitude + + + +

      +The zaubertrank applitude

      + +
      by Benjamin Fallenstein (b.fallenstein@gmx.de)
      + +

      +Name issues

      +The zaubertrank is pronounced TSAU-ber-trunk. The name means "magic potion" +in German. +

      +Raison d'être

      +"Programming for people." As +Chris +Crawford argues in his book +Understanding +Interactivity (2000), computers can expand our capabilities of +thought as much as the written word, but in a different direction: while +writing improved our sequential thinking (thinking in complex chains of +ideas), computers can improve what Chris calls subjunctive thinking (thinking +in many different possibilities). While the book allowed us to bring together +many different ideas, the computer program allows us to explore the countless +permutations resulting from a fixed set of rules. Instead of explaining +the effects of every single possible action to a recipient, we can write +a simulation they can experiment with. +

      Write a simulation? We need to be able to program for that, right? +

      The zaubertrank aims to be what the alphabet was (following Chris' line +of thought) for the Greeks: the very tool that made writing easy to learn, +that was the necessary prerequisite for a culture in which 'everybody' +(every free grown-up male) was supposed to be able to read and write. Before +the alphabet, there were thousands and thousands of signs which one needed +to know by heart in order to produce a written text, or even understand +one. Scribes where a very special class of people who had gotten a lot +of training. The alphabet reduced these signs to a small number which, +once learned, resembled the spoken language. Something people already knew. +

      So what does the zaubertrank do? In a way, the same. The complex world +of signs and abbrevations programming languages consist of is translated +into natural language (albeit not everyday language). Sentences like "Put +the selected card on top of the stack the user clicked on" replace cryptic +formulas like "selected.put(clickStack)," formulas which need time to understand +and more time to actively write. The user doesn't enter these sentences; +that would require a natural language parser far beyond our reach. Rather, +they put it together from fragments functionally equivalent to the tokens +of a programming language: "Put (which card?) on (which stack?)," "the +selected card," and "the stack the user clicked on." This putting together +with menus and mouses also ensures that there can't be any syntax errors: +the computer won't allow the user to enter anything wrong. +

      Will this make computer programming trivial? No, unfortunately not. +Creating a program will still be a complex task needing some thought. But +hopefully, the barriers will be lowered, the learning curve will be better, +and a program won't look as cryptic to non-programmers. +

      +My aim right now

      +In 2001, I will be teaching a course on Interactive Storytelling, which +uses the computer for interactive literary narrative. The interaction here +is not between author and reader or even different authors; rather, it's +between the reader and their computer. Stories take the form of interactive +simulations. Ever read a Choose Your Own Adventure book? Well, if +you imagine a more intelligent behind-the-scenes system than "flip to a +different page," you have the idea of what we'll be dealing with at first. +

      As the people in this course won't be computer science students, I need +some good way to teach them programming easily without wasting too +much time on it. +

      So right now, I'm working on a first version of the zaubertrank, which +shall be suitable for the needs of my course. The goals are: user interaction +in "turns;" relative freedom in the internal workings of the literary simulation; +easy to use for some simple structures, without the need of understanding +the internals right off; an interface showing some text and some possible +reactions (which you can click on). Of course, I need some good editing +tools for the programs, too. +

      I want to realize this as a GZigZag +applitude or zone of functionality. ZigZag(tm) is a new "world" +for computing, designed by +Ted Nelson, +the inventor of computer-based hypertext. It aims to be a replacement for +the file system, for the common user interfaces, for confining structures +like lists, tables, and hierarchies, and for many other things most people +take for granted in their everyday computer use. GZigZag is a free implementation +of the system, lead by Tuomas Lukka at the University of Jyväskylä, +Finland. An applitude is to ZigZag what an application is to the common +computer world, with the difference that applitudes are combinable -- that +is, they live in the same bigger structure and can share parts of their +substructures. One way to look at applitudes is to say they're a way to +interpret a part of the structure. Applitudes can contain custom views, +that is views of the structure which look (somewhat) like the text editors +or other programs we know so well. At the same time, the underlying structure +can be viewed in generic views, which show the "bare metal" in useful ways, +so that it's easy to see how things are stored. +

      Why, you ask, would anyone choose a completely different computer world +they have trouble explaining as the basis for a new system of computer +programming which shall function as the core of a new form of literature +they have even more trouble explaining? Well, because the trouble with +today's programming languages is not only in their cryptic syntax, but +also in the non-visibility of their inner workings. A whole mental model +needs to be build of variables, objects and so on, which can never be shown +on the screen (or only with sophisticated tools written for the classroom). +ZigZag makes this simple. If the underlying design is right, it will be +easy to show what's going on when a program is executed. Besides, once +the ZigZag model is learned, modeling otherwise complex structures in programs +will be easy, because the ZigZag model makes them easy: that's why Tuomas, +the technical leader of the GZigZag project, calls it a "hyperstructure +kit," a toolkit for creating structures beyond lists, tables, and hierarchies. +

      +Components I need

      + + diff --git a/Modules/zaubertrank/TokenTextCellView.java b/Modules/zaubertrank/TokenTextCellView.java new file mode 100644 index 0000000..4985bb8 --- /dev/null +++ b/Modules/zaubertrank/TokenTextCellView.java @@ -0,0 +1,65 @@ +/* +TokenTextCellView.zob + * + * Copyright (c) 2001, Benja Fallenstein + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benja Fallenstein + */ + +package org.gzigzag; +import java.util.*; +import java.awt.*; + +/** A cell view for showing (and editing) the text of a zaubertrank token. + * (This is to be used with ideosyncratic, not as the main cell view for a + * window.) The text for a token is connected to the token poswards on + * d.zt-text. Variables are recognized by them being clones. Their names are + * simply the content of the cloned cell. Thus, clones are shown with a + * different background/foreground; that's all we do to distinguish variables. + */ + +public class TokenTextCellView extends FTextCellView { +public static final String rcsid = "$Id: TokenTextCellView.java,v 1.1 2001/04/01 17:45:17 bfallenstein Exp $"; + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + public static String zttext = "d.zt-text"; + public static Color varbg = Color.darkGray; + public static Color varfg = Color.gray; + + /** Get the FText for this cell at the given scale. + * scale == fract * 1000. + */ + protected FText getFText(ZZCell c0, int scale) { + ZZCell cells[] = c0.readRank(zttext, 1, false); + FText.Part parts[] = new FText.Part[cells.length]; + + for(int i=0; i=0; i--) args[i] = data.pop(); + data.push(p.eval(new Data(args))); + } else if(root.s("d.zt-arg") != null) { + int nr = Data.i(root.s("d.zt-arg")); + data.push(frame.o(nr)); + } else { // FUNCTION CALL! (XXX need argument reads) + throw new ZZError("Function calls aren't working yet!"); +/* + Parser.DecNode dn = new Parser.DecNode(root); + Object[] args = new Object[dn.params.length]; + for(int i=args.length-1; i>=0; i--) args[i] = data.pop(); + returns.push(pos); + frames.push(frame); + frame = new Data(args); + pos = dn.c.h("zaubertrank:rpn"); // XXX fix +*/ + } + pos = pos.s(Parser.sequencedim); + } + + static public Object eval(ZZCell what, Data args) { + Evaluator e = new Evaluator(what, args); + while(e.running()) e.step(); + if(e.failed) return null; + return e.data.pop(); + } + + public boolean running() { + return (!failed && pos != null); + } + + public boolean finished() { + return (!failed && pos == null); + } +} \ No newline at end of file diff --git a/Modules/zaubertrank/old/ParsedView.zob b/Modules/zaubertrank/old/ParsedView.zob new file mode 100644 index 0000000..e1f11d7 --- /dev/null +++ b/Modules/zaubertrank/old/ParsedView.zob @@ -0,0 +1,209 @@ +/* +ParsedView.zob + * + * Copyright (c) 2000, Benjamin Fallenstein + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ +package org.zaubertrank; +import org.gzigzag.*; +import java.awt.*; +import java.util.*; + +/** A view for the zaubertrank using the Parser class. + */ + +public class ParsedView implements FlobView, ZOb { + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + + STRUCTPARAMS { + /** The font to use. */ + Font font + = new Font("SansSerif", Font.PLAIN, 16); + + ZOb ftextlayouter + = new FTextLayouter(); + + /** Whether to mark the accursed part. */ + boolean mark + = false; + + int xmargin + = 8; + + int ymargin + = 2; + + int yspace + = 10; + } + + FontMetrics fm; + + INITIALIZE { + fm = FONTMETRICS(font); + } + + static class TokenPart extends FText.CellPart { + int tkNumber; + ZZCell tkHandle; + public TokenPart(ZZCell c, int offs, int n, Font f, FontMetrics fm, + Color bg, Color fg, int tkNumber, ZZCell tkHandle) { + super(c, offs, n, f, fm, bg, fg); + this.tkNumber = tkNumber; + this.tkHandle = tkHandle; + } + public FText.Part subpart(int first, int last) { + return new TokenPart(c, offs+first, last-first, f, this.fm, + bg, fg, tkNumber, tkHandle); + } + public Renderable rend(int x, int y, int d, Renderable prev0) { + TokenFlob prev = null, parent = null, res; + p("SimpleView.TokenPart.rend prev "+prev0); + if(prev0 instanceof TokenFlob) { + prev = (TokenFlob)prev0; + if(prev.c != this.c) prev = null; + else if(prev.parent != null) parent = (TokenFlob)prev.parent; + else parent = prev; + } + p("SimpleView.TokenPart.rend found prev "+prev+" -- parent "+parent); + res = new TokenFlob(x, y, d, width(), height(), + c, s, f, this.fm, parent, offs, n, bg, tkHandle); + if(prev != null) res.setPrev(prev); + if(parent == null) res.tkNumber = tkNumber; + p("SimpleView.TokenPart nr "+tkNumber+" has nr "+res.tkNumber+" rend: "+res); + return res; + } + } + + FText.Part make(ZZCell c, int number, ZZCell tkHandle, + ZZCell view) { + Color bg = null; + if(mark && tkHandle.equals(ZZCursorReal.get(view))) + bg = ZZCursorReal.getColor(view); + Color fg = Color.black; + return new TokenPart(c, 0, -1, font, fm, bg, fg, number, tkHandle); + } + FText.Part make(String s) { + return new FText.StringPart(s, font, fm, null, Color.black); + } + + void getParts(Vector v, Parser.TypeRef tr, TokenGrouper g, int parent, + ZZCell tkHandle, ZZCell view) { + int number = g.addToken(parent); + ZZCell[] text = tr.getText(); + if(text == null) { v.addElement(make("")); return; } + v.addElement(make("[")); + for(int i=0; i= 0) inits[1] = res.y + res.height + 2*ym + yspace + 6; + } + + public void raster(FlobSet into, FlobFactory fact, + ZZCell view, String[] dims, ZZCell accursed) { + ZZCell c = accursed; + while(c.h(Parser.paramdim) != c || + c.h(Parser.valuedim) != c) { + c = c.h(Parser.paramdim); + c = c.h(Parser.valuedim); + } + + TokenGrouper grp = new TokenGrouper(); + Parser.GrammarNode gn = new Parser.GrammarNode( + view.getSpace().getHomeCell().s(Parser.grammardim)); + Parser.ExpNode en = new Parser.ExpNode(c); + Dimension size = into.getSize(); + Rectangle rect = new Rectangle(xmargin, ymargin, size.width-2*xmargin, + size.height-2*ymargin); + + int[] inits = new int[2]; + inits[0] = (inits[1] = rect.y + rect.height/2); + + place(into, en, rect, grp, gn, 0, view, inits); + + for(Parser.ExpNode en0 = en.step(-1); + en0 != null && inits[0] > rect.y; + en0 = en0.step(-1)) { + place(into, en0, rect, grp, gn, -1, view, inits); + } + + for(Parser.ExpNode en1 = en.step(1); + en1 != null && inits[1] < rect.y+rect.height; + en1 = en1.step(1)) { + place(into, en1, rect, grp, gn, 1, view, inits); + } + + grp.group(into); + } +} +// vim: set syntax=java : diff --git a/Modules/zaubertrank/old/Parser.java b/Modules/zaubertrank/old/Parser.java new file mode 100644 index 0000000..b3e4781 --- /dev/null +++ b/Modules/zaubertrank/old/Parser.java @@ -0,0 +1,275 @@ +/* +Parser.java + * + * Copyright (c) 2000, Benjamin Fallenstein + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ + +package org.zaubertrank; +import org.gzigzag.*; +import java.util.*; + +/** A parser for zaubertrank programs. + * Currently micro-level: the biggest structure recognized is one statement. + */ + +public class Parser { +public static final String rcsid = "$Id: Parser.java,v 1.1 2001/04/02 20:29:05 bfallenstein Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + static Object NULL = new Object(); + + static public final String paramdim = "d.2"; // parameter list dim + static public final String valuedim = "d.1"; + static public final String recorddim = "d.1"; + static public final String sequencedim = "d.zaubertrank-list"; + static public final String textdim = "d.zaubertrank-txt-alt"; + static public final String textrankdim = "d.2"; + static public final String textgrammardim = "d.1"; + static public final String grammardim = "d.zaubertrank-grammar-list"; + static public final String decdim = "d.zaubertrank-declarations"; + + /** A reference to an ExpNode param in a certain grammatical form. */ + static public final class DecRef { + int i; + GrammarNode g; + + public DecRef(int i, GrammarNode g) { this.i = i; this.g = g; } + } + + /** A reference to a certain ExpNode in a certain grammatical form. + * The difference to DecRef is that DecRef contains only a param number + * and a GrammarNode; additionally, an ExpNode is needed to read the + * actual text. + */ + static public final class ExpRef { + ExpNode e; + GrammarNode g; + + public ExpRef(ExpNode e, GrammarNode g) { this.e = e; this.g = g; } + public Object[] getText() { return e.getText(g); } + } + + static public final class TypeRef { + TypeNode t; + GrammarNode g; + + public TypeRef(TypeNode t, GrammarNode g) { this.t = t; this.g = g; } + public ZZCell[] getText() { return t.getText(g); } + } + + static public class Node { + public ZZCell c; + public boolean equals(Node other) { return c.equals(other.c); } + } + + /** A node declaring a grammatical way to utter a type. + * Example: English noun ("the person" // "which person?") + * Example: English statement ("the ball is red" // "what is true?") + * Example: English genitive ("the person's" // "whose?") + * etc. + */ + static public class GrammarNode extends Node { + public GrammarNode(ZZCell c) { + this.c = c.getRootclone(); + if(!this.c.h(grammardim).equals(this.c.getSpace().getHomeCell())) + throw new ZZError("Attempt to create GrammarNode from " + + "non-grammar cell "+this.c); + } + public GrammarNode(ZZSpace sp) { + this.c = sp.getHomeCell().N(grammardim, 1); + } + } + + static ZZCell[] readText(ZZCell c, GrammarNode g) { + ZZCell root = c.intersect(textdim, 1, g.c, "d.clone", 1); + p("Parse intersect "+c+" and "+g.c+" gives "+root); + if(root == null) return null; + return root.readRank(textrankdim, 1, false); + } + static void writeText(ZZCell c, GrammarNode g, ZZCell[] tc) { + ZZCell here = g.c.zzclone(); + c.insert(textdim, 1, here); + for(int i=0; i= params.length || params[i] == null) continue; + if(params[i].c.s(valuedim, -1) != null) + params[i].c.disconnect(valuedim, -1); + here.connect(valuedim, 1, params[i].c); + } + } + + /** Change a param in the structure. */ + public void setParam(int nr, ExpNode val) { + ZZCell var = c.getOrNewCell(paramdim, nr+1); + if(var.s(valuedim) != null) var.disconnect(valuedim, 1); + if(val.c.s(valuedim, -1) != null) val.c.disconnect(valuedim, -1); + var.connect(valuedim, 1, val.c); + } + + /** Read the text for a given GrammarNode. + * Returns an Object[] array where the Objects are ZZCells + * (which contain a piece of the text) ExpRef objects, or TypeRef + * objects. + *
      + * NOTE: there is no corresponding setText function because the + * text is deducted from params[] and dec.getText(). + */ + public Object[] getText(GrammarNode g) { + Object[] res = dec.getText(g); + if(res == null) return null; + for(int i=0; i= 0) { + if(toks[tf.tkNumber] == null) + toks[tf.tkNumber] = tf; + else + tf.setTkFirstPart(toks[tf.tkNumber]); + } + p("...is TokenFlob "+tf.tkNumber); + } + }}, false); + int child = 0; + for(Enumeration e = parents.elements(); e.hasMoreElements();) { + int parent = ((Integer)e.nextElement()).intValue(); + p("TokenGroup connect parent "+parent+" child "+child); + if(parent >= 0 && toks[child] != null && toks[parent] != null) + toks[child].setTkParent(toks[parent]); + child++; + } + } + +} + +// vim: set syntax=java : diff --git a/Modules/zaubertrank/old/Zaubertrank.java b/Modules/zaubertrank/old/Zaubertrank.java new file mode 100644 index 0000000..c0b749c --- /dev/null +++ b/Modules/zaubertrank/old/Zaubertrank.java @@ -0,0 +1,54 @@ +/* +Zaubertrank.java + * + * Copyright (c) 2000, Benjamin Fallenstein + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ +package org.gzigzag.module; +import org.gzigzag.*; +import java.awt.*; + +/** The module for the Zaubertrank applitude. + */ + +public class Zaubertrank { +public static final String rcsid = "$Id: Zaubertrank.java,v 1.1 2001/04/02 20:29:05 bfallenstein Exp $"; + public static boolean dbg = false; + static final void p(String s) { if(dbg) System.out.println(s); } + static final void pa(String s) { System.out.println(s); } + + static public ZZModule module = new ZZModule() { + public void action(String id, + ZZCell code, + ZZCell target, + ZZView view, ZZView cview, String key, Point pt, ZZScene xi) { + Flob[] flob = new Flob[1]; + if(pt != null) ((FlobSet)xi).getObjectAt(pt.x, pt.y, flob); + org.zaubertrank.Actions.action(view.getViewcell(), id, flob[0]); + } + public ZOb newZOb(String id) { + if(id.equals("Simple")) + return new org.zaubertrank.SimpleView(); + else if(id.equals("Parsed")) + return new org.zaubertrank.ParsedView(); + + return null; + } + }; +} diff --git a/Modules/zaubertrank/old/ZaubertrankPart.java b/Modules/zaubertrank/old/ZaubertrankPart.java new file mode 100644 index 0000000..efa5cdb --- /dev/null +++ b/Modules/zaubertrank/old/ZaubertrankPart.java @@ -0,0 +1,216 @@ +/* +ZaubertrankPart.java + * + * Copyright (c) 2000, Benjamin Fallenstein + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Benjamin Fallenstein + */ +package org.zaubertrank; +import org.gzigzag.*; +import java.util.*; + +/** A spacepart for the zaubertrank. + * Currently connects tokens in Reverse Polish Notation, and has cells whose + * content is the computed result of a Zaubertrank function. + */ + +public class ZaubertrankPart extends ZZROSpacePart { +public static final String rcsid = "$Id: ZaubertrankPart.java,v 1.1 2001/04/02 20:29:05 bfallenstein Exp $"; + public static boolean dbg = false; + private static final void p(String s) { if(dbg) System.out.println(s); } + private static final void pa(String s) { System.out.println(s); } + + public ZaubertrankPart(ZZSpace space, String id) { + super(space, id); + } + + public static class Result { + String codeID; + int nr; + public Result(String c, int nr) { codeID = c; this.nr = nr; } + } + + public Object parseIDPart(String idPart) { + if(idPart.substring(0, 7).equals("result-")) { + String rest = idPart.substring(7); + int idx = rest.indexOf("-"); + if(idx < 0 || idx+1 == rest.length()) return null; + String nr = rest.substring(0, idx); + String codeID = rest.substring(idx+1); + try { + return new Result(codeID, Integer.parseInt(nr)); + } catch(NumberFormatException e) { + return null; + } + } else + return null; + } + + public String generateIDPart(Object parsed) { + if(parsed instanceof Result) { + Result r = (Result)parsed; + return "result-" + r.nr + "-" + r.codeID; + } else + throw new ZZError("Not a ZaubertrankPart parsed ID object!"); + } + + public String getText(ZZCellHandle c) { + if(c.parsedID instanceof Result) { + Result r = (Result)c.parsedID; + ZZCell code = space.getCellByID(r.codeID); + pa("code "+code); + Object res; + try { + res = Evaluator.eval(code, new Data(c)); + } catch(Throwable t) { + // ZZLogger.exc(t); + return t.getMessage(); + } + return Data.s(res); + } else + return ""; + } + + public ZZDimension getDim(String name) { + if(name.equals("result")) return new ResultDimension(); + else if(name.equals("rpn")) return new ReversePolishNotation(); + return null; + } + + public class ResultDimension extends ZZRODimension { + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) { + Result r = null; + if(c.parsedID instanceof Result) r = (Result)c.parsedID; + + if(r == null) { + if(steps <= 0) return null; + r = new Result(c.getID(), steps); + return (ZZCellHandle)space.getCellByID(ZaubertrankPart.this, + generateID(r), r); + } else { + r = new Result(r.codeID, r.nr + steps); + if(r.nr < 0) return null; + else if(r.nr == 0) + return (ZZCellHandle)space.getCellByID(r.codeID); + else + return (ZZCellHandle)space.getCellByID(ZaubertrankPart.this, + generateID(r), r); + } + } + } + + public static ZZCell parent(ZZCell c, ZZObs o) throws SyntaxError { + c = c.s(Parser.valuedim, -1, o); + if(c == null) return null; + c = c.h(Parser.paramdim, -1, true, o); + if(c == null) throw new SyntaxError("Not connected to parent!"); + return c; + } + private static ZZCell sibling(ZZCell c, int dir, ZZObs o) + throws SyntaxError { + c = c.s(Parser.valuedim, -1, o); + if(c == null) return null; // XXX syntax error? has no siblings at all! + c = c.s(Parser.paramdim, dir, o); + if(dir < 0 && c == null) throw new SyntaxError("was parent already"); + else if(dir > 0 && c == null) return null; + // i.e., this was the last sibling + else if(dir < 0 && c.s(Parser.paramdim, -1, o) == null) return null; + // i.e., this was the first sibling + c = c.s(Parser.valuedim, 1, o); + if(c == null) throw new MissingTermError("Term's missing"); + return c; + } + public static ZZCell prevSibling(ZZCell c, ZZObs o) throws SyntaxError { + return sibling(c, -1, o); + } + public static ZZCell nextSibling(ZZCell c, ZZObs o) throws SyntaxError { + return sibling(c, 1, o); + } + public static ZZCell firstChild(ZZCell c, ZZObs o) throws SyntaxError { + c = c.s(Parser.paramdim, 1, o); + if(c == null) return null; + c = c.s(Parser.valuedim, 1, o); + if(c == null) throw new MissingTermError("Term's missing"); + return c; + } + public static ZZCell lastChild(ZZCell c, ZZObs o) throws SyntaxError { + c = c.h(Parser.paramdim, 1, true, o); + if(c == null) return null; + c = c.s(Parser.valuedim, 1, o); + if(c == null) throw new MissingTermError("Term's missing"); + return c; + } + + public static ZZCell firstDescendant(ZZCell c, ZZObs o) throws SyntaxError { + LoopDetector l = new LoopDetector(); + ZZCell d = c; + while(true) { + d = firstChild(c, o); + if(d == null) return c; + c = d; + l.detect(c); + } + } + + public static ZZCell rpnPrev(ZZCell c, ZZObs o) throws SyntaxError { + ZZCell d = lastChild(c, o); + if(d != null) return d; + LoopDetector l = new LoopDetector(); + while(true) { + d = prevSibling(c, o); + if(d != null) return d; + l.detect(c); + c = parent(c, o); + if(c == null) return null; + } + } + + public static ZZCell rpnNext(ZZCell c, ZZObs o) throws SyntaxError { + ZZCell d = nextSibling(c, o); + if(d == null) return parent(c, o); + else return firstDescendant(d, o); + } + + public class ReversePolishNotation extends ZZRODimension { + public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) { + // Sanity check: can this be a tree node? + if(c.s(Parser.valuedim, 1, o) != null) return null; + if(c.s(Parser.paramdim, -1, o) != null) return null; + // Until we have syntax error cells, let the errors be throws. + // try { + if(steps > 0) + for(int i=0; isteps; i--) + c = (ZZCellHandle)rpnPrev(c, o); + + // Another sanity check + if(c != null && (c.s(Parser.valuedim, 1, o) != null || + c.s(Parser.paramdim, -1, o) != null)) + throw new SyntaxError("Target not a tree node!"); + + return c; + // } catch(SyntaxError e) { + // ZZLogger.exc(e); + // return null; + // } + } + } +} + diff --git a/Modules/ztp/ZTPclient.java b/Modules/ztp/ZTPclient.java new file mode 100644 index 0000000..627b82f --- /dev/null +++ b/Modules/ztp/ZTPclient.java @@ -0,0 +1,71 @@ +/* +ZTPclient.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ +package org.gzigzag.module; +import org.gzigzag.*; +import org.gzigzag.ztp.*; +import org.gzigzag.ztp.client.*; +import java.awt.*; +import java.net.*; +import java.io.*; + +public class ZTPclient { + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + private static Action[] actions = { new Get(), new Put() }; + + public static ZZModule module = new ZZModule() { + public void action(String id, + ZZCell code, + ZZCell target, + ZZView view, ZZView cview, String key, + Point pt, ZZScene xi) { + for (int i = 0; i < actions.length; i++) { + if (id.toUpperCase().equals(actions[i].name().toUpperCase())) { + RemotePieceData rpd = new RemotePieceData(); + String err = rpd.readParams(target); + if (err != null && !err.equals("")) throw new ZZError(err); + Session ses = null; + if (actions[i].needSession()) { + try { + ses = new Session(rpd.serverFQDN, rpd.serverPort); + ses.login(rpd.userName, rpd.userPassword); + } catch (UnknownHostException e) { + throw new ZZError(""+e); + } catch (IOException e) { + throw new ZZError(""+e); + } + } + actions[i].action(rpd, ses); + try { + if (ses != null) ses.close(); + } catch (IOException e) { + throw new ZZError(""+e); + } + return; + } + } + throw new ZZError("unknown ZTPclient action"); + } + }; + +} diff --git a/Modules/ztp/ZTPserver.java b/Modules/ztp/ZTPserver.java new file mode 100644 index 0000000..d565e8e --- /dev/null +++ b/Modules/ztp/ZTPserver.java @@ -0,0 +1,82 @@ +/* +STPserver.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ +package org.gzigzag.module; +import org.gzigzag.ztp.*; +import org.gzigzag.ztp.server.*; +import org.gzigzag.*; +import java.net.*; +import java.io.*; +import java.util.*; + +/** This is a prototype STP server. Currently it supports a + * mock-STP/TCP in order to test the ideas in the WIP spec. */ +public class ZTPserver { + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log("[" + s + "]"); } + private static void pa(String s) { ZZLogger.log(s); } + + protected Listener listener; + + public ZTPserver(ZZSpace space, Integer inetport) { + this(space, inetport.intValue()); + } + + public ZTPserver(ZZSpace space, int inetport) { + p("ZTP creation start"); + ServerSocket sock; + try { + sock = new ServerSocket(inetport); + } catch (IOException e) { + throw new ZZError("Unable to bind to server port " + inetport + ": " + e); + } + listener = new Listener(space, sock); + listener.start(); + p("ZTP creation finished"); + } + + public void kill() throws InterruptedException { + listener.interrupt(); + listener.join(); + for (Enumeration e = Session.getActiveSessions(); e.hasMoreElements();) { + Session s = (Session) e.nextElement(); + s.interrupt(); + } + for (Enumeration e = Session.getActiveSessions(); e.hasMoreElements();) { + Session s = (Session) e.nextElement(); + s.join(); + } + } + + public static void main(String[] args) { + ZTPserver serv = new ZTPserver(new ZZDimSpace(), 5555); + try { + serv.listener.join(); + serv.kill(); + } catch (InterruptedException e) { + ZZLogger.exc(e); + } + SafeExit.exit(0); + } + +} + + + diff --git a/Modules/ztp/client/Action.java b/Modules/ztp/client/Action.java new file mode 100644 index 0000000..bf802f0 --- /dev/null +++ b/Modules/ztp/client/Action.java @@ -0,0 +1,29 @@ +/* +Action.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ + +package org.gzigzag.ztp.client; + +public interface Action { + String name(); + boolean needSession(); + void action(RemotePieceData rpd, Session ses); +} + diff --git a/Modules/ztp/client/Get.java b/Modules/ztp/client/Get.java new file mode 100644 index 0000000..9bc9095 --- /dev/null +++ b/Modules/ztp/client/Get.java @@ -0,0 +1,43 @@ +/* +Get.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ + +package org.gzigzag.ztp.client; +import org.gzigzag.ztp.*; +import org.gzigzag.*; +import java.io.*; +import java.util.*; + +public class Get implements Action { + + public String name() { return "GET"; } + public boolean needSession() { return true; } + public void action(RemotePieceData rpd, Session ses) { + + try { + ses.get(rpd.subspaceName, rpd.subspace); + } catch (IOException e) { + throw new ZZError("" + e); + } + + + + } +} diff --git a/Modules/ztp/client/Put.java b/Modules/ztp/client/Put.java new file mode 100644 index 0000000..dd522dd --- /dev/null +++ b/Modules/ztp/client/Put.java @@ -0,0 +1,43 @@ +/* +Put.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ + +package org.gzigzag.ztp.client; +import org.gzigzag.ztp.*; +import org.gzigzag.*; +import java.io.*; +import java.util.*; + +public class Put implements Action { + + public String name() { return "PUT"; } + public boolean needSession() { return true; } + public void action(RemotePieceData rpd, Session ses) { + if (rpd.subspace == null) throw new ZZError("there's nothing to put!"); + Subspace ss = new Subspace(rpd.subspace.s("d.ztp-subspace")); + try { + ses.put(rpd.subspaceName, ss.getCells(), ss.getSoftDims()); + } catch (IOException e) { + throw new ZZError("" + e); + } + } + +} + diff --git a/Modules/ztp/client/RemotePieceData.zob b/Modules/ztp/client/RemotePieceData.zob new file mode 100644 index 0000000..e632d93 --- /dev/null +++ b/Modules/ztp/client/RemotePieceData.zob @@ -0,0 +1,64 @@ +/* +RemotePieceData.zob + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ +package org.gzigzag.ztp.client; +import org.gzigzag.*; + +public class RemotePieceData implements ZOb { + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + STRUCTPARAMS { + + /** Server FQDN. */ + String serverFQDN = null; + + /** Server port. */ + int serverPort = -1; + + /** User name. */ + String userName = null; + + /** User password. */ + String userPassword = null; + + /** Subspace name. */ + String subspaceName = "ALL"; + + /** Subspace handle. */ + ZZCell subspace = null; + + } + + INITIALIZE { + if (serverFQDN == null) throw new ZZError("need server FQDN"); + if (serverPort == -1) throw new ZZError("need server port"); + if (userName == null) throw new ZZError("need a user name"); + if (subspaceName == null) throw new ZZError("need a subspace name"); + p("serverFQDN = " + serverFQDN); + p("serverPort = " + serverPort); + p("userName = " + userName); + p("userPassword = " + userPassword); + p("subspaceName = " + subspaceName); + p("subspace = " + subspace); + } + +} diff --git a/Modules/ztp/client/Response.java b/Modules/ztp/client/Response.java new file mode 100644 index 0000000..d2db63f --- /dev/null +++ b/Modules/ztp/client/Response.java @@ -0,0 +1,76 @@ +/* +Session.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ +package org.gzigzag.ztp.client; +import org.gzigzag.*; +import org.gzigzag.ztp.*; + +class Response { + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log("[" + s + "]"); } + private static void pa(String s) { ZZLogger.log(s); } + + public int major; + public int minor; + public int ident; + + // Major codes + public final static int positivePreliminary = 1; + public final static int positiveCompletion = 2; + public final static int positiveIntermediate = 3; + public final static int transientNegativeCompletion = 4; + public final static int permanentNegativeCompletion = 5; + + // Minor codes + public final static int syntaxCode = 0; + public final static int informationCode = 1; + public final static int connectionCode = 2; + public final static int authenticationCode = 3; + public final static int subspaceCode = 4; + + public String explanation; + + public Response(String line) { + try { + ZTPCommand.RV r; + + r = ZTPCommand.ASCII_number(line); + p("r = " + r); + if (r == null || r.rest.charAt(0) != '.') throw new SyntaxError("bad response line: " + line); + major = Integer.parseInt(r.token); + + r = ZTPCommand.ASCII_number(r.rest.substring(1)); + p("r = " + r); + if (r == null || r.rest.charAt(0) != '.') throw new SyntaxError("bad response line: " + line); + minor = Integer.parseInt(r.token); + + r = ZTPCommand.ASCII_number(r.rest.substring(1)); + p("r = " + r); + if (r == null || r.rest.charAt(0) != ' ') throw new SyntaxError("bad response line: " + line); + ident = Integer.parseInt(r.token); + + r = ZTPCommand.lwsp(r.rest); + explanation = r.rest; + } catch (NumberFormatException e) { + throw new ZZError("" + e); + } + } + +} diff --git a/Modules/ztp/client/Session.java b/Modules/ztp/client/Session.java new file mode 100644 index 0000000..e83cf53 --- /dev/null +++ b/Modules/ztp/client/Session.java @@ -0,0 +1,165 @@ +/* +Session.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ +package org.gzigzag.ztp.client; +import org.gzigzag.*; +import org.gzigzag.ztp.*; +import java.net.*; +import java.io.*; +import java.util.*; + +public class Session implements SafeExit.Cleanupable { + + private String server; + private Socket sock; + private int port; + private LineBufferedIO io; + + public Session(String server, int port) throws UnknownHostException { + this.server = server; + this.port = port; + + try { + sock = new Socket(server, port); + io = new LineBufferedIO(sock.getInputStream(), sock.getOutputStream()); + + String line = io.readline(); + Response resp = new Response(line); + if (resp.major != Response.positiveCompletion) { + sock.close(); + throw new ZZError("no response from server"); + } + } catch (IOException e) { + throw new ZZError("" + e); + } + SafeExit.registerObject(this); + } + + /** Login to server. If passwd is null, attempt + * preauthentication. */ + public void login(String username, String passwd) throws IOException { + if (passwd == null) { + io.writeln("AUTH/PRE " + ZTPCommand.encode(username)); + } else { + io.writeln("AUTH/PASS " + ZTPCommand.encode(username) + + " " + ZTPCommand.encode(passwd)); + } + Response resp = new Response(io.readline()); + if (resp.major != Response.positiveCompletion) { + throw new ZZError("Unable to login: " + resp.explanation); + } + } + + public void close() throws IOException { + io.writeln("QUIT"); + io.readline(); + sock.close(); + SafeExit.unregisterObject(this); + } + + public void cleanup() throws Throwable { + io.writeln("A"); + io.readline(); + io.writeln("QUIT"); + io.readline(); + sock.close(); + } + + public void put(String subspace, Enumeration cells, String[] sdims) throws IOException { + io.writeln("PUT " + ZTPCommand.encode(subspace)); + Response res = new Response(io.readline()); + if (res.major != Response.positiveIntermediate) { + throw new ZZError("unable to put: " + res.explanation); + } + SubspaceDump.dump(io, cells, sdims, ""); + res = new Response(io.readline()); + if (res.major != Response.positiveCompletion) { + throw new ZZError("failed to put: " + res.explanation); + } + } + + public void get(String subspace, ZZCell basecell) throws IOException { + io.writeln("GET " + ZTPCommand.encode(subspace)); + Response res = new Response(io.readline()); + if (res.major != Response.positiveIntermediate) { + throw new ZZError("unable to get: " + res.explanation); + } + + SubspaceDump sd; + try { + sd = new SubspaceDump(io); + } finally { + res = new Response(io.readline()); + if (res.major != Response.positiveCompletion) { + throw new ZZError("failed to get: " + res.explanation); + } + } + + // Delete the old subspace + if (basecell != null && basecell.s("d.ztp-subspace") != null) { + Subspace ss = new Subspace(basecell.s("d.ztp-subspace")); + String[] sdims = ss.getSoftDims(); + for (Enumeration e = ss.getCells(); e.hasMoreElements();) { + ZZCell c = (ZZCell)e.nextElement(); + + for (int i = 0; i < sdims.length; i++) { + if (c.s(sdims[i], 1) != null) c.disconnect(sdims[i], 1); + if (c.s(sdims[i], -1) != null) c.disconnect(sdims[i], -1); + } + if (c.s("d.ztp-subspace", 1) != null) c.disconnect("d.ztp-subspace", 1); + if (c.s("d.ztp-subspace", -1) != null) c.disconnect("d.ztp-subspace", -1); + } + } + + ZZDimSpace space = (ZZDimSpace)basecell.getSpace(); + + // Create the new subspace + { + ZZCell oc = basecell; + for (Enumeration e = sd.cellids.keys(); e.hasMoreElements();) { + String s = (String)e.nextElement(); + ZZCell c = space.getCellByID(s); + oc.connect("d.ztp-subspace", 1, c); + oc = c; + } + } + + for (Enumeration e = sd.content.keys(); e.hasMoreElements();) { + String s = (String)e.nextElement(); + ZZCell c = space.getCellByID(s); + c.setText((String)sd.content.get(s)); + } + for (Enumeration e = sd.dims.keys(); e.hasMoreElements();) { + String dimname = (String)e.nextElement(); + Hashtable dim = (Hashtable)sd.dims.get(dimname); + space.d(dimname); + for (Enumeration f = dim.keys(); f.hasMoreElements();) { + String s1 = (String)f.nextElement(); + String s2 = (String)dim.get(s1); + ZZCell c1 = space.getCellByID(s1); + ZZCell c2 = space.getCellByID(s2); + c1.connect(dimname, c2); + } + } + + +} + +} diff --git a/Modules/ztp/client/Subspace.java b/Modules/ztp/client/Subspace.java new file mode 100644 index 0000000..23a13d9 --- /dev/null +++ b/Modules/ztp/client/Subspace.java @@ -0,0 +1,76 @@ +/* +Put.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ + +package org.gzigzag.ztp.client; +import org.gzigzag.ztp.*; +import org.gzigzag.*; +import java.util.*; + +class Subspace { + + private String[] sdims; + private Hashtable cells = new Hashtable(); + + public String[] getSoftDims() { return sdims; } + public Enumeration getCells() { return cells.keys(); } + + public Subspace(ZZCell base) { + String[] origdims = base.getSpace().dims(); + Vector dimv = new Vector(); + + for (int i = 0; i < origdims.length; i++) { + if (origdims[i].equals("d.ztp-subspace") + || origdims[i].equals("d.cellcreation")) { + continue; + } + dimv.addElement(origdims[i]); + } + + sdims = new String[dimv.size()]; + for (int i = 0; i < sdims.length; i++) { + sdims[i] = (String)dimv.elementAt(i); + } + + if (base == null) return; + + Stack stack = new Stack(); + stack.push(base); + Hashtable seen = new Hashtable(); + while (!stack.empty()) { + ZZCell c = (ZZCell)stack.pop(); + + for (int i = 0; i < sdims.length; i++) { + ZZCell d = c.s(sdims[i], 1); + if (d != null && !seen.containsKey(d)) { + stack.push(d); + seen.put(d, d); + } + d = c.s(sdims[i], -1); + if (d != null && !seen.containsKey(d)) { + stack.push(d); + seen.put(d, d); + } + } + cells.put(c, c); + } + } + +} diff --git a/Modules/ztp/common/LineBufferedIO.java b/Modules/ztp/common/LineBufferedIO.java new file mode 100644 index 0000000..95d76de --- /dev/null +++ b/Modules/ztp/common/LineBufferedIO.java @@ -0,0 +1,111 @@ +/* +LineBufferedIO.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ +package org.gzigzag.ztp; +import org.gzigzag.module.*; +import org.gzigzag.*; +import java.io.*; + +/** Line-buffered UTF-8 I/O. */ +public class LineBufferedIO { + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log(s); } + private static void pa(String s) { ZZLogger.log(s); } + + InputStream in; + OutputStream out; + String buffer = new String(); + public LineBufferedIO(InputStream in, OutputStream out) { + this.in = in; + this.out = out; + } + + public synchronized void flush() throws IOException { + for (int i = 0; i < buffer.length(); i++) { + UTF8Char ch = new UTF8Char(buffer.charAt(i)); + out.write(ch.b, 0, ch.b.length); + } + out.flush(); + if (buffer.charAt(buffer.length()-1) == '\n') { + p("==> " + buffer.substring(0, buffer.length()-1)); + } else { + p("==> " + buffer); + } + buffer = ""; + } + public synchronized void write(String s) throws IOException { + for (int i = 0; i < s.length(); i++) { + buffer += s.charAt(i); + if (s.charAt(i) == '\n') flush(); + } + } + public synchronized void writeln(String s) throws IOException { + write(s + "\n"); + } + + private boolean ineof = false; + + public boolean isEOF() { return ineof; } + + /** Reads one UTF-8 character. If EOF is reached, the EOF + * flag is set and the returned value will be undefined. */ + public char getc() throws IOException { + if (ineof) return '\n'; + int o = in.read(); + if (o == -1) { + ineof = true; + return '\n'; + } + int len = UTF8Char.UTF8Len((byte) o); + byte[] bs = new byte[len]; + bs[0] = (byte)o; + for (int i = 1; i < len; i++) { + o = in.read(); + if (o == -1) { + ineof = true; + throw new IOException("file ended before char was complete"); + } + bs[i] = (byte)o; + } + return (new UTF8Char(bs)).c; + } + + /* Reads until the end of line (including the EOL character), + * or to EOF. */ + public String readline() throws IOException { + String rv = new String(); + + char c; + do { + c = getc(); + if (isEOF()) break; + rv += c; + } while (c != '\n'); + + if (rv.charAt(rv.length()-1) == '\n') { + p("<== " + rv.substring(0, rv.length()-1)); + } else { + p("<== " + rv); + } + return rv; + } + +} + diff --git a/Modules/ztp/common/SubspaceDump.java b/Modules/ztp/common/SubspaceDump.java new file mode 100644 index 0000000..c41c599 --- /dev/null +++ b/Modules/ztp/common/SubspaceDump.java @@ -0,0 +1,134 @@ +/* +SubspaceDump.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ +package org.gzigzag.ztp; +import org.gzigzag.*; +import java.io.*; +import java.util.*; + +public class SubspaceDump { + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log("[" + s + "]"); } + private static void pa(String s) { ZZLogger.log(s); } + + public static class AbortedException extends ZZError { + public AbortedException(String s) { + super(s); + } + } + + /** Cell content. This hashtable maps cell IDs into cell + * content. */ + public Hashtable content = new Hashtable(); + + /* Dimensions. This hashtable maps dimension names into + * hashtables that map cells to cells (key connected to datum + * posward along the dimension). */ + public Hashtable dims = new Hashtable(); + + + /* Cell IDs. This hashtable contains an entry for every cell that + * has a content entry or a connection entry. */ + public Hashtable cellids = new Hashtable(); + + public SubspaceDump(LineBufferedIO io) throws IOException { + boolean ok = true; + while (!io.isEOF()) { + try { + String line = io.readline(); + ZTPCommand cmd = new ZTPCommand(line); + + if (cmd.name.toUpperCase().equals("C")) { + if (cmd.args.length != 2) { + p("C args len = " + cmd.args.length); + ok = false; + continue; + } + Object o = content.get(cmd.args[0]); + String s = ""; + if (o != null) s = (String)o; + s += cmd.args[1]; + content.put(cmd.args[0], s); + cellids.put(cmd.args[0], cmd.args[0]); + } else if (cmd.name.toUpperCase().equals("R")) { + if (cmd.args.length < 3) { + p("R args len = " + cmd.args.length); + ok = false; + continue; + } + Hashtable dim = (Hashtable)dims.get(cmd.args[0]); + if (dim == null) { + dim = new Hashtable(); + dims.put(cmd.args[0], dim); + } + for (int i = 1; ok && i + 1 < cmd.args.length; i++) { + Object o = dim.get(cmd.args[i]); + if (o != null && !((String)o).equals(cmd.args[i+1])) { + p("existing connection (" + cmd.args[i] + ", " + (String)o + ") will be broken"+ + " by new connection (" + cmd.args[i] + ", " + cmd.args[i+1]); + ok = false; + continue; + } + dim.put(cmd.args[i], cmd.args[i+1]); + cellids.put(cmd.args[i], cmd.args[i]); + cellids.put(cmd.args[i+1], cmd.args[i+1]); + } + } else if (cmd.name.toUpperCase().equals("F")) { + break; + } else if (cmd.name.toUpperCase().equals("A")) { + throw new AbortedException("Subspace data transfer aborted"); + } else { + p("unknown command"); + ok = false; + continue; + } + } catch (SyntaxError e) { + ZZLogger.exc(e); + ok = false; + } + } + if (!ok) throw new SyntaxError("Syntax error is subspace data"); + } + + public static void dump(LineBufferedIO io, Enumeration cells, + String[] sdims, String prefix) throws IOException { + + for (; cells.hasMoreElements();) { + ZZCell c = (ZZCell)cells.nextElement(); + String cid = c.getGlobalID().substring(prefix.length()); + p("cell " + c); + io.writeln("C " + ZTPCommand.encode(cid) + " " + ZTPCommand.encode(c.getText())); + // Find connections from this cell + for (int i = 0; i < sdims.length; i++) { + String dim = sdims[i]; + p("dim " + dim); + ZZCell d = c.s(prefix + dim); + if (d != null) { + if (!d.getGlobalID().substring(0, prefix.length()).equals(prefix)) continue; + String did = d.getGlobalID().substring(prefix.length()); + io.writeln("R " + ZTPCommand.encode(dim) + + " " + ZTPCommand.encode(cid) + + " " + ZTPCommand.encode(did)); + } + } + } + io.writeln("F"); + } +} diff --git a/Modules/ztp/server/GetMessage.java b/Modules/ztp/server/GetMessage.java new file mode 100644 index 0000000..ed940b6 --- /dev/null +++ b/Modules/ztp/server/GetMessage.java @@ -0,0 +1,112 @@ +/* +PutMessage.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ +package org.gzigzag.ztp.server; +import org.gzigzag.*; +import org.gzigzag.ztp.*; +import java.io.*; +import java.util.*; + +class GetMessage implements Session.Message { + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log("[" + s + "]"); } + private static void pa(String s) { ZZLogger.log(s); } + + static String prefix = PutMessage.prefix; + + public String name() { return "GET"; } + public String help() { return "Gets a subspace from the server"; } + public int prereqs() { return Session.FL_AUTH; } + + public void invoke(Session sess, String[] args) throws IOException { + LineBufferedIO io = sess.getIO(); + ZZSpace space = sess.space; + if (args.length != 1) { + io.writeln("5.0.1 Syntax: GET "); + return; + } + + if (!args[0].equals("ALL")) { + io.writeln("5.4.1 No such subspace"); + return; + } + + io.writeln("3.4.1 Proceeding with subspace data ..."); + + synchronized (space) { + // Find all relevant dimensions + String[] dims; + { + Vector dimv = new Vector(); + for (ZZCell c = space.getHomeCell().s("d.masterdim", 1); c != null; + c = c.s("d.masterdim", 1)) { + String name = c.getText(); + if (name.length() >= prefix.length() + && name.substring(0, prefix.length()).equals(prefix)) { + dimv.addElement(name.substring(prefix.length())); + } + } + dims = new String[dimv.size()]; + for (int i = 0; i < dims.length; i++) { + dims[i] = (String)dimv.elementAt(i); + } + } + + class Enum implements Enumeration { + Enumeration e; + Object cur; + private void Cur() { + cur = null; + while (e.hasMoreElements()) { + cur = e.nextElement(); + ZZCell c = (ZZCell)cur; + p("considering " + c); + if (c.getID().substring(0, prefix.length()).equals(prefix)) + p("OK"); + break; + } + } + public Enum(Enumeration e) { + this.e = e; + Cur(); + } + public boolean hasMoreElements() { + return cur != null; + } + public Object nextElement() { + Object rv = cur; + if (rv == null) throw new NoSuchElementException(); + Cur(); + p("nextElement = " + rv); + return rv; + } + }; + + SubspaceDump.dump(io, + new Enum(space.getHomeCell().s("d.ztpspace").enumRank("d.ztpspace")), + dims, prefix); + + } + + io.writeln("2.4.1 Subspace successfully got"); + + } + +} diff --git a/Modules/ztp/server/Listener.java b/Modules/ztp/server/Listener.java new file mode 100644 index 0000000..51ef450 --- /dev/null +++ b/Modules/ztp/server/Listener.java @@ -0,0 +1,55 @@ +/* +Listener.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ +package org.gzigzag.ztp.server; +import org.gzigzag.*; +import org.gzigzag.ztp.*; +import java.net.*; +import java.io.*; + +public class Listener extends Thread { + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log("[" + s + "]"); } + private static void pa(String s) { ZZLogger.log(s); } + + private ZZSpace space; + private ServerSocket lsock; + public Listener(ZZSpace space, ServerSocket lsock) { + this.space = space; + this.lsock = lsock; + } + public void run() { + pa("Listener starts"); + while (!isInterrupted()) { + try { + p("waiting for connections"); + Socket csock = lsock.accept(); + p("connection request received"); + Session sess = new Session(space, csock); + sess.start(); + } catch (IOException e) { + ZZLogger.exc(e); + } + + } + pa("Listener stops"); + } +} + diff --git a/Modules/ztp/server/PutMessage.java b/Modules/ztp/server/PutMessage.java new file mode 100644 index 0000000..f6a147c --- /dev/null +++ b/Modules/ztp/server/PutMessage.java @@ -0,0 +1,117 @@ +/* +PutMessage.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ +package org.gzigzag.ztp.server; +import org.gzigzag.*; +import org.gzigzag.ztp.*; +import java.io.*; +import java.util.*; + +class PutMessage implements Session.Message { + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log("[" + s + "]"); } + private static void pa(String s) { ZZLogger.log(s); } + + static String prefix = "ztpspace!"; + + public String name() { return "PUT"; } + public String help() { return "Puts a subspace to the server"; } + public int prereqs() { return Session.FL_AUTH; } + + public void invoke(Session sess, String[] args) throws IOException { + LineBufferedIO io = sess.getIO(); + ZZSpace space = sess.space; + if (args.length != 1) { + io.writeln("5.0.1 Syntax: PUT "); + return; + } + + if (!args[0].equals("ALL")) { + io.writeln("5.4.1 No such subspace"); + return; + } + + io.writeln("3.4.0 Please proceed with subspace data, end with 'F'"); + + + SubspaceDump sd; + try { + sd = new SubspaceDump(io); + } catch (SubspaceDump.AbortedException e) { + io.writeln("5.4.0 " + e.getMessage()); + return; + } catch (SyntaxError e) { + io.writeln("5.0.1 " + e.getMessage()); + return; + } + + // Verify that the cells all have a good ID. + for (Enumeration e = sd.cellids.keys(); e.hasMoreElements();) { + String s = (String)e.nextElement(); + if (s.indexOf("@") == -1) { + io.writeln("5.4.2 Cannot put cells lacking a space ID"); + return; + } + } + + synchronized (space) { + // Delete old subspace + for (ZZCell c = space.getHomeCell().s("d.ztpspace", 1); c != null; ) { + ZZCell s = c.s("d.ztpspace", 1); + if (c.getID().substring(0, prefix.length()).equals(prefix)) { + c.delete(); + } + c = s; + } + + // Create the new subspace + { + ZZCell oc = space.getHomeCell(); + for (Enumeration e = sd.cellids.keys(); e.hasMoreElements();) { + String s = (String)e.nextElement(); + ZZCell c = space.getCellByID(prefix + s); + oc.connect("d.ztpspace", 1, c); + oc = c; + } + } + for (Enumeration e = sd.content.keys(); e.hasMoreElements();) { + String s = (String)e.nextElement(); + ZZCell c = space.getCellByID(prefix + s); + c.setText((String)sd.content.get(s)); + } + for (Enumeration e = sd.dims.keys(); e.hasMoreElements();) { + String dimname = (String)e.nextElement(); + Hashtable dim = (Hashtable)sd.dims.get(dimname); + ((ZZDimSpace)space).d(dimname); + for (Enumeration f = dim.keys(); f.hasMoreElements();) { + String s1 = (String)f.nextElement(); + String s2 = (String)dim.get(s1); + ZZCell c1 = space.getCellByID(prefix + s1); + ZZCell c2 = space.getCellByID(prefix + s2); + c1.connect(prefix + dimname, c2); + } + } + space.commit(); + } + io.writeln("2.4.0 Subspace successfully put"); + } + + +} diff --git a/Modules/ztp/server/Session.java b/Modules/ztp/server/Session.java new file mode 100644 index 0000000..63113c4 --- /dev/null +++ b/Modules/ztp/server/Session.java @@ -0,0 +1,227 @@ +/* +Session.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ +package org.gzigzag.ztp.server; +import org.gzigzag.*; +import org.gzigzag.ztp.*; +import java.net.*; +import java.io.*; +import java.util.*; + +public class Session extends Thread { + public static boolean dbg = false; + private static void p(String s) { if(dbg) ZZLogger.log("[" + s + "]"); } + private static void pa(String s) { ZZLogger.log(s); } + + public ZZSpace space; + private Socket socket = null; + + interface Message { + String name(); + String help(); + int prereqs(); + void invoke(Session sess, String[] args) throws IOException; + } + + private LineBufferedIO io; + + private boolean proper_close = false; + + public LineBufferedIO getIO() { return io; } + + private UserManager userManager; + + public UserManager getUserManager() { return userManager; } + + // prereq constants (orred) + static final int FL_AUTH = 1; + static final int FL_SAP = 2; + + private int reqstatus; + + public String user; + + public void setFlag(int flag) { reqstatus |= flag; } + public void clearFlag(int flag) { reqstatus &= ~flag; } + + private void login(UserRecord ur) throws IOException { + try { + if (ur.sap) { + setFlag(FL_SAP); + } else { + clearFlag(FL_SAP); + } + user = ur.username; + setFlag(FL_AUTH); + io.writeln("2.3.0 OK"); + if (socket != null) { + pa("connection from " + socket.getInetAddress().getHostName() + + " authenticated as " + user); + } + } catch (Throwable e) { + clearFlag(FL_AUTH); + ZZLogger.exc(e); + io.writeln("4.3.0 Problem authenticating user"); + } + } + + Message[] messages = { + new Message() { + public String name() { return "QUIT"; } + public String help() { return "Quit the session"; } + public int prereqs() { return 0; } + public void invoke(Session ses, String[] args) throws IOException { + clearFlag(FL_AUTH); + ses.interrupt(); + ses.proper_close = true; + ses.io.writeln("2.2.1 Be seeing you"); + } + }, + new Message() { + public String name() { return "AUTH/PRE"; } + public String help() { return "Request preauthentication"; } + public int prereqs() { return 0; } + public void invoke(Session ses, String[] args) throws IOException { + LineBufferedIO io = ses.getIO(); + if (args.length != 1) { + io.writeln("5.0.1 Syntax: AUTH/PRE "); + return; + } + UserRecord ur = ses.getUserManager().access(args[0]); + if (ur == null || !ur.auth_pre) { + io.writeln("5.3.0 Access denied"); + return; + } + if (ur.susp) { + io.writeln("5.3.1 User disabled"); + return; + } + ses.login(ur); + } + }, + new Message() { + public String name() { return "AUTH/PASS"; } + public String help() { return "Request password authentication"; } + public int prereqs() { return 0; } + public void invoke(Session ses, String[] args) throws IOException { + LineBufferedIO io = ses.getIO(); + if (args.length != 2) { + io.writeln("5.0.1 Syntax: AUTH/PASS "); + return; + } + UserRecord ur = ses.getUserManager().access(args[0]); + if (ur == null || !ur.auth_pass || !ur.password.equals(args[1])) { + io.writeln("5.3.0 Access denied"); + return; + } + if (ur.susp) { + io.writeln("5.3.1 User disabled"); + return; + } + ses.login(ur); + } + }, + new PutMessage(), + new GetMessage() + }; + + private static Hashtable sessions = new Hashtable(); + + + public static Enumeration getActiveSessions() { + synchronized (sessions) { + return sessions.keys(); + } + } + + public Session(ZZSpace space, Socket sock) throws IOException { + this(space, sock.getInputStream(), sock.getOutputStream()); + socket = sock; + } + + public Session(ZZSpace space, InputStream in, OutputStream out) throws IOException { + this.space = space; + io = new LineBufferedIO(in, out); + socket = null; + } + + public void run() { + try { + p("session start"); + if (socket != null) { + pa("accepting connection from " + socket.getInetAddress().getHostName()); + } + userManager = UserManager.create(space); + synchronized (sessions) { + sessions.put(this, this); + } + try { + io.writeln("2.2.0 Hello there!"); + } catch (IOException e) { + ZZLogger.exc(e); + } + while (!io.isEOF() && !isInterrupted()) { + try { + try { + String line = io.readline(); + p("read " + line); + ZTPCommand c = new ZTPCommand(line); + p("" + c); + Message m = null; + for (int i = 0; i < messages.length; i++) { + if (messages[i].name().toUpperCase().equals(c.name.toUpperCase())) { + m = messages[i]; + } + } + if (m == null) { + io.writeln("5.0.1 What?"); + } else { + if (((m.prereqs() & reqstatus) ^ m.prereqs()) == 0) { + m.invoke(this, c.args); + } else { + io.writeln("5.0.2 Permission denied"); + } + } + } catch (SyntaxError e) { + io.writeln("5.0.1 " + e.getMessage()); + } + } catch (IOException e) { + ZZLogger.exc(e); + } + } + } finally { + synchronized (sessions) { + try { + if (!proper_close) io.writeln("4.2.1 Aborting"); + socket.close(); + } catch (IOException e) { + ZZLogger.exc(e); + } + sessions.remove(this); + } + userManager.close(); + } + if (socket != null) { + pa("closing connection from " + socket.getInetAddress().getHostName()); + } + p("session end"); + } +} + diff --git a/Modules/ztp/server/UserManager.java b/Modules/ztp/server/UserManager.java new file mode 100644 index 0000000..ba025a0 --- /dev/null +++ b/Modules/ztp/server/UserManager.java @@ -0,0 +1,139 @@ +/* +UserManager.java + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ +package org.gzigzag.ztp.server; +import org.gzigzag.*; +import org.gzigzag.ztp.*; +import java.util.*; + +/** User manager for ZTP server. It enforces single-threaded access + * to the user table in the space. */ +class UserManager { + public static boolean dbg = true; + private static void p(String s) { if(dbg) ZZLogger.log("[" + s + "]"); } + private static void pa(String s) { ZZLogger.log(s); } + + private static Hashtable managers = new Hashtable(); + + private int refcount; + + private ZZSpace space; + + private boolean live = false; + + private void assertLiving() { + if (!live) throw new ZZError("UserManager closed"); + } + + /* + private ZZCell userlist; + */ + + private UserManager(ZZSpace space) { + synchronized (managers) { + this.space = space; + if (managers.containsKey(space)) { + throw new ZZError("there already is a UserManager for that space"); + } + managers.put(space, this); + live = true; + } + + refcount = 0; + + // NOT NOW + //// we find the user list here for convenience + //ZZCell home = space.getHomeCell(); + //userlist = home.findText("d.system", 1, "ZTPUserList"); + //if (userlist == null) { + ///* userlist = home.N("d.system", 1); + //userlist.setText("ZTPUserList");*/ + //throw new ZZError("no user list in space!"); + //} + } + + + public static UserManager create(ZZSpace space) { + UserManager rv; + synchronized (managers) { + Object o = managers.get(space); + if (o == null) { + rv = new UserManager(space); + } else { + rv = (UserManager)o; + } + } + ++rv.refcount; + return rv; + } + + public void close() { + if (--refcount < 1) { + synchronized (managers) { + live = false; + managers.remove(space); + } + } + } + + public synchronized UserRecord access(String username) { + assertLiving(); + + UserRecord rv = new UserRecord(); + + rv.username = "adm"; + rv.password = "mda"; + rv.susp = false; + rv.chpass = false; + rv.sap = true; + rv.auth_pre = true; + rv.auth_pass = true; + + return username.equals(rv.username) ? rv : null; + } + + public interface RecordHandler { + void doit(UserRecord ur); + } + + public synchronized void access_atomic(String username, RecordHandler rh) { + UserRecord ur = access(username); + rh.doit(ur); + } + + public synchronized void replace(UserRecord ur) { + throw new ZZError("user record replace not implemented at this time"); + } + + public synchronized void replace_atomic(String username, RecordHandler rh) { + UserRecord ur = access(username); + rh.doit(ur); + replace(ur); + } + + public synchronized void delete(String uname) { + throw new ZZError("user record deletion not implemented at this time"); + } + + public synchronized void insert(UserRecord ur) { + throw new ZZError("user record insertion not implemented at this time"); + } + +} diff --git a/Modules/ztp/server/UserRecord.zob b/Modules/ztp/server/UserRecord.zob new file mode 100644 index 0000000..1a91549 --- /dev/null +++ b/Modules/ztp/server/UserRecord.zob @@ -0,0 +1,56 @@ +/* +UserRecord.zob + * + * You may use and distribute under the terms of either the GNU Lesser + * General Public License, either version 2 of the license or, + * at your choice, any later version. Alternatively, you may use and + * distribute under the terms of the XPL. + * + * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of + * the licenses. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README + * file for more details. + * + */ +/* + * Written by Antti-Juhani Kaijanaho + */ +package org.gzigzag.ztp.server; +import org.gzigzag.*; +import org.gzigzag.ztp.*; +import java.util.*; + +/** User manager for ZTP server. It enforces single-threaded access + * to the user table in the space. */ + +public class UserRecord implements ZOb { + + STRUCTPARAMS { + /** The username. */ + String username; + + /** The password for AUTH/PASS. */ + String password; + + /** Is the user suspended? */ + boolean susp; + + /** Is the user allowed to change her password? */ + boolean chpass; + + /** Does the user have Space Administrator Privileges? */ + boolean sap; + + /** May the user use preauthentication? */ + boolean auth_pre; + + /** May the user use password authentication? */ + boolean auth_pass; + } + + +} + diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..b5172bb --- /dev/null +++ b/NEWS @@ -0,0 +1,207 @@ +=============================== -*- Text -*- +User-visible changes in GZigZag +=============================== + + +The 0.6 Series +============== + + +0.6.3 (2002-03-07) +----- + +The following features have been added: +- A PUICOPYRANK action (bound by default to Ctrl-Alt-C) has + been added. It copies the cell contents along the y-dimension + rank to the PUI clipboard, inserting newlines between cells. + +The following features have been improved: +- The Row and Column views have been fixed to show the dimensions + always. Previously, in some common cases the dimensions were hidden + under the cells shown by the views. +- The Ball-and-Strick cell view now does line breaking. +- The Prez (presentation) module has been changed so that its view + now uses the dimension settings (x, y and z axis) instead of fixed + dimension names (d.1, d.2 and d.3), and to work with circular ranks. + +The following bugs have been fixed: +- The mindmapping module is now included in the official jars. +- Documentation/index.html had a HTML error; this is now fixed. + + +0.6.2 (2002-02-16) +----- + +A bug that made GZigZag not run on Java 1.2 and above has been fixed. +GZZ does not compile correctly with IBM's jikes 1.15 now; Sun's javac +works (you may also want to try jikes 1.14). + +The following new features have been added: +- Asko Soukka's MindSundew and MindSun views, providing a mindmapping-like + interface to the ZZ structure. They works together nicely with the common + key bindings. You can find them under AllViews after creating a new space, + or re-generating the system part of an old space using the '-new' + command line option. + + Note that these views are only available in versions of GZigZag that + include this module. + +The following features have been improved: +- The row/column views show like they did previous to version 0.3.0, again. + + + +0.6.1 (2001-08-17) +----- + +Flowing Clang has been brought back to life (it wasn't included in some +previous releases due to lack of interest). + +The following new features have been added: + - The EDITHACK action (found on the actions list), which allows opening + a window for text editing. Java's AWT classes are used, which have + support for mouse selection, the PUI clipboard, and entering Japanese + characters, among other things. (For internal reasons, the text window + is not automatically re-opened when the client starts again; the + EDITHACK action has to be executed again.) + + +0.6.0 +----- + +Support for the old "PersistentDimSpace" file format has been removed. + +The following new features have been added: + - A preliminary ZigZag Transfer Protocol (ZTP) implementation + - space dump and slurp functionality (for disaster recovery + and format conversions) + - accessing past versions of the space + - a panic button + - demo module: associative writing tool - a multilayered concept map + - a -help option to the command line + - a multiline cell view + - support for cell-view specific bindings: when a cell view is associated + with a cell in the structure (per d.cellview connection), in the cell + edit mode bindings associated with that cellview can be used (so that + content which isn't plain text can be edited easily) + +The following features have been improved: + - the user's guide + - the multimedia module + - the virtual community module + - sound support + - view infrastructure + +The following notable bug fixes have been made: + - the new UTF-8-based string scroll format actually works now + - umlauts aren't doubled (don't appear twice when entered only once) + + +The 0.5 Series +============== + +The following new features have been added: + - Notemap Star view, a view showing a map of cells connected in a network + structure + - Parallel (Split) Nile View, a view which places two Nile streams next to + each other and shows transclusions with beams + - A preliminary multimedia module + - A prototype virtual community module + + +The 0.4 Series +============== + +The following new features have been added: + - A new UTF-8-based string scroll format (used in new scrolls; + existing scrolls continue to use the old format) + - a prototype NILE (NILE Is A Literary Editor) + - Zaubertrank + - F1 is help + + +The 0.3 Series +============== + + +Release 0.3.0 (2000-11-21) +------------- + +The following new features have been added: + - a new user's guide (work in progress, but already very useful) + - Heraclitus Clang + - XOR mode cursors + - Text find + - Flowing Clang + - Internationalization + - Calendar demo + - IC View + - Cursor View + - Rewritten XML import / export + - Wordnet applitude + - ball&stick model + - split vanishing into vanishing and rowcol + - nicer geometry for rowcol + - new, interesting parameters for vanishing: revper, halign + *** REQUIRES RECREATION OF SYSTEM PART *** + - ZOb's names are now class names. + +The following internal changes have been made + - huge API change to shorter core function names in ZZCell + + +The 0.2 Series +============== + +The 0.2 series was never released. + + +The 0.1 Series +============== + + +Release 0.1.5 (2000-11-02) +------------- + +This release contains the following bug fixes: + - Undoing a cell creation no longer throws an exception + - Compass and Presentation Views are now in AllViews list + + +Release 0.1.4 (2000-10-25) +------------- + +This release contains the following user-visible changes: + - The keys Ctrl-A, Ctrl-E, Home, End and Enter now work in edit + mode + - There is a new -recrmdim option, which will recreate a damaged + master dimension list (useful in converting old spaces) + - XML export and import bug fixes, including a new -xmlencoding + option for specifying the XML character encoding to use at export + time. + + +Release 0.1.3 (2000-10-09) +------------- + +This release contains the following bug fixes: + - The Mbox module works again + - Edit view background is now all-white + + +Release 0.1.2 (2000-09-28) +------------- + +This release fixes a packaging goofup in 0.1.1. + + +Release 0.1.1 (2000-09-28) +------------- + +This release contains no user-visible changes. + + +Release 0.1.0 (2000-09-26) +------------- + +This is the first public release. diff --git a/Perl/PerlServImpl.pm b/Perl/PerlServImpl.pm new file mode 100644 index 0000000..4de5e6f --- /dev/null +++ b/Perl/PerlServImpl.pm @@ -0,0 +1,63 @@ +# +# PerlServImpl.pm +# +# Copyright (c) 1999, Tuomas Lukka +# +# You may use and distribute under the terms of either the GNU Lesser +# General Public License, either version 2 of the license or, +# at your choice, any later version. Alternatively, you may use and +# distribute under the terms of the XPL. +# +# See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of +# the licenses. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README +# file for more details. + + +FOR A MODEL ONLY - COPY & IMPLEMENT + +# ref & lock handled by the sessions... + +# gethead, sethead not implemented +# +sub _c_get { + my($this, $sess, $cfrom, $dim, $dir) = @_; +} +sub _c_new { + my($this, $sess, $cfrom, $dim, $dir) = @_; +} +sub _c_delete { + my($this, $sess, $cell) = @_; +} +sub _c_connect { + my($this, $sess, $cfrom, $dim, $cto) = @_; +} +sub _c_insert { + my($this, $sess, $cfrom, $dim, $dir, $cto) = @_; +} +sub _c_disconnect { + my($this, $sess, $cfrom, $dim, $dir) = @_; +} +sub _c_gettext { + my($this, $sess, $cell) = @_; +} +sub _c_settext { + my($this, $sess, $cell) = @_; +} +sub _c_ref { + my($this, $cell, $ref) = @_; +} +sub _c_lock { + my($this, $cell, $lock) = @_; +} +sub _c_unlock { + my($this, $cell, $lock) = @_; +} +sub _c_execute { + my($this, $script, $obj, $ctrl, $view) = @_; +} + + diff --git a/Perl/README b/Perl/README new file mode 100644 index 0000000..8e9351a --- /dev/null +++ b/Perl/README @@ -0,0 +1,5 @@ +This directory contains various hacks related to the client-server +protocol. Not necessarily usable in its current form. Use the stuff +in the ../Java/ directory. + + Tuomas diff --git a/Perl/ZZPerlDBServ.pm b/Perl/ZZPerlDBServ.pm new file mode 100644 index 0000000..4cfcd3a --- /dev/null +++ b/Perl/ZZPerlDBServ.pm @@ -0,0 +1,137 @@ +# +# ZZPerlDBServ.pm +# +# Copyright (c) 1999, Tuomas Lukka +# +# You may use and distribute under the terms of either the GNU Lesser +# General Public License, either version 2 of the license or, +# at your choice, any later version. Alternatively, you may use and +# distribute under the terms of the XPL. +# +# See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of +# the licenses. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README +# file for more details. + + +package ZZPHash; +require Tie::Hash; +@ISA='Tie::StdHash'; +sub TIEHASH { + bless $_[1], $_[0]; +} +sub STORE { + $_[0]->{$_[1]} = $_[2]; + print "STORED: '$_[1]' '$_[2]'\n"; +} +sub DELETE { + my $r0 = $_[0]->{$_[1]}; + my $r = delete $_[0]->{$_[1]}; + print "DELETED: '$_[1]' ( = '$r0' '$r')\n"; + return $r0; +} + +sub sync { tied (%{$_[0]})->sync } + +package ZZPerlDBServ; +use base ZZPerlServ; +use DB_File; + +sub _init_zzspace { + my($this) = @_; + my $db = $this->{DB}; + $db->{1} = "Home"; + $db->{Newno} = 42; + $db->{Inited} = 1; +} + +sub _c__reallynew { + my($this) = @_; + my $n = $this->{DB}->{Newno}++; + $db->{$n} = ""; + return $n; +} + +sub new { + my($type, $id, $port, $dbf) = @_; + my $this = $type->SUPER::new($id,$port); + my %h; + tie %h, DB_File, $dbf, &O_RDWR|&O_CREAT, 0640, $DB_HASH; + $this->{DB} = \%h; + my %h2; + tie %h2, ZZPHash, $this->{DB}; + $this->{DB} = \%h2; + $this->_init_zzspace() unless $this->{DB}{Inited}; + + Event->timer( + interval => 2, + cb => sub { $this->sync() } + ); + return $this; +} + +# gethead, sethead not implemented +# +sub _c_get { + my($this, $sess, $cfrom, $dim, $dir) = @_; + my $c = $this->{DB}{$cfrom.$dir.$dim}; + $c += 0; # Undef -> 0 + return $c; +} + +sub _c_delete { + my($this, $sess, $cell) = @_; + my @chg; + for(@{$this->{Dims}}) { + my $c; + push @chg, $c = delete $this->{DB}{$cell."+".$_}; + delete $this->{DB}{$c."-".$_} if $c; + push @chg, $c = delete $this->{DB}{$cell."-".$_}; + delete $this->{DB}{$c."+".$_} if $c; + } + push @chg; + $this->_chg(\@chg); + $this->_del($cell); +} +sub _c_connect { + my($this, $sess, $cfrom, $dim, $cto) = @_; + my @chg; + print "C_CONN $cfrom $dim $cto\n"; + my $c; + push @chg, $c = delete $this->{DB}{$cfrom."+".$dim}; + delete $this->{DB}{$c."-".$dim} if $c; + push @chg, $c = delete $this->{DB}{$cto."-".$dim}; + delete $this->{DB}{$c."+".$dim} if $c; + $this->{DB}{$cfrom."+".$dim} = $cto; + $this->{DB}{$cto."-".$dim} = $cfrom; + $this->_chg(@chg, $cfrom, $cto); +} +sub _c_disconnect { + my($this, $sess, $cfrom, $dim, $dir) = @_; + print "C_DISCONN $cfrom $dim $dir\n"; + my $c = delete $this->{DB}{$cfrom.$dir.$dim}; + return unless $c; + delete $this->{DB}{$c.(ZZPerlServ::oppdir($dir)).$dim}; + $this->_chg($cfrom, $c); +} +sub _c_gettext { + my($this, $sess, $cell) = @_; + my $v = $this->{DB}{$cell}; + if(!defined $v) { + return "" if exists $this->{DB}{$cell}; + return undef; + } + return $v; +} +sub _c_settext { + my($this, $sess, $cell, $text) = @_; + $this->{DB}{$cell} = $text; + $this->_chg($cell); +} + +sub sync { my($this) = @_; (tied %{$this->{DB}})->sync } + +1; diff --git a/Perl/ZZPerlServ.pm b/Perl/ZZPerlServ.pm new file mode 100644 index 0000000..96ea8c4 --- /dev/null +++ b/Perl/ZZPerlServ.pm @@ -0,0 +1,410 @@ +# +# ZZPerlServ.pm +# +# Copyright (c) 1999, Tuomas Lukka +# +# You may use and distribute under the terms of either the GNU Lesser +# General Public License, either version 2 of the license or, +# at your choice, any later version. Alternatively, you may use and +# distribute under the terms of the XPL. +# +# See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of +# the licenses. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README +# file for more details. + + + + +package ZZPerlServ; +use Event; +use IO::Socket; + +sub oppdir { + return "-" if $_[0] eq "+"; + return "+" if $_[0] eq "-"; + die("INVALID DIR!"); +} + +sub new { + my($type, $id, $port) = @_; + my $fh = IO::Socket::INET->new( + Proto => 'tcp', + LocalPort => $port, + Listen => SOMAXCONN, + Reuse => 1 + ); + my $this = bless { + Id => $id, + ConnId => 42, + FH => $fh, + }, $type; + Event->io( + fd => $fh, + poll => 're', + cb => sub { + my $cfh = $fh->accept() + or die("Couldn't set up client"); + # XXX autoflush? + $this->newconnection($cfh); + } + ); + Event->idle( + max => 2, + cb => sub { + $this->flush_changes(); + } + ); + return $this; +} + +sub newconnection { + my($this, $fh) = @_; + my $c = bless { + FH => $fh, + S => $this, + Id => $this->{ConnId}++, + }, ZZPerlConn; + $this->{Sess}{$c} = $c; + # XXX Weaken!!! + $c->start(); +} + +sub _c_new { + my($this, $sess, $cfrom, $dim, $dir) = @_; + my $cur = $this->{DB}{$cfrom.$dir.$dim}; + my $new = $this->_c__reallynew($sess); + if(!$new) { + return (0, "Couldn't create"); + } + if($dir eq "-") { + ($cfrom, $cur) = ($cur, $cfrom); + } + # XXX Catch errors + $this->_c_connect($sess, $cfrom, $dim, $new) + if $cfrom; + $this->_c_connect($sess, $new, $dim, $cur) + if $cur; + return ($new,""); +} + +sub _c_insert { + my($this, $sess, $cfrom, $dim, $dir, $cto) = @_; + print "INSERT $cfrom $dim $dir $cto\n"; + my $cm = $this->_c_get($sess, $cto, $dim, "-"); + my $cp = $this->_c_get($sess, $cto, $dim, "+"); + if($cm && $cp) { + $this->_c_connect($sess, $cm, $dim, $cto); + } else { + print "CM: $cm CP: $cp\n"; + $this->_c_disconnect($sess, $cto, $dim, "-") if $cm; + $this->_c_disconnect($sess, $cto, $dim, "+") if $cp; + } + my $c = $this->_c_get($sess, $cfrom, $dim, $dir); + print "C: $c\n"; + # if($c == $cto) { + # return; + # } + if($dir eq "+") { + $this->_c_connect($sess, $cfrom, $dim, $cto); + $this->_c_connect($sess, $cto, $dim, $c) if $c; + } else { + $this->_c_connect($sess, $cto, $dim, $cfrom); + $this->_c_connect($sess, $c, $dim, $cto) if $c; + } +} + +sub _c_ref { + my($this, $sess, $cell, $ref) = @_; + if(($this->{Fer}{$sess}{$cell} += $ref) <= 0) { + delete $this->{Fer}{$sess}{$cell}; + } + if(($this->{Ref}{$cell}{$sess} += $ref) <= 0) { + delete $this->{Ref}{$cell}{$sess}; + if(!keys %{$this->{Ref}{$cell}}) { + delete $this->{Ref}{$cell}; + } + } +} + +sub _chg { + my $this = shift; + if(ref $_[0]) { + for(@{$_[0]}) { + $this->{Chg}{$_} = 1; + } + } else { + for(@_) { + $this->{Chg}{$_} = 1; + } + } +} + +sub _del { + my($this, $cell) = @_; + for my $sess (keys %{$this->{Ref}{$cell}}) { + $sess->change("-1 deleted($cell)\n"); + } + delete $this->{Ref}{$cell}; +} + +sub flush_changes { + my($this) = @_; + print "FLUSH!\n"; + for(keys %{$this->{Chg}}) { + print "CELL: $_\n"; + for my $sess (keys %{$this->{Ref}{$_}}) { + print "SESS: $sess CELL: $_\n"; + $this->{Sess}{$sess}->change("-1 changed($_)\n"); + } + } + %{$this->{Chg}} = (); +} + +# XXX What happens when deleting a cell being waited for locking +sub _c_lock { + my($this, $sess, $cell, $lock) = @_; + my $l = { + Sess => "$sess", + N => $lock+0, + }; + if($this->{Lock}{$cell}) { + if($lock =~ /w/) { + push @{$this->{Wait}{$cell}}, $l; + # This will disable the filehandle in select. + $this->{Waiting}{$sess} = 1; + } elsif($lock =~ /a/) { + push @{$this->{Wait}{$cell}}, $l; + } else { + #$sess->_send_wouldblock($cell); + } + } else { + $this->{Lock}{$cell} = $l; + if($lock =~ /a/) { + $sess->_send_locked($cell); + } + } +} + +sub del_sess { + my($this, $sess) = @_; + # XXX HANDLE LOCKS! + for(keys %{ $this->{Fer}{$sess} }) { + delete $this->{Ref}{$_}{$sess}; + } + delete $this->{Fer}{$sess}; + delete $this->{Sess}{$sess}; +} + +sub _c_unlock { + my($this, $sess, $cell, $lock) = @_; +} +sub _c_execute { + my($this, $sess, $script, $obj, $ctrl, $view) = @_; +} + + +# Subclasses must implement +# c_get, c_new, c_delete,... + +package ZZPerlConn; + +%clcom = ( +get => 5, +gethead => 5, +sethead => 3, +new => 5, +delete => 1, +connect => 3, +insert => 4, +disconnect => 3, +gettext => 1, +settext => 2, +ref => 2, +lock => 2, +unlock => 1, +execute => 4, +); +%bincom = map {($_=>1)} qw/settext/; + +%excom = ( +get => rl, +gethead => rl, +new => rl, +); + +%respcom = ( +get => cellno, +gethead => cellno, +sethead => ok, +new => cellno, +delete => ok, +connect => ok, +insert => ok, +disconnect => ok, +gettext => text, +settext => ok, +ref => +); + +my $ip = qr/\((.*?)\)/; +my @nip = ( + "", + qr/$ip/, + qr/$ip$ip/, + qr/$ip$ip$ip/, + qr/$ip$ip$ip$ip/, + qr/$ip$ip$ip$ip$ip/, +); + + +use Fcntl; + +sub start { + my($this) = @_; + $this->{FH}->print("ZZ(0.02)($this->{S}{Id})($this->{Id})\n"); + fcntl($this->{FH}, &O_NONBLOCK, $b); + $this->{FH}->autoflush(1); + $this->{State} = "init"; + my $buf = ""; + $this->{Watcher} = Event->io( + fd => $this->{FH}, + poll => 're', + cb => sub { + my $b; + print "GOTIN\n"; + my $l = $this->{FH}->sysread($b,1024); + if(!$l) { + $this->throwout(); return; + } + $buf .= $b; + TRYMORE: + my $got = 0; + print "BUF: '$buf'\n"; + if(exists $this->{Binary}) { + if(length($buf)>= $this->{Binary}) { + $got=1; + my $s = substr($buf, 0, $this->{Binary},""); + print "$this->{Binary} str: '$s'\n"; + $this->binary_input($s); + delete $this->{Binary}; + } + } else { + if($buf =~ /^(.*?)(?:\x0d\x0a?|\x0a\x0d?)/) { + $got=1; + my $line = $1; + chomp $line; + chomp $line; + $buf =~ s/^(.*?(?:\x0d\x0a?|\x0a\x0d?))//; + $this->input($line); + } + } + goto TRYMORE if $got; + } + ); +} + +sub throwout { + my($this, $msg) = @_; + print "THROWING OUT $this: $msg\n"; + return unless defined $this->{Watcher}; + $this->{Watcher}->cancel(); + $this->{S}->del_sess($this); +} + +sub input { + my($this, $line) = @_; + print "IN: '$line'\n"; + for($this->{State}) { + /normal/ and do { + # print join ',', map {ord} split '', $line; + # print "\n"; + $line =~ /^(\d+)\s+(\w+)/ or + die("Illegal line '$line'"); + my $comid = $1; + my $c = $2; + if(!$clcom{$c}) { + $this->throwout("Unknown command '$c'"); + return; + } + unless($line =~ /^\d+\s+\w+$nip[$clcom{$c}]$/) { + $this->throwout("Need $clcom{$c} params for $c"); + return; + } + my @pars = map {defined $_ ? $_ : ()} + ($1, $2, $3, $4, $5); + if($bincom{$c}) { + $this->{BC} = $c; + $this->{BCID} = $comid; + $this->{BP} = \@pars; + print "BPARS: @pars\n"; + $this->{Binary} = pop @pars; + print "Bin: $this->{Binary}\n"; + } else { + my $m = "_c_$c"; + my @l = $this->{S}->$m($this,@pars); + my $rc = $respcom{$c}; + if($rc eq "cellno") { + print "CELL: $l[0]\n"; + if(!$l[0]) { + # $this->{FH}->print("$comid error(FROM CELLNO $l[1])\n"); + # NO SUCH CELL + $this->{FH}->print("$comid cellno(0)\n"); + + last; + } + # assuming ref-lock. + my $ref = $pars[-2]; + my $lock = $pars[-1]; + print "REF: $ref\n"; + $this->{S}->_c_ref($this,$l[0], $ref) + if $ref; + $this->{S}->_c_lock($this,$l[0], $ref) + if $lock; + $this->{FH}->print("$comid cellno($l[0])\n"); + } elsif($rc eq "ok") { + $this->{FH}->print("$comid ok\n"); + } elsif($rc eq "text") { + if(!defined $l[0]) { + # $this->{FH}->print("$comid error(no such cell)\n"); + # last; + $l[0] = ""; + } + my $len = length $l[0]; + $this->{FH}->print("$comid text($pars[0])($len)\n$l[0]"); + } + print "REPLIED!\n"; + } + last; + }; + /init/ and do { + unless($line =~ /^ZZ$ip$ip$ip$/) { + $this->throwout("Invalid startline"); + return; + } + $this->{CVer} = $1; + $this->{CId} = $2; + $this->{CSess} = $3; + $this->{State} = normal; + last; + }; + } +} + +sub change { + my($this, $msg) = @_; + $this->{FH}->print($msg); +} + +sub binary_input { + my($this, $data) = @_; + my $m = "_c_$this->{BC}"; + $this->{S}->$m($this,@{$this->{BP}}, $data); + print "REPLIEDBIN!\n"; + $this->{FH}->print("$this->{BCID} ok\n"); +} + + diff --git a/Perl/ZZPerlSimpleClient.pm b/Perl/ZZPerlSimpleClient.pm new file mode 100644 index 0000000..96b45ae --- /dev/null +++ b/Perl/ZZPerlSimpleClient.pm @@ -0,0 +1,111 @@ +# +# ZZPerlSimpleClient.pm +# +# Copyright (c) 1999, Tuomas Lukka +# +# You may use and distribute under the terms of either the GNU Lesser +# General Public License, either version 2 of the license or, +# at your choice, any later version. Alternatively, you may use and +# distribute under the terms of the XPL. +# +# See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of +# the licenses. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README +# file for more details. + + +# Provides the same routines as are inside the C++ scriptAPI for +# Perl, but using the remote interface. + +package ZZPerlSimpleClient; +use IO::Socket; +use base Exporter; +@EXPORT = qw/zzconnect get_cell new_cell delete_cell + connect_cells insert_cells insert_cell disconnect get_text + set_text/; + +my $socket; +my $reqno = 1; + +sub zzconnect { + my($hostport, $id) = @_; + $socket = IO::Socket::INET->new( + PeerAddr => $hostport, # host:port + Proto => tcp, + ) or die("No socket: $!"); + $socket->autoflush(1); + $init = <$socket>; + print "INI: $init\n"; + $socket->print("ZZ(0.03)($id)(1)\n"); +} +sub request { + my($req, $resp) = @_; + $reqno++; + $socket->print("$reqno $req"); + while(<$socket>) { + print "REP: $_\n"; + next unless s/^$reqno\s+//; + unless(/^$resp\b/) { + die("INVALID RESPONSE $_\n"); + } + if($resp eq "ok") { return } + if($resp eq "cellno") { + /^cellno\((.*?)\)/ or die("INV $_"); + return $1; + } + if($resp eq "text") { + /^text\((.*?)\)\((.*?)\)/ or die("INVT $_"); + my $nb = $2; + my $res; + my $b; + my $n; + my $cur; + while($nb > $n) { + $cur = read $socket, $b, $nb - $n; + if($cur == 0) { + die("NOR BYT"); + } + $n += $cur; + } + return $b; + } + } +} + +sub get_cell { + my($from, $dim, $dir) = @_; + return request("get($from)($dim)($dir)(0)(0)\n", "cellno"); +} +sub new_cell { + my($from, $dim, $dir) = @_; + return request("new($from)($dim)($dir)(0)(0)\n", "cellno"); +} +sub delete_cell { + my($cell) = @_; + request("delete($cell)", "ok"); +} +sub connect_cells { + my($from, $dim, $other) = @_; + return request("connect($from)($dim)($other)\n", "ok"); +} +sub insert_cell { + my($from, $dim, $dir, $other) = @_; + return request("connect($from)($dim)($dir)($other)\n", "ok"); +} +sub disconnect { + my($from, $dim, $dir) = @_; + return request("new($from)($dim)($dir)\n", "ok"); +} +sub get_text { + my($cell) = @_; + return request("gettext($cell)\n", "text"); +} +sub set_text { + my($cell, $t) = @_; + my $l = length $t; + return request("settext($cell)($l)\n$t", "ok"); +} + diff --git a/Perl/cperl.pl b/Perl/cperl.pl new file mode 100644 index 0000000..ed7611c --- /dev/null +++ b/Perl/cperl.pl @@ -0,0 +1,33 @@ +# +# cperl.pl +# +# Copyright (c) 1999, Tuomas Lukka +# +# You may use and distribute under the terms of either the GNU Lesser +# General Public License, either version 2 of the license or, +# at your choice, any later version. Alternatively, you may use and +# distribute under the terms of the XPL. +# +# See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of +# the licenses. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README +# file for more details. + + + +use lib "."; +use ZZPerlSimpleClient; +zzconnect('localhost:3546', foo); + +print get_text(1),"\n"; +$x = new_cell(1,"d.1", "+"); +$y = get_cell($x,"d.1", "-"); +$z = get_cell(1,"d.1", "+"); +print "GOT: '$x' '$y' '$z'\n"; +set_text($x,"FOOFOO"); + +print "DONE!\n"; + diff --git a/Perl/sperl.pl b/Perl/sperl.pl new file mode 100644 index 0000000..5e4a5ef --- /dev/null +++ b/Perl/sperl.pl @@ -0,0 +1,28 @@ +# +# sperl.pl +# +# Copyright (c) 1999, Tuomas Lukka +# +# You may use and distribute under the terms of either the GNU Lesser +# General Public License, either version 2 of the license or, +# at your choice, any later version. Alternatively, you may use and +# distribute under the terms of the XPL. +# +# See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of +# the licenses. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README +# file for more details. + + +use lib "."; +use ZZPerlDBServ; +use Event loop; + +$s = ZZPerlDBServ->new("S1",3546, "test.db"); + +print loop(); +print "OUT!\n"; +print $@; diff --git a/README b/README new file mode 100644 index 0000000..f1a01a9 --- /dev/null +++ b/README @@ -0,0 +1,65 @@ +gzigzag - an implementation of Ted Nelson's ZigZag structure +============================================================ + +NOTE!!! If you are wondering what to do, use the code in the +Java/ subdirectory. Go to the Java/ subdirectory and type 'make'. +If there are any problems, read Java/README. + +What is gzigzag ? +================= + +gzigzag is an implementation of the ZigZag(tm)* structure, which +was originally conceived by Ted Nelson. For more information about +ZigZag structure see Tuomas Lukka's 'A Gentle Introduction to Ted +Nelson's ZigZag Structure', which is included in the distribution as +Documentation/Gentle_Introduction. gzigzag was originally developed as a +student project in the Department of Mathematical Information Technology +at the University of Jyväskylä, Finland. + +It has been agreed that the gzigzag name and distribution are under +the care of Ted Nelson, and are currently maintained for him by the +Jyväskylä group. + +Directories +=========== + +Java/ -- Java version, standalone and network client. +Modules/ -- Various modules for the Java gzigzag +Documentation/ -- guess + +C++/ -- The C++ standalone clientserver. OLD, NOT USEFUL ANY MORE +Perl/ -- Perl code for network. NOT YET FUNCTIONAL + +Currently, the Java version is the one undergoing most development +and having the most functionality (much that is not found in the +C++ version). The C++ version has not been +touched since the last millennium and the Perl code is waiting +to be tested with the updated Java code (as a TCP/IP cellserver). + +License +======= + +You may use and distribute under the terms of either the GNU Lesser +General Public License, either version 2 of the license or, +at your choice, any later version. Alternatively, you may use and +distribute under the terms of the XPL. + +See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of +the licenses. + + +Getting gzigzag +=============== + +The latest version of the gzigzag can be obtained through: + +http://gzigzag.sourceforge.net + +Compiling gzigzag +================= + +The individual directories have instructions regarding how to install +that version. + +------------------------------------------------------------------------------ +* ZigZag is the trademark of Ted Nelson, used with permission diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..8acdd82 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.0.1 diff --git a/changelog-authors b/changelog-authors new file mode 100644 index 0000000..7348054 --- /dev/null +++ b/changelog-authors @@ -0,0 +1,10 @@ +tjl:'Tuomas J. Lukka ' +veparkki:'Vesa Parkkinen ' +ajk:'Antti-Juhani Kaijanaho ' +tuukkah:'Tuukka Hastrup ' +bfallenstein:'Benjamin Fallenstein ' +cat:'Katariina Ervasti ' +deetsay:'Tero Mäyränen ' +otso:'Otso Kivekäs ' +raulir:'Rauli Ruohonen ' +wikikr:'Kimmo Wideroos ' diff --git a/cvsparser.pl b/cvsparser.pl new file mode 100644 index 0000000..7922fb2 --- /dev/null +++ b/cvsparser.pl @@ -0,0 +1,36 @@ +#!/usr/bin/perl -w +# Written by Antti-Juhani Kaijanaho for the GZigZag project + +use strict 'vars'; + +sub main { + my @dirs = (); + my $dn = ""; + push @dirs, "."; + DIRS : while ($#dirs >= 0) { + $dn = pop @dirs; + print STDERR "Finding files in `$dn'..."; + open(ENTRIES, "<$dn/CVS/Entries") || next DIRS; + while () { + if (m|^(D?)/([^/]+)/-?([0-9]+(\.[0-9]+)*)?/(dummy timestamp)?|) { + my $dir = ($1 eq "D"); + my $name = $2; + if (defined $5) { + print STDERR "Ignoring $name\n"; + } elsif ($dir) { + push @dirs, "$dn/$name"; + } else { + print "$dn/$name\n"; + } + } elsif (/^D$/) { + # ignore + } else { + print STDERR "###$_###"; + die "syntax error" + } + } + close(ENTRIES); + print STDERR "done.\n"; + } +} +main(); diff --git a/makedist.param b/makedist.param new file mode 100644 index 0000000..4c86928 --- /dev/null +++ b/makedist.param @@ -0,0 +1,2 @@ +# -*- Shell-script -*- +cvstree=yes diff --git a/makedist.sh b/makedist.sh new file mode 100644 index 0000000..f8ec7b7 --- /dev/null +++ b/makedist.sh @@ -0,0 +1,73 @@ +#!/bin/sh +# makedist.sh +# * +# * You may use and distribute under the terms of either the GNU Lesser +# * General Public License, either version 2 of the license or, +# * at your choice, any later version. Alternatively, you may use and +# * distribute under the terms of the XPL. +# * +# * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of +# * the licenses. +# * +# * This software is distributed in the hope that it will be useful, +# * but WITHOUT ANY WARRANTY; without even the implied warranty of +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README +# * file for more details. +# * +# * Written by Antti-Juhani Kaijanaho + +set -e + +sign=no + +cont=true +while $cont +do + case "$1" in + -sign) sign=yes + shift ;; + *) cont=false ;; + esac +done + +srcdir=${2:-$(pwd)} +distdir=${1:-$(pwd)/gzigzag-dist} +rm -rf $distdir + +. makedist.param + +if [ "$cvstree" = "yes" ] +then + make Manifest +else + if [ ! -f Manifest ] + then + echo "Manifest is missing" + exit 1 + fi +fi + +for d in $((for f in $(cat Manifest) ; do dirname $f ; done) | sort | uniq) +do + echo -n "Making directory $distdir/$d ..." + mkdir -p $distdir/$d + echo "done." +done + +for f in $(cat Manifest) +do + echo -n "Copying $f ..." + ln $f $distdir/$f + echo "done." +done + +cat Manifest | xargs md5sum > $distdir/md5sum + +if [ "$sign" = "yes" ] +then + gpg --clearsign $distdir/md5sum + mv $distdir/md5sum.asc $distdir/md5sum +fi + + + diff --git a/manifest-filter.lst b/manifest-filter.lst new file mode 100644 index 0000000..4553fe4 --- /dev/null +++ b/manifest-filter.lst @@ -0,0 +1,4 @@ +- \.cvsignore +- Documentation/Manuscripts ++ Manifest +- src diff --git a/manifest-filter.pl b/manifest-filter.pl new file mode 100644 index 0000000..605361e --- /dev/null +++ b/manifest-filter.pl @@ -0,0 +1,24 @@ +#!/usr/bin/perl -w + + +# +# Read in the filter list. +# Print out lines starting with + directly. +# Save the lines starting with - in the array @del for deleting +# the files from input later +# +open FILTER, ") { + /^\+ *(.*)$/ and print "$1\n"; + /^- *(.*)$/ and push @del, $1; +} + +# Loop through the standard input, deleting lines that match regexes +# in @del. +LINE: while (<>) { + for $f (@del) { + /$f/ and next LINE; + } + print; +} + diff --git a/md5sum b/md5sum new file mode 100644 index 0000000..5f1c86e --- /dev/null +++ b/md5sum @@ -0,0 +1,599 @@ +1cbf71f50938fd85bf9e2b2ebe5cc691 ./ChangeLog +5e70b82aec781fc9f7ef6190cb5906d5 ./changelog-authors +9eec46aa6edb26062c2a6a28c50e3359 ./ChangeLog.2000 +79edd7f18201f486d8814b9299e29198 ./CODING +dee9834caa1bf34f379a50a073d85b5e ./C++/README +1167e5b86ea1b0bb6be66a7a21e4494c ./cvsparser.pl +06922d1e5dc7926eb444f1a8ccb99560 ./Documentation/ApplitudeWriters/appw.wml +e82885b74c0c0217f278f349f342eea5 ./Documentation/ApplitudeWriters/Makefile +92acab08d20b603b3883c9105c885eaa ./Documentation/CellScroll/SCRATCH +2674320eed1ca8d1ef50accb4116acec ./Documentation/Clang_Design/design.ptex +2907639f2d97f13db5ad88afb8140f38 ./Documentation/Clang_Design/Makefile +8a5c0771131b1bf4184088a4043ce36c ./Documentation/Clang_Design/thales.wml +b214f82d1574f8fafa0625c24cb0ce2f ./Documentation/CyberText/ct-old.wml +1a150cba0b0c8b3dbc559d948e5ecfb7 ./Documentation/CyberText/ct.wml +1ae5dc076d7bdc489d14927c0bd8a879 ./Documentation/CyberText/email.dia +fbc5f4e1031a0af55183e5d89e509343 ./Documentation/CyberText/kello-o.png +90eb082375ffae5b09a0718d273185ec ./Documentation/CyberText/kello.png +3756d1682dc232ec019e7d3c41845b20 ./Documentation/CyberText/Makefile +e5bb2292dc8d678ef57be6175bda6b6c ./Documentation/CyberText/permascroll.dia +f4197bc6bb806d229bd139625bdb555b ./Documentation/CyberText/rank1vert.dia +c2cf6f505b8f9c575418434e8fe14111 ./Documentation/CyberText/rank2vert.dia +7c04ca907d86aee6b4a112c087c95e07 ./Documentation/CyberText/rank3both.dia +55c74e43e3c5de6b54326550c1022489 ./Documentation/CyberText/vilma.png +7d27e1fa281f318d1da7d7a42f5bd3af ./Documentation/CyberText/1.png +4be38eaa620b2e9c256a06092b9018e5 ./Documentation/CyberText/3.png +14afbae628da2fbaf6a1a3332b0037ae ./Documentation/CyberText/4.png +ad399fa4e7646fb604e443ca23b957b8 ./Documentation/DesignProblems/beamorder.dia +9f0f16b5b27f45a9cac3d770065c0854 ./Documentation/DesignProblems/dp.wml +1b7fb15e61a2a3628b96d58b0cb94cac ./Documentation/DesignProblems/linkorder.dia +12a4e5f5de692903d013ba6248129e23 ./Documentation/DesignProblems/Makefile +253bd65821ea9e18c29263c63d7a8772 ./Documentation/diagrams/cursoring.dia +9a0704f21e4d30f46481c1bfabcc9061 ./Documentation/diagrams/Makefile +5263347e542f5af9c5ac0aea9bb9f313 ./Documentation/diagrams/ZZCanvas.dia +e272690c0d831641cb946bd1e405347c ./Documentation/DimBased/dim.ptex +d77afb65c41a709df86322a0cab73f05 ./Documentation/DimBased/Makefile +b1ec5a66faee2d17eb995cba721168d8 ./Documentation/FAQ +79e5315e49c7c801cfea618cab18a353 ./Documentation/Gentle_Introduction/gi.wml +fefc1a337dc230ad29d29a5786434080 ./Documentation/Gentle_Introduction/Makefile +af0ee9f755f44804d8293294ed1e6f06 ./Documentation/Gentle_Introduction/README +93952985cf28fd78c67a5327733eb8e7 ./Documentation/Gentle_Introduction/zzgentle.tex +08e850bd71ecff403e5bb1180f54f182 ./Documentation/Glossary/gl.wml +4f873babe15b8f647d503b84b8fe6ea7 ./Documentation/Glossary/Makefile +5af65f3cc452571ce90b2c57c116e559 ./Documentation/index.html +3b9c62c919a9d5bab2f6d5b2499cc637 ./Documentation/Interfacing/int.ptex +2d18881f757b5e977946d566969c6e96 ./Documentation/Interfacing/Makefile +75850a3d3febe8f743e9b163849a0f15 ./Documentation/keybindings.wml +0f164425af5921445fe00f7b2b6642c1 ./Documentation/lib.mk +d260d145647e25194097a4b1210760af ./Documentation/Makefile +f1a59137ce45b80e08ce6bda3a53ec9f ./Documentation/Math/ajk-scribbles.tex +4f10758373d972db6de55a236dcc40fe ./Documentation/Math/Makefile +58b2455932f29eaf1c72e2a722812d75 ./Documentation/Math/math.ptex +ca6f9c8b6fd7c8b006583f00668d531a ./Documentation/Mediaserver/mediaserver.tex +f38eaf3ab7540eebc48feda5366b62d0 ./Documentation/misc/ADDRESSING +7c3e8882a776e349639623c201df4168 ./Documentation/misc/billow +636a76d80d6d5dea56be29a414c89937 ./Documentation/misc/byrokratiadoku +e0c64f493dc191af2c1caae5fe7b7e68 ./Documentation/misc/Curseling +8b2139061a39e136df30723f73bb9bd8 ./Documentation/misc/keys +265d31082a50876994efdaa16d146c98 ./Documentation/misc/RENDERING +0f3754f0ed3338d7fcf6989092a0c77c ./Documentation/misc/textcloud +06145b9937d60e2552eb013b33e613ee ./Documentation/misc/TORESOLVE +1c7f94813f247924c7623d2bc014e8ca ./Documentation/Networking/Makefile +568c9cded573b264bbb0e24d8b3a4481 ./Documentation/Networking/mock-ZTPTCP.txt +d0fec04278f67fc36bba96e234ccafb0 ./Documentation/Networking/ZTP.txt +9d16f6e6c75c26ada809c16a8596f25b ./Documentation/Networking/ZTP-usage.txt +296fe725d3651b14292c6a28a7054d5a ./Documentation/Networking/ztp.wml +77dddfa14c58042df82a266c129b2515 ./Documentation/Nile/Makefile +272da468da76e3962c356d7824cbc22c ./Documentation/Nile/nileug.wml +b4c56dffdb28382cbd76ca17b5c5cc82 ./Documentation/Nile/nile.wml +3df296abc1207cf955a4ad4fd0747920 ./Documentation/PROTOCOL +320d3e5c4fcbc755c5c225d587512271 ./Documentation/README +f7e97d4ded8f11077d4042f6c688a012 ./Documentation/Slices/SliceLogic +ad55238dfcf895470e7df47d6cca7117 ./Documentation/Slices/zzSliceLogic.jpg +5751d534620a7b4798abf208818d2d44 ./Documentation/Spec/canvasraster.dia +3b423006824e0aecb10fb1ee69530110 ./Documentation/Spec/cursordim.dia +76d41ccc440b56a52350e31ea96ac2e6 ./Documentation/Spec/cursor1.dia +52be0a8acb7c050480f16fdc2f4434b4 ./Documentation/Spec/email1.dia +92982cd98f6a838e165fbc42d4193a21 ./Documentation/Spec/inheritparam.dia +a2930af8d526a78068dac25cdf39f2d7 ./Documentation/Spec/Makefile +2878d8156b13f608a0eb3f8c914e6c4d ./Documentation/Spec/rasterspec.dia +60b4837514ac1ce687603f95afd86bb2 ./Documentation/Spec/zzspec.wml +3b673f36c676d5e6e7ed272582f8dd42 ./Documentation/STARTING +deb9f5fb94f26dbe14ec359f56932f14 ./Documentation/Syntaxless/synt.wml +f29ac786d3105c04f90ba9568e73e044 ./Documentation/UsersGuide/active.png +c33a80abab73e9e71379adafb252c1a1 ./Documentation/UsersGuide/addressbook.png +784d854d26524ebff1cedc1dc3937c1a ./Documentation/UsersGuide/aftermove.png +ac959b546e01c99afe44ebca28495853 ./Documentation/UsersGuide/alku.png +f274fa4f95834c9e69393f31538af4ae ./Documentation/UsersGuide/bind1.png +6e76a6570fc6a6272334398f93dc8130 ./Documentation/UsersGuide/bind2.png +8bc6cef14abcff76b3a49b084cc5c519 ./Documentation/UsersGuide/boring.png +8569479426c6c89f05c0b231aaca973b ./Documentation/UsersGuide/bothwins.png +165248dc62dcbae10b38c84c1de48dd3 ./Documentation/UsersGuide/breakkafka.png +2861f3af6c607b00baf1dc39a39458e6 ./Documentation/UsersGuide/change1.png +adc2e98476d2b2ce970d6ea7d3cd2a68 ./Documentation/UsersGuide/change2.png +c6455d9d3f0d84c7102790658556a15f ./Documentation/UsersGuide/child1.png +800fdf10d240fef7fc5dd5a19b20dc6c ./Documentation/UsersGuide/child2.png +a08558f901d4f0c17b13835d5b0c58d1 ./Documentation/UsersGuide/clone1.png +927cde9403515d7e2087eb849e74ad47 ./Documentation/UsersGuide/clone2.png +89ed97b2dc2735684351e461ac6c2e4f ./Documentation/UsersGuide/connection1.png +8a00b7affd55a7624c779bbbf92ccbec ./Documentation/UsersGuide/connect1.png +8792ac4e6399067f954acb417e9a27c3 ./Documentation/UsersGuide/connect2.png +a5663428ef55d8cc385b73eada991464 ./Documentation/UsersGuide/creation.png +5538144f60b3d606ea4c59eaf24e6bc3 ./Documentation/UsersGuide/dimensio.png +03a2e7f760605fec73573fca9741c250 ./Documentation/UsersGuide/edit1.png +79febd4cf0fd79c8cef3b299f8e69fa9 ./Documentation/UsersGuide/edit2.png +686d0a00044ef7de7f3b4afd7e29ca8c ./Documentation/UsersGuide/edit3.png +9fd330f680ed8bc8ec4b5b746863965e ./Documentation/UsersGuide/edit4.png +350c00c89788bddbc9f23ab4d1d01b80 ./Documentation/UsersGuide/extra.png +94c8c1331a4e4f48dab5f42c8c8ed60e ./Documentation/UsersGuide/familytree.png +a4ba8b5afeda337b46e413fe9452c928 ./Documentation/UsersGuide/font.png +548c53363088e18b477197b853c70702 ./Documentation/UsersGuide/f2.png +723a4abb4e5cf218a0f2620c28c331f3 ./Documentation/UsersGuide/grey.png +3c09feb17c60f73a83ea737ba407c3d5 ./Documentation/UsersGuide/hopolympos.png +0d7443fe6b900ca6a660e7c0ead162f7 ./Documentation/UsersGuide/hop1.png +32c296d606aed817bc844cb5c7e2edb0 ./Documentation/UsersGuide/hop2.png +ee91d3c8f7933a0f95fc2ded1d0564e0 ./Documentation/UsersGuide/htree.png +4137cd14f3b73722b79fcae29931a7f9 ./Documentation/UsersGuide/kafka.png +e2c5ff9c557816c811e5a0be5c7dfbba ./Documentation/UsersGuide/klooni.png +75778d9754af31df5197ec52d8f4f845 ./Documentation/UsersGuide/Makefile +2c9d93eac5e5512174fd432eedc92543 ./Documentation/UsersGuide/make1.png +12f4651c7be12d85f35ef8b19de9d9ae ./Documentation/UsersGuide/make2.png +6d4bab0a69e186b10150bb3dcf05023b ./Documentation/UsersGuide/make3.png +a69f1217f07921e34f0e83c518ca8250 ./Documentation/UsersGuide/make4.png +8618217b75529fbe05e356082cba2d41 ./Documentation/UsersGuide/make5.png +13b95a23fcb0966086311bce3c0cd26a ./Documentation/UsersGuide/make6.png +7531ee4cc6b04fc9b36daaf78c288f8e ./Documentation/UsersGuide/margins.png +3c67cd490eaf1c649d783efae7ec835f ./Documentation/UsersGuide/markconnect.png +130e67557d777cd038ab7ef375223e01 ./Documentation/UsersGuide/mark1.png +490f75b9c2ed33fcc380db7b0e9e76c7 ./Documentation/UsersGuide/mark2.png +08f121f59d3edbe1901764bd49f55ce7 ./Documentation/UsersGuide/mutsiosoite.png +c2b954b41415d45cd59c894ad02a8969 ./Documentation/UsersGuide/mutsi.png +2e4e0784ca64841555048f2699252d69 ./Documentation/UsersGuide/myspeech.png +72e636c5d1d4f7ef7be589de4fbc5e72 ./Documentation/UsersGuide/myspeech1.png +1b3f0ba2c3cccbb31038a31c24b68591 ./Documentation/UsersGuide/myspeech2.png +b3048fece5fa01d40c20df6aa7b07e2f ./Documentation/UsersGuide/myspeech3.png +4949ff33daad35f3f63904404f118008 ./Documentation/UsersGuide/newcells.png +1a483e3e87f2b4c8c6cf5296c7222a99 ./Documentation/UsersGuide/newstory.png +89be29789e3aaa86f58351b4b0964feb ./Documentation/UsersGuide/newstory2.png +98a1c77312d2e9d9375ad3849ffa1f12 ./Documentation/UsersGuide/newstory3.png +05d976c5ca5fbd03bf1309c0903878dd ./Documentation/UsersGuide/newug.wml +aa819e5c0cdd837b2a6ee26775805215 ./Documentation/UsersGuide/olympos.png +207140cf3d14a4c7a9fe903875ebf15e ./Documentation/UsersGuide/olympos2.png +66546455337c689d372bde846ff4c450 ./Documentation/UsersGuide/osoite.png +6670ec3ee81424a5d40290d70d9d6d8b ./Documentation/UsersGuide/para.png +6b5dfe2bc462ceb8f125d51e577f2af9 ./Documentation/UsersGuide/rainy.png +982c903248bafde07abb4b3f0111dc75 ./Documentation/UsersGuide/rastererror.png +ef92db0ce3c1d923f617bbb7571b5292 ./Documentation/UsersGuide/rcfact1.png +b89d3fbf91d149e186d1c82c96d5ecec ./Documentation/UsersGuide/rightmoved.png +4c1407664c7d38cb3910522426c111de ./Documentation/UsersGuide/rotate.png +3dff900f0f6cfa4aaeff508cd143eaf7 ./Documentation/UsersGuide/row.png +737367b98fcd2f1c8f09dfd38f9c6917 ./Documentation/UsersGuide/shinyhappy.png +9d0a435240db859fcec0deacbc59a7f9 ./Documentation/UsersGuide/shinyhappy2.png +7fabbee9c8b9cf277de04cdb2d20c639 ./Documentation/UsersGuide/shinyhappy3.png +10ed552a5d23a84f84a3cc77f7226497 ./Documentation/UsersGuide/shiny.png +85feda8e083bf39b31cac764618f3fc7 ./Documentation/UsersGuide/showingz.png +8026e9597dbb58407c2414d2e4e38094 ./Documentation/UsersGuide/start.png +5af1ce5db874152e57edf32125a35bbd ./Documentation/UsersGuide/story.png +02184d8e5aa7005de8424cda5d3245c8 ./Documentation/UsersGuide/storytext.png +e352a9c06afb8efa60f2adb587f6aed7 ./Documentation/UsersGuide/structure1.png +bf8565b0a2c0527c492b216477b1148d ./Documentation/UsersGuide/structure2.png +e2e5105de48ce3d80b0cc24a703afdca ./Documentation/UsersGuide/suku.png +3747471bb345f26ed3ea350c4b326511 ./Documentation/UsersGuide/testi.png +8d43b85a0508199a1278de2c1f33b2d3 ./Documentation/UsersGuide/ug.wml +1efbea4c1234c467bdbebfe89e159107 ./Documentation/UsersGuide/wallstreet.png +ee009a5faf5915cf29de63dee8410e82 ./Documentation/UsersGuide/widthstr.png +68eb90f0a5ab638acbc25b439e9994f3 ./Documentation/UsersGuide/wrongconn.png +468ab82ce27c8494d30ca0c1131d6e6c ./Documentation/wmlinc/art.css +9ffdb9946a33e224adf25d5d0ff91f08 ./Documentation/wmlinc/article.wml +c12776714f82acad6e02a1f695aad4f4 ./Documentation/wmlinc/catart.wml +955b7704c6a83a896f72b5fa90469b03 ./Documentation/wmlinc/common.wml +cbb1c89ee6d808f74f34ec2f161d433d ./INSTALL +6fcebaf4cd4ffe29a347f092bfc8e8f6 ./Java/ApplitudeMgr.java +8d4ff2ac9cc7d9fa3101f21160f9df5b ./Java/arch/javadoc/ZobDoc.java +c3fb86ba30675a643cd95d7d7b81ac71 ./Java/arch/java2d/ZZDrawingJ2D.java +5cceb6acbb2ef051e24247acf71fea35 ./Java/arch/syslog/arch.mk +dbe724cf87045aadc7b5e2511cf0679e ./Java/arch/syslog/org_gzigzag_SysLogger.c +5618cad8358b1cc3c6a74ff70f97b65b ./Java/BuildInfo.java.in +352f9bb095e968e988bb8eb498b85a8b ./Java/check.pl +7ac606745c75a928701064a8c0ff97c7 ./Java/ChkVersion.java +0a170b4bd8c299d0149767fcb27d8801 ./Java/clang/Data.java +e6d1ba4953e0786e051901ea6cc52bd2 ./Java/clang/flowing/B.java +be9302493189fb8442ded02c8ad61801 ./Java/clang/flowing/C.java +2fcfe2c4d43f66bdc3b2ec251034d221 ./Java/clang/flowing/FlowingClang.java +60214e087486f753bdf9c93499d20139 ./Java/clang/flowing/Flowing.java +f800f1c59d453cda75d78bd70462e880 ./Java/clang/flowing/Primitive.java +3c5e54b2b06b20ccffb7dddf2aef1d3e ./Java/clang/flowing/PrimitiveSet.java +d31c18fab0d54bdd4a6113c04e3462d4 ./Java/clang/flowing/StackFrame.java +44756aa8af6df7312c5dde10562a0256 ./Java/clang/flowing/StackFrameReal.java +09395dd9093976eff1c8d45d42b3c0ae ./Java/clang/flowing/StackFrameVirtual.java +f934cc2c108e2fa2d61422e855289db1 ./Java/clang/flowing/T.java +fa2e1d27fa6babbe34de14ad149eaa7d ./Java/clang/flowing/X.java +aaa3f5cc5b4f74a6cfa174db006743bd ./Java/clang/heraclitus/HeraclitusClang.java +d276e10a983aefd598648d64641a7e5f ./Java/clang/heraclitus/HeraclitusCommand.zob +1a3899708d7cc5bef3dbb074b367b04b ./Java/clang/heraclitus/Primitive.java +0afff042ad311d2e839a319d900bbcb1 ./Java/clang/heraclitus/PrimitiveSet.java +9a672efeabe43c6c890783a8a2b2343e ./Java/clang/heraclitus/PS1.java +e8a13b7342c8e9cad0b75d5dc2d31b0b ./Java/clang/thales/DimensionNames.java +371d510a88848efb11959ece7ad98b65 ./Java/clang/thales/Environment.java +128be976b5de6f553d6c37c654b3b100 ./Java/clang/thales/Evaluator.java +e8e230f3b73782480eb291751af30ea4 ./Java/clang/thales/PrimitiveOperation.java +ee3a15acb9ac3259fb2bfc2fd5cb24b6 ./Java/clang/thales/primitives/If.java +9bfe3f683440814ee87f68a120972d19 ./Java/clang/thales/README +8b1c48cc67f6fc4a355184aeca1074d0 ./Java/clang/thales/Refcounted.java +9c9cc69252cdd1ea5bbd7e145d08d657 ./Java/clang/thales/SyntaxForm.java +c6c17b6d21fb8aa256a862ba181f8a7a ./Java/clang/thales/syntaxforms/Abstraction.java +609d3b490a144b5e73e082c91039aff8 ./Java/clang/thales/syntaxforms/CellDenoter.java +07018b35a1780bc64df209c537e449dd ./Java/clang/thales/syntaxforms/CellLiteral.java +9c96b45a321a6be5e54e147a9e118b1c ./Java/clang/thales/syntaxforms/Primitive.java +9cd91778072b0a73790ee3f33084d935 ./Java/clang/thales/syntaxforms/Sequence.java +3f7914ffff5d65bc8ae769454565ce14 ./Java/clang/thales/Task.java +d0670191a618407de5daacd31715d913 ./Java/clang/thales/ThalesClang.java +00d9f6e0dde985bc7b5aa6572bf4b17e ./Java/clang/thales/ThalesProgram.zob +520276baf1b487178a86d9e4352ba9be ./Java/clang/ZZClangContext.java +ba5a6f3ee5be3c25edace6f2f40d13d9 ./Java/clang/ZZClangContextReal.java +c5873ec335d6eaa7bc1f87d41940c73a ./Java/clang/ZZClangContextVirtual.java +7a208dd269adc33efebf39cbb0b5559b ./Java/clang/ZZClangOp.java +68bcde9d6781d3fabd938659b1b11454 ./Java/clang/ZZClangOps.pl +fcbd4f896f500fad141d031bef7e3fbe ./Java/clang/ZZClang1.java +2744012f6cf00b2617724d4c4576b667 ./Java/CommandLineOptionsParser.java +c7de291e516bb432b22b57f9917ddb44 ./Java/d.java +a1e99e31ab9d419b170a0559f6aba403 ./Java/Dumper.java +21b87b81daed7c7e623455c3a6c9504c ./Java/Dump.java +a46e0d74248efe5d4336d6d79790b548 ./Java/dump2java.pl +8c985388765d50de623da830ff5c2bed ./Java/errors/MissingTermError.java +9116e5fb34b9cfc04218406bb984dd79 ./Java/errors/SyntaxError.java +1beeb7fc4c2760bc93e0421f0bf269ce ./Java/errors/ZZConnectWouldBreakError.java +086e1a7071cf89df15433cbb62e72c4c ./Java/errors/ZZError.java +73b0b664900a6b0aaae2efe0d5759c46 ./Java/errors/ZZFatalError.java +324d7097b22bbb700b62668fdfe1212e ./Java/errors/ZZInfiniteLoop.java +4254f59ca80aa334d2a2006a9cf939ee ./Java/errors/ZZInvalidCursorPositionError.java +c9b1b4c3601bd940435e281204cab946 ./Java/errors/ZZInvalidDimensionError.java +189e443c496591fc676cacd2cca93484 ./Java/exp/rast/vanishing.view +829fe293f2b0391bc43bdade843ee2d6 ./Java/flob/ArrowDecor.java +479f203e477234f64e9bc7dee029a4f2 ./Java/flob/BallCell.java +23bdd09339027f43f3b5031ac80dbf5c ./Java/flob/BeamDecor.java +040949a70c63a2b44ac3893026b62d75 ./Java/flob/BoxedFlob.java +2bac9ea9f7236674ea1f8e736630668e ./Java/flob/BoxType.java +60cf44f339bb502363a6b9a052ba72ee ./Java/flob/CellBgFlob.java +31caa624e77cd73bfc7b8bfe6d9d2081 ./Java/flob/CellFlobFactory1.zob +1cd48783b5418d783acc16c45b9078fc ./Java/flob/CellFlobFactory2.zob +83bad85795c37f85a312ac5dee3cf0d2 ./Java/flob/CellFlob1.java +697625ee706d6737e2b29419c9027ddd ./Java/flob/Colorer.java +1f9f90195bb4de5f240889176d762a6b ./Java/flob/CombinedView.zob +c3dc191cf65beb72990320aca8aa53f6 ./Java/flob/CompassView.zob +9a9d96c9dc565a8753381ac5879f1a4f ./Java/flob/ConnectionLineDecor.java +d71fa969f2b5df41fc913e5c3e07f5e8 ./Java/flob/CoordDecor.java +71e8c9f5546a6bf5ef790b87622a0cce ./Java/flob/CursorView.zob +e672105c03169bb4842a232d0ae80878 ./Java/flob/FlobDecorator.java +277ce61142bc645b76c8edf2522cb6dd ./Java/flob/FlobFactory.java +a969a14677160aac3e294f14f2b64354 ./Java/flob/Flob.java +98e5da013eefd07751010195f289b8a4 ./Java/flob/FlobSet.java +d74ba6956d8325232a96ae87af259d62 ./Java/flob/FlobView.java +234bf33239ef847d729939936bf110bc ./Java/flob/FTextCellView.zob +e2d83c5add5898199a326acea42f895d ./Java/flob/FTextLayouter.zob +05e2f43f5f69c8e4a3710ed8ebdcb0da ./Java/flob/GridGeom.java +545a6f78cf5a842169802bccbc16a71f ./Java/flob/ICView.zob +db664d3c85a08e506f2bc30826250df5 ./Java/flob/IdiosyncraticFlobFactory.zob +66b04915ad7a040c396d778af536efcc ./Java/flob/Level.java +54b1e8d489c6a8829b34dd943af17bfd ./Java/flob/LevelView.zob +29ec3ece03132c0a38d4e7dc82f8f5fd ./Java/flob/LineDecor.java +aad17c88f924778964702865a3cc479c ./Java/flob/MagGrid.zob +47eef925a2b406050c3381f3c48edf6b ./Java/flob/ManyToManyView.zob +dbd055860be4bcc907cd23785ef48891 ./Java/flob/MultiView.zob +f706340dda0ac0060d9bf00fdf222559 ./Java/flob/NullView.zob +8f943756074e0240be2ef4da2fb1c6ca ./Java/flob/ParallelTextView.zob +196dae163d44f45d2170cdeceb33c054 ./Java/flob/RankTextView.zob +e5315a9e83ef724f42bf5eff867f181d ./Java/flob/Renderable.java +312643ece8285bf6cfae3b59059bfb33 ./Java/flob/RowColView.zob +1cf8f4beb8ccd21cd5439206ea196e18 ./Java/flob/SceneFlob.java +33afff7c641b2bfbd108776082958fb3 ./Java/flob/SimpleBeamer.zob +5eeed6179c4548506758cc8256e096a4 ./Java/flob/SimpleBoxType.java +d0f17cdd840fe89ae95d2d97105400f0 ./Java/flob/SimpleFlobConnector.zob +ad64f69aec2423e6ceb62beb5ae2235f ./Java/flob/SimpleFlobView.zob +5e38f1d3ad4c271ecd8320a39ba96f41 ./Java/flob/SimpleSceneFlob.java +9290115001078986cc48a97aa40e6176 ./Java/flob/SimpleTextView.zob +01941c9b135f3032c29bdc2c167475af ./Java/flob/SpanFlob.java +e13dbee183befe6d8ea8db08025473e9 ./Java/flob/SplitCellFlob1.java +0888f6cf53e538a333cca7e184a03a3c ./Java/flob/SplitView.zob +9b9a8146fd77d1b1ede78c21c16402ac ./Java/flob/StdLinks.zob +064fee912247d9731e3986f7a20f0213 ./Java/flob/TextDecor.java +ac6beebe1fb02317c9799508248a3a71 ./Java/flob/TreeView.zob +38714eeb30421f9b703d00585b865afb ./Java/flob/VanishingView.zob +88cde6505b0a764dc7e920b8fc59a419 ./Java/flob/VobSet.java +54f80679d7bbdf7ea9b2cdb97c5d6afc ./Java/flob/WindowCellView.zob +4c3146285128a9e236723acb1eeb2646 ./Java/.gvimrc +42dfb0d169a939e003338dac39bc1e9c ./Java/JEv.java +5bd534e4d0ce9278e3c438e0234befc5 ./Java/LoopDetector.java +03fea609420a2d5722098c7b8c5279e9 ./Java/Main.java +f24687e2f2f52dfdcbae9b262be4a101 ./Java/Makefile +c75150ee9cb573df9580deca284cd7cc ./Java/media/Address.java +b2798df6ed30ef0bffb07af9d87d1257 ./Java/media/ByteScroll.java +33bcff0d04071eb6283741f663e9d537 ./Java/media/Capitalizer.java +06de2b7c32c816b406717b06fc86b04e ./Java/media/CharScroll.java +68fef86c239386db3bdab433b1d470b1 ./Java/media/FirstMatchBreaker.java +088f112c627fa574688610469615d5c0 ./Java/media/FText.java +3ae2766b21730781a96504dbe925e6c6 ./Java/media/LineBreaker.java +9515c7ee596939173625d59189af8141 ./Java/media/LineInfo.java +559de5d34663437a9d99edcfbcf01e19 ./Java/media/README +572668768fe57e8d200f1ae1698b84d6 ./Java/media/Scroll.java +7ddfd81401ac8d9a9256217a66f8298d ./Java/media/SimpleLineBreaker.java +38837807006dcc3f143e9c667f284f7e ./Java/media/SimpleLineInfo.java +d494a948d30c8d0aa561a878cd8e5c59 ./Java/media/SoundScroll.java +7e1f2958322ba496318b737a4fb83a5e ./Java/media/Span.java +755e10f2f2ec735ca99b65ff4bb2a9b2 ./Java/media/SpanSet.java +debc580f87e4f3280aa4b8e33c4ebf65 ./Java/media/SpanTree.java +e36c7f6f0a412741c0bfd6fbe78952b0 ./Java/media/Stream.java +51e5c7a99ea1e5ba68a9762f1dd6aab5 ./Java/media/StringScroll.java +879998e4bc07e2c8294bb89c6bd11e60 ./Java/media/TestLines.java +488763ed1902ab41eb863f2e6825d2dc ./Java/media/UTF8Char.java +b3b9ce84c5135294f02a8d191a23f442 ./Java/media/VStream.java +16adf9791d30c197e3b72fc46a1183a7 ./Java/media/ZZDefaultText.java +1e69024890ca5b387c989b03a20a20fd ./Java/media/ZZHumber.java +90e968f0791ce180b747222d5ab0ff10 ./Java/media/ZZSoundView.java +2b4dd4d16f5890db2d5a9f0f2b127674 ./Java/media/ZZText.java +faa7fad7fc880e4a69719d2b8859e87e ./Java/mungencss.pl +90d88252a16f98cadccfa14131dc157a ./Java/net/Peer.java +bfb767cb48d2643b133fb5d8e7e812e7 ./Java/net/ReliableUDPMessageFactory.java +9fe1038cd501a815497982fdf59206b9 ./Java/net/ReliableUDPMessage.java +75c21c58acaa278f86a542dacd31d9c6 ./Java/net/ReliableUDPSocket.java +c5a9fb1d8ef674df0c4b1ac35d85cfc2 ./Java/NullZOb.java +101219d5c50d07396356ec636de1bc5c ./Java/Package.html +c6b804589491b0197e623628de43c058 ./Java/part/BinaryTreePart.java +9c9a918d455806ca0fe70953e18f2c8f ./Java/part/DoubleStepPart.java +3d89637aff17f2026c4d7aa4fb9a3f2b ./Java/part/GenTreePart.java +c2e29c3ab9a48f298e8cb337daea8c1f ./Java/part/GenTreePartModel.java +71a810834cdaca798ee534741a279850 ./Java/part/GenTreeTestModel.java +afb53e36dfe913c67155a360920fe8ba ./Java/part/ImpliedTreePart.java +59e01fb7fb001b1d9c5c889a2a48979f ./Java/part/ImpliedTreePart2.java +6290103738e7e0aa407b652bb214cb63 ./Java/part/VersionPart.java +fe359a75105ba97b60db0a8b56fd7c7e ./Java/part/ZZROSpacePart.java +9fbc1c57b64c362a2e07719b0cd58d80 ./Java/part/ZZROStrSpacePart.java +1cfbabf626a85eaecb270da98621f450 ./Java/p2p/P2PStorage.java +6f0f36a24800a5901bfa7d63d223c1ea ./Java/p2p/UniqueID.java +5192d88653fa70415b83ecb49fadd7ff ./Java/README +c51cab2867beb87854eb83884daea16b ./Java/RString.java +8281b907c346e9d20d7537caee8a7b45 ./Java/SafeExit.java +1b2f9f2d866fa9ae6d37bbc8f709ee0b ./Java/ScalableFont.java +1be0e6a0b504d4d50feebeec19413615 ./Java/script/invoke.c +5299eb4a9ecb9456746b1b9cf21fc582 ./Java/script/Makefile +23c8c2d4a061afd4f210cfa2e885b29e ./Java/script/ZZId.h +6c461c6180710bf4377dc08b624a5103 ./Java/script/ZZScriptAPI_1_JNI.cpp +42cd737f20462535217e80c2db2aab49 ./Java/script/ZZScriptAPI_1_JNI.h +de5a57abfd0f0865dfbf4abe5e883e5b ./Java/script/ZZScriptPerl.cpp +0fdd0f793a4cc21c36ca38ae06be8919 ./Java/script/ZZScriptPerl.java +7f2f3f17df2d393ee9cb5657b03b5809 ./Java/SoundObs.java +a9c4b297676533c9f028165a6fca0226 ./Java/SpaceDump.java +20b9a4285a76a5a848f61ba9a0912c7e ./Java/storage/ContentStore.java +2e6919f346b024c01318c36fedf07d64 ./Java/storage/ContentStorer.java +cf4f9f42d8733e026286cfbc9d97d3f0 ./Java/storage/CountingStream.java +626f2817e1c42042239e879c677bfd8e ./Java/storage/DimStore.java +705ac5783262f04715aa702d348982db ./Java/storage/DirStreamSet.java +efe67476d4de323f667360c6f60b5d83 ./Java/storage/DummyStreamSet.java +983c3a6299ed47fce17d435eeb918a89 ./Java/storage/FileWritable.java +7aa6afc88dad9e3b4298eabf887a0213 ./Java/storage/Flushable.java +58506f32ddb5d7990af0d0718cc5f7e5 ./Java/storage/GZZ0.java +8e234262643385d2e2323109d779a528 ./Java/storage/MemWritable.java +33665cf2ea61206d7037daa025c480d7 ./Java/storage/Recs.pl +2ab5f8ec20b18703c20d9334faf61c83 ./Java/storage/SimpleContentFile.java +a6ff3b41a8af895114f5708244f8046a ./Java/storage/SimpleDimFile.java +52225a2559c249525da2e8bff3feebd5 ./Java/storage/SlicedCursor.java +c7ee3fa988dcc3268ca341e2db74c939 ./Java/storage/SlicedHomes.java +c5ad93ecfb8fd5688db1900fc6a1b287 ./Java/storage/Sliced.java +0f8490c364121d1370a8c6049d0380d8 ./Java/storage/SlicedSame.java +6f4978f3740a5b643116875934d99062 ./Java/storage/StreamSet.java +70486a4938fe8cc0f561bc9aab4bfa90 ./Java/storage/Writable.java +cf6e5d83669af794e0f720130c67401b ./Java/storage/ZZCacheContentStore.java +65e6a431b87d15da43a6a130dbe54350 ./Java/storage/ZZCacheDimension.java +84e54d49956c272a9d7261303fd0b23d ./Java/storage/ZZCacheDimSpace.java +90dc1b748866de7e217f126e237aad98 ./Java/storage/ZZDimStorer.java +24321864c1953cecbf651628ce1b1c82 ./Java/SysLogger.java +2a543bd95033b72d250521d8e69f4f97 ./Java/TestSpace.java +e41d64d35f1a6e72bc4a86f5d28b896f ./Java/TimeTest.java +212266fe772063ec572a7379355a7805 ./Java/TODO +1daf7016dd4c9a9db8551fa21e7b18ac ./Java/transform/ChangeDim.java +9baae4ba62744ce2da84dd2b05b4464b ./Java/transform/ClearDim.java +c63a14783b65d1d8fae7cbb646667a17 ./Java/transform/CopyDim.java +2afae00f73d9bef80df626280bc718e7 ./Java/transform/FoldDim.java +88e34fb3456366afc52c07b0d25254cf ./Java/transform/ReverseDim.java +7111804cbdb7ec2c90d848a9eaaf35ef ./Java/transform/VersionChanger.java +56b47bbb0af60699cbe5318ff6c9e0ae ./Java/transform/Version0.java +b689899172de4a0fcf8fac061eeba416 ./Java/transform/Version1.java +de320303cb8e4061e37fe9be0802a33d ./Java/transform/Version2.java +48e67d0bf0c9eac3888f26c27d9a91af ./Java/UndoList.java +52faf2b849eb16c46820babe76156b86 ./Java/ZOb.java +020bb3094e861cf4f3baff92bd97ad06 ./Java/zob2java.pl +532a18ff07255253425feaaac6729488 ./Java/ZTPCommand.java +7fc7fbc6ec94a933208040b0df4501c9 ./Java/ZZCanvasView.java +9ce7c4325d83f61ebcde31c9be4d3678 ./Java/ZZCellHandle.java +eba55ed2c72c8c0f167fc36341a0f3df ./Java/ZZCell.java +d0a8062146a83dfa72fd122850e093f5 ./Java/ZZCommand.java +f57f611b48cef525343946bbf7bf3089 ./Java/ZZConnection.java +043c7d81f28215210ed0b640c9297bcc ./Java/ZZCursor.java +2364cfd0d379f8feb451c8e11585e8b0 ./Java/ZZCursorReal.java +acb09e456ae4928b8e3d247dfd43bff4 ./Java/ZZCursorVirtual.java +7db8701915cab0b9b8dc166dff0a095d ./Java/ZZDefaultSpace.java +e72a512f1dcff0c3fe29e980d6faf3b4 ./Java/ZZDimension.java +89891888fb9554460177dd0047a3f36f ./Java/ZZDimSpace.java +af212418ec060449f20adcc6c012164d ./Java/ZZDrawing.java +ac07bff3aad3e2af70d1bb0e5881afee ./Java/ZZEvObs.java +57efea7e3addacc684612a72ae7b0340 ./Java/ZZExec.java +3715ccb7690a50282c2e77c02df45537 ./Java/ZZIter.java +4b4105e5420fe89b6db60a71da4bc5a5 ./Java/ZZKeyBindings.java +bfcaa696d3afcdef802de0b59164ecea ./Java/ZZKeyBindings0.java +d783dcd54fa3e61a888f4e609b54c119 ./Java/ZZKeyBindings1.java +269c22b51cc783ec4407d99b418baeb4 ./Java/ZZKeyHacks.java +a671c87ee71506e70bd1bf537e2976ac ./Java/ZZLocalDimension.java +8feb87db44092ffce2197b30e369a6fd ./Java/ZZLogger.java +12597e0332c5330c371645e1529c1952 ./Java/ZZModule.java +40a98c7bee5f339674822c0c269f8f4d ./Java/ZZObs.java +8a144980a5b8b6d94cb9b38470d73d71 ./Java/ZZObsTrigger.java +217b252092dbba0940919cfa7b2de264 ./Java/ZZPath.java +920dfcc9b460a80c523b7a639dd29a4e ./Java/ZZPhotoView.java +9a1d00c3123361ca031a08f7a0e355b8 ./Java/ZZPrimitiveActions.java +9f4e93522dcc7ee8656093ba59f4daca ./Java/ZZPrimitiveCommand.zob +b668abe45f13613ddd506ab07becaf55 ./Java/ZZRODimension.java +7735ba74206e1c2ce3b2b7fec20ab8e2 ./Java/ZZScene.java +32deb6719f25e084a564af870e3b196e ./Java/ZZSlicedDimSpace.java +8529bd5dea9b7c452ec62c0e739e84f4 ./Java/ZZSpace.java +43b97e57ec39bc7dcc308ee1b699c6ee ./Java/ZZSpacePart.java +298077bc0edf3d058748407c5d24661e ./Java/ZZTextView.java +89ca6a42d087bc28c27b81c9ced7779c ./Java/ZZTraverseCB.java +37b6366ee65d85d9540347e09ff11c5e ./Java/ZZUpdateManager.java +afdaf3509d26f0f06a8c0104bba63ffa ./Java/ZZUtil.java +38791925547399c362d052e8ee7dda24 ./Java/ZZViewComponent.java +8bdf80dd0a062d399c269f140b89d055 ./Java/ZZView.java +b518f1cc09de4da58cc203f0842fd574 ./Java/ZZWindows.java +6e29c688d912da12b66b73e32b03d812 ./LICENSE.lgpl +bb4bb554d0818bcbf54275d78c70cfae ./LICENSE.xpl +9a693c8ce0e2afc4c1b99c1c80f5946f ./makedist.param +8dcbbd155ce2854e8c0371d13e1337ac ./makedist.sh +6decdb20247d44deed82eecbfbc99b62 ./Makefile +265f410d6d78f4c565f2325f760fe9f1 Manifest +3f45193ab931aaf4910d399b8ce7a1a3 ./manifest-filter.lst +a79bfc4c2d3a4adc0cee5273b85046f4 ./manifest-filter.pl +925a6fd17158ccbf3ef6d75bfb79ae76 ./Modules/applet/example1.html +a1c76ce46af6a642dcd433260b02b368 ./Modules/applet/ZZApplet.java +7914102ab0af3c1e61dd56b8d37a4732 ./Modules/awtool/AwtCursor.java +81e211e55b5ab1fc18f1e02dc80d9935 ./Modules/awtool/AwtLink.java +18808224277fbc4664cffea2aa054dab ./Modules/awtool/AwtLink.zob +c28881dd64182b6899ae648f5c07407d ./Modules/awtool/AwtMetricsFC.java +cfa506eaff1db1ee91386d634d38d4e5 ./Modules/awtool/AwtMetricsFC2.java +f31c60623b10cfc9af3313506b5fa467 ./Modules/awtool/AwtMetrics.java +881358e7558e77fb450c1377a770b680 ./Modules/awtool/AwtMetricsNormal.java +7ea0a19501d9f9e75ee6baf4770a81e0 ./Modules/awtool/AwtMetrics.zob +90b1092e03be1e58b4426d6695602f2a ./Modules/awtool/AwtNileView.java +889be573d84a07b4aec97509f481ca60 ./Modules/awtool/AwtNote.java +f23bbd93b7c59cf5e292eb24ee7985eb ./Modules/awtool/AwtNote.zob +49e875a34ed9750e38e278841fc4d0a2 ./Modules/awtool/Awtool.java +cef39b65785a3d71db870df7de2fa257 ./Modules/awtool/Awtool.zob +55a79e0625571c254e2523b9239afa20 ./Modules/awtool/AwtUtil.java +0c9126c0cda42f44e6b0284c42a5ff2e ./Modules/awtool/AwtView1.java +e7ae0effd0e83a15ace6c09ecf072893 ./Modules/awtool/BooleanMesh.java +9c45120d5ec02b5116164ccda4cc9f29 ./Modules/awtool/README +df257f3b54e2796b57fd703b7c78c4b9 ./Modules/awtool/TODO +42bb6f87a096a94cbcd6df72e63b3cd4 ./Modules/awtool/ZObCellRepr.java +f4a7f9e53dbf85b71ac8b03020aa6162 ./Modules/benchmark/GraphBench.java +1cbe9556eb901da9d34cc511d85eadca ./Modules/benchmark/java2d/Java2DBench.java +698ef080d04a7e3205c14f327e3fbbf7 ./Modules/benchmark/README +442405e5bd142d29ee43a4b2848b8deb ./Modules/benchmark/ZZBench.java +a6ea06432827282fb8eba069c7457280 ./Modules/database/createscript.pl +c148624b523de50a7d740653421c6099 ./Modules/database/DB0.java +dd0f9e5d1ca7b455744883bc39f48182 ./Modules/database/zz.queries +fca6ec8dd5439eb8a9856330110b25ed ./Modules/database/zz.sql +c36795bc13e8f3e78acdda3220224c2d ./Modules/daytimedemo/Calendar2.zob +04dc4a14979ee2bbc0e196b47b6302f4 ./Modules/daytimedemo/ClockCellView.zob +b555e3bc30ed4be43c44de307fbe3e75 ./Modules/daytimedemo/DayTimeDemo.zob +d2ebeeb0ec57e273fd71690baab006cb ./Modules/extern/Extern.java +5a44ab88eb59011a452cf2ca68e403c1 ./Modules/hypergenealogy/HyperGenealogy.zob +e96d0641ec7001cdb3b2eb1350f3c93b ./Modules/iter/DimRecursor.java +87d3e70eeeca75b8e3ee710118d13769 ./Modules/iter/EnumVanishingView.zob +decd686d5e608e7fc02a1c6498315401 ./Modules/iter/Iter.java +441ffce54e957236ae894bb1172111ba ./Modules/iter/README +3e7f6dfab7ee63f04454951153d8534c ./Modules/joystick/LinuxJoystick.java +9bf4a1da80cd0c597838d74488dd35e8 ./Modules/mbox/SingleMail.zob +81bc7ecda0110c3ebef5c65381ebf375 ./Modules/mbox/ZZDateParser.java +28076d564164fc206e343bcccfe69f12 ./Modules/mbox/ZZMbox.java +b4b114d7c0986c88ce84fd19be00f7f8 ./Modules/mind/Mind.java +384325f9f6b863df4981a8e0f1237a17 ./Modules/mind/MindSundew.java +f021d23b01666e7edb8fd2af0062ac26 ./Modules/mind/MindSun.java +9dddf98d36021a0d0c574ca7009a7d62 ./Modules/multimedia/adjust.java +305674937b6d6d2508b12363be9db0da ./Modules/multimedia/crop.java +8d61ba772bca95443172c8796b244e51 ./Modules/multimedia/Default.java +9d6fc29d77e3ca903af1b33b93a633d2 ./Modules/multimedia/dots.java +bf58b8c5818f5bee16d76821b2b7e440 ./Modules/multimedia/image.java +5a2c682f2c634c74056d0fccae6412c4 ./Modules/multimedia/MediaFlobFactory.java +f533341e59d3539406471299cbcf853a ./Modules/multimedia/MediaFlobView.java +12424b3fff597bd6c634d6a47ca256fe ./Modules/multimedia/MediaMath.java +8e20f948baf967d3dd1e2ce5e872b4e7 ./Modules/multimedia/MediaZOb.java +e2a70dd0c140626e8f525df72f176d3e ./Modules/multimedia/mm.java +5cd0a9745ec7f52bbb86cefc6d23094d ./Modules/multimedia/move.java +a169b3a6a554575ed74171dc3d494715 ./Modules/multimedia/Pixels.java +c7c02a0ade7c29e8a9effb00b3389684 ./Modules/multimedia/PolygonRenderer.java +e12886d243c539d79b68ccb9d7609d31 ./Modules/multimedia/Polygons.java +9db8ec02f44a73346f1e00f1fcaf0c67 ./Modules/multimedia/readme.html +6fe23b7c55f8293450a1391ecba4008f ./Modules/multimedia/rect.java +9c13144d01a5c7ec95b50121643f88e5 ./Modules/multimedia/sin.java +cca8c0aa10bf519dafef2ea786352c61 ./Modules/nile/draft/Nile3Ops.java +97f8d9290fd19954205e8f461b721ec2 ./Modules/nile/draft/Nile3Part.java +e35c48b29e0f3ded057487715e35e1ca ./Modules/nile/draft/Nile3Pos.java +8f290f6cf73fecaff68e3a4f64ddc7d8 ./Modules/nile/draft/Nile3Unit.java +65ab721b13b54b57d24b8f1486d753c9 ./Modules/nile/NileApplet.java +2fdf3909c59af46363af5f70d2dc459c ./Modules/nile/NileDemo.java +8f037e44ee9f5bf79541adf1338adfa0 ./Modules/nile/Nile1Div.java +dc1a90edfd00fa9b3f9cf2db7fa6657d ./Modules/nile/Nile1GenTreeModel.java +801ea73772a6f6e91cbc825c05f930c6 ./Modules/nile/Nile1.java +edb2acc377ed1716f588a047dbd041db ./Modules/nile/Nile1Ops.java +11eab265c949ad2d8895263596f7da4e ./Modules/nile/Nile1Text.java +0cb9ec21d960fecfa8506e21af8a831e ./Modules/nile/Nile1View.zob +b6d533a7380625a0a802ae2155c15c1c ./Modules/nile/Nile2Iter.java +52a9ef49ce3dccb1b72073ff15b5de2d ./Modules/nile/Nile2Ops.java +96e34331465935136e81a015459ceed1 ./Modules/nile/Nile2Test.java +97ece27591313342b802534e883e7cad ./Modules/nile/Nile2Unit.java +1d741db89036b2aefa009238bd84a6c2 ./Modules/nile/README +644c964d0c8f6beb1af74ddb4b5734e6 ./Modules/nile/SplitNileDemo.java +5fd2907b150c1bfbfc77d7c6bb9e2e90 ./Modules/nile/SplitNileView.zob +d9a63d5cfd0926c89b75308b211eaa17 ./Modules/notemap/Notemap.zob +6e6b4dc23ad964beed3335a3ea88035a ./Modules/openGL/fi_iki_lukka_ZZOpenGLGraphics.h +8ed706298c05f9293ad481460a8e2a1f ./Modules/openGL/Makefile +b72792999c769a5a4668acb981da4b3f ./Modules/openGL/OpenGLCloud.java +68f822570b0fd62c48e80b2f8f949c1c ./Modules/openGL/ZZOpenGLGraphics.cc +c9ff5358229253e54d4fd9fe5c1121e7 ./Modules/openGL/ZZOpenGLGraphics.java +b9352a005581d78ad641aabd7f1738c1 ./Modules/panes/PaneView.zob +109b8aae81253d4acb26cfb7207c3f7a ./Modules/prez/Prez.java +85b728d7e4f141fb13e12c96ea9a1c39 ./Modules/prez/PrezRaster.zob +7b1376e584c6e586d26f2e613a7d497e ./Modules/README +40473ff9b47c2a7330d421731b73cc64 ./Modules/servlet/startjetty +efa3493aad01d13ad2f9f210c5e4ca0f ./Modules/servlet/VCServlet.java +2dc1e5f825c2ab8e0d46f507b404eb54 ./Modules/servlet/ZZServlet.java +b6b5f4994fdf46ec70adb4642b99bb2a ./Modules/servlet/zzserv.prp +4dad7b0e145abf8c2ac648abfe5d8033 ./Modules/servlet/zzserv2.prp +e339836283cdfa36e93b7e5afd03a17f ./Modules/sound/gsm_def.h +0e428af0a5e2ccb12fb3b76f4e84d5c8 ./Modules/sound/gsm_player.c +da859ad6c6224eafe57ef07ac0f8b3ad ./Modules/sound/gsm_recorder.c +03c79cf40080ec4ac2a58a0b1c817a7f ./Modules/sound/org_gzigzag_module_SimplePlayer.h +8491ce664ebe723a9f22f0a2cdf5aa7f ./Modules/sound/org_gzigzag_module_SimpleRecorder.h +0caad9d88177f6991ca39fd3679b166c ./Modules/sound/Player.java +c71d6c6056c9555d3a1de830888d7423 ./Modules/sound/Recorder.java +e86bae8148f7e5bd877284f12c50c099 ./Modules/sound/SimplePlayer.java +e29193f3dc59ad4fc74771a1581ce5ec ./Modules/sound/SimpleRecorder.java +f884549c0590a3ea5651d04de97285c0 ./Modules/sound/Sound.java +8fe08f3f70828049a7276669c3235072 ./Modules/test/README +5e2f8711d48a02d3b3b45e4311bf8224 ./Modules/test/TestClang1.java +67a1c141d8b7f4654c6c7a028145b628 ./Modules/test/TestHuge.java +a0f11cc84c5e66d1bf49f6c3d5514ced ./Modules/test/TestUndo.java +03094b5a42d3e32d8df43fc471f309f8 ./Modules/textcloud/TextCloud.zob +a34096038d953cd2cae93d51981c588c ./Modules/virtualcommunity/MessageFlobFactory.zob +0f6b87054720c74b728f26dcf84013c7 ./Modules/virtualcommunity/VCView1.java +6d48cd9983d11b562721b76a43f45bcf ./Modules/virtualcommunity/VCView2.java +b421b182b49668d5b7d9ccb3af9a2834 ./Modules/virtualcommunity/VCView3.java +b115cbae69e00e607a73d7ab54d27bc5 ./Modules/virtualcommunity/VCView4.java +e86b2443ae40d64a8d1bfd1eb8f5b99d ./Modules/virtualcommunity/VirtualCommunity.zob +fd3ad984d56a3d542290b3d8e59e431c ./Modules/vob/Connection.java +a5cf512f53454333ec7f763cb7b6658d ./Modules/vob/View.java +9513ba48c2b3a8a47e2f5f5b56f574a8 ./Modules/vob/Vob.java +01ed0350f167ed4454822c61c7379b5b ./Modules/vob/VobSet.java +b43e23e0cc03638782677d161e252b19 ./Modules/vob/VobStore.java +18da034b97bdb8ff5a8ce588a244d564 ./Modules/wordnet/conv.pl +def2c8a136ffe14b63ca7d1213187e9f ./Modules/xml/old2xml.pl +dc730e0e76b43a6433e391844e72abb2 ./Modules/xml/XML.java +94ddfe1cfcc45793b316f452024539ef ./Modules/zaubertrank/old/Actions.java +8ce6fd998eb35420d87626c1193d96b6 ./Modules/zaubertrank/old/Evaluator.java +039a8f25f90237e964d00775cdc8af58 ./Modules/zaubertrank/old/ParsedView.zob +68730b83954f598ebdebb333ac01a80b ./Modules/zaubertrank/old/Parser.java +6462d2438a93ffcbd4925972c4faf6e0 ./Modules/zaubertrank/old/Primitive.java +bc016fdfcc7069ddb17c9ea124dab505 ./Modules/zaubertrank/old/PrimitiveSet.java +3b07c9957a9d5a935b7cbc1412cf552c ./Modules/zaubertrank/old/SimpleView.zob +b92b437eb5fdee5189275ec755578265 ./Modules/zaubertrank/old/TokenFlob.java +38251a8ee6e30f4f55ac6ef2d1fe8d82 ./Modules/zaubertrank/old/TokenGrouper.java +d95d253353c6eb6c8274894cdb7b55a0 ./Modules/zaubertrank/old/Zaubertrank.java +c7990c975905c7ab892e8db298573ebb ./Modules/zaubertrank/old/ZaubertrankPart.java +448ab34951f8b280a6a2b15e5b1e4d04 ./Modules/zaubertrank/README.html +4b9d931e54c8a797b70be0c2c370a4ca ./Modules/zaubertrank/TokenTextCellView.java +7db224e3dbcbb542a175a1d60c86420a ./Modules/zaubertrank/ZaubertrankCellView.java +21d6102d124c44cb0beae241f33d2477 ./Modules/ztp/client/Action.java +de3230501ca36d4f1c26d5838b27ec45 ./Modules/ztp/client/Get.java +561c2a7d399ce6b9ba246eb9860e1416 ./Modules/ztp/client/Put.java +f9731410bbe95f52c662a3f356a45928 ./Modules/ztp/client/RemotePieceData.zob +6f30aadbc2073a58e438a766df09c9f9 ./Modules/ztp/client/Response.java +9f4f56ecad69f12874408a7543b5af14 ./Modules/ztp/client/Session.java +e4e245e2e119413373846528a1cf79e4 ./Modules/ztp/client/Subspace.java +f5a9fb3187f1ab9733fb2c57f4b28eb4 ./Modules/ztp/common/LineBufferedIO.java +0eed92e105cd4d42ec6c0e3574414df4 ./Modules/ztp/common/SubspaceDump.java +8286072ad1a37d6920aa84df6e0429dd ./Modules/ztp/server/GetMessage.java +a9150d5a7d4dec47a28563c84b9c5ff0 ./Modules/ztp/server/Listener.java +dc9c6045954c19bfbbafab16ff2af332 ./Modules/ztp/server/PutMessage.java +36fe65bee1db36c2ee506b9c5cfbffe6 ./Modules/ztp/server/Session.java +ad0198d0b647b9617e5fc37738bde56d ./Modules/ztp/server/UserManager.java +2096f7fd82609c8d98c40049e9ab6ea3 ./Modules/ztp/server/UserRecord.zob +08df1a8d7c09cd19233f3780bd9c8725 ./Modules/ztp/ZTPclient.java +bbd341b64c77696ba00a03140b7843b5 ./Modules/ztp/ZTPserver.java +c95342b5e64993c1aa4028c86d76c560 ./NEWS +717dda13238b80ff4e29e9f43293df41 ./Perl/cperl.pl +7cbc4f0e01357d4fdb273036b1232b05 ./Perl/PerlServImpl.pm +173087e5db7ad8338c6a9bb679938d14 ./Perl/README +2e2d54b8968a60f83b12c23ca7f425ca ./Perl/sperl.pl +b98bb2587720d03b603b8a3ae5249864 ./Perl/ZZPerlDBServ.pm +d751f660be9ed043a72aa6a1732b70ed ./Perl/ZZPerlServ.pm +09cec273af30bd97132982a4ae71109d ./Perl/ZZPerlSimpleClient.pm +86508b9a1c70efeb16630b47abe8071f ./README +523f7f8a2368d300345949dfb006cae4 ./VERSION