created mirror

This commit is contained in:
whatever
2026-09-14 20:19:29 -04:00
commit 6764738d92
600 changed files with 87187 additions and 0 deletions

2
Java/.gvimrc Normal file
View File

@@ -0,0 +1,2 @@
set cindent
set shiftwidth=4

310
Java/ApplitudeMgr.java Normal file
View File

@@ -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...<br>
* 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.<br>
* 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<res.length; i++) res[i] = (ZZCell)v.elementAt(i);
return res;
}
private static void unregister(ZZCell d, String name) {
ZZCell a = d.s("d.1");
a = a.findText("d.2", 1, name);
if(a == null) return;
d = a.s("d.1", -1);
for(ZZCell e = d.s("d.2"); e.s("d.1") == null; e = d.s("d.2"))
e.delete();
d.delete();
for(ZZCell c = a.s("d.clone"); c != null; c = a.s("d.clone"))
c.delete();
a.delete();
}
/** Register a new applitude.
* @param name The title of this applitude.
* @param dims The dimensions to associate with this applitude.
* @param view The id of the view for this applitude. (Currently,
* applitudes can have only one view.)
* @param binds The bindings cell for this applitude. If null, a bindings
* cell without a connected list is created. Applitude
* bindings work just like normal bindings.
* @returns The maincell of the applitude.
*/
static public ZZCell register(ZZSpace sp, String name, String[] dims,
String view, ZZCell binds) {
if(dims.length < 1)
throw new ZZError("Cannot register applitude without dims!");
ZZCell home = sp.getHomeCell();
ZZCell app = home.N();
app.setText(name);
ZZCell vc = app.N("d.1").N("d.2");
vc.setText("View");
vc.N("d.1").setText(name+" View");
vc.s("d.1").N("d.1").setText(view);
ZZCell bindc = vc.N("d.2");
bindc.setText("Bindings");
if(binds != null)
bindc.connect("d.1", 1, binds);
else
bindc.N("d.1");
ZZCell d = getDimCell(home);
unregister(d, name);
ZZCell a = d.s("d.1");
a.insert("d.2", 1, app);
d = d.N("d.2");
d.setText(dims[0]);
d.connect("d.1", 1, app);
for(int i=1; i<dims.length; i++) {
d = d.N("d.2");
d.setText(dims[i]);
}
return app;
}
static public ZZCell putDefApps(ZZCell home) {
ZZSpace sp = home.getSpace();
ZZCell c = ZZDefaultSpace.findOnClientlist(sp, "Applitudes", true);
ZZCell d = c.getOrNewCell("d.1", 1);
d.setText("Dims");
d.getOrNewCell("d.1", 1).setText("Applitudes");
ZZCell zz = register(sp, "ZigZag", new String[] { "d.1", "d.2", "d.3" },
"VanishingView", null);
ZZCursorReal.set(d.s("d.1"), zz);
ZZCell nbinds = d.N();
ZZCell nbc = nbinds.N("d.2"); nbc.setText("n");
nbc.N("d.1").setText("Notemap.NEW");
nbc = nbc.N("d.2"); nbc.setText("-");
nbc.N("d.1").setText("Notemap.CNCT");
register(sp, "Notemap", new String[] { "d.map-1", "d.map-2" },
"Notemap.Star", nbinds);
return c;
}
/** Get the "Applitude" param cell of a window.
* @param create Whether to create the param if it isn't there already.
*/
private static ZZCell getWinAppCell(ZZCell win, boolean create) {
ZZCell res = ZZDefaultSpace.findInheritableParam(win, "Applitude");
if(res != null || !create) return res;
res = win.N("d.2");
res.setText("Applitude");
return res;
}
/** Get the applitude associated with a window.
* This reads the "Applitude" inheritable param of a window and returns
* it (or null if it isn't set).
*/
static public ZZCell getWindowApp(ZZCell win) {
ZZCell c = getWinAppCell(win, false);
if(c == null) return null;
return ZZCursorReal.get(c);
}
/** Set the applitude associated with a window.
* May be set to null. (ESC should do that.)
*/
static public void setWindowApp(ZZCell win, ZZCell app) {
ZZCell c = getWinAppCell(win, true);
ZZCursorReal.set(c, app);
}
/** Get the "fallback" applitude used when no matching one is found. */
static public ZZCell getFallback(ZZSpace sp) {
return ZZCursorReal.get(getDimCell(sp.getHomeCell()).s("d.1"));
}
/** A convenience function combining getWindowApp and getApplitudes.
* First, this calls getApplitudes() on the cell accursed by the window.
* Then, it calls getWindowApp() to find out which applitude this is
* associated to. It looks through the applitudes from the first call,
* searching for this app. If it's found, it changes places with the first
* app in the list, so that the 'prefered' applitude is always found at
* index 0. If it's not found, setWindowApp() is called with the first
* element of the array.
* If the array returned by getApplitudes() is empty, the "safety net"
* applitude (ZigZag, showing the VanishingRaster) is returned.
* @returns Never null, never less than one element. The first element is
* always equals to what getWindowApp() would return (after the
* call).
* @deprecated Do it by hand. Don't set win app.
*/
static public ZZCell[] getWindowApplitudes(ZZCell win) {
pa("Call to deprecated getWindowApplitudes!");
ZZCell[] apps = getApplitudes(ZZCursorReal.get(win));
if(apps.length == 0) {
ZZCell c = getFallback(win.getSpace());
setWindowApp(win, c);
return new ZZCell[] { c };
}
ZZCell pref = getWindowApp(win);
if(apps[0].equals(pref)) return apps;
for(int i=1; i<apps.length; i++) {
if(apps[i].equals(pref)) {
apps[i] = apps[0];
apps[0] = pref;
return apps;
}
}
setWindowApp(win, apps[0]);
return apps;
}
/** Get the flob view associated with an applitude.
* Currently this just reads the View param, but later this may change
* e.g. so that you can rotate through the views of an applitude.
*/
static public FlobView getView(ZZCell app) {
ZZCell vc = ZZDefaultSpace.findInheritableParam(app.s("d.1"), "View");
if(vc != null) vc = vc.s("d.1");
if(vc == null)
throw new ZZError("No view found for applitude "+app);
ZOb zob = ZZDefaultSpace.readZOb(vc);
if(zob != null && zob instanceof FlobView) {
return (FlobView)zob;
} else {
ZZLogger.log("ApplitudeMgr.getView: invalid type: "+zob);
return new NullView();
}
}
/** Change applitude of window according to clicked flob.
* This is called by ZZKeyBindings1 whenever there was a click.
*/
static public void clicked(ZZCell win, ZZScene xi, Point pt) {
Flob[] fs = new Flob[1];
((FlobSet)xi).getObjectAt(pt.x, pt.y, fs);
Flob f = fs[0];
if(f == null || f.applitude == null) return;
setWindowApp(win, f.applitude);
}
/** Get the applitude bindings for this window.
* This first checks the applitude currently prefered by this window,
* then finds the bindings cursor for that applitude, then resolves
* that cursor and returns the result.<br>
* 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);
}
}

39
Java/BuildInfo.java.in Normal file
View File

@@ -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 = "@@@@@";
}

94
Java/ChkVersion.java Normal file
View File

@@ -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; i<classes.length; i++) {
try {
String n = "org.gzigzag."+classes[i];
p(n);
Class c = Class.forName(n);
Field f = c.getField("rcsid");
p((String)f.get(null));
} catch(Exception e) {
p(e.toString());
}
}
System.exit(0);
}
}

View File

@@ -0,0 +1,311 @@
/*
CommandLineOptionsParser.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.*;
/** Command line options parser. */
class CommandLineOptionsParser {
/** Objects of this class or of descendants of this class
* represent valid command-line options. By default, this option
* does nothing except note that the option was seen. Subclasses
* can override <code>action</code> 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
* <code>CommandLineOptionsParser</code> 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 <code>argNames</code> attribute.
*/
public void action(CommandLineOptionsParser clop, String[] args) {}
/** Constructs an option.
*
* @param name The value to be given to the <code>name</code>
* attribute.
* @param argNames The value to be given to the
* <code>argNames</code> attribute.
* @param helpText The value to be given to the
* <code>helpText</code> 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 <code>option</code> 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 <code>Option</code>.
* 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 <code>HelpOption</code>. 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
* <code>action</code> method of <code>Option</code> 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
* <code>i</code>th (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 <code>deflt</code>, if the option has not seen, otherwise the
* <code>i</code>th (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();
}

242
Java/Dump.java Normal file
View File

@@ -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; i<s.length(); i++)
if(!Character.isJavaIdentifierPart(s.charAt(i)))
throw new ZZError("Bad Dump cell id: '"+s+"'");
}
return s;
}
/** Write the dump of an array of cells to a Writer.
* Dumps the cells' contents and all connections <em>between them</em> 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<cells.length; i++) {
ZZCell c = cells[i];
w.println(id(c, ids) + " " + c.getText());
if(c.getSpan() != null)
ZZLogger.log("ATTENTION! Span converted to plain text in Dump "
+ "at cell "+c);
}
w.println(); w.println();
w.println("CONNECTIONS");
for(int i=0; i<dims.length; i++) {
w.println();
String d = dims[i];
w.println(d);
for(int j=0; j<cells.length; j++) {
ZZCell neg = cells[j];
ZZCell pos = neg.s(d);
if(pos != null && ids.get(pos) != null)
w.println(id(neg, ids) + " " + id(pos, ids));
}
}
w.println(); w.println();
w.println("END OF FILE");
w.flush();
}
/** Find all cells connected to start on dims, directly or indirectly.
*/
public static ZZCell[] select(ZZCell start, String[] dims) {
Vector cells = new Vector(); cells.addElement(start);
Vector todo = new Vector(); todo.addElement(start);
Hashtable found = new Hashtable(); found.put(start, start);
while(todo.size() > 0) {
ZZCell c1 = (ZZCell)todo.elementAt(0);
todo.removeElementAt(0);
for(int i=0; i<dims.length; i++) {
String dim = dims[i];
for(int dir=-1; dir<2; dir+=2) {
ZZCell c2 = c1.s(dim, dir);
if(c2 != null && found.get(c2) == null) {
todo.addElement(c2);
cells.addElement(c2);
found.put(c2, c2);
}
}
}
}
ZZCell[] arr = new ZZCell[cells.size()];
for(int i=0; i<arr.length; i++)
arr[i] = (ZZCell)cells.elementAt(i);
return arr;
}
public static void writeDump(ZZCell start, String[] dims, Writer writer) {
ZZCell[] cs = select(start, dims);
Hashtable ids = new Hashtable();
for(int i=0; i<cs.length; i++) ids.put(cs[i], cs[i].getID());
writeDump(cs, dims, ids, -1, "Dumped", writer);
}
public static class Read {
public ZZCell[] cells;
public String[] ids;
public String[] dims;
public int nextid = -1;
public String title;
public Hashtable cellByID = new Hashtable();
private final void fail() {
throw new ZZError("Bad Dump.Read input");
}
private final void test(String s1, String s2) {
if(!s1.equals(s2)) fail();
}
private final void test(BufferedReader r, String s) throws IOException {
if(!s.equals(r.readLine())) fail();
}
private final void skip(BufferedReader r) throws IOException {
if(!r.readLine().equals("")) fail();
}
private final String[] split(BufferedReader r, String sp)
throws IOException {
String s = r.readLine();
if(s.equals("")) return null;
int i = s.indexOf(sp);
return new String[] { s.substring(0, i),
s.substring(i+sp.length()) };
}
public Read(ZZSpace sp, Reader reader) {
try {
ZZCell home = sp.getHomeCell();
BufferedReader r = new BufferedReader(reader);
String s;
String[] parts; String var, val;
p("Reading Dump...");
test(r, "HEADER"); skip(r);
while((parts=split(r, ": ")) != null) {
var = parts[0]; val = parts[1];
if(var.equals("Format")) test(val, "Dump "+fmtversion);
else if(var.equals("Next free ID"))
nextid = Integer.parseInt(val);
else if(var.equals("Title"))
title = val;
else if(!var.equals("rcsid"))
ZZLogger.log("Strange line in Dump header: "+var+": "+val);
}
p(" Header.");
skip(r);
test(r, "CONTENTS"); skip(r);
Vector v = new Vector(); // cell ids found
while((parts=split(r, " ")) != null) {
var = parts[0]; val = parts[1]; p(" Ctnt: "+var+", "+val);
v.addElement(var);
ZZCell c = home.N();
c.setText(val);
cellByID.put(var, c);
}
cells = new ZZCell[v.size()];
ids = new String[cells.length];
for(int i=0; i<cells.length; i++) {
ids[i] = (String)v.elementAt(i);
cells[i] = (ZZCell)cellByID.get(ids[i]);
}
skip(r);
test(r, "CONNECTIONS"); skip(r);
v = new Vector(); // dimensions found
while(!(s = r.readLine()).equals("")) {
v.addElement(s);
p(" Dim: "+s);
while((parts=split(r, " ")) != null) {
var = parts[0]; val = parts[1]; p(" Conn: "+var+", "+val);
ZZCell c1 = (ZZCell)cellByID.get(var);
ZZCell c2 = (ZZCell)cellByID.get(val);
if(c1 == null || c2 == null)
throw new ZZError("Dump input: attempt to connect a "
+ "cell whose content isn't specified "
+ "("+(c1==null ? var : val)+")");
c1.connect(s, 1, c2);
}
}
dims = new String[v.size()];
for(int i=0; i<dims.length; i++)
dims[i] = (String)v.elementAt(i);
test(r, "END OF FILE");
p("...reading finished.");
} catch(IOException e) { ZZLogger.exc(e); }
}
}
}

161
Java/Dumper.java Normal file
View File

@@ -0,0 +1,161 @@
/*
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.module;
import org.gzigzag.*;
import java.util.*;
import java.io.*;
import java.awt.*;
/** A module interface to Dump.
* While Dump provides methods to dump any subspace, this module has a special
* zz infrastructure to save information about subspaces, as follows:
* <ul>
* <li> A subspace (SP) has a handle cell (HC).
* <li> The HC is connected to a cell of the subspace on +d.dump-conn
* <li> The HC contains the SP file name.
* <li> Connected to the HC on +d.2 is a rank with dim names; only these dims
* are saved to the SP file.
* <li> 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.
* <li> 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.
* </ul>
* 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<dims.length; i++) dims[i] = dcs[i].t();
ZZCell start = hdl.s("d.dump-conn");
if(start == null) throw new ZZError("Not a Dumper handle: "+hdl);
ZZCell[] cells = Dump.select(start, dims);
ZZCell nextidcell = hdl.s("d.dump-nextid");
int nextid;
try {
nextid = Integer.parseInt(nextidcell.t());
} catch(NumberFormatException e) {
throw new ZZError("Bad next Dumper cell id: "+nextidcell);
} catch(NullPointerException e) {
throw new ZZError("Not a Dumper handle: "+hdl);
}
Hashtable ids = new Hashtable();
for(int i=0; i<cells.length; i++) {
ZZCell c = cells[i], idc = c.s("d.dump-id");
if(idc != null) ids.put(c, idc.t());
else {
String id = String.valueOf(nextid);
nextid++;
c.N("d.dump-id").setText(id);
ids.put(c, id);
}
}
Dump.writeDump(cells, dims, ids, nextid, title, writer);
nextidcell.setText(String.valueOf(nextid));
}
static public void read(ZZCell hdl, Reader reader) {
if(hdl.s("d.2") != null) hdl.disconnect("d.2", 1);
if(hdl.s("d.dump-conn") != null) hdl.disconnect("d.dump-conn", 1);
if(hdl.s("d.dump-nextid") != null) hdl.disconnect("d.dump-nextid", 1);
Dump.Read r = new Dump.Read(hdl.getSpace(), reader);
hdl.setText(r.title);
if(r.nextid > 0) hdl.N("d.dump-nextid").setText(""+r.nextid);
else hdl.N("d.dump-nextid").setText("1");
for(int i=0; i<r.cells.length; i++)
r.cells[i].N("d.dump-id").setText(r.ids[i]);
for(int i=r.dims.length-1; 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;
}
};
}

73
Java/JEv.java Normal file
View File

@@ -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("------");
}
}
}

66
Java/LoopDetector.java Normal file
View File

@@ -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:
* <pre>
* LoopDetector l = new LoopDetector();
* while((x = iter(x)) != null) {
* l.detect(x);
* // ... do something with x.
* }
* </pre>
* Note: this only works for deterministic loops that always have the same
* elements and length.
* <p>
* 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;
}
}

535
Java/Main.java Normal file
View File

@@ -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.
* <dl>
* <dt> <b>-new</b>
* <dd> 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).
* <dt> <b>-convert</b>
* <dd> 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
* <b>new</b> and <b>dcold</b> to catch up with
* configuration changes.
* <dt> <b>-import</b> XMLfile
* <dd> When creating a new space, you can import an XML
* file describing the space.
* <dt> <b>-export</b> XMLfile
* <dd> Export the whole space to the specified file
* <dt> <b>-recrmdim</b>
<dd> Recreate master dimension list from data on disk.
* <dt> <b>-dbg</b> classname
* <dd> Turn on debugging in the given class. For developers
* only.
* <dt> <b>-pda</b>
* <dd> Run in PDA-mode.
* <dt> <b>-span</b>
* <dd> 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.
* <dt> <b>-ztpserv PORT</b>
* <dd> Invoke the ZTP server code instead of the ZZ client code.
* Listen on the TCP port PORT for incoming connections.
* <dt> <b>-dump</b>
* <dd> Dump the space to the file CELLSCROLLFILE.dmp (where
* CELLSCROLLFILE is the name of the space file).
*
* <dt> <b>-slurp FILENAME</b>
* <dd> Slurp the space from the file called FILENAME.
* <dt> <b>-versioneddims</b>
* <dd> Show connections from old versions along regular dimensions
* in addition to the special version: dimensions.
*
* </dl>
* <p>
* 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.
* <p>
* Example:
* <pre>
* java foo.Main -new /tmp/foo
* </pre>
* opens the cellscroll at /tmp/foo and creates the new client structure.
* XXX Make a good system for specifying the type.
* <p>
* 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<slices.length; i++)
// ss[i+1] = new ZZPersistentDimSpace(
// new DirSet(new File(slices[i]), "rw"));
// space = new ZZSlicedDimSpace(ss);
//throw new Error("No sliced stuff right now!");
}
if (slurpf != null) {
if (!newspace)
throw new ZZError("cannot slurp into an existing space");
Reader r = new FileReader(slurpf);
SpaceDump sd = new SpaceDump(r);
// First, instantiate the scrolls
for (Enumeration e = sd.stringscrolls.keys(); e.hasMoreElements();) {
String name = (String)e.nextElement();
StringScroll ss = space.getStringScroll(name);
String content = (String)sd.stringscrolls.get(name);
if (ss == null)
throw new ZZError("cannot create the string scroll " + name);
if (ss.curEnd() != 0)
throw new ZZError("the string scroll `" + name
+ "' is not initially empty!");
ss.append(content);
}
// Then put in cell content
for (Enumeration e = sd.content.keys(); e.hasMoreElements();) {
String cid = (String)e.nextElement();
ZZCell c = space.getCellByID(cid);
String content = (String)sd.content.get(cid);
if (sd.cellswithspans.containsKey(cid)) {
c.setSpan(Span.parse(content));
} else {
c.setText(content);
}
}
// Then make the connections
for (Enumeration e = sd.dims.keys(); e.hasMoreElements();) {
String dname = (String)e.nextElement();
// we ignore d.cellcreation
if (dname.equals("d.cellcreation")) continue;
Hashtable dim = (Hashtable)sd.dims.get(dname);
for (Enumeration f = dim.keys(); f.hasMoreElements();) {
String cid = (String)f.nextElement();
String did = (String)dim.get(cid);
ZZCell c = space.getCellByID(cid);
ZZCell d = space.getCellByID(did);
c.connect(dname, d);
}
}
space.commit();
ZZLogger.log("Done.");
SafeExit.exit(0);
}
if (dump) {
PrintWriter pw = new
PrintWriter(new FileOutputStream(argv[cur]
+ ".dmp", false));
SpaceDump.dump(pw, space);
pw.flush();
pw.close();
ZZLogger.log("Done.");
SafeExit.exit(0);
}
if (ztpserv && ztpport > 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<dims.length;s++) p(dims[s]);
// *** Start client
// ZZCell clientcell = space.getHomeCell().findText(
// "d.2",1,"ClientCell");
// if(clientcell==null)
// throw new ZZError("No client cell found on d.2!!");
// ZZCell dimlist = ZZDefaultSpace.findDefaultDimlist(home);
// ZZSimpleClient2 cli = new ZZSimpleClient2(clientcell,
// dimlist, dimlist);
// *** Initialize ZZWindows
if(pda) {
pa("PDA mode: Creating root window.");
Container c=new Window((Frame)null);
c.setLocation(0,0);
c.setSize(320,240);
c.setVisible(true);
ZZWindows.init(space,c);
} else ZZWindows.init(space,null);
// Make sure no undo to before start.
space.commit();
} catch(Throwable e) {
ZZLogger.exc(e, "In main");
}
ZZObsTrigger.runObsQueue();
p("Main exiting - on to the events..");
}
/** Convert a space from older client to be compatible with the current
* form. Classes org.gzigzag.transform.Version[number] will be used
* one after another until the current version is reached.
* @param fileversion Version of loaded space
* @param zzclientversion Version of current client
* @param s The space to be converted
*/
static void convert(int fileversion, int zzclientversion, ZZSpace s) {
try {
org.gzigzag.transform.VersionChanger vchg;
System.out.println("Converting space to current version:");
while(fileversion < zzclientversion) {
vchg = (org.gzigzag.transform.VersionChanger)
(Class.forName(
"org.gzigzag.transform.Version"+fileversion)
).newInstance();
fileversion = vchg.changeVersion(s);
}
System.out.println("Conversion done, new file version "+zzclientversion+".");
} catch (Exception e) {
e.printStackTrace();
System.out.println(e);
}
}
static void quit(String msg) {
System.out.println(msg);
SafeExit.exit(5);
}
}

185
Java/Makefile Normal file
View File

@@ -0,0 +1,185 @@
# This Makefile requires GNU make.
# IF YOU HAVE TROUBLE COMPILING, JUST REMOVE SOME MODULES
# AND GREEK CLANGS FIRST.
#
# Modules
# - which modules (directories in ../Modules) to compile in
#
MODULES=applet mbox joystick test 3d xml extern prez \
textcloud daytimedemo hypergenealogy nile notemap \
benchmark zaubertrank mind \
$(EXTRA)
#
# Clangs
# - which clangs (directories in clang/) to compile in
#
GREEKCLANG=heraclitus flowing #thales
# (flowing's not a GREEK clang really, but make doesn't care...)
#
# Architectures
# - which architecture-dependent code to compile
# (directories in arch/)
# ARCH=
# Default: none - set on command line.
# Put here the shell argument line to generate the build tag for the
# window title
BUILD_TAG := $(shell echo "Custom CVS Build `date -u +%Y-%m-%dT%H:%M:%SZ` by `whoami`@`hostname`")
# NOT COMPILED BY DEFAULT:
# sound xml applet
# It would be nice to use standard paths !
#
#JAVA_LIB=/usr/local/java/lib
JAVA_DOC=/usr/local/java/docs/api
JAVADOCOPTS=-use -version -author -windowtitle "GZigZag Java API"
TEMP=/tmp
ZOB:=$(wildcard *.zob) $(wildcard */*.zob) \
$(foreach module,$(MODULES),$(wildcard ../Modules/$(module)/*.zob)) \
$(foreach clang,$(GREEKCLANG),$(wildcard clang/$(clang)/*.zob) $(wildcard clang/$(clang)/*/*.zob)) \
$(foreach arch,$(ARCH),$(wildcard arch/$(arch)/*.zob))
ifeq ($(findstring ztp, $(MODULES)),ztp)
ZOB += $(wildcard ../Modules/ztp/*/*.zob)
endif
AUTOGENSRC := clang/ZZClangOps.java $(ZOB:.zob=.java) storage/Recs.java
AUTOGENERATED := $(AUTOGENSRC)
%.java: %.zob zob2java.pl ; perl zob2java.pl $< $@
# Can't add ZZClangOps since javac complains of doubly defined class...
# maybe should use uniq?
SRC0:=$(wildcard *.java) $(wildcard media/*.java) $(wildcard clang/*.java) \
$(wildcard storage/*.java) $(wildcard errors/*.java) \
$(wildcard flob/*.java) $(wildcard transform/*.java) \
$(wildcard part/*.java) \
$(foreach module,$(MODULES),$(wildcard ../Modules/$(module)/*.java)) \
$(foreach clang,$(GREEKCLANG),$(wildcard clang/$(clang)/*.java) $(wildcard clang/$(clang)/*/*.java)) \
$(foreach arch,$(ARCH),$(wildcard arch/$(arch)/*.java)) \
$(AUTOGENSRC)
ifeq ($(findstring ztp, $(MODULES)),ztp)
SRC0 += ../Modules/ztp/*/*.java
endif
SRC:=$(shell echo $(SRC0) | perl -pe 's/\s+/\n/g' - | sort | uniq | tee /tmp/foo)
jikes := $(shell which jikes)
# DEBUG=-g
ifeq (,$(JAVAC))
ifneq (,$(jikes))
JAVAC=jikes +P
else
JAVAC=javac
endif
endif
JAVANCSS=/BIG/javancss9.24/javancss
archcompile = set -e; for d in "$(ARCH)"; do if [ -e arch/$(ARCH)/arch.mk ] ; then $(MAKE) -f arch/$(ARCH)/arch.mk; fi; done
archclean = set -e; for d in "$(ARCH)"; do if [ -e arch/$(ARCH)/arch.mk ] ; then $(MAKE) -f arch/$(ARCH)/arch.mk clean; fi; done
# all must compile everywhere
all: $(SRC)
@echo "*** NOTE: YOU MAY HAVE TO RUN 'make' MORE THAN ONE TIME"
@echo "*** TO GET EVERYTHING TO COMPILE DUE TO DEPENDENCIES"
rm -f BuildInfo.java
sed 's/@@@@@/$(BUILD_TAG)/' BuildInfo.java.in > 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|</h1>|"</h1>".`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-ccn >ncss-ncss
sort -rnk4 -k1 <ncss-ccn >ncss-jvdc
# $(JAVANCSS) -all $(SRC) >ncss

40
Java/NullZOb.java Normal file
View File

@@ -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 <code>module</code> of this type.
* <p>
* 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; }
}

9
Java/Package.html Normal file
View File

@@ -0,0 +1,9 @@
<!-- To be inserted to the javadocced source by Perl -->
This package (name will probably change later) is the current home
of the GZigZag Java classes.
<p>
Start from ZZCell, ZZEdit and ZZObs.
<p>
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.

146
Java/README Normal file
View File

@@ -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

41
Java/RString.java Normal file
View File

@@ -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);
}

95
Java/SafeExit.java Normal file
View File

@@ -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);
}
}

122
Java/ScalableFont.java Normal file
View File

@@ -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;
}
}

37
Java/SoundObs.java Normal file
View File

@@ -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);
}

164
Java/SpaceDump.java Normal file
View File

@@ -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");
}
}

44
Java/SysLogger.java Normal file
View File

@@ -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);
}
}

155
Java/TODO Normal file
View File

@@ -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.

53
Java/TestSpace.java Normal file
View File

@@ -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);
}
}

155
Java/TimeTest.java Normal file
View File

@@ -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<nrounds; i++)
home.N("d.3", 1);
}
},
instest = new Test() { { name = "Insert"; }
public void test(ZZCell home, int nrounds) {
ZZCell c = home;
for(int i=0; i<nrounds; i++) {
c = c.s("d.3", 1);
home.insert("d.4", 1,c);
}
}
},
delneightest = new Test() { { name = "Delete"; }
public void test(ZZCell home, int nrounds) {
for(int i=0; i<nrounds; i++)
home.s("d.3", 1).delete();
}
},
neigh1test = new Test() { { name = "Neigh1"; }
public void test(ZZCell home, int nrounds) {
for(int i=0; i<nrounds; i++)
home.s("d.3", 1);
}
},
neigh2test = new Test() { { name = "Neigh2"; }
public void test(ZZCell home, int nrounds) {
for(int i=0; i<nrounds; i++)
home = home.s("d.3", 1);
}
},
cont1test = new Test() { { name = "Cont1"; }
public void test(ZZCell home, int nrounds) {
ZZCell c = home.s("d.3", 1);
for(int i=0; i<nrounds; i++)
c.setText("Blah");
}
},
cont2test = new Test() { { name = "Cont2"; }
public void test(ZZCell home, int nrounds) {
ZZCell c = home;
for(int i=0; i<nrounds; i++)
(c=c.s("d.3", 1)).setText("Blah");
}
};
static void p(String s) { System.out.println(s); }
static void pn(String s) { System.out.print(s); }
public static void test(ZZSpace[] sp, Test[] tsts, boolean warmup )
throws Exception{
p("Testing...");
int nrounds = 8;
long[][][] times = new long[sp.length][nrounds][tsts.length];
for(int iSpace = 0; iSpace < sp.length; iSpace++)
{
ZZCell home = sp[iSpace].getHomeCell();
for(int i = 0; i < nrounds; i++)
{
// Creating cells
for(int tst = 0; tst < tsts.length; tst++) {
long t0 = System.currentTimeMillis();
tsts[tst].test(home, (warmup ? 1 : 1000));
times[iSpace][i][tst] = System.currentTimeMillis() - t0;
}
}
p(""+sp[iSpace]);
for(int tst=0; tst<tsts.length; tst++) {
pn(" "+tsts[tst].name+"\n\t");
long tot = 0;
for(int i=0; i<nrounds; i++) {
tot += times[iSpace][i][tst];
pn(times[iSpace][i][tst]+"\t");
}
p("==\t"+(tot / nrounds));
}
}
}
public static void main(String[] argv) {
try {
File f1 = new File("/tmp/zztimetst"+Math.random());
File f2 = new File("/tmp/zztimetst"+Math.random());
ZZSpace spaces [] = new ZZSpace[] {
new ZZCacheDimSpace(new DirStreamSet(f1)),
};
for(int i=0; i<spaces.length; i++)
ZZDefaultSpace.create(spaces[i].getHomeCell());
Test[] tsts = new Test[] {
newtest,
instest,
neigh1test,
neigh2test,
cont1test,
cont2test,
delneightest
};
test(spaces, tsts, true);
test(spaces, tsts, true);
test(spaces, tsts, true);
test(spaces, tsts, false);
} catch(Exception e)
{
e.printStackTrace();
System.out.println(e);
}
System.exit(0);
}
}

220
Java/UndoList.java Normal file
View File

@@ -0,0 +1,220 @@
/*
UndoList.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;
/** An operation on the write-cache list that can be undone
* or committed.
* At commit time, the operations are traversed in reverse order
* so that the committables can remove unnecessary ones from the list.
* Commit time may need the undoables to be informed prior to beginning
* and definitely after committing.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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);
}
}

39
Java/ZOb.java Normal file
View File

@@ -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 <code>zob2java.pl</code>.
*/
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);
}

207
Java/ZTPCommand.java Normal file
View File

@@ -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;
}
}

231
Java/ZZCanvasView.java Normal file
View File

@@ -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;
}
}

719
Java/ZZCell.java Normal file
View File

@@ -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.
* <p>
* There is no unique cell to Java object mapping, so there may be
* several equivalent Java objects representing the same cell.
* Use the <b>equals</b> 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 <I>may</I> 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.
* <p>
* 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 <em>and</em> 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<r.length; i++) {
r[i] = (ZZCell)v.elementAt(i);
}
return r;
}
}
/** Returns the text contained in the cell.
* A null return means that the cell has been deleted.
*/
public String getText() { return getText(null); }
public abstract String getText(ZZObs o);
/** Returns the stable media reference in the cell.
* A null return means either that the cell has been deleted
* or that the text inside is not a reference.
* @param lang The requested language.
*/
public Span getSpan() { return getSpan(null); }
public abstract Span getSpan(ZZObs o);
/** Returns the names of the dimensions on which this cell
* is connected. XXX May be subject to change.
*/
public abstract String[] getRankNames();
/** Returns an array containing all connections leaving this cell. */
public ZZConnection[] getConns()
{
String[] dims = getSpace().dims();
int dn = dims.length;
Vector conns = new Vector();
ZZCell c;
for(int di = 0;di<dn;di++) {
for(int d=-1;d<=1;d+=2) {
c = s(dims[di], d);
if(c!=null)
conns.addElement(new ZZConnection(this, dims[di], d, c));
}
}
ZZConnection[] ret = new ZZConnection[conns.size()];
for(int i = 0;i<conns.size();i++)
ret[i] = (ZZConnection)conns.elementAt(i);
return ret;
//JDK1.2 return (ZZConnection[])(conns.toArray(new ZZConnection[conns.size()]));
}
/** Tests whether this cell is the same as another cell.
* There may be more than one Java object representing the same cell
* so it is important to use this method instead of the '==' operator
* to test for equality.
*/
public abstract boolean equals(Object c);
public abstract int hashCode();
/** Reads a rankful of cells and returns an array.
* @param dim The dimension along which to read the rank
* @param dir The direction in which to read the rank.
* @param includeThis Whether to include this
* A convenience function to allow the developer to grab
* a whole rank in an array, starting at the current cell.
* Thus, in a rank A-B-C-D-E, calling C.readRank(d.1, 1, false)
* yields D-E, and so on.
*/
public ZZCell[] readRank(String dim, int dir, boolean includeThis) {
return readRank(dim, dir, includeThis, null);
}
/** Reads a rankful of cells and returns an array.
* @param dim The dimension along which to read the rank
* @param dir The direction in which to read the rank.
* @param includeThis Whether to include this
* @param o An observer to attach to all the cells
* A convenience function to allow the developer to grab
* a whole rank in an array, starting at the current cell.
* Thus, in a rank A-B-C-D-E, calling C.readRank(d.1, 1, false)
* yields D-E, and so on.
*/
public ZZCell[] readRank(String dim, int dir, boolean includeThis,
ZZObs o) {
synchronized(getSpace()) {
LoopDetector l = new LoopDetector();
ZZCell cur = this;
Vector v = new Vector();
if(!includeThis) {
cur = cur.s(dim, dir, o);
}
while(cur != null) {
v.addElement(cur);
l.detect(cur);
cur = cur.s(dim, dir, o);
}
ZZCell[] r = new ZZCell[v.size()];
for(int i=0; i<r.length; i++)
r[i] = (ZZCell)v.elementAt(i);
return r;
}
}
/** Reads the headcells of a given rank along another
* dimension.
* @param dim The dimension along which to read the rank
* @param dir The direction in which to read the rank.
* @param includeThis Whether to include this
* @param dimh The dimension along which to read the headcells.
* @param dirh The direction in which to read the headcells..
* @param o An observer to attach to all the cells
* A convenience function to grab the headcells of a rank
* in an array. Useful for relcells.
*/
public ZZCell[] readRankHeadcells(String dim, int dir, boolean
includeThis, String dimh, int dirh, ZZObs o) {
synchronized(getSpace()) {
ZZCell[] r = readRank(dim, dir, includeThis, o);
for(int i=0; i<r.length; i++)
r[i] = r[i].getHeadcell(dimh, dirh, o);
return r;
}
}
/** Hops the cell along the dimension.
* This means that all other connections remain the
* same but that this cell changes places in the
* rank given by the dimension.
* This operation may be given interesting meanings when e.g.
* hopping over the end of a rank.
* @param dim The dimension to hop along
* @param count The number of places to hop. May be negative,
* in which case the cell will hop negwards.
*/
public abstract void hop(String dim, int count);
// {
// synchronized(getSpace()) {
// ZZCell n = s(dim, dir);
// if(n==null) return;
// n.insert(dim, dir, this);
// }
// }
/** Obtain a global ID for this cell.
* Global IDs will likely play an important rule in the future
* but currently they have no specific use.
* <p>
* 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 <code>'53' (Text in cell)</code>.
*/
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.
* <p>
* 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 <pre> c.getSpan() != null </pre>.
* @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 ) { }
}

81
Java/ZZCellHandle.java Normal file
View File

@@ -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.
* <p>
* The parts marked <b>EXPERIMENTAL</b> 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 <em>is</em> 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;
/** <b>EXPERIMENTAL:</b> the part of the space that this cell is in.
*/
public final ZZSpacePart part;
/** <b>EXPERIMENTAL:</b> 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();
}
}

84
Java/ZZCommand.java Normal file
View File

@@ -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.
* <p>
* 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).
* <p>
* 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;
}
}

62
Java/ZZConnection.java Normal file
View File

@@ -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;
}
}

70
Java/ZZCursor.java Normal file
View File

@@ -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();
}
}

367
Java/ZZCursorReal.java Normal file
View File

@@ -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 <code>d.cursor-cargo</code>: if
* the cell is already connected negwards on <code>d.cursor</code> or
* <code>d.cursor-list</code>,
* no cursor cargo cell is created, otherwise it is.
* <p>
* 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;
}
}
}
}
}

61
Java/ZZCursorVirtual.java Normal file
View File

@@ -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; }
}

1087
Java/ZZDefaultSpace.java Normal file

File diff suppressed because it is too large Load Diff

442
Java/ZZDimSpace.java Normal file
View File

@@ -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, <b>if already created</b>.
* 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<o.length; i++) res[i] = c((String)o[i]);
return res;
}
ZZObsTrigger textTrig = new ZZObsTrigger();
public void invalidateText(String id) {
DimCell dc = c(id);
if (dc == null) {
ZZLogger.log("FIXME: invalidateText called with a nonexistent ID!");
return;
}
// Do nothing now. Maybe?
}
protected Span getSpan(String id) {
return (Span) contents.get(id);
}
protected String getText(String id) {
String s = (String) contents.get(id);
return s;
}
protected void setText(String id, Object ct) {
contents.put(id,ct);
if(spanset != null && ct instanceof Span)
spanset.addSpan((Span)ct, id);
// XXX what if a span content is replaced by a non-span content?!?
// -- for now we can assume span contents don't change (I know
// no span-using code that does) but later, we'll need that?
}
/** A ZZCell in the dimspace representation.
* Interestingly, in this representation the cell is simply
* its identifier and the implicit reference to the surrounding
* ZZDimSpace object.
* <p>
* 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.
* <p>
* 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).
* <p>
* The default version simply returns a new ZZLocalDimension,
* except for d.cellcreation
* <p>
* 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;
}
}

178
Java/ZZDimension.java Normal file
View File

@@ -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.
* <p>
* 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 <b>s, connect and disconnect</b>.
*/
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 <I>steps</I> 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);
}

106
Java/ZZDrawing.java Normal file
View File

@@ -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 <pre>g instanceof Graphics2D</pre>
* would be sufficient but we want to also be able to <em>compile</em>
* 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.
* <p>
* 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.
* <p>
* 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) {
}
}

36
Java/ZZEvObs.java Normal file
View File

@@ -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();
}

58
Java/ZZExec.java Normal file
View File

@@ -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);
}

162
Java/ZZIter.java Normal file
View File

@@ -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;
}
};
}
}

39
Java/ZZKeyBindings.java Normal file
View File

@@ -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);
}

45
Java/ZZKeyBindings0.java Normal file
View File

@@ -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 { }

319
Java/ZZKeyBindings1.java Normal file
View File

@@ -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 <em>not</em> 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();
}
}
}

105
Java/ZZKeyHacks.java Normal file
View File

@@ -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.
* <p>
* 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(); }
}

View File

@@ -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);
}
}

83
Java/ZZLogger.java Normal file
View File

@@ -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);
}
}

91
Java/ZZModule.java Normal file
View File

@@ -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 <code>module</code> of this type.
* <p>
* 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 <b>module</b> 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;
}
}

36
Java/ZZObs.java Normal file
View File

@@ -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();
}

196
Java/ZZObsTrigger.java Normal file
View File

@@ -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.
* <p>
* First of all, there is a key for every object that this
* gob's <code>obs</code> has been <code>addObs</code>'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 <strong>this gob</strong>.
* That may seem odd until you realize that 1) hashtables can't
* store nulls, and 2) <code>this</code> 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
* <em>all</em> 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<allTrigs.size(); i++)
((ZZObsTrigger)allTrigs.elementAt(i)).rmObs(obs);
}
return true;
}
/** Called to add an observer.
*/
public synchronized void addObs(Object o, ZZObs obs) {
Object go = gobs.get(obs);
Gob g;
if(go==null) {
gobs.put(obs, g = new Gob());
g.obs = obs;
} else {
g = (Gob)go;
}
if(g.next.get(o) != null) return; // Already observing.
Gob t = (Gob)trigs.get(o);
trigs.put(o, g);
if(t==null) g.next.put(o,g); // First observer for this object.
else {
g.next.put(o,t);
t.prev.put(o,g);
}
}
/** Called to remove observers.
*/
public synchronized void rmObs(ZZObs obs) {
Gob g = (Gob)gobs.get(obs);
if(g == null) return; // Wasn't observing anything
gobs.remove(obs);
for(Enumeration e = g.next.keys(); e.hasMoreElements(); ) {
Object o = e.nextElement();
Gob ng = (Gob)g.next.get(o);
Gob pg = (Gob)g.prev.get(o);
if(pg==null) {
if(ng==g) trigs.remove(o);
else {
trigs.put(o,ng);
ng.prev.remove(o);
}
} else {
if(ng==g) pg.next.put(o,pg);
else {
pg.next.put(o,ng);
ng.prev.put(o,pg);
}
}
}
}
/** Does the actual triggering.
* XXX We must continue triggering until no new triggers are created,
* which is bad if there are lots of (or infinite amount, in case of a
* bug) triggers. This is because we must run triggers in the AWT event
* processing thread (+), and unless we use JDK 1.2 "EventQueue.invoke*()"
* methods or resort to some horrid dummy-event kludge, we can't expect
* any triggers we leave behind to be triggered until the next AWT event,
* which is unacceptable. ("- See, it doesn't display the new info if I
* don't move the mouse around! - Are you *sure* it isn't a M$ product?")
* This isn't a real problem at the moment, though.
*
* (+) The event thread must always be runnable, or we risk a deadlock,
* and most of ZZ structure -using code isn't thread-safe => 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);
}
}

202
Java/ZZPath.java Normal file
View File

@@ -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.
* <pre>
* STEP dim n
* HEAD dim dir
* END dim dir
* FIND dim dir str
* </pre>
* 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.
* <p>
* "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<arr.length; i++) {
n = arr[i].apply(n, o);
if(n==null) {
String s = "Couldn't find through ";
for(int j=0; j<i; j++)
s += arr[j];
s += " Failed: ";
s += arr[i];
p(s);
if(!error)
return null;
throw new ZZError(s);
}
}
return n;
}
public ZZCell readFrom(ZZCell from, boolean error) {
return readFrom(from, error, null);
}
// XXX ??? A little odd down from here...
// but basically right: ZZPath is immutable.
/** Sign gives the direction on dim, absolute value
* number of steps */
ZZPath step(final String dim, final int n) {
return appendOp(new PathOp() {
public ZZCell apply(ZZCell from, ZZObs o) {
return from.s(dim, n, o);
}
public String toString() {
return "step("+dim+","+n+")";
}
});
}
ZZPath headcell(final String dim, final int dir) {
return headcell(dim, dir, false);
}
ZZPath headcell(final String dim, final int dir, final boolean ensuremove) {
return appendOp(new PathOp() {
public ZZCell apply(ZZCell from, ZZObs o) {
return from.h(dim, dir,
ensuremove, o);
}
public String toString() {
return "headcell("+dim+","+dir+","
+ensuremove+")";
}
});
}
ZZPath untilstring(final String dim, final int dir, final String str)
{
return appendOp(new PathOp() {
public ZZCell apply(ZZCell from, ZZObs o) {
return from.findText(dim, dir, str, o);
}
public String toString() {
return "untilstring("+dim+","+dir+",'"+str+"')";
}
});
}
ZZPath copy() {
ZZPath n = new ZZPath();
n.arr = new PathOp[arr.length];
System.arraycopy(arr, 0, n.arr, 0, arr.length);
return n;
}
ZZPath appendOp(PathOp p) {
ZZPath n = new ZZPath();
n.arr = new PathOp[arr.length + 1];
System.arraycopy(arr, 0, n.arr, 0, arr.length);
n.arr[arr.length] = p;
return n;
}
}

102
Java/ZZPhotoView.java Normal file
View File

@@ -0,0 +1,102 @@
/*
ZZPhotoView.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
* Patched to work with ZZViewComponend format by Jarkko Laine
*/
package org.gzigzag;
import java.awt.*;
import java.net.*;
import java.awt.event.*;
/** A simple view showing photos from the cursor.
* This view shows the image at the URL on the end of d.photo from
* the cell the cursor this view is associated with is on.
*/
public class ZZPhotoView extends ZZViewComponent {
public static final String rcsid = "$Id: ZZPhotoView.java,v 1.14 2000/11/01 08:12:48 tjl Exp $";
ZZCell cursor;
public ZZPhotoView(ZZCell viewCell0) {
super(viewCell0);
}
URL cur;
Image img;
public boolean reraster() { return false; }
public void paintInto(Graphics g) {
// Clear the area
Dimension thisd = getSize();
Color bg = getBackground();
g.setColor(bg);
Insets ins = getInsets();
g.fillRect(ins.left, ins.top, thisd.width-ins.left-ins.right, thisd.height-ins.top-ins.bottom);
g.setColor(Color.black);
// Let's try it like this.. Is this a bad way of doing this?
cursor = ZZCursorReal.get(viewCell);
// If the current cell has no neighbours in the
// photo dimention..
if(cursor == null ||
cursor.s("d.photo", 1) == null)
{
Color c = Color.black;
g.setColor(c);
// For some weird reason, I can't get the drawStrings to work.... Jarkko
g.drawString("No photo for this cell", 0, 0);
return;
}
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);
}
}
}

1381
Java/ZZPrimitiveActions.java Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -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.");
}
}

45
Java/ZZRODimension.java Normal file
View File

@@ -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.
}
}

74
Java/ZZScene.java Normal file
View File

@@ -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);
}

116
Java/ZZSlicedDimSpace.java Normal file
View File

@@ -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; i<slices.length; i++)
dims[i] = slices[i].d(s);
if(s.equals("d.cursor")) return new SlicedCursor(this, dims, "d.preflets");
return new Sliced(this, dims);
}
// We delegate scroll creation to s.0
// XXX Should scrolls be created to slices?
public StringScroll getStringScroll() {
return slices[0].getStringScroll();
}
public StringScroll getStringScroll(String name) {
return slices[0].getStringScroll(name);
}
}
*/

319
Java/ZZSpace.java Normal file
View File

@@ -0,0 +1,319 @@
/*
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 and Tuukka Hastrup
*/
/*
* `He's got a good memory, you've got to grant him that,' said
* Didactylos. `Show him some more scrolls.'
* `How will we know he's remembered them?' Urn demanded, unrolling
* a scroll of geometrical theorems. `He can't read! And even if he
* could read, he can't write!'
* `We shall have to teach him.'
* - Terry Pratchett, Small Gods, p.214
*/
package org.gzigzag;
import java.util.*;
/** A simple ZZ interface for a ZZ space.
* This abstract class defines all the elementary operations
* for a ZZ space. Note though, that many operations are done to
* <b>cells</b> and are defined in ZZCell.java.
* <p>
* 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.
* <p>
* 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)
* <p>
* 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 <b>this synchronization may change in the future
* to a pair of freeze and thaw method calls</b>.
*/
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 <I>may not</I> 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 <I>may</I> 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 <I>may</I> 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<dims.size();i++)
ret[i] = (String)dims.elementAt(i);
return ret;
// return (String[])(dims.toArray(new String[dims.size()]));
}
// OBSERVING
/** Freeze the space. No events are dispatched while
* the space is frozen.
*/
public void freeze() { }
/** Thaw the space. No events are dispatched while
* the space is frozen.
*/
public void thaw() { }
/** Remove all the cells from the observation list of this observer */
abstract public void rmAllObs(ZZObs o);
// VARIOUS
/** Is this space readonly? FIXME: not used here */
public /* final */ boolean readonly;
public ZZSpace() { this(false); }
public ZZSpace(boolean readonly) {
this.readonly = readonly;
}
/** Finds the headcells of all ranks on dim
* that are longer than one cell in length */
public abstract ZZCell[] findLongRankHeads(String dim);
// HANDLING OF MASTER DIM LIST
/** Called when a new dimension is instantiated. It might be here already,
* however, as dimensions are instantiated again when the space is loaded
* from disk.
* @return true iff dimension was truly new
*/
protected boolean updateMasterDimList(String newdim) {
if(!validDim(newdim))
return false;
ZZCell p = getHomeCell().s(d.masterdim, 1);
while(p!=null) {
if(p.getText().equals(newdim))
return false;
p = p.s(d.masterdim, 1);
}
ZZCell c = getHomeCell().N(d.masterdim, 1);
c.setText(newdim);
return true;
}
/** Recreate the master dimension list. */
public void recreateMasterDimList() {
throw new ZZError("recreateMasterDimList not implemented for this space");
}
/** Returns an enumeration of posward
* connections on this dimension.
* XXX Should change to be just ZZCells!!!
*/
public Enumeration posconns(String dim) {
class ConnEnum implements Enumeration {
public ConnEnum(String dim) {
this.dim = dim;
next = findNext();
}
String dim;
Enumeration cells = cells();
ZZConnection next;
public boolean hasMoreElements() {
if(next != null)
return true;
else
return false;
}
public Object nextElement() {
if(next == null)
throw new NoSuchElementException();
ZZConnection ret = next;
next = findNext();
return ret;
}
public ZZConnection findNext() {
while(cells.hasMoreElements()) {
ZZCell c1 = (ZZCell) cells.nextElement();
ZZCell c2 = c1.s(dim, 1);
if(c2 != null)
return new ZZConnection(c1, dim, 1, c2);
}
return null;
}
}
return new ConnEnum(dim);
}
/** Whether a dimension name is acceptable.
*/
public boolean validDim(String d) {
if(d==null) return false;
if(d.equals("")) return false;
return true;
}
/** Class Dims acts as a structure containing concrete string representation
* of the special dimensions. It's not static so it can vary
* between spaces. Also, these strings could be initialized in the
* constructor to allow runtime setting.
* <p>
* 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();
}

95
Java/ZZSpacePart.java Normal file
View File

@@ -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;
/** <b>EXPERIMENTAL:</b> 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.
* <p>
* 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.
* <p>
* 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() {}
}

106
Java/ZZTextView.java Normal file
View File

@@ -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.)
* <p>
* 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;
}
}

43
Java/ZZTraverseCB.java Normal file
View File

@@ -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();
}

253
Java/ZZUpdateManager.java Normal file
View File

@@ -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;
}
}

575
Java/ZZUtil.java Normal file
View File

@@ -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<strs.length; i++) {
if(i!=0 || !incStart) start = start.N(dim, 1);
start.setText(strs[i]);
}
}
/** Set a number of integers onto a rank.
* Overwrites existing cells and creates new for the rest.
*/
static public void putInts(ZZCell start, String dim, boolean incStart,
int[] ns) {
for(int i=0; i<ns.length; i++) {
if(i!=0 || !incStart) start = start.getOrNewCell(dim, 1);
start.setText(""+ns[i]);
}
}
/** Get a number of strings from a rank.
*/
static public String[] getStrings(ZZCell start, String dim,
boolean incStart,
int nmin, int nmax, ZZObs obs) {
String[] r = new String[nmax];
int i=0;
for(; i<nmax; i++) {
if(i!=0 || !incStart) {
start = start.s(dim, 1, obs);
if(start == null) {
if(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<r.length; i++) {
p("GetI: "+s[i]);
r[i] = Integer.parseInt(s[i]);
}
return r;
}
static public int[] getInts(ZZCell start, String dim, boolean incStart,
int nmin, int nmax) {
return getInts(start,dim,incStart,nmin,nmax,null);
}
/** Mix two colors at a given fraction.
* 0 = c1, 256 = c2.
*/
static public Color mix(Color c1, Color c2, int fract) {
if(fract < 0) fract = 0;
if(fract > 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<objs.length; i++) {
if(objs[i] instanceof String)
(prev = prev.N(pdim, 1)).setText((String)objs[i]);
else {
tmp = ((ZZCell)objs[i]).N("d.clone", 1);
prev.connect(pdim, 1, tmp);
prev = tmp;
}
}
return cur;
}
static public ZZCell appendCommand(ZZCell cur, Object[] objs) {
return appendCommand(cur, "d.2", "d.1", objs);
}
static private Clipboard getPUIClipboard() {
return Toolkit.getDefaultToolkit().getSystemClipboard();
}
static public void puiCopy(String str) {
p("PuiCOPY '"+str+"'");
Clipboard clipboard = getPUIClipboard();
StringSelection contents = new StringSelection(str);
clipboard.setContents(contents, new ClipboardOwner() {
public void lostOwnership(Clipboard cb, Transferable t) {}
});
}
/** Copy to PUI clipboard.
* Copy a cell's contents to the clipboard of the surrounding PUI.
* There is no corresponding cut function because only the text is
* copied, not the connections, so cut wouldn't delete the cell, but
* only empty its contents; I see no reason for this operation.
* <p>
* 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).
* <p>
* 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<NPTS; i++) {
float d = (i/(float)(NPTS-1));
float dp = d*2 - 1;
float fact = (float)(0.5 + 0.5 * (a*(dp) + b*(dp*dp*dp)));
p(" "+dp+" "+fact);
res[2*i] = (int)(
((1-fact) * (x0 + dx * tense * d)) +
(fact * (x1 - dx * tense * (1-d)))
);
res[2*i+1] = (int)(
((1-fact) * (y0 + dy * tense * d)) +
(fact * (y1 - dy * tense * (1-d)))
);
}
return res;
}
/** Move a point in a direction and return new point. */
static public Point movePoint(Point p, int xa, int ya, int dist) {
// XXX use real distance
Point q = new Point(p.x, p.y);
q.x += xa * dist;
q.y += ya * dist;
return q;
}
static public void dumpSubSpace(ZZCell c, String[] dims) {
// XXX VERY naive.
Hashtable done = new Hashtable();
Stack stk = new Stack();
stk.push(c);
while(!stk.empty()) {
ZZCell cur = (ZZCell)stk.pop();
if(cur == null) continue;
if(done.get(cur) != null) continue;
done.put(cur, cur);
System.out.println("C: "+cur);
for(int i=0; i<dims.length; i++) {
System.out.println(" + "+dims[i]+"\t"+cur.s(dims[i]));
System.out.println(" - "+dims[i]+"\t"+cur.s(dims[i], -1));
stk.push(cur.s(dims[i]));
stk.push(cur.s(dims[i], -1));
}
}
}
}

63
Java/ZZView.java Normal file
View File

@@ -0,0 +1,63 @@
/*
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 view on the structure.
* This class is mostly to work with ZZUpdateManager which tells these
* classes to repaint themselves in response to changes in the structure
* (expose events are separate and handled inside the classes themselves).
* <p>
* 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.
* <p>
* 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();
}

287
Java/ZZViewComponent.java Normal file
View File

@@ -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);
}
}

231
Java/ZZWindows.java Normal file
View File

@@ -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();
}
}

View File

@@ -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))
);
}
}
}

View File

@@ -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 <b>tools.jar</b> 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<lists.length; i++) {
listpws[i] = new PrintWriter(new FileWriter(
new File(outdir, lists[i][2])));
}
ClassDoc[] classes = root.classes();
for(int i=0; i < classes.length; i++) {
ClassDoc[] ifaces = classes[i].interfaces();
boolean iszob = false;
for(int j=0; j<ifaces.length; j++) {
if(ifaces[j].qualifiedName().equals("org.gzigzag.ZOb"))
iszob = true;
}
if(!iszob) continue;
String qname = classes[i].qualifiedName();
String filename = qname+".html";
// XXX Modules go wrong. Hmm.. should correct.
String zobname = null;
if(qname.indexOf("org.gzigzag.module.") == 0)
zobname = "."+qname.substring(19);
else if(qname.indexOf("org.gzigzag.") == 0)
zobname = qname.substring(12);
else
zobname = qname;
for(int j=0; j<ifaces.length; j++) {
for(int l=0; l<lists.length; l++) {
if(ifaces[j].qualifiedName().equals(lists[l][0])) {
listpws[l].println(filename);
}
}
}
// Now we have the zob.
// System.out.println(classes[i].qualifiedName());
PrintWriter pr = new PrintWriter(
new FileWriter(new File(outdir, filename)));
printDoc(zobname, pr, classes[i]);
pr.close();
}
for(int i=0; i<lists.length; i++) {
listpws[i].close();
}
} catch(Exception e) {
ZZLogger.exc(e);
return false;
}
return true;
}
public static int optionLength(String opt) {
if(opt.equals("-d"))
return 2;
return 0;
}
public void readOptions(String[][] options) {
for (int i = 0; i < options.length; i++) {
String[] opt = options[i];
if (opt[0].equals("-d")) {
outdir = opt[1];
}
}
}
public void printDoc(String zobname, PrintWriter pw, ClassDoc cl) {
pw.println("<H1>"+zobname+"</H1>");
pw.println("<H2 id=\"descr\">Description</H2>");
pw.println(cl.commentText());
// System.out.println(cl.commentText());
pw.println("<H2 id=\"params\">Structural parameters</H2>");
FieldDoc[] fields = cl.fields();
for(int i=0; i<fields.length; i++)
printField(pw, fields[i]);
pw.flush();
}
public void printField(PrintWriter pw, FieldDoc f) {
Tag[] tg = f.tags();
boolean str = false;
for(int i=0; i<tg.length; i++) {
if(tg[i].name().equals("@structparam")) str = true;
System.out.println("Tag: "+tg[i].name()+" "+tg[i].kind());
}
if(!str) {
System.out.println("Not structparam "+f.name());
return;
}
pw.println("<H3>"+f.name()+"</H3>");
pw.println(f.commentText());
}
}

19
Java/arch/syslog/arch.mk Normal file
View File

@@ -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

View File

@@ -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 <syslog.h>
/*
* 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);
}

26
Java/check.pl Normal file
View File

@@ -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(<F>) {
/^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;
}

130
Java/clang/Data.java Normal file
View File

@@ -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.: <code>
* Data d = new Data("hi", new Integer(17), new Boolean(false));
* </code> can be stored as <code>
* new Data(cell1, cell2, cell3);
* </code> 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:
* <code>
* for(int i=0; i<data.len(); i++)
* cell[i].setText(data.s(i));
* </code>
* (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");
}
}
}
}

186
Java/clang/ZZClang1.java Normal file
View File

@@ -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!
* <p>
* 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<p.length; i++) {
h.put(p[i].h("d.clone", -1), params[i]);
}
p("Call real exec");
exec(c.s("d.2", 1), ctxt, h);
}
*/
Hashtable coords = new Hashtable();
{
coords.put("X", new Integer(1));
coords.put("Y", new Integer(2));
coords.put("Z", new Integer(3));
coords.put("W", new Integer(4));
coords.put("HOME", new Integer(-1));
}
// Implementation of ZZClangContext interface.
public ZZCursor getCursor() { return cursor; }
public ZZCell getViewspex() { return viewspex; }
public Object getSpecial(Object param) { return specials.get(param); }
// XXX Use something like this to get other params as cells / cursors!
/*
if(par==null) {
String s = p[i].getText();
Integer ind = (Integer)coords.get(s);
if(ind!=null) {
if(ind.intValue()==-1)
par = p[i].getSpace().getHomeCell();
else {
par = ctxt.getDim(ind.intValue()).get();
}
}
}
*/
public ZZCell paramAsCell(ZZCell var) {
ZZCell par =
(ZZCell)symtab.get(
var.h("d.clone",-1));
if(par==null) return var;
ZZCell res = ZZCursorReal.get(par);
// If it has an expression on d.2, execute.
ZZCell oc = var.s("d.2", 1);
if(oc==null)
return res;
// save cursor
ZZCursor tmp = cursor;
try {
cursor = new ZZCursorVirtual(res);
exec(oc);
res = cursor.get();
} finally {
cursor = tmp;
}
return res;
}
public ZZCursor paramAsCursor(ZZCell var) {
ZZCell par =
(ZZCell)symtab.get(
var.h("d.clone",-1));
if(par==null) return null;
ZZCell oc = var.s("d.2", 1);
if(oc != null)
throw new ZZError("Can't have a cursor with an expression");
return new ZZCursorReal(par);
}
public void execParam(ZZCell param) {
exec(param);
}
Hashtable funcs = new Hashtable();
/** WILL BE DEPRECATED. */
public void addOp(ZZClangOp op) {
p("Addop "+op.name());
funcs.put(op.name(), op);
}
// public void
}

View File

@@ -0,0 +1,95 @@
/*
ZZClangContext.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 context object for Clang.
* Mostly corresponds to a viewspecs: has a viewCell,
* a cursor and other stuff.
*
* <p>
* 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!
* <p>
* 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,
* <pre>
* clangcontext.getCursor() == ZZCursorReal(clangcontext.getViewcell())
* </pre>
* 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);
}

View File

@@ -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<n && d!=null; d=d.s("d.dims", 1)) {}
if(d==null) return null;
return new ZZCursorReal(d);
}
public ZZCell getViewcell() { return viewCell; }
public ZZClangContext getSubcontext(ZZCell startCursor) {
return new ZZClangContextVirtual(this, startCursor);
}
}
*/

View File

@@ -0,0 +1,60 @@
/*
ZZClangContextVirtual.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 EKMVLSVMEVSE {
}
/** A virtual viewspecs -context object for Clang. The main cursor
* is virtualized, the others are still global - XXX IS THIS RIGHT?
*/
/*
public class ZZClangContextVirtual implements ZZClangContext {
String rcsid = "$Id: ZZClangContextVirtual.java,v 1.4 2000/09/19 10:31:58 ajk Exp $";
ZZCursor cursor;
ZZClangContext parent;
ZZClangContextVirtual(ZZClangContext orig, ZZCell start) {
cursor = new ZZCursorVirtual(start);
parent = orig;
}
public ZZCursor getCursor() { return cursor; }
public String getDimString(int n) { return getDim(n).get().getText(); }
public ZZCursor getDim(int n) {
return parent.getDim(n);
}
public ZZCell getViewcell() { return null; }
public ZZClangContext getSubcontext(ZZCell startCursor) {
return new ZZClangContextVirtual(this, startCursor);
}
}
*/

59
Java/clang/ZZClangOp.java Normal file
View File

@@ -0,0 +1,59 @@
/*
ZZClangOp.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 operation for Clang.
* NOT YET FINISHED!
*/
public interface ZZClangOp {
String rcsid = "$Id: ZZClangOp.java,v 1.3 2000/09/19 10:31:58 ajk Exp $";
/** Execute the operation.
* The op is to start at cell c and go poswards on d.1 to find
* its parameters, with which it can call the ctxt object to find
* out the values.
* <p>
* 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();
}

144
Java/clang/ZZClangOps.pl Normal file
View File

@@ -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 <<END;
/*
ZZClangOps.java
*
* GENERATED USING ZZClangObs.pl - DO NOT MODIFY THE JAVA CODE:
* YOUR CHANGES WILL BE OVERWRITTEN. MODIFY THE GENERATING
* PERL CODE IN ZZClangObs.pl instead.
*
* 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.*;
/** Some primitive operations for Clang.
*/
public class ZZClangOps {
public static final String rcsid = "$rcsid";
public static final boolean dbg = false;
static final void p(String s) { if(dbg) System.out.println(s); }
/** Convert a cell to a dimension. */
static final String d(ZZCell c) { return c.getText(); }
END
$exec = " public void exec(ZZCell c, ZZCursor crs, ZZClangContext ctxt) ";
for(
#
# First, operators without side effects, operating just on the given
# cursor
#
[ Step,
2,
q{dim n},
q%
int n = Integer.parseInt($P(n).getText());
String dim = d($P(dim));
ZZCell it = $CURS.get();
it = it.s(dim, n);
$CURS.set(it);
%,
q{steps the cursor n steps (positive or negative) along a dim. },
],
[ Set,
2,
q{cell},
q%
$CURS.set($P(cell));
%,
q{set the cursor cursor to point to cell cell. },
],
# [ Deref,
# 0,
# q{},
# q%
# ZZCursor curs = ctxt.getCursor();
# curs.set(ZZDefaultSpace.getCursor(curs.get()));
# %,
# q{dereference a cursor. },
# ],
[ Connect,
3,
q{cell0 dim cell1},
q%
$P(cell0).connect(d($P(dim)), $P(cell1));
%,
q{connect two cells along dim. },
],
[ Connect2,
3,
q{dim cell1},
q%
$CURS.get().connect(d($P(dim)), $P(cell1));
%,
q{connect the cursor to cells along dim. },
],
) {
$lcname = lc $_->[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 <<END;
$classes
public static ZZClangOp[] getOps1() {
return new ZZClangOp[] {
$ja
};
}
}
END

99
Java/clang/flowing/B.java Normal file
View File

@@ -0,0 +1,99 @@
/*
B.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 "B" (Binary Logic) primitive set for Flowing clang.
*/
public class B extends PrimitiveSet {
public static final String rcsid = "$Id: B.java,v 1.2 2000/10/13 13:52:24 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("AND") || id.equals("&"))
return new And();
if(id.equals("OR") || id.equals("|"))
return new Or();
if(id.equals("NOT") || id.equals("!"))
return new Not();
if(id.equals("XOR"))
return new Xor();
if(id.equals("NOTNULL"))
return new NotNull();
return null;
}
static public class And extends Primitive {
protected Data execute(Data params) {
if(params.len() < 2) miscount();
boolean res = params.b(0);
for(int i=1; i<params.len(); i++) {
res = res && params.b(i);
}
return new Data(new Boolean(res));
}
}
static public class Or extends Primitive {
protected Data execute(Data params) {
if(params.len() < 2) miscount();
boolean res = params.b(0);
for(int i=1; i<params.len(); i++) {
res = res || params.b(i);
}
return new Data(new Boolean(res));
}
}
static public class Not extends Primitive {
protected Data execute(Data params) {
count(params, 1);
boolean res = !params.b(0);
return new Data(new Boolean(res));
}
}
static public class Xor extends Primitive {
protected Data execute(Data params) {
if(params.len() < 2) miscount();
boolean res = params.b(0);
for(int i=1; i<params.len(); i++) {
boolean b = params.b(i);
res = (!res && b) || (res && !b);
}
return new Data(new Boolean(res));
}
}
static public class NotNull extends Primitive {
protected Data execute(Data params) {
count(params, 1);
boolean res = params.o(0) != null;
return new Data(new Boolean(res));
}
}
}

115
Java/clang/flowing/C.java Normal file
View File

@@ -0,0 +1,115 @@
/*
C.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 "C" (Number Crunching) primitive set for Flowing clang.
*/
public class C extends PrimitiveSet {
public static final String rcsid = "$Id: C.java,v 1.2 2000/10/13 13:52:24 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("+"))
return new Plus();
if(id.equals("-"))
return new Minus();
if(id.equals("*"))
return new Mul();
if(id.equals("/"))
return new Div();
if(id.equals("="))
return new Compare(0);
if(id.equals(">"))
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<params.len(); i++) {
res += params.i(i);
}
return new Data(new Integer(res));
}
}
static public class Minus extends Primitive {
protected Data execute(Data params) {
if(params.len() < 2) miscount();
int res = params.i(0);
for(int i=1; i<params.len(); i++) {
res -= params.i(i);
}
return new Data(new Integer(res));
}
}
static public class Mul extends Primitive {
protected Data execute(Data params) {
if(params.len() < 2) miscount();
int res = params.i(0);
for(int i=1; i<params.len(); i++) {
res *= params.i(i);
}
return new Data(new Integer(res));
}
}
static public class Div extends Primitive {
protected Data execute(Data params) {
count(params, 2);
return new Data(new Integer(params.i(0) / params.i(1)));
}
}
static public class Compare extends Primitive {
int weight;
public Compare(int weight) { this.weight = weight; }
protected Data execute(Data params) {
count(params, 2);
int i0, i1;
if(weight > 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));
}
}
}

View File

@@ -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");
}
};
}

View File

@@ -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.
* <p>
* 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).
* <p>
* 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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).
* <p>
* 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!)
* <p>
* 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;
}
}
}

View File

@@ -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.
* <p>
* (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;
}
}
}

View File

@@ -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);
}

View File

@@ -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<arr.length; i++) res[arr.length-i-1] = arr[i];
return res;
}
public Data get(ZZCell c, int dir) {
p("Start getting for "+c.getText()+" ("+c.getID()+")");
ZZCell[] cells = c.readRank("d.1", dir, false);
if(dir<0) cells = reverse(cells);
Object[] result = new Object[cells.length];
p("Getting "+cells.length+" values");
for(int i=0; i<cells.length; i++) {
if(cells[i].s("d.clone", -1) != null) {
p("Getting: " + cells[i].getText());
result[i] = getSingle(cells[i].getRootclone());
if(result[i] == null)
throw new ZZError("Value for " + cells[i].getText() +
" not yet set");
} else {
p("Getting literal");
result[i] = cells[i];
}
p("Got "+result[i]);
}
p("Finish getting");
return new Data(result);
}
public void put(ZZCell c, Data params, int dir) {
p("Start putting for "+c.getText()+" ("+c.getID()+")");
Data pars = params != null ? params : new Data();
ZZCell[] cells = c.readRank("d.1", dir, false);
if(dir<0) cells = reverse(cells);
p("Putting "+cells.length+" values");
if(pars.len() < cells.length)
throw new ZZError("Pars: " + pars.len() +
" < cells: " + cells.length);
for(int i=0; i<cells.length; i++) {
p("Putting: "+pars.s(i)+" into: "+cells[i].getText());
setSingle(cells[i].getRootclone(), pars, i);
}
p("Finish putting");
}
}

View File

@@ -0,0 +1,97 @@
/*
StackFrameReal.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 structural implementation for Flowing Clang stack frames.
*/
public class StackFrameReal extends StackFrame {
String rcsid = "$Id: StackFrameReal.java,v 1.6 2000/11/16 20:33:13 bfallenstein Exp $";
public ZZCell main;
public StackFrameReal(ZZSpace sp) { main = sp.getHomeCell().N(); }
public StackFrameReal(ZZCell main) { this.main = main; }
public StackFrameReal(StackFrameReal caller) {
this(caller.main.N("d.2", 1));
}
public Object getSingle(ZZCell c) {
ZZCell where = main.intersect("d..flowing-frame", 1,
c, "d..flowing-data", 1);
if(where == null) return null;
ZZCell acc = ZZCursorReal.get(where);
if(acc != null) return acc;
else return where;
}
public void setSingle(ZZCell c, Data d, int at) {
ZZCell where = main.intersect("d..flowing-frame", 1,
c, "d..flowing-data", 1);
if(where == null) {
where = main.N("d..flowing-frame", 1);
c.insert("d..flowing-data", 1, where);
}
if(d.o(at) instanceof ZZCell)
ZZCursorReal.setcursor(where, d.c(at));
else {
ZZCursorReal.setcursor(where, null);
where.setText(d.s(at));
}
}
public ZZCell getPos() { return ZZCursorReal.get(main.h("d.2")); }
public void setPos(ZZCell c) { ZZCursorReal.setcursor(main, c); }
public StackFrame call() { return new StackFrameReal(this); }
public boolean parentof(StackFrame sf) {
if(!(sf instanceof StackFrameReal)) return false;
ZZCell find = ((StackFrameReal)sf).main;
for(ZZCell c = main; c != null && c != main; c = c.s("d.2")) {
if(c.equals(find)) return true;
}
return false;
}
public StackFrame ret() {
ZZCell caller = main.s("d.2", -1);
setPos(null);
if(caller != null) {
caller.disconnect("d.2", +1);
return new StackFrameReal(caller);
} else
return null;
}
public void delete() {
ZZCell pos = main;
while(pos != null) {
ZZCell nextrow = pos.s("d.2");
while(pos != null) {
ZZCell next = pos.s("d..flowing-frame");
pos.delete();
pos = next;
}
pos = nextrow;
}
}
public boolean equals(StackFrameReal f) { return main.equals(f.main); }
}

View File

@@ -0,0 +1,63 @@
/*
StackFrameVirtual.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.*;
/** A virtual implementation for Flowing Clang stack frames.
*/
public class StackFrameVirtual extends StackFrame {
String rcsid = "$Id: StackFrameVirtual.java,v 1.5 2000/11/16 20:33:13 bfallenstein Exp $";
Hashtable values = new Hashtable();
static final Object NULL = new Object();
StackFrameVirtual caller = null, called = null;
ZZCell pos;
public StackFrameVirtual() {}
public StackFrameVirtual(StackFrameVirtual frame) { caller = frame; }
public Object getSingle(ZZCell c) {
Object res = values.get(c);
return res == NULL ? null : res;
}
public void setSingle(ZZCell c, Data d, int at) {
values.put(c, d.o(at) == null ? NULL : d.o(at));
}
public ZZCell getPos() { return called == null ? pos : called.getPos(); }
public void setPos(ZZCell c) { pos = c; }
public StackFrame call() { return called = new StackFrameVirtual(this); }
public boolean parentof(StackFrame sf) {
if(called == null) return false;
return (sf == called) || (called.parentof(sf));
}
public StackFrame ret() {
pos = null;
if(caller != null) caller.called = null;
return caller;
}
public boolean equals(StackFrameVirtual frame) { return this == frame; }
}

229
Java/clang/flowing/T.java Normal file
View File

@@ -0,0 +1,229 @@
/*
T.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 "T" (Space Transformation) primitive set for Flowing clang.
*/
public class T extends PrimitiveSet {
public static final String rcsid = "$Id: T.java,v 1.4 2000/10/18 14:35:31 tjl 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("GET"))
return new Get();
if(id.equals("SET"))
return new Set();
if(id.equals("STEP") || id.equals("s"))
return new Step();
if(id.equals("END") || id.equals("h"))
return new End();
if(id.equals("FIND"))
return new Find();
if(id.equals("ORIGINAL"))
return new Original();
if(id.equals("CROSS")) // == intersect
return new Cross();
if(id.equals("HOMECELL"))
return new HomeCell();
if(id.equals("CONNECT"))
return new Connect();
if(id.equals("INSERT"))
return new Insert();
if(id.equals("DISCONNECT"))
return new Disconnect();
if(id.equals("HOP"))
return new Hop();
if(id.equals("NEW") || id.equals("N"))
return new New();
if(id.equals("CLONE"))
return new Clone();
if(id.equals("DELETE"))
return new Delete();
if(id.equals("SAME"))
return new Same();
return null;
}
static public class Get extends Primitive {
protected Data execute(Data params) {
count(params, 1);
return new Data(ZZCursorReal.get(params.c(0)));
}
}
static public class Set extends Primitive {
protected Data execute(Data params) {
count(params, 2);
ZZCursorReal.set(params.c(0), params.c(1));
return null;
}
}
static public class Step extends Primitive {
protected Data execute(Data params) {
if(params.len() < 2 || params.len() > 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;
}
}
}

138
Java/clang/flowing/X.java Normal file
View File

@@ -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<params.len(); i++) {
s = s + params.s(i);
}
return new Data(s);
}
}
static public class Equals extends Primitive {
protected Data execute(Data params) {
count(params, 2);
boolean res = params.s(0).equals(params.s(1));
return new Data(new Boolean(res));
}
}
static public class Len extends Primitive {
protected Data execute(Data params) {
count(params, 1);
return new Data(new Integer(params.s(0).length()));
}
}
static public class Part extends Primitive {
protected Data execute(Data params) {
if(params.len() < 2 || params.len() > 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;
}
}
}

View File

@@ -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);
}
}

View File

@@ -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 :

View File

@@ -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;
}
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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";
}

View File

@@ -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);
}
}

View File

@@ -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(); }
}

View File

@@ -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);
}

4
Java/clang/thales/README Normal file
View File

@@ -0,0 +1,4 @@
This directory contains the reference implementation of Thales Clang.
Talk to Antti-Juhani Kaijanaho <gaia@iki.fi> before making any
nontrivial changes.

View File

@@ -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();
}

Some files were not shown because too many files have changed in this diff Show More