/* ZZPrimitiveActions.java * * Copyright (c) 1999-2001, Ted Nelson, Tuomas Lukka and Vesa Parkkinen * * You may use and distribute under the terms of either the GNU Lesser * General Public License, either version 2 of the license or, * at your choice, any later version. Alternatively, you may use and * distribute under the terms of the XPL. * * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of * the licenses. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README * file for more details. * */ /* * Written by Tuomas Lukka */ package org.gzigzag; import java.util.*; import java.awt.*; /** A really simple mock script engine. * This class is intended for single, fixed commands that are * in reality coded in Java in this file. It is only here so that the Java * client can be used standalone. *

* Even worse, it is string-based: it doesn't hassle you about structure, * it simply takes the string in the cell and executes a corresponding command. *

* The one nifty thing is the module support: * Given a function name like ZZMbox.FOO * it will first dynamically load the class org.gzigzag.module.ZZMbox * (this will later be probably xanadu.zz.module), and run its action * routine (see ZZModule and ZZMbox docs for details). */ public class ZZPrimitiveActions implements ZZExec { public static final String rcsid = "$Id: ZZPrimitiveActions.java,v 1.141.2.8 2002/03/05 18:21:50 bfallenstein Exp $"; public static boolean dbg = false; static final void p(String s) { if(dbg) ZZLogger.log(s); } static final void pa(String s) { ZZLogger.log(s); } public ZZPrimitiveActions() {} public static java.io.PrintWriter textlog; ZZCell findPar(ZZCell view, String param) { ZZCell cur = view.s("d.2", 1); while(cur!=null) { if(cur.getText().equals(param)) return cur.s("d.1", 1); cur = cur.s("d.2", 1); } return null; } int getDimstrAsInt(String param) { if(param.equals("X")) return 0; else if(param.equals("Y")) return 1; else if(param.equals("Z")) return 2; return -1; } String getDim(ZZCell view, String param) { ZZCell c = findPar(view, param); if(c!=null) return c.getText(); int ind=getDimstrAsInt(param); return ZZDefaultSpace.getDimList(view)[ind]; } String D(ZZCell view, String param) { return getDim(view, param); } void exchangeCells(ZZCell view1, ZZCell view2) { String[] ds1 = ZZDefaultSpace.getDimList(view1); String[] ds2 = ZZDefaultSpace.getDimList(view2); Hashtable ds = new Hashtable(); ds.put(ds1[0], ds1[0]); ds.put(ds1[1], ds1[1]); ds.put(ds2[0], ds2[0]); ds.put(ds2[1], ds2[1]); ZZCell c1 = ZZCursorReal.get(view1); ZZCell c2 = ZZCursorReal.get(view2); for(Enumeration e = ds.keys(); e.hasMoreElements(); ) { String d = (String)e.nextElement(); ZZCell n1 = c1.s(d, -1); c1.disconnect(d, -1); ZZCell n2 = c2.s(d, -1); c2.disconnect(d, -1); if(n2 != null) c1.connect(d, -1, n2); if(n1 != null) c2.connect(d, -1, n1); n1 = c1.s(d, 1); c1.disconnect(d, 1); n2 = c2.s(d, 1); c2.disconnect(d, 1); if(n2 != null) c1.connect(d, 1, n2); if(n1 != null) c2.connect(d, 1, n1); } } // Set view cursor void svc(ZZCell view, ZZCell to) { if(to == null || view == null) return; ZZCursorReal.set(view, to); } ZZCell findOtherView(ZZCell view) { ZZCell oth = view.s("d.ctrlview", -1); if(oth == null) oth = view.s("d.ctrlview", 1); if(oth == null) { System.out.println("CNCTPAIR OTHER NOT FOUND"); } return oth; } /** Move the cursor. * @return Whether a timestamp would be reasonable. */ boolean move(ZZCell view, ZZCell viewCursor, String vdim, int dir, ZZCell realView, ZZCell realCtrl) { if ( viewCursor == null ) return false; String[] ss = ZZDefaultSpace.getDirActionWaitingAndClear(view); if(ss!=null) { String s = ss[0]; if(s.equals("CNCTI")) { cnct(view, viewCursor, true, vdim, dir); } else if(s.equals("NEW")) { viewCursor.N(vdim, dir); // } else if(s.equals("NEWANDEDIT")) { // svc(view, viewCursor.N(vdim, dir)); // switchcursmode(view); // XXX Problem: this doesn't switch keybindings mode } else if(s.equals("EXCISE")) { viewCursor.excise(vdim); } else if(s.equals("DISC")) { viewCursor.disconnect(vdim, dir); } else if(s.equals("HOP")) { viewCursor.hop(vdim, dir); } else if(s.equals("CLONE")) { ZZCell clone = ZZCursorReal.get(realView).zzclone(); viewCursor.insert(vdim, dir, clone); } else if(s.equals("CLONECTRL")) { ZZCell clone = ZZCursorReal.get(realCtrl).zzclone(); viewCursor.insert(vdim, dir, clone); } else if(s.equals("CNCTPAIR")) { smartconnect(viewCursor, vdim, dir, ZZCursorReal.get( findOtherView(view))); } else if(s.equals("CNCTC")) { cnctcln(view, viewCursor, true, vdim, dir); } else if(s.equals("CNCT")) { cnct(view, viewCursor, false, vdim, dir); } else if(s.equals("SORTALPH")) { ZZUtil.sortRank(viewCursor, vdim, dir, new ZZUtil.Comparator() { public int compare(ZZCell c1, ZZCell c2) { return c1.getText().compareTo(c2.getText()); } }, true); } else if(s.equals("END")) { svc(view, viewCursor.h(vdim, dir)); } else if(s.equals("MONOCHUG")) { if(ss[1] == null || ss[1].equals("")) { p("Move: "+s+" "+vdim+" "+dir); ZZDefaultSpace.storeDirActionWaiting(view, s); ZZDefaultSpace.storeDirWaiting(view, vdim, dir); return false; } // monochug operation int ddir = (ss[2].equals("+") ? 1 : -1); String ddim = ss[1]; ZZCell targ = viewCursor.s(ddim, ddir); if(targ == null) return false; targ = targ.s(vdim, dir); if(targ == null) return false; if(targ.s(ddim, -ddir) != null) return false; viewCursor.disconnect(ddim, ddir); viewCursor.connect(ddim, ddir, targ); } else if(s.equals("FINDTEXT")) { String tf = ZZDefaultSpace.getInbuf(view.getSpace(), false); if(tf == null || tf.equals("")) return false; for(ZZCell c = viewCursor.s(vdim, dir); c != null && c != viewCursor; c = c.s(vdim, dir)) { if(c.getText().indexOf(tf) >= 0) { svc(view, c); return true; } } } return true; } else { String s = ZZDefaultSpace.getInbuf(view.getSpace(), true); /* * * DO NOT DO IT. TOO CONFUSING FOR USERS. if(s != null && !s.equals("")) { ZZCell c = view.getSpace().getCellByID(s); if(c == null) { throw new ZZError("No such cell: '"+s+"'..."); } smartconnect(viewCursor, vdim, dir, c); } */ svc(view, viewCursor.s(vdim, dir)); // Do timestamp: it's a motion. return true; } } // or only mark, if ... void mrkmv(ZZCell v, ZZCell vc, String dim, int dir) { // New way: in the view synchronized(v.getSpace()) { ZZCell m = v.s("d.mark", 1); boolean had = false; ZZCell m0 = v; while(m!=null) { if(m.h("d.mark-set",-1) ==vc) { had = true; break; } m0 = m; m = m.s("d.mark", 1); } if(had) { // Delete the whole relation cell. // The ranks collapse around it just right. m.delete(); } else { ZZCell mark = vc.N("d.mark-set", 1); m0.connect("d.mark", mark); } } if(dim != null && dir != 0) move(v, vc, dim, dir, null, null); } // XXX Combine the following two. // Connect void cnct(ZZCell v, ZZCell vc, boolean inclCurs, String dim, int dir) { // Also clears mark. ZZCell[] cs; synchronized(v.getSpace()) { cs = ZZDefaultSpace.getMark(v); ZZDefaultSpace.clearMark(v); ZZCell cur = (inclCurs ? vc : null); for(int i=0; i 1) { if(toks[1].equals("CTRL")) { usec=true; } if(toks[1].equals("+")) { dx=null; dir = 1; } if(toks[1].equals("-")) { dx=null; dir = -1; } if(toks[1].equals("C+")) { dx=null; dir = 1; usec=true; } if(toks[1].equals("C-")) { dx=null; dir = -1; usec=true; } if(toks[1].equals("X+")) { dx="X"; dir = 1; } if(toks[1].equals("X-")) { dx="X"; dir = -1; } if(toks[1].equals("Y+")) { dx="Y"; dir = 1; } if(toks[1].equals("Y-")) { dx="Y"; dir = -1; } if(toks[1].equals("Z+")) { dx="Z"; dir = 1; } if(toks[1].equals("Z-")) { dx="Z"; dir = -1; } if(toks[1].equals("X")) { dx="X"; dir = 0; } if(toks[1].equals("Y")) { dx="Y"; dir = 0; } if(toks[1].equals("Z")) { dx="Z"; dir = 0; } if(toks[1].equals("CX+")) { dx="X"; dir = 1; usec=true; } if(toks[1].equals("CX-")) { dx="X"; dir = -1; usec=true; } if(toks[1].equals("CY+")) { dx="Y"; dir = 1; usec=true; } if(toks[1].equals("CY-")) { dx="Y"; dir = -1; usec=true; } if(toks[1].equals("CZ+")) { dx="Z"; dir = 1; usec=true; } if(toks[1].equals("CZ-")) { dx="Z"; dir = -1; usec=true; } if(toks[1].equals("T0+")) { sndedge = 0; dir = 1; } if(toks[1].equals("T0-")) { sndedge = 0; dir = -1; } if(toks[1].equals("T1+")) { sndedge = 1; dir = 1; } if(toks[1].equals("T1-")) { sndedge = 1; dir = -1; } } if(usec && ctrlView == null) { callbackFailed(c, "NO CONTROL VIEW"); ZZDefaultSpace.getDirActionWaitingAndClear(dataView); // Do not timestamp taking the operation out, either, // because putting it in was not stamped. // XXX Some strange bug? code.getSpace().stamp(); return; } if(!usec) { view = dataView; otherView = ctrlView; viewCursor = dataCursor; zzv = zzdv; } else { view = ctrlView; otherView = dataView; viewCursor = ctrlCursor; zzv = zzcv; } if(dx != null) vdim = D(view, dx); if(target != null) viewCursor = target; ZZCell coderoot = code.getRootclone(); if(coderoot.s("d.xeq") != null) { org.gzigzag.flowing.FlowingClang.run (coderoot, new Data(ctrlView, dataView, key), false); } else if(toks[0].equals("NEW") || toks[0].equals("NEWANDEDIT") || toks[0].equals("EXCISE") || toks[0].equals("DISC") || toks[0].equals("CNCTI") || toks[0].equals("CNCTPAIR") || toks[0].equals("CLONE") || toks[0].equals("CLONECTRL") || toks[0].equals("CNCT") || toks[0].equals("CNCTC") || toks[0].equals("HOP") || toks[0].equals("MONOCHUG") || toks[0].equals("SORTALPH") || toks[0].equals("FINDTEXT") || toks[0].equals("END")) { // XXX Should this be implemented differently, so that the // dir doesn't need to be stored in the structure? ZZDefaultSpace.storeDirActionWaiting(view, toks[0]); dontClearAction = true; if (dx != null) { move(view, viewCursor, vdim, dir, dataView, ctrlView); // Move has commands that take more than one dir. } else { dontStamp = true; } } else if(toks[0].equals("CRSR")) { dontStamp = ! move(view, viewCursor, vdim, dir, dataView, ctrlView); // Move has commands that take more than one dir. dontClearAction = true; } else if(toks[0].equals("EXCHANGECELLS")) { exchangeCells(dataView, ctrlView); } else if(toks[0].equals("ORIGINAL")) { svc(view, viewCursor.h("d.clone", -1)); } else if(toks[0].equals("NEXTCLONE")) { ZZCell foo = viewCursor.s("d.clone", 1); if(foo != null) svc(view, foo); } else if(toks[0].indexOf("MOUSE") == 0) { Object ob = xi.getObjectAt(pt.x, pt.y); ZZCursor cc=null; ZZCell cell=null; if(ob instanceof ZZCursor) { cc = (ZZCursor)ob; cell=cc.get(); } else if(ob instanceof ZZCell) { cell=(ZZCell)ob; } else return; if(cell==null) return; if(toks[0].equals("MOUSESETC")) { svc(view, cell); fastany = false; } else if(toks[0].equals("MOUSESETCTXT")) { if(cc==null) return; svc(view, cell); ZZCursorReal.setOffs(view, cc.getOffs()); fastany = false; } else if(ctrlCursor!=null && c.equals("MOUSEEXEC")) { pa("MOUSEEXEC"); this.execCallback(ctrlCursor, cell, zzv, zzcv, null, null, null); } else if(toks[0].equals("MOUSEMARK")) { mrkmv(view, cell, null, 0); fastany = false; } else if(toks[0].equals("MOUSESETDIMOTHER")) { setdim(otherView, dx, cell); } else { callbackFailed(c, "Unknown MOUSE code"); return; } } else if(ctrlCursor!=null && c.equals("EXEC")) { // This is an interesting one: it just means "execute // whatever cell is visible in the control view. // So we call ourselves... // XXX inherit xi really? ZZCommand comm = ZZCommand.getCommand(ctrlCursor); if(comm != null) comm.execCallback(viewCursor, zzdv, zzcv, null, pt, xi); else this.execCallback(ctrlCursor, viewCursor, zzdv, zzcv, null, pt, xi); } else if(c.equals("HERA1")) { // Execute the first, primitive calling sequence of // a Heraclitus Clang primitive poswards on d.2 from // the command cell ZZCell hc = code.s("d.2", 1); if(hc == null) throw new ZZError("No heraclitus1 prim!"); ZZCell curspar = code.N(); ZZCell curs1 = code.N(); ZZCell curs2 = curs1.N("d.1", 1); ZZCursorReal.set(curs1, ctrlView); ZZCursorReal.set(curs2, dataView); ZZCursorReal.set(curspar, curs1); try { p("Enter heraclitus: "); org.gzigzag.heraclitus.HeraclitusClang.execute( hc, curspar); p("Exit heraclitus"); } finally { ZZCursorReal.delete(curs1); ZZCursorReal.delete(curs2); ZZCursorReal.delete(curspar); curs1.delete(); curs2.delete(); curspar.delete(); } } else if(toks[0].equals("MARK")) mrkmv(view, viewCursor, dx, dir); else if(toks[0].equals("DIM")) chugdim(view, dx, dir); else if(toks[0].equals("SETDIMS")) setdims(view, viewCursor); else if(toks[0].equals("RASTER")) hopraster(view, dir!=0 ? dir : 1); else if(toks[0].equals("FFACTORY")) hopffactory(view, dir!=0 ? dir : 1); else if(toks[0].equals("HOME")) { ZZCell home = view.getSpace().getHomeCell(); svc(view, home); } else if(toks[0].equals("HOMECLR")) { ZZCell home = view.getSpace().getHomeCell(); ZZCell datarec = ZZDefaultSpace .findInheritableParam(dataView, "CursorRecovery"); if(datarec!=null) ZZCursorReal.attach(dataView, datarec); ZZCell ctrlrec = ZZDefaultSpace .findInheritableParam(ctrlView, "CursorRecovery"); if(ctrlrec!=null) ZZCursorReal.attach(ctrlView, ctrlrec); svc(dataView, home); svc(ctrlView, home); ZZCell dimlist = ZZDefaultSpace.findDefaultDimlist(home); setdims(dataView, dimlist); setdims(ctrlView, dimlist); ZZDefaultSpace.clearMark(dataView); } else if(toks[0].equals("DELETESCRAM")) { ZZCell mv = null; mv = viewCursor.s(D(view, "X"), -1); if(mv == null) mv = viewCursor.s(D(view, "X"), +1); if(mv == null) mv = viewCursor.s(D(view, "Y"), -1); if(mv == null) mv = viewCursor.s(D(view, "Y"), +1); if(mv == null) mv = viewCursor.s(D(view, "Z"), -1); if(mv == null) mv = viewCursor.s(D(view, "Z"), +1); if(mv == null) mv = view.getSpace().getHomeCell(); svc(view, mv); viewCursor.delete(); } else if(toks[0].equals("QUIT")) { // Commit changes to space here viewCursor.getSpace().commit(); SafeExit.exit(0); } else if(toks[0].equals("APPENDINPUT")) { if(key != null && key.length() == 1) ZZDefaultSpace.appendInbuf(viewCursor.getSpace(), key); dontStamp = true; } else if(toks[0].equals("BACKSPACEINPUT")) { ZZDefaultSpace.appendInbuf(viewCursor.getSpace(), null); dontStamp = true; } else if(toks[0].equals("CLRINPUT")) { ZZDefaultSpace.getInbuf(viewCursor.getSpace(), true); dontStamp = true; } else if(toks[0].equals("GOTO")) do_goto(view); // Sound span adjustment. These will be useful // in a more general way later on. else if(toks[0].equals("SNDL")) { Span sp = viewCursor.getSpan(); ZZCell n = viewCursor.s("d.2", sndedge*2-1); Span nsp = n.getSpan(); if(sp!=null && nsp!=null) { Span[] sps; if(sndedge==0) { sps = nsp.adjustEdgeLocked(100000000*dir, sp, 500000000); n.setSpan(sps[0]); viewCursor.setSpan(sps[1]); } else { sps = sp.adjustEdgeLocked(100000000*dir, nsp, 500000000); viewCursor.setSpan(sps[0]); n.setSpan(sps[1]); } } else if(sp!=null) viewCursor.setSpan( sp.adjustEdge(sndedge, 100000000 * dir)); } else if(toks[0].equals("SNDS")) { Span sp = viewCursor.getSpan(); if(sp!=null) viewCursor.setSpan( sp.adjustEdge(sndedge, 100000000 * dir)); } else if(toks[0].equals("SNDSPLIT")) { ZZCell n = viewCursor.N("d.2", 1); Span sp = viewCursor.getSpan(); if(sp!=null) { Span[] sps = sp.splitInHalf(); viewCursor.setSpan(sps[0]); n.setSpan(sps[1]); } } else if(toks[0].equals("SNDJOIN+")) { ZZCell o = viewCursor.s("d.2", 1); if(o!=null) { Span sp1 = viewCursor.getSpan(); Span sp2 = o.getSpan(); if(sp1!=null && sp2!=null) { Span spj = sp1.join(sp2, 500000000); if(spj!=null) { viewCursor.setSpan(spj); // XXX ??? Try to absorb links? o.delete(); } } } } else if(toks[0].equals("SWAPCRSR")) { ZZCell view2 = findOtherView(view); ZZCell view2c = ZZCursorReal.get(view2); svc(view, view2c); svc(view2, viewCursor); } else if(toks[0].equals("FETCH")) { svc(findOtherView(view), viewCursor); } else if(toks[0].equals("PUICOPY")) { ZZUtil.puiCopy(viewCursor); } else if(toks[0].equals("PUIPASTE")) { ZZUtil.puiPaste(viewCursor); } else if(toks[0].equals("PUICOPYLINE")) { // Copy along y-dim ZZUtil.puiCopy(viewCursor, ZZCursorReal.get( dataView.s("d.dims", 1) .s("d.dims", 1) ).getText()); } else if(toks[0].equals("PUICOPYRANK")) { // Copy along y-dim // insert \n between // cells ZZUtil.puiCopyRank(viewCursor, ZZCursorReal.get( dataView.s("d.dims", 1) .s("d.dims", 1) ).getText()); } else if(toks[0].equals("TXTINSERT")) { // XXX ??? p("Txtins: '"+key+"'"); CharScroll cs = (CharScroll) Scroll.obtain(viewCursor.getSpace(), "textinput"); long offs = cs.curEnd(); cs.append(key); long offs2 = cs.curEnd()-1; VStream.insert(new ZZCursorReal(view), Span.create( Address.scrollOffs(cs, offs), Address.scrollOffs(cs, offs2) ) ); } else if(toks[0].equals("SWITCHCURSMODE")) { switchcursmode(view); dontStamp = true; } else if(toks[0].equals("SWITCHOFFCURSMODE")) { switchcursmodeoff(view); } else if(toks[0].equals("CTXTHOME")) { if (ZZCursorReal.getOffs(view) == ZZCursorReal.NO_OFFSET) return; ZZCursorReal.setOffs(view, 0); dontStamp = true; } else if(toks[0].equals("CTXTEND")) { if (ZZCursorReal.getOffs(view) == ZZCursorReal.NO_OFFSET) return; ZZCursorReal.setOffs(view, viewCursor.getText().length()); dontStamp = true; } else if(toks[0].equals("CTXTSOL")) { // SOL = start of line if (ZZCursorReal.getOffs(view) == ZZCursorReal.NO_OFFSET) return; int cur = ZZCursorReal.getOffs(view); String line = viewCursor.getText(); if (cur >= line.length()) cur = line.length()-1; if (line.charAt(cur) == '\n') --cur; for (int i = cur; i >= 0; --i) { p("seeking SOL: charAt = " + line.charAt(i)); if (line.charAt(i) == '\n') { cur = i+1; break; } if (i == 0) { cur = i; break; } } if (cur > line.length()) cur = line.length(); if (cur < 0) cur = 0; ZZCursorReal.setOffs(view, cur); dontStamp = true; } else if(toks[0].equals("CTXTEOL")) { // EOL = start of line if (ZZCursorReal.getOffs(view) == ZZCursorReal.NO_OFFSET) return; int cur = ZZCursorReal.getOffs(view); String line = viewCursor.getText(); for (int i = cur; i < line.length(); ++i) { if (line.charAt(i) == '\n') { cur = i; break; } if (i == line.length() - 1) { cur = line.length(); break; } } if (cur > line.length()) cur = line.length(); if (cur < 0) cur = 0; ZZCursorReal.setOffs(view, cur); dontStamp = true; } else if(toks[0].equals("CTXTCRSR")) { int cur = ZZCursorReal.getOffs(view); if(cur == ZZCursorReal.NO_OFFSET) return; cur += dir; if(cur < 0) cur = 0; if(cur > viewCursor.getText().length()) cur = viewCursor.getText().length(); ZZCursorReal.setOffs(view, cur); dontStamp = true; } else if(toks[0].equals("VSTRMCRSR")) { if(ZZCursorReal.getOffs(view) == ZZCursorReal.NO_OFFSET) throw new ZZError("Need cursor offset"); if(!Stream.move( new ZZCursorReal(view), VStream.dim, dir)) { callbackFailed("VSTRMCRSR", "nothing there"); } else { fastany = false; } dontStamp = true; } else if(toks[0].equals("VSTRMJUMP")) { int offs = ZZCursorReal.getOffs(view); String txt = viewCursor.getText(); ZZCell next = viewCursor.s("d.2", dir!=0 ? dir : 1); offs = dir >= 0 ? txt.indexOf(' ', offs) : txt.lastIndexOf(' ', offs - 1); if(offs > -1) ZZCursorReal.setOffs(view, offs + (dir<0 ? 0 : 1)); else if(next != null) { svc(view, next); ZZCursorReal.setOffs(view, dir<0 ? next.getText().length() : 0); } else ZZCursorReal.setOffs(view, dir<0 ? 0 : txt.length() - 1); dontStamp = true; } else if(toks[0].equals("VSTRMSPLIT")) { ZZCell next = viewCursor.N("d.2", dir!=0 ? dir : 1); if(viewCursor.getSpan() == null) { int offs = ZZCursorReal.getOffs(view); String txt = viewCursor.getText(); String one = txt.substring(0, offs), two = txt.substring(offs); if(dir >= 0) { viewCursor.setText(one); next.setText(two); } else { viewCursor.setText(two); next.setText(one); } } // XXX Split spans, too ZZCursorReal.setOffs(view, 0); svc(view, next); dontStamp = true; } else if(toks[0].equals("CTXTINSERT") || toks[0].equals("CTXTBKSP") || toks[0].equals("CTXTDEL")) { dontStamp = true; if(viewCursor.getSpan() != null) { System.out.println("Can't modify span"); return; } int cur = ZZCursorReal.getOffs(view); // Make sure it fits. if(cur > viewCursor.getText().length()) cur = viewCursor.getText().length(); if(cur == ZZCursorReal.NO_OFFSET) return; StringBuffer s = new StringBuffer(viewCursor.getText()); if(toks[0].equals("CTXTINSERT")) { p("CTXTINSERT: key = " + key); String ik = key; if (ik != null && ik.equals("Enter")) ik = "\n"; // Don't insert e.g. "Shift" if(ik != null && ik.length() == 1) { if(textlog != null) { textlog.print(ik); // flush all the time so nothing is lost // in a crash textlog.flush(); } s.insert(cur, ik); cur += 1; } } else if(toks[0].equals("CTXTBKSP")) { if(cur > 0) { String str = s.toString(); // XXX delete requires JDK 1.2 s = new StringBuffer( str.substring(0, cur-1) ); s.append(str.substring(cur)); cur -= 1; } } else if(toks[0].equals("CTXTDEL")) { if(cur < viewCursor.getText().length()) { String str = s.toString(); s = new StringBuffer( str.substring(0, cur) ); s.append(str.substring(cur+1)); } } viewCursor.setText(s.toString()); ZZCursorReal.setOffs(view, cur); } else if(toks[0].equals("CURSEL")) cursel(view, dir, false); else if(toks[0].equals("SELEVATE")) cursel(view, dir, true); else if(toks[0].equals("CreateCursors")) { ZZCell h = view.getSpace().getHomeCell(); ZZCell sc = ZZDefaultSpace .findOnSystemlist(view.getSpace(), "SysCursors", false); if(sc != null) { ZZDefaultSpace.newSysCursor(sc, h, Color.blue.brighter()); ZZDefaultSpace.newSysCursor(sc, h, Color.yellow.darker()); ZZDefaultSpace.newSysCursor(sc, h, Color.red.darker()); ZZDefaultSpace.newSysCursor(sc, h, new Color(180, 0, 255)); } else callbackFailed(c, "SysCursors list required"); } else if(toks[0].equals("NEWVIEWS")) { // Create a new view pair. ZZDefaultSpace.newViewPair(view.getSpace()); } else if(toks[0].equals("EDITVIEW") || toks[0].equals("HELP")) { boolean help = toks[0].equals("HELP"); ZZCell home = dataView.getSpace().getHomeCell(); ZZCell rl = home.findText("d.2", 1, "AllViews"); rl = rl.s("d.1", 1); rl = rl.findText("d.2", 1, "Edit"); if (rl == null) throw new ZZError("Edit view not found"); rl = rl.getOrNewCell("d.clone", 1); ZZCell cursCell; if(help) { cursCell = home.N(); ZZCursorReal.set(cursCell, viewCursor.getOrNewCell("d.help", 1)); } else cursCell = dataView; ZZCell win = ZZDefaultSpace.newToplevelView(dataView.getSpace(), help ? "Help" : "Edit", help ? 100 : 512, help ? 100 : 449, help ? 400 : 512, help ? 400 : 100, rl, null, // XXX Defaultbind? null, cursCell, null, Color.white); // XXX PREFERENCE!!! } else if(toks[0].equals("EDITHACK")) { new ZZTextView(view); } else if(toks[0].equals("APPLITUDE")) { ApplitudeMgr.rotateWindowApp(view, dir); } else if(toks[0].equals("GETSPACEID")) { target.setText(target.getSpace().getID()); } else if(toks[0].equals("SETSPACEID")) { target.getSpace().setID(target.getText()); } else if(toks[0].equals("UPDATEWINS")) { ZZWindows.update(); } else if(toks[0].equals("ACCURSE")) { // Make the cell accursed in the other window a cursor to the // cell accursed in window for which the action occured. ZZCursorReal.set(ZZCursorReal.get(otherView), viewCursor); } else if(toks[0].equals("UNDO")) { code.getSpace().undo(); dontStamp = true; } else if(toks[0].equals("REDO")) { code.getSpace().redo(); dontStamp = true; } else if(toks[0].equals("COMMIT")) { code.getSpace().commit(); } else callbackFailed(c, "UNKNOWN CODE"); p("ZZPrimitiveActions: postlude: "+fastany+" "+zzv+" "+ dontClearAction); if(fastany) ZZUpdateManager.setFast(zzv); // Clear the waiting dir action if(!dontClearAction) ZZDefaultSpace.getDirActionWaitingAndClear(view); if(!dontStamp) code.getSpace().stamp(); } } static ZZCell addAct(ZZCell s, String name, String act) { ZZCell n1 = s.N("d.2", 1); n1.setText(name); ZZCell n2 = n1.N("d.1", 1); n2.setText(act); return n2; } static void addAct(ZZCell s, String name, String act, ZZCell after) { ZZCell c = addAct(s, name, act); after.insert("d.3", 1, c); } static void setModeColor(ZZCell mode, Color col) { if(col == null) { if(mode.s("d.color") != null) mode.disconnect("d.color", 1); } else { ZZCell c = mode.getOrNewCell("d.color", 1); c.setText(String.valueOf(col.getRGB())); } } /** Puts a number of default key bindings to the structure. * ZZKeyBindings1 structure is assumed (list on d.2 of keys * and on d.1 the responses) */ static public void putDefBinds(ZZCell start, ZZCell editstart) { start.setText("Normal mode"); editstart.setText("Text edit bindings"); // Apparently, this wasn't actually necessary! /* ZZCell dir = start.N("d.2", 1); dir = dir.N("d.3", -1); dir.setText("Motion"); */ ZZCell dir = start; ZZCell editmode = start.N("d.1", 1); setModeColor(editmode, Color.white); editmode.setText("Edit mode"); editmode.N("d.2").setText("EDITBINDS"); addAct(editmode, "Tab", "SWITCHOFFCURSMODE", dir); addAct(editmode, "Esc", "SWITCHOFFCURSMODE", dir); ZZCell curs = editstart; curs.setText("Text edit mode"); addAct(curs, "Ctrl-A", "CTXTSOL"); addAct(curs, "Ctrl-E", "CTXTEOL"); addAct(curs, "End", "CTXTEND"); addAct(curs, "Home", "CTXTHOME"); addAct(curs, "Right", "CTXTCRSR +"); addAct(curs, "Left", "CTXTCRSR -"); addAct(curs, "Backspace", "CTXTBKSP"); addAct(curs, "Delete", "CTXTDEL"); addAct(curs, "MouseClicked1", "MOUSESETCTXT"); addAct(curs, "DEFAULT", "CTXTINSERT"); ZZCell cursel = editmode.N("d.1", 1); cursel.setText("Cursel mode"); cursel.N("d.color").setText("CURSOR"); addAct(cursel, " ", "", dir); addAct(cursel, "Esc", "", dir); addAct(cursel, "Alt-C", "", dir); addAct(cursel, "Left", "CURSEL -"); addAct(cursel, "Right", "CURSEL +"); addAct(cursel, "Up", "SELEVATE -"); addAct(cursel, "Down", "SELEVATE +"); addAct(cursel, "j", "CURSEL -"); addAct(cursel, "l", "CURSEL +"); addAct(cursel, "i", "SELEVATE -"); addAct(cursel, ",", "SELEVATE +"); addAct(cursel, "s", "CURSEL C-"); addAct(cursel, "f", "CURSEL C+"); addAct(cursel, "e", "SELEVATE C-"); addAct(cursel, "c", "SELEVATE C+"); // Quote starts insert buffer mode... ZZCell bufins = cursel.N("d.1", 1); bufins.setText("Quotebuf"); setModeColor(bufins, Color.pink); addAct(bufins, "DEFAULT", "APPENDINPUT"); addAct(bufins, "Backspace", "BACKSPACEINPUT"); addAct(bufins, "\"", "", dir); addAct(bufins, "Esc", "", dir); // Totally temporary addAct(dir, "Tab", "SWITCHCURSMODE", editmode); addAct(dir, "Alt-C", "", cursel); addAct(dir, "\"", "CLRINPUT", bufins); addAct(dir, "l", "CRSR X+"); addAct(dir, "j", "CRSR X-"); addAct(dir, "i", "CRSR Y-"); addAct(dir, ",", "CRSR Y+"); addAct(dir, "k", "CRSR Z+"); addAct(dir, "K", "CRSR Z-"); // Caps locked addAct(dir, "L", "CRSR X+"); addAct(dir, "J", "CRSR X-"); addAct(dir, "I", "CRSR Y-"); addAct(dir, "a", "MONOCHUG"); addAct(dir, "f", "CRSR CX+"); addAct(dir, "s", "CRSR CX-"); addAct(dir, "e", "CRSR CY-"); addAct(dir, "c", "CRSR CY+"); addAct(dir, "d", "CRSR CZ+"); addAct(dir, "D", "CRSR CZ-"); // Caps locked addAct(dir, "F", "CRSR CX+"); addAct(dir, "S", "CRSR CX-"); addAct(dir, "E", "CRSR CY-"); addAct(dir, "C", "CRSR CY+"); addAct(dir, "Right", "CRSR X+"); addAct(dir, "Left", "CRSR X-"); addAct(dir, "Up", "CRSR Y-"); addAct(dir, "Down", "CRSR Y+"); addAct(start, "Ctrl-C", "PUICOPY"); addAct(start, "Ctrl-Shift-C", "PUICOPYLINE"); addAct(start, "Ctrl-Alt-C", "PUICOPYRANK"); addAct(start, "Ctrl-V", "PUIPASTE"); addAct(start, "-", "CNCTI" /*, dir */); addAct(start, "n", "NEW" /*, dir */); // XXX Problem: must switch to edit mode AFTER arrow // addAct(start, "N", "NEWANDEDIT", editmode); addAct(start, "b", "DISC" /*, dir */); addAct(start, "/", "CNCTPAIR" /*, dir */); addAct(start, "t", "CLONE" /*, dir */); addAct(start, "T", "CLONECTRL" /*, dir */); addAct(start, "o", "ORIGINAL"); addAct(start, "O", "ORIGINAL CTRL"); addAct(start, "Alt-O", "NEXTCLONE"); addAct(start, "Alt-Shift-O", "NEXTCLONE CTRL"); addAct(start, "h", "HOP" /*, dir */); addAct(start, "H", "HOP" /*, dir */); addAct(start, "%", "EXCHANGECELLS"); addAct(start, "Ctrl-X", "EXCISE"); addAct(start, "End", "END" /*, dir */); for(int i=0; i<=9; i++) addAct(start, ""+i, "APPENDINPUT"); addAct(start, "Backspace", "BACKSPACEINPUT"); addAct(start, "g", "GOTO"); addAct(start, "G", "GOTO CTRL"); addAct(start, "Esc", "HOMECLR"); addAct(start, "Home", "HOME"); addAct(start, "v", "RASTER +"); addAct(start, "Alt-V", "RASTER -"); addAct(start, "V", "RASTER C+"); addAct(start, "Alt-Shift-V", "RASTER C-"); addAct(start, "F2", "FFACTORY +"); addAct(start, "Alt-F2", "FFACTORY -"); addAct(start, "Shift-F2", "FFACTORY C+"); addAct(start, "Alt-Shift-F2", "FFACTORY C-"); addAct(start, "F3", "SORTALPH"); addAct(start, "x", "DIM X+"); addAct(start, "Alt-X", "DIM X-"); addAct(start, "y", "DIM Y+"); addAct(start, "Alt-Y", "DIM Y-"); addAct(start, "z", "DIM Z+"); addAct(start, "Alt-Z", "DIM Z-"); addAct(start, "X", "DIM CX+"); addAct(start, "Alt-Shift-X", "DIM CX-"); addAct(start, "Y", "DIM CY+"); addAct(start, "Alt-Shift-Y", "DIM CY-"); addAct(start, "Z", "DIM CZ+"); addAct(start, "Alt-Shift-Z", "DIM CZ-"); addAct(start, "~", "SWAPCRSR"); addAct(start, "<", "FETCH"); addAct(start, ">", "FETCH CTRL"); addAct(start, "Ctrl-<", "ACCURSE CTRL"); addAct(start, "Ctrl->", "ACCURSE"); // addAct(start, "Alt-x", "PSHDIM X+"); // addAct(start, "Alt-y", "PSHDIM Y+"); // addAct(start, "Alt-z", "PSHDIM Z+"); /* addAct(start, "L", "MARK X+"); addAct(start, "J", "MARK X-"); addAct(start, "I", "MARK Y-"); addAct(start, "<", "MARK Y+"); */ addAct(start, "Enter", "EXEC"); addAct(start, "m", "MARK"); addAct(start, "u", "UNDO"); addAct(start, "Ctrl-U", "REDO"); addAct(start, "Ctrl-S", "COMMIT"); addAct(start, "Ctrl-F", "FINDTEXT"); addAct(start, "MouseClicked1", "MOUSESETC"); addAct(start, "MouseClicked2", "MOUSEEXEC"); addAct(start, "MouseClicked3", "MOUSEMARK"); addAct(start, "Delete", "DELETESCRAM"); addAct(start, "F1", "HELP"); addAct(start, "q", "QUIT"); } static public void putDefTextBinds(ZZCell start) { start.setText("Text insert mode"); ZZCell dir = start; addAct(dir, "DEFAULT", "TXTINSERT"); } static public void putDefCmds(ZZCell fromHome) { String [][] foo = { { "EDITHACK" }, {}, { "NEWVIEWS" }, { "TextCloud.TESTWIN" }, /* doesn't work currently { "ZZMbox.READMBOX", "ZZMbox.CREATEFLOBWINDOW" }, */ { "NileDemo.UPDATE" }, { "SplitNileDemo.UPDATE" }, { "CreateCursors" }, { "UPDATEWINS" }, { "EDITVIEW" } , { "XML.IMPORT" } /* , { "---- (obsolete?)" }, { "CNCT X+", "CNCT X-" }, { "CNCT Y+", "CNCT Y-" }, { "CNCTI X+", "CNCTI X-" }, { "CNCTI Y+", "CNCTI Y-" }, { "CNCTC X+", "CNCTC X-" }, { "CNCTC Y+", "CNCTC Y-" }, { "SETDIMS", "SETCDIMS" }, //{ "RENDER" }, { "TestClang1.1" }, { "QUIT" }, */ }; ZZCell curv = fromHome; for(int i=0; i0) curh = curh.N("d.1", 1); curh.setText(foo[i][j]); } } if(true) { foo = new String[][]{ { "Dumper.Create" }, { "Dumper.Read" }, { "Dumper.Write" }, { "Dumper.Dump" }, { "Dumper.Enter" }, { "Dumper.ChangeID" }, { "HOME" }, }; curv = fromHome.N("d.1", 1); // curv.setText("Dumping"); // XXX -- set or don't? // (what's less confusing?) for(int i=0; i0) curh = curh.N("d.1", 1); curh.setText(foo[i][j]); } } } if(false) { foo = new String[][]{ { "SNDS T0-", "SNDS T0+" }, { "SNDS T1+", "SNDS T1-" }, { "SNDL T0-", "SNDL T0+" }, // locked to the other one { "SNDL T1+", "SNDL T1-" }, { "SNDSPLIT", "SNDJOIN+" }, { "ZZPlayer.PLAY", "ZZPlayer.PLAYLOOP", "ZZPlayer.PAUSE", "ZZPlayer.STOP" }, { "ZZPlayer.CRDEMO" }, }; curv = fromHome.N("d.1", 1); curv.setText("Sound"); for(int i=0; i0) curh = curh.N("d.1", 1); curh.setText(foo[i][j]); } } } } }