dasher r3599 - in trunk: . java java/dasher java/dasher/applet java/dasher/applet/font java/dasher/applet/system.rc java/dasher/net



Author: pwelche
Date: Tue Oct 14 16:17:28 2008
New Revision: 3599
URL: http://svn.gnome.org/viewvc/dasher?rev=3599&view=rev

Log:
Chris Smowton's java port.


Added:
   trunk/java/
   trunk/java/README
   trunk/java/dasher/
   trunk/java/dasher/CAlphIO.java
   trunk/java/dasher/CAlphabet.java
   trunk/java/dasher/CAlphabetManager.java
   trunk/java/dasher/CAlphabetManagerFactory.java
   trunk/java/dasher/CAlphabetMap.java
   trunk/java/dasher/CAutoSpeedControl.java
   trunk/java/dasher/CCannaConversionHelper.java
   trunk/java/dasher/CCircleStartHandler.java
   trunk/java/dasher/CClickFilter.java
   trunk/java/dasher/CColourIO.java
   trunk/java/dasher/CContextBase.java
   trunk/java/dasher/CControlEvent.java
   trunk/java/dasher/CConversionHelper.java
   trunk/java/dasher/CCustomColours.java
   trunk/java/dasher/CDasherComponent.java
   trunk/java/dasher/CDasherInput.java
   trunk/java/dasher/CDasherInterfaceBase.java
   trunk/java/dasher/CDasherModel.java
   trunk/java/dasher/CDasherModule.java
   trunk/java/dasher/CDasherNode.java
   trunk/java/dasher/CDasherScreen.java
   trunk/java/dasher/CDasherView.java
   trunk/java/dasher/CDasherViewSquare.java
   trunk/java/dasher/CDefaultFilter.java
   trunk/java/dasher/CDelayedDraw.java
   trunk/java/dasher/CEditContextEvent.java
   trunk/java/dasher/CEditEvent.java
   trunk/java/dasher/CEvent.java
   trunk/java/dasher/CEventHandler.java
   trunk/java/dasher/CFileLogger.java
   trunk/java/dasher/CFrameRate.java
   trunk/java/dasher/CInputFilter.java
   trunk/java/dasher/CLanguageModel.java
   trunk/java/dasher/CLockEvent.java
   trunk/java/dasher/CMessageEvent.java
   trunk/java/dasher/CModuleFactory.java
   trunk/java/dasher/CModuleManager.java
   trunk/java/dasher/CNodeManager.java
   trunk/java/dasher/CNodeManagerFactory.java
   trunk/java/dasher/CPPMLanguageModel.java
   trunk/java/dasher/CParamTables.java
   trunk/java/dasher/CParameterNotFoundException.java
   trunk/java/dasher/CParameterNotificationEvent.java
   trunk/java/dasher/CRemoteAlphabetManager.java
   trunk/java/dasher/CRemotePPM.java
   trunk/java/dasher/CSettingsStore.java
   trunk/java/dasher/CStartEvent.java
   trunk/java/dasher/CStartHandler.java
   trunk/java/dasher/CStopEvent.java
   trunk/java/dasher/CSymbolAlphabet.java
   trunk/java/dasher/CSymbolProb.java
   trunk/java/dasher/CUserLog.java
   trunk/java/dasher/CWrapperFactory.java
   trunk/java/dasher/EColorSchemes.java
   trunk/java/dasher/EParameters.java
   trunk/java/dasher/Ebp_parameters.java
   trunk/java/dasher/Elp_parameters.java
   trunk/java/dasher/Esp_parameters.java
   trunk/java/dasher/Opts.java
   trunk/java/dasher/SFactoryInfo.java
   trunk/java/dasher/SGroupInfo.java
   trunk/java/dasher/SSymbol.java
   trunk/java/dasher/applet/
   trunk/java/dasher/applet/DasherTasklet.java
   trunk/java/dasher/applet/DoFrameTask.java
   trunk/java/dasher/applet/JDasher.java
   trunk/java/dasher/applet/JDasherApplet.java
   trunk/java/dasher/applet/JDasherEdit.java
   trunk/java/dasher/applet/JDasherHost.java
   trunk/java/dasher/applet/JDasherMenuBar.java
   trunk/java/dasher/applet/JDasherMenuBarListener.java
   trunk/java/dasher/applet/JDasherPanel.java
   trunk/java/dasher/applet/JDasherScreen.java
   trunk/java/dasher/applet/JDasherThread.java
   trunk/java/dasher/applet/JMouseInput.java
   trunk/java/dasher/applet/JSettings.java
   trunk/java/dasher/applet/ScreenOverlay.java
   trunk/java/dasher/applet/font/
   trunk/java/dasher/applet/font/FontListener.java
   trunk/java/dasher/applet/font/JFontDialog.java
   trunk/java/dasher/applet/system.rc/
   trunk/java/dasher/applet/system.rc/alphabet.Thai.xml
   trunk/java/dasher/applet/system.rc/alphabet.dtd
   trunk/java/dasher/applet/system.rc/alphabet.english.xml
   trunk/java/dasher/applet/system.rc/alphabet.englishC.xml
   trunk/java/dasher/applet/system.rc/colour.dtd
   trunk/java/dasher/applet/system.rc/colour.euroasian-new.xml
   trunk/java/dasher/applet/system.rc/colour.euroasian.xml
   trunk/java/dasher/applet/system.rc/colour.rainbow.xml
   trunk/java/dasher/applet/system.rc/colour.thai.xml
   trunk/java/dasher/applet/system.rc/training_english_GB.txt
   trunk/java/dasher/applet/test.htm
   trunk/java/dasher/net/
   trunk/java/dasher/net/NetDashConnectionHandler.java
   trunk/java/dasher/net/NetDashGC.java
   trunk/java/dasher/net/NetDasher.java
   trunk/java/dasher/net/NetDasherCommandInterpreterThread.java
   trunk/java/dasher/net/NetDasherListener.java
   trunk/java/dasher/net/NetInput.java
   trunk/java/dasher/net/NetScreen.java
Modified:
   trunk/ChangeLog

Added: trunk/java/README
==============================================================================
--- (empty file)
+++ trunk/java/README	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,270 @@
+Here's the readme I provided when I published the sources online: of 
+course, to be accurate it needs to be accompanied by a license.txt file 
+containing the GPL.
+
+JDasher Source Code
+===================
+
+Find further information at www.smowton.net/chris
+
+Contents:
+
+I. Licensing
+II. Package outline
+III. Class outline of dasher package
+IV. Contacting the author
+
+I. Licensing
+------------
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+The complete license can be found in COPYING in the parent directory.
+
+II. Package outline
+-------------------
+
+dasher.*
+========
+
+This contains the core Dasher source code. It corresponds to the 
+DasherCore package in the original C version of Dasher. By themselves 
+the classes in this package cannot form a completely working Dasher. To 
+produce a working system, one must:
+
+a) Implement the CDasherScreen interface (see section III for details)
+b) Subclass CDasherInput at least once to provide co-ordinates (eg. from 
+a mouse) on demand (again, see details below)
+c) Subclass CDasherInterfaceBase, specifying the abstract methods of 
+that class. Most of these can be stubbed and still produce a working 
+system, though it may lack the ability to learn from training text, or 
+load XML files.
+d) Optionally, subclass CSettingsStore to provide the ability to store 
+persistent settings. If this isn't done and the base CSettingsStore is 
+used, the defaults will be loaded every time Dasher is run.
+
+dasher.applet.*
+===============
+
+This package contains the classes to complete an implementation of 
+Dasher as a Swing applet, by more or less the means described above. It 
+also provides some extra, optional functionality, such as listening for 
+text events and showing the currently entered text in a text box.
+
+Key components:
+
+* JDasher, which is a subclass of CDasherInterfaceBase and provides 
+methods to retrieve data files from a JAR
+* JDasherApplet, which sets up a Swing GUI and generates Dasher events 
+to provide control.
+* JMouseInput, a subclass of CDasherInput which provides mouse 
+co-ordinates on demand.
+* JDasherScreen, which implements CDasherScreen and converts graphics 
+primitive instructions to Java AWT drawing commands.
+* JSettings, which subclasses CSettingsStore to use the Java Preferences 
+class to store persistent settings. The Preferences class in turn defers 
+to the JVM, meaning it will try to use the Registry on Windows, a 
+.javasettings file in Linux, and so forth.
+
+dasher.net.*
+============
+
+This is an implementation of Dasher which provides a network interface 
+based upon XML transactions. The 'screen' (NetDasherScreen) implements 
+CDasherScreen but doesn't really act as a screen; rather it gathers 
+relevant data and sends this to a client, such as the JavaScript client 
+found at www.smowton.f2s.com/jsdasher.html. Similarly, NetInput provides 
+input by interpreting XML documents fed by the client.
+
+The net package provides a multithreaded server to host several such 
+Dashers at once. Loosely, the structure is that NetDasherListener is 
+started as the main thread, and this spawns a 
+NetDasherCommandInterpreterThread for every incoming connection it 
+receives. These threads interpret the XML document sent by the client 
+and respond in a variety of ways, usually creating or invoking methods 
+of a NetDasherConnectionHandler (which creates an instance of Dasher, 
+NetScreen and NetInput and acts to pass messages back and forth between 
+Dasher and the network server).
+
+These ConnectionHandler objects as well as their associated Dashers are 
+persistent between connections, and so act to provide a continuous session.
+
+Typically JavaScript clients will not speak directly to the Dasher 
+server, but will pass requests to a webserver first, since security 
+restrictions typically require that JavaScript does not invoke URLs 
+which are not on the same server as the JavaScript itself.
+
+III. Dasher core in detail
+--------------------------
+
+CAlphabet: Represents the alphabet we're currently working with. It it 
+responsible for holding information about how each symbol in the 
+alphabet should be typed, how it should be displayed on screen, and some 
+aspects of how the symbols should be coloured.
+
+CAlphabetManager: Carries out certain functions which manipulate the 
+general Dasher state, but depend upon Alphabet data. Example include 
+outputting the appropriate text when the user enters a node, and 
+populating child nodes when required to do so by the Model.
+
+CAlphabetManagerFactory: Factory class for the above.
+
+CAlphabetMap: Wrapper around a HashMap from a UTF-8 representation of a 
+symbol to its unique integer identifer. This used to be much more 
+complicated, but could probably now be reduced to just a HashMap which 
+would probably be a member of CAlphabet.
+
+CAlphIO: Given a list of XML files, parses them for descriptions of 
+alphabets, and uses this to report a list of available alphabets.
+
+CAutoSpeedControl: Uses a variety of diagnostic signs to establish 
+whether the user would like to go slower or faster, and controls the 
+Dasher maximum speed appropriately.
+
+CCannaConversionHelper: In the C version, provides for conversion from 
+Hiragana to Kanji in Japanese. At the time of writing this was an 
+unstable development feature, and this class is a stub at present in 
+JDasher.
+
+CCircleStartHandler: Provides the possibility of a circular target which 
+can be used to start Dasher.
+
+CClickFilter (extends CInputFilter): An input filter which causes Dasher 
+to zoom when the user clicks. It does this by calculating a set of 
+points forming a line between the current position and that which was 
+clicked and adds these to m_deGotoQueue, a list of "pending points" 
+which the Model consults as a potential source of movement instructions.
+
+CColourIO: As CAlphIO, but reads colour scheme XML files.
+
+CContextBase: Base class of all language models' classes representing 
+some context for predicting input. This is typically used outside the 
+language model so that the rest of the program does not depend upon a 
+particular language model. It exposes no methods, and so contexts cannot 
+be modified outside the language model.
+
+CCustomColours: Wraps around a colour scheme object read by CColourIO; 
+used by the View classes to determine how the nodes should look.
+
+CDasherComponent: This is a base class for a large number of Dasher 
+components, and provides several basic functionalities, including the 
+handling and creation of events, and the ability to consult and modify 
+the settings store. It provides a default EventHandler which ignores all 
+events, which is designed to be overridden by subclasses. Only 
+subclasses of CDasherComponent can register themselves to listen for events.
+
+CDasherInput: This is a base class for some form of co-ordinate input 
+which provides either 1 or 2 co-ordinates. This class is abstract and 
+must be extended if you wish to provide any input to Dasher.
+
+CDasherInterfaceBase: This is the central class of the Dasher core. It 
+provides centralised functions which have widespread consequences 
+including Start(), ChangeAlphabet() and so forth. It also provides 
+NewFrame(long) which is the standard way to cause Dasher to update the 
+model and draw a frame. It does not perform much of the functionality 
+itself however; it defers the maintenance of the model to CDasherModel 
+and the drawing of it to CDasherView and its children.
+
+It includes a number of abstract methods which are 
+implementation-dependent. These must be implemented to produce a working 
+Dasher, but most can be stubbed safely. The only issue which is 
+genuinely important is to ensure that a CSettingsStore (or subclass) is 
+produced before any CDasherComponents are created (which would depend 
+upon it).
+
+CDasherModel: This maintains a tree of CDasherNodes, each of which 
+represents a box with a letter in it. It is responsible for deciding 
+when to create new nodes (although it defers the actual act to the 
+AlphabetManager) as well as when to delete old nodes, in collaboration 
+with the View (which informs the Model of situations such as a node 
+being too small to draw, and so a candidate for deletion). It also plays 
+a major role in making Dasher "move" by altering the crosshair position 
+in response to newFrame calls made to CDasherInterfaceBase.
+
+CDasherNode: This represents a box with a symbol in it, and is the unit 
+component of the Dasher tree maintained by the CDasherModel. It also 
+posesses a Context object (child of CContextBase) which describes the 
+prediction context for this node (ie. the data the language model should 
+use in deciding its likely successors). Nodes are also aware of their 
+size in terms of Dasher co-ordinates, though not their on-screen size.
+
+CDasherScreen: This defines an interface for drawing (or otherwise 
+outputting) graphics primitives. Some class must implement this to get 
+any visual output from Dasher, and an instance of this class must be 
+registered with the Interface by means of its ChangeScreen method.
+
+CDasherView/Square: The base and one implementation for a 'view' which 
+is to say a class for visualising the Dasher tree. Whereas the model 
+knows only the nodes' relative probabilities, the View converts these 
+into some visual representation; in the case of ViewSquare, into a set 
+of square boxes. It responds to a Draw() request by translating the 
+Model's data into primitive drawing commands executed by some 
+implementation of CDasherScreen.
+
+CDefaultFilter: Default input filter, which simply causes Dasher to zoom 
+towards wherever the user is currently hovering the mouse.
+
+CDelayedDraw: Helper class for drawing boxes with a symbol in them 
+without the risk of overwriting symbols by mistake. All text to be drawn 
+is placed on a stack, and at the end of the drawing cycle, and after all 
+other primitives have been drawn, the stack is emptied and its contents 
+drawn.
+
+CEventHandler: The event handler permits CDasherComponents to register 
+themselves as event listeners. All components register themselves as 
+part of the Component's constructor, though of course this can be 
+overridden. When an event is raised, the HandleEvent method of each is 
+called in turn with the Event as a parameter.
+
+The EventHandler does not involve any threading whatsoever, unlike 
+Java's built-in event subsystem. When a Dasher event is raised, the 
+raising method will not continue until all listeners have had their 
+HandleEvent routines called.
+
+For the eventuality that a reponse to an event causes another event to 
+be raised, the event handler keeps track of how many events are 
+currently unfinished. If a listener tries to add itself whilst this 
+number is not zero, it goes in a queue. As soon as the last event 
+finishes processing, the Components in the queue are made listeners proper.
+
+CInputFilter: Base class of all input filters. These play a pivotal role 
+in the update-model-and-draw frame cycle. They respond to both key 
+presses and mouse clicks by their keyDown methods being invoked, and the 
+drawing of a frame without cue through their Timer method, whose 
+argument specifies the time since the last frame.
+
+Typically, the start of a new frame consists of the Timer method being 
+called, which is then responsible for calling the Model's functions with 
+parameters indicating what changes need making.
+
+The inputfilter will also be invoked at the very end of the new frame 
+cycle in order to apply any view decorations it wishes to on top of the 
+standard appearance rendered by DasherView. A typical example is drawing 
+a line to the current mouse position.
+
+CLanguageModel: This is responsible for Dasher's prediction of what the 
+user is most likely to enter next. It is fed data by having its 
+EnterSymbol and LearnSymbol methods called on Context objects (children 
+of CContextBase), and will have getProbs called to determine the 
+relative sizes of CDasherNodes whenver the tree is expanded by the 
+AlphabetManager.
+
+Details of how the modelling is done is dependent on the language model 
+used. The only subclass included here is CPPMLanguageModel, but a few 
+other possibilities were explored in the original C version and can be 
+found in its source.
+
+
+IV. Contacting the Author
+=========================
+
+I can be reached on chris smowton net, cs448 cam ac uk, or 
+chris smowton cl cam ac uk 

Added: trunk/java/dasher/CAlphIO.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CAlphIO.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,838 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.io.*;
+
+import org.xml.sax.*;
+import org.xml.sax.helpers.DefaultHandler;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.parsers.SAXParser;
+
+/**
+ * 
+ * Responsible for reading a given list of XML files, extracting
+ * alphabet information, and creating a list of AlphInfo objects
+ * for each.
+ * <p>
+ * Further, after doing so, responsible for returning an AlphInfo
+ * object corresponding to a given alphabet name, and of giving
+ * a full list of available alphabets.
+ *
+ */
+public class CAlphIO {
+
+	/* CSFS: I'm not exactly sure which of these strings are plain ASCII used internally
+	 * and which are UTF-8. For now I've made mostly everything UTF-8 except for filenames.
+	 */
+	
+	/* CSFS: I have added comments detailing which XML field corresponds
+	 * to each variable.
+	 */
+	
+	/**
+	 * Pointer to the DasherInterfaceBase which requested this enumeration.
+	 * This is only used for the purposes of trying Applet-style
+	 * resource retrieval, and may safely be set to null if this
+	 * is not required. 
+	 */
+	public CDasherInterfaceBase m_Interface;
+	
+	/**
+	 * Path of system resource files, used in the course
+	 * of locating DTD files where necessary.
+	 */
+	protected String SystemLocation;
+	
+	/**
+	 * Path of user resource files, used in the course
+	 * of locating DTD files where necessary.
+	 */
+	protected String UserLocation;
+	
+	/**
+	 * Map from Strings to AlphInfo objects, used in getting
+	 * an alphabet by name.
+	 */
+	protected HashMap <String, AlphInfo> Alphabets = new HashMap<String, AlphInfo>(); 
+	// map short names (file names) to descriptions
+	
+	/**
+	 * List of filenames to parse.
+	 */
+	protected ArrayList<String> Filenames;
+	
+	/**
+	 * Map from String alphabet types to enumerated constants
+	 * (members of Opts.AlphabetTypes).
+	 */
+	public HashMap <String, Integer> StoT = new HashMap<String, Integer>();
+	
+	/**
+	 * Map from Opts.AlphabetTypes constants to their String names.
+	 */
+	public HashMap <Integer, String> TtoS = new HashMap<Integer, String>();
+		
+	/**
+	 * Whether the loaded alphabet may be altered.
+	 */
+	public boolean LoadMutable;
+	
+	/**
+	 * Parser to be used to import XML data.
+	 */
+	protected SAXParser parser;
+	
+	/**
+	 * Simple struct representing an alphabet.
+	 */
+	static class AlphInfo {
+		// Basic information
+		/**
+		 * Alphabet name
+		 */
+		String AlphID; // <alphabet name="[AlphID]">
+		
+		/**
+		 * Whether this alphabet may be altered. At present this
+		 * isn't used in Dasher, but may in the future be used
+		 * to support user-created alphabets.
+		 */
+		boolean Mutable;  // If from user we may play. If from system defaults this is immutable. User should take a copy.
+		
+		// Complete description of the alphabet:
+		/**
+		 * Training file to be used to train a language model
+		 * which uses this alphabet as its symbol-set.
+		 */
+		String TrainingFile;
+		
+		// Undocumented pending changes
+		String GameModeFile;
+		
+		/**
+		 * Preferred colour scheme of this alphabet.
+		 */
+		String PreferredColours;
+		
+		// FIXME: Redundant; should be removed.
+		int Encoding;
+		int Type; // <alphabet><encoding type="[Type]">
+		// Needs converting to the appropriate member of
+		// Opts.AlphabetTypes. The table for this is at the top of the
+		// CPP file.
+		
+		/**
+		 * Preferred orientation of this alphabet. Should be
+		 * set to a member of Opts.ScreenOrientations.
+		 */
+		int Orientation; // <alphabet><orientation type="[Orientation]">
+		// Needs converting from eg. "RL" to Opts.ScreenOrientations.RighttoLeft.
+		
+		/**
+		 * Number of characters in this alphabet.
+		 */
+		int m_iCharacters;
+		
+		/**
+		 * List of groups into which this alphabet's symbols
+		 * are categorised.
+		 */
+		ArrayList<SGroupInfo> m_vGroups = new ArrayList<SGroupInfo>(); // Enumeration of <Group name="..." b="...">
+		// Name attribute is currently ignored.
+		// Potential "label" and "visible" attributes also. Visible defaults
+		// to false for the first group, and true for all others.
+		
+		/**
+		 * Root group; contains all groups.
+		 */
+		SGroupInfo m_BaseGroup;
+		
+		/**
+		 * List of characters in this alphabet, each of which
+		 * is represented by a small character struct.
+		 * 
+		 * @see character
+		 */
+		ArrayList<character> m_vCharacters = new ArrayList<character>();
+		
+		/**
+		 * Paragraph character for this alphabet.
+		 */
+		character ParagraphCharacter = new character();       // display and edit text of paragraph character. Use ("", "") if no paragraph character.
+		
+		/**
+		 * Space character for this alphabet.
+		 */
+		character SpaceCharacter = new character();   // display and edit text of Space character. Typically (" ", "_"). Use ("", "") if no space character.
+		
+		/**
+		 * Control character for this alphabet.
+		 */
+		character ControlCharacter = new character(); // display and edit text of Control character. Typically ("", "Control"). Use ("", "") if no control character.
+		
+		// Added for Kanji Conversion by T.Kaburagi 15 July 2005
+		/**
+		 * Start conversion character for this alphabet.
+		 * (Used to convert Hiragana to Kanji)
+		 */
+		character StartConvertCharacter = new character();
+		
+		/**
+		 * End conversion character for this alphabet.
+		 * (Used to convert Hiragana to Kanji)
+		 */
+		character EndConvertCharacter = new character();
+				
+	}
+	
+	/**
+	 * Simple struct representing a character in an alphabet.
+	 * <p>
+	 * The Display and Text attributes are usually the same,
+	 * but are distinguished in that Display is used when drawing
+	 * the symbol in a DasherNode on the screen, and Text when
+	 * printing it as output.
+	 * <p>
+	 * An example of a characters with a difference is most
+	 * combining accents, which commonly use a dotted circle or
+	 * other decorative item to represent the letter with which
+	 * they will combine, which of course does not appear when
+	 * it is entered as text. 
+	 */	
+	static class character {
+		/**
+		 * String representation for display purposes.
+		 */
+		String Display = ""; // <s d="...">
+		/**
+		 * String representation for typing in the edit box.
+		 */
+		String Text = ""; // <s t="...">
+		/**
+		 * Background colour
+		 */		
+		int Colour; // <s b="..."> (b for Background)
+		/**
+		 * Foreground colour
+		 */
+		String Foreground = ""; // <s f="...">
+		// Seems to represent only the name of a colour, which is always ASCII anyway.
+	}
+	
+	/**
+	 * Sole constructor. This will parse the list of files given in Fnames
+	 * by attempting both ordinary file I/O and applet-style
+	 * web retrieval. Once the constructor terminates, all XML
+	 * files have been read and the object is ready to be queried
+	 * for alphabet names.
+	 *  
+	 * @param SysLoc System data location, for retrieval of DTD files. Optional; if not supplied, this location will not be considered for DTD location.
+	 * @param UserLoc User data location, for retrieval of DTD files. Optional; if not supplied, this location will not be considered for DTD location.
+	 * @param Fnames Filenames to parse; these may be relative or absolute.
+	 * @param Interface Reference to the InterfaceBase parent class for applet-style IO. Optional; if not supplied, applet-style IO will fail.
+	 */
+	public CAlphIO(String SysLoc, String UserLoc, ArrayList<String> Fnames, CDasherInterfaceBase Interface) {
+		SystemLocation = SysLoc;
+		UserLocation = UserLoc;
+		Filenames = Fnames;
+		LoadMutable = false;
+		m_Interface = Interface;
+		CreateDefault();
+		
+		SAXParserFactory factory = SAXParserFactory.newInstance();
+		
+		try {
+			parser = factory.newSAXParser();
+		}
+		catch(Exception e) {
+			System.out.printf("Error creating SAX parser: %s%n", e);
+			return;
+		}
+		
+		/* CSFS: Method of translating between string representations
+		 * and numerical indentifiers altered to use a HashMap; however
+		 * this might not be optimal, will consider changing this later.
+		 */
+		
+		TtoS.put(0, "None");
+		TtoS.put(Opts.AlphabetTypes.Arabic, "Arabic");
+		TtoS.put(Opts.AlphabetTypes.Baltic, "Baltic");
+		TtoS.put(Opts.AlphabetTypes.CentralEurope, "CentralEurope");
+		TtoS.put(Opts.AlphabetTypes.ChineseSimplified, "ChineseSimplified");
+		TtoS.put(Opts.AlphabetTypes.ChineseTraditional, "ChineseTraditional");
+		TtoS.put(Opts.AlphabetTypes.Cyrillic, "Cyrillic");
+		TtoS.put(Opts.AlphabetTypes.Greek, "Greek");
+		TtoS.put(Opts.AlphabetTypes.Hebrew, "Hebrew");
+		TtoS.put(Opts.AlphabetTypes.Japanese, "Japanese");
+		TtoS.put(Opts.AlphabetTypes.Korean, "Korean");
+		TtoS.put(Opts.AlphabetTypes.Thai, "Thai");
+		TtoS.put(Opts.AlphabetTypes.Turkish, "Turkish");
+		TtoS.put(Opts.AlphabetTypes.VietNam, "VietNam");
+		TtoS.put(Opts.AlphabetTypes.Western, "Western");
+		
+		for(Map.Entry<Integer, String> m : TtoS.entrySet()) {
+			StoT.put(m.getValue(), m.getKey());
+		}
+	
+		LoadMutable = false;
+		ParseFile(SystemLocation + "alphabet.xml");
+		if(Filenames.size() > 0) {
+			for(int i = 0; i < Filenames.size(); i++) {
+				ParseFile(SystemLocation + Filenames.get(i));
+			}
+		}
+		LoadMutable = true;
+		ParseFile(UserLocation + "alphabet.xml");
+		if(Filenames.size() > 0) {
+			for(int i = 0; i < Filenames.size(); i++) {
+				ParseFile(UserLocation + Filenames.get(i));
+			}
+		} 
+		
+		
+	}
+	
+	/**
+	 * Parse a given XML file for alphabets. Any resulting alphabets
+	 * will be added to the internal buffer ready for retrieval
+	 * using GetInfo or GetAlphabets.
+	 * 
+	 * @param filename File to parse
+	 */
+	public void ParseFile(String filename) {
+		
+		InputStream FileInput;
+		try {
+			FileInput = new FileInputStream(filename);
+			// Try ordinary IO
+		}
+		catch(Exception e) {
+			try {
+				FileInput = m_Interface.getResourceStream(filename);
+				// Try applet-style IO
+			}
+			catch(Exception ex) {
+				return; // If the file cannot be retrieved, act as if it does not exist at all.
+			}
+		}
+				
+		InputSource XMLInput = new InputSource(FileInput);
+		
+		DefaultHandler handler = new AlphXMLHandler(Alphabets, this, SystemLocation, UserLocation);
+		// Pass in the Alphabet HashMap so it can be modified
+		try {
+			parser.parse(XMLInput, handler);
+		}
+		catch (Exception e) {
+			System.out.printf("Exception reading %s: %s%n", filename, e.toString());
+			return; // Again, an invalid file should be treated as if it isn't there.
+		}
+				
+	}
+	
+	/**
+	 * Fills the passed Collection with the names of all available alphabets.
+	 * 
+	 * @param AlphabetList Collection to be filled. 
+	 */
+	public void GetAlphabets(java.util.Collection<String> AlphabetList) {
+		
+		/* CSFS: Changed from a C++ listIterator */
+		
+		AlphabetList.clear();
+		for(Map.Entry<String, AlphInfo> m : Alphabets.entrySet()) {
+			AlphabetList.add(m.getValue().AlphID);
+		}
+	}
+	
+	/**
+	 * Retrieves the name of the default alphabet. At present this
+	 * will return English with limited punctuation if available,
+	 * or Default if not.
+	 * 
+	 * @return Name of a reasonable default alphabet.
+	 */
+	public String GetDefault() {
+		if(Alphabets.containsKey("English with limited punctuation")) {
+			return ("English with limited punctuation");
+		}
+		else {
+			return ("Default");
+		}
+	}
+	
+	/**
+	 * Returns an AlphInfo object representing the alphabet with
+	 * a given name. In the event that it could not be found,
+	 * the Default alphabet is returned instead. To ensure that
+	 * this is not the case, check the available alphabets first
+	 * using GetAlphabets().
+	 * 
+	 * @param AlphID Name of the alphabet to be retrieved.
+	 * @return Either the asked alphabet, or the default.
+	 */
+	public AlphInfo GetInfo(String AlphID) {
+		if(Alphabets.containsKey(AlphID)) {
+			// if we have the alphabet they ask for, return it
+			return Alphabets.get(AlphID);
+		}
+		else {
+			// otherwise, give them default - it's better than nothing
+			return Alphabets.get("Default");
+		}
+	}
+	
+	/**
+	 * Registers a new AlphInfo object as a valid alphabet, which
+	 * will henceforth be included in enumerations of available
+	 * alphabets.
+	 * 
+	 * @param NewInfo New alphabet
+	 */
+	public void SetInfo(AlphInfo NewInfo) {
+		Alphabets.put(NewInfo.AlphID, NewInfo);
+		Save(NewInfo.AlphID);
+	}
+	
+	/**
+	 * Removes a given alphabet; it will no longer appear in
+	 * enumerations of alphabets. If it does not exist,
+	 * this method will return without error.
+	 * 
+	 * @param AlphID
+	 */
+	public void Delete(String AlphID) {
+		Alphabets.remove(AlphID);
+	}
+	
+	/**
+	 * Stub. At present Dasher does not permit users to
+	 * specify their own alphabets, but in the case that this
+	 * were introduced, this method would write out an XML
+	 * document for the new alphabet.
+	 * 
+	 * @param AlphID Name of alphabet to save.
+	 */
+	public void Save(String AlphID) {
+		// stub, for now.
+	}
+	
+	/**
+	 * Creates the default alphabet and stores as an available
+	 * alphabet. This will be returned in the case that a requested
+	 * alphabet cannot be retrieved; at present it is essentially
+	 * lower-case english with no punctuation or numerals.
+	 * <p>
+	 * The constructor calls this method prior to attempting
+	 * to read XML files; it should not need to be called
+	 * more than once unless the Default is deleted.
+	 *
+	 */
+	protected void CreateDefault() {
+		// TODO I appreciate these strings should probably be in a resource file.
+		// Not urgent though as this is not intended to be used. It's just a
+		// last ditch effort in case file I/O totally fails.
+		AlphInfo Default = new AlphInfo();
+		Default.AlphID = "Default";
+		Default.Type = Opts.AlphabetTypes.Western;
+		Default.Mutable = false;
+		Default.Orientation = Opts.ScreenOrientations.LeftToRight;
+		Default.ParagraphCharacter.Display = "¶";
+		Default.ParagraphCharacter.Text = "\r\n";
+		Default.SpaceCharacter.Display = "_";
+		Default.SpaceCharacter.Text = " ";
+		Default.SpaceCharacter.Colour = 9;
+		Default.ControlCharacter.Display = "Control";
+		Default.ControlCharacter.Text = "";
+		Default.ControlCharacter.Colour = 8;
+		Default.TrainingFile = "training_english_GB.txt";
+		Default.GameModeFile = "gamemode_english_GB.txt";
+		Default.PreferredColours = "Default";
+		String Chars = "abcdefghijklmnopqrstuvwxyz";
+		
+		Default.m_BaseGroup = null;
+		character temp;
+		
+		for(Character c : Chars.toCharArray()) {
+			temp = new character();
+			temp.Text = c.toString();
+			temp.Display = c.toString();
+			temp.Colour = 10;
+			Default.m_vCharacters.add(temp);
+		}
+		
+		Alphabets.put("Default", Default);
+	}
+	
+}
+
+/**
+ * 
+ * SAX XML handler which populates AlphInfo objects and adds them
+ * to the AlphIO class list of available alphabets.
+ *
+ */
+class AlphXMLHandler extends DefaultHandler {
+	
+	protected HashMap<String, CAlphIO.AlphInfo> Alphs;
+	protected CAlphIO m_Parent;
+	protected CAlphIO.AlphInfo currentAlph;
+	protected String currentTag;
+	protected SGroupInfo currentGroup;
+	protected boolean bFirstGroup;
+	
+	protected String systemLoc, userLoc;
+	
+	public AlphXMLHandler(HashMap<String, CAlphIO.AlphInfo> i_Alph, CAlphIO parent, String sysloc, String userloc) {
+		Alphs = i_Alph;
+		m_Parent = parent; 
+		
+		userLoc = userloc;
+		systemLoc = sysloc;
+	}
+
+	public void startElement(String namespaceURI, String simpleName, String qualName, Attributes tagAttributes) throws SAXException {
+		
+		String tagName = (simpleName.equals("") ? qualName : simpleName);
+		
+		if(tagName == "alphabet") {
+			/* A new alphabet is beginnning. Initialise the data structure
+			 * and fill it with default values. */
+			
+			currentAlph = new CAlphIO.AlphInfo();
+			currentAlph.Mutable = m_Parent.LoadMutable;
+		    currentAlph.SpaceCharacter.Colour = -1;
+		    currentAlph.ParagraphCharacter.Colour = -1;
+		    currentAlph.ControlCharacter.Colour = -1;
+		    currentAlph.StartConvertCharacter.Text = "";
+		    currentAlph.EndConvertCharacter.Text = "";
+		    currentAlph.m_iCharacters = 1; // Start at 1 as 0 is the root node symbol
+		    currentAlph.m_BaseGroup = null;
+		    
+		    bFirstGroup = true;
+		    
+		    /* Find the 'name' attribute */
+		    for(int i = 0; i < tagAttributes.getLength(); i++) {
+		    	String attributeName = (tagAttributes.getLocalName(i).equals("") ? tagAttributes.getQName(i) : tagAttributes.getLocalName(i));
+		    	if(attributeName == "name") {
+		    		currentAlph.AlphID = tagAttributes.getValue(i);
+		    	}
+		    }
+		    
+		}
+		
+		else if(tagName == "orientation") {
+			for(int i = 0; i < tagAttributes.getLength(); i++) {
+				String attributeName = (tagAttributes.getLocalName(i).equals("") ? tagAttributes.getQName(i) : tagAttributes.getLocalName(i));
+				if(attributeName == "type") {
+					String orient = tagAttributes.getValue(i);
+					if(orient == "RL") {
+						currentAlph.Orientation = Opts.ScreenOrientations.RightToLeft;
+					}
+					else if(orient == "TB") {
+						currentAlph.Orientation = Opts.ScreenOrientations.TopToBottom;
+					}
+					else if(orient == "BT") {
+						currentAlph.Orientation = Opts.ScreenOrientations.BottomToTop;
+					}
+					else {
+						currentAlph.Orientation = Opts.ScreenOrientations.LeftToRight;
+					}
+				}
+			}
+		}
+		
+		else if(tagName == "encoding") {
+			for(int i = 0; i < tagAttributes.getLength(); i++) {
+				String attributeName = (tagAttributes.getLocalName(i).equals("") ? tagAttributes.getQName(i) : tagAttributes.getLocalName(i));
+				if(attributeName == "type") {
+					currentAlph.Encoding = m_Parent.StoT.get(tagAttributes.getValue(i));
+				}
+			}
+		}
+		
+		else if(tagName == "palette") {
+			currentTag = "palette"; // will be handled by characters routine
+		}
+		
+		else if(tagName == "train") {
+			currentTag = "train"; // Likewise
+		}
+		
+		else if(tagName == "paragraph") {
+			for(int i = 0; i < tagAttributes.getLength(); i++) {
+				String attributeName = (tagAttributes.getLocalName(i).equals("") ? tagAttributes.getQName(i) : tagAttributes.getLocalName(i));
+				if(attributeName == "d") {
+					currentAlph.ParagraphCharacter.Display = tagAttributes.getValue(i);
+					currentAlph.ParagraphCharacter.Text = String.format("%n");
+					
+					/* CSFS: This slightly odd route is used because the traditional method,
+					 * which is to read the system property 'line.seperator' is in fact
+					 * forbidden for applets! Why it's potentially dangerous to establish
+					 * how to terminate lines, I'm not sure.
+					 */
+					
+				}
+				if(attributeName == "b") {
+					currentAlph.ParagraphCharacter.Colour = Integer.parseInt(tagAttributes.getValue(i));
+				}
+				if(attributeName == "f") {
+					currentAlph.ParagraphCharacter.Foreground = tagAttributes.getValue(i);
+				}
+			}	
+		}
+		
+		else if(tagName == "paragraph") {
+			for(int i = 0; i < tagAttributes.getLength(); i++) {
+				String attributeName = (tagAttributes.getLocalName(i).equals("") ? tagAttributes.getQName(i) : tagAttributes.getLocalName(i));
+				if(attributeName == "d") {
+					currentAlph.ParagraphCharacter.Display = tagAttributes.getValue(i);
+					currentAlph.ParagraphCharacter.Text = System.getProperty("line.seperator");
+				}
+				if(attributeName == "b") {
+					currentAlph.ParagraphCharacter.Colour = Integer.parseInt(tagAttributes.getValue(i));
+				}
+				if(attributeName == "f") {
+					currentAlph.ParagraphCharacter.Foreground = tagAttributes.getValue(i);
+				}
+			}	
+		}
+		
+		else if(tagName == "space") {
+			for(int i = 0; i < tagAttributes.getLength(); i++) {
+				String attributeName = (tagAttributes.getLocalName(i).equals("") ? tagAttributes.getQName(i) : tagAttributes.getLocalName(i));
+				if(attributeName == "d") {
+					currentAlph.SpaceCharacter.Display = tagAttributes.getValue(i);
+				}
+				if(attributeName == "t") {
+					currentAlph.SpaceCharacter.Text = tagAttributes.getValue(i);
+				}
+				if(attributeName == "b") {
+					currentAlph.SpaceCharacter.Colour = Integer.parseInt(tagAttributes.getValue(i));
+				}
+				if(attributeName == "f") {
+					currentAlph.SpaceCharacter.Foreground = tagAttributes.getValue(i);
+				}
+			}	
+		}
+		
+		else if(tagName == "control") {
+			for(int i = 0; i < tagAttributes.getLength(); i++) {
+				String attributeName = (tagAttributes.getLocalName(i).equals("") ? tagAttributes.getQName(i) : tagAttributes.getLocalName(i));
+				if(attributeName == "d") {
+					currentAlph.ControlCharacter.Display = tagAttributes.getValue(i);
+				}
+				if(attributeName == "t") {
+					currentAlph.ControlCharacter.Text = tagAttributes.getValue(i);
+				}
+				if(attributeName == "b") {
+					currentAlph.ControlCharacter.Colour = Integer.parseInt(tagAttributes.getValue(i));
+				}
+				if(attributeName == "f") {
+					currentAlph.ControlCharacter.Foreground = tagAttributes.getValue(i);
+				}
+			}	
+		}
+		
+		else if(tagName == "convert") {
+			for(int i = 0; i < tagAttributes.getLength(); i++) {
+				String attributeName = (tagAttributes.getLocalName(i).equals("") ? tagAttributes.getQName(i) : tagAttributes.getLocalName(i));
+				if(attributeName == "d") {
+					currentAlph.StartConvertCharacter.Display = tagAttributes.getValue(i);
+				}
+				if(attributeName == "t") {
+					currentAlph.StartConvertCharacter.Text = tagAttributes.getValue(i);
+				}
+				if(attributeName == "b") {
+					currentAlph.StartConvertCharacter.Colour = Integer.parseInt(tagAttributes.getValue(i));
+				}
+				if(attributeName == "f") {
+					currentAlph.StartConvertCharacter.Foreground = tagAttributes.getValue(i);
+				}
+			}	
+		}
+		
+		else if(tagName == "protect") {
+			for(int i = 0; i < tagAttributes.getLength(); i++) {
+				String attributeName = (tagAttributes.getLocalName(i).equals("") ? tagAttributes.getQName(i) : tagAttributes.getLocalName(i));
+				if(attributeName == "d") {
+					currentAlph.EndConvertCharacter.Display = tagAttributes.getValue(i);
+				}
+				if(attributeName == "t") {
+					currentAlph.EndConvertCharacter.Text = tagAttributes.getValue(i);
+				}
+				if(attributeName == "b") {
+					currentAlph.EndConvertCharacter.Colour = Integer.parseInt(tagAttributes.getValue(i));
+				}
+				if(attributeName == "f") {
+					currentAlph.EndConvertCharacter.Foreground = tagAttributes.getValue(i);
+				}
+			}	
+		}
+		
+		else if(tagName == "group") {
+			
+			currentGroup = new SGroupInfo();
+			
+			if(bFirstGroup) {
+				currentGroup.bVisible = false;
+				bFirstGroup = false;
+			}
+			else {
+				currentGroup.bVisible = true;
+			}
+			
+			currentGroup.strLabel = "";
+			currentGroup.iColour = 0;
+			
+			for(int i = 0; i < tagAttributes.getLength(); i++) {
+				String attributeName = (tagAttributes.getLocalName(i).equals("") ? tagAttributes.getQName(i) : tagAttributes.getLocalName(i));
+				if(attributeName == "b") {
+					currentGroup.iColour = Integer.parseInt(tagAttributes.getValue(i));
+				}
+				if(attributeName == "visible") {
+					if(tagAttributes.getValue(i).equals("yes") || tagAttributes.getValue(i).equals("on")) {
+						currentGroup.bVisible = true;
+					}
+					else if(tagAttributes.getValue(i).equals("no") || tagAttributes.getValue(i).equals("off")) {						
+						currentGroup.bVisible = false;
+					}
+				}
+				if(attributeName == "label") {
+					currentGroup.strLabel = tagAttributes.getValue(i);
+				}
+			}
+			
+		    currentGroup.iStart = currentAlph.m_iCharacters;
+
+		    currentGroup.Child = null;
+
+		    if(currentAlph.m_vGroups.size() > 0) {
+		      currentGroup.Next = currentAlph.m_vGroups.get(currentAlph.m_vGroups.size() - 1).Child;
+		      currentAlph.m_vGroups.get(currentAlph.m_vGroups.size() - 1).Child = currentGroup;
+		    }
+		    else {
+		      currentGroup.Next = currentAlph.m_BaseGroup;
+		      currentAlph.m_BaseGroup = currentGroup;
+		    }
+		    
+		    currentAlph.m_vGroups.add(currentGroup);
+		}
+				
+		else if(tagName == "s") {
+			CAlphIO.character newChar = new CAlphIO.character();
+			newChar.Colour = -1;
+			++currentAlph.m_iCharacters;
+			
+			for(int i = 0; i < tagAttributes.getLength(); i++) {
+				String attributeName = (tagAttributes.getLocalName(i).equals("") ? tagAttributes.getQName(i) : tagAttributes.getLocalName(i));
+				if(attributeName == "d") {
+					newChar.Display = tagAttributes.getValue(i);
+				}
+				if(attributeName == "t") {
+					newChar.Text = tagAttributes.getValue(i);
+				}
+				if(attributeName == "b") {
+					newChar.Colour = Integer.parseInt(tagAttributes.getValue(i));
+				}
+				if(attributeName == "f") {
+					newChar.Foreground = tagAttributes.getValue(i);
+				}
+			}
+			
+			currentAlph.m_vCharacters.add(newChar);
+		}
+	}
+	
+	public void endElement(String namespaceURI, String simpleName, String qualName) {
+		String tagName = (simpleName.equals("") ? qualName : simpleName);
+		
+		if(tagName == "alphabet") {
+			Alphs.put(currentAlph.AlphID, currentAlph);
+		}
+		
+		else if(tagName == "palette") {
+			currentTag = "";
+		}
+		
+		else if(tagName == "train") {
+			currentTag = "";
+		}
+		// Both of these are to prevent the parser from dumping unwanted CDATA
+		// once the tags we're interested in have been closed.
+
+		else if(tagName == "group") {
+			currentAlph.m_vGroups.get(currentAlph.m_vGroups.size() - 1).iEnd = currentAlph.m_iCharacters;
+			currentAlph.m_vGroups.remove(currentAlph.m_vGroups.get(currentAlph.m_vGroups.size() - 1));
+		}
+		
+
+		
+	}
+
+	public void characters(char[] chars, int start, int length) throws SAXException {
+		
+		if(currentTag == "palette") {
+			currentAlph.PreferredColours = new String(chars, start, length);
+		}
+		
+		if(currentTag == "train") {
+			currentAlph.TrainingFile = new String(chars, start, length);
+		}
+		
+	}
+
+	public InputSource resolveEntity(String publicName, String systemName) throws IOException, SAXException {
+		
+		if(systemName.contains("alphabet.dtd")) {
+			try {
+				return new InputSource(new FileInputStream(systemLoc + "alphabet.dtd"));
+			}
+			catch(Exception e) {
+				try {
+					return new InputSource(new FileInputStream(userLoc + "alphabet.dtd"));
+				}
+				catch(Exception ex) {
+					return new InputSource(m_Parent.m_Interface.getResourceStream(systemLoc + "alphabet.dtd"));
+				}
+			}
+		}
+		else {
+			return null;
+		}
+		
+		
+		/* CSFS: This is here because SAX will by default look in a system location
+		 * first, which throws a security exception when running as an Applet.
+		 */
+	
+	}
+	
+}

Added: trunk/java/dasher/CAlphabet.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CAlphabet.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,642 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+package dasher;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Represents an Alphabet, including a list of its symbols,
+ * their appearance on screen and when typed, and their foreground
+ * and background colours.
+ * <p>
+ * Note that the colours specified here are mere ordinal numbers;
+ * the resolution of these into actual displayable colours is
+ * the responsibility of CCustomColours.
+ * <p>
+ * This class is also responsible for translating a tract of text
+ * into a sequence of logical symbol identifiers (see <code>
+ * GetSymbols</code>)
+ */
+
+public class CAlphabet {
+	
+	/**
+	 * This alphabet's default orientation. Valid values are
+	 * specified by Opts.AlphabetTypes, and indicate
+	 * left-to-right, right-to-left, top-to-bottom or
+	 * bottom-to-top screen orientation.
+	 */
+	protected int m_Orientation;
+	
+	/**
+	 * The symbol number of the new-paragraph character.
+	 */
+	protected int m_ParagraphSymbol;
+	
+	/**
+	 * The symbol number of the space character.
+	 */
+	protected int m_SpaceSymbol;
+	
+	/**
+	 * The symbol number of the control node.
+	 * 
+	 * Currently redundant as control mode is not implemented
+	 * in Java.
+	 */
+	protected int m_ControlSymbol;
+	
+	//-- Added for Kanji Conversion 13 July 2005 by T.Kaburagi
+	
+	/**
+	 * The symbol number of the Start Conversion symbol.
+	 * 
+	 * Current redundant as kanji conversion is not yet
+	 * implemented in Java.
+	 */
+	protected int m_StartConversionSymbol;
+	
+
+	/**
+	 * The symbol number of the End Conversion symbol.
+	 * 
+	 * Current redundant as kanji conversion is not yet
+	 * implemented in Java.
+	 */
+	protected int m_EndConversionSymbol;
+	
+	/**
+	 * Path of a file containing training text relevant
+	 * to this alphabet.
+	 */
+	protected String m_TrainingFile;
+	
+	// Undocumented as the future of this isn't decided.
+	protected String m_GameModeFile;
+	
+	/**
+	 * Name of the colour scheme which this alphabet
+	 * 'prefers' to use. This class does not enforce its
+	 * use.
+	 */
+	protected String m_DefaultPalette;
+		
+	/**
+	 * Symbols' representations when typed. These are Strings
+	 * and not Characters because some alphabets may define
+	 * multi-character symbols.
+	 */
+	protected ArrayList<String> m_Characters; // stores the characters
+	
+	/**
+	 * Symbols' representations on screen. Usually this is the
+	 * same as m_Characters, but some symbols are displayed
+	 * with extra ornamentation on screen, such as the apostrophe
+	 * in English, and most combining accent characters.
+	 */
+	protected ArrayList<String> m_Display;      // stores how the characters are visually represented in the Dasher nodes
+	
+	/**
+	 * Symbols' background colours, used by CDasherView to display
+	 * their nodes. These colour identifiers must be looked up
+	 * by an instance of CCustomColours to retrieve actual RGB
+	 * colours.
+	 */
+	protected ArrayList<Integer> m_Colours;       // stores the colour of the characters
+	
+	/**
+	 * Stores the foreground colour of the symbols.
+	 */
+	protected ArrayList<String> m_Foreground;   // stores the colour of the character foreground
+	
+	/**
+	 * Root of the group tree. Contains all other groups.
+	 */
+	public SGroupInfo m_BaseGroup = new SGroupInfo();
+	
+	/**
+	 * Mapping from text to symbol numbers, for use in parsing
+	 * training text.
+	 */
+	protected CAlphabetMap TextMap;
+	
+	/* CSFS: It would be good to fix the code duplication between these
+	 * two constructors.
+	 */
+	
+		
+	/**
+	 * Default constructor; produces an alphabet containing no
+	 * characters. Characters may subsequently be added by
+	 * calling AddChar. Special characters should be added
+	 * by using AddParagraphSymbol, AddSpaceSymbol, and so forth.
+	 */
+	
+	public CAlphabet() {
+		m_Orientation = Opts.ScreenOrientations.LeftToRight;
+		m_ControlSymbol = -1; 
+				
+		m_Characters = new ArrayList<String>();
+		m_Display = new ArrayList<String>();
+		m_Colours = new ArrayList<Integer>();
+		m_Foreground = new ArrayList<String>();
+		
+		m_Characters.add("");
+		m_Display.add("");
+		m_Colours.add(-1);
+		m_Foreground.add("");
+		TextMap = new CAlphabetMap();
+		
+	}
+	
+	/**
+	 * Produces a ready-made Alphabet from an AlphInfo class
+	 * which specifies the alphabet. These are typically produced
+	 * by an instance of CAlphIO by reading alphabet.*.xml files
+	 * but may be producd by other means.
+	 * <p>
+	 * The alphabet produced will have special characters
+	 * (such as the start conversion character) only if AlphabetInfo
+	 * specifies their text as having non-zero length.
+	 * 
+	 * @param AlphabetInfo The AlphInfo class containing the
+	 * 					   alphabet specification.
+	 * @see CAlphIO
+	 * @see CAlphIO.AlphInfo
+	 */
+	
+	public CAlphabet(CAlphIO.AlphInfo AlphabetInfo) { 
+		m_Orientation = Opts.ScreenOrientations.LeftToRight;
+		m_ControlSymbol = (-1);
+		
+		int nSymbols = AlphabetInfo.m_iCharacters + 5;
+		// +5 because of space, paragraph, control, start/end conversion.
+		
+		m_Characters = new ArrayList<String>(nSymbols);
+		m_Display = new ArrayList<String>(nSymbols);
+		m_Colours = new ArrayList<Integer>(nSymbols);
+		m_Foreground = new ArrayList<String>(nSymbols);
+		
+		m_Characters.add("");
+		m_Display.add("");
+		m_Colours.add(-1);
+		m_Foreground.add("");
+		TextMap = new CAlphabetMap();
+		
+		m_StartConversionSymbol = -1;
+		m_EndConversionSymbol = -1;
+		
+		// Set miscellaneous options
+		
+		SetOrientation(AlphabetInfo.Orientation);
+		SetTrainingFile(AlphabetInfo.TrainingFile);
+		SetGameModeFile(AlphabetInfo.GameModeFile);
+		SetPalette(AlphabetInfo.PreferredColours);
+		
+				
+		for(CAlphIO.character temp : AlphabetInfo.m_vCharacters) {
+			AddChar(temp.Text, temp.Display, temp.Colour, temp.Foreground);
+		}
+			
+		// Set Space character if requested
+		
+		if(AlphabetInfo.ParagraphCharacter.Text.length() != 0)
+			AddParagraphSymbol(AlphabetInfo.ParagraphCharacter.Text, AlphabetInfo.ParagraphCharacter.Display, AlphabetInfo.ParagraphCharacter.Colour, AlphabetInfo.ParagraphCharacter.Foreground);
+		
+		
+		if(AlphabetInfo.SpaceCharacter.Text.length() != 0)
+			AddSpaceSymbol(AlphabetInfo.SpaceCharacter.Text, AlphabetInfo.SpaceCharacter.Display, AlphabetInfo.SpaceCharacter.Colour, AlphabetInfo.SpaceCharacter.Foreground);
+		
+		//-- Added for Kanji Conversion 13 July 2005 by T.Kaburagi START
+		if(AlphabetInfo.StartConvertCharacter.Text.length() != 0)
+			AddStartConversionSymbol(AlphabetInfo.StartConvertCharacter.Text, AlphabetInfo.StartConvertCharacter.Display, AlphabetInfo.StartConvertCharacter.Colour, AlphabetInfo.StartConvertCharacter.Foreground);
+		
+		if(AlphabetInfo.EndConvertCharacter.Text.length() != 0)
+			AddEndConversionSymbol(AlphabetInfo.EndConvertCharacter.Text, AlphabetInfo.EndConvertCharacter.Display, AlphabetInfo.EndConvertCharacter.Colour, AlphabetInfo.EndConvertCharacter.Foreground);
+		//-- Added for Kanji Conversion 13 July 2005 by T.Kaburagi END
+		
+		// DJW - now the control symbol is always a part of the alphabet
+		// DasherModel knows whether or not to use it
+		
+		// FIXME - We really need to ensure that the control symbol is last in the alphabet with the current logic.
+		
+		if(AlphabetInfo.ControlCharacter.Display.length() != 0 && GetControlSymbol() == -1)
+			AddControlSymbol(AlphabetInfo.ControlCharacter.Text, AlphabetInfo.ControlCharacter.Display, AlphabetInfo.ControlCharacter.Colour, AlphabetInfo.ControlCharacter.Foreground);
+		
+		// New group stuff
+		
+		m_BaseGroup = AlphabetInfo.m_BaseGroup;
+		
+	}
+	
+	/**
+	 * Converts a string of text into a list of symbol indentifiers.
+	 * Typically used in the course of training a language model,
+	 * this fills the Symbols Collection with a seqeunce of integer
+	 * symbol identifiers. Each character is individually
+	 * used as a key into TextMap to determine its symbol number;
+	 * as such their is no support for multi-character symbols
+	 * at present. 
+	 * 
+	 * @param Symbols Collection to be filled with symbol identifiers.
+	 * @param Input String to be converted.
+	 * @param IsMore Redundant parameter; used to signal that the last
+	 * 			 	 input character may be an incomplete UTF-8
+	 * 				 character, but redundant since UTF-16 is now
+	 * 				 used internally.
+	 */
+	
+	public void GetSymbols(Collection<Integer> Symbols, String Input, boolean IsMore) {
+		
+		for(char c : Input.toCharArray()) {
+			Symbols.add((TextMap.Get(new Character(c).toString())).symbol);
+		}
+	
+	}
+	
+	/**
+	 * Adds a new character to this alphabet. The new character will
+	 * be assigned the next free symbol index.
+	 * 
+	 * @param NewCharacter Representation of this character as to be shown in textual output.
+	 * @param Display Representation to be shown on screen.
+	 * @param Colour Background colour index to be used in drawing nodes containing this character. 
+	 * @param Foreground Foreground colour to be used drawing the text..
+	 */
+	
+	public void AddChar(String NewCharacter, String Display, int Colour, String Foreground) {
+		m_Characters.add(NewCharacter);
+		m_Display.add(Display);
+		m_Colours.add(Colour);
+		m_Foreground.add(Foreground);
+		
+		int ThisSymbol = m_Characters.size() - 1;
+		TextMap.Add(NewCharacter, ThisSymbol);
+	}
+	
+	/**
+	 * Adds a paragraph symbol to the alphabet. Since there is only
+	 * one identifier for the paragraph symbol, if multiple
+	 * paragraph symbols are added all but the latest will
+	 * lose their status and will become ordinary symbols.
+	 * 
+	 * @param NewCharacter Representation of this character as to be shown in textual output.
+	 * @param Display Representation to be shown on screen.
+	 * @param Colour Background colour index to be used in drawing nodes containing this character. 
+	 * @param Foreground Foreground colour to be used drawing the text..
+	 */
+	
+	public void AddParagraphSymbol(String NewCharacter, String Display, int Colour, String Foreground) {
+		AddChar(NewCharacter, Display, Colour, Foreground);
+		m_ParagraphSymbol = GetNumberSymbols() - 1;
+	}
+	
+	/**
+	 * Adds a space symbol to the alphabet. Since there is only
+	 * one identifier for the space symbol, if multiple space
+	 * symbols are added all but the latest will lose their
+	 * status and will become ordinary symbols.
+	 * 
+	 * @param NewCharacter Representation of this character as to be shown in textual output.
+	 * @param Display Representation to be shown on screen.
+	 * @param Colour Background colour index to be used in drawing nodes containing this character. 
+	 * @param Foreground Foreground colour to be used drawing the text..
+	 */
+	
+	public void AddSpaceSymbol(String NewCharacter, String Display, int Colour, String Foreground) {
+		AddChar(NewCharacter, Display, Colour, Foreground);
+		m_SpaceSymbol = GetNumberSymbols() - 1;
+	}
+	
+	/**
+	 * Adds a control symbol to the alphabet. Since there is only
+	 * one identifier for the control symbol, if multiple control
+	 * symbols are added all but the latest will lose their
+	 * status and will become ordinary symbols.
+	 * 
+	 * @param NewCharacter Redundant; the Control character is not typed.
+	 * @param Display Representation to be shown on screen. (typically 'Control')
+	 * @param Colour Background colour index to be used in drawing nodes containing this character. 
+	 * @param Foreground Foreground colour to be used drawing the text..
+	 */
+	
+	public void AddControlSymbol(String NewCharacter, String Display, int Colour, String Foreground) {
+		AddChar(NewCharacter, Display, Colour, Foreground);
+		m_ControlSymbol = GetNumberSymbols() - 1;
+	}
+	
+	/**
+	 * Adds a start-conversion symbol top the alphabet. Since there is only
+	 * one identifier for the symbol, if multiple start-conversion
+	 * symbols are added all but the latest will lose their
+	 * status and will become ordinary symbols.
+	 * 
+	 * @param NewCharacter Redundant; the conversion symbol is not a typed character in the ordinary sense.
+	 * @param Display Representation to be shown on screen.
+	 * @param Colour Background colour index to be used in drawing nodes containing this character. 
+	 * @param Foreground Foreground colour to be used drawing the text..
+	 */	
+	
+	public void AddStartConversionSymbol(String NewCharacter, String Display, int Colour, String Foreground) {
+		AddChar(NewCharacter, Display, Colour, Foreground);
+		m_StartConversionSymbol = GetNumberSymbols() - 1;
+	}
+	
+	/**
+	 * Adds an end-conversion symbol top the alphabet. Since there is only
+	 * one identifier for the end-conversion symbol, if multiple end-conversion
+	 * symbols are added all but the latest will lose their
+	 * status and will become ordinary symbols.
+	 * 
+	 * @param NewCharacter Redundant; the end-conversion symbol is not typed in the ordinary sense.
+	 * @param Display Representation to be shown on screen.
+	 * @param Colour Background colour index to be used in drawing nodes containing this character. 
+	 * @param Foreground Foreground colour to be used drawing the text..
+	 */
+	
+	public void AddEndConversionSymbol(String NewCharacter, String Display, int Colour, String Foreground) {
+		AddChar(NewCharacter, Display, Colour, Foreground);
+		m_EndConversionSymbol = GetNumberSymbols() - 1;
+	}
+
+	/**
+	 * Retrieves the text colour to be used in drawing the specified
+	 * symbol. In the case that a foreground colour was not specified
+	 * (and so the m_Foreground list contains "" at this index)
+	 * the default colour 4 is returned.
+	 * 
+	 * @param Symbol Symbol whose colour is to be looked up.
+	 * @return Colour identifier to be used drawing this text.
+	 */
+	
+	public int GetTextColour(int Symbol) {
+		String TextColour = m_Foreground.get(Symbol);
+		if(!"".equals(TextColour)) {
+			return (Integer.parseInt(TextColour)); // CSFS: This used to use atoi.
+		}
+		else {
+			return 4;
+		}
+	}
+	
+	/**
+	 * Gets number of symbols in this alphabet, including special characters.
+	 * 
+	 * @return Symbol count in this Alphabet.
+	 */
+	
+	public int GetNumberSymbols() {
+		return m_Characters.size();
+	}
+	
+	/**
+	 * Gets the number of symbols in this alphabet which are not
+	 * 'special symbols' (eg the Control symbol). In reality
+	 * this is the same as GetNumberSymbols() - 1.
+	 * <p>
+	 * This method needs improving to correctly recognise the
+	 * start conversion symbol.
+	 * 
+	 * @return Textual symbol count in this alphabet.
+	 */
+	 
+	public int GetNumberTextSymbols() {
+		return m_Characters.size() - 1;
+	} 
+	
+	/**
+	 * Gets the orientation associated with this alphabet.
+	 * Allowable values are enumerated by Opts.ScreenOrientations.
+	 * 
+	 * @return This Alphabet's preferred orientation. 
+	 */
+	
+	public int GetOrientation() {
+		return m_Orientation;
+	}
+	
+	/**
+	 * Gets the training file to be used training a language
+	 * model which uses this alphabet.
+	 * 
+	 * @return Path to the specified training file.
+	 */
+	
+	public String GetTrainingFile() {
+		return m_TrainingFile;
+	}
+	
+	// Undocumented pending changes to this.
+	
+	public String GetGameModeFile() {
+		return m_GameModeFile;
+	}
+	
+	/**
+	 * Gets the name of the colour scheme preferred by this
+	 * alphabet.
+	 * 
+	 * @return Preferred colour scheme name.
+	 */
+	
+	public String GetPalette() {
+		return m_DefaultPalette;
+	}
+	
+	/**
+	 * Gets the array of display texts. This should not be used
+	 * to make changes to the alphabet.
+	 * 
+	 * @return Reference to the array of characters' display texts.
+	 */
+	
+	public ArrayList<String> GetDisplayTexts() {
+		return m_Display;
+		// Another method for efficiency, allowing an outside class to
+		// get a handle to our display text list. This shouldn't be bad
+		// as they only get a reference and do not copy data.
+	}
+	
+	/**
+	 * Retrieves the String which should be displayed to represent a given character.
+	 * 
+	 * @param i Index of the character to be looked up.
+	 * @return Display string for this character.
+	 */
+	
+	public String GetDisplayText(int i) {
+		return m_Display.get(i);
+	}
+	
+	/**
+	 * Retrieves the typed character representation of a given symbol.
+	 * 
+	 * @param i Symbol to look up
+	 * @return Character which should be typed in the edit box (for example) to represent it.
+	 */
+	
+	public String GetText(int i) {
+		return m_Characters.get(i);
+	} 
+	
+	/**
+	 * Gets a reference to the array of background colours used
+	 * when drawing symbols. The returned array should not be
+	 * modified, and GetColour(i) should be used where possible;
+	 * this is for increased efficiency when iteration over the
+	 * array is desired.
+	 * 
+	 * @return Array of background colours.
+	 */
+	
+	public ArrayList<Integer> GetColours() {
+		// Allows another class to obtain a reference to the colour map.
+		// This is in order to increase the efficiency of PopulateChildrenWithSymbol.
+		
+		return m_Colours;
+	}
+	
+	/**
+	 * Retrieves the background colour for a given symbol.
+	 * 
+	 * @param i Symbol indentifier
+	 * @return Background colour for this symbol.
+	 */
+	
+	public int GetColour(int i) {
+		return m_Colours.get(i);
+	}
+
+	/**
+	 * Retrieves the foreground (text) colour for a given symbol.
+	 * 
+	 * @param i Symbol identifier.
+	 * @return Foreground colour for this symbol.
+	 */
+	
+	public String GetForeground(int i) {
+	      return m_Foreground.get(i);
+	} 
+
+	/**
+	 * Sets the preferred orientation for this alphabet.
+	 * 
+	 * @param Orientation New orientation.
+	 */
+	
+	public void SetOrientation(int Orientation) {
+		m_Orientation = Orientation;
+	}
+		
+	/**
+	 * Sets the training file to be used training a language
+	 * model which uses this alphabet.
+	 * 
+	 * @param TrainingFile New training file location.
+	 */
+	
+	public void SetTrainingFile(String TrainingFile) {
+		m_TrainingFile = TrainingFile;
+	}
+	
+	// Undocumented pending changes.
+	
+	public void SetGameModeFile(String GameModeFile) {
+		m_GameModeFile = GameModeFile;
+	}
+	
+	/**
+	 * Sets this alphabet's preferred colour scheme.
+	 * 
+	 * @param Palette Name of the new scheme.
+	 */
+	
+	public void SetPalette(String Palette) {
+		m_DefaultPalette = Palette;
+	}
+	
+	/**
+	 * Gets the instance of CAlphabetMap which maps Strings
+	 * to symbols in this Alphabet.
+	 * 
+	 * @return TextMap
+	 */
+	
+	public CAlphabetMap GetAlphabetMap() {
+		return TextMap;
+	}
+	
+	/**
+	 * Gets the index of this alphabet's paragraph symbol.
+	 * 
+	 * @return index of paragraph symbol.
+	 */
+	
+	public int GetParagraphSymbol()  {
+		return m_ParagraphSymbol;
+	}
+	
+	/**
+	 * Gets the index of this alphabet's space symbol.
+	 * 
+	 * @return index of space symbol.
+	 */
+	
+	public int GetSpaceSymbol()  {
+		return m_SpaceSymbol;
+	}
+	
+	/**
+	 * Gets the index of this alphabet's control symbol.
+	 * 
+	 * @return index of control symbol, or -1 if there is none.
+	 */
+	
+	public int GetControlSymbol()  {
+		return m_ControlSymbol;
+	}
+	
+	/**
+	 * Gets the index of this alphabet's start-conversion symbol.
+	 * 
+	 * @return index of start-conversion symbol, or -1 if there is none.
+	 */
+	
+	public int GetStartConversionSymbol()  {
+		return m_StartConversionSymbol;
+	}
+	
+	/**
+	 * Gets the index of this alphabet's end-conversion symbol.
+	 * 
+	 * @return index of end-conversion symbol, or -1 if there is none.
+	 */
+	
+	public int GetEndConversionSymbol()  {
+		return m_EndConversionSymbol;
+	}
+	
+}

Added: trunk/java/dasher/CAlphabetManager.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CAlphabetManager.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,475 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.ArrayList;
+
+/**
+ * AlphabetManager is a specialisation of NodeManager which
+ * knows about an Alphabet.
+ * <p>
+ * The AlphabetManager is used by the DasherModel to perform
+ * tasks which require the knowledge of which Alphabet is currently
+ * in use. This includes the handling of output of text when the
+ * user enters or leaves a given node and extending the Model's
+ * tree of DasherNodes, either forwards or backwards, whenever
+ * necessary.
+ *
+ */
+
+public class CAlphabetManager extends CNodeManager {
+
+	/**
+	 * Pointer to the LanguageModel used in determining the
+	 * relative probability assigned to new Nodes. 
+	 */
+	protected CLanguageModel m_LanguageModel;
+	
+	/**
+	 * Pointer to the DasherModel which performs some of the
+	 * work in the course of producing probabilities.
+	 */
+    protected CDasherModel m_Model;
+    
+    // Undocumented, as these are present as caches only.
+    protected int SPSymbol, ConvertSymbol, ContSymbol;
+    
+    /**
+     * Pointer to the current Alphabet, used to find out what a
+     * given character looks like typed (for the purposes
+     * of output) and displayed (if growing the DasherNode tree).
+     */
+    protected CAlphabet m_Alphabet;
+    
+    protected ArrayList<Integer> m_Colours;
+    protected ArrayList<String> m_DisplayText;
+    // Both undocumented (caches)
+        
+    /**
+     * Sole constructor: produces an AlphabetManager linked to a
+     * given Model and LanguageModel. These cannot be set after
+     * the Manager has been created; as such the Manager must
+     * be created last of these three.
+     * 
+     * @param Model Linked DasherModel
+     * @param LanguageModel Linked LanguageModel
+     */
+    
+    public CAlphabetManager( CDasherModel Model, CLanguageModel LanguageModel) {
+    	
+    	super(0); // Constructor of CNodeManager
+    	this.m_LanguageModel = LanguageModel;
+    	this.m_Model = Model;
+    	SPSymbol = Model.GetSpaceSymbol();
+    	ConvertSymbol = Model.GetStartConversionSymbol();
+    	ContSymbol = Model.GetControlSymbol();
+    	
+    	m_Alphabet = Model.GetAlphabet();
+    	m_Colours = Model.GetColours();
+    	m_DisplayText = m_Alphabet.GetDisplayTexts();
+    	
+    	/* Caching these as the repeated requests which were twice deferred were
+    	 * actually taking 5% of our runtime
+    	 */
+    }
+
+    /**
+     * Creates a new root CDasherNode with the supplied parameters.
+     */
+    public CDasherNode GetRoot(CDasherNode Parent, long iLower, long iUpper, int UserData) { // VOID POINTER CHANGED TO INT
+    	CDasherNode NewNode;
+
+    	/* CSFS: Replaced "void* UserData" with "int UserData" since as far as I can see
+    	 * it is always cast to an int* and then dereferenced. Will change this if I
+    	 * find a counterexample.
+    	 */
+    	
+    	  int iSymbol = UserData;
+
+    	  // FIXME - Make this a CDasherComponent
+
+    	  int iColour;
+    	  
+    	  if(iSymbol == 0)
+    	    iColour = 7;
+    	  else
+    	    iColour = m_Colours.get(iSymbol);
+
+
+    	  if(iSymbol == m_Model.GetSpaceSymbol())
+    	    NewNode = new CDasherNode(Parent, iSymbol, 0, EColorSchemes.Special1, iLower, iUpper, m_LanguageModel, iColour);
+    	  else
+    	    NewNode = new CDasherNode(Parent, iSymbol, 0, EColorSchemes.Nodes1, iLower, iUpper, m_LanguageModel, iColour);
+    	  
+    	  NewNode.SetContext(m_LanguageModel.CreateEmptyContext()); // FIXME - handle context properly
+    	  NewNode.m_NodeManager = this;
+    	  NewNode.m_bShove = true;
+    	  NewNode.m_BaseGroup = m_Alphabet.m_BaseGroup;
+    	  NewNode.m_strDisplayText = m_DisplayText.get(iSymbol);
+    	  NewNode.Seen(true);
+
+    	  return NewNode;
+    }
+    
+    /**
+     * Stub: AlphabetManager is not reference counted.
+     */
+    public void Ref() {};
+	
+    /**
+     * Stub: AlphabetManager is not reference counted.
+     */    
+    public void Unref() {};
+    
+    /**
+     * Populates the children of a given DasherNode.
+     * <p>
+     * This is exactly the same as calling PopulateChildrenWithSymbol(Node, -2, null);
+     * 
+     * @param Node Node to be given children.
+     */
+    public void PopulateChildren( CDasherNode Node ) {
+    	PopulateChildrenWithSymbol( Node, -2, null );
+    }
+    
+    /**
+     * Populates the children of a given Node. This function
+     * calls CLanguageModel.getProbs on the Context associated
+     * with this Node; its function is identical to the four-arg
+     * version of the function called upon the same probabilities.
+     * 
+     * @param Node Node whose children we wish to populate.
+     * @param iExistingSymbol Symbol of child node which already exists, if any; -2 if none.
+     * @param ExistingChild Reference to the pre-existing child, if one exists.  
+     */
+
+    public void PopulateChildrenWithSymbol(CDasherNode Node, int iExistingSymbol, CDasherNode ExistingChild) {
+    	long[] cum = m_Model.GetProbs(Node.Context(), (int)m_Model.GetLongParameter(Elp_parameters.LP_NORMALIZATION));
+    	
+    	PopulateChildrenWithSymbol(Node, iExistingSymbol, ExistingChild, cum);
+    }
+    
+    /**
+     * Creates the children of a given Node given a set of probabilities
+     * associated with said children and, perhaps, one child which already exists.
+     * <p>
+     * The probabilties supplied should not be cumulative, but should be normalised
+     * such that they add up to the value of LP_NORMALIZATION.
+     * 
+     * @param Node Node whose children are to be populated.
+     * @param iExistingSymbol Symbol of its existing child, or -2 if there is none.
+     * @param ExistingChild Reference to its existing child, if any.
+     * @param cum Probabilities to be associated with the children,
+     *            supplied in alphabet symbol order.
+     */    
+    public void PopulateChildrenWithSymbol( CDasherNode Node, int iExistingSymbol, CDasherNode ExistingChild, long[] cum) {
+    	
+    	// CSFS: In the name of efficiency have removed ArrayLists from all of this.
+    	// It now uses a raw array and runs much faster.
+    	
+    	// Actually create the children here
+    	
+    	// FIXME: this has to change for history stuff and Japanese dasher
+    	//ArrayList<Integer> newchars = new ArrayList<Integer>(); // place to put this list of characters
+    	    	
+    	// CSFS: At the moment, newchars(j) = j as that's all the model puts in there.
+    	// To save time I've put this in for now.
+    	
+    	int iChildCount = m_Alphabet.GetNumberSymbols();    //newchars.size();
+    	
+//  	DASHER_TRACEOUTPUT("ChildCount %d\n", iChildCount);
+    	// work out cumulative probs in place
+    	for(int i = 1; i < iChildCount; i++)
+    		cum[i] += cum[i-1];
+    	
+    	// create the children
+    	EColorSchemes NormalScheme, SpecialScheme;
+    	if((Node.ColorScheme() == EColorSchemes.Nodes1) || (Node.ColorScheme() == EColorSchemes.Special1)) {
+    		NormalScheme = EColorSchemes.Nodes2;
+    		SpecialScheme = EColorSchemes.Special2;
+    	}
+    	else {
+    		NormalScheme = EColorSchemes.Nodes1;
+    		SpecialScheme = EColorSchemes.Special1;
+    	}
+    	
+    	EColorSchemes ChildScheme;
+    	
+    	long iLbnd = 0;
+    	
+    	ArrayList<CDasherNode> NewChildren = new ArrayList<CDasherNode>(iChildCount);
+    	NewChildren.ensureCapacity(iChildCount);
+    	
+    	// System.out.printf("Populating with ChildCount: %d%n", iChildCount);
+    	
+    	// Node.Children().ensureCapacity(iChildCount);    	 
+    	
+    	for(int j = 0; j < iChildCount; j++) {
+    		if(j == SPSymbol)
+    			ChildScheme = SpecialScheme;
+    		else
+    			ChildScheme = NormalScheme;
+    		CDasherNode NewNode;
+    		
+    		if(j == ContSymbol)
+    			NewNode = m_Model.GetRoot(1, Node, iLbnd, cum[j], 0);
+    		else if(j == ConvertSymbol) {
+    					NewNode = m_Model.GetRoot(0, Node, iLbnd, cum[j], 0);
+    					NewNode.Seen(false);
+    		}
+    		else if( j == iExistingSymbol) {
+    				NewNode = ExistingChild;
+    				NewNode.SetRange(iLbnd, cum[j]);
+    		}
+    		else {
+    			int iColour = (m_Colours.get(j));
+    			// This is provided for backwards compatibility. 
+    			// Colours should always be provided by the alphabet file
+    			if(iColour == -1) {
+    				if(j == SPSymbol) {
+    					iColour = 9;
+    				}
+    				else if(j == ContSymbol) {
+    					iColour = 8;
+    				}
+    				else {
+    					iColour = (j % 3) + 10;
+    				}
+    			}
+
+    			// Loop colours if necessary for the colour scheme
+    			if((ChildScheme.ordinal() % 2) == 1 && iColour < 130) {    // We don't loop on high
+    				iColour += 130;
+    			}
+
+    			NewNode = new CDasherNode(Node, j, j, ChildScheme, iLbnd, cum[j], m_LanguageModel, iColour);
+    			NewNode.m_NodeManager = this;
+    			NewNode.m_bShove = true;
+    			NewNode.m_BaseGroup = m_Alphabet.m_BaseGroup;
+    		}
+
+    		NewNode.m_strDisplayText = m_DisplayText.get(j);
+    		NewChildren.add(j, NewNode);
+    		iLbnd = cum[j];
+    		
+    		
+    	}
+    	
+    	Node.SetChildren(NewChildren);
+
+    }
+
+    /**
+     * Stub; to be used if in future there is work to be done
+     * upon deleting a node.
+     * <p>
+     * Note that this method should NOT actually destroy
+     * the node, but should remove the Manager's references
+     * to it, if any exist.
+     * 
+     * @param Node Node to be deleted
+     */
+    public void ClearNode( CDasherNode Node ) {
+    	// Should this be responsible for actually doing the deletion
+
+    }
+
+    /**
+     * Generates an EditEvent announcing a new character has been
+     * entered, inferring the character from the Node supplied.
+     * <p>
+     * The second and third parameters are solely for logging
+     * purposes. Logging is not currently enabled in JDasher
+     * and so these can safely be set to null and 0 respectively.
+     * <p>
+     * In the case that logging is enabled, passing the second parameter
+     * as null will cause this addition not to be logged.
+     * 
+     * @param Node The node whose symbol we wish to look up and announce.
+     * @param Added An ArrayList<CSymbolProb> to which the typed symbol, annotated with its probability, will be added for logging purposes.
+     * @param iNormalization The total to which probabilities should add (usually LP_NORMALIZATION) for the purposes of generating the logged probability.
+     */
+    public void Output( CDasherNode Node, ArrayList<CSymbolProb> Added, int iNormalization) {
+    	m_Model.m_bContextSensitive = true;
+    	int t = Node.Symbol();
+    	if(t != 0) { // Ignore symbol 0 (root node)
+    		CEditEvent oEvent = new CEditEvent(1, m_Alphabet.GetText(t));
+    		m_Model.InsertEvent(oEvent);
+    		
+    		// Track this symbol and its probability for logging purposes
+    		if (Added != null) {
+    			CSymbolProb sItem = new CSymbolProb();
+    			sItem.sym    = t;
+    			sItem.prob   = Node.GetProb(iNormalization);
+    			
+    			Added.add(sItem);
+    		}
+    	}
+    }
+
+    /**
+     * Generates an EditEvent announcing that the character represented
+     * by this Node should be removed.
+     * 
+     * @param Node Node whose symbol we wish to remove.
+     */    
+    public void Undo( CDasherNode Node ) {
+    	int t = Node.Symbol();
+    	if(t != 0) { // Ignore symbol 0 (root node)
+    		CEditEvent oEvent = new CEditEvent(2, m_Alphabet.GetText(t));
+    		m_Model.InsertEvent(oEvent);
+    	}
+    }
+    
+    /**
+     * Reconstructs the parent of a given node, in the case that
+     * it had been deleted but the user has now backed off far
+     * enough that we need to restore.
+     * <p>
+     * This will generate an EditContextEvent to try to extend
+     * its knowledge of the current context; this is necessary
+     * because Dasher only buffers a small amount of context
+     * internally. Typically a UI component is expected to reply
+     * with the appropriate context.
+     * <p>
+     * In the event that context is not available internally
+     * and the dispatched EditContextEvent is not passed a new
+     * context, the root symbol is created and returned.
+     * 
+     * @param Node The node whose parent we wish to recreated.
+     * @param iGeneration The depth in the tree of this node.
+     * @return The newly created parent, which may be the root node.
+     */
+    public CDasherNode RebuildParent(CDasherNode Node, int iGeneration) {
+    	
+    	/* This used to clear m_Model.strContextBuffer. Removed as per notes
+    	 * at the top of CDasherInterfaceBase.
+    	 */
+    	
+    	/* This reconstitutes the parent of the current root in the case
+    	 * that we've backed off far enough to need to do so.
+    	 */
+    	
+    	CEditContextEvent oEvent = new CEditContextEvent(10);
+    	m_Model.InsertEvent(oEvent);
+    	    	
+    	String strContext = oEvent.newContext;
+    	// String strContext = new String();
+    	
+    	/* Extract a potential reply from the event */
+    	
+    	ArrayList<Integer> vSymbols = new ArrayList<Integer>();
+    	m_LanguageModel.SymbolAlphabet().GetAlphabetPointer().GetSymbols(vSymbols, strContext, false);
+    	
+    	CDasherNode NewNode;
+    	
+    	if(vSymbols.size() <= iGeneration + 1) {
+    		
+    		/* In the case that there isn't enough context to rebuild the tree,
+    		 * we magically reappear at the root node.
+    		 */
+    		
+    		NewNode = new CDasherNode(null, 0, 0,  EColorSchemes.Nodes1, 0, 0, m_LanguageModel, 7);
+    		
+    		CContextBase oContext = m_LanguageModel.CreateEmptyContext();
+    		m_Model.EnterText(oContext, ". ");
+    		NewNode.SetContext(oContext);
+    	}
+    	else {
+    		
+    		EColorSchemes NormalScheme, SpecialScheme;
+    		if((Node.ColorScheme() == EColorSchemes.Nodes1) || (Node.ColorScheme() == EColorSchemes.Special1)) {
+    			NormalScheme = EColorSchemes.Nodes2;
+    			SpecialScheme = EColorSchemes.Special2;
+    		}
+    		else {
+    			NormalScheme = EColorSchemes.Nodes1;
+    			SpecialScheme = EColorSchemes.Special1;
+    		}
+    		
+    		EColorSchemes ChildScheme;
+    		if(vSymbols.get(vSymbols.size() - (iGeneration + 1)) == m_Model.GetSpaceSymbol())
+    			ChildScheme = SpecialScheme;
+    		else
+    			ChildScheme = NormalScheme;
+    		
+    		int NodeColour = m_Colours.get(vSymbols.get(vSymbols.size() - (iGeneration + 2)));
+    		
+    		if(NormalScheme == EColorSchemes.Nodes2) {
+    			NodeColour += 130;
+    		}
+    		
+    		NewNode = new CDasherNode(null, vSymbols.get(vSymbols.size() - (iGeneration + 2)), 0, ChildScheme, 0, 0, m_LanguageModel, NodeColour);
+    		
+    		CContextBase oContext = (m_LanguageModel.CreateEmptyContext());
+    		
+    		for(int i = (0); i < vSymbols.size() - iGeneration -1; ++i)
+    			m_LanguageModel.EnterSymbol(oContext, vSymbols.get(i));
+    			
+    			NewNode.SetContext(oContext);
+    			
+    	}
+    	
+    	NewNode.m_NodeManager = this;
+    	NewNode.m_bShove = true;
+    	NewNode.Seen(true);
+    	NewNode.m_BaseGroup = m_Alphabet.m_BaseGroup;
+    	
+    	PopulateChildrenWithSymbol( NewNode, Node.Symbol(), Node );
+    	if(m_Model.GetBoolParameter(Ebp_parameters.BP_LM_REMOTE)) {
+    		WaitForChildren(NewNode);
+    	}
+    	
+    	Node.SetParent(NewNode);
+    	
+    	return NewNode;
+    }
+    
+    /**
+     * Suspends the current thread until a given Node's children
+     * have been created. This is for use with specialised
+     * AlphabetManagers which populate their child lists
+     * asynchronously such as RemoteAlphabetManager.
+     * <p>
+     * This simply polls the child-list every 50ms, and returns
+     * when it finds it is neither null nor empty.
+     * 
+     * @param node Node whose children we wish to wait for.
+     */
+    public void WaitForChildren(CDasherNode node) {
+    	while(!(node.Children() != null && node.ChildCount() != 0)) {
+    		try {
+    			Thread.sleep(50);
+    		}
+    		catch(InterruptedException e) {
+    			// Do nothing
+    		}
+    	}
+    	
+    }
+    
+    
+}

Added: trunk/java/dasher/CAlphabetManagerFactory.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CAlphabetManagerFactory.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,47 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+// TODO Document
+public class CAlphabetManagerFactory extends CNodeManagerFactory {
+	
+	protected CAlphabetManager m_AlphabetManager;
+	
+	public CAlphabetManagerFactory( CDasherModel Model, CLanguageModel LanguageModel) {
+		if(LanguageModel.isRemote()) {
+			m_AlphabetManager = new CRemoteAlphabetManager( Model, LanguageModel);
+		}
+		else {
+			m_AlphabetManager = new CAlphabetManager( Model, LanguageModel);
+			}
+		}
+
+	public CDasherNode GetRoot(CDasherNode Parent, long iLower, long iUpper, int UserData) { // VOID POINTER CHANGED TO INT
+		  return m_AlphabetManager.GetRoot(Parent, iLower, iUpper, UserData);
+		  
+	}
+
+}

Added: trunk/java/dasher/CAlphabetMap.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CAlphabetMap.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,119 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.HashMap;
+
+/**
+ * Simple map from the textual representation of alphabet symbols
+ * to their symbol numbers. This used to be a lot more complicated
+ * but now essentially just wraps a Java HashMap and could easily
+ * be removed and replaced by a HashMap member of Alphabet.
+ */
+public class CAlphabetMap {
+
+	/* CSFS: Reimplemented this class, since it was a pain to get working
+	 * in the same way as the C++ version, plus the original code actually
+	 * included a brief essay at the beginning warning against its being
+	 * suboptimal, and advising us to use a proper hash table.
+	 */
+	
+	/**
+	 * The map itself, from Strings to SSymbols (a small class
+	 * giving its integer index and a boolean value
+	 * which determines whether it constitutes a prefix symbol.
+	 * This is always set to false by the constructor, so the
+	 * class too is redundant and should be replaced by a simple
+	 * Integer.
+	 * 
+	 * @see SSymbol
+	 */
+	protected HashMap<String, SSymbol> hashTable;
+	// maps string representations to symbol indexes
+	
+	/**
+	 * Constant used to represent any string which does not
+	 * correspond to a valid symbol.
+	 */
+	private final int Undefined = 0;
+	
+	/**
+	 * Creates the Hash Table with a given initial size.
+	 * 
+	 * @param InitialTableSize Initial size
+	 */
+	public CAlphabetMap(int InitialTableSize)	{
+		hashTable = new HashMap<String, SSymbol>(InitialTableSize);
+	}
+	
+	/**
+	 * Default constructor; creates the hash table with a size
+	 * of 255.
+	 */
+	public CAlphabetMap() {
+		this(255); // Default value from alphabet_map.h
+	}
+	
+	/* CSFS: It looks to me as if even in the original C++,
+	 * nothing ever gets to use the KeyIsPrefix flag -- there are
+	 * actions to be taken if it's true, but nothing ever sets it so.
+	 * Consider removing and reverting to a plain integer to represent
+	 * a symbol?
+	 */
+	
+	/**
+	 * Adds a new key/value pair to the table.
+	 * 
+	 * @param Key String representation of a symbol
+	 * @param Value Integer index of same symbol
+	 */
+	public void Add(String Key, int Value) {
+		SSymbol newsym = new SSymbol();
+		newsym.prefix = false;
+		newsym.symbol = Value;
+		hashTable.put(Key, newsym);
+	}
+	
+	/**
+	 * Retrieves a symbol index given the string representation.
+	 * 
+	 * @param Key String to look up
+	 * @return SSymbol containing the integer index of the symbol, or Undefined if the supplied String did not correspond to any symbol.
+	 */	
+	public SSymbol Get(String Key) {
+		
+		if(hashTable.containsKey(Key)) {
+			return hashTable.get(Key);
+		}
+		else {
+			SSymbol retval = new SSymbol();
+			retval.symbol = Undefined;
+			retval.prefix = false;
+			return retval;
+		
+		}
+	}
+}

Added: trunk/java/dasher/CAutoSpeedControl.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CAutoSpeedControl.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,346 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.LinkedList;
+
+/**
+ * AutoSpeedControl is responsible for adaptively tuning Dasher's
+ * maximum speed by observing user actions whilst dashing.
+ * <p>
+ * At present it is only used by DefaultFilter.
+ * <p>
+ * Its mode of action essentially involves observing how
+ * 'eratically' the user is behaving, something quantised
+ * by the angle they tend to move at compared to due East
+ * (in a left-to-right configuration).
+ * <p> A more scientific description can be found in
+ * dasher/Doc/speedcontrol.tex in the original Dasher
+ * source distribution, available from www.dasher.org.uk
+ */
+public class CAutoSpeedControl extends CDasherComponent {
+	
+	/**
+	 * Current maximum speed.
+	 */
+	protected double m_dBitrate; //  stores max bit rate internally
+	/**
+	 * TODO Find out what this does
+	 */
+	protected double m_dSampleScale, m_dSampleOffset; // internal, control sample size
+	/**
+	 * How many samples have been taken to date
+	 */
+	protected int m_nSpeedCounter;  // keep track of how many samples
+	/**
+	 * Maximum number of samples to take
+	 */
+	protected int m_nSpeedSamples;  // upper limit on #samples
+	/**
+	 * Maximum and minimum speed limits
+	 */
+	protected double m_dSpeedMax, m_dSpeedMin; // bit rate always within this range
+	/**
+	 * Critical points in user's movement angle variance.
+	 */
+	protected double m_dTier1, m_dTier2, m_dTier3, m_dTier4; // variance tolerance tiers 
+	/**
+	 * Fractional changes to speed which can be used to control speed.
+	 * <p>Tier 4 represents the greatest change, so we must have 1 < 2 < 3 < 4.
+	 */
+	protected double m_dChange1, m_dChange2, m_dChange3, m_dChange4; // fractional changes to bit rate
+	/**
+	 * Controls rate at which MinRadius is adapted; higher means slower.
+	 */
+	protected double m_dMinRRate; // controls rate at which min. r adapts HIGHER===SLOWER!
+	/**
+	 * Currently unused; may be used to tune the sensitivity of auto speed-control in the future. 
+	 */
+	protected double m_dSensitivity; // not used, control sensitivity of auto speed control
+	/**
+	 * List of the previous angles observed.
+	 */
+	protected LinkedList<Double> m_dequeAngles = new LinkedList<Double>(); // store angles for statistics
+	/**
+	 * Variables for adaptive radius calculations
+	 */
+	protected double m_dSigma1, m_dSigma2, m_dMinRadius;
+	
+	/**
+	 * Creates a new speed controller configured with a sample
+	 * size appropriate to the reported frame rate.
+	 * 
+	 * @param EventHandler Event handler to dispatch and received events.
+	 * @param SettingsStore Settings store to retrieve and set settings.
+	 * @param dFrameRate Initial frame rate, in FPS.
+	 */
+	
+	public CAutoSpeedControl(CEventHandler EventHandler, CSettingsStore SettingsStore, double dFrameRate)	  {
+	
+	super(EventHandler, SettingsStore);
+	  
+		//scale #samples by #samples = m_dSamplesScale / (current bitrate) + m_dSampleOffset
+	m_dSampleScale = 1.5;
+	m_dSampleOffset = 1.3;
+	m_dMinRRate = 80.0;
+	m_dSensitivity = GetLongParameter(Elp_parameters.LP_AUTOSPEED_SENSITIVITY) / 100.0; //param only, no GUI!
+		//tolerance for automatic speed control
+	m_dTier1 = 0.0005;  //  should be arranged so that tier4 > tier3 > tier2 > tier1 !!!
+	m_dTier2 = 0.01;
+	m_dTier3 = 0.2;
+	m_dTier4 = 0.31;
+		//bitrate fractional changes for auto-speed control
+	m_dChange1 = 1.1;
+	m_dChange2 = 1.02;
+	m_dChange3 = 0.97;
+	m_dChange4 = 0.94;
+		//cap bitrate at...
+	m_dSpeedMax = 8.0;
+	m_dSpeedMin = 0.1;
+		//variance of two-centred-gaussians for adaptive radius
+	m_dSigma1 = 0.5; 
+	m_dSigma2 = 0.05;
+		//Initialise auto-speed control
+	m_nSpeedCounter = 0;
+	m_dBitrate = (double)(round(GetLongParameter(Elp_parameters.LP_MAX_BITRATE) / 100.0));
+
+	  UpdateMinRadius();
+	  UpdateSampleSize(dFrameRate); 
+	}
+
+	  ////////////////////////////////////////////////
+	  ///
+	  ///  Change max bitrate based on variance of angle 
+	  ///  in dasher space.
+	  ///
+	  /////////////////////////////////////////////////
+
+	/**
+	 * Updates the current dasher speed according to the current
+	 * variance in the user's angle of attack. Essentially, we
+	 * compare their variance to the m_dTier variables, and multiply
+	 * by the corresponding m_dChange in the case that they are above
+	 * or below it.
+	 * <p>
+	 * Also caps the new speed at SpeedMin and SpeedMax.
+	 * 
+	 * @return New calculated speed.
+	 */
+	protected double UpdateBitrate()
+	{
+	  double var = Variance();
+	  if(var < m_dTier1)
+	  {
+	      m_dBitrate *= m_dChange1;
+	  }
+	  else if(var < m_dTier2)
+	  {
+	      m_dBitrate *= m_dChange2;
+	  }
+	  else if(var > m_dTier4) //Tier 4 comes before tier 3 because tier4 > tier3 !!!
+	  {
+	      m_dBitrate *= m_dChange4;
+	  }
+	  else if(var > m_dTier3)
+	  {
+	      m_dBitrate *= m_dChange3;
+	  }
+	  //else if( in the middle )
+	  //    nothing happens! ;
+
+	  //always keep bitrate values sane
+	  if(m_dBitrate > m_dSpeedMax) 
+	  {
+	    m_dBitrate = m_dSpeedMax;
+	  }
+	  else if(m_dBitrate < m_dSpeedMin) 
+	  {
+	    m_dBitrate = m_dSpeedMin;
+	  }
+
+	  return m_dBitrate;
+	}
+
+	/**
+	 * Finds the variance in the user's angle of movement.
+	 * 
+	 * @return Variance
+	 */
+	protected double Variance() 
+	
+		{      
+		double avgcos, avgsin;
+		avgsin = avgcos = 0.0;
+		// find average of cos(theta) and sin(theta) 
+		for(double i : m_dequeAngles) {
+			
+			avgcos += Math.cos(i);
+			avgsin += Math.sin(i);
+		}
+		avgcos /= (1.0 * m_dequeAngles.size());
+		avgsin /= (1.0 * m_dequeAngles.size());
+		//return variance (see dasher/Doc/speedcontrol.tex)
+		return -(Math.log(avgcos * avgcos + avgsin * avgsin));
+		
+	}
+
+	/**
+	 * Determines the number of speed samples to take into account,
+	 * based on the current frame rate and the user's movement rate.
+	 * 
+	 * @param dFrameRate Current frame rate
+	 * @return Recommended number of samples
+	 */
+	
+	protected int UpdateSampleSize(double dFrameRate)
+	{
+	  double dFramerate = dFrameRate;
+	  double dSpeedSamples = 0.0;
+	  double dBitrate = m_dBitrate; 
+	  if(dBitrate < 1.0)// for the purposes of this function
+	    dBitrate = 1.0; // we don't care exactly how slow we're going
+	                    // *really* low speeds are ~ equivalent?
+	  dSpeedSamples = dFramerate * (m_dSampleScale / dBitrate + m_dSampleOffset);
+	 
+	  m_nSpeedSamples = (int)(round(dSpeedSamples));
+	  return m_nSpeedSamples;
+	}
+
+	
+	/**
+	 * Finds adaptive minimum radius for
+	 * auto-speed control. Calculated by DJCM's
+	 * mixture-of-2-centred-gaussians model.
+	 * 
+	 * @return New minimum radius.
+	 */
+	protected double UpdateMinRadius() 
+	{
+	  m_dMinRadius = Math.sqrt( Math.log( (m_dSigma2 * m_dSigma2) / (m_dSigma1 * m_dSigma1) ) / 
+	                ( 1 / (m_dSigma1 * m_dSigma1) - 1 / (m_dSigma2 * m_dSigma2)) );
+	  return m_dMinRadius;
+	}
+
+
+	
+	/**
+	 * Updates VARIANCES of two populations of 
+ 	 * mixture-of-2-centred-Gaussians model!
+ 	 * 
+ 	 * @param r Current minimum radius
+ 	 * @param dFrameRate Current Dasher frame rate in FPS
+ 	 */
+
+	public void UpdateSigmas(double r, double dFrameRate)
+	{
+	  double dSamples = m_dMinRRate* dFrameRate / m_dBitrate;
+	  if(r > m_dMinRadius)
+	    m_dSigma1 = m_dSigma1 - (m_dSigma1 - r * r) / dSamples;
+	  else 
+	    m_dSigma2 = m_dSigma2 - (m_dSigma2 - r * r) / dSamples;
+	}
+
+/**
+ * AUTOMATIC SPEED CONTROL, CEH 7/05: Analyse variance of angle
+ * mouse position makes with +ve x-axis in Dasher-space.
+ * <p>
+ * SpeedControl alters the LP_MAX_BITRATE parameter to reflect
+ * the perceived user's need. 
+ * 
+ * @param iDasherX User's current mouse position in Dasher co-ordinates
+ * @param iDasherY User's current mouse position in Dasher co-ordinates
+ * @param dFrameRate Current Dasher frame rate in FPS
+ * @param View Current DasherView, used to ascertain the user's true
+ *             mouse position.
+ */
+	public void SpeedControl(long iDasherX, long iDasherY, double dFrameRate, CDasherView View) {
+	  if(GetBoolParameter(Ebp_parameters.BP_AUTO_SPEEDCONTROL) && !GetBoolParameter(Ebp_parameters.BP_DASHER_PAUSED)) {
+	    
+//	  Coordinate transforms:    
+	    iDasherX = (long)(View.applyXMapping(iDasherX / (double)(GetLongParameter(Elp_parameters.LP_MAX_Y))) * GetLongParameter(Elp_parameters.LP_MAX_Y));
+	    iDasherY = (long)(View.ymap(iDasherY));
+
+	    long iDasherOX = (long)(View.applyXMapping(GetLongParameter(Elp_parameters.LP_OX) / (double)(GetLongParameter(Elp_parameters.LP_MAX_Y))) * GetLongParameter(Elp_parameters.LP_MAX_Y));
+	    long iDasherOY = (long)(View.ymap(GetLongParameter(Elp_parameters.LP_OY)));
+
+	    double x = -(iDasherX - iDasherOX) / (double)iDasherOX; //Use normalised coords so min r works 
+	    double y = -(iDasherY - iDasherOY) / (double)iDasherOY; 
+	    double theta = Math.atan2(y, x);
+	    double r = Math.sqrt(x * x + y * y);
+	    m_dBitrate = GetLongParameter(Elp_parameters.LP_MAX_BITRATE) / 100.0; //  stored as long(round(true bitrate * 100))
+
+	    UpdateSigmas(r, dFrameRate);
+
+//	  Data collection:
+	    
+	    // CSFS: Replaced push_back with addLast and pop_front with removeFirst.
+	    // 		 (C++ deque to Java LinkedList translation)
+	    // CSFS: Replaced C++ 'fabs' with Math.abs
+	    
+	    if(r > m_dMinRadius && Math.abs(theta) < 1.25) {
+	      m_nSpeedCounter++;
+	      m_dequeAngles.addLast(theta);
+	      while(m_dequeAngles.size() > m_nSpeedSamples) {
+		    m_dequeAngles.removeFirst();
+	      }
+	      
+	    }
+	    m_dSensitivity = GetLongParameter(Elp_parameters.LP_AUTOSPEED_SENSITIVITY) / 100.0;
+	    if(m_nSpeedCounter > round(m_nSpeedSamples / m_dSensitivity)) {
+	      //do speed control every so often!
+	      
+	      UpdateSampleSize(dFrameRate);
+	      UpdateMinRadius();
+	      UpdateBitrate();
+	      long lBitrateTimes100 =  (long)(round(m_dBitrate * 100)); //Dasher settings want long numerical parameters
+	      SetLongParameter(Elp_parameters.LP_MAX_BITRATE, lBitrateTimes100);
+	      m_nSpeedCounter = 0;	  
+	    
+	    }	
+	  
+	  }
+	}
+	  
+
+	/**
+	 * Rounds a double to the nearest integer without
+	 * casting to an integer type.
+	 * 
+	 * @param dVal Value to round
+	 * @return Nearest integer (as an FP value)
+	 */
+	
+	protected double round(double dVal) {
+		  double dF = Math.floor(dVal);
+		  double dC = Math.ceil(dVal);
+		  if(dVal - dF < dC - dVal)
+		    return dF;
+		  else
+		    return dC;
+	  }
+
+	
+}

Added: trunk/java/dasher/CCannaConversionHelper.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CCannaConversionHelper.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,46 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.ArrayList;
+
+public class CCannaConversionHelper extends CConversionHelper {
+
+	private int context_id;
+	private boolean IsInit;
+	
+	public boolean Convert(final String strSource, ArrayList<ArrayList<String>> vResult) {
+		return false;
+		
+		/* DUMMY METHOD */
+		
+	}
+	
+	/* INCOMPLETE. Appears to be used only if Dasher is compiled for the Japanese
+	 * language, so I'll look at this later. Dummy methods inserted for now.
+	 */
+	
+}

Added: trunk/java/dasher/CCircleStartHandler.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CCircleStartHandler.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,225 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Displays a circle centred around the crosshair
+ * which the user can click to start dasher.
+ * <p>
+ *  Status flags:<br>
+ * -1 undefined<br>
+ * 0 = out of circle, stopped<br>
+ * 1 = out of circle, started<br>
+ * 2 = in circle, stopped<br>
+ * 3 = in circle, started<br>
+ * 4 = in circle, stopping<br>
+ * 5 = in circle, starting
+ */
+
+public class CCircleStartHandler extends CStartHandler{
+	
+	/**
+	 * Current status of the handler.
+	 */
+	protected int m_iStatus;
+	/**
+	 * Time (recorded as a UNIX timestamp) when the status
+	 * last changed.
+	 */
+	protected long m_iChangeTime;
+	/**
+	 * Radius of the displayed circle in Dasher co-ordinates. 
+	 */	
+	protected int m_iCircleRadius;
+	/**
+	 * Radius of the circle in screen co-ordinates.
+	 */
+	protected int m_iScreenRadius;
+	
+	/**
+	 * Sole constructor. Creates a start handler in its default start state.
+	 * Calculates the intial circle radius using LP_CIRCLE_PERCENT and LP_MAX_X.
+	 * 
+	 * @param EventHandler
+	 * @param SettingsStore
+	 * @param Interface
+	 */
+	public CCircleStartHandler(CEventHandler EventHandler, CSettingsStore SettingsStore, CDasherInterfaceBase Interface) 
+    {
+		super(EventHandler, SettingsStore, Interface);
+		m_iStatus = -1;
+		m_iChangeTime = 0;
+		m_iCircleRadius = (int)(GetLongParameter(Elp_parameters.LP_MAX_Y) * GetLongParameter(Elp_parameters.LP_CIRCLE_PERCENT) / 100);
+	}
+	
+	/**
+	 * Draws the start handler to the passed view.
+	 * 
+	 * @param View DasherView upon which to run drawing commands.
+	 * @return True, to indicate that something has been drawn.
+	 */
+	public boolean DecorateView(CDasherView View) {
+				
+		CDasherView.Point C = View.Dasher2Screen(2048, 2048);
+		
+		CDasherView.Point C2 = View.Dasher2Screen(2048, 2048 + m_iCircleRadius);
+		
+		m_iScreenRadius = C2.y - C.y;
+		
+		if((m_iStatus == 0) || (m_iStatus == 2))
+			View.Screen().DrawCircle(C.x, C.y, m_iScreenRadius, 0, true);
+		else if(m_iStatus == 5)
+			View.Screen().DrawCircle(C.x, C.y, m_iScreenRadius, 1, true);
+		else
+			View.Screen().DrawCircle(C.x, C.y, m_iScreenRadius, 0, false);
+					
+		return true;
+	}
+	
+	/**
+	 * Updates the start handler's current state dependent on the current
+	 * mouse position.
+	 * <p>
+	 * In a nutshell, it determines whether the mouse is within the circle,
+	 * and if so, instructs Dasher to start or stop dependent on its
+	 * current state and how long the user has hovered over the circle.
+	 * <p>
+	 * Specifically, we start and stop if the user has hovered for over 1 second.
+	 * 
+	 * @param iTime Current system time, as a UNIX time stamp.
+	 * @param m_DasherView View against which co-ordinate transforms should be performed.
+	 * @param m_DasherModel Model to which commands should be passed.
+	 */
+	public void Timer(long iTime, CDasherView m_DasherView, CDasherModel m_DasherModel) {
+
+		CDasherView.DPoint dashXY = m_DasherView.getInputDasherCoords();
+		
+		CDasherView.Point C = m_DasherView.Dasher2Screen(2048, 2048);
+		
+		CDasherView.Point Cursor = m_DasherView.Dasher2Screen(dashXY.x, dashXY.y);
+		
+		double dR;
+		
+		dR = Math.sqrt(Math.pow((double)(C.x - Cursor.x), 2.0) + Math.pow((double)(C.y - Cursor.y), 2.0));
+		
+		int iNewStatus = 0;
+		
+		// Status flags:
+		// -1 undefined
+		// 0 = out of circle, stopped
+		// 1 = out of circle, started
+		// 2 = in circle, stopped
+		// 3 = in circle, started
+		// 4 = in circle, stopping
+		// 5 = in circle, starting
+		
+		// TODO - need to check that these respond correctly to (eg) external pauses
+		
+		if(dR < m_iScreenRadius) {
+			switch(m_iStatus) {
+			case -1:
+				if(m_Interface.GetBoolParameter(Ebp_parameters.BP_DASHER_PAUSED))
+					iNewStatus = 2;
+				else
+					iNewStatus = 3;
+				break;
+			case 0:
+				iNewStatus = 5;
+				break;
+			case 1:
+				iNewStatus = 4;
+				break;
+			case 2:
+			case 3:
+			case 4:
+			case 5:
+				iNewStatus = m_iStatus;
+				break;
+			}
+		}
+		else {
+			switch(m_iStatus) {
+			case -1:
+				if(m_Interface.GetBoolParameter(Ebp_parameters.BP_DASHER_PAUSED))
+					iNewStatus = 0;
+				else
+					iNewStatus = 1;
+				break;
+			case 0:
+			case 1:
+				iNewStatus = m_iStatus;
+				break;
+			case 2:
+				iNewStatus = 0;
+				break;
+			case 3:
+				iNewStatus = 1;
+				break;
+			case 4:
+				iNewStatus = 1;
+				break;
+			case 5:
+				iNewStatus = 0;
+				break;
+			}
+		}
+		
+		if(iNewStatus != m_iStatus) {
+			m_iChangeTime = iTime;
+		}
+		
+		if(iTime - m_iChangeTime > 1000) {
+			if(iNewStatus == 4) {
+				iNewStatus = 2;
+				m_Interface.PauseAt(0, 0);
+			} 
+			else if(iNewStatus == 5) {
+				iNewStatus = 3;
+				m_Interface.Unpause(iTime);
+			}
+		}
+		
+		m_iStatus = iNewStatus;
+		
+	}
+	
+	/**
+	 * Responds to events:
+	 * <p>
+	 * BP_DASHER_PAUSED changes: Updates start handler state
+	 * so that we don't try to stop when already stopped, etc.
+	 */
+	public void HandleEvent(CEvent Event) {
+		if(Event.m_iEventType == 1) {
+			CParameterNotificationEvent Evt = (CParameterNotificationEvent)Event;
+			
+			if(Evt.m_iParameter == Ebp_parameters.BP_DASHER_PAUSED) {
+				m_iStatus = -1;
+			}
+		}
+	}
+	
+}

Added: trunk/java/dasher/CClickFilter.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CClickFilter.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,133 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * This is an InputFilter implementation which accepts mouse clicks
+ * and causes Dasher to zoom to the location of successive clicks.
+ * <p>
+ * The filter does not pay any attention to the mouse position
+ * except for when the user clicks the display, and does not
+ * decorate the display in any way.
+ * <p>
+ * In order to zoom smoothly to a given location, it invokes
+ * CDasherModel.ScheduleZoom, which interpolates a number of points
+ * between the current crosshair location and the point clicked by
+ * the user, and jumps to these points on each successive frame.
+ * <p>
+ * This filter registers itself with the name <i>Click Mode</i>.
+ */
+
+public class CClickFilter extends CInputFilter {
+
+	/**
+	 * Current DasherView, to be used in determining mouse co-ordinates.
+	 */
+	private CDasherView DasherView;
+	
+	/**
+	 * Sole constructor. Calls the CInputFilter constructor with a type of 7,
+	 * an ID of 1, and the name <i>Click Mode</i>.
+	 * 
+	 * @param EventHandler Event handler.
+	 * @param SettingsStore Settings repository.
+	 * @param Interface Interface with which the filter should be registered.
+	 */
+	public CClickFilter(CEventHandler EventHandler, CSettingsStore SettingsStore, CDasherInterfaceBase Interface) {
+	  super(EventHandler, SettingsStore, Interface, 7, 1, "Click Mode");
+	  DasherView = null;
+	}
+
+	/**
+	 * This filter does not decorate the view.
+	 * 
+	 * @param View Unused, may be null.
+	 * @return False, indicating no work done.
+	 */
+	public boolean DecorateView(CDasherView View) {
+	  return false;
+	}
+
+	/**
+	 * Timer simply calls the DasherModel's Tap_on_display method,
+	 * causing it to move forward a frame if there is currently
+	 * a zoom scheduled. In the event that no further destination
+	 * is scheduled (ie. we are stationary and the user has not
+	 * clicked a new destination), nothing is done.
+	 * 
+	 * @param Time Current system time as a Unix timestamp
+	 * @param m_DasherView View to be used for co-ordinate transforms
+	 * @param m_DasherModel Model which will be instructed to advance a frame
+	 * @return True if the model has changed, false otherwise. 
+	 */
+	public boolean Timer(long Time, CDasherView m_DasherView, CDasherModel m_DasherModel) {
+	  // FIXME - REALLY, REALLY horrible - bleh
+	  DasherView = m_DasherView;
+	  boolean retval = m_DasherModel.Tap_on_display(0, 0, Time, null);
+	  if(m_DasherModel.ScheduledSteps() == 0) {
+		  while(m_DasherModel.CheckForNewRoot(DasherView)) {
+			  // Do nothing. This allows the root to get reparented as many times as
+			  // are necessary before we pause.
+		  }
+		  
+		  SetBoolParameter(Ebp_parameters.BP_DASHER_PAUSED, true);
+	  }
+	  return retval;
+	}
+
+	/**
+	 * KeyDown is to be called by the Interface when the user
+	 * presses a key or clicks the mouse. ClickFilter responds to:
+	 * 
+	 * <b>Left mouse button</b>: Schedules a zoom to the clicked location.
+	 * 
+	 * @param iTime Current system time as a UNIX timestamp.
+	 * @param iId Key/button identifier.
+	 * @param Model DasherModel which should be zoomed in response to clicks.
+	 */
+	public void KeyDown(long iTime, int iId, CDasherModel Model) {
+
+	  switch(iId) {
+	  case 100: // Mouse clicks
+	    if(DasherView != null) {
+	      SetBoolParameter(Ebp_parameters.BP_DASHER_PAUSED, false);
+	    	
+	      CDasherView.DPoint retval = DasherView.getInputDasherCoords();
+	      Model.ScheduleZoom(retval.x, retval.y);
+	    }
+	    break;
+	  }
+	}
+
+	/**
+	 * This class ignores all events.
+	 * 
+	 * @param Event Event to be processed.
+	 */
+	public void HandleEvent(CEvent Event) {
+	}
+	
+}

Added: trunk/java/dasher/CColourIO.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CColourIO.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,1143 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * 
+ * Responsible for reading a given list of XML files, extracting
+ * colour scheme information, and creating a list of ColourInfo objects
+ * for each.
+ * <p>
+ * Further, after doing so, responsible for returning a ColourInfo
+ * object corresponding to a given alphabet name, and of giving
+ * a full list of available colour schemes.
+ *
+ */
+public class CColourIO {
+
+	/**
+	 * The current system data location, for locating DTDs.
+	 */
+	protected String SystemLocation;
+	
+	/**
+	 * The current user data location, for locating DTDs.
+	 */
+	protected String UserLocation;
+	
+	/**
+	 * Map from colour scheme names to their ColourInfo objects.
+	 */
+	protected HashMap<String, ColourInfo> Colours = new HashMap<String,ColourInfo>(); // map short names (file names) to descriptions
+	
+	/**
+	 * Files which are to be parsed.
+	 */
+	protected ArrayList<String> Filenames;
+	
+	/**
+	 * Flag indicating whether or not the current colour scheme may be modified.
+	 */
+	public boolean LoadMutable;
+	
+	/**
+	 * Interface which will be used for Applet style I/O.
+	 */
+	public CDasherInterfaceBase m_Interface;
+	
+	/**
+	 * SAXParser used to read XML files.
+	 */
+	protected SAXParser parser;
+	
+	/**
+	 * Simple struct which represents a colour scheme.
+	 */
+	public static class ColourInfo {
+	    // Basic information
+		/**
+		 * Friendly name of this colour-scheme.
+		 */
+	    String ColourID;
+	    
+	    /**
+	     * Can this scheme be modified?
+	     */
+	    boolean Mutable;               // If from user we may play. If from system defaults this is immutable. User should take a copy.
+
+	    // Complete description of the colour:
+	    /**
+	     * Array of scheme's defined colours' red values.
+	     */
+	    ArrayList<Integer> Reds = new ArrayList<Integer>();
+	    
+	    /**
+	     * Array of scheme's defined colours' green values.
+	     */
+	    ArrayList<Integer> Greens = new ArrayList<Integer>();
+	    
+	    /**
+	     * Array of scheme's defined colours' blue values.
+	     */
+	    ArrayList<Integer> Blues = new ArrayList<Integer>();
+	}
+	
+	/**
+	 * Sole constructor. Parses a given list of XML files; once
+	 * the constructor terminates, the class is ready to give
+	 * a list of available colour schemes and return ColourInfo
+	 * objects requested by name.
+	 * 
+	 * @param SysLoc System data location to search for DTD files. 
+	 * @param UserLoc User data location to search for DTD files.
+	 * @param Fnames List of files to parse. 
+	 * @param dib Interface against which we can perform applet-style IO. Optional; if null, applet-style IO will not be attempted.
+	 */
+	public CColourIO(String SysLoc, String UserLoc, ArrayList<String> Fnames, CDasherInterfaceBase dib) {
+		
+		SystemLocation = SysLoc;
+		UserLocation = UserLoc;
+		Filenames = Fnames;
+		LoadMutable = false;
+		
+		m_Interface = dib;
+		
+		SAXParserFactory factory = SAXParserFactory.newInstance();
+		try {
+			parser = factory.newSAXParser();
+		}
+		catch(Exception e) {
+			System.out.printf("Exception creating XML parser in CColourIO: %s%n", e);
+		}
+		
+		CreateDefault();
+		
+		LoadMutable = false;
+		ParseFile(SystemLocation + "colour.xml");
+		if(Filenames.size() > 0) {
+			for(int i = 0; i < Filenames.size(); i++) {
+				ParseFile(SystemLocation + Filenames.get(i));
+			}
+		}
+		LoadMutable = true;
+		ParseFile(UserLocation + "colour.xml");
+		if(Filenames.size() > 0) {
+			for(int i = 0; i < Filenames.size(); i++) {
+				ParseFile(UserLocation + Filenames.get(i));
+			}
+		}
+	}
+	
+	/**
+	 * Parse a named XML file. Colour-schemes found, if any,
+	 * will be imported and may be enumerated with GetColours
+	 * or retrieved using GetInfo. If the specified XML file
+	 * cannot be read, the method prints the exception raised
+	 * but does not throw an exception.
+	 * <p>
+	 * This method will attempt to retrieve the file first by
+	 * ordinary file I/O, and then if this fails, will attempt
+	 * to retrieve a resource stream, allowing it to find XML
+	 * files stored in a JAR.
+	 * 
+	 * @param filename Relative or absolute path to the file to be parsed.
+	 */
+	public void ParseFile(String filename) {
+		
+		InputStream FileInput;
+		try {
+			FileInput = new FileInputStream(filename);
+			// Try ordinary IO
+		}
+		catch(Exception e) {
+			try {
+				FileInput = m_Interface.getResourceStream(filename);
+				// Try applet-style IO
+			}
+			catch(Exception ex) {
+				return; // If the file cannot be retrieved, act as if it does not exist at all.
+			}
+		}
+		
+		InputSource XMLInput = new InputSource(FileInput);
+		
+		DefaultHandler handler = new ColourXMLHandler(Colours, this, SystemLocation, UserLocation);
+		// Back-pointer passed so it can modify our colours ArrayList.
+		
+		
+		
+		try {
+			parser.parse(XMLInput, handler);
+		}
+		catch (Exception e) {
+			System.out.printf("Exception reading %s: %s%n", filename, e.toString());
+			return; // Again, an invalid file should be treated as if it isn't there.
+		}
+		
+	}
+	
+	/**
+	 * Fills a given Collection with the names of all available
+	 * colour schemes.
+	 * <p>
+	 * Colour schemes can be made available by being parsed from
+	 * an XML file by way of the ParseFile method (or through
+	 * the constructor), or by the manual creation of a ColourInfo
+	 * object which must then be saved using SetInfo.
+	 * 
+	 * @param ColourList Collection to be filled with available colours.
+	 */
+	public void GetColours(Collection<String> ColourList) {
+		ColourList.clear();
+		
+		/* CSFS: Rewritten from the old version which used
+		 * C++ list-iterators.
+		 */
+		
+		for(Map.Entry<String, ColourInfo> m : Colours.entrySet()) {
+			ColourList.add(m.getValue().ColourID);
+		}
+		
+	}
+	
+	/**
+	 * Retrieves the ColourInfo object associated with a given colour scheme.
+	 * <p>
+	 * If the specified name cannot be found, the Default scheme
+	 * will be retrieved. To avoid this happening, make sure that
+	 * only schemes enumerated by GetColours are requested.
+	 * <p>
+	 * Schemes' names may consist of any Unicode character in the
+	 * Basic Multilingual Plane.
+	 * 
+	 * @param ColourID Name of the colour scheme to retrieve.
+	 * @return ColourInfo object representing the named scheme, or the Default if this is not possible.
+	 */
+	public ColourInfo GetInfo(String ColourID) {
+		if(ColourID == "")            // return Default if no colour scheme is specified
+			return Colours.get("Default");
+		else {
+			if(Colours.containsKey(ColourID)) {
+				return Colours.get(ColourID);
+			}
+			else {
+				// if we don't have the colour scheme they asked for, return default
+				return Colours.get("Default");
+			}
+		}
+	}
+	
+	/**
+	 * Adds a ColourInfo object to the list of those available.
+	 * At present, schemes cannot be manually stored in Dasher,
+	 * but this may change in the future if user-defined schemes
+	 * become a possibility.
+	 * 
+	 * @param NewInfo Colour scheme to save. Must not be null.
+	 */
+	public void SetInfo(ColourInfo NewInfo) {
+		Colours.put(NewInfo.ColourID, NewInfo);
+		Save(NewInfo.ColourID);
+	}
+	
+	/**
+	 * Removes a colour scheme by name. This removes the stated
+	 * scheme from the list of those available; it will no longer
+	 * be returned by GetColours or be retrievable by GetInfo.
+	 * 
+	 * @param ColourID Name of the scheme to remove. If the given name
+	 * does not exist the method will return without error.
+	 */
+	public void Delete(String ColourID) {
+		Colours.remove(ColourID);
+		Save("");
+	}
+	
+	/**
+	 * Stub method. In the future, this may save a given scheme
+	 * as an XML file, or in some other format. This should be
+	 * implemented if user-defined or mutable colour schemes are
+	 * implemented.
+	 * <p>
+	 * The class must already know about the scheme to be able
+	 * to save it.
+	 * 
+	 * @param name Name of the scheme to save.
+	 */
+	public void Save(String name) {
+		
+		// Stub
+		
+	}
+	
+	/**
+	 * Creates and stores a default colour scheme, named simply
+	 * <i>Default</i>. This is the scheme which will be returned
+	 * in the event of a non-existent scheme being requested,
+	 * and can always be assumed to be available.
+	 *
+	 */
+	protected void CreateDefault() {
+		  
+		ColourInfo Default = new ColourInfo();
+		
+		Default.ColourID = "Default";
+		Default.Mutable = false;
+		Default.Reds.add(255);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(0);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(218);
+		Default.Greens.add(218);
+		Default.Blues.add(218);
+		Default.Reds.add(0);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(0);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(0);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(80);
+		Default.Greens.add(80);
+		Default.Blues.add(80);
+		Default.Reds.add(235);
+		Default.Greens.add(235);
+		Default.Blues.add(235);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(180);
+		Default.Greens.add(238);
+		Default.Blues.add(180);
+		Default.Reds.add(155);
+		Default.Greens.add(205);
+		Default.Blues.add(155);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(255);
+		Default.Greens.add(255);
+		Default.Blues.add(0);
+		Default.Reds.add(0);
+		Default.Greens.add(200);
+		Default.Blues.add(0);
+		Default.Reds.add(255);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(255);
+		Default.Greens.add(255);
+		Default.Blues.add(0);
+		Default.Reds.add(0);
+		Default.Greens.add(200);
+		Default.Blues.add(0);
+		Default.Reds.add(255);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(255);
+		Default.Greens.add(255);
+		Default.Blues.add(0);
+		Default.Reds.add(0);
+		Default.Greens.add(200);
+		Default.Blues.add(0);
+		Default.Reds.add(255);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(255);
+		Default.Greens.add(255);
+		Default.Blues.add(0);
+		Default.Reds.add(0);
+		Default.Greens.add(200);
+		Default.Blues.add(0);
+		Default.Reds.add(255);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(255);
+		Default.Greens.add(255);
+		Default.Blues.add(0);
+		Default.Reds.add(0);
+		Default.Greens.add(200);
+		Default.Blues.add(0);
+		Default.Reds.add(255);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(255);
+		Default.Greens.add(255);
+		Default.Blues.add(0);
+		Default.Reds.add(0);
+		Default.Greens.add(200);
+		Default.Blues.add(0);
+		Default.Reds.add(255);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(255);
+		Default.Greens.add(255);
+		Default.Blues.add(0);
+		Default.Reds.add(0);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(0);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(0);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(0);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(0);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(0);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(0);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(0);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		Default.Reds.add(80);
+		Default.Greens.add(80);
+		Default.Blues.add(80);
+		Default.Reds.add(255);
+		Default.Greens.add(255);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(255);
+		Default.Greens.add(174);
+		Default.Blues.add(185);
+		Default.Reds.add(255);
+		Default.Greens.add(187);
+		Default.Blues.add(255);
+		Default.Reds.add(135);
+		Default.Greens.add(206);
+		Default.Blues.add(255);
+		Default.Reds.add(0);
+		Default.Greens.add(255);
+		Default.Blues.add(0);
+		Default.Reds.add(240);
+		Default.Greens.add(240);
+		Default.Blues.add(0);
+		Default.Reds.add(255);
+		Default.Greens.add(0);
+		Default.Blues.add(0);
+		
+		Colours.put("Default", Default);
+	}
+	
+}
+
+class ColourXMLHandler extends DefaultHandler {
+	protected HashMap<String, CColourIO.ColourInfo> Colours;
+	protected CColourIO m_Parent;
+	
+	protected String userLoc;
+	protected String sysLoc;
+	
+	protected CColourIO.ColourInfo currentColour;
+		
+	public ColourXMLHandler(HashMap<String, CColourIO.ColourInfo> Cols, CColourIO parent, String sys, String usr) {
+		Colours = Cols;
+		m_Parent = parent;
+		
+		sysLoc = sys;
+		userLoc = usr;
+	}
+	
+	public void startElement(String namespaceURI, String simpleName, String qualName, Attributes tagAttributes) throws SAXException {
+		
+		String tagName = (simpleName.equals("") ? qualName : simpleName);
+		
+		if(tagName == "palette") {
+			currentColour = new CColourIO.ColourInfo();
+			currentColour.Mutable = m_Parent.LoadMutable;
+			for(int i = 0; i < tagAttributes.getLength(); i++) {
+		    	String attributeName = (tagAttributes.getLocalName(i).equals("") ? tagAttributes.getQName(i) : tagAttributes.getLocalName(i));
+		    	if(attributeName == "name") {
+		    		currentColour.ColourID = tagAttributes.getValue(i); 
+		    	}
+			}
+		}
+		else if(tagName == "colour") {
+			for(int i = 0; i < tagAttributes.getLength(); i++) {
+		    	String attributeName = (tagAttributes.getLocalName(i).equals("") ? tagAttributes.getQName(i) : tagAttributes.getLocalName(i));
+		    	if(attributeName == "r") {
+		    		currentColour.Reds.add(Integer.parseInt(tagAttributes.getValue(i)));
+		    	}
+		    	if(attributeName == "g") {
+		    		currentColour.Greens.add(Integer.parseInt(tagAttributes.getValue(i)));
+		    	}
+		    	if(attributeName == "b") {
+		    		currentColour.Blues.add(Integer.parseInt(tagAttributes.getValue(i)));
+		    	}
+			}
+		}
+	}
+	
+	public void endElement(String namespaceURI, String simpleName, String qualName) {
+		String tagName = (simpleName.equals("") ? qualName : simpleName);
+		
+		if(tagName == "palette") {
+			Colours.put(currentColour.ColourID, currentColour);
+		}
+	
+	}
+	
+	public InputSource resolveEntity(String publicName, String systemName) throws IOException, SAXException {
+		
+		if(systemName.contains("colour.dtd")) {
+			try {
+				return new InputSource(new FileInputStream(sysLoc + "colour.dtd"));
+			}
+			catch(Exception e) {
+				try {
+					return new InputSource(new FileInputStream(userLoc + "colour.dtd"));
+				}
+				catch(Exception ex) {
+					return new InputSource(m_Parent.m_Interface.getResourceStream(sysLoc + "colour.dtd"));
+				}
+			}
+		}
+		else {
+			return null;
+		}
+		
+		/* CSFS: This is here because SAX will by default look in a system location
+		 * first, which throws a security exception when running as an Applet.
+		 * All other requests are deferred to SAX.
+		 */
+		
+		
+	}
+	
+}
\ No newline at end of file

Added: trunk/java/dasher/CContextBase.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CContextBase.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,37 @@
+
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+package dasher;
+
+/**
+ * Parent class of all Contexts used by language models. This class
+ * implements no methods and has no fields, as contexts are entirely
+ * opaque outside of their applicable language model.
+ */
+public class CContextBase {
+
+	/* Intentionally blank class; ancestor of all Context classes */
+	
+}

Added: trunk/java/dasher/CControlEvent.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CControlEvent.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,48 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Event to be raised when a control mode event arises, such as the
+ * user enters the Start or Stop node.
+ */
+public class CControlEvent extends CEvent {
+	
+	/**
+	 * Creates a new control event with a given ID.
+	 * 
+	 * @param iID ID of the new event.
+	 */
+	public CControlEvent(int iID) {
+	    m_iEventType = 6; // EV_CONTROL
+	    m_iID = iID;
+	}
+	
+	/**
+	 * ID of this event.
+	 */
+	int m_iID;
+}
\ No newline at end of file

Added: trunk/java/dasher/CConversionHelper.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CConversionHelper.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,32 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.ArrayList;
+
+abstract public class CConversionHelper {
+	abstract boolean Convert(final String strSource, ArrayList<ArrayList<String>> vResult);
+}

Added: trunk/java/dasher/CCustomColours.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CCustomColours.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,115 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.ArrayList;
+
+/**
+ * Represents a custom colour scheme, wrapping a ColourInfo object
+ * and importing its contents into Collections suitable for random
+ * access.
+ * <p>
+ * This also ensures that the ColourInfo object is read-only
+ * when in use.
+ */
+public class CCustomColours {
+	
+	/**
+	 * Wrapped colour info object.
+	 */
+	protected CColourIO.ColourInfo m_ColourInfo;
+	
+	/**
+	 * Fast-access array of available colours' red values.
+	 */
+	protected ArrayList<Integer> m_Red = new ArrayList<Integer>();
+	
+	/**
+	 * Fast-access array of available colours' green values.
+	 */
+	protected ArrayList<Integer> m_Green = new ArrayList<Integer>();
+	
+	/**
+	 * Fast-access array of available colours' blue values.
+	 */
+	protected ArrayList<Integer> m_Blue = new ArrayList<Integer>();
+
+	/**
+	 * Sole constructor; copies the data from a given ColourInfo
+	 * object.
+	 * 
+	 * @param ColInfo ColourInfo object detailing the scheme we wish to represent.
+	 */
+	public CCustomColours(CColourIO.ColourInfo ColInfo) {
+		m_ColourInfo = ColInfo;
+		
+		// Add all the colours.
+		for(int i = 0; i < m_ColourInfo.Reds.size(); i++) {    // loop colours
+			m_Red.add(m_ColourInfo.Reds.get(i));
+			m_Green.add(m_ColourInfo.Greens.get(i));
+			m_Blue.add(m_ColourInfo.Blues.get(i));
+		}
+	}
+		
+	/**
+	 * Gets number of available colours.
+	 * 
+	 * @return Number of available colours.
+	 */
+	public int GetNumColours() {
+		return m_Red.size();
+	}
+	
+	/**
+	 * Gets the red value of a given colour.
+	 * 
+	 * @param colour Index of the colour to look up.
+	 * @return Red value, on a scale from 0 to 255.
+	 */
+	public int GetRed(int colour) {
+		return m_Red.get(colour);
+	}
+	
+	/**
+	 * Gets the green value of a given colour.
+	 * 
+	 * @param colour Index of the colour to look up.
+	 * @return green value, on a scale from 0 to 255.
+	 */
+	public int GetGreen(int colour) {
+		return m_Green.get(colour);
+	}
+	
+	/**
+	 * Gets the blue value of a given colour.
+	 * 
+	 * @param colour Index of the colour to look up.
+	 * @return blue value, on a scale from 0 to 255.
+	 */
+	public int GetBlue(int colour) {
+		return m_Blue.get(colour);
+	}
+}

Added: trunk/java/dasher/CDasherComponent.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CDasherComponent.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,203 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * DasherComponent is the base class of most functional units of
+ * Dasher, and serves to provide a number of common functions and
+ * services to its children. These include:
+ * <p><ul><li>The ability to register oneself as an event listener
+ * and so receive notification when other components dispatch events.
+ * <li>The ability to dispatch events, of which all other Components will
+ * be notified.
+ * <li>The ability to get and set global settings, using some child of CSettingsStore.
+ * </ul>
+ * <p>
+ * Generally speaking, a single EventHandler and SettingsStore should be
+ * created during Dasher's initialisation, and a reference to both
+ * passed to each created DasherComponent. However, there is no
+ * reason why in future there could not be multiple subgroups
+ * of components which are not connected, and by virtue of
+ * having seperate EventHandlers and SettingsStores would not
+ * hear each other's events, or be effected by each other's parameter changes.
+ * <p>
+ * It is, however, not recommended that any two components should
+ * share a SettingsStore without also sharing an EventHandler,
+ * as the SettingsStore raises an Event to notify whenever a parameter
+ * is changed, a behaviour which components may depend upon.
+ */
+public class CDasherComponent {
+
+	/**
+	 * This Component's EventHandler
+	 */
+	protected CEventHandler m_EventHandler;
+	
+	/**
+	 * This Component's SettingsStore
+	 */
+	protected CSettingsStore m_SettingsStore;
+	
+	/**
+	 * Sole constructor. Registers this component as an event listener,
+	 * such that HandleEvent will be called whenever any other componenet
+	 * raises an event.
+	 * 
+	 * @param EventHandler Event handler with which to register. Must not be null.
+	 * @param SettingsStore Settings store to be used to get and set parameters. Must not be null.
+	 */
+	public CDasherComponent(CEventHandler EventHandler, CSettingsStore SettingsStore) {
+	  m_EventHandler = EventHandler;
+	  m_SettingsStore = SettingsStore;
+
+	  if (m_EventHandler != null)
+	    m_EventHandler.RegisterListener(this);
+
+	}
+	
+	/**
+	 * Unregisters this component with the EventHandler, preventing
+	 * the receipt of any further events, though new ones can still
+	 * be dispatched. Typically this is called on destruction of the object.
+	 *
+	 */
+	public void UnregisterComponent() {
+		if (m_EventHandler != null)
+		    m_EventHandler.UnregisterListener(this);
+	}
+	
+	/**
+	 * Dispatches a new event, which will be passed to the HandleEvent of all
+	 * other components registered with the EventHandler.
+	 * 
+	 * @param Event Event we wish to pass to other components.
+	 */
+	public void InsertEvent(CEvent Event) {
+		  m_EventHandler.InsertEvent(Event);
+	}
+
+	/**
+	 * Called by the EventHandler to notify this component of an
+	 * event raised by another. Modifications of the Event object
+	 * will be seen by subsequent listeners and by the originator.
+	 * No garuntees are made as to the order in which components
+	 * will receive events.
+	 * 
+	 * @param pEvent Event received.
+	 */
+	public void HandleEvent(CEvent pEvent) {}
+	
+	/**
+	 * Retreives the value of a given global boolean parameter.
+	 * <p>This request is actioned by calling the same method on m_SettingsStore
+	 * 
+	 * @param iParameter Parameter to retrieve
+	 * @return Boolean value of this parameter
+	 */
+	public boolean GetBoolParameter(Ebp_parameters iParameter) {
+		return m_SettingsStore.GetBoolParameter(iParameter);
+	}
+	
+	/**
+	 * Retreives the value of a given global long parameter.
+	 * <p>This request is actioned by calling the same method on m_SettingsStore
+	 * 
+	 * @param iParameter Parameter to retrieve
+	 * @return Long value of this parameter
+	 */
+	public long GetLongParameter(Elp_parameters iParameter) {
+		  return m_SettingsStore.GetLongParameter(iParameter);
+	}
+	
+	/**
+	 * Retreives the value of a given global string parameter.
+	 * <p>This request is actioned by calling the same method on m_SettingsStore
+	 * 
+	 * @param iParameter Parameter to retrieve
+	 * @return String value of this parameter
+	 */
+	public String GetStringParameter(Esp_parameters iParameter) {
+		  return m_SettingsStore.GetStringParameter(iParameter);
+	}
+	
+	/**
+	 * Sets the value of a given boolean parameter by calling the
+	 * SettingsStore's SetBoolParameter method.
+	 * 
+	 * @param iParameter Parameter to set
+	 * @param bValue New value for this parameter
+	 */
+	public void SetBoolParameter(Ebp_parameters iParameter, boolean bValue) {
+		  m_SettingsStore.SetBoolParameter(iParameter, bValue);
+	}
+	
+	/**
+	 * Sets the value of a given long parameter by calling the
+	 * SettingsStore's SetBoolParameter method.
+	 * 
+	 * @param iParameter Parameter to set
+	 * @param lValue New value for this parameter
+	 */
+	public void SetLongParameter(Elp_parameters iParameter, long lValue) {
+		  m_SettingsStore.SetLongParameter(iParameter, lValue);
+	}
+	
+	/**
+	 * Sets the value of a given string parameter by calling the
+	 * SettingsStore's SetBoolParameter method.
+	 * 
+	 * @param iParameter Parameter to set
+	 * @param sValue New value for this parameter
+	 */
+	public void SetStringParameter(Esp_parameters iParameter, String sValue) {
+		  m_SettingsStore.SetStringParameter(iParameter, sValue);
+	}
+
+	/**
+	 * Determines the type of some parameter; this is exactly
+	 * the same as checking whether it is an instance of
+	 * Ebp_parameters (boolean), Elp_parameters (long) or Esp_parameters (string).
+	 */
+	public int GetParameterType(EParameters iParameter) {
+		  if (m_SettingsStore != null)
+		    return m_SettingsStore.GetParameterType(iParameter);
+		  return 3; //
+	}
+	
+	/**
+	 * Retrieves the friendly name of a given parameter.
+	 * <p>Useful for dumping a complete human-readable configuration.
+	 * 
+	 * @param iParameter Parameter we wish to identify
+	 * @return Friendly name for this parameter
+	 */
+	public String GetParameterName(EParameters iParameter) {
+		  if (m_SettingsStore != null)
+		    return m_SettingsStore.GetParameterName(iParameter);
+		  return "";
+	}
+	
+}

Added: trunk/java/dasher/CDasherInput.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CDasherInput.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,102 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * DasherInput is the base class for all modules which provide
+ * some sort of co-ordinate input.
+ * <p>
+ * To serve as a co-ordinate source, a device must be able to
+ * provide synchronous or quasi-synchronous readout of its
+ * current co-ordinates, such that a call to GetCoordinates
+ * will return almost instantaneously.
+ * <p>
+ * Devices are free to return their co-ordinates relative
+ * to the screen, using pixels as their unit of measure, or
+ * relative to the Dasher world, using Dasher co-ordinates.
+ * 
+ * @see CDasherModule
+ */
+abstract public class CDasherInput extends CDasherModule {
+	
+	/**
+	 * Sole constructor. Simply recalls CDasherModule's constructor.
+	 * 
+	 * @param EventHandler Event handler with which we wish to register ourselves
+	 * @param SettingsStore Settings store for parameter getting/setting
+	 * @param iID This device's ID
+	 * @param iType This device's type number
+	 * @param szName Friendly name for this device, to be used with GetModuleByName
+	 */
+	public CDasherInput(CEventHandler EventHandler, CSettingsStore SettingsStore, long iID, int iType, String szName) { 
+		super(EventHandler, SettingsStore, iID, iType, szName);
+	}
+	
+	/**
+	 * Sets the maximum co-ordinates which the device should
+	 * return. These are given as Dasher-world co-ordinates and
+	 * should be translated if necessary.
+	 * 
+	 * @param iN Number of co-ordinates specified
+	 * @param iDasherMax Maximum co-ordinates.
+	 */
+	public void SetMaxCoordinates(int iN, long[] iDasherMax) {}
+	
+	/**
+	 * Called to request that the device report the current co-ordinates.
+	 * 
+	 * @param iN Number of co-ordinates expected.
+	 * @param Coordinates Fill with the current co-ordinates
+	 * @return 0 if those reported are screen co-ordinates, or 1 if they are Dasher world co-ordinates.
+	 */
+	public abstract int GetCoordinates(int iN, long[] Coordinates);
+	
+	/// Get the number of co-ordinates that this device supplies
+	///
+
+	/**
+	 * Gets the number of co-ordinates this device returns.
+	 * <p>
+	 * At present, only 1- and 2-axis devices are accepted, but
+	 * this may be easily upgraded in the future.
+	 * 
+	 * @return Number of co-ordinates supplied by this device.
+	 */
+	public abstract int GetCoordinateCount();
+	
+	/**
+	 * Activates the input device. If threads must be started
+	 * to support the device, this is the place to do it.
+	 */
+	public void Activate() {};
+	
+	/**
+	 * Deactivates the device; resources should be freed at this point.
+	 *
+	 */
+	public void Deactivate() {};
+	
+}

Added: trunk/java/dasher/CDasherInterfaceBase.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CDasherInterfaceBase.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,1772 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.Collection;
+import java.io.*;
+
+/**
+ * DasherInterfaceBase is the core of Dasher, and the entry
+ * point for all high-level functions which control the system
+ * as a whole.
+ * <p>
+ * The majority of the actual work involved in running Dasher is
+ * done by the Interface's two main children, a DasherModel and
+ * a DasherView; the interface primarily acts as a co-ordinator.
+ * <p>
+ * The DasherModel represents the tree of DasherNodes which forms
+ * the core of Dasher. It knows how to update the model in response
+ * to user input, and how to build, destroy and rebuild the tree.
+ * <p>
+ * The DasherView on the other hand is responsible for taking the abstract
+ * information in the Model and rendering it, visually or otherwise,
+ * in some way.
+ * <p>
+ * the Interface simply sits in the middle and co-ordinates
+ * whole-system actions such as updating the model and drawing a new frame.
+ * <p>
+ * The interface has a number of methods which remain abstract;
+ * this means that in order to implement Dasher, this class must be
+ * extended and the missing methods implemented.
+ * <p>
+ * Typically one would also extend DasherInput to provide a co-ordinate
+ * input of some sort, and implement DasherScreen to provide visual 
+ * (or other) display.   
+ */
+abstract public class CDasherInterfaceBase {
+	
+		
+	public CFileLogger g_Logger; // CSFS: No logging yet.
+	// public final eLogLevel g_iLogLevel = logNORMAL; // FIXME enums
+	// public final int       g_iLogOptions = logTimeStamp | logDateStamp;
+	
+	/**
+	 * Current alphabet
+	 */
+	protected CAlphabet m_Alphabet;
+	
+	/**
+	 * Current colour scheme
+	 */
+	protected CCustomColours m_Colours;
+	
+	/**
+	 * Current DasherModel
+	 */
+	protected CDasherModel m_DasherModel;
+	
+	/**
+	 * Current DasherScreen
+	 */
+	protected CDasherScreen m_DasherScreen;
+	
+	/**
+	 * Current DasherView
+	 */
+	protected CDasherView m_DasherView;
+	
+	/**
+	 * Current Input device
+	 */
+	protected CDasherInput m_Input;
+	
+	/**
+	 * Current AlphIO
+	 */
+	protected CAlphIO m_AlphIO;
+	
+	/**
+	 * Current ColourIO
+	 */
+	protected CColourIO m_ColourIO;
+	
+	/**
+	 * Entered text which has not yet been written out to disk
+	 */
+	protected StringBuffer strTrainfileBuffer;
+	
+	/**
+	 * Context of recently entered characters
+	 */
+	protected LinkedList<Character> strCurrentContext;
+		
+	/**
+	 * Our event handler 
+	 */
+	protected CEventHandler m_EventHandler;
+	
+	/**
+	 * Our settings repository
+	 */
+	protected CSettingsStore m_SettingsStore;
+	
+	/**
+	 * Our logging module
+	 */
+	protected CUserLog m_UserLog;
+	
+	/**
+	 * Current input filter
+	 */
+	protected CInputFilter m_InputFilter;
+	
+	/**
+	 * The module manager
+	 */
+	protected CModuleManager m_oModuleManager;
+	
+	/**
+	 * Lock engaged when Dasher should not respond to
+	 * commands for unspecified reason
+	 */
+	protected boolean m_bGlobalLock; // The big lock
+	
+	/**
+	 * Lock engaged when Dasher is being destroyed
+	 */
+	protected boolean m_bShutdownLock;
+	
+	/**
+	 * Lock engaged when we're in the process of connecting
+	 * to a remote language model
+	 */
+	protected boolean m_bConnectLock; // Connecting to server.
+	
+	/**
+	 * Somehow determines which alphabet XML files to parse.
+	 * 
+	 * @param vFileList List to fill with filenames to process.
+	 */
+	public abstract void ScanAlphabetFiles(Collection<String> vFileList);
+	
+	/**
+	 * Somehow determines which colour XML files to parse.
+	 * 
+	 * @param vFileList List to fill with filenames to process.
+	 */
+	public abstract void ScanColourFiles(Collection<String> vFileList);
+	
+	/**
+	 * Should setup the system and user locations; called
+	 * early in the startup sequence.
+	 * <p>
+	 * These correspond to the string parameters SP_SYSTEM_LOC
+	 * and SP_USER_LOC respectively.
+	 */
+	public abstract void SetupPaths();
+	
+	/**
+	 * Should perform any UI building which is required.
+	 */
+	public abstract void SetupUI();
+	
+	/**
+	 * Should create a SettingsStore object of some sort and
+	 * store a reference to it in m_SettingsStore.
+	 * <p>
+	 * This is an abstract method because most implementations
+	 * will want to extend the default SettingsStore to provide
+	 * the possibility of persistent settings.
+	 */
+	public abstract void CreateSettingsStore();
+	
+	/**
+	 * Should return the size of a given file, or 0 if the
+	 * file does not exist or cannot be accessed.
+	 * 
+	 * @param strFileName File to be read
+	 * @return Size of this file, or 0 on error.
+	 */
+	public abstract int GetFileSize(String strFileName);
+	
+	/**
+	 * Sole constructor. Creates an EventHandler, sets up an
+	 * initial context, and creates a ModuleManager. This does
+	 * only enough that we can retrieve the event handler for the
+	 * purposes of creating further components; as neither the
+	 * settings store nor any of Dasher's internal components
+	 * yet exist, it is not yet capable of any meaningful task.
+	 * <p>
+	 * Realize() must be called after construction and before
+	 * any other functions which depend upon anything other than
+	 * the event handler and module manager.
+	 */
+	public CDasherInterfaceBase() {
+		
+		m_EventHandler = new CEventHandler(this);
+		
+		strCurrentContext = new LinkedList<Character>();
+		strCurrentContext.add('.');
+		strCurrentContext.add(' ');
+		strTrainfileBuffer = new StringBuffer();
+		m_oModuleManager = new CModuleManager();
+				
+		// Global logging object we can use from anywhere
+		// g_logger = new CFileLogger("dasher.log", g_iLogLevel, g_iLogOptions);
+		
+	}
+	
+	/**
+	 * Realize does the bulk of the work of setting up a working
+	 * Dasher. The sequence of actions is as follows:
+	 * <p>
+	 * <ul><li>Creates a SettingsStore (by calling CreateSettingsStore())
+	 * <li>Creates the user interface (using SetupUI())
+	 * <li>Sets up the system and user locations (by calling SetupPaths())
+	 * <li>Reads in the available alphabets and colour schemes
+	 * using ScanAlphabetFiles and then creating a CAlphIO based upon
+	 * the filenames returned (and the equivalent for ColourIO).
+	 * The resulting objects are stored in m_AlphIO and m_ColourIO.
+	 * <li>Calls ChangeColours() and ChangeAlphabet(), which will
+	 * create a number of internal components of their own
+	 * (see these functions' documentation for details)
+	 * <li>Calls CreateFactories() and CreateInputFilter() to complete
+	 * the input setup.
+	 * </ul>
+	 * <p>
+	 * When realize terminates, Dasher will be in a broadly usable
+	 * state. It will still lack a co-ordinate input device, which
+	 * should be registered with RegisterFactory, and will need a Screen
+	 * which should be created externally and registered with
+	 * ChangeScreen, but will otherwise be good to go.
+	 */
+	public void Realize() {
+		
+		// TODO: What exactly needs to have happened by the time we call Realize()?
+		CreateSettingsStore();
+		SetupUI();
+		SetupPaths();
+		
+		ArrayList<String> vAlphabetFiles = new ArrayList<String>();
+		ScanAlphabetFiles(vAlphabetFiles);
+		m_AlphIO = doAlphIO(vAlphabetFiles);
+		
+		ArrayList<String> vColourFiles = new ArrayList<String>();
+		ScanColourFiles(vColourFiles);
+		m_ColourIO = doColourIO(vColourFiles);
+		
+		/* CSFS: Added a back-pointer to each of these so they can use the Interface's
+		 * centralised GetResource method.
+		 */
+		
+		ChangeColours();
+		ChangeAlphabet();
+		
+		// Create the user logging object if we are suppose to.  We wait
+		// until now so we have the real value of the parameter and not
+		// just the default.
+		
+		int iUserLogLevel = (int)GetLongParameter(Elp_parameters.LP_USER_LOG_LEVEL_MASK);
+		if (iUserLogLevel > 0) 
+			m_UserLog = new CUserLog(m_EventHandler, m_SettingsStore, iUserLogLevel, m_Alphabet);  
+		
+		CreateFactories();
+		CreateInputFilter();
+		
+		// All the setup is done by now, so let the user log object know
+		// that future parameter changes should be logged.
+		if (m_UserLog != null) m_UserLog.InitIsDone();
+			
+	}
+	
+	/**
+	 * Instructs all componenets to unregister themselves with the
+	 * event handler, and nulls our pointers to them, such that
+	 * they will be available for garbage collection.
+	 */
+	public void DestroyInterface() {
+				
+		if(m_DasherModel != null) {
+			m_DasherModel.deleteLM();
+			m_DasherModel.UnregisterComponent();
+		}
+		  m_DasherModel = null;        // The order of some of these deletions matters
+		  m_Alphabet = null;
+		  m_DasherView = null;
+		  m_ColourIO = null;
+		  m_AlphIO = null;
+		  m_Colours = null;
+		  if(m_InputFilter != null) m_InputFilter.UnregisterComponent();
+		  m_InputFilter = null;
+		  // FIXME Decide what needs happen to these
+		  // Do NOT delete Edit box or Screen. This class did not create them.
+
+		  // When we destruct on shutdown, we'll output any detailed log file
+		  if (m_UserLog != null)
+		  {
+		    m_UserLog.OutputFile();
+		    m_UserLog.Close();
+		    // FIXME again do what's appropriate
+		    m_UserLog = null;
+		  }
+
+		  if (g_Logger != null) {
+		    g_Logger.Destroy();
+		    g_Logger = null;
+		  }
+
+		  // Must delete event handler after all CDasherComponent derived classes
+
+		  m_EventHandler = null;
+	}
+	
+	/**
+	 * Notifies the interface before a string parameter is changed.
+	 * <p>
+	 * This enables the interface to read the parameter's current value if necessary.
+	 * <p>
+	 * Presently the interface responds to:
+	 * <p><i>SP_ALPHABET_ID</i>: Stores a history of previous used alphabets
+	 * in SP_ALPHABET_1, SP_ALPHABET_2 and so on.
+	 * 
+	 * @param iParameter Parameter which is going to change.
+	 * @param sNewValue Value to which it will change.
+	 */
+	public void PreSetNotify(Esp_parameters iParameter, String sNewValue) {
+		
+		// FIXME - make this a more general 'pre-set' event in the message
+		// infrastructure
+		
+		if(iParameter == Esp_parameters.SP_ALPHABET_ID) { 
+			// Cycle the alphabet history
+			if(GetStringParameter(Esp_parameters.SP_ALPHABET_ID) != sNewValue) {
+				if(GetStringParameter(Esp_parameters.SP_ALPHABET_1) != sNewValue) {
+					if(GetStringParameter(Esp_parameters.SP_ALPHABET_2) != sNewValue) {
+						if(GetStringParameter(Esp_parameters.SP_ALPHABET_3) != sNewValue)
+							SetStringParameter(Esp_parameters.SP_ALPHABET_4, GetStringParameter(Esp_parameters.SP_ALPHABET_3));
+						
+						SetStringParameter(Esp_parameters.SP_ALPHABET_3, GetStringParameter(Esp_parameters.SP_ALPHABET_2));
+					}
+					
+					SetStringParameter(Esp_parameters.SP_ALPHABET_2, GetStringParameter(Esp_parameters.SP_ALPHABET_1));
+				}
+				
+				SetStringParameter(Esp_parameters.SP_ALPHABET_1, GetStringParameter(Esp_parameters.SP_ALPHABET_ID));
+			}
+			
+		}	
+		
+	}
+	
+	/**
+	 * This is called by the EventHandler after all other
+	 * components have received this event.
+	 * <p>
+	 * The interface responds to the following parameter changes:
+	 * <p>
+	 * <i>BP_COLOUR_MODE</i>: Calls Start() and redraws the display.
+	 * <p>
+	 * <i>BP_OUTLINE_MODE</i>: Redraws the display.
+	 * <p>
+	 * <i>BP_CONNECT_LOCK</i>: Sets the internal m_bConnectLock variable.
+	 * <p>
+	 * <i>LP_ORIENTATION</i>: Sets the LP_REAL_ORIENTATION parameter either
+	 * to the value of LP_ORIENTATION, or if the latter is -2 (a special sentinel value)
+	 * queries the current alphabet for its preferred orientation, and
+	 * sets LP_REAL_ORIENTATION appropriately.
+	 * <p>
+	 * <i>SP_ALPHABET_ID</i>: Calls ChangeAlphabet() to rebuild the DasherModel
+	 * appropriately, and then Start().
+	 * <p>
+	 * <i>SP_COLOUR_ID</i>: Calls ChangeColours() to insert the new colour scheme.
+	 * <p>
+	 * <i>BP_PALETTE_CHANGE and SP_DEFAULT_COLOUR_ID</i>: If Palette Change is true,
+	 * changes COLOUR_ID to match DEFAULT_COLOUR_ID which contains the current
+	 * alphabet's preferred colour scheme.
+	 * <p>
+	 * <i>LP_LANGUAGE_MODEL_ID</i>: Runs CreateDasherModel() to rebuild the model
+	 * based on our newly chosen language model.
+	 * <p>
+	 * <i>SP_LM_HOST</i>: If we are currently using a remote language model,
+	 * rebuilds the Model as above; otherwise, ignores.
+	 * <p>
+	 * <i>LP_DASHER_FONTSIZE and LP_LINE_WIDTH</i>: Redraws the display.
+	 * <p>
+	 * <i>SP_INPUT_FILTER</i>: Runs CreateInputFilter() to recreate the
+	 * requested filter.
+	 * <p>
+	 * <i>SP_INPUT_DEVICE</i>: Runs CreateInput() to create the requested
+	 * input device.
+	 * <p>
+	 * It also responds to EditEvents by modifying strCurrentContext
+	 * according to the text the user is reported to have entered
+	 * or deleted, and LockEvents by setting m_bGlobalLock to the value
+	 * indicated.
+	 * 
+	 * @param Event The event the interface is to process.
+	 */
+	public void InterfaceEventHandler(CEvent Event) {
+		
+		/* CSFS: Changed to lots of if statements, since Java won't switch on a non-
+		 * constant such as the ordinal or ordinal of one of these parameters.
+		 */
+		
+		if(Event.m_iEventType == 1) {
+			CParameterNotificationEvent Evt = ((CParameterNotificationEvent)(Event));
+			
+			if(Evt.m_iParameter == Ebp_parameters.BP_COLOUR_MODE) {       // Forces us to redraw the display
+				// TODO) { Is this variable ever used any more?
+				Start();
+				Redraw(true);
+			}
+			if(Evt.m_iParameter ==  Ebp_parameters.BP_OUTLINE_MODE) {
+				Redraw(true);
+			}
+			if(Evt.m_iParameter == Ebp_parameters.BP_CONNECT_LOCK) {
+				m_bConnectLock = GetBoolParameter(Ebp_parameters.BP_CONNECT_LOCK);
+			}
+			if(Evt.m_iParameter ==  Elp_parameters.LP_ORIENTATION) {
+				if(GetLongParameter(Elp_parameters.LP_ORIENTATION) == Opts.AlphabetDefault)
+					// TODO) { See comment in DasherModel.cpp about prefered values
+					SetLongParameter(Elp_parameters.LP_REAL_ORIENTATION, m_Alphabet.GetOrientation());
+				else
+					SetLongParameter(Elp_parameters.LP_REAL_ORIENTATION, GetLongParameter(Elp_parameters.LP_ORIENTATION));
+				Redraw(true);
+			}
+			if(Evt.m_iParameter ==  Esp_parameters.SP_ALPHABET_ID) {
+				ChangeAlphabet();
+				Start();
+				Redraw(true);
+			}
+			if(Evt.m_iParameter ==  Esp_parameters.SP_COLOUR_ID) {
+				ChangeColours();
+				Redraw(true);
+			}
+			if(Evt.m_iParameter == Ebp_parameters.BP_PALETTE_CHANGE || Evt.m_iParameter == Esp_parameters.SP_DEFAULT_COLOUR_ID) { 
+				if(GetBoolParameter(Ebp_parameters.BP_PALETTE_CHANGE))
+					SetStringParameter(Esp_parameters.SP_COLOUR_ID, GetStringParameter(Esp_parameters.SP_DEFAULT_COLOUR_ID));
+			}
+			if(Evt.m_iParameter == Elp_parameters.LP_LANGUAGE_MODEL_ID) {
+				CreateDasherModel();
+				Start();
+				Redraw(true);
+			}
+			if(Evt.m_iParameter == Esp_parameters.SP_LM_HOST) {
+				if(GetLongParameter(Elp_parameters.LP_LANGUAGE_MODEL_ID) == 5) {
+					CreateDasherModel();
+					Start();
+					Redraw(true);
+				}
+			}
+			if(Evt.m_iParameter == Elp_parameters.LP_LINE_WIDTH) {
+				Redraw(false); // TODO - make this accessible everywhere
+			}
+			if(Evt.m_iParameter == Elp_parameters.LP_DASHER_FONTSIZE) {
+				// TODO - make screen a CDasherComponent child?
+				Redraw(true);
+			}
+			if(Evt.m_iParameter == Esp_parameters.SP_INPUT_DEVICE) {
+				CreateInput();
+			}
+			if(Evt.m_iParameter == Esp_parameters.SP_INPUT_FILTER) {
+				CreateInputFilter();
+			}
+			
+		}
+		else if(Event.m_iEventType == 2) {
+			CEditEvent EditEvent= ((CEditEvent)(Event));
+			
+				
+			if(EditEvent.m_iEditType == 1) {				
+				for(char c : EditEvent.m_sText.toCharArray()) {
+					strCurrentContext.add(c);
+				}
+				while(strCurrentContext.size() > 20) {
+					strCurrentContext.removeFirst();
+				}
+			
+				
+				strTrainfileBuffer.append(EditEvent.m_sText);
+			}
+			
+			/* CSFS: The routines below used to use std::substr. substr(i, n) extracts
+			 * a substring of length n starting at character i, whereas Java's 
+			 * "somestring".substring(a, b) returns the substring beginning at index a and
+			 * ending at index b.
+			 * 
+			 * In both of these cases, the two ought to be identical since b == n
+			 * when a == i == 0.
+			 */
+			
+			else if(EditEvent.m_iEditType == 2) {
+				for(int i = 0; i < EditEvent.m_sText.length(); i++) {
+					if(strCurrentContext.size() > 0) {
+						strCurrentContext.removeFirst();
+						strTrainfileBuffer.setLength(strTrainfileBuffer.length() - 1);
+					}
+				}
+				
+				
+			}
+		}
+		else if(Event.m_iEventType == 6 /*EV_CONTROL*/) {
+			/* CControlEvent ControlEvent = ((CControlEvent)(Event));
+			
+			switch(ControlEvent.m_iID) {
+			case CControlManager.CTL_STOP:
+				PauseAt(0,0);
+			break;
+			case CControlManager.CTL_PAUSE:
+				Halt();
+			break;
+			} */
+			
+			// CSFS: Do nothing for the time being until Control Mode is brought back
+		}
+		else if(Event.m_iEventType == 7 /*EV_LOCK*/) {
+			// TODO: 'Reference counting' for locks?
+			CLockEvent LockEvent = ((CLockEvent)(Event));
+			m_bGlobalLock = LockEvent.m_bLock;
+		}
+	}
+	
+	/**
+	 * Reads a list of XML files and returns an instance
+	 * of CAlphIO which knows about the alphabets found in these
+	 * files.
+	 * <p>
+	 * This class does it by the simple expedient of creating a new
+	 * CAlphIO and passing these files, but some extensions may
+	 * redirect the request in the case that the XML files have
+	 * already been parsed.
+	 * 
+	 * @param vFiles List of files to be parsed
+	 * @return a CAlphIO which knows about the alphabets recorded in these files.
+	 */
+	public CAlphIO doAlphIO(ArrayList<String> vFiles) {
+		return new CAlphIO(GetStringParameter(Esp_parameters.SP_SYSTEM_LOC), GetStringParameter(Esp_parameters.SP_USER_LOC), vFiles, this);
+	}
+	
+	/**
+	 * Reads a list of XML files and returns an instance
+	 * of CColourIO which knows about the colours found in these
+	 * files.
+	 * <p>
+	 * This class does it by the simple expedient of creating a new
+	 * CColourIO and passing these files, but some extensions may
+	 * redirect the request in the case that the XML files have
+	 * already been parsed.
+	 * 
+	 * @param vFiles List of files to be parsed
+	 * @return a CColourIO which knows about the colours recorded in these files.
+	 */
+	public CColourIO doColourIO(ArrayList<String> vFiles) {
+		return new CColourIO(GetStringParameter(Esp_parameters.SP_SYSTEM_LOC), GetStringParameter(Esp_parameters.SP_USER_LOC), vFiles, this);
+	}
+	
+	/**
+	 * Creates a new DasherModel, deleting any previously existing
+	 * one if necessary.
+	 * <p>
+	 * The DasherModel does most of the actual initialisation work,
+	 * so see the constructor documentation for DasherModel for details.
+	 * <p>
+	 * This function will also set m_Alphabet to that created in the
+	 * course of the DasherModel's initialisation, and will train
+	 * the newly created model using the new Alphabet's specified
+	 * training text. 
+	 */
+	public void CreateDasherModel() 
+	{
+		if(m_AlphIO == null)
+			return;
+		
+		// TODO: Move training into model?
+		// TODO: Do we really need to check for a valid language model?
+		int lmID = (int)GetLongParameter(Elp_parameters.LP_LANGUAGE_MODEL_ID);
+		if( lmID != -1 ) {
+			
+			// Train the new language model
+			CLockEvent Event;
+			
+			Event = new CLockEvent("Training Dasher", true, 0);
+			m_EventHandler.InsertEvent(Event);
+			Event = null;
+			
+			// Delete the old model and create a new one
+			if(m_DasherModel != null) {
+				m_DasherModel.deleteLM(); // Added CSFS: The language model was
+				// previously given no opportunity to unregister itself.
+				m_DasherModel.UnregisterComponent();
+			}
+			
+			m_DasherModel = new CDasherModel(m_EventHandler, m_SettingsStore, this, m_AlphIO);
+			m_Alphabet = m_DasherModel.GetAlphabetNew();
+			
+			String T = m_Alphabet.GetTrainingFile();
+			
+			int iTotalBytes = 0;
+			iTotalBytes += GetFileSize(GetStringParameter(Esp_parameters.SP_SYSTEM_LOC) + T);
+			iTotalBytes += GetFileSize(GetStringParameter(Esp_parameters.SP_USER_LOC) + T);
+			
+			if(iTotalBytes > 0) {
+				int iOffset;
+				iOffset = TrainFile(GetStringParameter(Esp_parameters.SP_SYSTEM_LOC) + T, iTotalBytes, 0);
+				TrainFile(GetStringParameter(Esp_parameters.SP_USER_LOC) + T, iTotalBytes, iOffset);
+			}
+			else {
+				CMessageEvent oEvent = new CMessageEvent("No training text is avilable for the selected alphabet. Dasher will function, but it may be difficult to enter text.\nPlease see http://www.dasher.org.uk/alphabets/ for more information.", 0, 0);
+				m_EventHandler.InsertEvent(oEvent);
+			}
+			
+			Event = new CLockEvent("Training Dasher", false, 0);
+			m_EventHandler.InsertEvent(Event);
+			Event = null;
+		}
+	}
+	
+	/**
+	 * Simply calls DasherModel.Start() and DasherView.ResetYAutoOffset()
+	 * so see these functions' documentation for detail. 
+	 */
+	public void Start() {
+		// TODO: Clarify the relationship between Start() and
+		// InvalidateContext() - I believe that they essentially do the same
+		// thing
+		PauseAt(0, 0);
+		if(m_DasherModel != null) {
+			m_DasherModel.Start();
+		}
+		if(m_DasherView != null) {
+			m_DasherView.ResetYAutoOffset();
+		}
+	}
+	
+	/**
+	 * Pauses Dasher at a given mouse location, and sets
+	 * BP_REDRAW so that a full redraw will be performed next
+	 * frame.
+	 * <p>
+	 * Also generates a StopEvent to notify other components.
+	 * 
+	 * @param MouseX Mouse x co-ordinate at the time of stopping
+	 * @param MouseY Mouse y co-ordinate at the time of stopping
+	 */
+	public void PauseAt(int MouseX, int MouseY) {
+		SetBoolParameter(Ebp_parameters.BP_DASHER_PAUSED, true);
+		
+		// Request a full redraw at the next time step.
+		SetBoolParameter(Ebp_parameters.BP_REDRAW, true);
+		
+		CStopEvent oEvent = new CStopEvent();
+		m_EventHandler.InsertEvent(oEvent);
+		
+		if (m_UserLog != null)
+			m_UserLog.StopWriting((float) GetNats());
+	}
+	
+	/**
+	 * Pauses Dasher and calls DasherModel.Halt().
+	 * <p>
+	 * This function, unlike PauseAt, does not throw a StopEvent. 
+	 */	
+	public void Halt() {
+		SetBoolParameter(Ebp_parameters.BP_DASHER_PAUSED, true);
+		
+		if(GetBoolParameter(Ebp_parameters.BP_MOUSEPOS_MODE)) {
+			SetLongParameter(Elp_parameters.LP_MOUSE_POS_BOX, 1);
+		}
+		
+		// This will cause us to reinitialise the frame rate counter - ie we start off slowly
+		if(m_DasherModel != null)
+			m_DasherModel.Halt();
+	}
+	
+	/**
+	 * Unpause Dasher. This will send a StartEvent to all
+	 * components.
+	 * 
+	 * @param Time System time as a UNIX timestamp at which Dasher was restarted.
+	 */
+	public void Unpause(long Time) { // CSFS: Formerly unsigned.
+		SetBoolParameter(Ebp_parameters.BP_DASHER_PAUSED, false);
+		
+		if(m_DasherModel != null) {
+			m_DasherModel.Reset_framerate(Time);
+			//m_pDasherModel->Set_paused(m_Paused);
+		}
+				
+		CStartEvent oEvent = new CStartEvent();
+		m_EventHandler.InsertEvent(oEvent);
+		
+		ResetNats();
+		if (m_UserLog != null)
+			m_UserLog.StartWriting();
+	}
+	
+	/**
+	 * Creates an input device by calling GetModuleByName on the parameter
+	 * SP_INPUT_DEVICE. In the event that this does not correspond
+	 * to a module known by the Module Manager, m_Input will
+	 * be set to null.
+	 * <p>
+	 * If there is an existing input device, it will be Unref'd and
+	 * Deactivated first.
+	 * <p>
+	 * In the event that a non-null DasherInput class is created,
+	 * its Ref and Activate methods will be called immediately.
+	 * 
+	 * @see CDasherInput
+	 * @see CModuleManager
+	 *
+	 */	
+	public void CreateInput() {
+		
+		// FIXME - this shouldn't be the model used here - we should just change a parameter and work from the appropriate listener
+		
+		if(m_Input != null) {
+			m_Input.Deactivate();
+			m_Input.Unref();
+		}
+		
+		m_Input = (CDasherInput)GetModuleByName(GetStringParameter(Esp_parameters.SP_INPUT_DEVICE));
+		
+		if(m_Input != null) {
+			m_Input.Ref();
+			m_Input.Activate();
+		}
+		
+		if(m_DasherView != null)
+			m_DasherView.SetInput(m_Input);
+	}
+	
+	/**
+	 * Encapsulates the entire process of drawing a
+	 * new frame of the Dasher world.
+	 * <p>
+	 * We invoke our input filter's Timer method, which determines
+	 * in what way the Model should be updated, if at all, allow the
+	 * Model to check its consistency after being changed, and then
+	 * finally ask our View to draw the newly updated world.
+	 * <p>
+	 * Method will return without any action if any of the three
+	 * lock variables are true.
+	 * 
+	 * @param iTime Current system time as a UNIX time stamp.
+	 */
+	public void NewFrame(long iTime) {
+		// Fail if Dasher is locked
+		
+		
+		if(m_bGlobalLock || m_bShutdownLock || m_bConnectLock) return;
+			
+			boolean bChanged = false;
+		
+		
+		if(m_DasherView != null) {
+			if(!GetBoolParameter(Ebp_parameters.BP_TRAINING)) {
+				if (m_UserLog != null) {
+					
+					ArrayList<CSymbolProb> vAdded = new ArrayList<CSymbolProb>();
+					int iNumDeleted = 0;
+					
+					if(m_InputFilter != null) {
+						bChanged = m_InputFilter.Timer(iTime, m_DasherView, m_DasherModel); // FIXME - need logging stuff here
+					}
+					
+					if (iNumDeleted > 0)
+						m_UserLog.DeleteSymbols(iNumDeleted);
+						if (vAdded.size() > 0)
+							m_UserLog.AddSymbols(vAdded);
+							
+				}
+				else {
+					if(m_InputFilter != null) {
+						bChanged = m_InputFilter.Timer(iTime, m_DasherView, m_DasherModel);
+					}
+				}
+				
+				m_DasherModel.CheckForNewRoot(m_DasherView);
+			}
+		}
+		
+		Draw(bChanged);
+		
+		// This just passes the time through to the framerate tracker, so we
+		// know how often new frames are being drawn.
+		if(m_DasherModel != null)
+			m_DasherModel.NewFrame(iTime);
+	}
+	
+	/**
+	 * Completely draws the screen based on the current state
+	 * of the model, taking into account whether the model
+	 * has changed since the last frame.
+	 * <p>
+	 * This breaks down to calling the Model's RenderToView
+	 * method if we need to draw the nodes, and then calling the
+	 * InputFilter's DecorateView method.
+	 * <p>
+	 * The View's Display() method is called only in the event
+	 * that anything has changed.
+	 * <p>
+	 * At present, this is hacked such that it always does a full
+	 * redraw if Dasher is unpaused, owing to the fact that the
+	 * Java front-end must receive a frame every time it calls
+	 * Draw. See the documentation for applet.JDasherScreen for details.
+	 *  
+	 * @param bRedrawNodes True if the Model has changed since the last frame.
+	 * @see dasher.applet.JDasherScreen
+	 */
+	public void Draw(boolean bRedrawNodes) {
+		
+		// FIXME -- currently always drawing the nodes, since Swing's images
+		// do not persist.
+		
+		bRedrawNodes = true;
+		
+		if(m_DasherView == null || m_DasherModel == null)
+			return;
+		
+		if(bRedrawNodes) {
+			m_DasherView.Screen().SendMarker(0);
+			m_DasherModel.RenderToView(m_DasherView, true);
+		}
+		
+		m_DasherView.Screen().SendMarker(1);
+		
+		boolean bDecorationsChanged = false;
+		
+		if(m_InputFilter != null) {
+			bDecorationsChanged = m_InputFilter.DecorateView(m_DasherView);
+		}
+		
+		if(bRedrawNodes || bDecorationsChanged)
+			m_DasherView.Display();
+	}
+	
+	/**
+	 * Abstract method which will be called whenever a screen
+	 * redraw is required. This is implemented for architectures
+	 * which require drawing to happen in a top-down fashion.
+	 * Implementations which allow drawing to be initiated from
+	 * the bottom up may do so my recalling Draw.
+	 * 
+	 * @param bChanged True if the model has changed since the last frame
+	 */
+	public abstract void Redraw(boolean bChanged);
+	
+	/**
+	 * Changes the alphabet in use to that described by SP_ALPHABET_ID.
+	 * <p>
+	 * Writes the training file to disk using WriteTrainFileFull,
+	 * and then runs CreateDasherModel, deleting an exsiting Model
+	 * if it exists.
+	 * <p>
+	 * In the event that SP_ALPHABET_ID is empty when this function
+	 * is called, it is set to the default suggested by m_AlphIO.
+	 */
+	public void ChangeAlphabet() {
+		
+		if(GetStringParameter(Esp_parameters.SP_ALPHABET_ID) == "") {
+			SetStringParameter(Esp_parameters.SP_ALPHABET_ID, m_AlphIO.GetDefault());
+			// This will result in ChangeAlphabet() being called again, so
+			// exit from the first recursion
+			return;
+		}
+		
+		// Send a lock event
+		
+		WriteTrainFileFull();
+		
+		// Lock Dasher to prevent changes from happening while we're training.
+		
+		SetBoolParameter( Ebp_parameters.BP_TRAINING, true );
+		
+		if(m_DasherModel != null) {
+			m_DasherModel.UnregisterComponent();
+			m_DasherModel = null;
+		}
+				
+		CreateDasherModel();
+		
+		// Let our user log object know about the new alphabet since
+		// it needs to convert symbols into text for the log file.
+		if (m_UserLog != null)
+			m_UserLog.SetAlphabetPtr(m_Alphabet);
+			
+			// Apply options from alphabet
+			
+			SetBoolParameter( Ebp_parameters.BP_TRAINING, false );
+			
+			Start();
+			
+			
+		}
+	
+	/**
+	 * Changes the colour scheme to that described by SP_COLOUR_ID.
+	 * <p>
+	 * If m_ColourIO is null at the time, this method will return
+	 * without performing any action.
+	 * <p>
+	 * Specifically, this method retrieves the colour scheme named
+	 * by SP_COLOUR_ID from m_ColourIO, and creates a new CustomColours
+	 * wrapping it, finally setting m_Colours to point to the new
+	 * scheme. Finally, if successful, the screen is informed of the
+	 * new scheme by calling its SetColourScheme method.
+	 */
+	public void ChangeColours() {
+		if(m_ColourIO == null)
+			return;
+		
+		if(m_Colours != null) {
+			m_Colours = null;
+		}
+		
+		
+		CColourIO.ColourInfo oColourInfo = (m_ColourIO.GetInfo(GetStringParameter(Esp_parameters.SP_COLOUR_ID)));
+		m_Colours = new CCustomColours(oColourInfo);
+		
+		if(m_DasherScreen != null) {
+			m_DasherScreen.SetColourScheme(m_Colours);
+		}
+	}
+	
+	/**
+	 * Changes the Screen to which we should send drawing instructions.
+	 * <p>
+	 * If a view already exists, it is notified of the new screen.
+	 * <p>
+	 * If no view exists, one is created by a call to ChangeView.
+	 * 
+	 * @param NewScreen New screen
+	 */
+	public void ChangeScreen(CDasherScreen NewScreen) {
+		m_DasherScreen = NewScreen;
+		m_DasherScreen.SetColourScheme(m_Colours);
+		
+		if(m_DasherView != null) {
+			m_DasherView.ChangeScreen(m_DasherScreen);
+		} else {
+			if(GetLongParameter(Elp_parameters.LP_VIEW_ID) != -1)
+				ChangeView();
+		}
+		
+		Redraw(true);
+	}
+	
+	/**
+	 * Creates an instance of DasherViewSquare, and, if they are present,
+	 * informs it of our current Input Filter and Screen.
+	 * <p>
+	 * This ought to respond to the LP_VIEW_ID parameter, but since
+	 * at present there is only one, it is ignored for now. 
+	 *
+	 */
+	public void ChangeView() {
+		// TODO: Actually respond to LP_VIEW_ID parameter (although there is only one view at the moment)
+		
+		if(m_DasherScreen != null && m_DasherModel != null) 
+		{
+			m_DasherView = null;
+			m_DasherView = new CDasherViewSquare(m_EventHandler, m_SettingsStore, m_DasherScreen);
+			
+			
+			if (m_Input != null)
+				m_DasherView.SetInput(m_Input);
+		}
+	}
+	
+	/**
+	 * Deferred to m_AlphIO
+	 * 
+	 * @see CAlphIO
+	 */
+	public void GetAlphabets(ArrayList<String> AlphabetList) {
+		m_AlphIO.GetAlphabets(AlphabetList);
+	}
+	
+	/**
+	 * Deferred to m_AlphIO
+	 * 
+	 * @see CAlphIO
+	 */
+	public CAlphIO.AlphInfo GetInfo(String AlphID) {
+		return m_AlphIO.GetInfo(AlphID);
+	}
+	
+	/**
+	 * Deferred to m_AlphIO
+	 * 
+	 * @see CAlphIO
+	 */
+	public void SetInfo(CAlphIO.AlphInfo NewInfo) {
+		m_AlphIO.SetInfo(NewInfo);
+	}
+	
+	/**
+	 * Deferred to m_AlphIO
+	 * 
+	 * @see CAlphIO
+	 */
+	public void DeleteAlphabet(String AlphID) {
+		m_AlphIO.Delete(AlphID);
+	}
+	
+	/**
+	 * Deferred to m_ColourIO
+	 * 
+	 * @see CColourIO
+	 */
+	public void GetColours(ArrayList<String> ColourList) {
+		m_ColourIO.GetColours(ColourList);
+	}
+	
+	/**
+	 * Trains our Model from the text found in a given file,
+	 * which must be UTF-8 encoded.
+	 * <p>
+	 * The actual training is done by TrainStream; this just
+	 * creates a FileInputStream and passes it into TrainStream.
+	 * 
+	 * @param Filename Path (absolute or relative) to file containing training text.
+	 * @param iTotalBytes Number of bytes to read
+	 * @param iOffset Offset at which to start reading
+	 * @return Number of bytes read
+	 */
+	public int TrainFile(String Filename, int iTotalBytes, int iOffset) {
+		
+		/* CSFS: This has now been split into two parts in order to accomodate
+		 * training from streams which aren't files. This is especially
+		 * relevant using an Applet. This method is overridden in JDasher to
+		 * permit the use of JAR resources instead. The bulk of the functionality
+		 * is now in TrainStream, which takes an InputStream as an argument.
+		 */
+		
+		if(Filename == "")
+			return 0;
+		
+		InputStream FileIn;
+		try {
+			FileIn = new BufferedInputStream(new FileInputStream(Filename));
+		}
+		catch (Exception e){
+			return 0;
+		}
+
+		return TrainStream(FileIn, iTotalBytes, iOffset);
+		
+	}
+	
+	/**
+	 * Trains the language model from a given InputStream, which
+	 * must be UTF-8 encoded.
+	 * <p>
+	 * LockEvents will be inserted every 1KB of data read, informing
+	 * components and the interface of the progress made in reading
+	 * the file.
+	 * 
+	 * @param FileIn InputStream from which to read.
+	 * @param iTotalBytes Number of bytes to read.
+	 * @param iOffset Offset at which to start reading.
+	 * @return Number of bytes read
+	 */	
+	public int TrainStream(InputStream FileIn, int iTotalBytes, int iOffset) {
+		
+		/* CSFS: This function is going to be rather more involved
+		 * to port, so I am leaving a commented version of the C++
+		 * here for reference, annotated with my interpretations
+		 * of what it means, so as to help establish whether my Java
+		 * version is even *trying* to do the right thing, or if
+		 * I have misunderstood the original.
+		 */
+		
+		/* CSFS: I have made significant changes to this function and CAlphabet.getSymbols
+		 * on the grounds that our internal character set is different. Under C++, the scheme
+		 * was that this function did the file I/O and fed UTF-8 bytes to CAlphabet to
+		 * find the symbol identifiers. Here, I am reading a UTF-8 file to produce
+		 * a UTF-16 String, which is then fed to CAlphabet.
+		 */
+		
+		// BEGIN C++
+		
+		/*
+		if(Filename == "")
+			return 0;
+		
+		FILE *InputFile;
+		if((InputFile = fopen(Filename.c_str(), "r")) == (FILE *) 0)
+			return 0;
+			
+			 * If the file-handle we get back is null, return zero.
+			 * So the Java version should handle an exception at this point
+			 * by returning zero.
+		
+		const int BufferSize = 1024;
+		char InputBuffer[BufferSize]; // 1024-byte buffer; should be doable using BufferedReader
+		string StringBuffer;
+		int NumberRead;
+		int iTotalRead(0);
+		
+		ArrayList < symbol > Symbols;
+		
+		CDasherModel::CTrainer * pTrainer = m_pDasherModel->GetTrainer();
+		do {
+			NumberRead = fread(InputBuffer, 1, BufferSize - 1, InputFile); // Means 'read 1023 bytes to InputBuffer'
+			InputBuffer[NumberRead] = '\0'; // Add a null terminator
+			StringBuffer += InputBuffer;
+			bool bIsMore = false;
+			if(NumberRead == (BufferSize - 1)) // Did we get as many bytes as expected?
+				bIsMore = true; // If so, there may be more!
+			
+			Symbols.clear(); // Empty ArrayList
+			m_Alphabet->GetSymbols(&Symbols, &StringBuffer, bIsMore); // Fill with symbols recognised by Alphabet
+			
+			pTrainer->Train(Symbols); // Train! 
+			iTotalRead += NumberRead; // Accumulate.
+			
+			// TODO: No reason for this to be a pointer (other than cut/paste laziness!)
+			CLockEvent *pEvent;
+			pEvent = new CLockEvent("Training Dasher", true, static_cast<int>((100.0 * (iTotalRead + iOffset))/iTotalBytes));
+			m_pEventHandler->InsertEvent(pEvent);
+			delete pEvent;
+			
+		} while(NumberRead == BufferSize - 1); // Until we appear to have reached EOF
+		
+		delete pTrainer;
+		
+		fclose(InputFile);
+		
+		return iTotalRead;
+		*/
+		
+		// END C++
+		
+		final int BufferSize = 1024;
+		byte[] InputBuffer = new byte[BufferSize];
+		
+		/* CSFS: Changed to bytes since Java chars are a 16-bit type. */
+		
+		// ArrayList<Byte> StrBuffer = new ArrayList<Byte>(); // For the reasons discussed above.
+		// Ought to be impossible that the buffer should have this much data in it at
+		// any given time.
+		int NumberRead = 0;
+		int iTotalRead = 0;
+		boolean bIsMore = false;
+		
+		ArrayList<Integer> Symbols = new ArrayList<Integer>();
+		
+		CDasherModel.CTrainer Trainer = m_DasherModel.GetTrainer();
+		
+		do {
+			
+			try {
+				//NumberRead = FileIn.read(InputBuffer, 0, BufferSize - 1); // Means 'read 1023 bytes to InputBuffer at offset 0'
+				
+				//System.out.printf("%d, %d+", NumberRead, FileIn.available());
+				
+				NumberRead = 0;
+				int temp = 0;
+				while(NumberRead < (BufferSize - 1)) {
+					temp = FileIn.read();
+					if(temp == -1) {
+						break;
+					}
+					else if(temp != 13) {
+						InputBuffer[NumberRead] = (byte)temp;
+						NumberRead++;
+					}
+				}
+			}
+			catch(IOException e) {
+				System.out.printf("Aborting training on an IOException%n");
+				return 0;
+			}
+			
+			InputBuffer[NumberRead] = 0; // Add a null terminator
+			
+			bIsMore = false;
+			if(NumberRead == (BufferSize - 1)) // Did we get as many bytes as expected?
+				bIsMore = true; // If so, there may be more!
+			
+			Symbols.clear(); // Empty ArrayList
+			
+			String translatedInput;
+			
+			try {
+				translatedInput = new String(InputBuffer, "UTF-8");
+			}
+			catch(Exception e) {
+				System.out.printf("Failed reading training file: This system cannot decode UTF-8.%n");
+				return 0;
+			}
+			
+			m_Alphabet.GetSymbols(Symbols, translatedInput, bIsMore); // Fill with symbols recognised by Alphabet
+			
+			Trainer.Train(Symbols); // Train! 
+			iTotalRead += NumberRead; // Accumulate.
+			
+			CLockEvent Event;
+			Event = new CLockEvent("Training Dasher", true, (int)((100.0 * (iTotalRead + iOffset))/iTotalBytes));
+			m_EventHandler.InsertEvent(Event);
+			Event = null;
+			
+		} while(NumberRead == BufferSize - 1); // Until we appear to have reached EOF
+		
+		return iTotalRead;
+		
+	}
+	
+	/**
+	 * Retrieves a list of available font sizes. This class
+	 * returns a generic reasonably sensible list 
+	 * (11, 14, 20, 22, 28, 40, 44, 56, 80) but should be
+	 * overridden by the implementing class if a better answer
+	 * can be retrieved.
+	 * 
+	 * @param FontSizes Collection to be filled with available sizes
+	 */
+	public void GetFontSizes(Collection<Integer> FontSizes) {
+		FontSizes.add(20);
+		FontSizes.add(14);
+		FontSizes.add(11);
+		FontSizes.add(40);
+		FontSizes.add(28);
+		FontSizes.add(22);
+		FontSizes.add(80);
+		FontSizes.add(56);
+		FontSizes.add(44);
+	}
+	
+	/**
+	 * Stub. Ought to return the current characters per minute,
+	 * but this is not yet implemented.
+	 *  
+	 * @return 0
+	 */
+	public double GetCurCPM() {
+		//
+		return 0;
+	}
+	
+	/**
+	 * Stub. Ought to return the current frames rate, but this
+	 * is not yet implemented.
+	 * 
+	 * @return 0
+	 */
+	public double GetCurFPS() {
+		//
+		return 0;
+	}
+	
+	/**
+	 * Deferred to m_DasherView. If this is
+	 * null, -1 is returned.
+	 * 
+	 * @return -1 if null, or else DasherView's answer.
+	 * @see CDasherView
+	 */
+	public int GetAutoOffset() {
+		if(m_DasherView != null) {
+			return m_DasherView.GetAutoOffset();
+		}
+		return -1;
+	}
+	
+	/**
+	 * Deferred to CDasherModel
+	 * 
+	 * @see CDasherModel
+	 */
+	public double GetNats() {
+		if(m_DasherModel != null)
+			return m_DasherModel.GetNats();
+			else
+				return 0.0;
+	}
+	
+	/**
+	 * Passed on to CDasherModel, if it is non-null.
+	 * 
+	 * @see CDasherModel
+	 */
+	public void ResetNats() {
+		if(m_DasherModel != null)
+			m_DasherModel.ResetNats();
+	}
+	
+	/**
+	 * Attempts to retrieve a fresh context by dispatching an
+	 * EditContextEvent, which has a field to return a new context
+	 * if anybody hearing the event chose to submit one.
+	 * <p>
+	 * If bForceStart is true, or we received a non-empty context,
+	 * the Model is fed the new Context using SetContext and is
+	 * then paused.
+	 * <p>
+	 * Finally there is a mandatory screen redraw.
+	 * 
+	 * @param bForceStart Should we rebuild the context even if none is submitted?
+	 */
+	public void InvalidateContext(boolean bForceStart) {
+			
+		/* CSFS: This used to clear m_DasherModel.strContextBuffer,
+		 * which has been removed per the notes at the top of the file.
+		 */
+		
+		CEditContextEvent oEvent = new CEditContextEvent(10);
+		m_EventHandler.InsertEvent(oEvent);
+		
+		String strNewContext = oEvent.newContext;
+		
+		strTrainfileBuffer.append(strNewContext);
+		
+		/* Extract a potential answer from the event packet */
+		
+		oEvent = null;
+				
+		if(bForceStart || !(strCurrentContext.isEmpty())) {
+			if(m_DasherModel != null) {
+				if(m_DasherModel.m_bContextSensitive || bForceStart) {
+					m_DasherModel.SetContext(strNewContext);
+					PauseAt(0,0);
+				}
+			}
+		}
+		
+		if(m_DasherView != null)
+			while( m_DasherModel.CheckForNewRoot(m_DasherView) ) {
+				// Do nothing
+			}
+		
+		Redraw(true);
+		
+	}
+	
+	
+	/* public void SetContext(String strNewContext) {
+		m_DasherModel.m_strContextBuffer = strNewContext;
+	} */
+	
+	// REMOVED: See bug notes at the top.
+	
+//	Control mode stuff
+	
+	/**
+	 * Deferred to m_DasherModel.
+	 * 
+	 * @see CDasherModel
+	 */
+	public void RegisterNode( int iID, String strLabel, int iColour ) {
+		m_DasherModel.RegisterNode(iID, strLabel, iColour);
+	}
+	
+	/**
+	 * Deferred to m_DasherModel.
+	 * 
+	 * @see CDasherModel
+	 */
+	public void ConnectNode(int iChild, int iParent, int iAfter) {
+		m_DasherModel.ConnectNode(iChild, iParent, iAfter);
+	}
+	
+	/**
+	 * Deferred to m_DasherModel.
+	 * 
+	 * @see CDasherModel
+	 */
+	public void DisconnectNode(int iChild, int iParent) {
+		m_DasherModel.DisconnectNode(iChild, iParent);
+	}
+	
+	/**
+	 * Deferred to CSettingsStore
+	 * 
+	 * @see CSettingsStore
+	 * 
+	 */
+	public void SetBoolParameter(Ebp_parameters iParameter, boolean bValue) {
+		m_SettingsStore.SetBoolParameter(iParameter, bValue);
+	}
+	
+	/**
+	 * Deferred to CSettingsStore
+	 * 
+	 * @see CSettingsStore
+	 * 
+	 */
+	public void SetLongParameter(Elp_parameters iParameter, long lValue) { 
+		m_SettingsStore.SetLongParameter(iParameter, lValue);
+	};
+	
+	/**
+	 * Deferred to CSettingsStore
+	 * 
+	 * @see CSettingsStore
+	 * 
+	 */
+	public void SetStringParameter(Esp_parameters iParameter, String sValue) {
+		PreSetNotify(iParameter, sValue);
+		m_SettingsStore.SetStringParameter(iParameter, sValue);
+	};
+	
+	/**
+	 * Deferred to CSettingsStore
+	 * 
+	 * @see CSettingsStore
+	 * 
+	 */
+	public boolean GetBoolParameter(Ebp_parameters iParameter) {
+		return m_SettingsStore.GetBoolParameter(iParameter);
+	}
+	
+	/**
+	 * Deferred to CSettingsStore
+	 * 
+	 * @see CSettingsStore
+	 * 
+	 */
+	public long GetLongParameter(Elp_parameters iParameter) {
+		return m_SettingsStore.GetLongParameter(iParameter);
+	}
+	
+	/**
+	 * Deferred to CSettingsStore
+	 * 
+	 * @see CSettingsStore
+	 * 
+	 */
+	public String GetStringParameter(Esp_parameters iParameter) {
+		return m_SettingsStore.GetStringParameter(iParameter);
+	}
+	
+	/**
+	 * Deferred to CSettingsStore
+	 * 
+	 * @see CSettingsStore
+	 * 
+	 */
+	public void ResetParameter(EParameters iParameter) {
+		m_SettingsStore.ResetParameter(iParameter);
+	}
+	
+	/**
+	 * Gets a reference to m_UserLog.
+	 * 
+	 * @return m_UserLog
+	 */
+	public CUserLog GetUserLogPtr() {
+		return m_UserLog;
+	}
+	
+	/**
+	 * Signals a key press to our input filter. This should be invoked
+	 * by an implementation whenever a key is pressed.
+	 * <p>
+	 * Key presses signalled in this way are ignored if we have
+	 * no input filter, or if BP_TRAINING is true.
+	 * <p>
+	 * Currently assigned key IDs:
+	 * <p><ul>
+	 * <li>0: Start/stop (keyboard)
+	 * <li>1: Move east (for button modes)
+	 * <li>2: Move north
+	 * <li>3: Move west
+	 * <li>4: Move south
+	 * <li>100: Mouse click
+	 * </ul>
+	 * <p>
+	 * The actual physical keys assigned to these functions
+	 * are down to the implementation, and may be user-definable.
+	 * 
+	 * @param iTime System time as a UNIX timestamp at which the key was pressed
+	 * @param iId Identifier of the pressed key
+	 */
+	public void KeyDown(long iTime, int iId) {
+		if(m_InputFilter != null && !GetBoolParameter(Ebp_parameters.BP_TRAINING)) {
+			m_InputFilter.KeyDown(iTime, iId, m_DasherModel);
+		}
+	}
+	
+	/**
+	 * Signals a key press to our input filter. This should be invoked
+	 * by an implementation whenever a key is released.
+	 * <p>
+	 * Key presses signalled in this way are ignored if we have
+	 * no input filter, or if BP_TRAINING is true.
+	 * <p>
+	 * Currently assigned key IDs:
+	 * <p><ul>
+	 * <li>0: Start/stop
+	 * <li>1: Move east (for button modes)
+	 * <li>2: Move north
+	 * <li>3: Move west
+	 * <li>4: Move south
+	 * <li>100: Left mouse click (or equivalent)
+	 * </ul>
+	 * <p>
+	 * The actual physical keys assigned to these functions
+	 * are down to the implementation, and may be user-definable.
+	 * 
+	 * @param iTime System time as a UNIX timestamp at which the key was pressed
+	 * @param iId Identifier of the pressed key
+	 */
+	public void KeyUp(long iTime, int iId) {
+		if(m_InputFilter != null && !GetBoolParameter(Ebp_parameters.BP_TRAINING)) {
+			m_InputFilter.KeyUp(iTime, iId, m_DasherModel);
+		}
+	}
+	
+	/**
+	 * Creates m_InputFilter by retrieving the module named
+	 * in SP_INPUT_FILTER.
+	 * <p>
+	 * If this is successful and an input filter is created,
+	 * it will be Ref'd and Activated immediately.
+	 * <p>
+	 * If unsuccessful, m_InputFilter will be set to null.
+	 * <p>
+	 * If there is an existing filter, it is Deactivated and
+	 * Unref'd first.
+	 *
+	 */
+	public void CreateInputFilter()
+	{
+		if(m_InputFilter != null) {
+			m_InputFilter.Deactivate();
+			m_InputFilter.Unref();
+			m_InputFilter = null;
+		}
+		
+		m_InputFilter = (CInputFilter)GetModuleByName(GetStringParameter(Esp_parameters.SP_INPUT_FILTER));
+		
+		if(m_InputFilter != null) {
+			m_InputFilter.Ref();
+			m_InputFilter.Activate();
+		}
+	}
+	
+	/**
+	 * Deferred to m_oModuleManager
+	 * 
+	 * @see CModuleManager
+	 */
+	public void RegisterFactory(CModuleFactory Factory) {
+		m_oModuleManager.RegisterFactory(Factory);
+	}
+	
+	/**
+	 * Deferred to m_oModuleManager
+	 * 
+	 * @see CModuleManager
+	 */
+	public CDasherModule GetModule(long iID) {
+		return m_oModuleManager.GetModule(iID);
+	}
+	
+	/**
+	 * Deferred to m_oModuleManager
+	 * 
+	 * @see CModuleManager
+	 */
+	public CDasherModule GetModuleByName(String strName) {
+		return m_oModuleManager.GetModuleByName(strName);
+	}
+	
+	/**
+	 * Manually registers a number of input filters.
+	 * <p>
+	 * At present this registers only Normal Control and Click Mode,
+	 * but as an when others are implemented will register these also.
+	 * <p>
+	 * The same input filter may be registered repeatedly under
+	 * a variety of different names if desired (so long as the
+	 * filter's constructor permits a user-defined name).
+	 * <p>
+	 * This is commonly used to produce a number of different
+	 * button modes which use the same filter class.
+	 *
+	 */
+	public void CreateFactories() {
+		RegisterFactory(new CWrapperFactory(m_EventHandler, m_SettingsStore, new CDefaultFilter(m_EventHandler, m_SettingsStore, this, m_DasherModel,3, "Normal Control")));
+		//RegisterFactory(new CWrapperFactory(m_EventHandler, m_SettingsStore, new COneDimensionalFilter(m_EventHandler, m_SettingsStore, this, m_DasherModel)));
+		//RegisterFactory(new CWrapperFactory(m_EventHandler, m_SettingsStore, new CEyetrackerFilter(m_EventHandler, m_SettingsStore, this, m_DasherModel)));
+		RegisterFactory(new CWrapperFactory(m_EventHandler, m_SettingsStore, new CClickFilter(m_EventHandler, m_SettingsStore, this)));
+		//RegisterFactory(new CWrapperFactory(m_EventHandler, m_SettingsStore, new CDynamicFilter(m_EventHandler, m_SettingsStore, this)));
+		//RegisterFactory(new CWrapperFactory(m_EventHandler, m_SettingsStore, new CTwoButtonDynamicFilter(m_EventHandler, m_SettingsStore, this)));
+		// TODO: specialist factory for button mode
+		//RegisterFactory(new CWrapperFactory(m_EventHandler, m_SettingsStore, new CDasherButtons(m_EventHandler, m_SettingsStore, this, 5, 1, true,8, "Menu Mode")));
+		//RegisterFactory(new CWrapperFactory(m_EventHandler, m_SettingsStore, new CDasherButtons(m_EventHandler, m_SettingsStore, this, 3, 0, false,10, "Direct Mode")));
+		//  RegisterFactory(new CWrapperFactory(m_EventHandler, m_SettingsStore, new CDasherButtons(m_EventHandler, m_SettingsStore, this, 4, 0, false,11, "Buttons 3")));
+		//RegisterFactory(new CWrapperFactory(m_EventHandler, m_SettingsStore, new CDasherButtons(m_EventHandler, m_SettingsStore, this, 3, 3, false,12, "Alternating Direct Mode")));
+		//RegisterFactory(new CWrapperFactory(m_EventHandler, m_SettingsStore, new CDasherButtons(m_EventHandler, m_SettingsStore, this, 4, 2, false,13, "Compass Mode")));
+		//RegisterFactory(new CWrapperFactory(m_EventHandler, m_SettingsStore, new CStylusFilter(m_EventHandler, m_SettingsStore, this, m_DasherModel,15, "Stylus Control"))); 
+		
+		/* CSFS: The commented out filters are not yet implemented. */
+		
+	}
+	
+	/* CSFS: This is worrisome, it looks as if all identifiers and their associated
+	 * functions may need to be set to use UTF-8, ie. prevented from using Java
+	 * Strings. Commenting out for the time being since I won't be using GetValues
+	 * until much later in testing.
+	 */
+	
+	/* public void GetPermittedValues(int iParameter, ArrayList<String> vList) {
+		// TODO: Deprecate direct calls to these functions
+		switch (iParameter) {
+		case Esp_parameters.SP_ALPHABET_ID:
+			GetAlphabets(vList);
+			break;
+		case Esp_parameters.SP_COLOUR_ID:
+			GetColours(vList);
+			break;
+		case Esp_parameters.SP_INPUT_FILTER:
+			m_oModuleManager.ListModules(1, vList);
+			break;
+		case Esp_parameters.SP_INPUT_DEVICE:
+			m_oModuleManager.ListModules(0, vList);
+			break;
+		}
+	} */
+	
+	/**
+	 * Engages the shutdown lock (m_bShutdownLock).
+	 */
+	public void StartShutdown() {
+		m_bShutdownLock = true;
+	}
+	
+	
+	/**
+	 * Writes the text entered by the user as a training file.
+	 * <p>
+	 * Won't work at present, as WriteTrainFile() is stubbed.
+	 *
+	 */
+	protected void WriteTrainFileFull() {
+		WriteTrainFile(strTrainfileBuffer.toString());
+		strTrainfileBuffer.setLength(0);
+	}
+	
+	/**
+	 * Writes the first 100 characters of user-entered text
+	 * as a training file.
+	 * <p>
+	 * Won't work at the moment, as WriteTrainFile() is stubbed.
+	 *
+	 */
+	protected void WriteTrainFilePartial() {
+		// TODO: what if we're midway through a unicode character?
+		
+		if(strTrainfileBuffer.length() > 100) {
+			//LinkedList<Byte> surplus = new LinkedList<Byte>();
+			//while(strTrainfileBuffer.length() > 100) {
+			//	surplus.addFirst(strTrainfileBuffer.getLast());
+			//	strTrainfileBuffer.removeLast();
+			//}
+			WriteTrainFile(strTrainfileBuffer.substring(0, 99));
+			strTrainfileBuffer.delete(0, 99);
+			// strTrainfileBuffer.addAll(surplus);
+			
+			/* CSFS: Write the first 100 bytes to disk and keep the rest */
+		}
+		else {
+			WriteTrainFile(strTrainfileBuffer.toString());
+			strTrainfileBuffer.setLength(0);
+		}
+		
+	}
+	
+	/**
+	 * Retrieves the EventHandler created during this class'
+	 * construction, and which calls this interface to handle
+	 * events.
+	 * 
+	 * @return EventHandler tied to this Interface.
+	 */
+	public CEventHandler GetEventHandler() {
+		return m_EventHandler;
+	}
+	
+	/**
+	 * Called for every dispatched event after all components
+	 * have received it and *after* InterfaceEventHandler.
+	 * <p>
+	 * By default this ignores all events; the intent is for
+	 * implementations to override it if they want to either
+	 * a) Pass events out to UI components which the core doesn't
+	 * know about, or b) Transcribe our internal events into some
+	 * other event-dispatching scheme such as Win32's message
+	 * dispatching scheme.
+	 * 
+	 * @param Event Event being signalled
+	 */
+	public void ExternalEventHandler(CEvent Event) {
+		
+	}
+	
+	/**
+	 * Gets the current alphabet
+	 * 
+	 * @return Current alphabet
+	 */
+	public CAlphabet GetAlphabet() {
+	    return m_Alphabet;
+	}
+	
+	/**
+	 * Stub. This ought to write out a training file, but
+	 * is not implemented at present due since the applet
+	 * implementation cannot write a training file to the
+	 * local disk.
+	 * <p>
+	 * This method should be implemented if a local application
+	 * version of JDasher is to be implemented, and should write
+	 * a file containing the user's typed text encoded as UTF-8
+	 * suitable for reading by the TrainStream routine.
+	 * 
+	 * @param strNewText
+	 */
+	public void WriteTrainFile(String strNewText) {
+		/* Empty method: at the platform-independent level
+		 * we can't know how to write the file.
+		 */
+	}
+	
+	/**
+	 * This will be called by a number of file I/O methods when
+	 * ordinary file I/O fails; it is intended for implementations
+	 * to override it if they wish to return a stream pointing to
+	 * JAR-packed files, remote network locations, etc.
+	 * <p>
+	 * By default it ignores its arguments and returns null.
+	 * <p>
+	 * Overriding is optional; ordinary file I/O will still be
+	 * tried before calling this method.
+	 * 
+	 * @param filename File to be opened
+	 * @return InputStream if it could be opened, or null if not.
+	 */
+	public InputStream getResourceStream(String filename) {
+		return null;
+	}
+	
+}

Added: trunk/java/dasher/CDasherModel.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CDasherModel.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,2030 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.LinkedList;
+import java.util.ArrayList;
+
+/**
+ * Dasher 'world' data structures and dynamics.
+ * <p>
+ * The DasherModel represents the current state of Dasher.
+ * It contains a tree of DasherNodes, knows the current viewpoint
+ * and knows how to evolve the viewpoint.
+ * <p>
+ * It also plays host to the LanguageModel, being responsible
+ * for its creation and passing some requests to it from external
+ * components.
+ * <p>
+ * The Model does not know how to draw Dasher; this is the responsibility
+ * of a DasherView.
+ */
+public class CDasherModel extends CDasherComponent {
+
+	/**
+	 * Are the current model's predictions dependent on
+	 * our context?
+	 * <p>
+	 * In reality almost all models are context sensitive.
+	 */
+	public boolean m_bContextSensitive;
+	// public String m_strContextBuffer;
+	
+	/* Removed, believed redundant. See the comments at the top of
+	 * CDasherInterfaceBase.
+	 */
+	
+	/**
+	 * The Interface to which this Model belongs.
+	 */
+	public CDasherInterfaceBase m_DasherInterface;
+	
+/////////////////////////////////////////////////////////////////////////////
+	
+	// Interfaces
+	
+	/**
+	 * LanguageModel used by this Model for prediction.
+	 */
+	protected CLanguageModel m_LanguageModel;     // pointer to the language model
+	
+	/**
+	 * Alphabet used by this Model 
+	 */
+	protected CAlphabet m_cAlphabet;        // pointer to the alphabet
+	
+	/**
+	 * Our current prediction context.
+	 */
+	protected CContextBase LearnContext; // Used to add data to model as it is entered
+	
+/////////////////////////////////////////////////////////////////////////////
+	
+//	protected CDasherGameMode m_GameMode;
+	
+	/**
+	 * Node which is currently root of the Node tree.
+	 */
+	protected CDasherNode m_Root;
+	
+	/**
+	 * List of previous roots, to which we may revert if the
+	 * user backs off sufficiently.
+	 */
+	protected LinkedList<CDasherNode> oldroots = new LinkedList<CDasherNode>();
+	
+	/**
+	 * Root node's lower bound in Dasher world co-ordinates
+	 */	
+	protected long m_Rootmin;
+	
+	/**
+	 * Root node's upper bound in Dasher world co-ordinates
+	 */
+	protected long m_Rootmax;
+	
+	/**
+	 * Next lower bound which NewGoto will make the lower edge
+	 * of the viewport on its next call.
+	 */
+	protected long m_iTargetMin;
+	
+	/**
+	 * Next upper bound which NewGoto will make the upper edge
+	 * of the viewport on its next call.
+	 */
+	protected long m_iTargetMax;
+	
+	/**
+	 * Minimum allowable value of m_Rootmin
+	 */
+	protected long m_Rootmin_min;
+	
+	/**
+	 * Maximum allowable value of m_Rootmax
+	 */
+	protected long m_Rootmax_max;
+	
+	/**
+	 * Framerate tracker
+	 */
+	protected CFrameRate m_fr;              // keep track of framerate
+	
+	/**
+	 * Record of 'amount of information' entered so far, for logging purposes.
+	 */
+	protected double total_nats;            // Information entered so far
+	
+	/**
+	 * The probability that gets added to every symbol
+	 */ 
+	protected double m_dMaxRate;
+	
+	/**
+	 * Number of interpolated steps to use in Click Mode.
+	 * 
+	 * @see CClickFilter
+	 */
+	protected int m_Stepnum;
+	
+	/**
+	 * Our alphabet manager, for functions which require knowledge
+	 * of an Alphabet.
+	 */
+	protected CAlphabetManagerFactory m_AlphabetManagerFactory;
+	// protected CControlManagerFactory m_ControlManagerFactory;
+
+	/* CSFS: Converted a struct in the original C into this class */
+	
+	/**
+	 * List of points which we are to go to before responding
+	 * to user input again. 
+	 */
+	protected LinkedList<SGotoItem> m_deGotoQueue = new LinkedList<SGotoItem>();
+	
+	/**
+	 * Amount to add to all symbols' probabilities, in order to
+	 * avoid a zero probability.
+	 */
+	protected int uniformAdd;
+	
+	/**
+	 * Probability assinged to the Control Node
+	 */
+	protected long ControlSpace;
+	
+	// Both of these are to save repeated calculations of the same answers. Their
+	// values are calculated when the model is created and are recalculated
+	// in response to any dependent parameter changes.
+	
+	/**
+	 * Simple struct recording a point to which we are scheduled
+	 * to zoom.
+	 */
+	class SGotoItem {
+		/**
+		 * Co-ordinate 1
+		 */
+		public long iN1;
+		/**
+		 * Co-ordinate 2
+		 */
+		public long iN2;
+		/**
+		 * 2 if this is the last point in a sequence, 1 if not.
+		 */
+		public int iStyle;
+	}
+	
+	/**
+	 * Helper class to assist in training of the language model.
+	 * 
+	 */
+	class CTrainer {
+		/**
+		 * Context which we are extending in the training process
+		 */
+		protected CContextBase m_Context;
+		
+		/**
+		 * Model which we are training
+		 */
+	    protected CDasherModel m_DasherModel;
+	    
+	    /**
+	     * Sole constructor. Produces a Trainer with an empty
+	     * context which is ready to train. 
+	     * 
+	     * @param DasherModel Model whose LanguageModel we are training. Must not be null.
+	     */
+	    public CTrainer(CDasherModel DasherModel) {
+	    	m_DasherModel = DasherModel;
+	    	m_Context = m_DasherModel.m_LanguageModel.CreateEmptyContext();
+	    }
+	    
+	   	/**
+	   	 * Trains this trainer's associated language model according
+	   	 * to the symbols specified. Note that these are not character codes
+	   	 * but integer symbol indices; these may be obtained by passing characters
+	   	 * to the relevant Alphabet's GetSymbols method.
+	   	 * 
+	   	 * @param vSymbols Symbols to teach the model.
+	   	 */    
+	    public void Train(ArrayList<Integer> vSymbols) {
+	    	
+	    	for(int i : vSymbols)
+	    		m_DasherModel.m_LanguageModel.LearnSymbol(m_Context, i);
+	    }
+	    
+	    /* CSFS: IMPORTANT DESTRUCTOR. The only place where this ever gets
+	     * called is in CInterfaceBase, which contains one "delete pTrainer"
+	     * statement. This must call this method first.
+	     */
+	    
+	    /**
+	     * Destroys our context; this should only be called when
+	     * the language model is of no further use.
+	     */
+	    public void DeleteTrainer() {
+	    	m_DasherModel.m_LanguageModel.ReleaseContext(m_Context);
+	    }
+
+	}
+	
+	/**
+	 * Initialise a new DasherModel. This consists of:
+	 * <p><ul>
+	 * <li>Retrieving an AlphInfo object describing the user's chosen alphabet
+	 * (ie. which corresponds to SP_ALPHABET_ID)
+	 * <li>Setting global parameters which reflect information about this alphabet
+	 * (eg. SP_TRAIN_FILE)
+	 * <li>Creating a new CAlphabet which describes this alphabet, by calling
+	 * its constructor which takes an AlphInfo
+	 * <li>Creating a CSymbolAlphabet which wraps this Alphabet
+	 * <li>Creating the LanguageModel described by LP_LANGUAGE_MODEL_ID
+	 * <li>Initialising this LanguageModel with a blank context.
+	 * </ul><p>
+	 * This does not train the newly created language model;
+	 * this must be requested from outside, typically by the
+	 * Interface.
+	 * 
+	 * @param EventHandler Event handler with which to register ourselves
+	 * @param SettingsStore Settings repository
+	 * @param DashIface Interface which we serve
+	 * @param AlphIO AlphIO object from which to retrieve the AlphInfo object describing the user's chosen alphabet
+	 */
+	public CDasherModel(CEventHandler EventHandler, CSettingsStore SettingsStore, CDasherInterfaceBase DashIface, CAlphIO AlphIO) {
+	super(EventHandler, SettingsStore); 
+	m_DasherInterface = DashIface;
+	
+	// Set max bitrate in the FrameRate class
+	m_dMaxRate = GetLongParameter(Elp_parameters.LP_MAX_BITRATE) / 100.0;
+	
+	m_fr = new CFrameRate();
+	m_fr.SetMaxBitrate(m_dMaxRate);
+	
+	// Convert the full alphabet to a symbolic representation for use in the language model
+	
+	// -- put all this in a separate method
+	// TODO: Think about having 'prefered' values here, which get
+	// retrieved by DasherInterfaceBase and used to set parameters
+	
+	// TODO: We might get a different alphabet to the one we asked for -
+	// if this is the case then the parameter value should be updated,
+	// but not in such a way that it causes everything to be rebuilt.
+	
+	CAlphIO.AlphInfo oAlphInfo = AlphIO.GetInfo(GetStringParameter(Esp_parameters.SP_ALPHABET_ID));
+	m_cAlphabet = new CAlphabet(oAlphInfo);
+	
+	SetStringParameter(Esp_parameters.SP_TRAIN_FILE, m_cAlphabet.GetTrainingFile());
+	SetStringParameter(Esp_parameters.SP_DEFAULT_COLOUR_ID, m_cAlphabet.GetPalette());
+	
+	if(GetLongParameter(Elp_parameters.LP_ORIENTATION) == Opts.AlphabetDefault)
+		SetLongParameter(Elp_parameters.LP_REAL_ORIENTATION, m_cAlphabet.GetOrientation());
+	// --
+		
+	CSymbolAlphabet alphabet = new CSymbolAlphabet(m_cAlphabet.GetNumberTextSymbols());
+	alphabet.SetSpaceSymbol(m_cAlphabet.GetSpaceSymbol());      // FIXME - is this right, or do we have to do some kind of translation?
+	alphabet.SetAlphabetPointer(m_cAlphabet);    // Horrible hack, but ignore for now.
+	
+	// Create an appropriate language model;
+	
+	switch ((int)GetLongParameter(Elp_parameters.LP_LANGUAGE_MODEL_ID)) {
+	case 0:
+		m_LanguageModel = new CPPMLanguageModel(m_EventHandler, m_SettingsStore, alphabet);
+		SetBoolParameter(Ebp_parameters.BP_LM_REMOTE, false);
+		break;
+	/* case 2:
+		m_pLanguageModel = new CWordLanguageModel(m_pEventHandler, m_pSettingsStore, alphabet);
+		break;
+	case 3:
+		m_pLanguageModel = new CMixtureLanguageModel(m_pEventHandler, m_pSettingsStore, alphabet);
+		break;  
+		#ifdef JAPANESE
+	case 4:
+		m_pLanguageModel = new CJapaneseLanguageModel(m_pEventHandler, m_pSettingsStore, alphabet);
+		break;
+		#endif */
+		
+	case 5:
+		m_LanguageModel = new CRemotePPM(m_EventHandler, m_SettingsStore, alphabet);
+		SetBoolParameter(Ebp_parameters.BP_LM_REMOTE, true);
+	
+		break;
+	/* CSFS: Commented out the other language models for the time being as they are not
+	 * implemented yet.
+	 */
+		
+	default:
+		// If there is a bogus value for the language model ID, we'll default
+		// to our trusty old PPM language model.
+		m_LanguageModel = new CPPMLanguageModel(m_EventHandler, m_SettingsStore, alphabet);    
+		break;
+	}
+	
+	LearnContext = m_LanguageModel.CreateEmptyContext();
+	
+	int iNormalization = (int)GetLongParameter(Elp_parameters.LP_NORMALIZATION);
+	
+	/* CSFS: These used to be int64_max and int64_min.
+	 * As far as I can determine from the internet,
+	 * these are signed types like long.
+	 */
+	
+	m_Rootmin_min = Long.MIN_VALUE / iNormalization / 2;
+	m_Rootmax_max = Long.MAX_VALUE / iNormalization / 2;
+	
+	m_AlphabetManagerFactory = new CAlphabetManagerFactory(this, m_LanguageModel);
+	// m_ControlManagerFactory = new CControlManagerFactory(this, m_LanguageModel);
+	
+	m_bContextSensitive = true;
+	
+	uniformAdd = getUniformAdd((int)GetLongParameter(Elp_parameters.LP_NORMALIZATION));
+	
+	ControlSpace = getControlSpace((int)GetLongParameter(Elp_parameters.LP_NORMALIZATION));
+	
+	}
+	
+	/**
+	 * The Model responds to the following events:
+	 * <p>
+	 * <i>LP_MAX_BITRATE</i>: Informs the CFrameRate which performs
+	 * frame rate tracking for us of the new frame rate.
+	 * <p>
+	 * <i>BP_CONTROL_MODE</i>: Rebuilds the model (calls RebuildAroundNode) to include/exclude a control node.
+	 * <p>
+	 * <i>BP_DELAY_VIEW</i>: Sets the TargetMax to match RootMax and similarly RootMin.
+	 * <p>
+	 * <i>LP_UNIFORM</i>: Updates our internally cached value (uniformAdd)
+	 * to reflect the new value. 
+	 */	
+	public void HandleEvent(CEvent Event) {
+		
+		if(Event.m_iEventType == 1) {
+			CParameterNotificationEvent Evt = (CParameterNotificationEvent)(Event);
+			
+			if(Evt.m_iParameter == Elp_parameters.LP_MAX_BITRATE
+					|| Evt.m_iParameter == Elp_parameters.LP_BOOSTFACTOR
+					|| Evt.m_iParameter == Elp_parameters.LP_SPEED_DIVISOR) {
+				m_dMaxRate = GetLongParameter(Elp_parameters.LP_MAX_BITRATE) * GetLongParameter(Elp_parameters.LP_BOOSTFACTOR) / 100 / (double)(GetLongParameter(Elp_parameters.LP_SPEED_DIVISOR));
+				m_fr.SetMaxBitrate(m_dMaxRate);
+			}
+			else if(Evt.m_iParameter == Ebp_parameters.BP_CONTROL_MODE) { // Rebuild the model if control mode is switched on/off
+				RebuildAroundNode(Get_node_under_crosshair());
+				uniformAdd = getUniformAdd((int)GetLongParameter(Elp_parameters.LP_NORMALIZATION));
+				ControlSpace = getControlSpace((int)GetLongParameter(Elp_parameters.LP_NORMALIZATION));
+			}
+			else if(Evt.m_iParameter == Ebp_parameters.BP_DELAY_VIEW) {
+				MatchTarget();
+			}
+			else if(Evt.m_iParameter == Elp_parameters.LP_UNIFORM) {
+				uniformAdd = getUniformAdd((int)GetLongParameter(Elp_parameters.LP_NORMALIZATION));
+			}
+			
+		}
+		
+	}
+	
+	/**
+	 * Makes a specified child the new root node, deleting all of its siblings
+	 * (by virtue of instructing its parent, the current root, to DeleteNephews.
+	 * <p>
+	 * This function does not make any checks that the specified
+	 * Node really is a child of the current root, or that we are
+	 * in a sensible position to redefine the root; the behaviour
+	 * if this is not ensured before calling is undefined.
+	 * <p>
+	 * The former root node will be added to oldroots, in case
+	 * we need to recover it in future.
+	 * <p>
+	 * m_RootMax, m_TargetMax and their brethren are also updated
+	 * to take into account the new root's Hbnd and Lbnd values.
+	 * <p>
+	 * Due to this function's lack of checks made on the validity
+	 * of the requested operation, it is recommended to use
+	 * RecursiveMakeRoot instead where possible.
+	 * 
+	 * @param whichchild Child to make the new root node.
+	 */
+	protected void Make_root(CDasherNode whichchild)
+	//	find a new root node 
+	{
+		// TODO - support for this in alphabet manager
+		int t = m_Root.Symbol();
+		
+		/* CSFS: This structure is somewhat confusing. It seems to choose to
+		 * learn if the symbol is in range, but doesn't actually seem to bother
+		 * about any adaptive setting. 
+		 */
+		
+		if(t < (m_DasherInterface.GetAlphabet().GetNumberTextSymbols())) {
+			// Only learn if we have adaptive behaviour enabled
+			// This was m_bAdaptive, which should be a setting for all dasher?
+			m_LanguageModel.LearnSymbol(LearnContext, t);
+		}
+		
+		m_Root.DeleteNephews(whichchild);
+		
+		oldroots.addLast(m_Root);
+		
+		m_Root = whichchild;
+		
+		// Commented out so that network mode doesn't encounter problems
+		// when backing off to the point that we need to call PopulateChildrenWithSymbol.
+		// This method was not tolerant of the asynchronous behaviour necessitated
+		// when we might have significant delay.
+		
+		while(oldroots.size() > 10) {
+			
+			/* CSFS: All rewritten to use LinkedList commands instead
+			 * of deque operations. In the original version, it deleted
+			 * the node which was about to get pop_front'd; hopefully
+			 * this will run the destructor and cause the garbage collector
+			 * to come get it.
+			 */
+			
+			oldroots.get(0).OrphanChild(oldroots.get(1));
+			oldroots.get(0).DeleteNode();
+			// oldroots.set(0, null);
+			oldroots.removeFirst();
+		}
+		
+		/* CSFS: These formerly used myint and have been changed to long */
+		
+		long range = m_Rootmax - m_Rootmin;
+		m_Rootmax = m_Rootmin + (range * m_Root.Hbnd()) / (int)GetLongParameter(Elp_parameters.LP_NORMALIZATION);
+		m_Rootmin = m_Rootmin + (range * m_Root.Lbnd()) / (int)GetLongParameter(Elp_parameters.LP_NORMALIZATION);
+		
+		long iTargetRange = m_iTargetMax - m_iTargetMin;
+		m_iTargetMax = m_iTargetMin + (iTargetRange * m_Root.Hbnd()) / (int)GetLongParameter(Elp_parameters.LP_NORMALIZATION);
+		m_iTargetMin = m_iTargetMin + (iTargetRange * m_Root.Lbnd()) / (int)GetLongParameter(Elp_parameters.LP_NORMALIZATION);
+	}
+	
+	/**
+	 * Forget about the queue of old root nodes.
+	 * <p>
+	 * This should be called when the previous context is no
+	 * longer valid. 
+	 *
+	 */
+	protected void ClearRootQueue() {
+		while(oldroots.size() > 0) {
+			if(oldroots.size() > 1) {
+				oldroots.get(0).OrphanChild(oldroots.get(1));
+			}
+			else {
+				oldroots.get(0).OrphanChild(m_Root);
+			}
+			
+			/* CSFS: Again, this originally would delete oldroots[0] before
+			 * pop_front'ing the deque.
+			 */
+			
+			oldroots.get(0).DeleteNode();
+			oldroots.set(0, null);
+			oldroots.removeFirst();
+		}
+	}
+
+	/**
+	 * Calls Make_root repeatedly to make a specified node the new root node.
+	 * <p>
+	 * This function must be called on some descendent of the current root.
+	 * <p>
+	 * Behaviour if called upon a node which is not is undefined;
+	 * most likely it would eventually run into a node whose parent
+	 * has been deleted, and fail with a NullPointerException.
+	 * 
+	 * @param NewRoot Node to make the root.
+	 */
+	protected void RecursiveMakeRoot(CDasherNode NewRoot) {
+		if(NewRoot == null)
+			return;
+		
+		if(NewRoot == m_Root)
+			return;
+		
+		// FIXME - we really ought to check that pNewRoot is actually a
+		// descendent of the root, although that should be guaranteed
+		
+		if(!NewRoot.NodeIsParent(m_Root))
+			RecursiveMakeRoot(NewRoot.Parent());
+		
+		Make_root(NewRoot);
+	}
+	
+	/**
+	 * Makes a given Node the root, and then deletes and rebuilds
+	 * its children.
+	 * <p>
+	 * This is intended for situations when an existing Node has
+	 * children which are no longer correct; for instance, if
+	 * Control Mode has been switched on necessitating a new child
+	 * Node, or if the language model has been changed.
+	 * <p>
+	 * The specified Node must be a descendent of the existing
+	 * root, or RecursiveMakeRoot will fail to find a link
+	 * between the two.
+	 * 
+	 * @param Node New root node after the rebuild.
+	 */
+	protected void RebuildAroundNode(CDasherNode Node) {
+		RecursiveMakeRoot(Node);
+		ClearRootQueue();
+		Node.Delete_children();
+		Node.m_NodeManager.PopulateChildren(Node);
+	}
+
+	/**
+	 * Reconstructs the existing root's parent, so that we can
+	 * back out of it.
+	 * <p>
+	 * This will first try to use an old Node stored in the oldroots
+	 * list, but if this is empty will use the AlphabetManager's
+	 * RebuildParent method to instantiate a new parent.
+	 * <p>
+	 * If unsuccessful in building a parent, or if the current
+	 * root is the base node in which Dasher starts, the method
+	 * will return without performing any action.
+	 * <p>
+	 * m_RootMax, m_TargetMax and their brethren will also be
+	 * appropriately updated.
+	 * 
+	 * @param lower Current root's Lbnd
+	 * @param upper Current root's Hbnd
+	 */
+	protected void Reparent_root(long lower, long upper) {
+		
+		/* Change the root node to the parent of the existing node
+		 We need to recalculate the coordinates for the "new" root as the 
+		 user may have moved around within the current root */
+		
+		if(m_Root.Symbol() == 0)
+			return; // Don't try to reparent the root symbol
+		
+		
+		CDasherNode NewRoot;
+		
+		if(oldroots.size() == 0) {
+			
+			/* If our internal buffer of old roots is exhausted, */
+			
+			CDasherNode CurrentNode = (Get_node_under_crosshair());
+			int iGenerations = 0;
+			
+			while(CurrentNode != m_Root) {
+				++iGenerations;
+				CurrentNode = CurrentNode.Parent();
+			}
+			
+			NewRoot = m_Root.m_NodeManager.RebuildParent(m_Root, iGenerations);
+			
+			lower = m_Root.Lbnd();
+			upper = m_Root.Hbnd();
+			
+		}
+		else {
+			
+			/* CSFS: Translated from .back() and .pop_back() */
+			
+			NewRoot = oldroots.getLast();
+			oldroots.removeLast();
+		}
+		
+		// Return if there's no existing parent and no way of recreating one
+		
+		if(NewRoot == null) { 
+			return;
+		}
+		
+		/* Determine how zoomed in we are */
+		
+		/* CSFS: Used to be myints */
+		
+		long iRootWidth = m_Rootmax - m_Rootmin;
+		long iTargetWidth = m_iTargetMax - m_iTargetMin;
+		long iWidth = upper - lower;
+	
+		m_Root = NewRoot;
+		
+		m_Rootmax = m_Rootmax + (((GetLongParameter(Elp_parameters.LP_NORMALIZATION) - upper)) * iRootWidth / iWidth);
+		
+		m_Rootmin = m_Rootmin - ((lower) * iRootWidth / iWidth);
+		
+		m_iTargetMax = m_iTargetMax + (((GetLongParameter(Elp_parameters.LP_NORMALIZATION) - upper)) * iTargetWidth / iWidth);
+		m_iTargetMin = m_iTargetMin - ((lower) * iTargetWidth / iWidth);
+		
+		
+	}
+
+	protected CDasherNode Get_node_under_crosshair() {
+		if(GetBoolParameter(Ebp_parameters.BP_DELAY_VIEW))
+			return m_Root.Get_node_under(GetLongParameter(Elp_parameters.LP_NORMALIZATION), m_iTargetMin, m_iTargetMax, GetLongParameter(Elp_parameters.LP_OX), GetLongParameter(Elp_parameters.LP_OY));
+			else
+				return m_Root.Get_node_under(GetLongParameter(Elp_parameters.LP_NORMALIZATION), m_Rootmin, m_Rootmax, GetLongParameter(Elp_parameters.LP_OX), GetLongParameter(Elp_parameters.LP_OY));
+	}
+	
+
+	/**
+	 * Gets the node under the current mouse position.
+	 * 
+	 * @param Mousex Current mouse x co-ordinate
+	 * @param Mousey Current mouse y co-ordinate
+	 * @return Reference to Node under mouse
+	 */
+	protected CDasherNode Get_node_under_mouse(long Mousex, long Mousey) {
+		if(GetBoolParameter(Ebp_parameters.BP_DELAY_VIEW))
+			return m_Root.Get_node_under(GetLongParameter(Elp_parameters.LP_NORMALIZATION), m_iTargetMin, m_iTargetMax, Mousex, Mousey);
+			else
+				return m_Root.Get_node_under(GetLongParameter(Elp_parameters.LP_NORMALIZATION), m_Rootmin, m_Rootmax, Mousex, Mousey);
+	}
+	
+/////////////////////////////////////////////////////////////////////////////
+	
+	/*public void Get_string_under_mouse(long Mousex, long Mousey, ArrayList<Integer> str) {
+		if(GetBoolParameter(Ebp_parameters.BP_DELAY_VIEW))
+			m_Root.Get_string_under(GetLongParameter(Elp_parameters.LP_NORMALIZATION), m_iTargetMin, m_iTargetMax, Mousex, Mousey, str);
+		else
+			m_Root.Get_string_under(GetLongParameter(Elp_parameters.LP_NORMALIZATION), m_Rootmin, m_Rootmax, Mousex, Mousey, str);
+	}*/
+	
+	// Redundant method.
+	
+/////////////////////////////////////////////////////////////////////////////
+	
+	/**
+	 * Sets a blank context. This method could use some work;
+	 * it looks as if it tries to request any known context
+	 * from the UI using an EditContextEvent, but this doesn't
+	 * work at present.
+	 * <p>
+	 * This ought not to matter as SetContext fulfils this purpose
+	 * with a given context, and so can duplicate the function
+	 * of Start by passing it the empty string.
+	 */
+	public void Start() {
+		
+		// FIXME - re-evaluate this function and SetContext...
+		
+		String strNewContext = "";
+		
+		SetContext(strNewContext);    // FIXME - REALLY REALLY broken!
+		
+		CEditContextEvent oEvent = new CEditContextEvent(5);
+		
+		InsertEvent(oEvent);
+		
+		// FIXME - what if we don't get a reply?
+		
+	}
+	
+	/**
+	 * Forces the current context to a given value, and resets
+	 * our position in the Dasher world based upon it.
+	 * <p>
+	 * If the given context is empty, the context is actually set
+	 * to ". " so that the prediction is the same as for the 
+	 * beginning of a new sentence.
+	 * <p>
+	 * Internally, this works by requesting a new Root node from
+	 * the Alphabet Manager, creating a blank context, and training
+	 * it using the supplied String.
+	 * <p>
+	 * This method also has the following side-effects:
+	 * <p>
+	 * <ul><li>Any zoom scheduled using ScheduleZoom will be cancelled.
+	 * <li>Our current LearnContext will be released.
+	 * <li>m_RootMax, m_TargetMax and their brethren will be altered
+	 * to reflect the changes.
+	 * 
+	 * @param sNewContext Context to set
+	 */
+	public void SetContext(String sNewContext) {
+		
+		m_deGotoQueue.clear();
+		
+		/* If a zoom was in progress, cancel it -- this function will likely change
+		 * our location within the Dasher world, and so the target being aimed for
+		 * is likely not to be there anymore.
+		 */
+		
+		if(oldroots.size() > 0) {
+			oldroots.get(0).DeleteNode();
+			oldroots.clear();
+			// At this point we have also deleted the root - so better NULL pointer
+		}
+		
+		/* CSFS: BUGFIX: Didn't used to check the root really exists before deleting it */
+		
+		if(m_Root != null) {
+			m_Root.DeleteNode();
+		}
+		m_Root = null;
+			
+		CContextBase therootcontext = m_LanguageModel.CreateEmptyContext();
+		
+		if(sNewContext.length() == 0) {
+			m_Root = m_AlphabetManagerFactory.GetRoot(null, 0,(int)GetLongParameter(Elp_parameters.LP_NORMALIZATION), 0);
+			EnterText(therootcontext, ". ");  
+		}
+		else {
+			ArrayList<Integer> vSymbols = new ArrayList<Integer>();
+			m_LanguageModel.SymbolAlphabet().GetAlphabetPointer().GetSymbols(vSymbols, sNewContext, false);
+
+			int iRootSymbol = (vSymbols.get(vSymbols.size()-1));
+			
+			m_Root = m_AlphabetManagerFactory.GetRoot(null, 0,(int)GetLongParameter(Elp_parameters.LP_NORMALIZATION), iRootSymbol);
+			
+			/* CSFS: This used to pass in the address of iRootSymbol; however, this only
+			 * led to the void pointer called "UserData" found in CAlphabetManager which
+			 * doesn't appear to ever do anything but dereference as an int and use read-only,
+			 * so this shouldn't cause problems.
+			 */
+			
+			EnterText(therootcontext, sNewContext);  
+		}
+		
+		m_LanguageModel.ReleaseContext(LearnContext);
+		LearnContext = m_LanguageModel.CloneContext(therootcontext);
+		
+		m_Root.SetContext(therootcontext);   // node takes control of the context
+		Recursive_Push_Node(m_Root, 0);
+		
+		double dFraction = ( 1 - (1 - m_Root.MostProbableChild() / (double)(GetLongParameter(Elp_parameters.LP_NORMALIZATION))) / 2.0 );
+		
+		int iWidth = ( (int)( (GetLongParameter(Elp_parameters.LP_MAX_Y) / (2.0*dFraction)) ) );
+		
+		m_Rootmin = GetLongParameter(Elp_parameters.LP_MAX_Y) / 2 - iWidth / 2;
+		m_Rootmax = GetLongParameter(Elp_parameters.LP_MAX_Y) / 2 + iWidth / 2;
+		
+		m_iTargetMin = m_Rootmin;
+		m_iTargetMax = m_Rootmax;
+	}
+	
+	/**
+	 * Simple struct for returning min/max pairs.
+	 */
+	class GNRCReturn {
+		/**
+		 * New max
+		 */
+		long iNewMin;
+		/**
+		 * New min
+		 */
+		long iNewMax;
+	}
+	
+	/**
+	 * Calculate the new co-ordinates for the root node after a single
+	 * update step. For further information, see Doc/geometry.tex.
+	 * 
+	 * @param Mousex x mouse co-ordinate measured right to left.
+     * @param Mousey y mouse co-ordinate measured top to bottom.
+     * @return New root co-ordinates.
+	
+	 */
+	protected GNRCReturn Get_new_root_coords(long Mousex, long Mousey) {
+	  // Comments refer to the code immedialtely before them
+
+	  if(Mousex <= 0) {
+	    Mousex = 1;
+	  }
+
+	  // Avoid Mousex=0, as this corresponds to infinite zoom
+
+	  // If Mousex is too large we risk overflow errors, so make limit it
+	  // (this is a somewhat empirical limit - at some point we should
+	  // probably do it a little more scientifically)
+
+	  if(Mousex > 60000000)
+	    Mousex = 60000000;
+
+	  // Cache some results so we don't do a huge number of parameter lookups
+
+	  long iMaxY = (GetLongParameter(Elp_parameters.LP_MAX_Y));
+	  long iOX = (GetLongParameter(Elp_parameters.LP_OX));
+	  long iOY = (GetLongParameter(Elp_parameters.LP_OY));
+
+	  /* CSFS: In the original C++ iTargetMin and iTargetMax were, apparently
+	   * intentionally, ints and not longs. I've changed this since it seems they may
+	   * be liable to overflow if simply assigned the values given.
+	   */
+	  
+	  long iTargetMin = (Mousey - (iMaxY * Mousex) / (2 * iOX));
+	  long iTargetMax = (Mousey + (iMaxY * Mousex) / (2 * iOY));
+
+	  // Calculate what the extremes of the viewport will be when the
+	  // point under the cursor is at the cross-hair. This is where 
+	  // we want to be in iSteps updates
+
+	  int iSteps = m_fr.Steps();
+
+	  assert(iSteps > 0);
+
+	  // iSteps is the number of update steps we need to get the point
+	  // under the cursor over to the cross hair. Calculated in order to
+	  // keep a constant bit-rate.
+
+	  
+	  long iNewTargetMin = (iTargetMin * iMaxY / (iMaxY + (iSteps - 1) * (iTargetMax - iTargetMin)));
+
+	  long iNewTargetMax = ((iTargetMax * iSteps - iTargetMin * (iSteps - 1)) * iMaxY) / (iMaxY + (iSteps - 1) * (iTargetMax - iTargetMin));
+
+	  iTargetMin = iNewTargetMin;
+	  iTargetMax = iNewTargetMax;
+
+	  // Calculate the new values of iTargetMin and iTargetMax required to
+	  // perform a single update step. Note that the slightly awkward
+	  // expressions are in order to reproduce the behaviour of the old
+	  // algorithm
+
+	  long iMinSize = (m_fr.MinSize(iMaxY));
+
+	  // Calculate the minimum size of the viewport corresponding to the
+	  // maximum zoom.
+
+	  if((iTargetMax - iTargetMin) < iMinSize) {
+	    iNewTargetMin = iTargetMin * (iMaxY - iMinSize) / (iMaxY - (iTargetMax - iTargetMin));
+	    iNewTargetMax = iNewTargetMin + iMinSize;
+
+	    iTargetMin = iNewTargetMin;
+	    iTargetMax = iNewTargetMax;
+	  }
+
+	  GNRCReturn retval = new GNRCReturn();
+	  
+	  retval.iNewMin = (((m_Rootmin - iTargetMin) * GetLongParameter(Elp_parameters.LP_MAX_Y)) / (iTargetMax - iTargetMin));
+	  retval.iNewMax = (((m_Rootmax - iTargetMax) * GetLongParameter(Elp_parameters.LP_MAX_Y)) / (iTargetMax - iTargetMin) + GetLongParameter(Elp_parameters.LP_MAX_Y));
+	  return retval;
+	}
+	
+	/**
+	 * Performs a single update of the model based on a given
+	 * mouse position and the time elpased since the last
+	 * update took place.
+	 * <p>
+	 * If BP_OLD_STYLE_PUSH is enabled, prompts the creation
+	 * of new segments of tree where appropriate, using
+	 * OldPush. If not, we let node pushing take place elsewhere.
+	 * <p>
+	 * In the case that the m_deGotoQueue contains any points,
+	 * indicating that a pre-scheduled zoom is currently in
+	 * progress, we move to the next specified point in the queue
+	 * instead and ignore the mouse position.
+	 * <p>
+	 * Internally, this method uses Get_new_root_coords to work
+	 * out where to go, and NewGoto to actually go there.
+	 * <p>
+	 * If this method is called whilst Dasher is paused, it
+	 * will do nothing and return false.
+	 * 
+	 * @param miMousex Current mouse X co-ordinate
+	 * @param miMousey Current mouse Y co-ordinate
+	 * @param Time Current system time as a UNIX timestamp
+	 * @param pAdded Ignored parameter
+	 * @return True if we have updated the model, false otherwise.
+	 */
+	public boolean Tap_on_display(long miMousex,
+			long miMousey, 
+			long Time, 
+			ArrayList<CSymbolProb> pAdded)	{
+
+		/* CSFS: There used to be an extra parameter here called pNumDeleted
+		 * which was an int * which looked as if it was intended to return the
+		 * number of deleted nodes to the calling routine; however, every
+		 * call in the current source-code supplies a null pointer, so rather
+		 * than work on actually returning NumDeleted I've removed the parameter.
+		 */
+		
+		//		TODO: Reimplement this 
+//		Clear out parameters that might get passed in to track user activity
+		if (pAdded != null)	pAdded.clear();
+			
+		if(GetBoolParameter(Ebp_parameters.BP_DASHER_PAUSED) && (m_deGotoQueue.size() == 0))
+			return false;
+		
+		long iNewMin;
+		long iNewMax;
+		
+		if(m_deGotoQueue.size() == 0) {
+//			works out next viewpoint
+			
+			/* CSFS: Modified as detailed above to use the new minature
+			 * return type to get data out of the function.
+			 */
+			
+			GNRCReturn retval = Get_new_root_coords(miMousex, miMousey);
+			iNewMin = retval.iNewMin; iNewMax = retval.iNewMax;
+			
+			if(GetBoolParameter(Ebp_parameters.BP_OLD_STYLE_PUSH))
+				OldPush(miMousex, miMousey);
+		}
+		else {
+			iNewMin = m_deGotoQueue.getFirst().iN1;
+			iNewMax = m_deGotoQueue.getFirst().iN2;
+			m_deGotoQueue.removeFirst();
+		}
+		
+//		Now actually zoom to the new location
+		NewGoTo(iNewMin, iNewMax);
+		
+		total_nats += -1.0 * java.lang.Math.log((iNewMax - iNewMin) / 4096.0);
+		
+		return true;
+	}
+	
+	/**
+	 * Expands sections of the node tree, using random point
+	 * selection and the Get_node_under method to try to bias
+	 * the process in favour of larger nodes.
+	 * <p>
+	 * Takes account of the current frame rate, and does more
+	 * pushing if Dasher is performing better.
+	 * <p>
+	 * This method is only ever used if BP_OLD_STYLE_PUSH is
+	 * enabled which is not the default.
+	 * <p>
+	 * The actual node pushing is done by Push_Node.
+	 * 
+	 * @param iMousex Current mouse X co-ordinate
+	 * @param iMousey Current mosue Y co-ordinate
+	 */
+	protected void OldPush(long iMousex, long iMousey) {
+//		push node under mouse
+		CDasherNode UnderMouse = Get_node_under_mouse(iMousex, iMousey);
+		
+		/* CSFS: This code originally made liberal use of RandomInt, which on
+		 * most platforms called rand(), which in turn generates a random integer
+		 * between 0 and, on GCC, the largest signed integer. This may however
+		 * vary from platform to platform. This is my attempt to emulate this
+		 * under Java.
+		 */ 
+		
+		Push_Node(UnderMouse);
+		
+		if(Framerate() > 4) {
+//			push node under mouse but with x coord on RHS
+			CDasherNode Right = Get_node_under_mouse(50, iMousey);
+			Push_Node(Right);
+		}
+		
+		if(Framerate() > 8) {
+//			push node under the crosshair
+			CDasherNode UnderCross = Get_node_under_crosshair();
+			Push_Node(UnderCross);
+		}
+		
+		java.util.Random rgen = new java.util.Random();
+		int iRandom = rgen.nextInt(Integer.MAX_VALUE);
+		
+		if(Framerate() > 8) {
+//			add some noise and push another node
+			CDasherNode Right = Get_node_under_mouse(50, iMousey + iRandom % 500 - 250);
+			Push_Node(Right);
+		}
+		
+		iRandom = rgen.nextInt(Integer.MAX_VALUE);
+		
+		if(Framerate() > 15) {
+//			add some noise and push another node
+			CDasherNode Right = Get_node_under_mouse(50, iMousey + iRandom % 500 - 250);
+			Push_Node(Right);
+		}
+		
+//		only do this if Dasher is flying
+		if(Framerate() > 30) {
+			for(int i = 1; i < (Framerate() - 30) / 3; i++) {
+				
+				int iRandom2 = rgen.nextInt(Integer.MAX_VALUE);
+				
+				if(Framerate() > 8) {
+//					add some noise and push another node
+					CDasherNode Right = Get_node_under_mouse(50, iMousey + iRandom2 % 500 - 250);
+					Push_Node(Right);
+				}
+				
+				iRandom = rgen.nextInt(Integer.MAX_VALUE);
+//				push at a random node on the RHS
+				CDasherNode Right = Get_node_under_mouse(50, iMousey + iRandom % 1000 - 500);
+				Push_Node(Right);
+				
+			}
+		}
+	}
+	
+	/**
+	 * Given a Node which is supposed to be the current end of
+	 * output, recursively checks whether the parent's Seen property
+	 * is true (which indicates it has been output if appropriate)
+	 * and invokes the AlphabetManager's Enter and Output methods
+	 * on each unseen ancestor in tree-descending order.
+	 * <p>
+	 * The nodes' Seen flag is also set, preventing repeated
+	 * output of the same nodes.
+	 * 
+	 * @param Node Node to output, possibly including its ancestors
+	 * @param pAdded ArrayList which will be filled with output characters
+	 * for logging purposes.
+	 */
+	protected void RecursiveOutput(CDasherNode Node, ArrayList<CSymbolProb> pAdded) {
+		if(Node.Parent() != null && (!Node.Parent().isSeen())) 
+			RecursiveOutput(Node.Parent(), pAdded);
+		
+		if(Node.Parent() != null) Node.Parent().m_NodeManager.Leave(Node.Parent());
+			
+		Node.m_NodeManager.Enter(Node);
+		
+		Node.Seen(true);
+		Node.m_NodeManager.Output(Node, pAdded, (int)GetLongParameter(Elp_parameters.LP_NORMALIZATION));
+	}
+
+	/*
+	class PNGCReturn {
+		int iSteps;
+		long o1;
+		long o2;
+		long n1;
+		long n2;
+		double originalRetval;
+	}*/
+	
+//	public PNGCReturn Plan_new_goto_coords(int iRxnew, long mousey)
+	
+	/* CSFS: Here we have another class which uses its arguments as output.
+	 * As per usual when it's more than one item, I use a small class to return values.
+	 * The variable names are the same as they were in the old method prototype.
+	 * Potential problem: it's possible they may carry values when submitted to the
+	 * routine which are important; however, looking at it I'm fairly sure they're all
+	 * written before they're read.
+	 */
+	
+/*	{	
+		
+		final int ZOOMDENOM = (1<<10);
+		final int STEPDENOM = 64;
+		PNGCReturn retval = new PNGCReturn(); // create class to return multiple values.
+		
+		m_Stepnum = (int)GetLongParameter(Elp_parameters.LP_ZOOMSTEPS);
+		int iRxnew_dup = iRxnew;
+		// note -- iRxnew is the zoom factor  in units of ZOOMDENOM
+		retval.o1 = m_Rootmin;
+		retval.o2 = m_Rootmax;
+		assert(iRxnew > 0);
+		if (iRxnew < ZOOMDENOM && m_Rootmax< GetLongParameter(Elp_parameters.LP_MAX_Y) && m_Rootmin>0 ) {
+			// refuse to zoom backwards if the entire root node is visible.
+			retval.iSteps = 0 ;
+			retval.n1 = m_Rootmin;
+			retval.n2 = m_Rootmax;
+		} 
+		else {
+			long above=(mousey-retval.o1);
+			long below=(retval.o2-mousey);
+			
+			long miNewrootzoom=GetLongParameter(Elp_parameters.LP_MAX_Y)/2 ;
+			long newRootmax=miNewrootzoom+(below*iRxnew/ZOOMDENOM); // is there a risk of overflow in this multiply?
+			long newRootmin=miNewrootzoom-(above*iRxnew/ZOOMDENOM);
+			
+			retval.n1 = newRootmin;
+			retval.n2 = newRootmax;
+			
+			retval.iSteps = 1;
+			
+			// We might be moving at zoomfactor one vertically, in which case the below invention won't
+			// come up with more than one step.  Look for a mousey difference and use an iSteps concordant
+			// to that if it would be larger than the iSteps created by taking the log of the zoomfactor. 
+			
+			/* CSFS: Changed 'distance' to a long as it didn't seem safe to be casting
+			 * longs to ints and simply hoping they fit.
+			 */
+			
+			/*long distance = mousey - (GetLongParameter(Elp_parameters.LP_MAX_Y)/2);
+			
+			double s = (Math.log(2.0) * 2 / Math.log( (STEPDENOM*1.0)/(m_Stepnum*1.0)) ) / 4096;
+			
+			double alpha = 2 * (2 * s);
+			int alternateSteps = (int)(alpha * Math.abs(distance));
+			
+			// Take log of iRxnew to base ( STEPDENOM / STEPNUM ):
+			if ( STEPDENOM > m_Stepnum && m_Stepnum > 0 ) { // check that the following loop will terminate.
+				//cout << "iRxnew is " << iRxnew << " and ZOOMDENOM is" << ZOOMDENOM << endl;
+				if ( iRxnew > ZOOMDENOM ) {
+					while ( iRxnew > ZOOMDENOM ) {
+						retval.iSteps += 1;
+						iRxnew = iRxnew * m_Stepnum / STEPDENOM;
+					}
+				} else {
+					while ( iRxnew < ZOOMDENOM ) {
+						retval.iSteps += 1;
+						iRxnew = iRxnew * STEPDENOM / m_Stepnum;
+					}
+				}
+			}
+			
+			// Done taking log of iRxnew. 
+			if (alternateSteps > retval.iSteps) {
+				retval.iSteps = alternateSteps;
+			}
+		}
+		
+		double iRxnew_ratio = (double) iRxnew_dup / ZOOMDENOM;
+		double iRxnew_log = Math.log(iRxnew_ratio);
+		retval.originalRetval = iRxnew_log;
+		return retval;
+	}*/
+	
+	/**
+	 * Changes the state of the Model updating the values of
+	 * m_RootMax and m_RootMin, which has the effect of making
+	 * us appear to move around. Also pushes the node we're moving
+	 * into, and cues output handling.
+	 * <p>
+	 * Both values are checked for sanity and truncated if necessary.
+	 * <p>
+	 * m_iTargetMax and Min are also updated according to the
+	 * new values of RootMax/Min.
+	 * <p>
+	 * For the purpose of output handling, the node under the
+	 * crosshair is noted before and after enacting the move,
+	 * and HandleOutput invoked upon this pair.
+	 * <p>
+	 * At present, this function takes no action if the proposed
+	 * new values are not allowable; it returns without making
+	 * any changes which has the effect of causing Dasher to
+	 * freeze.
+	 * 
+	 * @param newRootmin Desired new value of m_RootMin
+	 * @param newRootmax Desired new value of m_RootMax
+	 */
+	protected void NewGoTo(long newRootmin, long newRootmax) {
+		// Find out the current node under the crosshair
+		CDasherNode old_under_cross=Get_node_under_crosshair();
+		
+		// Update the max and min of the root node to make iTargetMin and iTargetMax the edges of the viewport.
+			
+		if(newRootmin > GetLongParameter(Elp_parameters.LP_MAX_Y) / 2 - 1)
+			newRootmin = GetLongParameter(Elp_parameters.LP_MAX_Y) / 2 - 1;
+		
+		if(newRootmax < GetLongParameter(Elp_parameters.LP_MAX_Y) / 2 + 1)
+			newRootmax = GetLongParameter(Elp_parameters.LP_MAX_Y) / 2 + 1;
+		
+		// Check that we haven't drifted too far. The rule is that we're not
+		// allowed to let the root max and min cross the midpoint of the
+		// screen.
+		
+		if(newRootmax < m_Rootmax_max && newRootmin > m_Rootmin_min && (newRootmax - newRootmin) > GetLongParameter(Elp_parameters.LP_MAX_Y) / 4) {
+			// Only update if we're not making things big enough to risk
+			// overflow. In theory we should have reparented the root well
+			// before getting this far.
+			//
+			// Also don't allow the update if it will result in making the
+			// root too small. Again, we should have re-generated a deeper
+			// root in most cases, but the original root is an exception.
+			
+			m_Rootmax = newRootmax;
+			m_Rootmin = newRootmin;
+			
+			/* CSFS: These were implicit casts in the original C. Hopefully
+			 * the semantics are the same.
+			 */
+			
+			m_iTargetMax = (long)(m_iTargetMax + 0.1 * (m_Rootmax - m_iTargetMax));
+			m_iTargetMin = (long)(m_iTargetMin + 0.1 * (m_Rootmin - m_iTargetMin));
+		}
+		else {
+			// TODO - force a new root to be chosen, so that we get better
+			// behaviour than just having Dasher stop at this point.
+		}
+		
+		// push node under crosshair
+		CDasherNode new_under_cross = Get_node_under_crosshair();
+		Push_Node(new_under_cross);
+		
+		HandleOutput(new_under_cross, old_under_cross);
+		
+	}
+	
+	/**
+	 * Handles output based on the nodes which were under the
+	 * crosshair before and after a move.
+	 * <p>
+	 * If the NewNode has its Seen flag already set, returns
+	 * without taking any action.
+	 * <p>
+	 * Internally this works by calling DeleteCharacters on the
+	 * two nodes if they are different, and then RecursiveOutput
+	 * on the current node and null.
+	 * 
+	 * @param NewNode Node now under the crosshair
+	 * @param OldNode Node previously under the crosshair (maybe the same as NewNode)
+	 */
+	protected void HandleOutput(CDasherNode NewNode, CDasherNode OldNode) {
+		if(NewNode != OldNode)
+			DeleteCharacters(NewNode, OldNode);
+		
+		if(NewNode.isSeen())
+			return;
+		
+		// TODO: Reimplement second parameter
+		RecursiveOutput(NewNode, null);
+	}
+	
+	/**
+	 * Traces back from oldnode to either a) newnode, in the case
+	 * that oldnode is a descendent of newnode, or b) to the nearest
+	 * common ancestor (ie. the nearest ancestor of newnode which
+	 * has its seen flag set), calling the AlphabetManager's
+	 * Undo method on each in turn.
+	 * <p>
+	 * In case a) we will now be consistent with the user's current
+	 * location; in case b) we have deleted the text belonging
+	 * to oldnode's branch but not output the text for newnode;
+	 * HandleOutput must be used to finish the job.
+	 * <p>
+	 * If either parameter is null, this method will return false
+	 * and take no action.
+	 * 
+	 * @param newnode Node currently under the crosshair
+	 * @param oldnode Node previously under the crosshair
+	 * @return False if either argument as null, True otherwise.
+	 */
+	protected boolean DeleteCharacters(CDasherNode newnode, CDasherNode oldnode) {
+			
+		/* CSFS: Much like tap_on_screen, this method used to have an int *
+		 * argument named pNumDeleted. However, every call from an external
+		 * method passed in a null argument; only DeleteCharacters itself ever
+		 * made use of it. I'm assuming this is fossilised code and have
+		 * removed the argument.
+		 */
+		
+		if(newnode == null || oldnode == null)
+			return false;
+		
+		// This deals with the trivial instance - we're reversing back over
+		// text that we've seen already
+		if(newnode.isSeen() == true) {
+			if(oldnode.Parent() == newnode) {
+				oldnode.m_NodeManager.Undo(oldnode);
+				oldnode.Parent().m_NodeManager.Enter(oldnode.Parent());
+				oldnode.Seen(false);
+				return true;
+			}
+			if(DeleteCharacters(newnode, oldnode.Parent()) == true) {
+				oldnode.m_NodeManager.Undo(oldnode);
+				oldnode.Parent().m_NodeManager.Enter(oldnode.Parent());
+				oldnode.Seen(false);
+				return true;
+			}
+		}
+		else {
+			// This one's more complicated - the user may have moved onto a new branch
+			// Find the last seen node on the new branch
+			CDasherNode lastseen = newnode.Parent();
+			
+			while(lastseen != null && lastseen.isSeen() == false) {
+				lastseen = lastseen.Parent();
+			}
+			// Delete back to last seen node
+			while(oldnode != lastseen) {
+				
+				oldnode.Seen(false);
+				
+				oldnode.m_NodeManager.Undo(oldnode);
+				oldnode.Parent().m_NodeManager.Enter(oldnode.Parent());
+				oldnode = oldnode.Parent();
+				if(oldnode == null) {
+					return false;
+				}
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Requests node probabilities from the language model given
+	 * a context and a normalization value (usually LP_NORMALIZATION).
+	 * <p>
+	 * Internally, this recalculates the norm value using getNonUniformNorm,
+	 * and passes the context and this new norm onto m_LanguageModel.getProbs.
+	 * <p>
+	 * Once the probabilities are calculated, it runs them
+	 * through adjustProbs before returning.
+	 *  
+	 * @param context Language model context in which the
+	 * probabilities are to be found.
+	 * @param iNorm Normalization
+	 * @return Array of probabilities, in alphabet order.
+	 */
+	public long[] GetProbs(CContextBase context, int iNorm) {
+		
+		/* Lots of refactoring has gone on here. The model used to do three
+		 * things in this function: calculate the non-uniform norm, control
+		 * space and so forth, retrieve the probs, and then perform a little
+		 * post-processing before returning its answer. I have refactored
+		 * these out into three seperate stages. My reason for doing so was
+		 * so that the networking system can call the stages asynchronously,
+		 * but it also helps readability.
+		 */
+		
+		long[] probs = m_LanguageModel.GetProbs(context, getNonUniformNorm(iNorm));
+		
+		adjustProbs(probs);
+		
+		return probs;
+		
+	}
+	
+	/**
+	 * Increments all probabilities by the value of uniformAdd,
+	 * and sets the final probability to ControlSpace.
+	 * 
+	 * @param probs The probabilities to modify
+	 */
+	public void adjustProbs(long[] probs) {
+		
+		for(int k = 1; k < probs.length; ++k) probs[k] += uniformAdd;
+		
+		probs[probs.length - 1] = ControlSpace;
+
+		
+	}
+	
+	/**
+	 * Calculates the non-uniform norm.
+	 * 
+	 * @param iNorm Normalization value, usually LP_NORMALIZATION
+	 * @return Non-uniform norm
+	 */
+	public int getNonUniformNorm(int iNorm) {
+//		 Total number of symbols
+		int iSymbols = m_cAlphabet.GetNumberSymbols();      // note that this includes the control node and the root node
+		
+		//NewSymbols.ensureCapacity(iSymbols);
+		//for(int i = 0; i < iSymbols; i++) {
+		//	NewSymbols.add(i);          // This will be replaced by something that works out valid nodes for this context
+		//}
+		
+		// TODO - sort out size of control node - for the timebeing I'll fix the control node at 5%
+		
+		int uniform_add;
+		long control_space; // CSFS: Changed to long to match the probs.
+		long uniform = GetLongParameter(Elp_parameters.LP_UNIFORM);
+		
+		if(!GetBoolParameter(Ebp_parameters.BP_CONTROL_MODE)) {
+			control_space = 0;
+			uniform_add = (int)((iNorm * uniform) / 1000) / (iSymbols - 2);  // Subtract 2 from no symbols to lose control/root nodes
+			return iNorm - (iSymbols - 2) * uniform_add;
+		}
+		else {
+			control_space = (long)(iNorm * 0.05);
+			uniform_add = (int)(((iNorm - control_space) * uniform / 1000) / (iSymbols - 2));        // Subtract 2 from no symbols to lose control/root nodes
+			return (int)(iNorm - control_space - (iSymbols - 2) * uniform_add);
+		}
+		
+	}
+	
+	/**
+	 * Calculates a value to add to all probabilities before use,
+	 * preventing any zero values from being used and potentially
+	 * resulting in missing nodes.
+	 * 
+	 * @param iNorm Normalization value (usually LP_NORMALIZATION)
+	 * @return Uniform value to add to all probabilities.
+	 */
+	protected int getUniformAdd(int iNorm) {
+		
+		int iSymbols = m_cAlphabet.GetNumberSymbols();      // note that this includes the control node and the root node
+		long uniform = GetLongParameter(Elp_parameters.LP_UNIFORM);
+		
+		if(!GetBoolParameter(Ebp_parameters.BP_CONTROL_MODE)) {
+			return (int)((iNorm * uniform) / 1000) / (iSymbols - 2);  // Subtract 2 from no symbols to lose control/root nodes
+		}
+		else {
+			return (int)(((iNorm - getControlSpace(iNorm)) * uniform / 1000) / (iSymbols - 2));        // Subtract 2 from no symbols to lose control/root nodes
+		}
+	}
+	
+	/**
+	 * Gets the probability to associate with the control node
+	 * <p>
+	 * This will be either 5% of the norm value if control mode
+	 * is enabled, or zero otherwise.
+	 * 
+	 * @param iNorm Normalization value (usually LP_NORMALIZATION)
+	 * @return Probability of control node.
+	 */
+	protected long getControlSpace(int iNorm) {
+		if(!GetBoolParameter(Ebp_parameters.BP_CONTROL_MODE)) {
+			return 0;
+		}
+		else {
+			return (long)(iNorm * 0.05);
+		}
+	}
+	
+	/**
+	 * Extends a given context with a given string of characters,
+	 * whilst modifying the language model itself based on what is
+	 * entered.
+	 * <p>
+	 * The bulk of the work is deferred to the language
+	 * model's LearnSymbol method.
+	 * 
+	 * @param context Context to extend
+	 * @param TheText Text to add
+	 * @param IsMore Ignored
+	 */	
+	public void LearnText(CContextBase context, String TheText, boolean IsMore) {
+		ArrayList <Integer> Symbols = new ArrayList<Integer>();
+		
+		m_cAlphabet.GetSymbols(Symbols, TheText, IsMore);
+		
+		for(int i = 0; i < Symbols.size(); i++)
+			m_LanguageModel.LearnSymbol(context, Symbols.get(i)); // FIXME - conversion to symbol alphabet
+	}
+	
+	/**
+	 * Extends a given language model context without modifying
+	 * the model itself.
+	 * <p>
+	 * The bulk of the work itself is deferred to the LanguageModel's
+	 * EnterSymbol method.
+	 *  
+	 * @param context Context to extend
+	 * @param TheText Text to add
+	 */
+	public void EnterText(CContextBase context, String TheText) {
+		ArrayList <Integer> Symbols = new ArrayList<Integer>();
+		m_cAlphabet.GetSymbols(Symbols, TheText, false); // UTF8 bytes become Unicode Integers
+		for(int i = 0; i < Symbols.size(); i++)
+			m_LanguageModel.EnterSymbol(context, Symbols.get(i)); // FIXME - conversion to symbol alphabet
+	}
+	
+	/**
+	 * Gets this model's helper training class.
+	 * 
+	 * @return Trainer class
+	 */
+	public CTrainer GetTrainer() {
+		return new CTrainer(this);
+	}
+	
+	/**
+	 * Deletes and then repopulates the children of a given
+	 * node.
+	 * <p>
+	 * If the pushed node has no associated context, an attempt
+	 * is made to derive it by extending that of the node's
+	 * parent, and as a last ditch, creating an empty one.
+	 * 
+	 * @param Node Node to push. Must not be null.
+	 */
+	protected void Push_Node(CDasherNode Node) {
+		
+		if(Node.HasAllChildren()) {
+			assert(Node.Children().size() > 0);
+			// if there are children just give them a poke
+			
+			for(CDasherNode i : Node.Children()) {
+				i.Alive(true);
+			}
+			return;
+		}
+		
+		Node.Delete_children();
+		
+		// if we haven't got a context then derive it
+		
+		if(Node.Context() == null) {
+			CContextBase cont;
+			// sym0
+			if(Node.Symbol() < m_cAlphabet.GetNumberTextSymbols() && Node.Symbol() > 0) {
+				CDasherNode Parent = Node.Parent();
+				assert(Parent != null);
+				// Normal symbol - derive context from parent
+				cont = m_LanguageModel.CloneContext(Parent.Context());
+				m_LanguageModel.EnterSymbol(cont, Node.Symbol());
+			} else {
+				// For new "root" nodes (such as under control mode), we want to 
+				// mimic the root context
+				cont = CreateEmptyContext();
+				//      EnterText(cont, "");
+			}
+			Node.SetContext(cont);
+			
+		}
+		
+		Node.Alive(true);
+		
+		Node.m_NodeManager.PopulateChildren(Node);
+		Node.SetHasAllChildren(true);
+	}
+	
+	/**
+	 * Pushes a given node and recursively pushes its children to a given depth.
+	 * <p>
+	 * The tree of recursive pushes will be truncated whenever an attempt
+	 * is made to push a node filling less than 10% of the screen
+	 * or which is the control node.
+	 * 
+	 * @param Node Node at which to start pushing
+	 * @param iDepth Maximum depth to which we should push
+	 */
+	protected void Recursive_Push_Node(CDasherNode Node, int iDepth) {
+		
+		if(Node.Range() < 0.1 * GetLongParameter(Elp_parameters.LP_NORMALIZATION)) {
+			return;
+		}
+		
+		if(Node.Symbol() == GetControlSymbol()) {
+			return;
+		}
+		
+		Push_Node(Node);
+		
+		if(iDepth == 0)
+			return;
+		
+		for(int i = 0; i < Node.ChildCount(); i++) {
+			Recursive_Push_Node(Node.Children().get(i), iDepth - 1);
+		}
+	}
+	
+	/**
+	 * Calls the View's Render method on our current Root; the View
+	 * will take care of all drawing from here on in.
+	 * <p>
+	 * If BP_OLD_STYLE_PUSH is not enabled, all Nodes which the
+	 * View reports it has drawn will be pushed here, and all which
+	 * the View reported as undrawable due to being too small,
+	 * off the screen, etc, will have their children deleted.
+	 * 
+	 * @param View View to which we wish to draw
+	 * @param bRedrawDisplay Whether to force a complete redraw
+	 * @return True if the View changed anything, false otherwise
+	 */	
+	public boolean RenderToView(CDasherView View, boolean bRedrawDisplay) {
+		ArrayList<CDasherNode> vNodeList = new ArrayList<CDasherNode>();
+		ArrayList<CDasherNode> vDeleteList = new ArrayList<CDasherNode>();
+		
+		boolean bReturnValue;
+		
+		if(GetBoolParameter(Ebp_parameters.BP_DELAY_VIEW)) {
+			bReturnValue = View.Render(m_Root, m_iTargetMin, m_iTargetMax, vNodeList, vDeleteList, bRedrawDisplay);
+		}
+		else {
+			bReturnValue = View.Render(m_Root, m_Rootmin, m_Rootmax, vNodeList, vDeleteList, bRedrawDisplay);
+		}
+		if(!GetBoolParameter(Ebp_parameters.BP_OLD_STYLE_PUSH)) {
+			for(CDasherNode it : vNodeList) {
+				Push_Node(it);
+			}
+		}
+		
+		for(CDasherNode it : vDeleteList) {
+			it.Delete_children();
+		}	
+		return bReturnValue;
+	}
+	
+	/**
+	 * If the view reports that our current root node isn't
+	 * visible, calls Reparent_root; if only one child of the
+	 * current root is Alive (ie. on screen and visible), makes
+	 * this child the root.
+	 * <p>
+	 * The actual work will be done by Reparent_root and Make_root
+	 * respectively; this just decides which to use and when.
+	 * 
+	 * @param View View against which to check node visibility.
+	 * @return True if Reparent_root made any changes, false otherwise.
+	 */
+	public boolean CheckForNewRoot(CDasherView View) {
+		
+		if(m_deGotoQueue.size() > 0)
+			return false;
+		
+		/* CSFS: Some slightly doubtful semantics here. In the C++ version, the new
+		 * variable named root is created using a copy constructor on a pointer
+		 * which I think/hope means we ultimately get a pointer to the same object
+		 * as is done below.
+		 */
+		
+		CDasherNode root = m_Root;
+		ArrayList<CDasherNode> children = m_Root.Children();
+		
+		if(View.IsNodeVisible(m_Rootmin,m_Rootmax)) {
+			Reparent_root(root.Lbnd(), root.Hbnd());
+			return(m_Root != root); // Has the reparent method changed the root?
+		}
+		
+		if(children.size() == 0)
+			return false;
+		
+		int alive = 0;
+		CDasherNode theone = null;
+		
+		
+		// Find whether there is exactly one alive child; if more, we don't care.
+			
+		for(CDasherNode i : children) {
+			if(i.Alive()) {
+				alive++;
+				theone = i;
+				if(alive > 1)
+					break;
+			}
+		}
+		
+		if(alive == 1) {
+			// We must have zoomed sufficiently that only one child of the root node 
+			// is still alive.  Let's make it the root.
+			
+			/* CSFS: All formerly myints */
+			
+			long y1 = m_Rootmin;
+			long y2 = m_Rootmax;
+			long range = y2 - y1;
+			
+			long newy1 = y1 + (range * theone.Lbnd()) / (int)GetLongParameter(Elp_parameters.LP_NORMALIZATION);
+			long newy2 = y1 + (range * theone.Hbnd()) / (int)GetLongParameter(Elp_parameters.LP_NORMALIZATION);
+			if(!View.IsNodeVisible(newy1, newy2)) {
+				Make_root(theone);
+				return false;
+			}
+		}
+		
+		return false;
+	}
+
+	/**
+	 * TODO work out what this does and document.
+	 * 
+	 * @param dasherx Dasher X co-ordinate
+	 * @param dashery Dasher Y co-ordinate
+	 * @return Correction factor
+	 */
+	protected double CorrectionFactor(long dasherx, long dashery) {
+		double dX = 1 - dasherx/2048.0;
+		double dY = dashery/2048.0 - 1;
+		
+		/* CSFS: All C++ maths functions switched for Java's equivalent;
+		 * now I just hope for equivalent function!
+		 */
+		
+		double dR = Math.sqrt(Math.pow(dX, 2.0) + Math.pow(dY, 2.0));
+		
+		if(Math.abs(dX) < 0.1)
+			return dR * (1 + dX /2.0+ Math.pow(dX, 2.0) / 3.0 + Math.pow(dX, 3.0) / 4.0 + Math.pow(dX, 4.0) / 5.0);
+		else
+			return -dR * Math.log(1 - dX) / dX;
+	}
+	
+	/**
+	 * Interpolates between our current position and a given
+	 * new position, scheduling a zoom to the new position by
+	 * adding the interpolated points to m_deGotoQueue.
+	 * <p>
+	 * dasherx will be increased to 100 if this is not already so.
+	 * <p>
+	 * The number of points to interpolate (and hence the smoothness
+	 * of the zoom, at the expense of speed,) is controlled by
+	 * LP_ZOOMSTEPS.
+	 * 
+	 * @param dasherx Destination Dasher X co-ordinate
+	 * @param dashery Destination Dasher Y co-ordinate
+	 */
+	public void ScheduleZoom(long dasherx, long dashery) {
+		
+		// Takes dasher co-ordinates and 'schedules' a zoom to that location
+		// by storing a sequence of moves in 'm_deGotoQueue'
+		
+		/* CSFS: In a few locations here there were implicit casts
+		 * where an integer/long is multiplied by some double
+		 * and then is implictly cast back to int/long. I've made
+		 * these explicit and again hope this is what's intended...
+		 */
+		
+		// TODO: What is the following line for?
+		if (dasherx < 2) { dasherx = 100; }
+		
+		double dCFactor = CorrectionFactor(dasherx, dashery);
+		
+		int iSteps = (int)(GetLongParameter(Elp_parameters.LP_ZOOMSTEPS) * dCFactor);
+		long n1, n2, iTarget1, iTarget2;
+			
+		iTarget1 = dashery - dasherx;
+		iTarget2 = dashery + dasherx;
+		
+		double dZ = 4096 / (double)(iTarget2 - iTarget1);
+		
+		n1 = (long)((m_Rootmin - iTarget1) * dZ);
+		n2 = (long)((m_Rootmax - iTarget2) * dZ + 4096);
+		
+		m_deGotoQueue.clear();
+		
+		
+		for(int s = 1; s < iSteps; ++s) {
+			// use simple linear interpolation. Really should do logarithmic interpolation, but
+			// this will probably look fine.
+			SGotoItem sNewItem = new SGotoItem();
+			
+			sNewItem.iN1 = (s * n1 + (iSteps-s) * m_Rootmin) / iSteps;
+			sNewItem.iN2 = (s * n2 + (iSteps-s) * m_Rootmax) / iSteps;
+			sNewItem.iStyle = 1;
+			
+			m_deGotoQueue.addLast(sNewItem);
+		} 
+		
+		SGotoItem sNewItem = new SGotoItem();
+		
+		sNewItem.iN1 = n1;
+		sNewItem.iN2 = n2;
+		sNewItem.iStyle = 2;
+		
+		m_deGotoQueue.addLast(sNewItem);
+		
+		/* CSFS: Swapped push_back for addLast in both cases */
+	}
+	
+	/**
+	 * Runs the LanguageModel's UnregisterComponent method, if
+	 * there is currently a LanguageModel.
+	 *
+	 */
+	public void deleteLM() {
+		if(m_LanguageModel != null) m_LanguageModel.UnregisterComponent();
+	}
+	
+	/**
+	 * Unregisters the language model and then ourselves.
+	 */
+	public void UnregisterComponent() {
+		if(m_LanguageModel != null) m_LanguageModel.UnregisterComponent();
+		super.UnregisterComponent();
+	}
+
+	/**
+	 * Sets each of Rootmin and Rootmax to TargetMin and TargetMax
+	 * plus a given offset. 
+	 * 
+	 * @param iOffset Offset to add
+	 */
+	public void Offset(int iOffset) {
+		m_Rootmin = m_iTargetMin + iOffset;
+		m_Rootmax = m_iTargetMax + iOffset;
+	} 
+	
+	/**
+	 * Sets each of RootMin and RootMax to match
+	 * their TargetMax and TargetMin partners.
+	 */
+	protected void MatchTarget() {
+		m_Rootmin = m_iTargetMin;
+		m_Rootmax = m_iTargetMax;
+	}
+	
+	/* CSFS: Both of these methods currently use boolean types to
+	 * indicate failure or success. Ideally these would use exceptions
+	 * but it doesn't seem to cause a problem at present.
+	 */
+	
+	//Framerate functions:
+	
+	/**
+	 * Deferred to m_fr.
+	 */
+	public void NewFrame(long Time) { // Used to be unsigned -- potential problem.
+		m_fr.NewFrame(Time);
+	}
+	
+	/**
+	 * Deferred to m_fr.
+	 */
+	public double Framerate() {
+	    return m_fr.Framerate();
+	}
+	
+	/**
+	 * Deferred to m_fr.
+	 */
+	public void Reset_framerate(long Time) {
+	    m_fr.Reset(Time);
+	}
+	
+	/**
+	 * Deferred to m_fr.Initialise().
+	 */
+	public void Halt() {
+	    m_fr.Initialise();
+	}
+	
+	/**
+	 * Deferred to m_fr.
+	 */
+	public void SetBitrate(double TargetRate) {
+	    m_fr.SetBitrate(TargetRate);
+	}
+	
+	/**
+	 * Sets total_nats back to 0.
+	 */
+	public void ResetNats() {
+		total_nats = 0;
+	}
+	
+	/**
+	 * Gets total_nats
+	 * @return total_nats
+	 */
+	public double GetNats() {
+		return total_nats;
+	}
+	
+	/**
+	 * Gets our current alphabet's Space symbol
+	 * 
+	 * @return Requested symbol number
+	 */
+	public int GetSpaceSymbol() {
+		return m_cAlphabet.GetSpaceSymbol();
+	}
+	
+	/**
+	 * Gets our current alphabet's Control symbol
+	 * 
+	 * @return Requested symbol number
+	 */
+	public int GetControlSymbol() {
+		return m_cAlphabet.GetControlSymbol();
+	}
+	
+	/**
+	 * Gets our current alphabet's Start-conversion symbol
+	 * 
+	 * @return Requested symbol number
+	 */
+	public int GetStartConversionSymbol() {
+		return m_cAlphabet.GetStartConversionSymbol();
+	}
+	
+	// Potentially redundant function.
+	/**
+	 * Deferred to m_cAlphabet
+	 */
+	public String GetDisplayText(int iSymbol) {
+		return m_cAlphabet.GetDisplayText(iSymbol);
+	}
+	
+	/* CSFS: Potential trouble here, as it seems one of these may be intended
+	 * to produce a copy of the alphabet, and the other to return a reference
+	 * to the live one.
+	 */
+	
+	/**
+	 * Retrieves our current alphabet.
+	 */
+	public CAlphabet GetAlphabet() {
+		return m_cAlphabet; // FIXME CLONE
+	}
+	
+	/**
+	 * Retrieves our current alphabet.
+	 */
+	public CAlphabet GetAlphabetNew() {
+		return m_cAlphabet;
+	}
+	
+	/* CSFS: In the original C++, these read:
+	 * 
+	 * const CAlphabet & GetAlphabet() const {
+     * return *m_pcAlphabet;
+     * }
+     *
+     * CAlphabet *GetAlphabetNew() const {
+     * return m_pcAlphabet;
+     * }
+     * 
+     * Confusingly, it looks as if the return from GetAlphabet will be
+     * a clone of the Alphabet currently registered, whereas the
+     * return from GetAlphabetNew will be a pointer to the current
+     * alphabet which one could then alter
+     */
+	
+	/**
+	 * Constructs a new root Node of a given type, with a given parent
+	 * which may be null if necessary.
+	 * 
+	 * @param iType Type of node to create. At present, ignored; only ordinary letter nodes are created.
+	 * @param Parent Parent of the node we will create. May be null.
+	 * @param iLower Desired Lbnd of the new Node
+	 * @param iUpper Desired Hbnd of the new Node
+	 * @return Newly created DasherNode
+	 */
+	public CDasherNode GetRoot( int iType, CDasherNode Parent, long iLower, long iUpper, int UserData ) {
+		
+			return m_AlphabetManagerFactory.GetRoot(Parent, iLower, iUpper, UserData);
+		// case 1:
+			// return m_ControlManagerFactory.GetRoot(Parent, iLower, iUpper, UserData);
+		//case 2:
+		//	return m_ConversionManagerFactory.GetRoot(pParent, iLower, iUpper, UserData);
+		
+		
+		/* CSFS: Excluded the last case for now as it was surrounded
+		 * by #ifdef JAPANESE in the original source, and I have not
+		 * ported the Japanese modules yet.
+		 */
+		
+	}
+	
+	// Control mode stuff
+	
+	/**
+	 * Stub; implement if Control Mode is required.
+	 * <p>
+	 * The code for this is commented but present in the source.
+	 */
+	public void RegisterNode( int iID, String strLabel, int iColour ) {
+		// m_ControlManagerFactory.RegisterNode(iID, strLabel, iColour);
+	}
+	
+	/**
+	 * Stub; implement if Control Mode is required.
+	 * <p>
+	 * The code for this is commented but present in the source.
+	 */
+	public void ConnectNode(int iChild, int iParent, int iAfter) {
+		// m_ControlManagerFactory.ConnectNode(iChild, iParent, iAfter);
+	}
+	
+	/**
+	 * Stub; implement if Control Mode is required.
+	 * <p>
+	 * The code for this is commented but present in the source.
+	 */
+	public void DisconnectNode(int iChild, int iParent) {
+		// m_ControlManagerFactory.DisconnectNode(iChild, iParent);
+	}
+	
+	/* CSFS: These mades stubs for now until I've written Control Mode back in */
+	
+	/**
+	 * Retrieves the number of points currently in the m_deGotoQueue.
+	 * 
+	 * @return Number of scheduled steps.
+	 */
+	public int ScheduledSteps() {
+		return m_deGotoQueue.size();
+	}
+	
+	/* CSFS: This class used to return a context; these have
+	 * been converted to a class as detailed in the notes found
+	 * in CLanguageModel.
+	 */
+	
+	/**
+	 * Deferred to m_LanguageModel
+	 */
+	protected CContextBase CreateEmptyContext() {
+		return m_LanguageModel.CreateEmptyContext();
+	}
+	
+	/**
+	 * Deferred to m_cAlphabet
+	 */
+	public int GetColour(int s) {
+		return m_cAlphabet.GetColour(s);
+	}
+
+	/**
+	 * Deferred to m_cAlphabet
+	 */	
+	public ArrayList<Integer> GetColours() {
+		// See comments in CAlphabet
+		return m_cAlphabet.GetColours();
+	}
+	
+}

Added: trunk/java/dasher/CDasherModule.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CDasherModule.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,143 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * A Module is a richer extension of a Component. It supplies all
+ * the facilities of a Component, including registration for event
+ * listening and access to a settings store, and adds some module-specific
+ * functions, including:
+ * <p>
+ * <ul><li>Naming. Modules each have a name which is decided when
+ * the class is constructed, in order to facilitate GetModuleByName.
+ * <li>Type and ID, to classify modules without necessarily knowing
+ * their class.
+ * <li>Reference counting. When the count reaches zero, the module
+ * will automatically unregister itself from the EventHandler,
+ * allowing the module to be garbage collected.
+ */
+public class CDasherModule extends CDasherComponent {
+	
+	/**
+	 * This module's unique identifier
+	 */
+	private long m_iID;
+	
+	/**
+	 * This module's type number
+	 */
+	private int m_iType;
+	
+	/**
+	 * Current reference count for this module
+	 */
+	private int m_iRefCount;
+	
+	/**
+	 * Module name
+	 */
+	private String m_szName;
+	
+	/**
+	 * Creates a new module, passing the appropriate parameters
+	 * to DasherComponent's constructor. In order for this module
+	 * to be used by the interface it should be wrapped in a 
+	 * CWrapperFactory and then registered with the ModuleManager.
+	 * 
+	 * @param EventHandler EventHandler with which this module
+	 * should register itself
+	 * @param SettingsStore SettingsStore to use
+	 * @param iID Unique ID
+	 * @param iType Type number
+	 * @param szName Friendly, preferably unique, name
+	 */
+	public CDasherModule(CEventHandler EventHandler, CSettingsStore SettingsStore, long iID, int iType, String szName) {
+		super(EventHandler, SettingsStore);
+		
+		m_iID = iID;
+		m_iType = iType;
+		m_iRefCount = 0;
+		m_szName = szName;
+	}
+	
+	/**
+	 * Gets this module's unique ID
+	 * 
+	 * @return UID
+	 */
+	public long GetID() {
+		return m_iID;
+	}
+	
+	/**
+	 * Gets this module's type ID
+	 * 
+	 * @return Type
+	 */
+	public int GetType() {
+		return m_iType;
+	}
+	
+	/**
+	 * Gets this module's name
+	 * 
+	 * @return Name
+	 */
+	public String GetName() {
+		return m_szName;
+	}
+	
+	/**
+	 * Increments this module's reference count
+	 *
+	 */
+	public void Ref() {
+		++m_iRefCount;
+	}
+	
+	/**
+	 * Decrements this module's reference count; if this becomes
+	 * zero, unregisters the module with the event handler so
+	 * that it can be garbage collected.
+	 *
+	 */
+	public void Unref() {
+		--m_iRefCount;
+		
+		/* CSFS: In the original C++, this read 'delete this'.
+		 * Since in Java we can't do that, I just unregister the component
+		 * with the manager (inherited method from CDasherComponent).
+		 * Therefore we *must* drop the reference at the other end
+		 * such that the module will be garbage collected.
+		 */
+		
+		if(m_iRefCount == 0) { 
+			this.UnregisterComponent();
+		}
+		
+	}
+	
+}

Added: trunk/java/dasher/CDasherNode.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CDasherNode.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,559 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.ArrayList;
+
+/**
+ * A DasherNode represents a node in the DasherModel's tree; it
+ * is has a probability, children and one parent, and is typically
+ * drawn as a box with a letter or symbol in it.
+ * <p>
+ * It is capable of finding a Node at a given Screen location
+ * and of performing certain tree modifications (such as deleting
+ * its children) but otherwise mainly acts as a data structure.
+ */
+public class CDasherNode {
+
+	//	Information required to display the node
+	/**
+	 * Colour scheme associated with this node
+	 */
+	protected EColorSchemes m_ColorScheme;
+	
+	/**
+	 * Phase; this is related to colour cycling from one generation
+	 * to the next.
+	 */
+	protected int m_iPhase;
+	
+	/**
+	 * Colour number if this node is using a colour scheme defined
+	 * by an instance of CCustomColours
+	 */
+	protected int m_iColour;
+	
+	/**
+	 * Lower cumulative probability bound relative to our parent
+	 */
+	protected long m_iLbnd;
+	
+	/**
+	 * Upper cumulative probability bound relative to our parent
+	 */
+	protected long m_iHbnd; 
+
+	/**
+	 * Indicates whether this node is currently drawable
+	 */	
+	protected boolean m_bAlive;
+	
+	/**
+	 * Indicates whether this node's symbol has been output already
+	 */
+	protected boolean m_bSeen;
+	 
+	// Information internal to the data structure
+	
+	/**
+	 * List of this node's child Nodes
+	 */
+	protected ArrayList<CDasherNode> m_mChildren;
+	
+	/**
+	 * Flag indicating whether all of this node's children are present
+	 */
+	protected boolean m_bHasAllChildren;
+
+	/**
+	 * Parent Node
+	 */
+	protected CDasherNode m_Parent;
+
+	// TODO: The following should be included in m_pUserData, as they only apply to nodes managed by CAlphabetManager
+	
+	/**
+	 * LanguageModel which was responsible for generating this
+	 * node's probability
+	 */
+	protected CLanguageModel m_LanguageModel;     // pointer to the language model - in future, could be different for each node      
+	
+	/**
+	 * Language model context corresponding to this node's
+	 * position in the tree.
+	 */
+	protected CContextBase m_Context;
+	
+	/**
+	 * Symbol number represented by this node
+	 */
+	protected int m_Symbol;	// the character to display
+	
+	/**
+	 * Root of the tree of groups into which this Node's
+	 * children are arranged.
+	 */
+	public SGroupInfo m_BaseGroup;
+	
+	/**
+	 * NodeManager responsible for populating this Node's
+	 * children.
+	 */
+	public CNodeManager m_NodeManager;
+    /* CSFS: This was a void pointer in the original C++. Since it always seemed
+     * to get cast to an int and used as such, I've made it an int for now.
+     * If trouble crops up this may need to become an Object or something else
+     * awkward.
+     */
+    
+    /**
+     * Stores arbitrary information; may be extended to hold
+     * more in the future.
+     */
+	public int m_UserData;
+
+	/**
+	 * This Node's display text
+	 */
+    public String m_strDisplayText;
+
+    /**
+     * Whether this Node shoves or not (ie. whether the symbols
+     * of its children should be displaced to the right so as
+     * not to obscure this one)
+     */
+    public boolean m_bShove;
+	
+	/**
+	 * Creates a Node and sets its describing variables.
+	 * 
+	 * @param Parent Parent Node
+	 * @param Symbol Symbol number
+	 * @param iphase Colour-cycling phase
+	 * @param ColorScheme Colour scheme
+	 * @param ilbnd Lower bound of cum. probability relative to parent
+	 * @param ihbnd Upper bound of cum. probability relative to parent
+	 * @param lm LanguageModel
+	 * @param Colour Colour number
+	 */
+    public CDasherNode(CDasherNode Parent, int Symbol, int iphase, EColorSchemes ColorScheme, long ilbnd, long ihbnd, CLanguageModel lm, int Colour) {
+		m_iLbnd = ilbnd;
+		m_iHbnd = ihbnd;
+		m_Symbol = Symbol;
+		m_mChildren = new ArrayList<CDasherNode>();
+		// m_bHasAllChildren = false; (default)
+		m_bAlive = true;
+		// m_bSeen = false; (default)
+		m_ColorScheme = ColorScheme;
+		m_iPhase = iphase;
+		m_iColour = Colour;
+		m_LanguageModel = lm;
+		m_Context = CLanguageModel.nullContext;
+		m_Parent = Parent;
+		// m_strDisplayText = new String();
+		// WARNING: Whilst I think this is redundant it MAY get used uninitialised.
+		
+		/* CSFS: BUGFIX: There used to be a chance this was used uninitialised.
+		 * Fixed.
+		 */
+		
+	}
+
+	/**
+	 * At present, does nothing; Nodes will be "deleted" by virtue
+	 * of their parents cutting them loose at the appropriate time,
+	 * making them available for garbage collection.
+	 *
+	 */
+    public void DeleteNode() {
+
+	  /* CSFS: Lifted from C++ destructor function. Must be called for all nodes before they
+	   * are garbage collected.
+	   */
+		
+		// ClearNode and ReleaseContext both do nothing, so I'm experimenting with this method doing nothing.
+		
+      // Release any storage that the node manager has allocated,
+	  // unreference ref counted stuff etc.
+
+	  //m_NodeManager.ClearNode(this);
+
+	  //Delete_children();
+	  //if(m_Context != null)
+	  //  m_LanguageModel.ReleaseContext(m_Context);
+	}
+
+	/**
+	 * Sets the context associated with this node.
+	 * <p>
+	 * Releases its existing context with the language model
+	 * if one exists.
+	 * 
+	 * @param context New context
+	 */
+    public void SetContext(CContextBase context) {
+	  if(m_Context != null)
+	    m_LanguageModel.ReleaseContext(m_Context);
+	  m_Context = context;
+	}
+
+    /**
+     * Gets m_iLbnd
+     * 
+     * @return m_iLbnd
+     */
+	public long Lbnd() {
+	  return m_iLbnd;
+	}
+
+	/**
+     * Gets m_iHbnd
+     * 
+     * @return m_iHbnd
+     */
+	public long Hbnd() {
+	  return m_iHbnd;
+	}
+
+	/**
+	 * Gets the difference between m_iLbnd and m_iHbnd.
+	 * 
+	 * @return Range
+	 */
+	public long Range() {
+	  return m_iHbnd - m_iLbnd;
+	}
+
+	/**
+	 * Gets a reference to this Node's child list. 
+	 * 
+	 * @return m_mChildren
+	 */
+	public synchronized ArrayList<CDasherNode> Children() {
+	  return m_mChildren;
+	}
+
+	/**
+	 * Gets a reference to this Node's child list. 
+	 * 
+	 * @return m_mChildren
+	 */
+	public synchronized ArrayList<CDasherNode> GetChildren() {
+	  return m_mChildren;
+	}
+	
+	/**
+	 * Sets this Node's child list. 
+	 * 
+	 * @param in The list of children to be attached to this node.
+	 */
+	public synchronized void SetChildren(ArrayList<CDasherNode> in) {
+		m_mChildren = in;
+	}
+
+	/**
+	 * Retrives the LM context associated with this node.
+	 * 
+	 * @return Context
+	 */
+	public CContextBase Context() {
+	  return m_Context;
+	}
+	
+	/**
+	 * Determine if a given node is this one's parent.
+	 * 
+	 * @param oldnode Potential parent
+	 * @return True if parent
+	 */
+	public boolean NodeIsParent(CDasherNode oldnode) {
+		  if(oldnode == m_Parent)
+		    return true;
+		  else
+		    return false;
+
+	}	
+	
+	/**
+	 * Returns the size of our child list.
+	 * 
+	 * @return Size of m_mChildren.
+	 */
+	public synchronized int ChildCount() {
+	    return m_mChildren.size();
+	}
+
+	/**
+	 * Gets this node's parent.
+	 * 
+	 * @return Parent node.
+	 */
+	public CDasherNode Parent() {
+	    return m_Parent;
+	}
+	  
+	/**
+	 * Attaches this Node to a given Parent.
+	 * 
+	 * @param NewParent Our new parent
+	 */
+	public void SetParent(CDasherNode NewParent) {
+	    m_Parent = NewParent;
+	}
+	
+	/**
+	 * Sets this node's probabilities.
+	 * 
+	 * @param iLower New Lbnd
+	 * @param iUpper New Hbnd
+	 */
+	public void SetRange(long iLower, long iUpper) {
+	    m_iLbnd = iLower;
+	    m_iHbnd = iUpper;
+	}
+
+	/**
+	 * Determines if this node is currently drawable.
+	 * 
+	 * @return m_bAlive
+	 */
+	public boolean Alive() {
+	    return m_bAlive;
+	}
+	 
+	/**
+	 * Sets this node's Alive flag
+	 * 
+	 * @param b new value
+	 */
+	public void Alive(boolean b) {
+	    m_bAlive = b;
+	}
+
+	/**
+	 * Sets this node's Alive flag to false
+	 *
+	 */
+	public void Kill() {
+	    m_bAlive = false;
+	}
+
+	/**
+	 * Gets this node's Seen flag
+	 * 
+	 * @return Seen
+	 */
+	public boolean isSeen() {
+	    return m_bSeen;
+	} 
+
+	/**
+	 * Sets this node's Seen flag
+	 * 
+	 * @param seen new value
+	 */
+	public void Seen(boolean seen) {
+	    m_bSeen = seen;
+	}
+
+	/**
+	 * Gets this node's symbol
+	 * 
+	 * @return symbol number
+	 */
+	public int Symbol() { 
+	    return m_Symbol; 
+	}
+
+	/**
+	 * Gets this node's colour-cycling phase
+	 * 
+	 * @return Phase
+	 */
+	public int Phase() {
+	    return m_iPhase;
+	}
+	// DJW Sort out the colour scheme / phase confusion
+	
+	/**
+	 * Gets this Node's colour scheme
+	 */
+	public EColorSchemes ColorScheme() {
+	    return m_ColorScheme;
+	} 
+	  
+	/**
+	 * Gets this Node's colour index
+	 * 
+	 * @return Colour index
+	 */
+	public int Colour() {
+	    return m_iColour;
+	} 
+
+	/**
+	 * Checks whether all of this Node's children exist at present
+	 * 
+	 * @return m_bHasAllChildren
+	 */
+    public boolean HasAllChildren() {
+	    return m_bHasAllChildren;
+	}
+	 
+    /**
+     * Sets the HasAllChildren flag
+     *
+     * @param val new value
+     */
+    public void SetHasAllChildren(boolean val) {
+	    m_bHasAllChildren = val;
+	}
+    
+    /**
+     * Gets the probability associated with this node's most
+     * probable child.
+     * 
+     * @return Probability
+     */
+    public long MostProbableChild() {
+    	
+    	long iMax = 0;
+    	    	
+    	for(CDasherNode i : this.GetChildren()) {
+    		if(i.Range() > iMax) iMax = i.Range();
+    	}
+    	
+    	return iMax;
+    }
+
+   
+    /**
+     * Finds the node under a given mouse location, given our boundaries
+     * in Dasher space. Essentially this iterates through our children
+     * checking whether the point falls within each child, and if so recalls
+     * this method in the child. If no children match, we replace a reference
+     * to ourselves.
+     * <p>
+     * The "mouse position" may of course be replaced by any other
+     * point we want to find the node under. 
+     * 
+     * @param iNormalization Normalization value, usually LP_NORMALIZATION
+     * @param miY1 Our upper bound in Dasher co-ordinate space
+     * @param miY2 Our lower bound in Dasher co-ordiante space
+     * @param miMousex Current mouse position X
+     * @param miMousey Current mouse position Y
+     * @return Node under this mouse position.
+     */
+    public CDasherNode Get_node_under(long iNormalization, long miY1, long miY2, long miMousex, long miMousey) {
+		
+		long miRange = miY2 - miY1;
+        m_bAlive = true;
+        
+        for(CDasherNode i : this.GetChildren()) {
+        	long miNewy1 = miY1 + (miRange * i.m_iLbnd) / iNormalization;
+        	long miNewy2 = miY1 + (miRange * i.m_iHbnd) / iNormalization;
+        	if(miMousey < miNewy2 && miMousey > miNewy1 && miMousex < miNewy2 - miNewy1)
+        		return i.Get_node_under(iNormalization, miNewy1, miNewy2, miMousex, miMousey);
+        }
+        return this;
+	}
+	
+//		 kill ourselves and all other children except for the specified
+//		 child
+//		 FIXME this probably shouldn't be called after history stuff is working
+	
+    /**
+     * Delete our children except for a given one, the delete ourself.
+     * 
+     * @param pChild Child to keep
+     */
+    public void OrphanChild(CDasherNode pChild) {
+		  assert(ChildCount() > 0);
+		  
+		  /* CSFS: Iteration through children changed as per previous
+		   * and also the new DeleteNode() routines used.
+		   * Finally delete replaced with orphaning the object,
+		   * leaving it ready for GC.
+		   */
+	  
+		  for(CDasherNode i : this.GetChildren()) {
+			  if(i != pChild) {
+				  i.Delete_children();
+				  i.DeleteNode();
+				  i = null;
+			  }
+			  
+		  }
+		  Children().clear();
+		  SetHasAllChildren(false);
+	}
+
+
+    /**
+     * Deletes the nephews of a given child; that is to say,
+     * deletes its siblings' children. 
+     * 
+     * @param pChild Child whose children will NOT be deleted.
+     */
+	public void DeleteNephews(CDasherNode pChild) {
+		  assert(Children().size() > 0);
+		  
+		  for(CDasherNode i : this.GetChildren()) {
+		    if(i != pChild) {
+		      i.Delete_children();
+		    }
+
+		  }
+	}
+
+	/**
+	 * Clears the Children list and sets our HasAllChildren flag
+	 * to false; this will leave this section of tree unrefrenced
+	 * and available for garbage collection.
+	 *
+	 */
+	public void Delete_children() {
+		
+		//for(CDasherNode i : this.GetChildren()) {
+			// i.DeleteNode(); (stub method)
+		//	i = null;
+		//}
+		Children().clear(); // This should be enough to render them GC-able.
+		SetHasAllChildren(false);
+	}
+
+//		 Gets the probability of this node 
+	
+	/**
+	 * Gets this node's probability
+	 * 
+	 * @param iNormalization Norm value, usually LP_NORMALIZATION
+	 */
+	public double GetProb(int iNormalization) {    
+		  return (double) (m_iHbnd - m_iLbnd) / (double) iNormalization;
+	}
+
+}

Added: trunk/java/dasher/CDasherScreen.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CDasherScreen.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,180 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+
+/**
+ * Defines a screen which Dasher can use to draw graphics
+ * primitives.
+ */
+public interface CDasherScreen {
+
+	/**
+	 * Gets the width, and hence maximum X screen co-ordinate.
+	 * 
+	 * @return width
+	 */
+	public abstract int GetWidth();
+	
+	/**
+	 * Gets the height, and hence maximum Y screen co-ordinate.
+	 * 
+	 * @return height
+	 */
+	public abstract int GetHeight();
+	
+	/**
+	 * Determines / guesses the size of a given string as drawn on this screen.
+	 * <p>
+	 * This is used in determining how much to displace other drawn
+	 * strings in order to prevent them from overlapping.
+	 * <p>
+	 * This must be carried out by the screen because only the
+	 * actual drawing surface can know how fonts appear when
+	 * rendered.
+	 * 
+	 * @param string String whose size we wish to determine
+	 * @param Size Font size in points
+	 * @return Point specifying the width and height of this string.
+	 */
+	public abstract CDasherView.Point TextSize(String string, int Size);
+	
+	
+	/**
+	 * Draws a string
+	 * 
+	 * @param string String to draw
+	 * @param x1 Top-left hand corner x co-ordinate
+	 * @param y1 Top-left hand corner y co-ordinate
+	 * @param Size Font size in points
+	 */
+	public abstract void DrawString(String string, int x1, int y1, long Size);
+	
+
+	/**
+	 * Informs the screen of certain drawing phases.
+	 * <p>
+	 * A '0' will be sent when beginning to draw persistent
+	 * features (ie. those which should remain the same from
+	 * frame to frame), and a '1' will be sent prior to drawing
+	 * ephemeral details which should vanish if not redrawn next
+	 * frame.
+	 * 
+	 * @param iMarker Marker number
+	 */	
+	public abstract void SendMarker(int iMarker);
+	
+  /** Draw a filled rectangle
+	* 
+	* @param x1 top left of rectangle (x coordinate)
+	* @param y1 top left corner of rectangle (y coordinate)
+	* @param x2 bottom right of rectangle (x coordinate)
+	* @param y2 bottom right of rectangle (y coordinate)
+	* @param Color the colour to be used (numeric)
+	* @param ColorScheme Which colourscheme is to be used
+	* @param bDrawOutline Whether to draw an outline or not
+	* @param bFill Whether to fill or not
+	* @param iThickness Line thickness for outline
+	*/
+	public abstract void DrawRectangle(int x1, int y1, int x2, int y2, int Color, int iOutlineColour, EColorSchemes ColorScheme, boolean bDrawOutline, boolean bFill, int iThickness);
+	
+	/**
+	 * Draw a circle
+	 * 
+	 * @param iCX X co-ordinate of the centre
+	 * @param iCY Y co-ordinate of the centre
+	 * @param iR Radius in pixels
+	 * @param iColour Colour number
+	 * @param bFill Fill or outline?
+	 */	
+	public abstract void DrawCircle(int iCX, int iCY, int iR, int iColour, boolean bFill);
+	
+	/**
+	 * Draws a sequence of lines in a fixed colour, usually black.
+	 * 
+	 * @param Points Array of Points describing the vertices of the line.
+	 * @param Number Number of points
+	 * @param iWidth Line width
+	 */
+	public abstract void Polyline(CDasherView.Point[] Points, int Number, int iWidth) ;
+	
+	/**
+	 * Draws a sequence of lines.
+	 * 
+	 * @param Points Array of Points describing the vertices of the line.
+	 * @param Number Number of points
+	 * @param iWidth Line width
+	 * @param Colour Colour number
+	 */
+	public abstract void Polyline(CDasherView.Point[] Points, int Number, int iWidth, int Colour);
+	
+   /**
+	* Draw a filled polygon - given vertices and color id.
+	* This is not (currently) used in standard Dasher. However, it could be very
+	* useful in the future. Please implement unless it will be very difficult,
+	* in which case make this function call Polyline.
+	* Draw a filled polygon
+	*
+	* @param Points array of points defining the edge of the polygon
+	* @param Number number of points in the array
+	* @param Color colour of the polygon (numeric)
+	*/
+	public abstract void Polygon(CDasherView.Point[] Points, int Number, int Color);
+	
+	/**
+	* Draw a filled polygon - given vertices, width and color id.
+	* This is not (currently) used in standard Dasher. However, it could be very
+	* useful in the future. Please implement unless it will be very difficult,
+	* in which case make this function call Polyline.
+	* Draw a filled polygon
+	*
+	* @param Points array of points defining the edge of the polygon
+	* @param Number number of points in the array
+	* @param Color colour of the polygon (numeric)
+	* @param iWidth Width of the polygon border to draw
+	*/
+	public abstract void Polygon(CDasherView.Point[] Points, int Number, int Color, int iWidth);
+	
+	/**
+	 * Signals the beginning of a new frame.
+	 *
+	 */
+	public abstract void Blank();
+	
+	/**
+	 * Signals the end of a frame.
+	 *
+	 */
+	public abstract void Display();
+	
+	/**
+	 * Sets the colour scheme to use
+	 * 
+	 * @param ColourScheme New colour scheme
+	 */
+	public abstract void SetColourScheme(CCustomColours ColourScheme);
+	
+}

Added: trunk/java/dasher/CDasherView.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CDasherView.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,838 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**	
+ * Dasher views represent the visualisation of a Dasher model on the screen.
+ * <p>
+ * There are really three roles played by CDasherView: providing high
+ * level drawing functions, providing a mapping between Dasher
+ * co-ordinates and screen co-ordinates and providing a mapping
+ * between true and effective Dasher co-ordinates (eg for eyetracking
+ * mode).
+ * <p>
+ * This class supplies only those functions which are independent
+ * of the way in which we choose to represent the Model; the specifics
+ * are decided in subclasses which decide exactly how a node should
+ * be rendered. At present, the only subclass is DasherViewSquare
+ * which draws square boxes for each node.
+ * <p>
+ * Most actual drawing functions will be passed on to an implementation
+ * of CDasherScreen.
+ */
+public abstract class CDasherView extends CDasherComponent {
+	
+
+	/**
+	 * Class representing a point on the screen.
+	 */
+	static public class Point {
+		/**
+		 * X co-ord
+		 */
+		public int x;
+		/**
+		 * Y co-ord
+		 */
+		public int y;
+	}
+
+	/*
+	 * Class representing a point in Dasher space
+	 */
+	static public class DPoint {
+		/**
+		 * X co-ord
+		 */
+		public long x;
+		/**
+		 * Y co-ord
+		 */
+		public long y;
+	}
+
+	/**
+	 * Rectangle in Dasher space
+	 */
+	static public class DRect {
+		/**
+		 * Larger y co-ord
+		 */
+		public long maxY;
+		/**
+		 * Smaller y co-ord
+		 */
+		public long minY;
+		/**
+		 * Smaller x co-ord
+		 */
+		public long minX;
+		/**
+		 * Larger x co-ord
+		 */
+		public long maxX;
+	}
+
+	/**
+	 * Flag indicating whether we need to update our impression
+	 * of the region in Dasher space which is currently visible.
+	 */
+	protected boolean m_bVisibleRegionValid;
+	
+	/**
+	 * Screen we're currently using for drawing
+	 */
+	protected CDasherScreen m_Screen;
+	
+	/**
+	 * Current input device
+	 */
+	protected CDasherInput m_Input;
+	
+	/**
+	 * Delayed drawing helper. This allows us to draw Strings
+	 * at the natural time, with the helper storing them and
+	 * actually drawing all strings last.
+	 */
+	protected CDelayedDraw m_DelayDraw;
+	
+	/**
+	 * Stores the current value of LP_MAX_Y for efficiency.
+	 * <p>
+	 * We listen for parameter change events to update this
+	 * when necessary.
+	 */
+	protected long lpMaxY; // Caching result for dashery2screen
+	
+	/**
+	 * Stores the current value of LP_REAL_ORIENTATION again because
+	 * this parameter is requested many times during drawing, which
+	 * can become exceedingly inefficient.
+	 */
+	protected int realOrientation; // Caching result for dasher2screen
+	
+	/**
+	 * Current font size used for drawing.
+	 */
+	protected int lpFontSize;
+	
+	/**
+	 * Creates a new View wrapping a specified screen. The Screen
+	 * passed must not be null; as such, the View must be created
+	 * after a Screen has been instantiated.
+	 * <p>
+	 * To this ends, the View will usually be created in response
+	 * to the first call to InterfaceBase.ChangeScreen().
+	 * <p>
+	 * This constructor will also initialise fields which cache
+	 * parameter values, which will subsequently be kept up to
+	 * date by listening for parameter change events.
+	 * 
+	 * @param EventHandler Event handler with which to register ourselves
+	 * @param SettingsStore Settings repository to use 
+	 * @param DasherScreen Screen object to wrap.
+	 */
+	public CDasherView(CEventHandler EventHandler, CSettingsStore SettingsStore, CDasherScreen DasherScreen) {
+		super(EventHandler, SettingsStore);
+		m_Screen = DasherScreen;
+		m_Input = null;
+		
+		lpMaxY = SettingsStore.GetLongParameter(Elp_parameters.LP_MAX_Y);
+		realOrientation = (int)SettingsStore.GetLongParameter(Elp_parameters.LP_REAL_ORIENTATION);
+		lpFontSize = (int)SettingsStore.GetLongParameter(Elp_parameters.LP_DASHER_FONTSIZE);
+		
+		// Value caching
+	}
+	
+	/**
+	 * This class responds to the following events:
+	 * <p>
+	 * <i>LP_REAL_ORIENTATION, LP_MAX_Y and LP_DASHER_FONTSIZE</i>:
+	 * Updates our internally cached values of these parameters.
+	 * <p>
+	 * This method is called by the EventHandler when processing
+	 * events.
+	 * 
+	 * @param event Event to handle
+	 */
+	public void HandleEvent(CEvent event) {
+		if(event.m_iEventType == 1) { // Param-notify
+			CParameterNotificationEvent evt = (CParameterNotificationEvent)event;
+			if(evt.m_iParameter ==  Elp_parameters.LP_REAL_ORIENTATION) {
+				realOrientation = (int)GetLongParameter(Elp_parameters.LP_REAL_ORIENTATION);
+			}
+			else if (evt.m_iParameter == Elp_parameters.LP_MAX_Y) {
+				lpMaxY = GetLongParameter(Elp_parameters.LP_MAX_Y);
+			}
+			else if (evt.m_iParameter == Elp_parameters.LP_DASHER_FONTSIZE) {
+				lpFontSize = (int)GetLongParameter(Elp_parameters.LP_DASHER_FONTSIZE);
+			}
+		}
+	}
+	
+	/**
+	 * Sets our screen. New drawing instructions will immediately
+	 * being to be sent to the new one.
+	 * 
+	 * @param NewScreen New screen
+	 */
+	public void ChangeScreen(CDasherScreen NewScreen) {
+		m_Screen = NewScreen;
+	}
+	
+	/**
+	 * Renders the entire model, starting at a given Node and given
+	 * specific bounds in Dasher space.
+	 * <p>
+	 * At present this just passes all of its parameters to RenderNodes
+	 * with the exception of bRedrawDisplay, which is ignored (the
+	 * display is always redrawn).
+	 * 
+	 * @param Root Node at which to start the drawing process
+	 * @param iRootMin Minimum bounding co-ordinate in Dasher space
+	 * @param iRootMax Maximum bounding co-ordinate in Dasher space
+	 * @param vNodeList Collection which will be filled with Nodes which were drawn
+	 * @param vDeleteList Collection which will be filled with Nodes which were not drawn
+	 * @param bRedrawDisplay Flag indicating whether we wish for a redraw (ignored; always redraws)
+	 * @return True if a redraw took place (always the case at the moment) 
+	 */
+	public boolean Render(CDasherNode Root, long iRootMin, long iRootMax, Collection<CDasherNode> vNodeList, Collection<CDasherNode> vDeleteList, boolean bRedrawDisplay) {
+		
+		RenderNodes(Root, iRootMin, iRootMax, vNodeList, vDeleteList);
+		return true;
+	}
+	
+	/**
+	 * Deferred to m_Input.
+	 * 
+	 * @see CDasherInput
+	 * @return Number of co-ordinates, or 0 if there is no input device.
+	 */
+	public int GetCoordinateCount() {
+		// TODO: Do we really need support for co-ordinate counts other than 2?
+		if(m_Input != null)
+			return m_Input.GetCoordinateCount();
+			else
+				return 0;
+	}
+	
+	/**
+	 * Deferred to m_Input
+	 * 
+	 * @param iN Number of co-ordinates
+	 * @param Coordinates Array to fill with co-ordinates
+	 * @return 0 if the returned co-ordinates are screen co-ordinates,
+	 * 1 if Dasher co-ordinates. 0 will also be returned if there
+	 * is currently no input device. 
+	 */
+	public int GetCoordinates(int iN, long[] Coordinates) {
+		if(m_Input != null)
+			return m_Input.GetCoordinates(iN, Coordinates);
+			else
+				return 0;
+	}
+	
+	/**
+	 * Determines whether the node falling between two specified
+	 * y co-ordinates is visible.
+	 * <p>
+	 * Always returns true if not overridden.
+	 * 
+	 * @param y1 upper y co-ordinate
+	 * @param y2 lower y co-ordinate
+	 * @return True if visible, false if not.
+	 */
+	public boolean IsNodeVisible(long y1, long y2) { return true; };
+	
+	/**
+	 * Sets our current reference input device and informs the
+	 * new device of our maximal co-ordinates.
+	 * <p>
+	 * The input device will not be dereferenced or deleted, as
+	 * the caller may be intending for the input device to
+	 * switch frequently without destroying one which is 
+	 * nominally out of use.
+	 * 
+	 * @param Input New input device
+	 */
+	public void SetInput(CDasherInput Input) {
+		// TODO: Is it sensible to make this responsible for the input
+		// device - I guess it makes sense for now
+		
+		// Don't delete the old input class; whoever is calling this method
+		// might want to keep several Input class instances around and
+		// change which one is currently driving dasher without deleting any
+		
+		m_Input = Input;
+		
+		// Tell the new object about maximum values
+		
+		long[] iMaxCoordinates = new long[2];
+		
+		iMaxCoordinates[0] = lpMaxY;
+		iMaxCoordinates[1] = lpMaxY;
+		
+		m_Input.SetMaxCoordinates(2, iMaxCoordinates);
+	}
+	
+	/**
+	 * Deferred to our screen.
+	 *
+	 * @see CDasherScreen
+	 */
+	public void Display() {
+		m_Screen.Display();
+	}
+	
+	/**
+	 * Draws a polyline given a series of points in Dasher space.
+	 * <p>
+	 * Internally, we convert these to screen co-ordinates and pass
+	 * the request on to our screen.
+	 * <p>
+	 * Specifying a line colour of -1 causes the default to be drawn.
+	 * 
+	 * @param x Array of points' x co-ordinates
+	 * @param y Array of points' y co-ordinates
+	 * @param n Number of points in the line
+	 * @param iWidth Line width
+	 * @param iColour Colour index (-1 means default colour)
+	 */
+	public void DasherPolyline(long[] x, long[] y, int n, int iWidth, int iColour) {
+		
+		CDasherView.Point[] ScreenPoints = new CDasherView.Point[n];
+		
+		for(int i = (0); i < n; ++i)
+			ScreenPoints[i] = Dasher2Screen(x[i], y[i]);
+		
+		if(iColour != -1) {
+			Screen().Polyline(ScreenPoints, n, iWidth, iColour);
+		}
+		else {
+			Screen().Polyline(ScreenPoints, n, iWidth);
+		}
+	}
+	
+//	Draw a filled polygon specified in Dasher co-ordinates
+	
+	/**
+	 * Draws a filled polygon given a series of points in Dasher space.
+	 * <p>
+	 * Internally, we convert these to screen co-ordinates and pass
+	 * the request on to our screen.
+	 * <p>
+	 * Specifying a colour of -1 is not handled specially by
+	 * this method but ought to be translated to some sensible
+	 * default by the Screen.
+	 * 
+	 * @param x Array of points' x co-ordinates
+	 * @param y Array of points' y co-ordinates
+	 * @param n Number of points specified
+	 * @param iColour Colour index (-1 means default colour)
+	 */
+	public void DasherPolygon(long[] x, long[] y, int n, int iColour) {
+		
+		CDasherView.Point[] ScreenPoints = new CDasherView.Point[n];
+		
+		for(int i = (0); i < n; ++i)
+			ScreenPoints[i] = Dasher2Screen(x[i], y[i]);
+		
+		Screen().Polygon(ScreenPoints, n, iColour);
+	}
+	
+
+	/**
+	 * Draws a rectangle given its top-left and bottom-right co-ordinates
+	 * in Dasher space.
+	 * <p>
+	 * The co-ordinates are translated to screen co-ordinates and
+	 * the request passed on to the screen.
+	 * 
+	 * @param iLeft Left side x co-ordinate
+	 * @param iTop Top y co-ordinate
+	 * @param iRight Right side x co-ordinate
+	 * @param iBottom Bottom y co-ordinate
+	 * @param Color Fill colour
+	 * @param iOutlineColour Outline colour
+	 * @param ColorScheme Colour scheme to use (usually ignored in favour of colour indices now)
+	 * @param bDrawOutline Should we draw an outline?
+	 * @param bFill Filled?
+	 * @param iThickness Outline thickness
+	 */	
+	public void DasherDrawRectangle(long iLeft, long iTop, long iRight, long iBottom, int Color, int iOutlineColour, EColorSchemes ColorScheme, boolean bDrawOutline, boolean bFill, int iThickness) {
+		
+		CDasherView.Point topleft = new CDasherView.Point();
+		CDasherView.Point bottomright = new CDasherView.Point();
+		
+		topleft = Dasher2Screen(iLeft, iTop);
+		bottomright = Dasher2Screen(iRight, iBottom);
+		
+		Screen().DrawRectangle(topleft.x, topleft.y, bottomright.x, bottomright.y, Color, iOutlineColour, ColorScheme, bDrawOutline, bFill, iThickness);
+	}
+	
+//	/ Draw a rectangle centred on a given dasher co-ordinate, but with a size specified in screen co-ordinates (used for drawing the mouse blob)
+	
+	/**
+	 * Draws a square with a given centre in Dasher co-ordinates
+	 * and a given side-length in pixels (screen co-ordinates).
+	 * 
+	 * @param iDasherX Centre point x co-ordinate
+	 * @param iDasherY Centre point y co-ordinate
+	 * @param iSize Side length in pixels
+	 * @param Color Fill colour index
+	 * @param ColorScheme Colour scheme (usually ignored now in favour of colour index)
+	 * @param bDrawOutline Whether to draw a hairline black outline
+	 */
+	public void DasherDrawCentredRectangle(long iDasherX, long iDasherY, int iSize, int Color, EColorSchemes ColorScheme, boolean bDrawOutline) {
+		
+		CDasherView.Point centre = new CDasherView.Point();
+		
+		centre = Dasher2Screen(iDasherX, iDasherY);
+		
+		Screen().DrawRectangle(centre.x - iSize, centre.y - iSize, centre.x + iSize, centre.y + iSize, Color, -1, ColorScheme, bDrawOutline, true, 1);
+	}
+	
+	/**
+	 * Draws a given string inside a specified box, the dimensions and co-ordinates
+	 * of which are given in Dasher co-ordinates.
+	 * <p>
+	 * The actual specified bounding box is more or less taken as a guideline
+	 * however, and many changes are made from that which is specified to the
+	 * drawing command which is actually issued.
+	 * <p>
+	 * The most important change is that, using the mostleft parameter to
+	 * indicate the right-hand edge of some ancestor's text, an effort is made
+	 * to 'shove' this text to the right far enough that it does not overlap
+	 * with our ancestor.
+	 * <p>
+	 * This feature is enabled only when bShove is true.
+	 * <p>
+	 * The font size to be used to draw text is currently hard coded
+	 * so that text within 15 pixels of the y axis is drawn at size 11,
+	 * between 15 and 30 pixels is drawn at size 14, and over 30 pixels
+	 * is drawn at size 20.
+	 * <p>
+	 * The bounding box is recalculated by calling the Screen's TextSize
+	 * method, which attempts to determine the dimensions of this string
+	 * at a given size. This is then used to work out how far our children's
+	 * text must be 'shoved' to avoid overlapping our own.
+	 * <p>
+	 * As such, this method is far from general, and should only
+	 * be used to draw node labels. A new method will be required
+	 * if the need arises to draw arbitrary strings in a specified
+	 * location without adjustment.
+	 * <p>
+	 * This method will return a new 'mostleft' value for use when
+	 * drawing our children; if the Screen's TextSize method is
+	 * accurate, this ought to prevent our text from overlapping that
+	 * of our children.
+	 * <p>
+	 * For the actual drawing of text, m_DelayDraw is used instead
+	 * of passing the command directly to our Screen. This queue
+	 * of text to draw will be emptied towards the end of the
+	 * drawing cycle.
+	 * 
+	 * @param iAnchorX1 Left edge x co-ordinate
+	 * @param iAnchorY1 Top edge y co-ordinate
+	 * @param iAnchorX2 Right edge x co-ordinate
+	 * @param iAnchorY2 Bottom edge y co-ordinate
+	 * @param sDisplayText String to draw
+	 * @param mostleft Co-ordinate of the right-most text drawn by our ancestor.
+	 * @param bShove Should we try to avoid overlapping ancestor's text?
+	 * @return New 'mostleft' value for drawing children
+	 */
+	public long DasherDrawText(long iAnchorX1, long iAnchorY1, long iAnchorX2, long iAnchorY2, String sDisplayText, long mostleft, boolean bShove) {
+		
+		// Don't draw text which will overlap with text in an ancestor.
+		
+		if(iAnchorX1 > mostleft)
+			iAnchorX1 = mostleft;
+		
+		if(iAnchorX2 > mostleft)
+			iAnchorX2 = mostleft;
+		
+		CDasherView.DRect VisRegion = VisibleRegion();
+		
+		iAnchorY1 = Math.min( VisRegion.maxY, Math.max( VisRegion.minY, iAnchorY1 ) );
+		iAnchorY2 = Math.min( VisRegion.maxY, Math.max( VisRegion.minY, iAnchorY2 ) );
+		
+		CDasherView.Point ScreenAnchor1 = new CDasherView.Point();
+		CDasherView.Point ScreenAnchor2 = new CDasherView.Point();
+		// FIXME - Truncate here before converting - otherwise we risk integer overflow in screen coordinates
+		
+		ScreenAnchor1 = Dasher2Screen(iAnchorX1, iAnchorY1);
+		ScreenAnchor2 = Dasher2Screen(iAnchorX2, iAnchorY2);
+		
+		// Truncate the ends of the anchor line to be on the screen - this
+		// prevents us from loosing characters off the top and bottom of the
+		// screen
+		
+		// TruncateToScreen(iScreenAnchorX1, iScreenAnchorY1);
+		// TruncateToScreen(iScreenAnchorX2, iScreenAnchorY2);
+		
+		// Actual anchor point is the midpoint of the anchor line
+		
+		int iScreenAnchorX = ((ScreenAnchor1.x + ScreenAnchor2.x) / 2);
+		int iScreenAnchorY = ((ScreenAnchor1.y + ScreenAnchor2.y) / 2);
+		
+		// Compute font size based on position
+		int Size = lpFontSize;
+		
+		/* CSFS: BUGFIX: longs needed here, not ints. Fixed. */
+		
+		// FIXME - this could be much more elegant, and probably needs a
+		// rethink anyway - behvaiour here is too dependent on screen size
+		
+		//long iLeftTimesFontSize = (lpMaxY) - ((iAnchorX1 + iAnchorX2)/ 2) *Size;
+		
+		//long limit1 = (lpMaxY * 19) / 20;
+		//long limit2 = (lpMaxY * 159) / 160;
+		
+		int DistFromLeft = Dasher2Screen(0,0).x - iScreenAnchorX;
+		
+		int newlimit1 = 30;
+		int newlimit2 = 15;
+		
+		if(DistFromLeft > newlimit1) {
+			Size *= 20;
+		}
+		else if(DistFromLeft > newlimit2) { 
+			Size *= 14;
+		}
+		else {
+			Size *= 11;
+		}
+
+		int TextWidth, TextHeight;
+		
+		CDasherView.Point textDimensions = Screen().TextSize(sDisplayText, Size);
+		TextHeight = textDimensions.y;
+		TextWidth = textDimensions.x;
+		// Poistion of text box relative to anchor depends on orientation
+		
+		int newleft2 = 0;
+		int newtop2 = 0;
+		int newright2 = 0;
+		int newbottom2 = 0;
+		
+		switch ((int)(realOrientation)) {
+		case (Opts.ScreenOrientations.LeftToRight):
+			newleft2 = iScreenAnchorX;
+		newtop2 = iScreenAnchorY - TextHeight / 2;
+		newright2 = iScreenAnchorX + TextWidth;
+		newbottom2 = iScreenAnchorY + TextHeight / 2;
+		break;
+		case (Opts.ScreenOrientations.RightToLeft):
+			newleft2 = iScreenAnchorX - TextWidth;
+		newtop2 = iScreenAnchorY - TextHeight / 2;
+		newright2 = iScreenAnchorX;
+		newbottom2 = iScreenAnchorY + TextHeight / 2;
+		break;
+		case (Opts.ScreenOrientations.TopToBottom):
+			newleft2 = iScreenAnchorX - TextWidth / 2;
+		newtop2 = iScreenAnchorY;
+		newright2 = iScreenAnchorX + TextWidth / 2;
+		newbottom2 = iScreenAnchorY + TextHeight;
+		break;
+		case (Opts.ScreenOrientations.BottomToTop):
+			newleft2 = iScreenAnchorX - TextWidth / 2;
+		newtop2 = iScreenAnchorY - TextHeight;
+		newright2 = iScreenAnchorX + TextWidth / 2;
+		newbottom2 = iScreenAnchorY;
+		break;
+		default:
+			break;
+		}
+		
+		// Update the value of mostleft to take into account the new text
+		
+		if(bShove) {
+			CDasherView.DPoint newTopLeft;
+			CDasherView.DPoint newBottomRight;
+			
+			newTopLeft = Screen2Dasher(newleft2, newtop2, false, true);
+			newBottomRight = Screen2Dasher(newright2, newbottom2, false, true);
+			
+			mostleft = Math.min(newBottomRight.x, newTopLeft.x);
+		}
+		
+		// Actually draw the text. We use DelayDrawText as the text should
+		// be overlayed once all of the boxes have been drawn.
+		
+		m_DelayDraw.DelayDrawText(sDisplayText, newleft2, newtop2, Size);
+		
+		return mostleft;
+		
+		/* CSFS: This method was using a pointer to set mostleft; this seemed to be
+		 * all it returned, so I've altered it to directly return mostleft.
+		 */
+	}
+	
+	/**
+	 * Render our nodes, beginning at a given node with given upper
+	 * and lower y co-ordinates.
+	 * <p>
+	 * Will also fill vNodeList with a list of nodes which were
+	 * successfully drawn, and vDeleteList with a list of those
+	 * whom we abandoned drawing because they were off screen,
+	 * too small, etc.
+	 * 
+	 * @param Root Node at which to start drawing
+	 * @param iRootMin Lower y co-ordinate of this node
+	 * @param iRootMax Upper y co-ordinate of this node
+	 * @param vNodeList Collection to be filled with drawn nodes
+	 * @param vDeleteList Collection to be filled with undrawn nodes
+	 */
+	public abstract void RenderNodes(CDasherNode Root, long iRootMin, long iRootMax, Collection<CDasherNode> vNodeList, Collection<CDasherNode> vDeleteList);
+	
+	/**
+	 * Converts a pair of input co-ordinates to dasher co-ordinates.
+	 * <p>
+	 * Also takes account of the type of input device we're using,
+	 * so that one-dimensional devices and eyetrackers are corrected
+	 * appropriately.
+	 * <p><i>This method has been renamed from TapOnDisplay</i>
+	 * 
+	 * @return Dasher co-ordinates corresponding to this input point
+	 */
+	public abstract CDasherView.DPoint getInputDasherCoords();
+	
+	/**
+	 * Converts a pair of input co-ordinates to dasher co-ordinates.
+	 * <p>
+	 * Also takes account of the type of input device we're using,
+	 * so that one-dimensional devices and eyetrackers are corrected
+	 * appropriately.
+	 * <p>
+	 * This last parameter is redundant.
+	 * <p><i>This method has been renamed from TapOnDisplay</i>
+	 * @param Added Redundant
+	 * 
+	 * @return Dasher co-ordinates corresponding to this input point
+	 */
+	public abstract CDasherView.DPoint getInputDasherCoords(ArrayList<CSymbolProb> Added);
+	
+	/* CSFS: this method used to have an extra parameter, pNumDeleted, which defaulted to zero.
+	 * Since no method ever actually passes this parameter, I've deleted it.
+	 */
+	
+	/**
+	 * Should convert a given screen co-ordinate to dasher co-ordinates.
+	 * 
+	 * @param iInputX Screen x co-ordinate  
+	 * @param iInputY Screen y co-ordinate
+	 * @param b1D Indicates whether these co-ordinates come from a 1D device
+	 * @param bNonlinearity If true, we may wish to correct for a non-linearity in one or other co-ordinate system
+	 * @return Dasher co-ordinates
+	 */
+	public abstract CDasherView.DPoint Screen2Dasher(int iInputX, int iInputY, boolean b1D, boolean bNonlinearity);
+	
+	/**
+	 * Should convert a given Dasher co-ordinate to its equivalent
+	 * screen co-ordinates.
+	 * 
+	 * @param iDasherX Dasher x co-ordinate
+	 * @param iDasherY Dasher y co-ordinate
+	 * @return Screen co-ordinates
+	 */
+	public abstract CDasherView.Point Dasher2Screen(long iDasherX, long iDasherY);
+		
+
+	/**
+	 * Converts input device co-ordinates to the appropriate, not
+	 * necessarily equivalent, Dasher co-ordinates.
+	 * 
+	 * @param iInputX Input x co-ordinate
+	 * @param iInputY Input y co-ordinate
+	 * @param iType Input co-ordinate scheme: 0 for Screen or 1 for Dasher co-ordintes
+	 * @param iMode Input device mode; 0 for normal, 1 for 1D and 2 for eyetracker
+	 * @return Dasher co-ordinates corresponding to given input co-ordinates
+	 */
+	protected abstract CDasherView.DPoint Input2Dasher(int iInputX, int iInputY, int iType, int iMode);
+	
+	/**
+	 * Stub; Returns 0
+	 * 
+	 * @return 0
+	 */
+	public int GetAutoOffset() {
+	    return 0;
+	}
+	
+	/**
+	 * Draws a square aligned to the y axis and between given y co-ordinates
+	 * 
+	 * @param iDasherMin Bottom y co-ordinate
+	 * @param iDasherMax Top y co-ordinate
+	 * @param bActive Affects colouring
+	 */
+	public abstract void NewDrawGoTo(long iDasherMin, long iDasherMax, boolean bActive);
+	
+	/**
+	 * Gets our current screen
+	 * 
+	 * @return Current screen
+	 */
+	public CDasherScreen Screen() {
+	    return m_Screen;
+	}
+	
+	/**
+	 * Stub
+	 *
+	 */
+	public void ResetSum() {
+	}
+	
+	/**
+	 * Stub
+	 *
+	 */
+	public void ResetSumCounter() {
+	}
+	
+	/**
+	 * Stub
+	 *
+	 */
+	public void ResetYAutoOffset() {
+	}
+	
+	/**
+	 * Applies auto speed control given the user's current input
+	 * position in Dasher co-ordinates.
+	 * 
+	 * @param iDasherX x co-ordinate
+	 * @param iDasherY y co-ordinate
+	 * @param dFrameRate Current frame rate in FPS
+	 */
+	public void SpeedControl(long iDasherX, long iDasherY, double dFrameRate) {};
+	
+	/**
+	 * Applies any desired co-ordinate nonlinearity in the X direction.
+	 * <p>
+	 * Both input and output are co-ordinates in Dasher space.
+	 * <p>
+	 * Returns 0 in this base class; must be overridden if used.
+	 * 
+	 * @param x raw X co-ordinate
+	 * @return New x co-ordinate
+	 */
+	public double applyXMapping(double x) {return 0.0;};   
+	
+	/**
+	 * Applies any desired co-ordinate nonlinearity in the Y direction.
+	 * <p>
+	 * Both input and output are co-ordinates in Dasher space.
+	 * <p>
+	 * Returns 0 in this base class; must be overridden if used.
+	 * 
+	 * @param x raw Y co-ordinate
+	 * @return New y co-ordinate
+	 */
+	public double ymap(double x) {return 0.0;}; 
+	
+	/**
+	 * Returns a rectangle indicating the area in Dasher space
+	 * which is current visible.
+	 * 
+	 * @return Visible region
+	 */
+	public abstract CDasherView.DRect VisibleRegion();
+	
+	/**
+	 * Draws the crosshair
+	 * 
+	 * @param sx X co-ordinate at which to draw the crossbeam
+	 */
+	protected abstract void Crosshair(long sx);
+	
+	// Old screen-to-dasher and vice versa mappings.
+	
+	/*public CDasherView.Point MapScreen(int DrawX, int DrawY) {
+		
+		CDasherView.Point retval = new CDasherView.Point();
+		
+		retval.x = DrawX;
+		retval.y = DrawY;
+		
+		switch (realOrientation) {
+		case (Opts.ScreenOrientations.LeftToRight):
+			break;
+		case (Opts.ScreenOrientations.RightToLeft):
+			retval.x = Screen().GetWidth() - retval.x;
+		break;
+		case (Opts.ScreenOrientations.TopToBottom):{
+			int Swapper = (retval.x * Screen().GetHeight()) / Screen().GetWidth();
+			retval.x = (DrawY * Screen().GetWidth()) / Screen().GetHeight();
+			retval.y = Swapper;
+			break;
+		}
+		case (Opts.ScreenOrientations.BottomToTop):{
+			// Note rotation by 90 degrees not reversible like others
+			int Swapper = Screen().GetHeight() - (retval.x * Screen().GetHeight()) / Screen().GetWidth();
+			retval.x = (retval.y * Screen().GetWidth()) / Screen().GetHeight();
+			retval.y = Swapper;
+			break;
+		}
+		default:
+			break;
+		}
+		return retval;
+	}*/
+	
+	/*public void UnMapScreen(int MouseX, int MouseY) {
+				
+		CDasherView.Point retval = new CDasherView.Point();
+		retval.x = MouseX;
+		retval.y = MouseY;
+		
+		switch (realOrientation) {
+		case (Opts.ScreenOrientations.LeftToRight):
+			break;
+		case (Opts.ScreenOrientations.RightToLeft):
+			retval.x = Screen().GetWidth() - retval.x;
+			break;
+		case (Opts.ScreenOrientations.TopToBottom):{
+			int Swapper = (retval.x * Screen().GetHeight()) / Screen().GetWidth();
+			retval.x = (retval.y * Screen().GetWidth()) / Screen().GetHeight();;
+			retval.y = Swapper;
+			break;
+		}
+		case (Opts.ScreenOrientations.BottomToTop):{
+			int Swapper = (retval.x * Screen().GetHeight()) / Screen().GetWidth();
+			retval.x = ((Screen().GetHeight() - retval.y) * Screen().GetWidth()) / Screen().GetHeight();
+			retval.y = Swapper;
+			break;
+		}
+		default:
+			break;
+		}
+	}*/
+}

Added: trunk/java/dasher/CDasherViewSquare.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CDasherViewSquare.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,1422 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * An implementation (currently the one and only) of DasherView.
+ * <p>
+ * This draws all DasherNodes as a square aligned to the Y axis
+ * and with sizes dependent on their probability.
+ * <p>
+ * The horizontal and vertical scales are both subject to non-linearity;
+ * the x axis is linear at first and logarithmic after a given
+ * point, and the y axis is linear in all places but with different
+ * decreasing magnification factors towards the edges.
+ */
+public class CDasherViewSquare extends CDasherView {
+
+	/**
+	 * Helper class which applies and unapplies the y-axis
+	 * non-linearity.
+	 */
+	protected class Cymap {
+		
+		/**
+		 * Compression factor
+		 */
+		protected long m_Y1;
+		
+		/**
+		 * Y co-ordinate above which to apply compression
+		 */
+		protected long m_Y2;
+		
+		/**
+		 * Y co-ordinate below which to apply compression
+		 */
+		protected long m_Y3;
+		
+		/**
+		 * Calculates m_Y1, 2 and 3 based on the total length
+		 * of the y axis and hard coded scaling factors which
+		 * state that objects should be scaled down a factor
+		 * of 4 when within 5% of the outer edges.
+		 * 
+		 * @param iScale Total y-axis length
+		 */
+		public Cymap(long iScale) {
+			double dY1 = 0.25;
+			double dY2 = 0.95;
+			double dY3 = 0.05;
+			
+			m_Y2 = (long)(dY2 * iScale);
+			m_Y3 = (long)(dY3 * iScale);
+			m_Y1 = (long)(1.0 / dY1);
+		}
+		
+		/**
+		 * Converts a y co-ordinate according to this schema
+		 * 
+		 * @param y Raw y co-ordinate
+		 * @return Converted y co-ordinate
+		 */
+		public long map(long y) {
+			if(y > m_Y2)
+				return m_Y2 + (y - m_Y2) / m_Y1;
+			else if(y < m_Y3)
+				return m_Y3 + (y - m_Y3) / m_Y1;
+			else
+				return y;
+		}
+		
+		/**
+		 * Restores a y co-ordinate by unapplying non-linearity
+		 * 
+		 * @param ydash Converted y co-ordinate
+		 * @return Original, raw y co-ordinate
+		 */
+		public long unmap(long ydash) {
+			if(ydash > m_Y2)
+				return (ydash - m_Y2) * m_Y1 + m_Y2;
+			else if(ydash < m_Y3)
+				return (ydash - m_Y3) * m_Y1 + m_Y3;
+			else
+				return ydash;
+		}
+	}
+	
+	/**
+	 * Small class for returning dashery2screen values, which
+	 * compute two new y co-ordinates and a size attribute.
+	 */
+	class D2Yret {
+		/**
+		 * y co-ordinate 1
+		 */
+		int s1;
+		/**
+		 * y co-ordinate 2
+		 */
+		int s2;
+		/**
+		 * Size
+		 */
+		int size;
+	}
+	
+	/**
+	 * Scale factor applied to the logarithmic portion of the
+	 * x-axis nonlinearity. Formerly known as m_dXmpa.
+	 */
+	protected double m_dXMappingLogarithmicScaleFactor;
+	
+	/**
+	 * X co-ordinate at which we switch from linear to logarithmic
+	 * magnification. Formerly known as m_dXmpb.
+	 */
+	protected double m_dXMappingLogLinearBoundary;
+	
+	/**
+	 * Scale factor applied to the linear portion of the 
+	 * x-axis nonlinearity. Formerly known as m_dXmpc.
+	 */	
+	protected double m_dXMappingLinearScaleFactor;
+		
+	/**
+	 * Height of our current screen in pixels
+	 */
+	protected int CanvasY;
+	
+	/**
+	 * Nominally an offset which will be auto-calibrated
+	 * and applied to input co-ordinates. At present this is
+	 * always zero.
+	 */	
+	protected int m_yAutoOffset;
+	
+	/**
+	 * Helper for y mapping.
+	 */
+	protected Cymap m_ymap;
+	
+	
+	// Cached values for scaling
+	/**
+	 * Cached values for scaling
+	 */
+	protected long iLRScaleFactorX;
+	
+	/**
+	 * Cached values for scaling
+	 */
+	protected long iLRScaleFactorY;
+	
+	/**
+	 * Cached values for scaling
+	 */
+	protected long iTBScaleFactorX;
+	
+	/**
+	 * Cached values for scaling
+	 */
+	protected long iTBScaleFactorY;
+	
+	/**
+	 * The factor that scale factors are multipled by
+	 */  
+	protected long m_iScalingFactor;
+	
+	/**
+	 * Top-left corner of the current visible region
+	 */
+	protected CDasherView.DPoint m_iDasherMin;
+	
+	/**
+	 * Bottom-right corner of the current visible region
+	 */
+	protected CDasherView.DPoint m_iDasherMax;
+	
+	/**
+	 * Cache of LP_TRUNCATION
+	 */
+	protected int lpTruncation;
+	
+	/**
+	 * Cache of LP_TRUNCATION_TYPE
+	 */
+	protected int lpTruncationType;
+	
+	/**
+	 * Cache of LP_NORAMLIZATON
+	 */
+	protected int lpNormalisation;
+	
+	/**
+	 * Sole constructor. Creates a new view wrapping a specified
+	 * screen, fires the ChangeScreen method to configure itself
+	 * around said screen, creates a DelayedDraw object for
+	 * String drawing, preloads our cached parameter values
+	 * and sets certain hard-coded scaling factors, such as those
+	 * used in the x-axis nonlinearity.
+	 * <p>
+	 * The specific values at present are:
+	 * <p>
+	 * Multiply all linear scaled values by 0.9, switch to logarithmic
+	 * scaling from the midpoint of the axis, and multiply all log
+	 * scaled values by 0.2.
+	 * 
+	 * @param EventHandler Event handler with which to register ourselves
+	 * @param SettingsStore Settings repository to use
+	 * @param DasherScreen Screen to wrap and use for primitive drawing
+	 */
+	public CDasherViewSquare(CEventHandler EventHandler, CSettingsStore SettingsStore, CDasherScreen DasherScreen)  {
+		
+		super(EventHandler, SettingsStore, DasherScreen);
+		
+		 m_iDasherMin = new CDasherView.DPoint();
+		 m_iDasherMax = new CDasherView.DPoint();
+		
+		// TODO - AutoOffset should be part of the eyetracker input filter
+		// Make sure that the auto calibration is set to zero berfore we start
+		
+		m_yAutoOffset = 0;
+		
+		m_DelayDraw = new CDelayedDraw();
+		ChangeScreen(DasherScreen);
+		
+		// TODO - Make these parameters
+		// tweak these if you know what you are doing
+		m_dXMappingLogarithmicScaleFactor = 0.2;                // these are for the x non-linearity
+		m_dXMappingLogLinearBoundary = 0.5;
+		m_dXMappingLinearScaleFactor = 0.9;
+				
+		m_ymap = new Cymap(lpMaxY);
+		
+		m_bVisibleRegionValid = false;
+		
+		lpTruncation = (int)SettingsStore.GetLongParameter(Elp_parameters.LP_TRUNCATION);
+		lpTruncationType = (int)SettingsStore.GetLongParameter(Elp_parameters.LP_TRUNCATIONTYPE);
+		lpNormalisation = (int)SettingsStore.GetLongParameter(Elp_parameters.LP_NORMALIZATION);
+		
+		// These results are cached to make co-ordinate transformations quicker.
+		// We ought not to be caught out, as I have registered the class
+		// to watch for changes to these parameters.
+		
+	}
+	
+	/**
+	 * Method is called by the EventHandler when dispatching
+	 * events.
+	 * <p>
+	 * This class responds to the follow parameter-change events:
+	 * <p>
+	 * <i>LP_REAL_ORIENTATION</i>: Invalidates our current visible region.
+	 * <p>
+	 * <i>LP_TRUNCATION, LP_TRUNCATION_TYPE, LP_NORMALIZATION</i>:
+	 * Updates internally cached values of these parameters.
+	 */
+	public void HandleEvent(CEvent Event) {
+		// Let the parent class do its stuff
+		super.HandleEvent(Event);
+		
+		// And then interpret events for ourself
+		if(Event.m_iEventType == 1) {
+			CParameterNotificationEvent Evt = (CParameterNotificationEvent)Event;
+			
+			if (Evt.m_iParameter == Elp_parameters.LP_REAL_ORIENTATION) {
+				m_bVisibleRegionValid = false;
+			}
+			else if (Evt.m_iParameter == Elp_parameters.LP_TRUNCATION) {
+				lpTruncation = (int)GetLongParameter(Elp_parameters.LP_TRUNCATION);
+			}
+			else if (Evt.m_iParameter == Elp_parameters.LP_TRUNCATIONTYPE) {
+				lpTruncationType = (int)GetLongParameter(Elp_parameters.LP_TRUNCATIONTYPE);
+			}
+			else if (Evt.m_iParameter == Elp_parameters.LP_NORMALIZATION) {
+				lpNormalisation = (int)GetLongParameter(Elp_parameters.LP_NORMALIZATION);
+			}
+		}
+	}
+	
+	/**
+	 * Draws a tree of nodes beginning at a given root.
+	 * <p>
+	 * This function will call our screen's Blank method, and then call
+	 * RecursiveRender on the Node we wish to draw. Once the RecursiveRender
+	 * is finished, it will call m_DelayDraw's Draw method to draw
+	 * all strings which have been queued up.
+	 * <p>
+	 * Finally, it will draw the Crosshair.
+	 * 
+	 * @param Root Node at which to begin drawing
+	 * @param iRootMin Bottom co-ordinate of the root node (in Dasher space)
+	 * @param iRootMax Top co-ordinate of the root node (in Dasher space)
+	 * @param vNodeList Collection which will be filled with drawn Nodes
+	 * @param vDeleteList Collection which will be filled with undrawable Nodes
+	 */
+	public void RenderNodes(CDasherNode Root, long iRootMin, long iRootMax, Collection<CDasherNode> vNodeList, Collection<CDasherNode> vDeleteList) {
+		
+		Screen().Blank();
+		
+		CDasherView.DRect visreg = VisibleRegion();
+		
+		try  {
+			RecursiveRender(Root, iRootMin, iRootMax, (int)visreg.maxX, vNodeList, vDeleteList);
+		}
+		catch(NodeCannotBeDrawnException e) {
+			// Do nothing
+		}
+		
+		// DelayDraw the text nodes
+		m_DelayDraw.Draw(Screen());
+		
+		Crosshair(GetLongParameter(Elp_parameters.LP_OX));  // add crosshair
+	}
+	
+	
+	/* CSFS: Heavily modified to get the new mostleft value out. I'm fairly sure this
+	 * obeys the same semantics as the C++ version but this needs to be tested.
+	 */
+	
+	/**
+	 * Recursively renders a tree of Nodes beginning at a given root, based on the following procedure:
+	 * <p>
+	 * <ol><li>Calls RenderNode on this node, drawing it
+	 * <li>Calls RenderGroups on this node, drawing the grouping boxes for our children
+	 * <li>Recurses on each of our children in turn
+	 * </ol><p>
+	 * Of course, if our children are not yet present, we return
+	 * after step one.
+	 * <p>
+	 * This method also takes care of filling our Collections of drawable
+	 * and undrawable nodes, by catching NodeCannotBeDrawnExceptions in the latter
+	 * case.
+	 * <p>
+	 * 'Shoving,' the process which keeps a child node's text from overlapping
+	 * that of its parent, is also co-ordinated here; the new mostleft
+	 * value returned by RenderNode is passed into the recursive
+	 * calls which draw our children.
+	 * 
+	 * @param Render Node at which to begin rendering
+	 * @param y1 Top y co-ordinate of this Node
+	 * @param y2 Bottom y co-ordinate of this Node
+	 * @param mostleft Shoving parameter; see above
+	 * @param vNodeList Collection to fill with drawn, childless Nodes
+	 * @param vDeleteList Collection to fill with undrawable Nodes
+	 */
+	public void RecursiveRender(CDasherNode Render, long y1, long y2, int mostleft, Collection<CDasherNode> vNodeList, Collection<CDasherNode> vDeleteList) throws NodeCannotBeDrawnException {
+		
+		// This method takes mostleft by VALUE.
+		
+		/* Step 1: Render *this* node */
+		try {
+		
+		mostleft = RenderNode(Render.Colour(), Render.ColorScheme(), y1, y2, mostleft, Render.m_strDisplayText, Render.m_bShove);
+			
+		}
+		/* If this node was not drawable, mark it for deletion */
+		catch(NodeCannotBeDrawnException e) {
+			vDeleteList.add(Render);
+			Render.Kill();
+			return;
+		}
+						
+		/* If this node hasn't any children (yet), we're done */
+		if(Render.ChildCount() == 0) {
+			vNodeList.add(Render);
+			return;
+		}
+		
+		// Render groups
+		/* Step 2: Render the large grouping boxes to which this node's
+		 * children belong. For example, draw the yellow box for the
+		 * capitals.
+		 */
+		RenderGroups(Render, y1, y2, mostleft);
+		
+		/* Step 3: Draw our child nodes */
+		int norm = lpNormalisation;
+		
+		for(CDasherNode i : Render.GetChildren()) {
+			
+			long Range = y2 - y1;
+			long newy1 = y1 + (Range * i.Lbnd()) / norm;
+			long newy2 = y1 + (Range * i.Hbnd()) / norm;
+			
+			// FIXME - make the threshold a parameter
+			
+			if((newy2 - newy1 > 50) || (i.Alive())) {
+				i.Alive(true);
+				RecursiveRender(i, newy1, newy2, mostleft, vNodeList, vDeleteList);
+				
+			}
+		}
+	}
+	
+	/* CSFS: Modified to return mostleft. */
+	
+	/**
+	 * Draws a given Node's grouping boxes, into which its Children
+	 * are arranged. The simply calls RecursiveRenderGroups on each top-level
+	 * group in turn, which does the actual drawing.
+	 * 
+	 * @param Render Node whose grouping boxes we wish to draw
+	 * @param y1 Top y co-ordinate of this Node
+	 * @param y2 Bottom y co-ordinate of this Node
+	 * @param mostleft Shoving parameter; indicates how far group labels should be displaced
+	 * to the right in order to avoid overlapping parents' text.
+	 */
+	public void RenderGroups(CDasherNode Render, long y1, long y2, int mostleft) {
+		
+		// This method takes mostleft by VALUE.
+		
+		SGroupInfo CurrentGroup = (Render.m_BaseGroup);
+		
+		while(CurrentGroup != null) {
+			RecursiveRenderGroups(CurrentGroup, Render, y1, y2, mostleft);
+			CurrentGroup = CurrentGroup.Next;
+		}
+	}
+	
+	/**
+	 * Renders a given Group and all of its child groups by recursion.
+	 * <p>
+	 * RenderNode is used to do the actual work of drawing the group
+	 * boxes, and their sizes are determined by consulting the
+	 * child list which this group delimits. 
+	 * 
+	 * @param CurrentGroup Group at which to start drawing
+	 * @param Node Node of which this group is a child
+	 * @param y1 Top Dasher co-ordinate of this group
+	 * @param y2 Bottom Dasher co-ordinate of this group
+	 * @param mostleft Shoving parameter; indicates how far group labels should be displaced
+	 * to the right in order to avoid overlapping parents' text.
+	 */	
+	public void RecursiveRenderGroups(SGroupInfo CurrentGroup, CDasherNode Node, long y1, long y2, int mostleft) {
+		
+		// This method takes mostleft by VALUE.
+		
+		if(CurrentGroup.bVisible) {
+			long range = y2 - y1;
+			
+			int lower = (CurrentGroup.iStart);
+			int upper = (CurrentGroup.iEnd);
+			
+			long lbnd = Node.Children().get(lower).Lbnd();
+			long hbnd = Node.Children().get(upper - 1).Hbnd();
+			
+			long newy1 = y1 + (range * lbnd) / lpNormalisation;
+			long newy2 = y1 + (range * hbnd) / lpNormalisation;
+			try {
+				mostleft = RenderNode(CurrentGroup.iColour, EColorSchemes.Groups, newy1, newy2, mostleft, CurrentGroup.strLabel, true);
+			}
+			catch(NodeCannotBeDrawnException e) {
+				// Do nothing
+			}
+			
+		}
+		
+		// Iterate through child groups
+		SGroupInfo CurrentChild = (CurrentGroup.Child);
+		
+		while(CurrentChild != null) {
+			RecursiveRenderGroups(CurrentChild, Node, y1, y2, mostleft);
+			CurrentChild = CurrentChild.Next;
+		}
+	}
+	
+	
+	
+	/**
+	 * Determines whether a given Node can be drawn, and if so, draws it.
+	 * <p>
+	 * If the Node is undrawable because it's off the screen
+	 * or is too small to sensibly draw, a NodeCannotBeDrawnException
+	 * is thrown.
+	 * <p>
+	 * The drawing instruction is clipped to the visible region first,
+	 * so the Screen should not be ordered to draw anything outside
+	 * its bounds.
+	 * <p>
+	 * If truncation is enabled, it is applied here; if not, we
+	 * simply call DasherDrawRectangle to form the Node box.
+	 * <p>
+	 * Lastly, the Node's text is added to m_DelayDraw to be
+	 * drawn to the screen at the end of the drawing sequence.
+	 * <p>
+	 * This also generates a new mostleft value for shoving purposes,
+	 * which is returned to our caller.
+	 * 
+	 * @param Color Colour index to use for the node's background
+	 * @param ColorScheme ColourScheme to use; usually ignored in favour of a colour index
+	 * @param y1 Top y co-ordinate of this Node (Dasher space)
+	 * @param y2 Bottom y co-ordinate of this Node (Dasher space)
+	 * @param mostleft Shoving parameter; indicates how far node labels should be displaced
+	 * to the right in order to avoid overlapping parents' text.
+	 * @param sDisplayText Text to draw in this Node
+	 * @param bShove Should we shove (report how far our text juts out, 
+	 * to help our caller avoid overlapping it)
+	 * @return New value of mostleft (or that which was passed in, if we
+	 * do not) 
+	 * @throws NodeCannotBeDrawnException if this Node cannot be drawn!
+	 */
+	public int RenderNode(int Color, EColorSchemes ColorScheme, long y1, long y2, int mostleft, String sDisplayText, boolean bShove) throws NodeCannotBeDrawnException {
+		
+		/*
+		 * IMPORTANT: This method takes mostleft by REFERENCE in the original
+		 * C++; as such it returns its new value here.
+		 */
+		
+		if (!(y2 >= y1)) { return mostleft; }
+		
+		// TODO - Get sensible limits here (to allow for non-linearities)
+		CDasherView.DRect visreg = VisibleRegion();
+		
+		// TODO - use new versions of functions
+		
+		//int top = Dasher2Screen(0, y1).y;
+		//int bottom = Dasher2Screen(0, y2).y; 
+		long iSize = m_ymap.map(y2) - m_ymap.map(y1);
+		
+		// Actual height in pixels
+		int iHeight = (int)((iSize * CanvasY) / (int) lpMaxY);
+		
+		if(iHeight <= 1)
+			{ throw new NodeCannotBeDrawnException(); }                  // We're too small to render
+		
+		if((y1 > visreg.maxY) || (y2 < visreg.minY)){
+			{ throw new NodeCannotBeDrawnException(); }                // We're entirely off screen, so don't render.
+		}
+		
+		long iDasherSize = (y2 - y1);
+		
+		// FIXME - get rid of pointless assignment below
+		
+		if(lpTruncation == 0) {        // Regular squares
+			DasherDrawRectangle(Math.min(iDasherSize,visreg.maxX), Math.min(y2,visreg.maxY), 0, Math.max(y1,visreg.minY), Color, -1, ColorScheme, GetBoolParameter(Ebp_parameters.BP_OUTLINE_MODE), true, 1);
+		}
+		else {
+			int iDasherY = (int)lpMaxY;
+			
+			int iSpacing = iDasherY / 128;       // FIXME - assuming that this is an integer below
+			
+			int iXStart = 0;
+			
+			switch (lpTruncationType) {
+			case 1:
+				iXStart = (int)(iSize - iSize * lpTruncation / 200);
+				break;
+			case 2:
+				iXStart = (int)(iSize - iSize * lpTruncation / 100);
+				break;
+			}
+			
+			int iTipMin = (int)((y2 - y1) * lpTruncation / (200) + y1);
+			int iTipMax = (int)(y2 - (y2 - y1) * lpTruncation / (200));
+			
+			int iLowerMin = (int)(((y1 + 1) / iSpacing) * iSpacing);
+			int iLowerMax = (((iTipMin - 1) / iSpacing) * iSpacing);
+			
+			int iUpperMin = (((iTipMax + 1) / iSpacing) * iSpacing);
+			int iUpperMax = (int)(((y2 - 1) / iSpacing) * iSpacing);
+			
+			if(iLowerMin < 0)
+				iLowerMin = 0;
+			
+			if(iLowerMax < 0)
+				iLowerMax = 0;
+			
+			if(iUpperMin < 0)
+				iUpperMin = 0;
+			
+			if(iUpperMax < 0)
+				iUpperMax = 0;
+			
+			if(iLowerMin > iDasherY)
+				iLowerMin = iDasherY;
+			
+			if(iLowerMax > iDasherY)
+				iLowerMax = iDasherY;
+			
+			if(iUpperMin > iDasherY)
+				iUpperMin = iDasherY;
+			
+			if(iUpperMax > iDasherY)
+				iUpperMax = iDasherY;
+			
+			while(iLowerMin < y1)
+				iLowerMin += iSpacing;
+			
+			while(iLowerMax > iTipMin)
+				iLowerMax -= iSpacing;
+			
+			while(iUpperMin < iTipMax)
+				iUpperMin += iSpacing;
+			
+			while(iUpperMax > y2)
+				iUpperMax -= iSpacing;
+			
+			int iLowerCount = ((iLowerMax - iLowerMin) / iSpacing + 1);
+			int iUpperCount = ((iUpperMax - iUpperMin) / iSpacing + 1);
+			
+			if(iLowerCount < 0)
+				iLowerCount = 0;
+			
+			if(iUpperCount < 0)
+				iUpperCount = 0;
+			
+			int iTotalCount = (int)(iLowerCount + iUpperCount + 6);
+			
+			long[] x = new long[iTotalCount];
+			long[] y = new long[iTotalCount];
+			
+			// Weird duplication here is to make truncated squares possible too
+			
+			x[0] = 0;
+			y[0] = y1;
+			x[1] = iXStart;
+			y[1] = y1;
+			
+			x[iLowerCount + 2] = iDasherSize;
+			y[iLowerCount + 2] = iTipMin;
+			x[iLowerCount + 3] = iDasherSize;
+			y[iLowerCount + 3] = iTipMax;
+			
+			x[iTotalCount - 2] = iXStart;
+			y[iTotalCount - 2] = y2;
+			x[iTotalCount - 1] = 0;
+			y[iTotalCount - 1] = y2;
+			
+			for(int i = (0); i < iLowerCount; ++i) {
+				x[i + 2] = (iLowerMin + i * iSpacing - y1) * (iDasherSize - iXStart) / (iTipMin - y1) + iXStart;
+				y[i + 2] = iLowerMin + i * iSpacing;
+			}
+			
+			for(int j = (0); j < iUpperCount; ++j) {
+				x[j + iLowerCount + 4] = (y2 - (iUpperMin + j * iSpacing)) * (iDasherSize - iXStart) / (y2 - iTipMax) + iXStart;
+				y[j + iLowerCount + 4] = iUpperMin + j * iSpacing;
+			}
+			
+			DasherPolygon(x, y, iTotalCount, Color);
+			
+		}
+		
+		long iDasherAnchorX = (iDasherSize);
+		
+		if( sDisplayText != null && sDisplayText.length() > 0 )
+			mostleft = (int)DasherDrawText(iDasherAnchorX, y1, iDasherAnchorX, y2, sDisplayText, mostleft, bShove);
+		
+		/* CSFS: Method altered to use a Byte ArrayList for UTF-8 characters instead of a String. */
+		
+		{ return mostleft; }
+	}
+
+	
+	/**
+	 * Determines whether a node falls within our current visible
+	 * region. This is determined by the simple expedient of calling
+	 * VisibleRegion and comparing the passed co-ordinates.
+	 * 
+	 *  @param y1 Node's top y co-ordinate
+	 *  @param y2 Node's bottom y co-ordinate
+	 *  @return True if falls within visible region, False otherwise
+	 */
+	public boolean IsNodeVisible(long y1, long y2) {
+		
+		CDasherView.DRect visreg = VisibleRegion();
+		
+		return (y1 > visreg.minY) || (y2 < visreg.maxY ) || (y2-y1 < visreg.maxX);
+	}
+	
+	/** 
+	 * Convert screen co-ordinates to dasher co-ordinates. This doesn't
+	 * include the nonlinear mapping for eyetracking mode etc - it is
+	 * just the inverse of the mapping used to calculate the screen
+	 * positions of boxes etc.
+	 * 
+	 * @param iInputX Screen x co-ordinate
+	 * @param iInputY Screen y co-ordinate
+	 * @param b1D Should we use a simpler transform
+	 * for 1D devices?
+	 * @param bNonlinearity Should we use unapplyXMapping and m_ymap.unmap
+	 * to reverse an applied nonlinearity?
+	 * @return Point in Dasher space equivalent to the given Screen point
+	 */	
+	public CDasherView.DPoint Screen2Dasher(int iInputX, int iInputY, boolean b1D, boolean bNonlinearity) {
+		
+		// Things we're likely to need:
+		
+		/* CSFS: Replacement return value since the C++ version uses pass-by-ref */
+		
+		CDasherView.DPoint retval = new CDasherView.DPoint();
+		
+		long iDasherWidth = lpMaxY;
+		long iDasherHeight = lpMaxY;
+		
+		int iScreenWidth = Screen().GetWidth();
+		int iScreenHeight = Screen().GetHeight();
+		
+		if( b1D ) { // Special case for 1D mode...
+			retval.x = iInputX * iDasherWidth / iScreenWidth;
+			retval.y = iInputY * iDasherHeight / iScreenHeight;
+			return retval;
+		}
+		
+		int eOrientation = realOrientation;
+		
+		long iScaleFactorX;
+		long iScaleFactorY;
+		
+		CDasherView.DPoint scale = GetScaleFactor(eOrientation); // FIXME
+		
+		iScaleFactorX = scale.x;
+		iScaleFactorY = scale.y;
+		
+		switch(eOrientation) {
+		case Opts.ScreenOrientations.LeftToRight:
+			retval.x = iDasherWidth / 2 - ( iInputX - iScreenWidth / 2 ) * m_iScalingFactor / iScaleFactorX;
+		retval.y = iDasherHeight / 2 + ( iInputY - iScreenHeight / 2 ) * m_iScalingFactor / iScaleFactorY;
+		break;
+		case Opts.ScreenOrientations.RightToLeft:
+			retval.x = (iDasherWidth / 2 + ( iInputX - iScreenWidth / 2 ) * m_iScalingFactor/ iScaleFactorX);
+		retval.y = (iDasherHeight / 2 + ( iInputY - iScreenHeight / 2 ) * m_iScalingFactor/ iScaleFactorY);
+		break;
+		case Opts.ScreenOrientations.TopToBottom:
+			retval.x = (iDasherWidth / 2 - ( iInputY - iScreenHeight / 2 ) * m_iScalingFactor/ iScaleFactorY);
+		retval.y = (iDasherHeight / 2 + ( iInputX - iScreenWidth / 2 ) * m_iScalingFactor/ iScaleFactorX);
+		break;
+		case Opts.ScreenOrientations.BottomToTop:
+			retval.x = (iDasherWidth / 2 + ( iInputY - iScreenHeight / 2 ) * m_iScalingFactor/ iScaleFactorY);
+		retval.y = (iDasherHeight / 2 + ( iInputX - iScreenWidth / 2 ) * m_iScalingFactor/ iScaleFactorX);
+		break;
+		}
+		
+		// FIXME - disabled to avoid floating point
+		if( bNonlinearity ) {
+			retval.x = (long)(unapplyXMapping(retval.x / (double)lpMaxY) * lpMaxY);
+			retval.y = (long)m_ymap.unmap(retval.y);
+		}
+		
+		return retval;
+	}
+	
+	/**
+	 * Computes a set of scaling factors for use in transforming
+	 * screen to Dasher co-ordinates and vice versa. This should
+	 * be re-run any time the Screen's height or width are liable
+	 * to have changed, or if we wish to change the size of the
+	 * Dasher world's co-ordinate space.
+	 */
+	public void SetScaleFactor()
+	{
+		long iDasherWidth = lpMaxY;
+		long iDasherHeight = iDasherWidth;
+		
+		int iScreenWidth = Screen().GetWidth();
+		int iScreenHeight = Screen().GetHeight();
+		
+		// Try doing this a different way:
+		
+		long iDasherMargin = ( 300 ); // Make this a parameter
+		
+		long iMinX = ( 0-iDasherMargin );
+		long iMaxX = ( iDasherWidth + iDasherMargin );
+		long iMinY = ( 0 );
+		long iMaxY = ( iDasherHeight );
+		
+		double dLRHScaleFactor;
+		double dLRVScaleFactor;
+		double dTBHScaleFactor;
+		double dTBVScaleFactor;
+		
+		dLRHScaleFactor = iScreenWidth / (double)( iMaxX - iMinX );
+		dLRVScaleFactor = iScreenHeight / (double)( iMaxY - iMinY );
+		dTBHScaleFactor = iScreenWidth / (double)( iMaxY - iMinY );
+		dTBVScaleFactor = iScreenHeight / (double)( iMaxX - iMinX );
+		
+		iLRScaleFactorX = (long)(Math.max(Math.min(dLRHScaleFactor, dLRVScaleFactor), dLRHScaleFactor / 4.0) * m_iScalingFactor);
+		iLRScaleFactorY = (long)(Math.max(Math.min(dLRHScaleFactor, dLRVScaleFactor), dLRVScaleFactor / 4.0) * m_iScalingFactor);
+		iTBScaleFactorX = (long)(Math.max(Math.min(dTBHScaleFactor, dTBVScaleFactor), dTBVScaleFactor / 4.0) * m_iScalingFactor);
+		iTBScaleFactorY = (long)(Math.max(Math.min(dTBHScaleFactor, dTBVScaleFactor), dTBHScaleFactor / 4.0) * m_iScalingFactor);
+	}
+	
+	/**
+	 * Retrieves the x and y scaling factors relevant to our
+	 * current orientation -- so iLRScaleFactorX and Y if we're
+	 * in LeftToRight or RightToLeft modes, or their TB equivalents
+	 * otherwise.
+	 * 
+	 * @param eOrientation Current orientation
+	 * @return Dasher-world co-ordinate containing the width scaling
+	 * factor as its x, and the height factor as its y.
+	 */
+	public CDasherView.DPoint GetScaleFactor(int eOrientation) {
+		CDasherView.DPoint retval = new CDasherView.DPoint();
+		
+		if(( eOrientation == Opts.ScreenOrientations.LeftToRight ) || ( eOrientation == Opts.ScreenOrientations.RightToLeft )) {
+			retval.x = iLRScaleFactorX;
+			retval.y = iLRScaleFactorY;
+		} else {
+			retval.x = iTBScaleFactorX;
+			retval.y = iTBScaleFactorY;
+		}
+		
+		return retval;
+	}
+	
+	/**
+	 * Converts Dasher co-ordinates to the Screen co-ordinate
+	 * indicating the same location.
+	 * <p>
+	 * Applies non-linearities to the Dasher co-ordinates using
+	 * applyXMapping and m_ymap.map, before scaling appropriate
+	 * to our current screen orientation.
+	 * 
+	 * @param iDasherX Dasher x co-ordinate
+	 * @param iDasherY Dasher y co-ordinate
+	 * @return Screen point corresponding to this location
+	 */
+	public CDasherView.Point Dasher2Screen(long iDasherX, long iDasherY) {
+		
+		CDasherView.Point retval = new CDasherView.Point();
+		// Apply the nonlinearities
+		
+		
+		// FIXME
+		iDasherX = (long)(applyXMapping(iDasherX / (double)(lpMaxY)) * lpMaxY);
+		iDasherY = m_ymap.map(iDasherY);
+		
+		
+		// Things we're likely to need:
+		
+		long iDasherWidth = lpMaxY;
+		long iDasherHeight = lpMaxY;
+		
+		int iScreenWidth = Screen().GetWidth();
+		int iScreenHeight = Screen().GetHeight();
+		
+		long iScaleFactorX;
+		long iScaleFactorY;
+		
+		CDasherView.DPoint scale = GetScaleFactor(realOrientation);
+		iScaleFactorX = scale.x;
+		iScaleFactorY = scale.y;
+		
+		switch( realOrientation ) {
+		case Opts.ScreenOrientations.LeftToRight:
+			retval.x = (int)(iScreenWidth / 2 - ( iDasherX - iDasherWidth / 2 ) * iScaleFactorX / m_iScalingFactor);
+			retval.y = (int)(iScreenHeight / 2 + ( iDasherY - iDasherHeight / 2 ) * iScaleFactorY / m_iScalingFactor);
+		break;
+		case Opts.ScreenOrientations.RightToLeft:
+			retval.x = (int)(iScreenWidth / 2 + ( iDasherX - iDasherWidth / 2 ) * iScaleFactorX / m_iScalingFactor);
+			retval.y = (int)(iScreenHeight / 2 + ( iDasherY - iDasherHeight / 2 ) * iScaleFactorY / m_iScalingFactor);
+		break;
+		case Opts.ScreenOrientations.TopToBottom:
+			retval.x = (int)(iScreenWidth / 2 + ( iDasherY - iDasherHeight / 2 ) * iScaleFactorX / m_iScalingFactor);
+			retval.y = (int)(iScreenHeight / 2 - ( iDasherX - iDasherWidth / 2 ) * iScaleFactorY / m_iScalingFactor);
+		break;
+		case Opts.ScreenOrientations.BottomToTop:
+			retval.x = (int)(iScreenWidth / 2 + ( iDasherY - iDasherHeight / 2 ) * iScaleFactorX / m_iScalingFactor);
+			retval.y = (int)(iScreenHeight / 2 + ( iDasherX - iDasherWidth / 2 ) * iScaleFactorY / m_iScalingFactor);
+		break;
+		}
+		
+		return retval;
+	}
+	
+	/**
+	 * Produces a rectangle showing the region of Dasher space
+	 * which is currently visible on screen.
+	 * <p>
+	 * This is accomplished by the simple expedient of running
+	 * Screen2Dasher against the minimum and maximum screen
+	 * co-ordinates.
+	 * <p>
+	 * This function takes our current orientation into account
+	 * in producing its answer.
+	 * 
+	 * @return Rectangle indicating the visible region.
+	 */
+	public CDasherView.DRect VisibleRegion() {
+		
+		CDasherView.DRect retval = new CDasherView.DRect();
+				
+		if(!m_bVisibleRegionValid) {
+			
+					
+			switch( realOrientation ) {
+			case Opts.ScreenOrientations.LeftToRight:
+				m_iDasherMin = Screen2Dasher(Screen().GetWidth(),0,false,true);
+				m_iDasherMax = Screen2Dasher(0,Screen().GetHeight(),false,true);
+			break;
+			case Opts.ScreenOrientations.RightToLeft:
+				m_iDasherMin = Screen2Dasher(0,0,false,true);
+				m_iDasherMax = Screen2Dasher(Screen().GetWidth(),Screen().GetHeight(),false,true);
+			break;
+			case Opts.ScreenOrientations.TopToBottom:
+				m_iDasherMin = Screen2Dasher(0,Screen().GetHeight(),false,true);
+				m_iDasherMax = Screen2Dasher(Screen().GetWidth(),0,false,true);
+			break;
+			case Opts.ScreenOrientations.BottomToTop:
+				m_iDasherMin = Screen2Dasher(0,0,false,true);
+				m_iDasherMax = Screen2Dasher(Screen().GetWidth(),Screen().GetHeight(),false,true);
+			break;
+			}
+			
+			m_bVisibleRegionValid = true;
+		}
+		
+		retval.maxX = m_iDasherMax.x;
+		retval.maxY = m_iDasherMax.y;
+		retval.minX = m_iDasherMin.x;
+		retval.minY = m_iDasherMin.y;
+		
+		return retval;
+	}
+	
+
+	/* CSFS: Removed functions which returned a single aspect of the visible region;
+	 * it didn't seem any routine made use of them anymore.
+	 */
+
+	
+	/** 
+	 * Convert abstract 'input coordinates', which may or may not
+	 * correspond to actual screen positions, depending on the settings,
+	 * into dasher co-ordinates. Modes are:
+	 * <p>
+	 * 0 = Direct (ie mouse)<br>
+	 * 1 = 1D<br>
+	 * 2 = Eyetracker
+	 * <p>
+	 * This should be done once initially, then we work in Dasher
+	 * co-ordinates for everything else. Input co-ordinates will be
+	 * assumed to range over the extent of the screen.
+	 * <p>
+	 * Internally, we essentially
+	 * <ol><li>Apply m_yAutoOffset to the y co-ordinate if this is an Eyetracker
+	 * <li>Feed screen co-ordinates through Screen2Dasher with the
+	 * appropriate flags (1D and Nonlinear as necessary)
+	 * <li>Apply y co-ordinate scaling if this is a 1D device.
+	 * </ol>
+	 * 
+	 * @param iInputX Input x co-ordinate
+	 * @param iInputY Input y co-ordinate
+	 * @param iType 0 if input co-ordinates are in pixels
+	 * or 1 if in Dasher co-ordinates
+	 * @param iMode See table above
+	 * @return Dasher world point corresponding but not necessarily
+	 * in the same place as this input point.
+	 */
+	public CDasherView.DPoint Input2Dasher(int iInputX, int iInputY, int iType, int iMode) {
+		
+		// FIXME - need to incorporate one-button mode?
+		// First convert the supplied co-ordinates to 'linear' Dasher co-ordinates
+			
+		CDasherView.DPoint retval = new CDasherView.DPoint();
+		
+		switch (iType) {
+		case 0:
+			// Raw secreen coordinates
+			
+			// TODO - autocalibration should be at the level of the eyetracker filter
+			if(iMode == 2) {
+				// First apply the autocalibration offset
+				iInputY += (int) (m_yAutoOffset);   // FIXME - we need more flexible autocalibration to work with orientations other than left-to-right
+			}
+			
+			if( iMode == 0 )
+				retval = Screen2Dasher( iInputX, iInputY, false, true );
+			else if( iMode == 1 )
+				retval = Screen2Dasher( iInputX, iInputY, true, false );
+			else
+				retval = Screen2Dasher( iInputX, iInputY, false, true );
+			break;
+		case 1:
+			// Raw dasher coordinates
+			
+			retval.x = iInputX;
+			retval.y = iInputY;
+			break;
+		default:
+			// ERROR
+			break;
+		}
+		
+		// Apply y scaling
+		
+		// TODO: Check that this is still doing something vaguely sensible - I think it isn't
+		
+		if(iMode == 1 ) {
+			if( GetLongParameter(Elp_parameters.LP_YSCALE) > 0 ) {
+				
+				double dYScale;
+				
+				if(( realOrientation == Opts.ScreenOrientations.LeftToRight ) || ( realOrientation == Opts.ScreenOrientations.RightToLeft )) {
+					dYScale = Screen().GetHeight() / (double)(GetLongParameter(Elp_parameters.LP_YSCALE));
+				}
+				else {
+					dYScale = Screen().GetWidth() / (double)(GetLongParameter(Elp_parameters.LP_YSCALE));
+				}
+				
+				retval.y = (long)((retval.y - lpMaxY/2) * dYScale + lpMaxY/2);
+			}
+		}
+		
+		return retval;
+	}
+	
+
+	/**
+	 * Truncate a set of co-ordinates so that they are on the screen
+	 *   
+	 * @param iX Screen x co-ordinate
+	 * @param iY Screen y co-ordinate
+	 * @return Truncated point
+	 */
+	public CDasherView.Point TruncateToScreen(int iX, int iY) {
+		
+		// I think that this function is now obsolete
+		
+		CDasherView.Point retval = new CDasherView.Point();
+		
+		retval.x = iX;
+		retval.y = iY;
+		
+		if(iX < 0)
+			retval.x = 0;
+		if(iX > Screen().GetWidth())
+			retval.x = Screen().GetWidth();
+			
+			if(iY < 0)
+				retval.y = 0;
+			if(iY > Screen().GetHeight())
+				retval.y = Screen().GetHeight();
+		
+		return retval;
+	}
+	
+	/**
+	 * Calls getInputDasherCoords(mousex, mousey, null)
+	 */
+	public CDasherView.DPoint getInputDasherCoords() {
+		return getInputDasherCoords(null);
+	}
+	
+	/**
+	 * Gets the point in the Dasher world currently pointed
+	 * to by our input device.
+	 * <p>
+	 * Internally this boils down to calling GetCoordinates
+	 * with the appropriate flags and then feeding the results
+	 * through Input2Dasher.
+	 * @param Added Ignored, may be null
+	 */
+	public CDasherView.DPoint getInputDasherCoords(ArrayList<CSymbolProb> Added) {
+		
+		/* CSFS: int * parameter "pNumDeleted" removed as according to notes in
+		 * CDasherView.
+		 */ 	
+	
+		
+		// FIXME - rename this something more appropriate (all this really should do is convert the coordinates)
+		
+		// NOTE - we now ignore the values which are actually passed to the display
+		
+		// FIXME - Actually turn autocalibration on and off!
+		// FIXME - AutoCalibrate should use Dasher co-ordinates, not raw mouse co-ordinates?
+		// FIXME - Have I broken this by moving it before the offset is applied?
+		// FIXME - put ymap stuff back in 
+		
+		// FIXME - optimise this
+		
+		int iCoordinateCount = (GetCoordinateCount());
+		
+		long[] Coordinates = new long[iCoordinateCount];
+		
+		int iType = (GetCoordinates(iCoordinateCount, Coordinates));
+		
+		int mousex, mousey;
+		
+		if(iCoordinateCount == 1) {
+			mousex = 0;
+			mousey = (int)Coordinates[0];
+		}
+		else {
+			mousex = (int)Coordinates[0];
+			mousey = (int)Coordinates[1];
+		}
+		
+		// TODO: Mode probably isn't being used any more
+		
+		// Convert the input co-ordinates to dasher co-ordinates
+		
+		int mode;
+		
+		if(GetBoolParameter(Ebp_parameters.BP_NUMBER_DIMENSIONS))
+			mode = 1;
+		else if(GetBoolParameter(Ebp_parameters.BP_EYETRACKER_MODE))
+			mode = 2;
+		else
+			mode = 0;
+		
+		CDasherView.DPoint retval = Input2Dasher(mousex, mousey, iType, mode);
+		
+		/* CSFS: As well as extensive replacement of functions which used 
+		 * primitives by reference, I've removed code which saved co-ordinates
+		 * to m_iDasherXCache as it appears it never gets referenced.
+		 */
+		
+		return retval;
+	}
+	
+	/**
+	 * Draws a square highlighting the area between two given y co-ordinates.
+	 * <p>
+	 * Draws the square a different colour dependent on whether the
+	 * 'active' flag is specified.
+	 * <p>
+	 * At present the colours are hard-coded: Colour 1 is used with
+	 * a width of 3 for active, and colour 2 with a width of 1 for
+	 * inactive.
+	 * 
+	 * @param iDasherMin Bottom y co-ordinate at which to align the square
+	 * @param iDasherMax Top y co-ordinate at which to align the square
+	 * @param bActive Draw this square in 'active' style?
+	 */
+	public void NewDrawGoTo(long iDasherMin, long iDasherMax, boolean bActive) {
+		long iHeight = (iDasherMax - iDasherMin);
+		
+		int iColour;
+		int iWidth;
+		
+		if(bActive) {
+			iColour = 1;
+			iWidth = 3;
+		}
+		else {
+			iColour = 2;
+			iWidth = 1;
+		}
+		
+		CDasherView.Point[] p = new CDasherView.Point[4];
+		
+		p[0] = Dasher2Screen( 0, iDasherMin);
+		p[1] = Dasher2Screen( iHeight, iDasherMin);
+		p[2] = Dasher2Screen( iHeight, iDasherMax);
+		p[3] = Dasher2Screen( 0, iDasherMax);
+		
+		Screen().Polyline(p, 4, iWidth, iColour);
+	}
+	
+//	TODO: Autocalibration should be in the eyetracker filter class
+	
+	/* CSFS: There were two functions here called ResetSum and ResetSumCounter
+	 * I've removed them, their calls, and their relevant variables, since the
+	 * Eclipse asserted these variables were only ever set and so were useless.
+	 */
+	
+	/**
+	 * Sets m_yAutoOffset back to zero.
+	 */
+	public void ResetYAutoOffset() {
+		m_yAutoOffset = 0;
+	}
+	
+	/**
+	 * Sets a new screen, invalidates our current visible region,
+	 * and recalls SetScalingFactor, since the relationships between
+	 * Dasher and Screen co-ordinates may well have changed at this
+	 * point.
+	 * <p>
+	 * Also caches the Screen's current height in CanvasY.
+	 *
+	 * @param NewScreen New screen
+	 */
+	public void ChangeScreen(CDasherScreen NewScreen) {
+		m_Screen = NewScreen;
+		m_bVisibleRegionValid = false;
+		//int Width = Screen().GetWidth();
+		int Height = Screen().GetHeight();
+		//CanvasX = 9 * Width / 10;
+		// CanvasBorder = Width - CanvasX; REMOVED: redundant according to Eclipse.
+		CanvasY = Height;
+		m_iScalingFactor = 100000000;
+		SetScaleFactor();
+	}
+	
+	/**
+	 * Gets m_yAutoOffset, the y-coordinate screen offset to be applied
+	 * for eyetracker devices.
+	 */
+	public int GetAutoOffset() {
+		return m_yAutoOffset;
+	}
+	
+	/* CSFS: The following method had a large body but returned on its first
+	 * line. Presumably this is dead code; deleted and modified its only
+	 * calling routine so that it doesn't call it anymore.
+	 * 
+	public CDasherScreen.Point AutoCalibrate(int mousex, int mousey) {
+		return;
+	}
+
+	 */
+	
+	
+		
+	/* CSFS: Another method which was apparently dead: DrawGameModePointer. Again
+	 * I've edited out references to it.
+	 */
+
+	/**
+	 * Defers to m_ymap.map
+	 * 
+	 * @see Cymap
+	 */
+	public double ymap(double x) {
+		return m_ymap.map((long)x);
+	}
+	
+	
+	// INLINE FUNCTIONS (CDasherViewSquare.inl)
+	
+	// Redundant function; taken over by Dasher2Screen.
+	
+	/*public D2Yret dashery2screen(long y1, long y2, int s1, int s2) {
+
+		D2Yret retval = new D2Yret();
+
+		retval.s1 = s1;
+		retval.s2 = s2;
+
+		y1 = m_ymap.map(y1);
+		y2 = m_ymap.map(y2);
+
+		if(y1 > lpMaxY) {
+			retval.size = 0; return retval;
+		} if(y2 < 0) {
+			retval.size = 0; return retval;
+		}
+
+		if(y1 < 0)                  // "highest" legal coordinate to draw is 0.
+		{
+			y1 = 0;
+		}
+
+		// Is this square actually on the screen? Check bottom
+		if(y2 > lpMaxY)
+			y2 = lpMaxY;
+
+		retval.size = (int)(y2 - y1);
+
+		retval.s1 = (int)(y1 * CanvasY / lpMaxY);
+		retval.s2 = (int)(y2 * CanvasY / lpMaxY);
+
+		return retval;
+
+	}*/
+
+	/* CSFS: There used to be another version of dashery2screen accepting only one
+	 * long as an argument; however it seemed to be dead code and so I have removed
+	 * it.
+	 */
+
+	/// Draw the crosshair
+
+	/**
+	 * Draws the Crosshair, with the vertical bar at a specified
+	 * x co-ordinate and the horizontal bar halfway up the screen.
+	 * <p>
+	 * The horizontal bar is hard coded to run from 12/14(sx)
+	 * to 17/14(sx). This will cause trouble if sx is zero, and
+	 * there will be issues if sx is small since we're working
+	 * with integers, not floating point.
+	 * <p>
+	 * This method could do with being rewritten.
+	 * 
+	 * @param sx X co-ordinate for the vertical bar. Not zero, or
+	 * the horizontal bar will not correctly display at present.
+	 */
+	public void Crosshair(long sx) {
+		long[] x = new long[2];
+		long[] y = new long[2];
+
+		// Vertical bar of crosshair
+
+		/* CSFS: These used to use the 'old' get-visible-extent functions. Since I
+		 * had deleted these, I have converted them to use the new version.
+		 */
+
+		CDasherView.DRect visreg = VisibleRegion();
+
+		x[0] = sx;
+		y[0] = visreg.minY;
+
+		x[1] = sx;
+		y[1] = visreg.maxY;
+
+		if(GetBoolParameter(Ebp_parameters.BP_COLOUR_MODE) == true) {
+			DasherPolyline(x, y, 2, 1, 5);
+		}
+		else {
+			DasherPolyline(x, y, 2, 1, -1);
+		}
+
+		// Horizontal bar of crosshair
+
+		x[0] = 12 * sx / 14;
+		y[0] = lpMaxY / 2;
+
+		x[1] = 17 * sx / 14;
+		y[1] = lpMaxY / 2;
+
+		if(GetBoolParameter(Ebp_parameters.BP_COLOUR_MODE) == true) {
+			DasherPolyline(x, y, 2, 1, 5);
+		}
+		else {
+			DasherPolyline(x, y, 2, 1, -1);
+		}
+	}
+
+	/**
+	 * Reverse the x co-ordinate nonlinearity.
+	 * <p>
+	 * For details of this non-linearity, see the constructor.
+	 * 
+	 * @param x Value to which the mapping should be unapplied
+	 * @return Raw value
+	 */
+	public double unapplyXMapping(double x) // invert x non-linearity
+	{
+		if(x < m_dXMappingLogLinearBoundary * m_dXMappingLinearScaleFactor)
+			return x / m_dXMappingLinearScaleFactor;
+		else
+			return m_dXMappingLogLinearBoundary - m_dXMappingLogarithmicScaleFactor + m_dXMappingLogarithmicScaleFactor * Math.exp((x / m_dXMappingLinearScaleFactor - m_dXMappingLogLinearBoundary) / m_dXMappingLogarithmicScaleFactor);
+
+	}
+
+	/**
+	 * Apply the x co-ordinate nonlinearity.
+	 * <p>
+	 * For details of this non-linearity, see the constructor.
+	 * 
+	 * @param x Value to which the mapping should be applied
+	 * @return Mapped value
+	 */
+	public double applyXMapping(double x) 
+	// x non-linearity
+	{
+		if(x < m_dXMappingLogLinearBoundary)
+			return m_dXMappingLinearScaleFactor * x;
+		else
+			return m_dXMappingLinearScaleFactor * (m_dXMappingLogarithmicScaleFactor * Math.log((x + m_dXMappingLogarithmicScaleFactor - m_dXMappingLogLinearBoundary) / m_dXMappingLogarithmicScaleFactor) + m_dXMappingLogLinearBoundary);
+	}
+
+}
+
+
+/**
+ * Exception to be raised to signal that a given Node was not
+ * drawable.
+ */
+class NodeCannotBeDrawnException extends Exception {
+	/**
+	 * The Node which could not be drawn
+	 */
+	protected CDasherNode WhichNode;
+
+	/**
+	 * Default constructor; creates the exception but does not
+	 * store a Node.
+	 *
+	 */
+	public NodeCannotBeDrawnException() {
+		WhichNode = null;
+	}
+
+	/**
+	 * Creates a new exception with a reference to the Node
+	 * which could not be drawn.
+	 * 
+	 * @param thenode Problem Node.
+	 */
+	public NodeCannotBeDrawnException(CDasherNode thenode) {
+		WhichNode = thenode;
+	}
+
+	/**
+	 * Retrieves the Node which couldn't be drawn.
+	 * 
+	 * @return Reference to undrawable Node.
+	 */
+	public CDasherNode GetNode() {
+		return WhichNode;
+	}
+}
\ No newline at end of file

Added: trunk/java/dasher/CDefaultFilter.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CDefaultFilter.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,349 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Dasher's current default input filter, otherwise known as 
+ * Normal Control. This causes Dasher, when unpaused, to zoom
+ * towards the mouse position with the goal that the spot the
+ * mouse hovers over at time X should be under the crosshair at
+ * some later time.
+ * <p>
+ * The filter also includes support for a number of Start Handlers,
+ * and is responsible for instantiating and managing them if the
+ * parameters relating to them are set appropriately.
+ * <p>
+ * It does not respond to key presses except to start and stop
+ * on key 100.
+ * <p>
+ * Automatic Speed Control is also featured with the Default Filter,
+ * using an instance of AutoSpeedControl for this purpose.
+ * 
+ * @see CAutoSpeedControl
+ */
+public class CDefaultFilter extends CInputFilter {
+
+	/**
+	 * Our Automatic Speed Control helper class
+	 */
+	protected CAutoSpeedControl m_AutoSpeedControl;
+	
+	/**
+	 * The currently enabled start handler, if any 
+	 */
+	protected CStartHandler m_StartHandler;
+	
+	/**
+	 * Sole constructor. Constructs a DefaultFilter with an
+	 * AutoSpeedControl helper class and runs CreateStartHandler
+	 * to produce a start handler if this is necessary.
+	 * 
+	 * @param EventHandler Event handler with which to register ourselves
+	 * @param SettingsStore Setting repository to use
+	 * @param Interface Interface with which this Module should register itself
+	 * @param m_DasherModel Model which will yield a FrameRate for creation of CAutoSpeedControl
+	 * @param iID Unique ID for this module
+	 * @param szName Friendly name for this module
+	 */
+	public CDefaultFilter(CEventHandler EventHandler, CSettingsStore SettingsStore, CDasherInterfaceBase Interface, CDasherModel m_DasherModel, long iID, String szName)
+	{ 
+		super(EventHandler, SettingsStore, Interface, iID, 1, szName);
+		m_StartHandler = null;
+		m_AutoSpeedControl = new CAutoSpeedControl(m_EventHandler, m_SettingsStore, m_DasherModel.Framerate());
+		
+		CreateStartHandler();
+	}
+		
+	/**
+	 * Draws the mouse square and mouse line to the specified View
+	 * in the case that BP_DRAW_MOUSE and BP_DRAW_MOUSE_LINE are enabled
+	 * respectively, and calls m_StartHandler's DecorateView method
+	 * to draw the start handler, if applicable.
+	 * 
+	 * @param View View to which we should draw decorations
+	 * @return True if this method drew anything, false if not.
+	 */
+	public boolean DecorateView(CDasherView View) {
+		
+		boolean bDidSomething = (false);
+		
+		if(GetBoolParameter(Ebp_parameters.BP_DRAW_MOUSE)) {
+			DrawMouse(View);
+			bDidSomething = true;
+		}
+		
+		if(GetBoolParameter(Ebp_parameters.BP_DRAW_MOUSE_LINE)) {
+			DrawMouseLine(View);
+			bDidSomething = true;
+		}
+		
+		if(m_StartHandler != null) {
+			bDidSomething = m_StartHandler.DecorateView(View) || bDidSomething;
+		}
+		return bDidSomething;
+	}
+	
+	/**
+	 * See CInputFilter for an description of the method's purpose.
+	 * <p>
+	 * This filter simply asks the View for our mouse co-ordinates
+	 * in Dasher space, and feeds them to the Model's Tap_on_display
+	 * method which causes the model to move in this direction.
+	 * <p>
+	 * The coordinates are then fed to our AutoSpeedControl helper
+	 * to fine tune the dashing speed, and our start handler
+	 * is passed the View and Model pointers in case it too
+	 * has action to take.
+	 * 
+	 * @param Time System time at which this event was called, as a UNIX timestamp
+	 * @param m_DasherView View to query for input co-ordinates
+	 * @param m_DasherModel Model to alter using these co-ordinates
+	 * @return True if the model has been changed, false if not.
+	 */
+	public boolean Timer(long Time, CDasherView m_DasherView, CDasherModel m_DasherModel) {
+		
+		CDasherView.DPoint inputCoords = m_DasherView.getInputDasherCoords();
+		
+		/* CSFS: Substituted a DPoint class for the returning of Dasher co-ords here */
+		
+		// ApplyAutoCalibration(iDasherX, iDasherY, true);
+		// ApplyTransform(iDasherX, iDasherY);
+		
+		/*  CSFS: These lines didn't appear to do anything */
+		
+		boolean bDidSomething;
+		bDidSomething = m_DasherModel.Tap_on_display(inputCoords.x,inputCoords.y, Time, null);
+		
+		m_AutoSpeedControl.SpeedControl(inputCoords.x, inputCoords.y, m_DasherModel.Framerate(), m_DasherView);
+		
+		if(m_StartHandler != null) {
+			m_StartHandler.Timer(Time, m_DasherView, m_DasherModel);
+		}
+		return bDidSomething;
+	}
+	
+	/**
+	 * Called by the InterfaceBase when a key is pressed. This
+	 * filter responds to space and mouse by starting and stopping
+	 * Dasher if BP_START_SPACE and BP_START_MOUSE are set respectively.
+	 * <p>
+	 * For a complete listing of key IDs, see the documentation
+	 * for DasherInterfaceBase.KeyDown.
+	 * 
+	 * @param iTime System time when this key was pressed, as a UNIX timestamp
+	 * @param iId Key identifier
+	 * @param Model Ignored by this filter
+	 */
+	public void KeyDown(long iTime, int iId, CDasherModel Model) {
+		
+		switch(iId) {
+		case 0: // Start on space
+			// FIXME - wrap this in a 'start/stop' method (and use for buttons as well as keys)
+			if(GetBoolParameter(Ebp_parameters.BP_START_SPACE)) {
+				if(GetBoolParameter(Ebp_parameters.BP_DASHER_PAUSED))
+					m_Interface.Unpause(iTime);
+				else
+					m_Interface.PauseAt(0, 0);
+			}
+			break; 
+		case 100: // Start on mouse
+			if(GetBoolParameter(Ebp_parameters.BP_START_MOUSE)) {
+				if(GetBoolParameter(Ebp_parameters.BP_DASHER_PAUSED))
+					m_Interface.Unpause(iTime);
+				else
+					m_Interface.PauseAt(0, 0);
+			}
+			break;
+		}
+	}
+	
+	/**
+	 * Called by the event handler when dispatching events.
+	 * <p>
+	 * This class responds to the following parameter changes:
+	 * <p><i>BP_CIRCLE_START</i> and <i>BP_MOUSEPOS_MODE</i>: Recalls CreateStartHandler()
+	 * in case we need to change our set start handler.
+	 * 
+	 * @param Event Event to handle
+	 */
+	public void HandleEvent(CEvent Event) {
+		if(Event.m_iEventType == 1) {
+			CParameterNotificationEvent Evt = (CParameterNotificationEvent)Event;
+			
+			if(Evt.m_iParameter == Ebp_parameters.BP_CIRCLE_START || 
+					Evt.m_iParameter == Ebp_parameters.BP_MOUSEPOS_MODE) {
+				CreateStartHandler();
+				
+			}
+		}
+	}
+	
+	/**
+	 * Creates a start handler. At present, this method will
+	 * create a CircleStartHandler in response to BP_CIRCLE_START only.
+	 * If CTwoBoxStartHandler is ported to Java in the future,
+	 * there is commented code in the source which would instantiate
+	 * this in response to BP_MOUSEPOS_MODE also.
+	 */
+	public void CreateStartHandler() {
+				
+		if(GetBoolParameter(Ebp_parameters.BP_CIRCLE_START)) {
+			m_StartHandler = new CCircleStartHandler(m_EventHandler, m_SettingsStore, m_Interface);
+		}
+		else if(GetBoolParameter(Ebp_parameters.BP_MOUSEPOS_MODE)) {
+			/* m_StartHandler = new CTwoBoxStartHandler(m_EventHandler, m_SettingsStore, m_Interface); */
+		}
+			// CSFS: Disabled for now, one is enough for testing purposes, if even that is necessary.
+	}
+	
+	/**
+	 * Draws a small box at the current mouse position.
+	 * 
+	 * @param View View to which we should draw
+	 */
+	public void DrawMouse(CDasherView View) {
+		
+		int iCoordinateCount = (View.GetCoordinateCount());
+		
+		long[] Coordinates = (new long[iCoordinateCount]);
+		
+		int iType = (View.GetCoordinates(iCoordinateCount, Coordinates));
+		
+		int mousex;
+		int mousey;
+		
+		if(iCoordinateCount == 1) {
+			mousex = 0;
+			mousey = (int)Coordinates[0];
+		}
+		else {
+			mousex = (int)Coordinates[0];
+			mousey = (int)Coordinates[1];
+			
+			/* CSFS: This looks a little questionable; however this is also exactly
+			 * what's found in the C++ version only using "myint" for the long and
+			 * screenint for the int...
+			 */
+		}
+		
+		int mode;
+		
+		if(GetBoolParameter(Ebp_parameters.BP_NUMBER_DIMENSIONS))
+			mode = 1;
+		else if(GetBoolParameter(Ebp_parameters.BP_EYETRACKER_MODE))
+			mode = 2;
+		else
+			mode = 0;
+		
+		CDasherView.DPoint dashXY = View.Input2Dasher(mousex, mousey, iType, mode);
+		
+		// ApplyAutoCalibration(iDasherX, iDasherY, false);
+		// ApplyTransform(iDasherX, iDasherY);
+		
+		/* CSFS: These lines didn't appear to do anything */
+		
+		if(GetBoolParameter(Ebp_parameters.BP_COLOUR_MODE) == true) {
+			View.DasherDrawCentredRectangle(dashXY.x, dashXY.y, 5, 2, EColorSchemes.Objects, false);
+		}
+		else {
+			View.DasherDrawCentredRectangle(dashXY.x, dashXY.y, 5, 1, EColorSchemes.Objects, false);
+		}
+		
+	}
+	
+	/**
+	 * Draws a line from the origin (LP_OX, LP_OY) to the current
+	 * mouse position.
+	 * 
+	 * @param View View to which this line should be drawn.
+	 */
+	public void DrawMouseLine(CDasherView View) {
+		
+		int iCoordinateCount = (View.GetCoordinateCount());
+		
+		long[] Coordinates = (new long[iCoordinateCount]);
+		
+		int iType = (View.GetCoordinates(iCoordinateCount, Coordinates));
+		
+		int mousex;
+		int mousey;
+		
+		if(iCoordinateCount == 1) {
+			mousex = 0;
+			mousey = (int)Coordinates[0];
+		}
+		else {
+			mousex = (int)Coordinates[0];
+			mousey = (int)Coordinates[1];
+		}
+		
+		long[] x = new long[2];
+		long[] y = new long[2];
+		
+		// Start of line is the crosshair location
+		
+		x[0] = GetLongParameter(Elp_parameters.LP_OX);
+		y[0] = GetLongParameter(Elp_parameters.LP_OY);
+		
+		// End of line is the mouse cursor location - note that we should
+		// probably be using a cached value rather than computing this
+		// separately to TapOn
+		
+		int mode;
+		
+		if(GetBoolParameter(Ebp_parameters.BP_NUMBER_DIMENSIONS))
+			mode = 1;
+		else if(GetBoolParameter(Ebp_parameters.BP_EYETRACKER_MODE))
+			mode = 2;
+		else
+			mode = 0;
+		
+		CDasherView.DPoint newXY = View.Input2Dasher(mousex, mousey, iType, mode);
+		x[1] = newXY.x;
+		y[1] = newXY.y;
+		
+		// ApplyAutoCalibration(x[1], y[1], false);
+		// ApplyTransform(x[1], y[1]);
+
+		/* CSFS: Again, this just called stubs */
+		
+		// Actually plot the line
+		
+		if(GetBoolParameter(Ebp_parameters.BP_COLOUR_MODE)) {
+			View.DasherPolyline(x, y, 2, (int)GetLongParameter(Elp_parameters.LP_LINE_WIDTH), 1);
+		}
+		else {
+			View.DasherPolyline(x, y, 2, (int)GetLongParameter(Elp_parameters.LP_LINE_WIDTH), -1);
+		}
+	}
+	/*
+	public void CDefaultFilter::ApplyTransform(myint &iDasherX, myint &iDasherY) {
+	}
+	
+	public void CDefaultFilter::ApplyAutoCalibration(myint &iDasherX, myint &iDasherY, bool bUpdate) {
+	}
+	*/
+}

Added: trunk/java/dasher/CDelayedDraw.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CDelayedDraw.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,121 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.ArrayList;
+
+/**
+ * Simple class permitting the delayed drawing of Strings when
+ * drawing the DasherNodes to the screen.
+ * <p>
+ * The idea is that we can both<br>
+ * a) Cause all text to appear above other drawn objects, and
+ * b) Draw text at the same time as its Node, allowing the
+ * drawing process to remain modular.
+ * <p>
+ * Essentially, all strings which are drawn with this class are
+ * added to a list, which is emptied and drawn when Draw is called.
+ */
+public class CDelayedDraw {
+
+	/**
+	 * Queues up a piece of text for drawing. 
+	 * 
+	 * @param str String to draw
+	 * @param x1 x co-ordinate of top-left corner of the string's bounding box
+	 * @param y1 y co-ordinate of top-left corner of the string's bounding box
+	 * @param Size Font size to use
+	 */
+	public void DelayDrawText(String str, int x1, int y1, long Size) {
+		m_DrawTextString.add(new CTextString(str, x1, y1, Size));
+	}
+	
+	/**
+	 * Draws all queued up text to a given screen, and clears the queue.
+	 *  
+	 * @param screen Screen to which we should draw
+	 */
+	public void Draw(CDasherScreen screen) {
+		int iSize = m_DrawTextString.size();
+		
+		for(int i = 0; i < iSize; i++) {
+			CTextString draw = m_DrawTextString.get(i);
+			screen.DrawString(draw.m_String, draw.m_x, draw.m_y, draw.m_iSize);
+		}
+		m_DrawTextString.clear();
+		
+	}
+			
+	/**
+	 * Internal list of objects we are waiting to draw
+	 */
+	protected ArrayList <CTextString> m_DrawTextString = new ArrayList<CTextString>();
+		
+	/* CSFS: The class CTextSymbol and its associated ArrayList has been removed
+	 * since it was redundant according to Eclipse.
+	 */
+	
+	/**
+	 * Class representing a String to be drawn plus information
+	 * needed to draw it
+	 */
+	protected class CTextString {
+		
+		/**
+		 * Default constructor
+		 * 
+		 * @param str String to draw
+		 * @param x x co-ordinate of top-left corner of the string's bounding box
+		 * @param y y co-ordinate of top-left corner of the string's bounding box
+		 * @param iSize font size
+		 */
+		public CTextString(String str, int x, int y, long iSize) {
+		
+			m_String = (str);
+			m_x = (x);
+			m_y = (y);
+			m_iSize = (iSize);
+						
+		} 
+		/**
+		 * String to be drawn
+		 */
+		String m_String;
+		/**
+		 * x co-ordinate of top-left corner of the string's bounding box
+		 */
+		int m_x;
+		/**
+		 * y co-ordinate of top-left corner of the string's bounding box
+		 */
+		int m_y;
+		/**
+		 * Font size
+		 */
+		long m_iSize;
+	}
+		
+}

Added: trunk/java/dasher/CEditContextEvent.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CEditContextEvent.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,66 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Event which can be loosely interpreted to mean "I want to know
+ * what the context is". It will be issued by the Interface when
+ * the internal context buffer is empty, or the current context is
+ * most likely no longer valid, but a UI component may know what
+ * the context ought to be.
+ * <p>
+ * Components should respond by setting the newContext property.
+ * When first dispatched this property is empty, so components
+ * should be wary of overwriting another's answer unless they are
+ * sure they have a better context.
+ * <p>
+ * The MaxLength property specifies how much context the Interface
+ * is asking for; longer strings should not be supplied.
+ */
+public class CEditContextEvent extends CEvent {
+
+	/**
+	 * Creates a new event with type 3 (EV_EDIT_CONTEXT) and a
+	 * specified maxLength.
+	 * 
+	 * @param iMaxLength Maximum length of context desired
+	 */
+	public CEditContextEvent(int iMaxLength) {
+		m_iEventType = 3; //EV_EDIT_CONTEXT
+		m_iMaxLength = iMaxLength;
+	}
+	/**
+	 * Maximum length of context desired
+	 */
+	public int m_iMaxLength;
+	
+	/**
+	 * Empty string, to be replaced with a context if one is known
+	 */
+	public String newContext = "";
+
+	
+}

Added: trunk/java/dasher/CEditEvent.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CEditEvent.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,61 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Event which signals that text has been entered or deleted.
+ * <p>
+ * An m_iEditType of 1 indicates new text, and 2 indicates deletion.
+ */
+public class CEditEvent extends CEvent {
+
+	/**
+	 * Creates a new EditEvent with a given type and text.
+	 * <p>
+	 * If deleting text, the content of m_sText is likely not
+	 * to matter, though its length may be used in deciding how
+	 * many characters to remove.
+	 * 
+	 * @param iEditType 1 for new text, 2 for deleted text
+	 * @param sText Text to be added / deleted.
+	 */
+	public CEditEvent(int iEditType, String sText) {
+	    m_iEventType = 2; // EV_EDIT
+	    m_iEditType = iEditType;
+	    m_sText = sText;
+	};
+
+	/**
+	 * Edit event type
+	 */
+	public int m_iEditType;
+	
+	/**
+	 * Text to add/remove
+	 */
+	public String m_sText;
+	
+}

Added: trunk/java/dasher/CEvent.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CEvent.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,55 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Base class representing a generic Event.
+ * <p>
+ * Generally this should not be instantiated and dispatched; rather
+ * one should use a specialisation of this class with a non-zero
+ * m_iEventType. As this will appear to have type 0, most components
+ * will ignore it.
+ * <p>
+ * Currently assigned types:
+ * <p>1: Parameter change (CParameterNotificationEvent)
+ * <p>2: Edit event (CEditEvent)
+ * <p>3: Edit context request (CEditContextEvent)
+ * <p>4: Dasher Starting notification (CStartEvent)
+ * <p>5: Dasher Stopping notification (CStopEvent)
+ * <p>6: Control Mode related (CControlEvent)
+ * <p>7: Lock event (locks/unlocks Dasher and may state
+ * progress of the current operation) (CLockEvent)
+ * <p>8: Message event -- typically interpreted
+ * by showing the user a message box (CMessageEvent)
+ */
+public class CEvent {
+	
+	/**
+	 * Event type. This is set by the constructor of various
+	 * superclasses of Event.
+	 */
+	public int m_iEventType;
+}

Added: trunk/java/dasher/CEventHandler.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CEventHandler.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,196 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.ArrayList;
+
+/**
+ * The EventHandler class is a fairly simple device whose responsibilities are to
+ * <p>a) Allow DasherComponents to register themselves as event listeners,
+ * <p>b) Accept events from DasherComponents and notify all other Components
+ * using their HandleEvent method, and
+ * <p>c) Allow Components to unregister themselves when they are being destroyed.
+ * <p>
+ * The mode of action is very simple indeed; we have a list of
+ * Listeners to which new listeners are added and old ones removed,
+ * and which we iterate through when notified of an event, notifying
+ * all other Components by calling their HandleEvent methods in turn.
+ * <p>
+ * There is however one special case: In the event that a listener tries
+ * to register itself whilst an event is being handled (for example, a parameter
+ * change caused a Component to be created which immediately tried
+ * to register itself), the component is added to a queue of listeners
+ * who are waiting to be registered.
+ * <p>
+ * This is because otherwise there would be some ambiguity as to
+ * when a given component would start receiving events, particularly
+ * as to whether it would receive that which was being handled
+ * when it registered itself.
+ * <p>
+ * The result is that new listeners will begin receiving events
+ * as soon as all those which were in progress when it registered
+ * have finished.
+ * <p>
+ * Because events are dispatched immediately and not added to a queue,
+ * there cannot be any certainty as to in what order a given component
+ * will hear about multiple events inserted without waiting for
+ * the first to end.
+ * <p>
+ * It is also possible to cause the program to enter a tight
+ * loop by creating a direct or indirect loop of dispatched events;
+ * Components should be careful to avoid causing this situation by
+ * avoiding creating events during their HandleEvent procedures which
+ * are likely to cause the same event to be re-raised unless they
+ * can be certain of stopping the loop at some future point.
+ */
+public class CEventHandler {
+	  
+	/**
+	 * List of currently active listeners
+	 */
+	protected ArrayList <CDasherComponent> m_vListeners;
+	
+	/**
+	 * List of Components waiting to be added as listeners
+	 * when we finish handling events.
+	 */
+	protected ArrayList <CDasherComponent> m_vListenerQueue;
+
+	/**
+	 * Integer indicating how many times we are 'in' the event
+	 * handler (for example, we might be in twice if a component
+	 * responded to an event by issuing an event of its own). 
+	 */
+	protected int m_iInHandler;
+	
+	/**
+	 * Interface to whom this Handler belongs, and which will
+	 * have its InterfaceEventHandler method called for all events.
+	 */
+	protected CDasherInterfaceBase m_pInterface;
+	
+	/**
+	 * Creates a new EventHandler with no listeners and attached
+	 * to a specified interface.
+	 * 
+	 * @param pInterface Parent interface
+	 */
+	public CEventHandler(CDasherInterfaceBase pInterface){
+	    m_iInHandler = 0;
+	    m_pInterface = pInterface;
+	    m_vListeners = new ArrayList<CDasherComponent>();
+	    m_vListenerQueue = new ArrayList<CDasherComponent>();
+	}
+	
+	/**
+	 * Informs all registered listeners of a specified Event.
+	 * <p>
+	 * Before beginning, m_iInHandler is incremented to indicate
+	 * that one event is currently in progress; when finished,
+	 * it is decremented and, if zero, listeners which are queued
+	 * up for registration will be added to the list of active
+	 * listeners.
+	 * <p>
+	 * The last components to be notified of a given event will
+	 * always be the parent Interface and then the external
+	 * event handler (by way of the interface's ExternalEventHandler
+	 * method.
+	 * 
+	 * @param Event Event to dispatch to all registered listeners.
+	 */
+	public void InsertEvent(CEvent Event) {
+
+		  // We may end up here recursively, so keep track of how far down we
+		  // are, and only permit new handlers to be registered after all
+		  // messages are processed.
+
+		  // An alternative approach would be a message queue - this might actually be a bit more sensible
+		  ++m_iInHandler;
+		  
+		  /* CSFS: Rewritten to use ArrayLists and for-each
+		   * instead of C++ list iterators.
+		   */
+
+		  // Loop through components and notify them of the event
+		  		  
+		  for(CDasherComponent i : m_vListeners) {
+		    i.HandleEvent(Event);
+		  }
+		  // Call external handler last, to make sure that internal components are fully up to date before external events happen
+
+		  m_pInterface.InterfaceEventHandler(Event);
+
+		  m_pInterface.ExternalEventHandler(Event);
+
+		  --m_iInHandler;
+		  
+		  if(m_iInHandler == 0) {
+			  
+			  
+			  for(CDasherComponent i : m_vListenerQueue) {
+				  m_vListeners.add(i); 
+			  }
+			  m_vListenerQueue.clear();
+		  }
+	}
+
+	/**
+	 * Registers a given component as an event listener.
+	 * <p>
+	 * In the event that one or more events are currently in progress,
+	 * it will be added to a queue of pending listeners and will
+	 * be added when InsertEvent finishes for the last time.
+	 * 
+	 * @param pListener Component to add as a listener
+	 */
+	public void RegisterListener(CDasherComponent pListener) {
+
+		if(m_vListeners.contains(pListener) == false && m_vListenerQueue.contains(pListener) == false) {
+		    if(!(m_iInHandler > 0))
+		      m_vListeners.add(pListener);
+		    else
+		      m_vListenerQueue.add(pListener);
+		  }
+		  else {
+		    // Can't add the same listener twice
+		  }
+		}
+
+	/**
+	 * Removes a given Component from the list of listeners.
+	 * <p>
+	 * This is necessary before a given Component can be garbage
+	 * collected.
+	 * 
+	 * @param pListener Component to remove
+	 */
+	public void UnregisterListener(CDasherComponent pListener) {
+		
+		if(m_vListeners.contains(pListener)) m_vListeners.remove(pListener);
+		if(m_vListenerQueue.contains(pListener)) m_vListenerQueue.remove(pListener);
+	}
+
+}

Added: trunk/java/dasher/CFileLogger.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CFileLogger.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,42 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Stub at the moment; may potentially be developed into a logfile
+ * writer in the future!
+ */
+public class CFileLogger {
+
+	/**
+	 * Destroy the logger, which doesn't exist :)
+	 *
+	 */
+	public void Destroy() {
+		//stub
+	}
+	
+}

Added: trunk/java/dasher/CFrameRate.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CFrameRate.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,226 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Monitors the framerate by taking records every time NewFrame
+ * is called; this is used to control performance-specific features
+ * such as automatic speed control.
+ */
+public class CFrameRate {
+	
+	/**
+	 * Current frame rate
+	 */
+	private double m_dFr;
+	
+	/**
+	 * Maximum rate of entering information
+	 */
+	private double m_dMaxbitrate;         // the maximum rate of entering information
+	
+	/**
+	 * Maximum x movement per frame 
+	 */
+	private double m_dRXmax;              // the maximum zoomin per frame
+	
+	/**
+	 * Number of frames elapsed
+	 */
+	private int m_iFrames;
+	
+	/**
+	 * Number of samples currently stored
+	 */
+	private int m_iSamples;
+	
+	/**
+	 * Time of the second-to-last frame
+	 */
+	private long m_iTime;
+	
+	/**
+	 * Time of last frame
+	 */
+	private long m_iTime2;
+	
+	/**
+	 * Not sure! Comments said "see djw thesis" 
+	 */
+	private int m_iSteps;                 // the 'Steps' parameter. See djw thesis.
+	
+	/**
+	 * Cache of the natural log of 2
+	 */
+	final double LN2 = Math.log(2.0);
+
+	/**
+	 * Gets maximum x movement per frame
+	 * 
+	 * @return m_dRXmax
+	 */
+	public double Rxmax() {
+	    return m_dRXmax;
+	}
+	/// Get the minimum size of the target viewport
+	////// TODO: Eventually fix this so that it uses integer maths internally. 
+	
+	/**
+	 * Gets the minimum size of the target viewport
+	 * 
+	 * @param t Current time
+	 * @return Minimum size of target viewport
+	 */
+	public long MinSize(long t) {
+		return (long)(t / m_dRXmax);
+	}
+	
+	/**
+	 * Gets m_iSteps; see its description
+	 * 
+	 * @return m_iSteps
+	 */
+	public int Steps() {
+		return m_iSteps;
+	} 
+	
+	/**
+	 * Gets current frame rate
+	 * 
+	 * @return Frame rate (FPS)
+	 */
+	public double Framerate() {
+		return m_dFr;
+	} 
+	
+	// TODO: These two shouldn't be the same thing:
+	
+	/**
+	 * Creates a new framerate monitor; all initial values
+	 * are currently hard coded in.
+	 * <p>
+	 * We start with a frame rate of 32FPS. 
+	 */
+	public CFrameRate() {
+		
+		// maxbitrate should be user-defined and/or adaptive. Currently it is not.
+		m_dMaxbitrate = 5.5;
+		m_dRXmax = 2;                 // only a transient effect
+		m_iFrames = 0;
+		m_iSamples = 1;
+		
+		// we dont know the framerate yet - play it safe by setting it high
+		m_dFr = 1 << 5;
+		
+		// start off very slow until we have sampled framerate adequately
+		m_iSteps = 2000;
+		m_iTime = 0;                  // Hmmm, User must reset framerate before starting.
+	}
+	
+	/**
+	 * Resets all our internal values to the same defaults as
+	 * are chosen in the constructor.
+	 */
+	public void Initialise() {
+		m_dRXmax = 2;                 // only a transient effect
+		m_iFrames = 0;
+		m_iSamples = 1;
+		
+		// we dont know the framerate yet - play it safe by setting it high
+		m_dFr = 1 << 5;
+		
+		// start off very slow until we have sampled framerate adequately
+		m_iSteps = 2000;
+		m_iTime = 0;                  // Hmmm, User must reset framerate before starting.
+	}
+	
+	/**
+	 * Insert a new frame and recompute the frame rate, if enough
+	 * samples have been gathered.
+	 * <p>
+	 * If this would result in a Steps parameter of 0 it is set to 1.
+	 * 
+	 * @param Time Time at which the new frame began, as a UNIX timestamp.
+	 */
+	public void NewFrame(long Time)
+//	compute framerate if we have sampled enough frames
+	{
+		m_iFrames++;
+		
+		if(m_iFrames == m_iSamples) {
+			m_iTime2 = Time;
+			if(m_iTime2 - m_iTime < 50)
+				m_iSamples++;             // increase sample size
+			else if(m_iTime2 - m_iTime > 80) {
+				m_iSamples--;
+				if(m_iSamples < 2)
+					m_iSamples = 2;
+			}
+			if(m_iTime2 - m_iTime != 0) {
+				m_dFr = m_iFrames * 1000.0 / (m_iTime2 - m_iTime);
+				m_iTime = m_iTime2;
+				m_iFrames = 0;
+				
+			}
+			m_dRXmax = Math.exp(m_dMaxbitrate * LN2 / m_dFr);
+			m_iSteps = m_iSteps / 2 + (int)(-Math.log(0.2) * m_dFr / LN2 / m_dMaxbitrate) / 2;
+			
+			// If the framerate slows to < 4 then we end up with steps < 1 ! 
+			if(m_iSteps == 0)
+				m_iSteps = 1;
+			
+		}
+		
+	}
+	
+	/**
+	 * Clears our frame count
+	 * 
+	 * @param Time System time as a UNIX timestamp.
+	 */
+	public void Reset(long Time) {
+		m_iFrames = 0;
+		m_iTime = Time;
+	}
+	
+	/**
+	 * Sets the max bitrate
+	 * 
+	 * @param TargetRate New bitrate
+	 */
+	public void SetBitrate(double TargetRate) {
+		m_dMaxbitrate = TargetRate;
+	}
+	
+	/**
+	 * Sets the max bitrate
+	 * 
+	 * @param MaxRate New bitrate
+	 */
+	public void SetMaxBitrate(double MaxRate) {
+		m_dMaxbitrate = MaxRate;
+	}
+}

Added: trunk/java/dasher/CInputFilter.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CInputFilter.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,162 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Input filters are a key part of the Dasher infrastructure.
+ * <p>
+ * They are responsible for taking raw input co-ordinates and
+ * modifying the DasherModel in some way if appropriate.
+ * <p>
+ * They are also notified of all key presses and are given a chance
+ * to apply graphical decorations towards the end of the drawing
+ * cycle.
+ * <p>
+ * The most important method is Timer, which will be fired at the
+ * beginning of each new frame. This is responsible for obtaining
+ * input co-ordinates from the View, typically using the GetCoordinates
+ * method, and interacting with the model in some way, typically
+ * by calling Tap_on_display.
+ * <p>
+ * Timer will always be called every frame, regardless of the filter
+ * in use, except for when Dasher is paused or locked.
+ * <p>
+ * Being Modules, InputFilters have an Activate and Deactivate
+ * method which is intended to allow the allocation and deallocation
+ * of temporary helper objects, helper threads, network connections
+ * and so forth.
+ * <p>
+ * It is very important that the Timer method should return as near
+ * instantaneously as possible, as this will be called tens of times
+ * per second.
+ * <p>
+ * Input filters may also interact with the main Dasher interface,
+ * typically to start and stop Dasher in response to key presses.
+ */
+public class CInputFilter extends CDasherModule {
+	
+	/**
+	 * Interface which this InputFilter may control
+	 */	
+	protected CDasherInterfaceBase m_Interface;
+	
+	/**
+	 * Creates a new filter. See DasherModule for information
+	 * on registering this with the Interface as a usable
+	 * module.
+	 * 
+	 * @param EventHandler Event handler with which we should register ourselves
+	 * @param SettingsStore Settings repository to use
+	 * @param Interface Interface which this filter may control
+	 * @param iID Unique identifier for this Module
+	 * @param iType Module type (see DasherModule for a list)
+	 * @param szName Friendly name (ideally unique)
+	 * @see CDasherModule
+	 */
+	public CInputFilter(CEventHandler EventHandler, CSettingsStore SettingsStore, CDasherInterfaceBase Interface, long iID, int iType, String szName)
+    { 
+      	super(EventHandler, SettingsStore, iID, iType, szName);
+      	m_Interface = Interface;
+    }
+	
+	/**
+	 * Ignores all events; to be overridden by subclasses if desired.
+	 */
+	public void HandleEvent(CEvent Event) {};
+	
+	/**
+	 * Should draw any decorations applicable to this filter.
+	 * <p>
+	 * For example, DefaultFilter might draw a line indicating
+	 * the mouse position at this stage.
+	 * <p>
+	 * If we wish to allow any helper classes to do their own
+	 * decorating, we should pass the View to them at this stage.
+	 * 
+	 * @param View View to which we should draw our decorations.
+	 * @return True if anything has been drawn, false otherwise.
+	 */
+	public boolean DecorateView(CDasherView View) { return false; };
+	
+	/**
+	 * Notifies the filter of a key-down event at a given time,
+	 * and allows it to make changes to the Model but not the View
+	 * in response to this change. If we wish to display things
+	 * in response to a key event, we must store state in the meantime
+	 * and wait for the next frame. 
+	 * 
+	 * @param Time System time at which the key event took place, as a unix timestamp.
+	 * @param iId ID of the key pressed (see DasherInterfaceBase.KeyDown for a list)
+	 * @param Model DasherModel which may be modified in response to this keypress
+	 */
+	public void KeyDown(long Time, int iId, CDasherModel Model) {};
+	
+	/**
+	 * Notifies the filter of a key-up event at a given time,
+	 * and allows it to make changes to the Model but not the View
+	 * in response to this change. If we wish to display things
+	 * in response to a key event, we must store state in the meantime
+	 * and wait for the next frame. 
+	 * 
+	 * @param Time System time at which the key event took place, as a unix timestamp.
+	 * @param iId ID of the key pressed (see DasherInterfaceBase.KeyDown for a list)
+	 * @param Model DasherModel which may be modified in response to this keypress
+	 */
+	public void KeyUp(long Time, int iId, CDasherModel Model) {};
+	
+	/**
+	 * Requests that the input filter should modify the indicated Model.
+	 * The View is passed so that input co-ordinates can be resolved
+	 * to Dasher co-ordinates prior to interacting with the Model.
+	 * <p>
+	 * Nothing should be drawn at this stage in spite of the availability
+	 * of the View; drawing should take place during the call to DecorateView.
+	 * <p>
+	 * See DefaultFilter for a typical example of a Timer method.
+	 * 
+	 * @param Time System time as a unix timestamp
+	 * @param m_DasherView View against which co-ordinates should be resolved
+	 * @param m_DasherModel Model which we may manipulate in response to this event
+	 * @return True if the model was changed, false otherwise.
+	 */
+	public boolean Timer(long Time, CDasherView m_DasherView, CDasherModel m_DasherModel) { return false; };
+	
+	/**
+	 * Activates this filter; now is the time to start helper threads,
+	 * allocate resources, and so forth.
+	 *
+	 */
+	public void Activate() {};
+	
+	/**
+	 * Deactivates this filter; threads should be stopped and resources
+	 * which can be freed should be.
+	 *
+	 */
+	public void Deactivate() {};
+	
+	
+}

Added: trunk/java/dasher/CLanguageModel.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CLanguageModel.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,210 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/* CSFS: WARNING: This is a DasherComponent derived class and so MUST
+ * have UnregisterComponent called on destruction.
+ */
+
+/**
+ * LanguageModels are responsible for predicting / guessing the probabilities
+ * associated with members of a given alphabet in a given context.
+ * <p>
+ * They have no internal state except for knowledge of the
+ * alphabet in which they make predictions; 
+ * rather they produce, modify and destroy Context objects
+ * (subclasses of CContextBase) which represent the context in which
+ * they were working. This enables the impression of multiple
+ * diverging models, when in fact the model is only capable of
+ * answering one question: "What comes next in this context?"
+ * <p>
+ * Models can adapt themselves in response to user input, and should
+ * do so if they are capable when LearnSymbol is called. Calls
+ * to EnterSymbol on the other hand should modify their context
+ * without altering the model.
+ * 
+ */
+public abstract class CLanguageModel extends CDasherComponent {
+
+	/**
+	 * Value to be returned when we need a null context.
+	 */
+	public static final CContextBase nullContext = null;
+	
+	/**
+	 * Alphabet in which we make predictions
+	 */
+	protected CSymbolAlphabet m_Alphabet;
+	
+	/**
+	 * Creates a LanguageModel working in a given alphabet.
+	 * 
+	 * @param EventHandler Event handler with which to register ourselves
+	 * @param SettingsStore Settings repository to use
+	 * @param Alphabet Alphabet to work in
+	 */
+	
+	public CLanguageModel(CEventHandler EventHandler, CSettingsStore SettingsStore, CSymbolAlphabet Alphabet) {
+	  super(EventHandler, SettingsStore);
+	  m_Alphabet = Alphabet;
+	}
+
+	/**
+	 * Ignores all events
+	 */
+	public void HandleEvent(CEvent Event) {
+		/* Ignores all events */
+	}
+
+	/**
+	 * Indicates whether this is a remote/asynchronous model
+	 * with respect to returning probabilities.
+	 * 
+	 * @return True if asynchronous, false if not
+	 */
+	public boolean isRemote() {
+		return false;
+	}
+	
+	/////////////////////////////////////////////////////////////////////////////
+	// Context creation/destruction
+	////////////////////////////////////////////////////////////////////////////
+
+	/* CPPMLanguageModel and others: These were using a 
+	 * horrible hack wherein an integer (really a CPPMContext * ) 
+	 * was being used to represent the context of a given node when 
+	 * outside the generating class, in order that it could be
+	 * swapped out for some other CLanguageModel derivation and retain 
+	 * type-compatibility at the expense of being entirely type-unsafe. 
+	 * Since Java doesn't like to be type unsafe, I've replaced this by 
+	 * all Context-representing classes being a child of CContextBase, which 
+	 * has no members or methods, thus retaining type-safety. */
+	
+	// Create a context (empty)
+	/**
+	 * Creates an empty context
+	 * 
+	 * @return Child of CContextBase representing the empty context
+	 */
+	public abstract CContextBase CreateEmptyContext();
+	
+	/**
+	 * Clones a given context; changes to one clone must not
+	 * effect the state of the other.
+	 * 
+	 * @param Context Context to clone
+	 * @return Clone of said context.
+	 */
+	public abstract CContextBase CloneContext(CContextBase Context);
+	
+	/**
+	 * Releases a given context; if the LanguageModel is keeping
+	 * track of them internally or doing allocation work, it should
+	 * release their storage.
+	 * 
+	 * @param Context Context to release 
+	 */
+	public abstract void ReleaseContext(CContextBase Context);
+
+	/////////////////////////////////////////////////////////////////////////////
+	// Context modifiers
+	////////////////////////////////////////////////////////////////////////////
+
+	/**
+	 * Modifies the supplied context, appending a given symbol.
+	 * <p>
+	 * The model should not alter its predictions based upon this
+	 * entry.
+	 * @param context Context to modify
+	 * @param Symbol Symbol to enter
+	 */
+	public abstract void EnterSymbol(CContextBase context, int Symbol);
+
+	/**
+	 * Modifies the supplied context, appending a given symbol.
+	 * <p>
+	 * The model should learn from this if it can in order to make
+	 * better predictions in future.
+	 * <p>
+	 * If the model is not capable of learning, this should behave
+	 * precisely as EnterSymbol.
+	 * 
+	 * @param context Context to modify
+	 * @param Symbol Symbol to enter
+	 */
+	public abstract void LearnSymbol(CContextBase context, int Symbol);
+
+	/////////////////////////////////////////////////////////////////////////////
+	// Prediction
+	/////////////////////////////////////////////////////////////////////////////
+
+	/**
+	 * Given a context and a normalisation value to which all
+	 * probabilities must add up, this should produce an array
+	 * in which each term corresponds to the relative probability
+	 * of that symbol coming next.
+	 * <p>
+	 * The indices assigned to symbols should match those in the
+	 * SymbolAlphabet we're working with.
+	 * <p>
+	 * The size of the array returned should be equal to the number of
+	 * symbols in our current alphabet. 
+	 */
+	public abstract long[] GetProbs(CContextBase Context , long iNorm);
+
+	/** Get some measure of the memory usage for diagnostic
+	 * purposes. No need to implement this if you're not comparing
+	 * language models. The exact meaning of the result will
+	 * depend on the implementation (for example, could be the
+	 * number of nodes in a trie, or the physical memory usage).
+	 * 
+	 * @return Memory usage in bytes, or 0 if unknown or we don't care
+	 */
+	public abstract int GetMemory();
+
+	/**
+	 * Gets our working alphabet
+	 * 
+	 * @return m_Alphabet
+	 */
+	public CSymbolAlphabet SymbolAlphabet() {
+	    return m_Alphabet;
+	}
+
+	/**
+	 * Gets the number of characters in our alphabet
+	 * 
+	 * @return m_Alphabet.size()
+	 */
+	protected int GetSize() {
+	    return m_Alphabet.GetSize();
+	}
+
+
+	 
+
+	
+}

Added: trunk/java/dasher/CLockEvent.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CLockEvent.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,72 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Event which cues the Interface to lock or unlock Dasher, and may
+ * optionally give a completion perrcentage of an event necessitating
+ * the lock's engagement.
+ * <p>
+ * The interface will always honour a cue to lock Dasher; user
+ * interface components should, if possible, inform the user that
+ * the lock is engaged, and, again if possible, give some indication
+ * of the percent completion.
+ * <p>
+ * If raising lock events relating to a monolithic operation, or
+ * an operation whose duration is unknown, zero percent completion
+ * should be indicated until finished.  
+ */
+public class CLockEvent extends CEvent {
+
+	/**
+	 * Creates a new Lock event
+	 * 
+	 * @param strMessage Message to show the user during lock
+	 * @param bLock Whether the lock should currently be engaged
+	 * @param iPercent Percentage completion
+	 */
+	public CLockEvent(String strMessage, boolean bLock, int iPercent) {
+		m_iEventType = 7; // EV_LOCK
+		m_strMessage = strMessage;
+		m_bLock = bLock;
+		m_iPercent = iPercent;
+	}
+	  
+	/**
+	 * Message intended for the user
+	 */
+	public String m_strMessage;
+	
+	/**
+	 * Lock engaged
+	 */
+	public boolean m_bLock;
+	
+	/**
+	 * Percent completion
+	 */
+	public int m_iPercent;
+}

Added: trunk/java/dasher/CMessageEvent.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CMessageEvent.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,63 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Event carrying a message for the user. User interface components
+ * should, if possible, display its contents to the user in some manner,
+ * typically by showing a message box. 
+ */
+public class CMessageEvent extends CEvent {
+	
+	/**
+	 * Creates a new message event
+	 * 
+	 * @param strMessage Message for the user
+	 * @param iID This message's unique numerical identifier
+	 * @param iType 0 for informative, 1 for warning, 2 for error
+	 */
+	public CMessageEvent(String strMessage, int iID, int iType) {
+		m_iEventType = 8; // EV_MESSAGE
+		m_strMessage = strMessage;
+		m_iID = iID;
+		m_iType = iType; // 0: information. 1: warning. 2: error.
+	}
+
+	/**
+	 * Message body
+	 */
+	public String m_strMessage;
+
+	/**
+	 * Message UID
+	 */
+	public int m_iID;
+
+	/**
+	 * Message type
+	 */
+	public int m_iType;
+}

Added: trunk/java/dasher/CModuleFactory.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CModuleFactory.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,91 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * A ModuleFactory is a factory capable of yielding one or more
+ * distinct CDasherModules, each associated with a friendly name
+ * and a unique identifier.
+ */
+public abstract class CModuleFactory {
+
+	/**
+	 * Called when a factory is to be registered with a ModuleManager
+	 * and will shortly be asked for its modules. Any work involved
+	 * in creating its modules or setting up its internal state
+	 * should be done now.
+	 *
+	 */
+	public abstract void Start();
+	
+	/**
+	 * Are more modules available beyond those already yielded?
+	 * 
+	 * @return True if so, false otherwise
+	 */
+	public abstract boolean IsMore();
+	
+	/**
+	 * Given information about a previous module, returns a struct
+	 * describing the next module.
+	 * <p>
+	 * In order to retrieve the first factory, a new/blank SFactoryInfo
+	 * should be passed in.
+	 * <p>
+	 * Null should never be passed as a parameter.
+	 * 
+	 * @param info SFactoryInfo describing the previous module or, to retrieve the first module, a blank SFactoryInfo. 
+	 * @return SFactoryInfo describing the next module
+	 */
+	public abstract SFactoryInfo GetNext(SFactoryInfo info);
+	
+	/**
+	 * Retrieves the module associated with a given unique identifier
+	 *  
+	 * @param iID UID of the required module
+	 * @return Corresponding module, or null if no module belonging
+	 * to this factory has this ID.
+	 */
+	public abstract CDasherModule GetModule(long iID);
+	
+	/**
+	 * Gets the name of a module by UID.
+	 * 
+	 * @param iID UID of the requested module
+	 * @return Name of the requested module, or "Not Implemented" if there
+	 * is no such module
+	 */
+	public abstract String GetName(long iID);
+	
+	/**
+	 * Gets the type of a given module by UID.
+	 * 
+	 * @param iID UID of the requested module
+	 * @return Type of the given module, or 0 if there is no such module
+	 */
+	public abstract int GetType(long iID);
+	
+}

Added: trunk/java/dasher/CModuleManager.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CModuleManager.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,123 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Collection;
+
+/**
+ * Helper class for the InterfaceBase which enumerates the modules
+ * present in supplied module factories and returns said modules
+ * by ID or by name on request.
+ * <p>
+ * A list of all available modules can also be supplied.
+ */
+public class CModuleManager {
+	
+	/**
+	 * Map from modules' IDs to the modules themselves
+	 */
+	protected HashMap<Long, CModuleFactory> m_mapModules = new HashMap<Long, CModuleFactory>();
+	
+	/**
+	 * Enumerates all modules provided by a given factory and stores
+	 * them in our internal map.
+	 * <p>
+	 * These modules can henceforth be retrieved using GetModuleByName
+	 * or GetModule.
+	 * 
+	 * @param Factory Factory to search for new modules
+	 */
+	public void RegisterFactory(CModuleFactory Factory) {
+		Factory.Start();
+		SFactoryInfo info = new SFactoryInfo();
+		while(Factory.IsMore()) {
+		
+			/* CSFS: This wants to update three variables, so I have altered the call
+			 * to return a small struct
+			 */
+			
+			
+			info = Factory.GetNext(info);
+			
+			m_mapModules.put(info.iID, Factory);
+		}
+	}
+	
+	/**
+	 * Gets a module with the given identifier
+	 * 
+	 * @param iID ID of the required module
+	 * @return Matching Module, or null if none was found.
+	 */
+	public CDasherModule GetModule(long iID) {
+		// TODO: Error checking here
+		
+		return m_mapModules.get(iID).GetModule(iID);
+	}
+	
+	/**
+	 * Retrieves a module by name. The module must previously
+	 * have been registered using RegisterFactory.
+	 * 
+	 * @param strName Name of the requested module
+	 * @return Module with this name, or null if there is none.
+	 */
+	public CDasherModule GetModuleByName(String strName) {
+		
+		for(Map.Entry<Long, CModuleFactory> s : m_mapModules.entrySet()) {
+			if (s.getValue().GetName(s.getKey()).equals(strName)) {
+				return s.getValue().GetModule(s.getKey());
+			}
+		}
+		
+		return null;
+	}
+	
+	/**
+	 * Retrieves a list of all modules with a given type.
+	 * <p>
+	 * Available types:
+	 * <p>
+	 * 0 - Input device
+	 * <p>
+	 * 1 - Input filter
+	 *  
+	 * @param iType Type of modules to enumerate
+	 * @param vList Collection to be filled with the names of available
+	 * modules
+	 */
+	public void ListModules(int iType, Collection<String> vList) {
+		for(Map.Entry<Long, CModuleFactory> s : m_mapModules.entrySet()) {
+			if(s.getValue().GetType(s.getKey()) == iType) {
+				vList.add(s.getValue().GetName(s.getKey()));
+			}
+		}
+	}
+	
+
+}

Added: trunk/java/dasher/CNodeManager.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CNodeManager.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,169 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.ArrayList;
+
+/**
+ * A NodeManager is used by the DasherModel to perform
+ * tasks which require some knowledge about the collection of
+ * Nodes besides the Model's highly general view. 
+ * This includes the handling of output when the
+ * user enters or leaves a given node and extending the Model's
+ * tree of DasherNodes, either forwards or backwards, whenever
+ * necessary.
+ */
+public abstract class CNodeManager {
+	
+	/**
+	 * Our unique ID
+	 */
+	protected int m_iID;
+	
+	/**
+	 * Creates a new NodeManager with a given ID
+	 * 
+	 * @param iID ID to use
+	 */
+	public CNodeManager(int iID) {
+		m_iID = iID;
+	}
+	
+	/**
+	 * Gets our unique ID
+	 * 
+	 * @return UID
+	 */
+	public int GetID() {
+		return m_iID;
+	}
+	
+	/**
+	 * Increment this manager's reference count.
+	 */
+	public abstract void Ref();
+	
+	/**
+	 * Decrement this manager's reference count. We can safely
+	 * destroy any allocated resources when this reaches zero.
+	 */
+	public abstract void Unref();
+	
+	/**
+	 * Produces a new root Node belonging to this NodeManager
+	 * 
+	 * @param Parent Parent to which the new root will be a child
+	 * @param iLower New node's lower probability bound with respect to its parent
+	 * @param iUpper New node's upper probability bound with respect to its parent
+	 * @param UserData Usage depends on the type of NodeManager
+	 * @return new root CDasherNode
+	 */
+	public abstract CDasherNode GetRoot(CDasherNode Parent, long iLower, long iUpper, int UserData); // VOID POINTER CHANGED TO INT 
+	
+	/**
+	 * Fills this Node's child list.
+	 * 
+	 * @param Node Node to populate
+	 */
+	public abstract void PopulateChildren( CDasherNode Node );
+	
+	/**
+	 * Removes all references to this node and deallocates storage
+	 * if appropriate. Essentially we should do whatever is necessary
+	 * to make this Node available for garbage collection.
+	 * 
+	 * @param Node Node to free
+	 */
+	public abstract void ClearNode(CDasherNode Node);
+	
+	/**
+	 * Performs output appropriate to a given Node, if any.
+	 * <p>
+	 * This method will be called when a user enters a given Node.
+	 * <p>
+	 * This method is defined to do nothing in this class; if
+     * a subclass does not wish to take action at this point, it
+     * is safe to avoid overriding this.
+	 * 
+	 * @param Node Node to output
+	 * @param Added CSymbolProbs detailing what has been output should
+	 * be added to this list
+	 * @param iNormalization Normalisation value (total to which
+	 * node probabilities always add up)
+	 */
+	public void Output(CDasherNode Node, ArrayList<CSymbolProb> Added, int iNormalization)	{}
+    
+	/**
+	 * Reverse or undo the output associated with a given Node
+	 * <p>
+	 * This method is defined to do nothing in this class; if
+     * a subclass does not wish to take action at this point, it
+     * is safe to avoid overriding this. 
+	 * 
+	 * @param Node Node to undo
+	 */
+	public void Undo( CDasherNode Node ) {}
+
+    /**
+     * Signals that the user has entered a given Node. Output
+     * should not be performed at this stage.
+     * <p>
+     * This method is defined to do nothing in this class; if
+     * a subclass does not wish to take action at this point, it
+     * is safe to avoid overriding this.
+     * 
+     * @param Node
+     */
+	public void Enter(CDasherNode Node) {}
+    
+	/**
+	 * Signals that the user has left a given Node. Output should
+	 * not be performed at this stage.
+	 * <p>
+	 * This method is defined to do nothing in this class; if
+     * a subclass does not wish to take action at this point, it
+     * is safe to avoid overriding this.
+	 * 
+	 * @param Node Node to be left
+	 */
+    public void Leave(CDasherNode Node) {}
+
+    /**
+     * Rebuild's the parent of a given Node.
+     * <p>
+     * The new Node should have all of its children populated, one
+     * of which should be the supplied Node.
+     * <p>
+     * See CAlphabetManager for a concrete example.
+     * 
+     * @param Node Node whose parent is to be rebuilt
+     * @param iGeneration Tree depth of the node to be created
+     * @return Parent of the input Node
+     */
+    public CDasherNode RebuildParent (CDasherNode Node, int iGeneration) {
+      return null;
+    }
+}

Added: trunk/java/dasher/CNodeManagerFactory.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CNodeManagerFactory.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,43 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * NodeManager Factory
+ */
+public abstract class CNodeManagerFactory {
+	
+	/**
+	 * Produces a new root Node belonging to this NodeManager
+	 * 
+	 * @param Parent Parent to which the new root will be a child
+	 * @param iLower New node's lower probability bound with respect to its parent
+	 * @param iUpper New node's upper probability bound with respect to its parent
+	 * @param UserData Usage depends on the type of NodeManager
+	 * @return new root CDasherNode
+	 */
+	public abstract CDasherNode GetRoot(CDasherNode Parent, long iLower, long iUpper, int UserData);
+}

Added: trunk/java/dasher/CPPMLanguageModel.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CPPMLanguageModel.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,649 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+
+package dasher;
+
+/**
+ * Subclass of LanguageModel which implements Prediction by
+ * Partial Match. For information on the algorithm and its 
+ * implementation, see (http://www.compression-links.info/PPM).
+ * <p>
+ * For the general contract obeyed by LanguageModel methods, see
+ * the documentation of CLanguageModel.
+ */
+public class CPPMLanguageModel extends CLanguageModel {
+
+	public CPPMContext m_RootContext;
+	public CPPMnode m_Root;
+
+	public int m_iMaxOrder;
+	public double m_dBackOffConstat;
+
+	public int NodesAllocated;
+
+	public boolean bUpdateExclusion;
+
+	private long lpAlpha;
+	private long lpBeta;
+
+	// public CSimplePooledAlloc < CPPMnode > m_NodeAlloc;
+	// public CPooledAlloc < CPPMContext > m_ContextAlloc;
+
+	/* CSFS: I have modified this to use GC for allocation for the time being; the memory
+	 * pools are next to useless in a garbage-collected language anyway since you can't
+	 * return a pointer to a free location. I will modify this later to use something
+	 * which works in a GC language AND is efficient.
+	 */
+
+	/* class BinaryRecord {
+    	  public int m_iIndex;
+    	  public int m_iChild;
+    	  public int m_iNext;
+    	  public int m_iVine;
+    	  public int m_iCount;
+    	  public short m_iSymbol;
+    	  } */ // This is part of the LMIO framework and so is not needed at present.
+
+	/**
+	 * Class representing a context which contains information
+	 * relevant to the PPM model.
+	 */
+	class CPPMContext extends CContextBase {
+
+		private CPPMnode head;
+		private int order;
+
+		public CPPMContext(CPPMnode _head, int _order) {
+			this.head = _head;
+			this.order = _order;
+		};
+
+		/* CSFS: Because bah, Java provides no possibility of
+		 * default values in the constructor,
+		 * necessitating lots of constructors.
+		 */
+
+		public CPPMContext(int _order) {
+			this.head = null;
+			this.order = _order;
+		};
+
+		public CPPMContext(CPPMnode _head)  {
+			this.head = _head;
+			this.order = 0;
+		};
+
+		public CPPMContext() {
+			this.head = null;
+			this.order = 0;
+		};
+
+		public CPPMContext(CPPMContext input) {
+			this.head = input.head;
+			this.order = input.order;
+		}
+	}
+
+	/**
+	 * Node in PPM's prediction trie.
+	 * 
+	 * @see CPPMLanguageModel
+	 */
+	class CPPMnode {
+		public CPPMnode child;
+		public CPPMnode next;
+		public CPPMnode vine;
+		public short count;
+		public int symbol;
+
+		/* CSFS: Found that the C++ code used a short
+		 * to represent a symbol in certain places and an
+		 * int in others. As such, I've changed it to int
+		 * everywhere. This ought to cause no trouble
+		 * except in the case that behaviour on overflow
+		 * is relied upon.
+		 */
+
+		public CPPMnode(int sym) {
+			child = null;
+			next = null;
+			vine = null;
+			count = 1;
+			symbol = sym;
+		}
+
+		public CPPMnode() {
+			child = null;
+			next = null;
+			vine = null;
+			count = 1;
+		}
+
+		public CPPMnode find_symbol(int sym) // see if symbol is a child of node
+		{
+			CPPMnode found = child;
+
+			/* CSFS: I *think* this is supposed to be a pointer-copy but
+			 * I'm not perfectly sure. If the find_symbol method fails,
+			 * this may need to become a .clone()
+			 */
+
+			while(found != null) {
+				if(found.symbol == sym) {
+					return found;
+				}
+				found = found.next;
+			}
+			return null;
+		}
+	}
+
+	/**
+	 * Small struct for use by CPPMLanguageModel's
+	 * AddSymbol method.
+	 * 
+	 * @see CPPMLanguageModel
+	 */
+	class CAddSymReturnValue {
+		public CPPMnode node;
+		public int update;
+	}
+
+	public CPPMLanguageModel(CEventHandler EventHandler, CSettingsStore SettingsStore, CSymbolAlphabet SymbolAlphabet) {
+
+		super(EventHandler, SettingsStore, SymbolAlphabet); // Constructor of CLanguageModel
+		m_iMaxOrder = 4;
+		NodesAllocated = 0;
+		// m_NodeAlloc = new CSimplePooledAlloc<CPPMnode>(8192);
+		// m_ContextAlloc = new CPooledAlloc<CPPMContext>(1024);
+		m_Root = new CPPMnode(); // m_NodeAlloc.Alloc();
+		m_Root.symbol = -1;
+
+		m_RootContext = new CPPMContext();// m_ContextAlloc.Alloc();
+		m_RootContext.head = m_Root;
+		m_RootContext.order = 0;
+
+		// Cache the result of update exclusion - otherwise we have to look up a lot when training, which is slow
+
+		// FIXME - this should be a boolean parameter
+
+		bUpdateExclusion = ( GetLongParameter(Elp_parameters.LP_LM_UPDATE_EXCLUSION) !=0 );
+
+		lpAlpha = GetLongParameter(Elp_parameters.LP_LM_ALPHA);
+		lpBeta = GetLongParameter(Elp_parameters.LP_LM_BETA);
+
+	}
+
+	public void HandleEvent(CEvent Event) {
+		super.HandleEvent(Event);
+
+		if(Event.m_iEventType == 1) { // Parameter change notification
+			CParameterNotificationEvent evt = (CParameterNotificationEvent)Event;
+			if(evt.m_iParameter == Elp_parameters.LP_LM_ALPHA) {
+				lpAlpha = GetLongParameter(Elp_parameters.LP_LM_ALPHA);
+			}
+			else if(evt.m_iParameter == Elp_parameters.LP_LM_BETA) {
+				lpBeta = GetLongParameter(Elp_parameters.LP_LM_BETA);
+			}
+		}
+	}
+
+	public int GetMemory() {
+		return NodesAllocated;
+	}
+
+	public long[] GetProbs(CContextBase context, long norm) {
+
+		/* CSFS: In the original C++ the norm value was an
+		 * unsigned int. Since Java will only provide a signed
+		 * int with half the capacity, I've converted it to a long.
+		 */
+
+		/* CSFS: All exclusion-related code commented out as it was wasting
+		 * time, and was disabled by boolean doExclusion = false; anyway.
+		 */
+
+		// System.out.printf("Sending probs for context %s%n", context);
+
+		final CPPMContext ppmcontext = (CPPMContext)(context);
+
+		int iNumSymbols = GetSize();
+
+		long[] probs = new long[iNumSymbols + 1];
+		//boolean[] exclusions = new boolean[iNumSymbols];
+
+		// probs.setSize(iNumSymbols);
+
+		//ArrayList<Boolean> exclusions = new ArrayList<Boolean>(iNumSymbols);
+		//exclusions.setSize(iNumSymbols);
+
+		int i;
+		//for(i = 0; i < iNumSymbols; i++) {
+		//  probs.setElementAt(0L, i);
+		//  exclusions.setElementAt(false, i);
+		//} 
+
+		//  bool doExclusion = GetLongParameter( LP_LM_ALPHA );
+//		boolean doExclusion = false; //FIXME
+
+		long iToSpend = norm;
+
+		CPPMnode pTemp = ppmcontext.head;
+
+		while(pTemp != null) {
+			int iTotal = 0;
+
+			/* CSFS: Various changes in what follows to convert
+			 * from libc-type ArrayLists to Java ArrayLists. Also a variety
+			 * of small alterations like changing if(pSymbol) to
+			 * if(pSymbol != null) since Java doesn't know about
+			 * null pointers.
+			 */
+
+			CPPMnode pSymbol = pTemp.child;
+			while(pSymbol != null) {
+				// if(!(exclusions.elementAt(sym) && doExclusion))
+				iTotal += pSymbol.count;
+				pSymbol = pSymbol.next;
+			}
+
+			if(iTotal != 0) {
+				long size_of_slice = iToSpend;
+				/* Changed type to long so that we don't run into trouble with overflows. */
+				pSymbol = pTemp.child;
+				while(pSymbol != null) {
+					//if(!(exclusions[pSymbol.symbol] && doExclusion)) {
+					//  exclusions[pSymbol.symbol] = true;
+
+					long p = (size_of_slice) * (100 * pSymbol.count - lpBeta) / (100 * iTotal + lpAlpha);
+
+					probs[pSymbol.symbol] += p;
+					iToSpend -= p;
+					//}
+					pSymbol = pSymbol.next;
+				}
+			}
+			pTemp = pTemp.vine;
+		}
+
+		long size_of_slice = iToSpend;
+		int symbolsleft = 0;
+
+		for(i = 1; i < iNumSymbols; i++) symbolsleft++;
+		//if(!(exclusions[i] && doExclusion))
+
+
+		for(i = 1; i < iNumSymbols; i++) {
+			//if(!(exclusions[i] && doExclusion)) {
+			long p = size_of_slice / symbolsleft;
+			probs[i] += p;
+			iToSpend -= p;
+			//}
+		}
+
+		int iLeft = iNumSymbols-1;
+
+		for(int j = 1; j < iNumSymbols; ++j) {
+			long p = iToSpend / iLeft;
+			probs[j] += p;
+			--iLeft;
+			iToSpend -= p;
+		}
+
+		assert(iToSpend == 0);
+
+		return probs;
+	}
+
+	private void AddSymbol(CPPMContext context, int sym)
+	// add symbol to the context
+	// creates new nodes, updates counts
+	// and leaves 'context' at the new context
+	{
+		// Ignore attempts to add the root symbol
+
+
+		if(sym==0) return;
+
+		assert(sym >= 0 && sym < GetSize());
+
+		CPPMnode vineptr, temp;
+		int updatecnt = 1;
+
+		temp = context.head.vine;
+
+		/* CSFS: AddSymbolToNode calls want to update two values, one of which
+		 * is a primitive and passed by value in Java. Therefore I have modified it
+		 * to return a small wrapper class, doubtless at the expense of some
+		 * performance.
+		 */
+
+		CAddSymReturnValue temp2 = AddSymbolToNode(context.head, sym, updatecnt);
+		context.head = temp2.node;
+
+		updatecnt = temp2.update;
+
+		vineptr = context.head;
+		context.order++;
+		while(temp != null) {
+			temp2 = AddSymbolToNode(temp, sym, updatecnt);
+			vineptr.vine = temp2.node;
+			updatecnt = temp2.update;
+			vineptr = vineptr.vine;
+			temp = temp.vine;
+		}
+		vineptr.vine = m_Root;
+
+		m_iMaxOrder = (int)GetLongParameter( Elp_parameters.LP_LM_MAX_ORDER );
+
+		while(context.order > m_iMaxOrder) {
+			context.head = context.head.vine;
+			context.order--;
+		}
+	}
+
+	public void EnterSymbol(CContextBase c, int Symbol) {
+		if(Symbol==0) return;
+
+		assert(Symbol >= 0 && Symbol < GetSize());
+
+		CPPMContext context = (CPPMContext) (c);
+
+		CPPMnode find;
+
+		while(context.head != null) {
+
+			if(context.order < m_iMaxOrder) {   // Only try to extend the context if it's not going to make it too long
+				find = context.head.find_symbol(Symbol);
+				if(find != null) {
+					context.order++;
+					context.head = find;
+					return;
+				}
+			}
+
+			// If we can't extend the current context, follow vine pointer to shorten it and try again
+
+			context.order--;
+			context.head = context.head.vine;
+		}
+
+		if(context.head == null) {
+			context.head = m_Root;
+			context.order = 0;
+		}
+
+	}	
+
+	public void LearnSymbol(CContextBase c, int Symbol) {
+		if(Symbol==0)
+			return;
+
+		assert(Symbol >= 0 && Symbol < GetSize());
+		CPPMContext context = (CPPMContext) (c);
+		AddSymbol(context, Symbol);
+
+		// System.out.printf("Learn symbol %d with context %s%n", Symbol, c);
+	}
+
+	/**
+	 * Diagnostic method; prints a given symbol.
+	 * 
+	 * @param sym Symbol to print
+	 */
+	public void dumpSymbol(int sym) {
+
+		/* CSFS: This method appears never to be referenced.
+		 * It exists only here and in one Japanese class.
+		 */
+
+		if((sym <= 32) || (sym >= 127))
+			System.out.printf("<%d>", sym);
+		else
+			System.out.printf("%c", sym);
+	}
+
+	/**
+	 * Diagnostic method; prints a given String starting
+	 * at pos and with length len.
+	 * 
+	 * @param str String to print
+	 * @param pos Position to start printing
+	 * @param len Number of characters to print
+	 */
+	public void dumpString(String str, int pos, int len)
+	// Dump the string STR starting at position POS
+	{
+		char cc;
+		int p;
+		for(p = pos; p < pos + len; p++) {
+			cc = str.charAt(p);
+			if((cc <= 31) || (cc >= 127))
+				System.out.printf("<%d>", cc);
+			else
+				System.out.printf("%c", cc);
+		}
+	}
+
+	private CAddSymReturnValue AddSymbolToNode(CPPMnode Node, int sym, int updatein) {
+		CPPMnode Return = Node.find_symbol(sym);
+
+		int updateout = updatein;
+
+		if(Return != null) {
+
+			if(updatein != 0 || !bUpdateExclusion) {  // perform update exclusions
+
+				/* CSFS: BUGFIX: This used to read 'bUpdateExclusion' without the !
+				 * This led to the language model generating probabilities which were
+				 * just ever so slightly off. FIXED.
+				 */
+
+				Return.count++;
+				updateout = 0;
+			}
+			CAddSymReturnValue retval = new CAddSymReturnValue();
+			retval.node = Return;
+			retval.update = updateout;
+			return retval;
+		}
+
+		Return = new CPPMnode(); //m_NodeAlloc.Alloc();        // count is initialized to 1
+		Return.symbol = sym;
+		Return.next = Node.child;
+		Node.child = Return;
+
+		++NodesAllocated;
+
+		CAddSymReturnValue retval = new CAddSymReturnValue();
+		retval.node = Return;
+		retval.update = updateout;
+		return retval;
+
+	}
+
+	/* Excluded methods: it appears the DumpTrie methods are still
+	 * being written as they are festooned with TODO tags. It looks
+	 * as if nobody ever uses them, so I've excluded them for now.
+	 */
+
+	/*boolean WriteToFile(String strFilename) {
+
+
+		std::map<CPPMnode *, int> mapIdx;
+		int iNextIdx(1); // Index of 0 means NULL;
+
+		std::ofstream oOutputFile(strFilename.c_str());
+
+		RecursiveWrite(m_pRoot, &mapIdx, &iNextIdx, &oOutputFile);
+
+		oOutputFile.close();
+
+		return false; 
+
+		}*/
+
+	/* CSFS: This and following methods commented out where it appears
+	 * they do not currently get used. Would be good to get Java IO
+	 * going in the future, but for now it's pointless until the
+	 * authors of the original C++ version actually use the functions.
+	 */
+
+	/* TODO: Rewrite this I/O framework and find out how
+	 * it ought to be plumbed into Dasher at large.
+	 */
+
+	/* boolean RecursiveWrite(CPPMnode *pNode, std::map<CPPMnode *, int> *pmapIdx, int *pNextIdx, std::ofstream *pOutputFile) {
+
+		  // Dump node here
+
+		  BinaryRecord sBR;
+
+		  sBR.m_iIndex = GetIndex(pNode, pmapIdx, pNextIdx); 
+		  sBR.m_iChild = GetIndex(pNode->child, pmapIdx, pNextIdx); 
+		  sBR.m_iNext = GetIndex(pNode->next, pmapIdx, pNextIdx); 
+		  sBR.m_iVine = GetIndex(pNode->vine, pmapIdx, pNextIdx);
+		  sBR.m_iCount = pNode->count;
+		  sBR.m_iSymbol = pNode->symbol;
+
+		  pOutputFile->write(reinterpret_cast<char*>(&sBR), sizeof(BinaryRecord));
+
+		  CPPMnode *pCurrentChild(pNode->child);
+
+		  while(pCurrentChild != NULL) {
+		    RecursiveWrite(pCurrentChild, pmapIdx, pNextIdx, pOutputFile);
+		    pCurrentChild = pCurrentChild->next;
+		  }
+
+		  return true;
+		}; */
+
+	/* int CPPMLanguageModel::GetIndex(CPPMnode *pAddr, std::map<CPPMnode *, int> *pmapIdx, int *pNextIdx) {
+
+		  int iIndex;
+		  if(pAddr == NULL)
+		    iIndex = 0;
+		  else {
+		    std::map<CPPMnode *, int>::iterator it(pmapIdx->find(pAddr));
+
+		    if(it == pmapIdx->end()) {
+		      iIndex = *pNextIdx;
+		      pmapIdx->insert(std::pair<CPPMnode *, int>(pAddr, iIndex));
+		      ++(*pNextIdx);
+		    }
+		    else {
+		      iIndex = it->second;
+		    }
+		  }
+		  return iIndex;
+		}; */
+
+	/* boolean ReadFromFile(std::string strFilename) {
+
+		  std::ifstream oInputFile(strFilename.c_str());
+		  std::map<int, CPPMnode*> oMap;
+		  BinaryRecord sBR;
+		  bool bStarted(false);
+
+		  while(!oInputFile.eof()) {
+		    oInputFile.read(reinterpret_cast<char *>(&sBR), sizeof(BinaryRecord));
+
+		    CPPMnode *pCurrent(GetAddress(sBR.m_iIndex, &oMap));
+
+		    pCurrent->child = GetAddress(sBR.m_iChild, &oMap);
+		    pCurrent->next = GetAddress(sBR.m_iNext, &oMap);
+		    pCurrent->vine = GetAddress(sBR.m_iVine, &oMap);
+		    pCurrent->count = sBR.m_iCount;
+		    pCurrent->symbol = sBR.m_iSymbol;
+
+		    if(!bStarted) {
+		      m_pRoot = pCurrent;
+		      bStarted = true;
+		    }
+		  }
+
+		  oInputFile.close();
+
+		  return false;
+		} */
+
+	/* CPPMLanguageModel::CPPMnode *CPPMLanguageModel::GetAddress(int iIndex, std::map<int, CPPMnode*> *pMap) {
+		  std::map<int, CPPMnode*>::iterator it(pMap->find(iIndex));
+
+		  if(it == pMap->end()) {
+		    CPPMnode *pNewNode;
+		    pNewNode = m_NodeAlloc.Alloc();
+		    pMap->insert(std::pair<int, CPPMnode*>(iIndex, pNewNode));
+		    return pNewNode;
+		  }
+		  else {
+		    return it->second;
+		  }
+		} */
+
+	/* CPPMLanguageModel and others: These were using a 
+	 * horrible hack wherein an integer (really a CPPMContext * ) 
+	 * was being used to represent the context of a given node when 
+	 * outside the generating class, in order that it could be
+	 * swapped out for some other CLanguageModel derivation and retain 
+	 * type-compatibility at the expense of being entirely type-unsafe. 
+	 * Since Java doesn't like to be type unsafe, I've replaced this by 
+	 * all Context-representing classes being a child of CContextBase, which 
+	 * has no members or methods, thus retaining type-safety. */
+
+	public CContextBase CreateEmptyContext() {
+		CPPMContext Cont = new CPPMContext(); // m_ContextAlloc.Alloc();
+		Cont.head = m_RootContext.head;
+		Cont.order = m_RootContext.order;
+
+		// System.out.printf("Creating new context: %s%n", Cont);
+
+		return Cont;
+
+
+	}
+
+	public CContextBase CloneContext(CContextBase Input) {
+		CPPMContext Cont = new CPPMContext(); // m_ContextAlloc.Alloc();
+		CPPMContext Copy = (CPPMContext) Input;
+		Cont.head = Copy.head;
+		Cont.order = Copy.order;
+
+		// System.out.printf("Cloning context %s to %s%n", Input, Cont);
+
+		return Cont;
+	}
+
+	public void ReleaseContext(CContextBase release) {
+
+		// System.out.printf("Releasing context %s%n", release);
+
+		release = null; //m_ContextAlloc.Free((CPPMContext) release);
+
+
+	}
+
+}

Added: trunk/java/dasher/CParamTables.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CParamTables.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,258 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Enumeration of possible Dasher settings, including their internal
+ * names, friendly names, default values, and a flag indicating whether
+ * they are persistent and should be stored across sessions.
+ * <p>
+ * The set of available parameters is currently hard-coded into
+ * this class.
+ * <p>
+ * If a new parameter must be created, an external identifier should
+ * be added to Ebp_parameters, Elp_parameters or Esp_parameters for
+ * a boolean, integer or string parameter respectively, and then an
+ * entry added to the appropriate table in this class.
+ */
+public class CParamTables {
+	
+	/**
+	 * Value indicating a persistent setting
+	 */
+	public final boolean PERS = true;
+	
+	/**
+	 * Table of all available boolean parameters.
+	 */	
+	public bp_table[] BoolParamTable = {
+			  new bp_table(Ebp_parameters.BP_DRAW_MOUSE_LINE, "DrawMouseLine", PERS, true, "Draw Mouse Line"),
+			  new bp_table(Ebp_parameters.BP_DRAW_MOUSE, "DrawMouse", PERS, true, "Draw Mouse Position"),
+			  new bp_table(Ebp_parameters.BP_SHOW_SLIDER, "ShowSpeedSlider", PERS, true, "ShowSpeedSlider"),
+			  new bp_table(Ebp_parameters.BP_START_MOUSE, "StartOnLeft", PERS, true, "StartOnLeft"),
+			  new bp_table(Ebp_parameters.BP_START_SPACE, "StartOnSpace", PERS, false, "StartOnSpace"),
+			  new bp_table(Ebp_parameters.BP_START_STYLUS, "StartOnStylus", PERS, false, "StartOnStylus"),
+			  new bp_table(Ebp_parameters.BP_STOP_IDLE, "StopOnIdle", PERS, false, "StopOnIdle"),
+			  new bp_table(Ebp_parameters.BP_KEY_CONTROL, "KeyControl", PERS, false, "KeyControl"),
+			  new bp_table(Ebp_parameters.BP_CONTROL_MODE, "ControlMode", PERS, false, "ControlMode"),
+			  new bp_table(Ebp_parameters.BP_COLOUR_MODE, "ColourMode", PERS, true, "ColourMode"),
+			  new bp_table(Ebp_parameters.BP_MOUSEPOS_MODE, "StartOnMousePosition", PERS, false, "StartOnMousePosition"),
+			  new bp_table(Ebp_parameters.BP_OUTLINE_MODE, "OutlineBoxes", PERS, true, "OutlineBoxes"),
+			  new bp_table(Ebp_parameters.BP_PALETTE_CHANGE, "PaletteChange", PERS, true, "PaletteChange"),
+			  new bp_table(Ebp_parameters.BP_NUMBER_DIMENSIONS, "NumberDimensions", PERS, false, "NumberDimensions"),
+			  new bp_table(Ebp_parameters.BP_EYETRACKER_MODE, "EyetrackerMode", PERS, false, "EyetrackerMode"),
+			  new bp_table(Ebp_parameters.BP_AUTOCALIBRATE, "Autocalibrate", PERS, true, "Autocalibrate"),
+			  new bp_table(Ebp_parameters.BP_DASHER_PAUSED, "DasherPaused", !PERS, true, "Dasher Paused"),
+			  new bp_table(Ebp_parameters.BP_GAME_MODE, "GameMode", PERS, false, "Dasher Game Mode"),
+			  new bp_table(Ebp_parameters.BP_TRAINING, "Training", !PERS, false, "Provides locking during training"),
+			  new bp_table(Ebp_parameters.BP_REDRAW, "Redraw", !PERS, false, "Force a full redraw at the next timer event"),
+			  new bp_table(Ebp_parameters.BP_LM_DICTIONARY, "Dictionary", PERS, true, "Whether the word-based language model uses a dictionary"),
+			  new bp_table(Ebp_parameters.BP_LM_LETTER_EXCLUSION, "LetterExclusion", PERS, true, "Whether to do letter exclusion in the word-based model"),
+			  new bp_table(Ebp_parameters.BP_AUTO_SPEEDCONTROL, "AutoSpeedControl", PERS, true, "AutoSpeedControl"),
+			  new bp_table(Ebp_parameters.BP_CLICK_MODE, "ClickMode", PERS, false, "Dasher Click Mode"),
+			  new bp_table(Ebp_parameters.BP_LM_ADAPTIVE, "LMAdaptive", PERS, true, "Whether language model should learn as you enter text"),
+			  new bp_table(Ebp_parameters.BP_BUTTONONESTATIC, "ButtonOneStaticMode", PERS, false, "One-button static mode"),
+			  new bp_table(Ebp_parameters.BP_BUTTONONEDYNAMIC, "ButtonOneDynamicMode", PERS, false, "One-button dynamic mode"),
+			  new bp_table(Ebp_parameters.BP_BUTTONMENU, "ButtonMenuMode", PERS, false, "Button menu mode"),
+			  new bp_table(Ebp_parameters.BP_BUTTONPULSING, "ButtonPulsingMode", PERS, false, "One-button dynamic pulsing mode"),
+			  new bp_table(Ebp_parameters.BP_BUTTONSTEADY, "ButtonSteadyMode", PERS, true, "One-button dynamic steady mode"),
+			  new bp_table(Ebp_parameters.BP_BUTTONDIRECT, "ButtonDirectMode", PERS, false, "Three-button direct mode"),
+			  new bp_table(Ebp_parameters.BP_BUTTONFOURDIRECT, "ButtonFourDirectMode", PERS, false, "Four-button direct mode"),
+			  new bp_table(Ebp_parameters.BP_BUTTONALTERNATINGDIRECT, "ButtonAlternatingDirectMode", PERS, true, "Alternating direct mode"),
+			  new bp_table(Ebp_parameters.BP_COMPASSMODE, "ButtonCompassMode", PERS, false, "Compass mode"),
+			  new bp_table(Ebp_parameters.BP_SOCKET_INPUT_ENABLE, "SocketInputEnable", PERS, false, "Read pointer coordinates from network socket instead of mouse"),
+			  new bp_table(Ebp_parameters.BP_SOCKET_DEBUG, "SocketInputDebug", PERS, false, "Print information about socket input processing to console"),
+			  new bp_table(Ebp_parameters.BP_OLD_STYLE_PUSH, "OldStylePush", PERS, false, "Old style node pushing algorithm"),
+			  new bp_table(Ebp_parameters.BP_CIRCLE_START, "CircleStart", PERS, false, "Start on circle mode"),
+			  new bp_table(Ebp_parameters.BP_GLOBAL_KEYBOARD, "GlobalKeyboard", PERS, false, "Whether to assume global control of the keyboard"),
+			  new bp_table(Ebp_parameters.BP_DELAY_VIEW, "DelayView", !PERS, false, "Delayed dynamics (for two button mode)"),
+			  new bp_table(Ebp_parameters.BP_LM_REMOTE, "RemoteLM", PERS, false, "Language model is remote and responds asynchronously."),
+			  new bp_table(Ebp_parameters.BP_CONNECT_LOCK, "Connecting", !PERS, false, "Currently waiting for a connection to a remote LM; lock Dasher.")};
+	
+	/**
+	 * Table of all available integer parameters
+	 */
+	public lp_table[] LongParamTable = {
+			  new lp_table(Elp_parameters.LP_ORIENTATION, "ScreenOrientation", PERS, -2, "Screen Orientation"),
+			  new lp_table(Elp_parameters.LP_REAL_ORIENTATION, "RealOrientation", !PERS, 0, "Actual screen orientation (allowing for alphabet default)"),
+			  new lp_table(Elp_parameters.LP_MAX_BITRATE, "MaxBitRateTimes100", PERS, 80, "Max Bit Rate Times 100"),
+			  new lp_table(Elp_parameters.LP_VIEW_ID, "ViewID", PERS, 1, "ViewID"),
+			  new lp_table(Elp_parameters.LP_LANGUAGE_MODEL_ID, "LanguageModelID", PERS, 0, "LanguageModelID"),
+			  new lp_table(Elp_parameters.LP_DASHER_FONTSIZE, "DasherFontSize", PERS, 1, "DasherFontSize"),
+			  new lp_table(Elp_parameters.LP_UNIFORM, "UniformTimes1000", PERS, 50, "UniformTimes1000"),
+			  new lp_table(Elp_parameters.LP_YSCALE, "YScaling", PERS, 0, "YScaling"),
+			  new lp_table(Elp_parameters.LP_MOUSEPOSDIST, "MousePositionBoxDistance", PERS, 50, "MousePositionBoxDistance"),
+			  new lp_table(Elp_parameters.LP_STOP_IDLETIME, "StopIdleTime", PERS, 1000, "StopIdleTime" ),
+			  new lp_table(Elp_parameters.LP_TRUNCATION, "Truncation", PERS, 0, "Truncation"),
+			  new lp_table(Elp_parameters.LP_TRUNCATIONTYPE, "TruncationType", PERS, 0, "TruncationType"),
+			  new lp_table(Elp_parameters.LP_LM_MAX_ORDER, "LMMaxOrder", PERS, 5, "LMMaxOrder"),
+			  new lp_table(Elp_parameters.LP_LM_EXCLUSION, "LMExclusion", PERS, 0, "LMExclusion"),
+			  new lp_table(Elp_parameters.LP_LM_UPDATE_EXCLUSION, "LMUpdateExclusion", PERS, 1, "LMUpdateExclusion"),
+			  new lp_table(Elp_parameters.LP_LM_ALPHA, "LMAlpha", PERS, 49, "LMAlpha"),
+			  new lp_table(Elp_parameters.LP_LM_BETA, "LMBeta", PERS, 77, "LMBeta"),
+			  new lp_table(Elp_parameters.LP_LM_MIXTURE, "LMMixture", PERS, 50, "LMMixture"),
+			  new lp_table(Elp_parameters.LP_MOUSE_POS_BOX, "MousePosBox", !PERS, -1, "Mouse Position Box Indicator"),
+			  new lp_table(Elp_parameters.LP_NORMALIZATION, "Normalization", !PERS, 1 << 16, "Interval for child nodes"),
+			  new lp_table(Elp_parameters.LP_LINE_WIDTH, "LineWidth", PERS, 1, "Width to draw crosshair and mouse line"),
+			  new lp_table(Elp_parameters.LP_LM_WORD_ALPHA, "WordAlpha", PERS, 50, "Alpha value for word-based model"),
+			  new lp_table(Elp_parameters.LP_USER_LOG_LEVEL_MASK, "UserLogLevelMask", PERS, 0, "Controls level of user logging, 0 = none, 1 = short, 2 = detailed, 3 = both"),
+			  new lp_table(Elp_parameters.LP_SPEED_DIVISOR, "SpeedDivisor", !PERS, 100, "Factor by which to slow down (multiplied by 100)"),
+			  new lp_table(Elp_parameters.LP_ZOOMSTEPS, "Zoomsteps", PERS, 32, "Integerised ratio of zoom size for click/button mode, denom 64."),
+			  new lp_table(Elp_parameters.LP_B, "ButtonMenuBoxes", PERS, 4, "Number of boxes for button menu mode"),
+			  new lp_table(Elp_parameters.LP_S, "ButtonMenuSafety", PERS, 25, "Safety parameter for button mode, in percent."),
+			  new lp_table(Elp_parameters.LP_Z, "ButtonMenuBackwardsBox", PERS, 1, "Number of back-up boxes for button menu mode"),
+			  new lp_table(Elp_parameters.LP_R, "ButtonModeNonuniformity", PERS, 0, "Button mode box non-uniformity"),
+			  new lp_table(Elp_parameters.LP_RIGHTZOOM, "ButtonCompassModeRightZoom", PERS, 5120, "Zoomfactor (*1024) for compass mode"),
+			  new lp_table(Elp_parameters.LP_BOOSTFACTOR, "BoostFactor", !PERS, 100, "Boost/brake factor (multiplied by 100)"),
+			  new lp_table(Elp_parameters.LP_AUTOSPEED_SENSITIVITY, "AutospeedSensitivity", PERS, 100, "Sensitivity of automatic speed control (percent)"),
+			  new lp_table(Elp_parameters.LP_SOCKET_PORT, "SocketPort", PERS, 20320, "UDP/TCP socket to use for network socket input"),
+			  new lp_table(Elp_parameters.LP_SOCKET_INPUT_X_MIN, "SocketInputXMinTimes1000", PERS, 0, "Bottom of range of X values expected from network input"),
+			  new lp_table(Elp_parameters.LP_SOCKET_INPUT_X_MAX, "SocketInputXMaxTimes1000", PERS, 1000, "Top of range of X values expected from network input"),
+			  new lp_table(Elp_parameters.LP_SOCKET_INPUT_Y_MIN, "SocketInputYMinTimes1000", PERS, 0, "Bottom of range of Y values expected from network input"),
+			  new lp_table(Elp_parameters.LP_SOCKET_INPUT_Y_MAX, "SocketInputYMaxTimes1000", PERS, 1000, "Top of range of Y values expected from network input"),
+			  new lp_table(Elp_parameters.LP_OX, "OX", PERS, 2048, "X coordinate of crosshair"),
+			  new lp_table(Elp_parameters.LP_OY, "OY", PERS, 2048, "Y coordinate of crosshair"),
+			  new lp_table(Elp_parameters.LP_MAX_Y, "MaxY", PERS, 4096, "Maximum Y coordinate"),
+			  new lp_table(Elp_parameters.LP_INPUT_FILTER, "InputFilterID", PERS, 3, "Module ID of input filter"),
+			  new lp_table(Elp_parameters.LP_CIRCLE_PERCENT, "CirclePercent", PERS, 10, "Percentage of nominal vertical range to use for radius of start circle"),
+			  new lp_table(Elp_parameters.LP_TWO_BUTTON_OFFSET, "TwoButtonOffset", PERS, 1024, "Offset for two button dynamic mode")	};
+	
+	/**
+	 * Table of all available string parameters
+	 */
+	public sp_table[] StringParamTable = {
+			  new sp_table(Esp_parameters.SP_ALPHABET_ID, "AlphabetID", PERS, "", "AlphabetID"),
+			  new sp_table(Esp_parameters.SP_ALPHABET_1, "Alphabet1", PERS, "", "Alphabet History 1"),
+			  new sp_table(Esp_parameters.SP_ALPHABET_2, "Alphabet2", PERS, "", "Alphabet History 2"),
+			  new sp_table(Esp_parameters.SP_ALPHABET_3, "Alphabet3", PERS, "", "Alphabet History 3"),
+			  new sp_table(Esp_parameters.SP_ALPHABET_4, "Alphabet4", PERS, "", "Alphabet History 4"),
+			  new sp_table(Esp_parameters.SP_COLOUR_ID, "ColourID", PERS, "", "ColourID"), 
+			  new sp_table(Esp_parameters.SP_DEFAULT_COLOUR_ID, "DefaultColourID", !PERS, "", "Default Colour ID (Used for auto-colour mode)"),
+			  new sp_table(Esp_parameters.SP_DASHER_FONT, "DasherFont", PERS, "", "DasherFont"),
+			  new sp_table(Esp_parameters.SP_SYSTEM_LOC, "SystemLocation", !PERS, "sys_", "System Directory"),
+			  new sp_table(Esp_parameters.SP_USER_LOC, "UserLocation", !PERS, "usr_", "User Directory"),
+			  new sp_table(Esp_parameters.SP_GAME_TEXT_FILE, "GameTextFile", !PERS, "gamemode_english_GB.txt", "File with strings to practice writing"),
+			  new sp_table(Esp_parameters.SP_TRAIN_FILE, "TrainingFile", !PERS, "", "Training text for alphabet"),
+			  new sp_table(Esp_parameters.SP_SOCKET_INPUT_X_LABEL, "SocketInputXLabel", PERS, "x", "Label preceding X values for network input"),
+			  new sp_table(Esp_parameters.SP_SOCKET_INPUT_Y_LABEL, "SocketInputYLabel", PERS, "y", "Label preceding Y values for network input"),
+			  new sp_table(Esp_parameters.SP_INPUT_FILTER, "InputFilter", PERS, "Normal Control", "Input filter used to provide the current control mode"),
+			  new sp_table(Esp_parameters.SP_INPUT_DEVICE, "InputDevice", PERS, "Mouse Input", "Driver for the input device"),
+			  new sp_table(Esp_parameters.SP_LM_HOST, "LMHost", PERS, "", "Language Model Host")};
+}
+
+/**
+ * Struct detailing a boolean parameter 
+ */
+class bp_table {
+	
+	/**
+	 * Creates a new Boolean parameter
+	 * 
+	 * @param k Parameter (member of Ebp_parameters)
+	 * @param rName Internal name
+	 * @param pers Persistent
+	 * @param def Default value
+	 * @param hr Human-readable name
+	 */
+	public bp_table(Ebp_parameters k, String rName, boolean pers, boolean def, String hr) {
+		key = k.ordinal();
+		humanReadable = hr;
+		persistent = pers;
+		defaultVal = def;
+		value = def;
+		regName = rName;
+	}
+	
+	int key;
+	String regName;
+	boolean persistent;
+	boolean defaultVal;
+	boolean value;
+	String humanReadable;
+}
+
+/**
+ * Struct defining an integer parameter
+ */
+class lp_table {
+	
+	static private final int lp_offset = Ebp_parameters.values().length;
+	
+	/**
+	 * Creates a new integer parameter
+	 * 
+	 * @param k Parameter (member of Elp_parameters)
+	 * @param rName Internal name
+	 * @param pers Persistent
+	 * @param def Default value
+	 * @param hr Human-readable name
+	 */
+	public lp_table(Elp_parameters k, String rName, boolean pers, long def, String hr) {
+		key = k.ordinal() + lp_offset;
+		humanReadable = hr;
+		persistent = pers;
+		defaultVal = def;
+		value = def;
+		regName = rName;
+	}
+	
+	int key;
+	String regName;
+	boolean persistent;
+	long defaultVal;
+	long value;
+	String humanReadable;
+}
+
+/**
+ * Creates a new String parameter
+ * 
+ * @param k Parameter (member of Esp_parameters)
+ * @param rName Internal name
+ * @param pers Persistent
+ * @param def Default value
+ * @param hr Human-readable name
+ */
+class sp_table {
+	
+	static private final int sp_offset = Ebp_parameters.values().length + Elp_parameters.values().length;
+	
+	public sp_table(Esp_parameters k, String rName, boolean pers, String def, String hr) {
+		key = k.ordinal() + sp_offset;
+		humanReadable = hr;
+		persistent = pers;
+		defaultVal = def;
+		value = def;
+		regName = rName;
+	}
+	
+	int key;
+	String regName;
+	boolean persistent;
+	String value;
+	String defaultVal;
+	String humanReadable;
+}

Added: trunk/java/dasher/CParameterNotFoundException.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CParameterNotFoundException.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,56 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Exception to be thrown by a CSettingsStore object when it attempts
+ * to load a setting but is unable to find a record of it in its
+ * backing store.
+ * <p>
+ * This exception is caught within CSettingsStore, and is never
+ * seen by external classes.
+ * <p>
+ * Typically the SettingsStore responds to this problem by loading
+ * a default setting.
+ * <p>
+ * The base implementation of CSettingsStore throws this for all
+ * calls to LoadSetting, as it does not know about a backing store.
+ */
+public class CParameterNotFoundException extends Exception {
+	/**
+	 * Name of the parameter which couldn't be loaded.
+	 */
+	public String paramName;
+	
+	/**
+	 * Creates a new ParameterNotFoundException.
+	 * 
+	 * @param p Parameter which couldn't be loaded
+	 */
+	public CParameterNotFoundException(String p) {
+		this.paramName = p;
+	}
+}

Added: trunk/java/dasher/CParameterNotificationEvent.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CParameterNotificationEvent.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,50 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Event notifying components that a given parameter's value
+ * has changed, and so dependent components should reload
+ * its value.
+ */
+public class CParameterNotificationEvent extends CEvent {
+	
+	/**
+	 * Creates a new ParameterNotificationEvent
+	 * 
+	 * @param iParameter Parameter which has changed
+	 */
+	public CParameterNotificationEvent(EParameters iParameter) {
+	    m_iEventType = 1; // EV_PARAM_NOTIFY
+	    m_iParameter = iParameter;
+	}
+
+	/**
+	 * Changed parameter
+	 */
+	public EParameters m_iParameter;
+	
+}

Added: trunk/java/dasher/CRemoteAlphabetManager.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CRemoteAlphabetManager.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,174 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+/** 
+ * This is part of an experiment with remote language modelling. It is
+ * designed for use with the CRemotePPM language model. 
+ * <p>
+ * This class is designed to allow us to update nodes asynchronously whilst
+ * using as much of Dasher's existing code as possible. Historically, the task would go:
+ * <p><ul><li>AlphabetManager is asked to rebuild a node
+ * <li>It asks the Model for the probabilities required, supplying a 
+ * normalisation constant
+ * <li>Which in turn modifies this constant to produce 'non-uniform norm' and 
+ * asks the langauge model
+ * <li>The model takes the language model's reply and performs some 'post-processing'
+ * <li>Finally the alphManager can rebuild based on these probabilities
+ * </ul><p>
+ * My new schema is: When asked to populate a node, we note the details of the
+ * request and place it in a queue. We directly notify the language model of the
+ * requirement, supplying the model-calculated normalisation constant, the
+ * generation of which has been refactored out into a seperate function,
+ * getNonUniformNorm(int iNorm).
+ * <p>
+ * When the reply comes back, we apply the model's post-processing by calling
+ * AdjustProbs(long[] probs), which again used to be a part of the getProbs sequence
+ * but is now a seperate function so that the model *can* do its modifications
+ * on probabilities which come from elsewhere. The main codepath has been modified
+ * so that it calls the appropriate refactored functions, also increasing code
+ * readability.
+ */
+public class CRemoteAlphabetManager extends CAlphabetManager implements ProbsListener {
+	
+	/**
+	 * Struct describing a pending PopulateChildrenWithSymbol
+	 */
+	class PendingPopulate {
+		
+		/**
+		 * Node to be populated
+		 */
+		CDasherNode Node;
+		
+		/**
+		 * Symbol belonging to its existing child, if any
+		 */
+		int iExistingSymbol;
+		
+		/**
+		 * Existing child of the Node we are populating, if any
+		 */
+		CDasherNode ExistingChild;
+		
+	}
+
+	
+	/**
+	 * Queue of requests pending with the remote server
+	 */
+	private Queue<PendingPopulate> pendingPopulates;
+	
+	/**
+	 * Create a new RemoteAlphabetManager which uses a given Model
+	 * and LanguageModel to produce probabilities.
+	 * 
+	 * @param model Model which knows how to mangle probabilities
+	 * @param langmodel LanguageModel which produces probabilities
+	 */
+	public CRemoteAlphabetManager(CDasherModel model, CLanguageModel langmodel) {
+		super(model, langmodel);
+		pendingPopulates = new LinkedList<PendingPopulate>();
+		
+		((CRemotePPM)m_LanguageModel).RegisterProbsListener(this);
+		
+	}
+
+	/**
+	 * Override of CAlphabetManager's PopulateChildrenWithSymbol method.
+	 * <p>
+	 * Requests that our remote language model should produce probabilities
+	 * appropriate to this Node and returns without actually populating the
+	 * Node's children.
+	 * <p>
+	 * The population itself will be performed when our asynchronous
+	 * request completes; at this point, probsArrived() will be called.
+	 * 
+	 * @param Node Node whose children we are to populate
+	 * @param iExistingSymbol Symbol of the Node's existing child, if any
+	 * @param ExistingChild Pre-existing child of the Node we are to
+	 * populate, if any. Null if none. 
+	 */
+	public void PopulateChildrenWithSymbol(CDasherNode Node, int iExistingSymbol, CDasherNode ExistingChild) {
+		
+		PendingPopulate pend = new PendingPopulate();
+		
+		pend.Node = Node;
+		pend.iExistingSymbol = iExistingSymbol;
+		pend.ExistingChild = ExistingChild;
+		
+		pendingPopulates.add(pend);
+		
+		// Ordinarily the call to the language model would be made after getting this
+		// modified normalisation factor. I have altered the structure so that the
+		// normalisation factor can be retrieved seperately.
+		
+		((CRemotePPM)m_LanguageModel).PromptForProbs(Node.Context(), m_Model.getNonUniformNorm((int)m_Model.GetLongParameter(Elp_parameters.LP_NORMALIZATION)));
+		
+	}
+	
+	/**
+	 * Called by the LanguageModel when a request sent to the remote
+	 * language modelling server responds to a request.
+	 * <p>
+	 * This will perform the actual population by calling the ordinary
+	 * AlphabetManager's PopulateChildrenWithSymbol method.
+	 * 
+	 * @param probs Probabilities received
+	 */
+	public void probsArrived(long[] probs) {
+		
+		// System.out.printf("Probs arrived: %s%n", ShowArray(probs));
+		
+		m_Model.adjustProbs(probs);
+		// Apply the model's tweaks to the retrieved probabilities.
+		
+		PendingPopulate nextPopulate = pendingPopulates.remove();
+		
+		super.PopulateChildrenWithSymbol(nextPopulate.Node, nextPopulate.iExistingSymbol, nextPopulate.ExistingChild, probs);
+		
+		m_Model.m_DasherInterface.Redraw(true);
+		
+	}
+	
+}
+
+/**
+ * Interface to be implemented by classes which wish to be
+ * notified of the completion of asynchronous getProbs requests
+ * by CRemotePPM.
+ * <p>
+ * To actually receive notifications, one must also register with
+ * the LanguageModel using its RegisterProbsListener method.
+ */
+interface ProbsListener {
+	
+	public void probsArrived(long[] probs);
+	
+}

Added: trunk/java/dasher/CRemotePPM.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CRemotePPM.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,566 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.LinkedList;
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.io.IOException;
+
+/**
+ * Implements the client side of a remote language model. Whilst
+ * named RemotePPM, there is no reason why the remote side shouldn't
+ * operate some different language model.
+ * <p>
+ * For details on the server required, see the website at www.smowton.net/chris
+ * <p>
+ * For details of the PPM Language model see CPPMLanguageModel
+ * <p>
+ * For details of the general contract of a language model, see CLanguageModel.
+ */
+public class CRemotePPM extends CLanguageModel {
+
+	class RemotePPMContext extends CContextBase {
+		
+		public RemotePPMContext(int handle) {
+			contextHandle = handle;
+		}
+		
+		public int contextHandle;
+		
+	}
+
+	enum RemotePPMOperationType {
+		CLONE_CONTEXT, CREATE_EMPTY_CONTEXT, ENTER_SYMBOL, GET_PROBS, RELEASE_CONTEXT
+	}
+
+	abstract class RemotePPMOperation {
+		
+		public int m_clientID;
+		public RemotePPMOperationType m_opType; 
+		
+		public abstract byte[] toBytes();
+		
+	}
+
+	class ReleaseContextOp extends RemotePPMOperation {
+			
+		public int m_contextHandle;
+		
+		public ReleaseContextOp(int contextHandle) {
+			m_contextHandle = contextHandle;
+			m_opType = RemotePPMOperationType.RELEASE_CONTEXT;
+		}
+		
+		public byte[] toBytes() {
+			byte[] asBytes = new byte[5];
+			
+			asBytes[0] = 4; // Operation Identifier
+			
+			intToBytes(asBytes, m_contextHandle, 1);
+			
+			return asBytes;
+		}
+		
+	}
+
+	class CreateEmptyContextOp extends RemotePPMOperation {
+		
+		public int requestedHandle;
+
+		public CreateEmptyContextOp(int handle) {
+			requestedHandle = handle;
+			m_opType = RemotePPMOperationType.CREATE_EMPTY_CONTEXT;
+		}
+		
+		public byte[] toBytes() {
+			byte[] asBytes = new byte[5];
+			
+			asBytes[0] = 1; // Operation Identifier
+			
+			intToBytes(asBytes, requestedHandle, 1);
+			
+			return asBytes;
+		}
+		
+	}
+
+	class CloneContextOp extends RemotePPMOperation {
+		
+		public int requestedHandle;
+		public int existingHandle;
+
+		public CloneContextOp(int oldhandle, int newhandle) {
+			requestedHandle = newhandle;
+			existingHandle = oldhandle;
+			m_opType = RemotePPMOperationType.CLONE_CONTEXT;
+		}
+		
+		public byte[] toBytes() {
+			
+			byte[] asBytes = new byte[9];
+
+			asBytes[0] = 0; // Operation Identifier
+
+			intToBytes(asBytes, requestedHandle, 1);
+			intToBytes(asBytes, existingHandle, 5);
+
+			return asBytes;
+		}
+	}
+
+	class EnterSymbolOp extends RemotePPMOperation {
+		
+		public int Symbol;
+		public int m_contextHandle;
+		public boolean learn;
+		
+		public EnterSymbolOp(int handle, int sym, boolean learn) {
+			Symbol = sym;
+			m_contextHandle = handle;
+			this.learn = learn;
+			m_opType = RemotePPMOperationType.ENTER_SYMBOL;
+		}
+		
+		public byte[] toBytes() {
+
+			byte[] asBytes = new byte[10];
+
+			asBytes[0] = 2; // Operation Identifier
+
+			intToBytes(asBytes, m_contextHandle, 1);
+			intToBytes(asBytes, Symbol, 5);
+
+			if(learn) {
+				asBytes[9] = 1;
+			}
+			else {
+				asBytes[9] = 0;
+			}
+
+			return asBytes;
+		
+		}
+	}
+
+	class GetProbsOp extends RemotePPMOperation {
+		public int m_contextHandle;
+		public long m_Norm;
+		
+		public GetProbsOp(int handle, long norm) {
+			m_contextHandle = handle;
+			m_Norm = norm;
+			m_opType = RemotePPMOperationType.GET_PROBS;
+		}
+		
+		public byte[] toBytes() {
+			
+			byte[] asBytes = new byte[13];
+
+			asBytes[0] = 3; // Operation Identifier
+
+			intToBytes(asBytes, m_contextHandle, 1);
+			
+			longToBytes(asBytes, m_Norm, 5);
+			
+			return asBytes;
+		}
+		
+	}
+
+	class MessageDispatcherThread extends Thread {
+		
+		private CRemotePPM myParent;
+		private OutputStream networkStream;
+		private String m_host;
+		private int m_port;
+		private int m_symbolCount;
+		
+		private boolean alive;
+		
+		public MessageDispatcherThread(CRemotePPM parent, int nSymbols, String host, int port) throws UnknownHostException, IOException {
+			super();
+			myParent = parent;
+			m_host = host;
+			m_port = port;
+			m_symbolCount = nSymbols;
+			
+			this.setName("JDasher Network Dispatcher");
+			
+			alive = true;
+		}
+		
+		public void die() {
+			alive = false;
+		}
+		
+		public void run() {
+			
+			Socket sock;
+			
+			try {
+				sock = new Socket(m_host, m_port);
+			}
+			catch(Exception e) {
+				System.out.printf("Could not start MessageDispatcherThread: %s%n", e);
+				myParent.notifyNetworkFailure(0);
+				return;
+			}
+			try {
+				networkStream = sock.getOutputStream();
+			}
+			catch(IOException e) {
+				System.out.printf("Could not retrieve output stream in MessageDispatcherThread: %s%n", e);
+				myParent.notifyNetworkFailure(1);
+				return;
+			}
+			
+			MessageListenerThread listener;
+					
+			try {
+				listener = new MessageListenerThread(myParent, sock.getInputStream());
+				listener.start();
+			}
+			catch(IOException e) {
+				System.out.printf("Could not retrieve input stream in MessageDispatcherThread: %s%n", e);
+				myParent.notifyNetworkFailure(2);
+				return;
+			}
+			
+			myParent.SetBoolParameter(Ebp_parameters.BP_CONNECT_LOCK, false);
+			// We've successfully connected; unset the connecting flag!
+			
+			byte[] alphSize = new byte[4];
+			CRemotePPM.intToBytes(alphSize, m_symbolCount, 0);
+			
+			try {
+				networkStream.write(alphSize);
+			}
+			catch(IOException e) {
+				System.out.printf("Failed writing alphabet size to the server: %s%n", e);
+				myParent.notifyNetworkFailure(2);
+				return;
+			}
+			
+			while(alive) {
+						
+				myParent.transmitMessages(networkStream);
+				try {
+					Thread.sleep(100);
+					// FIXME improve this behaviour
+				}
+				catch(InterruptedException e) {
+					System.out.printf("Message dispatcher thread exited.%n");
+					myParent.notifyNetworkFailure(3);
+					break; // Stop the thread
+				}
+			}
+			
+			// We've left the loop -- this means we've been ordered to terminate.
+			
+			try {
+				sock.close();
+			}
+			catch(IOException e) {
+				System.out.printf("Dispatcher could not close socket: %s%n", e);
+			}
+			
+			// This should cause the listener to error out and terminate too.
+			
+		}
+	}
+
+	class MessageListenerThread extends Thread {
+		
+		private InputStream networkStream;
+		private CRemotePPM m_parent;
+		private boolean alive = true;
+		
+		public MessageListenerThread(CRemotePPM parent, InputStream in) {
+			m_parent = parent;
+			networkStream = in;
+			
+			this.setName("JDasher Network Listener");
+		}
+		
+		public void run() {
+			
+			 while(alive) {
+				 int arraySize = 0;
+				 
+				 byte arraySizeAsBytes[] = new byte[4];
+				 
+				 try {
+					 networkStream.read(arraySizeAsBytes);
+				 }
+				 catch(Exception e) {
+					 System.out.printf("Exception reading from InputStream: %s%n", e);
+					 break;
+				 }
+				 
+				 arraySize = intFromBytes(arraySizeAsBytes);
+				 
+				 long[] newProbs = new long[arraySize];
+				 
+				 for(int i = 0; i < arraySize; i++) {
+					 
+					 byte[] nextLongAsBytes = new byte[8];
+					 try {
+						 networkStream.read(nextLongAsBytes);
+					 }
+					 catch(Exception e) {
+						 System.out.printf("Exception reading from InputStream: %s%n", e);
+						 alive = false; // The socket has most likely closed; time to die.
+						 break;
+					 }
+					 			 
+					 newProbs[i] = longFromBytes(nextLongAsBytes);
+					 
+				 }
+				 
+				 if(alive == false) break; // Avoid sending a spurior probsArrived.
+				 
+				 m_parent.ProbsArrived(newProbs);
+			 }
+			
+		}
+		
+		private int intFromBytes(byte[] intBytes) {
+			int result = 0;
+
+			for(int i = 0; i < 4; i++) {
+				int nextbyte = (int)intBytes[i];
+				if(nextbyte < 0) nextbyte += 256;
+
+				result |= (nextbyte << ((3 - i)*8));
+			}
+
+			return result;
+		}
+
+		private long longFromBytes(byte[] longBytes) {
+			long result = 0;
+
+			for(int i = 0; i < 8; i++) {
+				long nextbyte = (long)longBytes[i];
+				if(nextbyte < 0) nextbyte += 256;
+
+				result |= (nextbyte << ((7 - i)*8));
+			}
+
+			return result;
+		}
+	}
+	
+	public static void intToBytes(byte[] destination, int input, int offset) {
+		for(int i = 0; i < 4; i++) {
+			destination[i + offset] = (byte)((input >>> (8 * (3 - i))) & 0xFF); 
+		}
+	}
+	
+	public static void longToBytes(byte[] destination, long input, int offset) {
+		for(int i = 0; i < 8; i++) {
+			destination[i + offset] = (byte)((input >>> (8 * (7 - i))) & 0xFF); 
+		}
+	}
+	
+	private int lastHandle;
+	
+	private MessageDispatcherThread dispatch;
+	
+	private LinkedList<RemotePPMOperation> pendingMessageQueue;
+	
+	private LinkedList<ProbsListener> eventListeners;
+	
+	public CRemotePPM(CEventHandler EventHandler, CSettingsStore SettingsStore, CSymbolAlphabet SymbolAlphabet) {
+		
+		super(EventHandler, SettingsStore, SymbolAlphabet); // Constructor of CLanguageModel
+		
+		pendingMessageQueue = new LinkedList<RemotePPMOperation>();
+		eventListeners = new LinkedList<ProbsListener>();
+				
+		try {
+			dispatch = new MessageDispatcherThread(this, SymbolAlphabet.GetSize(), GetStringParameter(Esp_parameters.SP_LM_HOST), 2111);
+			dispatch.start();
+		}
+		catch(Exception e) {
+			System.out.printf("Failed to start MessageDispatcherThread: %s%n", e);
+		}
+	}
+	
+	public CContextBase CloneContext(CContextBase Context) {
+		
+		/* We ask the server to create a new context with a handle we choose.
+		 * This is so that the method can return instantly and still pass
+		 * out a valid handle.
+		 */
+		
+		CloneContextOp newOp = new CloneContextOp(((RemotePPMContext)Context).contextHandle, GetUnusedHandle());
+		enQueueMessage(newOp);
+		
+		return new RemotePPMContext(newOp.requestedHandle);
+		
+	}
+
+	public CContextBase CreateEmptyContext() {
+		
+		/* As above */
+		
+		CreateEmptyContextOp newOp = new CreateEmptyContextOp(GetUnusedHandle());
+		enQueueMessage(newOp);
+		
+		return new RemotePPMContext(newOp.requestedHandle);
+		
+	}
+
+	public void EnterSymbol(CContextBase context, int Symbol) {
+		
+		/* Notify the server of a symbol to add to the specified context */
+		
+		EnterSymbolOp newOp = new EnterSymbolOp(((RemotePPMContext)context).contextHandle, Symbol, false);
+		enQueueMessage(newOp);
+		
+	}
+
+	public int GetMemory() {
+		
+		return 0;
+		
+	}
+
+	public void PromptForProbs(CContextBase Context, long iNorm) {
+		
+		GetProbsOp newOp = new GetProbsOp(((RemotePPMContext)Context).contextHandle, iNorm);
+		enQueueMessage(newOp);
+		
+	}
+	
+	public void ProbsArrived(long[] probs) {
+		
+		for(ProbsListener p : eventListeners) {
+			p.probsArrived(probs);
+		}
+	}
+	
+	public void RegisterProbsListener(ProbsListener it) {
+		
+		eventListeners.add(it);
+		
+	}
+	
+	public long[] GetProbs(CContextBase Context, long iNorm) {
+						
+		return null; // Not how it works for this class.
+		
+	}
+
+	public void LearnSymbol(CContextBase context, int Symbol) {
+
+		/* Similar to EnterSymbol, but the symbol is learned by the language
+		 * model and is used to alter its future predictions.
+		 */
+		
+		// System.out.printf("%d, %n", Symbol);
+		EnterSymbolOp newOp = new EnterSymbolOp(((RemotePPMContext)context).contextHandle, Symbol, true);
+		enQueueMessage(newOp);
+		
+	}
+
+	public void ReleaseContext(CContextBase Context) {
+		
+		/* Just releases the context being used, informing the server it can dispose
+		 * of the object and reclaim its memory.
+		 */
+		
+		ReleaseContextOp newOp = new ReleaseContextOp(((RemotePPMContext)Context).contextHandle);
+		enQueueMessage(newOp);
+		
+	}
+	
+	private int GetUnusedHandle() {
+		
+		/* Handles are client-specific, so we can just use serial numbers,
+		 * assuming we won't ever need more than MAXINT handles.
+		 */
+		
+		lastHandle++;
+		return lastHandle;
+	}
+	
+	private synchronized void enQueueMessage(RemotePPMOperation message) {
+				
+		//Add to the queue
+		pendingMessageQueue.add(message);
+		notifyAll();
+	}
+	
+	public synchronized void transmitMessages(OutputStream out) {
+		for(RemotePPMOperation op : this.pendingMessageQueue) {
+			try {
+				out.write(op.toBytes());
+			}
+			catch(IOException e) {
+				System.out.printf("Failed to write to OutputStream: %s%n", e);
+			}
+		}
+		
+		pendingMessageQueue.clear();
+	}	
+	
+	public boolean isRemote() {
+		return true;
+	}
+	
+	public void UnregisterComponent() {
+		
+		dispatch.die(); // Stop our helper threads.
+		super.UnregisterComponent();
+		
+	}
+	
+	public void notifyNetworkFailure(int errorCode) {
+		if(errorCode < 3) {
+			// Failure on connection
+			
+			CMessageEvent message = new CMessageEvent("Could not connect to host; switching to local PPM.", 0, 1);
+			InsertEvent(message);
+			
+		}
+		
+		else {
+			
+			// Connection dropped mid-conversation.
+			CMessageEvent message = new CMessageEvent("Connection to PPM server lost; switching to local PPM.", 0, 1);
+			InsertEvent(message);
+				
+		}
+		
+		SetBoolParameter(Ebp_parameters.BP_CONNECT_LOCK, false); // In case we never successfully connected.
+		SetLongParameter(Elp_parameters.LP_LANGUAGE_MODEL_ID, 0); // Set to local PPM
+	}
+}
\ No newline at end of file

Added: trunk/java/dasher/CSettingsStore.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CSettingsStore.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,435 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * SettingsStore is a base implementation of a settings repository.
+ * It has no ability to store its settings persistently, and will
+ * load the defaults specified in CParamTables every time it is
+ * instantiated.
+ * <p>
+ * In general the contract of a SettingsStore is to
+ * <p><ul><li>Store parameter settings internally
+ * <li>Optionally save these out to a persistent storage any time
+ * a parameter changes
+ * <li>Optionally restore parameters from this persistent store
+ * when instaitated. 
+ * <li>Raise a CParameterNotificationEvent whenever a parameter
+ * is changed.
+ * </ul>
+ * <p>
+ * Implementations wishing for persistent settings should subclass
+ * CSettingsStore and, by subclassing CDasherInterfaceBase, ensure
+ * that CreateSettingsStore is overridden to create their subclass.
+ * <p>
+ * Directly instantiating CSettingsStore will, however, be perfectly
+ * functional for testing purposes or environments which cannot
+ * save settings.
+ * 
+ */
+public class CSettingsStore {
+		
+	/**
+	 * Our reference parameter tables
+	 */
+	protected CParamTables s_oParamTables;
+	
+	/**
+	 * Event handler which we should notify whenever a parameter
+	 * changes
+	 */
+	protected CEventHandler m_pEventHandler;
+	
+	protected final int ParamBool = 0;
+	protected final int ParamLong = 1;
+	protected final int ParamString = 2;
+	protected final int ParamInvalid = 3;
+	
+	
+	/**
+	 * Same as new CSettingsStore(..., true)
+	 * 
+	 * @param pEventHandler Event handler which we should notify
+	 * of parameter changes
+	 */
+	public CSettingsStore(CEventHandler pEventHandler) {
+		
+		this(pEventHandler, true);
+		
+	}
+	
+	/**
+	 * Creates a new SettingsStore and instructs it to retrieve persistent
+	 * settings if the backing store is ready to respond.
+	 * 
+	 * @param pEventHandler Event handler to notify of parameter changes
+	 * @param readyYet Is the backing store ready; can we retrieve
+	 * persistent settings?
+	 */
+	public CSettingsStore(CEventHandler pEventHandler, boolean readyYet) {
+		
+		m_pEventHandler = pEventHandler;
+		s_oParamTables = new CParamTables();
+		
+		if(readyYet) { // If the backing store is ready (prepared by a subclass)
+			LoadPersistent();
+		}
+	}
+	
+	/* All C++-style integer based enums have now been replaced by three Enum types
+	 * which implement EParameters, meaning one can pass both a generic parameter AND
+	 * a specialised parameter. For references into the tables, the .ordinal() of
+	 * a specialised parameter is used. All switch() statements should now check
+	 * the parameter's type, cast it to the appropriate one, and then switch on
+	 * the relevant enum. Alternatively it may be possible to have cases of a
+	 * child-type, I've yet to check this.
+	 * 
+	 * 14/07: The whole codebase is now converted to use the new parameter scheme.
+	 * It's broadly very solid; everything is passed around as enum types until the actual
+	 * load/store instructions in CSettingsStore, whereupon ordinals are taken.
+	 * 
+	 * The only weakness is that one CANNOT in fact switch on an EParameters, since
+	 * there is no way for the compiler to know that all its children are Enums.
+	 * There may be some way around this -- some sort of enum-interface -- but
+	 * I haven't found it yet. This can be solved by splitting any switch
+	 * into three, type-checking, casting, and then switching in a type-specific
+	 * manner.
+	 */
+	
+	/**
+	 * Loads persistent settings by means of the LoadSetting function.
+	 * <p>
+	 * If loading fails, the default value is retrieved and SaveSetting
+	 * is called to save this out to our backing store. 
+	 */
+	public void LoadPersistent() {
+		
+		// Load each of the persistent parameters.  If we fail loading for the store, then 
+		// we'll save the settings with the default value that comes from Parameters.h
+		
+		/* CSFS: The load/save settings were previously using the return value
+		 * to communicate success or failure, and a reference to some temporary
+		 * variable to actually confer the value. I have redesigned this
+		 * to use an Exception instead.
+		 */
+		
+		for(int i = 0; i < Ebp_parameters.values().length; ++i) {
+			if(s_oParamTables.BoolParamTable[i].persistent) {
+				try {
+					s_oParamTables.BoolParamTable[i].value = LoadBoolSetting(s_oParamTables.BoolParamTable[i].regName);
+				}
+				catch(CParameterNotFoundException e) {
+					SaveSetting(s_oParamTables.BoolParamTable[i].regName, s_oParamTables.BoolParamTable[i].value);
+				}
+			}			            
+		}
+		
+		for(int j = 0; j < Elp_parameters.values().length; ++j) {
+			if(s_oParamTables.LongParamTable[j].persistent) {
+				try {
+					s_oParamTables.LongParamTable[j].value = LoadLongSetting(s_oParamTables.LongParamTable[j].regName);
+				}
+				catch(CParameterNotFoundException e) {
+					SaveSetting(s_oParamTables.LongParamTable[j].regName, s_oParamTables.LongParamTable[j].value);            
+				}
+			}
+		}
+		
+		for(int k = 0; k < Esp_parameters.values().length; ++k) {
+			if(s_oParamTables.StringParamTable[k].persistent) {
+				try {
+					s_oParamTables.StringParamTable[k].value = LoadStringSetting(s_oParamTables.StringParamTable[k].regName);
+				}
+				catch(CParameterNotFoundException e) {
+					SaveSetting(s_oParamTables.StringParamTable[k].regName, s_oParamTables.StringParamTable[k].value);
+				}
+			}		            
+		}
+	}
+	
+	/**
+	 * Sets the value of a given boolean parameter.
+	 * <p>
+	 * This will raise a ParameterNotificationEvent with our
+	 * event handler.
+	 * 
+	 * @param iParameter Parameter to set
+	 * @param bValue New value for this parameter
+	 */
+	public void SetBoolParameter(Ebp_parameters iParameter, boolean bValue) {
+		
+		// Check that the parameter is in fact in the right spot in the table
+				
+		if(bValue == GetBoolParameter(iParameter))
+			return;
+		
+		// Set the value
+		s_oParamTables.BoolParamTable[iParameter.ordinal()].value = bValue;
+		
+		// Initiate events for changed parameter
+		CParameterNotificationEvent oEvent = new CParameterNotificationEvent(iParameter);
+		
+		m_pEventHandler.InsertEvent(oEvent);
+		oEvent = null; // Left for the Garbage Collector.
+		
+		// Write out to permanent storage
+		if(s_oParamTables.BoolParamTable[iParameter.ordinal()].persistent)
+			SaveSetting(s_oParamTables.BoolParamTable[iParameter.ordinal()].regName, bValue);
+	}
+	
+	/**
+	 * Sets the value of a given long parameter.
+	 * <p>
+	 * This will raise a ParameterNotificationEvent with our
+	 * event handler.
+	 * 
+	 * @param iParameter Parameter to set
+	 * @param lValue New value for this parameter
+	 */
+	public void SetLongParameter(Elp_parameters iParameter, long lValue) {
+		
+		if(lValue == GetLongParameter(iParameter))
+			return;
+		
+		// Set the value
+		s_oParamTables.LongParamTable[iParameter.ordinal()].value = lValue;
+		
+		// Initiate events for changed parameter
+		CParameterNotificationEvent oEvent = new CParameterNotificationEvent(iParameter);
+		m_pEventHandler.InsertEvent(oEvent);
+		
+		// Write out to permanent storage
+		if(s_oParamTables.LongParamTable[iParameter.ordinal()].persistent)
+			SaveSetting(s_oParamTables.LongParamTable[iParameter.ordinal()].regName, lValue);
+	}
+	
+	/**
+	 * Sets the value of a given string parameter.
+	 * <p>
+	 * This will raise a ParameterNotificationEvent with our
+	 * event handler.
+	 * 
+	 * @param iParameter Parameter to set
+	 * @param sValue New value for this parameter
+	 */
+	public void SetStringParameter(Esp_parameters iParameter, String sValue) {
+		
+		if(sValue == GetStringParameter(iParameter))
+			return;
+		
+		// Set the value
+		s_oParamTables.StringParamTable[iParameter.ordinal()].value = sValue;
+		
+		// Initiate events for changed parameter
+		CParameterNotificationEvent oEvent = new CParameterNotificationEvent(iParameter);
+		m_pEventHandler.InsertEvent(oEvent);
+		
+		// Write out to permanent storage
+		if(s_oParamTables.StringParamTable[iParameter.ordinal()].persistent)
+			SaveSetting(s_oParamTables.StringParamTable[iParameter.ordinal()].regName, sValue);
+	}
+	
+	/**
+	 * Gets the value of a boolean parameter
+	 * 
+	 * @param iParameter Parameter to query
+	 * @return Value of this parameter
+	 */
+	public boolean GetBoolParameter(Ebp_parameters iParameter) {
+				
+		// Return the value
+		return s_oParamTables.BoolParamTable[iParameter.ordinal()].value;
+	}
+	
+	/**
+	 * Gets the value of an integer parameter
+	 * 
+	 * @param iParameter Parameter to query
+	 * @return Value of this parameter
+	 */
+	public long GetLongParameter(Elp_parameters iParameter) {
+		
+		// Return the value
+		return s_oParamTables.LongParamTable[iParameter.ordinal()].value;
+	}
+	
+	/**
+	 * Gets the value of a String parameter
+	 * 
+	 * @param iParameter Parameter to query
+	 * @return Value of this parameter
+	 */
+	public String GetStringParameter(Esp_parameters iParameter) {
+		// Return the value
+		return s_oParamTables.StringParamTable[iParameter.ordinal()].value;
+	}
+	
+	/**
+	 * Resets a given parameter to its default value, as given
+	 * by its entry in CParamTables.
+	 * 
+	 * @param iParameter Parameter to reset
+	 */
+	public void ResetParameter(EParameters iParameter) {
+		switch(GetParameterType(iParameter)) {
+		case ParamBool:
+			SetBoolParameter((Ebp_parameters)iParameter, s_oParamTables.BoolParamTable[((Ebp_parameters)iParameter).ordinal()].defaultVal);
+			break;
+		case ParamLong:
+			SetLongParameter((Elp_parameters)iParameter, s_oParamTables.LongParamTable[((Elp_parameters)iParameter).ordinal()].defaultVal);
+			break;
+		case ParamString:
+			SetStringParameter((Esp_parameters)iParameter, s_oParamTables.StringParamTable[((Esp_parameters)iParameter).ordinal()].defaultVal);
+			break;
+		}
+	}
+	
+	/**
+	 * Determines the type of a given parameter.
+	 * 
+	 * @param iParameter Parameter to query
+	 * @return 0 for boolean, 1 for long, 2 for String, 3 for invalid
+	 */
+	public int GetParameterType(EParameters iParameter)
+	{
+		if (iParameter instanceof Ebp_parameters)
+			return ParamBool;
+		if (iParameter instanceof Elp_parameters)
+			return ParamLong;
+		if (iParameter instanceof Esp_parameters)
+			return ParamString;
+		
+		return ParamInvalid;
+	}
+	
+	/**
+	 * Gets the internal name of a parameter
+	 * 
+	 * @param iParameter Parameter to query
+	 * @return Internal name
+	 */
+	public String GetParameterName(EParameters iParameter)
+	{
+		// Pull the registry name out of the correct table depending on the parameter type
+		switch (GetParameterType(iParameter))
+		{
+		case (ParamBool):
+		{
+			return s_oParamTables.BoolParamTable[((Ebp_parameters)iParameter).ordinal()].regName;
+		}
+		case (ParamLong):
+		{
+			return s_oParamTables.LongParamTable[((Elp_parameters)iParameter).ordinal()].regName;
+		}
+		case (ParamString):
+		{
+			return s_oParamTables.StringParamTable[((Esp_parameters)iParameter).ordinal()].regName;
+		}
+		};
+		
+		return "";
+	}
+	
+	/* CSFS: There were some deprecated functions below here, named GetBoolOption
+	 * and the obvious brethren. Since nobody seemed to be calling these anymore,
+	 * I've removed them.
+	 */	
+	
+	/* Private functions -- Settings are not saved between sessions unless these
+	 functions are over-ridden.
+	 --------------------------------------------------------------------------*/
+	
+	/**
+	 * Loads a given boolean setting from the backing store.
+	 * 
+	 * @param Key Name of parameter to retrieve
+	 * @return Value of this setting
+	 * @throws CParameterNotFoundException if loading failed, eg. because the backing
+	 * store did not contain information about this parameter.
+	 */
+	protected boolean LoadBoolSetting(String Key) throws CParameterNotFoundException {
+		throw new CParameterNotFoundException(Key);
+	}
+	
+	/**
+	 * Loads a given integer setting from the backing store.
+	 * 
+	 * @param Key Name of parameter to retrieve
+	 * @return Value of this setting
+	 * @throws CParameterNotFoundException if loading failed, eg. because the backing
+	 * store did not contain information about this parameter.
+	 */
+	protected long LoadLongSetting(String Key) throws CParameterNotFoundException {
+		throw new CParameterNotFoundException(Key);
+	}
+	
+	/**
+	 * Loads a given String setting from the backing store.
+	 * 
+	 * @param Key Name of parameter to retrieve
+	 * @return Value of this setting
+	 * @throws CParameterNotFoundException if loading failed, eg. because the backing
+	 * store did not contain information about this parameter.
+	 */
+	protected String LoadStringSetting(String Key) throws CParameterNotFoundException {
+		throw new CParameterNotFoundException(Key);
+	}
+	
+	/**
+	 * Saves a given bool parameter to the backing store. In this base
+	 * class, this method is a stub; it should be overridden by a
+	 * subclass if persistent settings are desired.
+	 * 
+	 * @param Key Name of the parameter to save
+	 * @param Value Value of the parameter
+	 */
+	protected void SaveSetting(String Key, boolean Value) {
+	}
+	
+	/**
+	 * Saves a given integer parameter to the backing store. In this base
+	 * class, this method is a stub; it should be overridden by a
+	 * subclass if persistent settings are desired.
+	 * 
+	 * @param Key Name of the parameter to save
+	 * @param Value Value of the parameter
+	 */
+	protected void SaveSetting(String Key, long Value) {
+	}
+	
+	/**
+	 * Saves a given string parameter to the backing store. In this base
+	 * class, this method is a stub; it should be overridden by a
+	 * subclass if persistent settings are desired.
+	 * 
+	 * @param Key Name of the parameter to save
+	 * @param Value Value of the parameter
+	 */
+	protected void SaveSetting(String Key, String Value) {
+	}
+
+	
+}

Added: trunk/java/dasher/CStartEvent.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CStartEvent.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,42 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Event giving notification of Dasher starting or unpausing.
+ * <p>
+ * This will be dispatched by the InterfaceBase in the appropriate
+ * situation.
+ */
+public class CStartEvent extends CEvent {
+	
+	/**
+	 * Create a new StartEvent
+	 */
+	public CStartEvent() {
+	    m_iEventType = 4; // EV_START
+	} 
+}

Added: trunk/java/dasher/CStartHandler.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CStartHandler.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,91 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * A start handler is a helper to an input filter which serves the
+ * purpose of starting and stopping Dasher.
+ * <p>
+ * At present they are only supported by CDefaultFilter.
+ * <p>
+ * Its Timer event will be called during its parent filter's
+ * Timer event; similarly it will be given a chance to draw itself
+ * in the DecorateView phase within its parent's DecorateView call. 
+ */
+public abstract class CStartHandler extends CDasherComponent {
+	
+	/**
+	 * Interface which this Start Handler should control
+	 */
+	protected CDasherInterfaceBase m_Interface;
+	
+	/**
+	 * Creates a new start handler which controls a given Interface
+	 * 
+	 * @param EventHandler Event handler with which to register ourselves
+	 * @param SettingsStore Settings repository to use
+	 * @param Interface Interface this Start Handler should control
+	 */
+	public CStartHandler(CEventHandler EventHandler, CSettingsStore SettingsStore, CDasherInterfaceBase Interface)  {
+		super(EventHandler, SettingsStore);
+		m_Interface = Interface;
+	}
+	
+	/**
+	 * Similar to its companion method in CInputFilter, this gives
+	 * the start handler an opportunity to draw itself and other
+	 * relevant decorations during the production of a new frame.
+	 * <p>
+	 * Start handlers should ensure that this method can reliably
+	 * terminate quickly, or performance will be greatly degraded.
+	 * 
+	 * @param View View to which we should draw decorations
+	 * @return True if any decorating was done, false otherwise
+	 */
+	public abstract boolean DecorateView(CDasherView View);
+	
+	/**
+	 * Fired during the start handler's parent input filter's
+	 * Timer event. This is when the start handler should interact
+	 * with the Model if necessary. Despite the availability of a
+	 * View, no drawing should be done at this stage; if this event
+	 * makes drawing necessary it should be stored in the class'
+	 * state for now and drawn at the next call to DecorateView.
+	 * 
+	 * @param iTime Current system time as a unix timestamp
+	 * @param m_DasherView View which we may use for co-ordinate transforms and to get input co-ordinates
+	 * @param m_DasherModel Model which may be modified if we wish
+	 */
+	public abstract void Timer(long iTime, CDasherView m_DasherView, CDasherModel m_DasherModel);
+
+	/**
+	 * Event handler
+	 * 
+	 * @see CEventHandler
+	 */
+	public abstract void HandleEvent(CEvent Event);
+	
+}

Added: trunk/java/dasher/CStopEvent.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CStopEvent.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,43 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Event notifying components that Dasher has been paused / halted.
+ * <p>
+ * The Interface will dispatch this event at an appopriate time;
+ * components should enter an idle state.
+ */
+public class CStopEvent extends CEvent {
+	
+	/**
+	 * Creates a new Stop event
+	 *
+	 */
+	public CStopEvent() {
+	    m_iEventType = 5; // EV_STOP
+	} 
+}
\ No newline at end of file

Added: trunk/java/dasher/CSymbolAlphabet.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CSymbolAlphabet.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,128 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * A symbol alphabet is a companion to an Alphabet which contains
+ * the minimal information needed to perform language modelling
+ * across said alphabet.
+ * <p>
+ * Essentially all it knows about is the size of the alphabet and the
+ * indices of the space symbol.
+ * <p>
+ * Typically, a CAlphabet will be formed first, and a SymbolAlphabet
+ * produced afterwards prior to creating a LanguageModel.
+ */
+public class CSymbolAlphabet {
+
+	/**
+	 * Size of this alphabet
+	 */
+	protected int m_iSize;
+	
+	/**
+	 * Index of the space symbol (needed to allow the language
+	 * model to establish where words end)
+	 */
+    protected int m_SpaceSymbol;
+    
+    /**
+     * Companion alphabet
+     */
+    protected CAlphabet AlphabetPointer;
+	
+	/////////////////////////////////////////////////////////////////////////////
+	    // iSize is the number of Symbols - please dont change the constructor
+	    // Add functions to set customizable behaviour
+
+    /**
+     * Creates a new Alphabet with a given size and a space
+     * symbol of -1.
+     * 
+     * @param iSize Alphabet size
+     */
+    public CSymbolAlphabet(int iSize) {
+	    m_iSize = iSize;
+	    SetSpaceSymbol(-1);       // Default (uniformative) value.
+	    } 
+	
+    /**
+     * Gets the size of this alphabet
+     * 
+     * @return Size
+     */
+    public int GetSize() {
+	      return m_iSize;
+	}
+	
+    /**
+     * Sets the index of the space symbol
+     * 
+     * @param _SpaceSymbol Space symbol index
+     */
+    public void SetSpaceSymbol(int _SpaceSymbol) {
+	     m_SpaceSymbol = _SpaceSymbol;
+	} 
+	
+    /**
+     * Gets the index of the space symbol
+     * 
+     * @return Space symbol index
+     */
+    public int GetSpaceSymbol() {
+		// Get the space symbol. -1 means that no symbol has been set.
+		return m_SpaceSymbol;
+	} 
+	
+	/**
+	 * Sets our companion alphabet
+	 * 
+	 * @param _AlphabetPointer New alphabet
+	 */
+    public void SetAlphabetPointer(CAlphabet _AlphabetPointer) {
+		
+		// NOTE - you are VERY strongly discouraged from
+		// using this function. It is only here as a hack
+		// until I figure out a better solution.
+		
+		AlphabetPointer = _AlphabetPointer;
+	}
+	
+	/**
+	 * Gets our companion alphabet
+	 * 
+	 * @return Companion alphabet
+	 */
+    CAlphabet GetAlphabetPointer() {
+		
+		// NOTE - you are VERY strongly discouraged from
+		// using this function. It is only here as a hack
+		// until I figure out a better solution.
+		
+		return AlphabetPointer;
+	} 
+	
+}
\ No newline at end of file

Added: trunk/java/dasher/CSymbolProb.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CSymbolProb.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,47 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Simple struct representing a symbol and its probability, used
+ * in logging only.
+ */
+public class CSymbolProb {
+	/* CSFS: This replaces the struct SymbolProb declared
+	 * in DasherTypes.h
+	 */
+	
+	/**
+	 * Symbol
+	 */
+    public int          sym;
+    
+    /**
+     * Probability
+     */
+    public double          prob;
+	
+}

Added: trunk/java/dasher/CUserLog.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CUserLog.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,71 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+import java.util.ArrayList;
+
+/**
+ * Stubbed logging class. These methods should be implemented
+ * if we want to start generating a textual log.
+ */
+public class CUserLog {
+
+	public CUserLog(CEventHandler EventHandler, CSettingsStore SetStore, int loglevel, CAlphabet Alpha) {
+		//stub
+	}
+	
+	public void OutputFile() {
+		// stub
+	}
+	
+	public void Close() {
+		// stub
+	}
+	
+	public void InitIsDone() {
+		// stub
+	}
+	
+	public void StopWriting(float x) {
+		// stub
+	}
+	
+	public void StartWriting() {
+		// stub
+	}
+	
+	public void DeleteSymbols (int deleted) {
+		// stub
+	}
+	
+	public void AddSymbols (ArrayList<CSymbolProb> added) {
+		// stub
+	}
+	
+	public void SetAlphabetPtr(CAlphabet alph) {
+		// stub
+	}
+}
\ No newline at end of file

Added: trunk/java/dasher/CWrapperFactory.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/CWrapperFactory.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,140 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * A simple ModuleFactory which simply wraps a pre-existing DasherModule
+ * and returns it as the sole module it can produce.
+ */
+public class CWrapperFactory extends CModuleFactory {
+	
+	/**
+	 * Module wrapped by this factory
+	 */
+	protected CDasherModule m_Module;
+	
+	/**
+	 * Index of the next module to retrieve
+	 */
+	protected int m_iCurrentPos;
+	
+	/**
+	 * Creates a new WrapperFactory wrapping a specified Module.
+	 *  
+	 * @param EventHandler EventHandler with which to register ourselves
+	 * @param SettingsStore Settings repository to use
+	 * @param Module Module to wrap
+	 */
+	public CWrapperFactory(CEventHandler EventHandler, CSettingsStore SettingsStore, CDasherModule Module) {
+		m_Module = Module;
+		m_Module.Ref();
+		
+		m_iCurrentPos = 0;
+	}
+	
+	/**
+	 * Unref's our module and deletes its reference.
+	 *
+	 */
+	public void DestroyFactory() {
+		m_Module.Unref();
+		m_Module = null;
+	}
+	
+	/**
+	 * Sets m_iCurrentPost to 0
+	 */
+	public void Start() {
+		m_iCurrentPos = 0;
+	}
+	
+	/**
+	 * Returns true if no Modules have been retrieved yet
+	 */
+	public boolean IsMore() {
+		return (m_iCurrentPos < 1);
+	}
+	
+	/**
+	 * Returns the details of our module with the name "Unknown Module"
+	 * if this is the first call made to this method, or a copy of
+	 * the SFactoryInfo fed in if not.
+	 * 
+	 * @param info Previous module details
+	 * @return Next module details
+	 */
+	public SFactoryInfo GetNext(SFactoryInfo info) {
+		
+		/* CSFS: BUGFIX: This was returning its retval within the if block, which isn't correct */
+		
+		SFactoryInfo retval = new SFactoryInfo();
+		retval.iID = info.iID;
+		retval.iType = info.iType;
+		retval.strName = info.strName;
+		if(m_iCurrentPos == 0) {
+			
+			retval.iID = m_Module.GetID();
+			retval.iType = m_Module.GetType();
+			retval.strName = "Unknown Module";
+		}
+		++m_iCurrentPos;
+		return retval;
+		
+	}
+	
+	/**
+	 * Returns our wrapped module if the ID is correct,
+	 * or null otherwise.
+	 */
+	public CDasherModule GetModule(long iID) {
+		if(iID == m_Module.GetID())
+			return m_Module;
+		else
+			return null;
+	}
+	
+	/**
+	 * Returns our wrapped module's name if the ID is correct,
+	 * or "Not implemented" otherwise.
+	 */
+	public String GetName(long iID) {
+		if(iID == m_Module.GetID())
+			return m_Module.GetName();
+			else
+				return "Not implemented"; // TODO: Is this the right thing to do here?
+	}
+	
+	/**
+	 * Returns our wrapped module's type if the ID is correct,
+	 * or 0 otherwise.
+	 */
+	public int GetType(long iID) {
+		if(iID == m_Module.GetID())
+			return m_Module.GetType();
+			else
+				return 0; // TODO: Is this the right thing to do here?
+	}
+}

Added: trunk/java/dasher/EColorSchemes.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/EColorSchemes.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,33 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Enumeration of possible colour schemes
+ */
+public enum EColorSchemes { Nodes1, Nodes2, Special1, Special2, Groups, Objects 
+    
+}

Added: trunk/java/dasher/EParameters.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/EParameters.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,44 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Interface implemented by all parameter enumerations, allowing
+ * an EParameters to be passed as a generic parameter of indeterminate
+ * type.
+ */
+public interface EParameters {
+
+	
+	/* CSFS: This space intentionally left blank.
+	 * 
+	 * This is the parent class for the enumerations of all three types of parameters.
+	 * Ebp_parameters houses the boolean parameters,
+	 * Elp_parameters the longs,
+	 * and Esp_parameters the strings.
+	 */
+	
+}

Added: trunk/java/dasher/Ebp_parameters.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/Ebp_parameters.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,49 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Enumeration of possible boolean parameter references. See
+ * CParamTables for a list and definitions.
+ */
+public enum Ebp_parameters implements EParameters {
+	
+		  BP_DRAW_MOUSE_LINE, BP_DRAW_MOUSE,
+		  BP_SHOW_SLIDER, BP_START_MOUSE,
+		  BP_START_SPACE, BP_START_STYLUS, BP_STOP_IDLE, BP_KEY_CONTROL,  BP_CONTROL_MODE, 
+		  BP_COLOUR_MODE, BP_MOUSEPOS_MODE,
+		  BP_OUTLINE_MODE, BP_PALETTE_CHANGE, BP_NUMBER_DIMENSIONS,
+		  BP_EYETRACKER_MODE, BP_AUTOCALIBRATE, BP_DASHER_PAUSED,
+		  BP_GAME_MODE, BP_TRAINING, BP_REDRAW, BP_LM_DICTIONARY, 
+		  BP_LM_LETTER_EXCLUSION, BP_AUTO_SPEEDCONTROL, BP_CLICK_MODE, 
+		  BP_LM_ADAPTIVE, BP_BUTTONONESTATIC, BP_BUTTONONEDYNAMIC,
+		  BP_BUTTONMENU, BP_BUTTONPULSING, BP_BUTTONSTEADY, 
+		  BP_BUTTONDIRECT, BP_BUTTONFOURDIRECT, BP_BUTTONALTERNATINGDIRECT,
+		  BP_COMPASSMODE, BP_SOCKET_INPUT_ENABLE, BP_SOCKET_DEBUG, 
+		  BP_OLD_STYLE_PUSH, BP_CIRCLE_START, BP_GLOBAL_KEYBOARD, 
+		  BP_DELAY_VIEW, BP_LM_REMOTE, BP_CONNECT_LOCK
+	
+}

Added: trunk/java/dasher/Elp_parameters.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/Elp_parameters.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,45 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Enumeration of possible integer parameter references. See
+ * CParamTables for a list and definitions.
+ */
+public enum Elp_parameters implements EParameters {
+		  LP_ORIENTATION, LP_REAL_ORIENTATION, LP_MAX_BITRATE,
+		  LP_VIEW_ID, LP_LANGUAGE_MODEL_ID, LP_DASHER_FONTSIZE,
+		  LP_UNIFORM, LP_YSCALE, LP_MOUSEPOSDIST, LP_STOP_IDLETIME, LP_TRUNCATION, 
+		  LP_TRUNCATIONTYPE, LP_LM_MAX_ORDER, LP_LM_EXCLUSION,
+		  LP_LM_UPDATE_EXCLUSION, LP_LM_ALPHA, LP_LM_BETA,
+		  LP_LM_MIXTURE, LP_MOUSE_POS_BOX, LP_NORMALIZATION, LP_LINE_WIDTH, 
+		  LP_LM_WORD_ALPHA, LP_USER_LOG_LEVEL_MASK, LP_SPEED_DIVISOR, 
+		  LP_ZOOMSTEPS, LP_B, LP_S, LP_Z, LP_R, LP_RIGHTZOOM,
+		  LP_BOOSTFACTOR, LP_AUTOSPEED_SENSITIVITY, LP_SOCKET_PORT, LP_SOCKET_INPUT_X_MIN, LP_SOCKET_INPUT_X_MAX,
+		  LP_SOCKET_INPUT_Y_MIN, LP_SOCKET_INPUT_Y_MAX, LP_OX, LP_OY, LP_MAX_Y, LP_INPUT_FILTER, 
+		  LP_CIRCLE_PERCENT, LP_TWO_BUTTON_OFFSET;
+		  
+}

Added: trunk/java/dasher/Esp_parameters.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/Esp_parameters.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,38 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Enumeration of possible String parameter references. See
+ * CParamTables for a list and definitions.
+ */
+public enum Esp_parameters implements EParameters {
+	  SP_ALPHABET_ID, SP_ALPHABET_1, SP_ALPHABET_2, SP_ALPHABET_3, SP_ALPHABET_4, 
+	  SP_COLOUR_ID, SP_DEFAULT_COLOUR_ID, SP_DASHER_FONT, SP_SYSTEM_LOC, SP_USER_LOC, SP_GAME_TEXT_FILE,
+	  SP_TRAIN_FILE, SP_SOCKET_INPUT_X_LABEL, SP_SOCKET_INPUT_Y_LABEL, SP_INPUT_FILTER, SP_INPUT_DEVICE,
+	  SP_LM_HOST;
+	  
+}

Added: trunk/java/dasher/Opts.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/Opts.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,76 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * List of miscellaneous constants, some of which are probably
+ * now redundant, inclduing those describing encodings, as Java
+ * will always use UTF16 internally.
+ */
+public class Opts {
+	
+	// Encodings
+	
+	public static final int UserDefault = -1; 
+	public static final int AlphabetDefault = -2; 
+	public static final int UTF8 = 65001;
+	public static final int UTF16LE = 1200;
+	public static final int UTF16BE = 1201;
+	
+	/**
+	 * List of available screen orientations. The "Alphabet"
+	 * option means that the Alphabet's preferred orientation
+	 * is used.
+	 */
+	class ScreenOrientations {
+		public static final int Alphabet = -2; 
+		public static final int LeftToRight = 0;
+		public static final int RightToLeft = 1;
+		public static final int TopToBottom = 2;
+		public static final int BottomToTop = 3;
+	}
+	
+	/**
+	 * This appears to enumerate codepages, which is also very
+	 * much useless in Java.
+	 */
+	class AlphabetTypes { 
+		public static final int MyNone = 0;
+		public static final int Arabic = 1256;
+		public static final int Baltic = 1257;
+		public static final int CentralEurope = 1250;
+		public static final int ChineseSimplified = 936;
+		public static final int ChineseTraditional = 950;
+		public static final int Cyrillic = 1251;
+		public static final int Greek = 1253;
+		public static final int Hebrew = 1255;
+		public static final int Japanese = 932;
+		public static final int Korean = 949;
+		public static final int Thai = 874;
+		public static final int Turkish = 1254;
+		public static final int VietNam = 1258;
+		public static final int Western = 1252; }
+}

Added: trunk/java/dasher/SFactoryInfo.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/SFactoryInfo.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,47 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Simple struct describing a module as returned by a CModuleFactory.
+ */
+public class SFactoryInfo {
+
+	/**
+	 * Module ID
+	 */
+	long iID;
+	
+	/**
+	 * Module type
+	 */
+	int iType;
+	
+	/**
+	 * Friendly name
+	 */
+	String strName;
+}

Added: trunk/java/dasher/SGroupInfo.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/SGroupInfo.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,69 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Small struct representing a group of Nodes, as used to draw
+ * coloured grouping boxes which surround a family of nodes, such
+ * as punctuation.
+ */
+public class SGroupInfo {
+	
+	/**
+	 * First child group
+	 */
+	SGroupInfo Child;
+	
+	/**
+	 * Next sibling group
+	 */
+	SGroupInfo Next;
+	
+	/**
+	 * Label for this group
+	 */
+	String strLabel;
+	
+	/**
+	 * Index of the first node contained in this group
+	 */
+	int iStart;
+	
+	/**
+	 * Index of the last node contained in this group
+	 */
+	int iEnd;
+	
+	/**
+	 * Colour index used to draw this group
+	 */
+	int iColour;
+	
+	/**
+	 * Should this group be drawn?
+	 */
+	boolean bVisible;
+}
\ No newline at end of file

Added: trunk/java/dasher/SSymbol.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/SSymbol.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,44 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher;
+
+/**
+ * Small struct representing a symbol. This is apparently useless
+ * as the 'prefix' flag is never used; integer symbol identifiers
+ * may as well be used instead.
+ */
+public class SSymbol {
+	
+	/**
+	 * Symbol index
+	 */
+	int symbol;
+	
+	/**
+	 * Prefix?
+	 */
+	boolean prefix;
+}
\ No newline at end of file

Added: trunk/java/dasher/applet/DasherTasklet.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/DasherTasklet.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,7 @@
+package dasher.applet;
+
+public abstract class DasherTasklet {
+
+	public abstract void run();
+	
+}

Added: trunk/java/dasher/applet/DoFrameTask.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/DoFrameTask.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,67 @@
+
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+package dasher.applet;
+
+import javax.swing.JApplet;
+
+/**
+ * TimerTask which orders a specified applet to redraw every time
+ * it is run, the idea being that the DasherScreen Panel will be
+ * ordered to redraw and thus produce a new frame. This differs
+ * from Dasher's traditional methods in which drawing is triggered
+ * at the bottom level; here the Applet's redraw triggers the generation
+ * of a new frame.
+ */
+public class DoFrameTask extends java.util.TimerTask {
+
+	/**
+	 * Applet to repaint.
+	 */
+	private JApplet m_Applet;
+
+	/**
+	 * Creates a new task to redraw a specified applet.
+	 * 
+	 * @param iApplet Applet to redraw
+	 */
+	public DoFrameTask(JApplet iApplet) {
+		m_Applet = iApplet;
+	}
+	
+	/**
+	 * Redraws, incrementing the FramesInQueue counter beforehand
+	 * and decrementing afterwards. If FramesInQueue is non-zero
+	 * when we are called, a frame is skipped, both to avoid
+	 * tasks stacking up, and to prevent the confusion involved
+	 * if two frames are in progress simeltaneously.
+	 */
+	public void run() {
+		
+		m_Applet.repaint();
+			
+	}
+	
+}

Added: trunk/java/dasher/applet/JDasher.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/JDasher.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,238 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher.applet;
+
+import java.io.InputStream;
+import java.util.Collection;
+
+import dasher.CDasherInterfaceBase;
+import dasher.CEvent;
+import dasher.CSettingsStore;
+
+/**
+ * Simple implementation of CDasherInterfaceBase providing minimal
+ * facilities to support an Applet version of Dasher.
+ */
+public class JDasher extends CDasherInterfaceBase {
+
+	/**
+	 * Our mouse input
+	 */
+	private JMouseInput m_MouseInput;
+	
+	/**
+	 * Host to notify of events and request redraws.
+	 */
+	private JDasherHost m_Host;
+			
+	/**
+	 * Creates a new JDasher. We call CreateSettingsStore immediately
+	 * after our super-constructor, create, wrap and register a new
+	 * JMouseInput, run CreateInput and register our newly created
+	 * input device wiht our host to hook it up to mouse events. 
+	 * 
+	 * @param host Host to report events and request mouse events
+	 * and redraws.
+	 */
+	public JDasher(JDasherHost host) {
+		super();
+		CreateSettingsStore();
+		m_MouseInput = new JMouseInput(m_EventHandler, m_SettingsStore);
+		RegisterFactory(new dasher.CWrapperFactory(m_EventHandler, m_SettingsStore, m_MouseInput));
+		CreateInput();
+		
+		m_Host = host;
+		m_Host.regMouseMotionListener(m_MouseInput);
+			
+	}
+	
+	/**
+	 * External event handler; simply passes the event to our
+	 * host, typically a JDasherApplet.
+	 * 
+	 * @param Event Event to handle
+	 */
+	public void ExternalEventHandler(CEvent Event) {
+
+		m_Host.handleEvent(Event);
+	
+	}
+
+	/**
+	 * Attempts to create a JSettings object; if a StoreUnavailableException
+	 * is produced in the course of this, we fall back and produce a 
+	 * standard CSettingsStore.
+	 * <p>
+	 * If a SettingsStore already exists, we ignore the call.
+	 */
+	public void CreateSettingsStore() {
+				
+		if(m_SettingsStore == null) {
+		
+			try {
+				m_SettingsStore = new JSettings(m_EventHandler);
+			}
+			catch (StoreUnavailableException e) {
+				// We can't use the registry/config file due to security problems.
+				m_SettingsStore = new CSettingsStore(m_EventHandler);
+			}
+			
+		
+		
+		}
+	}
+	
+	/**
+	 * Attempts to retrieve a stream pointing to a given file in this Applet's
+	 * JAR file and recalls TrainStream on this stream.
+	 * <p>
+	 * If we can't retrieve said stream for some reason, 0 is
+	 * returned.
+	 * 
+	 * @param Filename File to retrieve
+	 * @param iTotalBytes Bytes to read
+	 * @param iOffset Offset to start reading
+	 * @return Number of bytes successfully read
+	 */
+	public int TrainFile(String Filename, int iTotalBytes, int iOffset) {
+		
+		java.io.InputStream in = this.getClass().getResourceAsStream(Filename);
+		if(in == null) {
+			System.out.printf("Couldn't retrieve resource stream for %s%n", Filename);
+			return 0; // Failed to retrieve, possibly due to security.
+		}
+		
+		return TrainStream(in, iTotalBytes, iOffset);
+		
+	}
+
+	/**
+	 * Attempts to retrieve a ResourceStream for a given file by
+	 * retrieving it from our JAR file, and returns its available
+	 * property which should indicate the file size.
+	 * <p>
+	 * In the event of failure of any sort, we return zero.
+	 * 
+	 * @param strFileName File whose size we wish to retrieve
+	 * @return File size, or 0 on error.
+	 */
+	public int GetFileSize(String strFileName) {
+		try {
+			java.io.InputStream in = this.getClass().getResourceAsStream(strFileName);
+			return in.available();
+		}
+		catch (Exception e) { // Including if 'in' was null (throwing NullPointerException)
+			return 0;
+		}
+	}
+
+	/**
+	 * Populates a given Collection with a list of available
+	 * alphabet files.
+	 * <p>
+	 * Due to the difficulty in enumerating the contents of a JAR
+	 * file, at present this is hard coded to report a certain set.
+	 * <p>
+	 * Ideally this should be upgraded to report the true list of
+	 * available files, potentially by reading some master XML file.
+	 * 
+	 * @param vFileList Collection to fill with a list of available alphabet files.
+	 */	
+	public void ScanAlphabetFiles(Collection<String> vFileList) {
+		
+		vFileList.add("alphabet.english.xml");
+		vFileList.add("alphabet.englishC.xml");
+		vFileList.add("alphabet.Thai.xml");
+						
+		/* CSFS: TODO replace this with an actual file enumerator.
+		 */
+		
+	}
+
+	/**
+	 * Populates a given Collection with a list of available
+	 * colour files.
+	 * <p>
+	 * Due to the difficulty in enumerating the contents of a JAR
+	 * file, at present this is hard coded to report a certain set.
+	 * <p>
+	 * Ideally this should be upgraded to report the true list of
+	 * available files, potentially by reading some master XML file.
+	 * 
+	 * @param vFileList Collection to fill with a list of available colour files.
+	 */
+	public void ScanColourFiles(Collection<String> vFileList) {
+
+		vFileList.add("colour.euroasian.xml");
+		vFileList.add("colour.rainbow.xml");
+		vFileList.add("colour.euroasian-new.xml");
+		vFileList.add("colour.thai.xml");
+		
+		/* CSFS: See above */
+		
+	}
+	
+	/**
+	 * Attempts to retrieve a resource stream representing a given
+	 * file by using the getResourceAsStream method.
+	 * 
+	 * @return InputStream pointing to the relevant file if possible,
+	 * or null if not.
+	 */
+	public InputStream getResourceStream(String filename) {
+		return getClass().getResourceAsStream(filename);
+	}
+
+	/**
+	 * Sets our system path to "system.rc/".
+	 */
+	public void SetupPaths() {
+		
+		m_SettingsStore.SetStringParameter(dasher.Esp_parameters.SP_SYSTEM_LOC, "system.rc/");
+		
+	}
+
+	
+	/**
+	 * Stub
+	 */
+	public void SetupUI() {
+		// TODO Auto-generated method stub
+		
+	}
+	
+	/**
+	 * Orders our host to redraw.
+	 * 
+	 * @param bChanged ignored
+	 */
+	public void Redraw(boolean bChanged) {
+		m_Host.Redraw();
+	}
+	
+	
+	
+}

Added: trunk/java/dasher/applet/JDasherApplet.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/JDasherApplet.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,848 @@
+
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+package dasher.applet;
+
+import java.awt.Font;
+import java.awt.event.*;
+import java.util.ArrayList;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import java.awt.datatransfer.Clipboard;
+
+import javax.swing.*;
+
+import dasher.Ebp_parameters;
+import dasher.Elp_parameters;
+import dasher.Esp_parameters;
+
+/**
+ * Applet containing a JDasherScreen panel, a JDasherEdit TextBox,
+ * and a set of menus to set relevant parameters.
+ *
+ */
+public class JDasherApplet extends JApplet implements MouseListener, KeyListener, JDasherMenuBarListener, JDasherHost, dasher.applet.font.FontListener {
+
+	/**
+	 * Instance of Dasher which does the work
+	 */
+	public JDasher Dasher;
+	
+	/**
+	 * Screen object to be used for drawing
+	 */	
+	private JDasherScreen Screen;
+	
+	/**
+	 * Panel object which will reflect those drawings on the GUI
+	 */
+	private JDasherPanel panel;
+	
+	/**
+	 * Our menu bar
+	 */
+	private JDasherMenuBar MenuBar;
+	
+	/**
+	 * Overlay to display when Dasher is locked
+	 */
+	private ScreenOverlay ProgressMeter;
+	
+	/**
+	 * Edit box in which typed text appears
+	 */
+	private JDasherEdit EditBox;
+	
+	/**
+	 * Clipboard object
+	 */
+	public Clipboard m_Clipboard;
+	
+	/**
+	 * Scheduling agent used to cue new frames
+	 */
+	private Timer taskScheduler;
+	
+	/**
+	 * Date of last build; appears in About box
+	 */
+	public final String buildDate = "22:17 08/10/2008";
+					
+	/**
+	 * Instantiates Dasher, gets a handle to the system clipboard
+	 * if possible, calls constructGUIPanel to produce our GUI,
+	 * and informs Dasher of the Screen Panel created by this method
+	 * using the ChangeScreen method.
+	 * <p>
+	 * Finally, we call constructMenus to produce our menu bar.
+	 */
+	public void init() {
+				
+		Dasher = new JDasher(this);
+		
+		/* Instantiate Dasher. The argument is simply so it has a back-pointer
+		 * to its host applet for the purpose of adding listeners where this is
+		 * necessary.
+		 */
+		
+		/* Try to create a clipboard */
+		
+		try {
+			m_Clipboard = java.awt.Toolkit.getDefaultToolkit().getSystemClipboard();
+		}
+		catch(Exception e) {
+			System.out.printf("Exception retrieving the system clipboard: %s%n", e.toString());
+			m_Clipboard = new java.awt.datatransfer.Clipboard("Private clipboard");
+		}
+		
+		ProgressMeter = new ScreenOverlay();
+		
+		this.add(constructGUIPanel(this.getSize()));
+		
+		Dasher.Realize();
+		Dasher.ChangeScreen(Screen);				
+
+		/* Inform Dasher that we have created a Screen and it can now display.
+		 * This will cause the View to instantiate too, due to the ChangeView
+		 * method (which in turn fires in response to a parameter-change event!)
+		 */
+				
+		//TimerTask doFrame = new DoFrameTask(this);
+		//taskScheduler = new Timer();
+		//taskScheduler.scheduleAtFixedRate(doFrame, 0, 20);
+		
+		/* Simple threaded scheduling. The C++ version calls NewFrame directly
+		 * every 20 ms as part of a message-processing loop. This is not entirely
+		 * suitable for Java as we need the Applet to be idle on some occasions
+		 * so that we can process the MouseEvents detailing where the pointer
+		 * is at present. This is actually much less efficient, but I don't think
+		 * we can ask "where is the pointer now?" in Java, as in C++; 
+		 * we must use a MouseMotionListener.
+		 */
+		
+		this.addMouseListener(this);
+		this.addKeyListener(this);
+				
+		/* The applet itself will handle MouseEvents relating to clicks; these will
+		 * be fed into the interface via KeyDown, which also accounts for mouse-clicks.
+		 * Further it handles actual keyboard events. The code for this may be moved
+		 * out to some dedicated event-handler code in the future, but there is no
+		 * particular reason to do so other than for tidiness' sake.
+		 */
+		
+		/* Next, make our menus */
+		
+		// (Parameter-holding object, some action-listener, some item-listener)
+		
+		MenuBar = constructMenus();
+		
+		this.setJMenuBar(MenuBar);
+		
+	}
+	
+	/**
+	 * Sets up a Panel containing the entire Applet's GUI, and
+	 * returns the Panel.
+	 * <p>
+	 * The Panel contains a JDasherScreen (which is stored in the
+	 * Screen variable) and a JDasherEdit (stored in EditBox).
+	 * 
+	 * @param size Size of the panel to be created
+	 * @return Created Panel
+	 */
+	public JPanel constructGUIPanel(java.awt.Dimension size) {
+		
+		JPanel GUIPanel = new JPanel();
+		
+		GUIPanel.setSize(size);
+
+		GUIPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(10,10,10,10));
+
+		GUIPanel.setLayout(new javax.swing.BoxLayout(GUIPanel, javax.swing.BoxLayout.Y_AXIS));
+
+		java.awt.Dimension EditSize = new java.awt.Dimension(GUIPanel.getWidth() - 20, GUIPanel.getHeight() / 10);
+
+		Screen = new JDasherScreen(Dasher, GUIPanel.getWidth() - 20, (int)(GUIPanel.getHeight() * 0.9) - 40); 
+		panel = new JDasherPanel(Screen, Dasher, GUIPanel.getWidth() - 20, (int)(GUIPanel.getHeight() * 0.9) - 40);
+		
+		GUIPanel.add(panel);
+
+		/* The Screen is a specialisation of JPanel. All drawing is done by
+		 * its paintComponent method. This is different to the original Dasher,
+		 * which painted in a bottom-up method, with Dasher causing its Screen
+		 * obejct to me modified; here the Screen object is very much in charge,
+		 * and Dasher is invoked to determine its appearance.
+		 */
+
+		EditBox = new JDasherEdit(3,80, Dasher);
+
+		EditBox.setLineWrap(true);
+
+		JScrollPane EditScroll = new JScrollPane(EditBox);
+
+		EditScroll.setPreferredSize(EditSize);
+		EditScroll.setMaximumSize(EditSize);
+		EditScroll.setMinimumSize(EditSize);
+		EditScroll.setSize(EditSize);
+
+		/* The EditBox is a specialisation of a JTextPane, but a much lighter
+		 * one than the Screen. */
+		
+		GUIPanel.add(EditScroll);
+		
+		return GUIPanel;
+
+	}
+	
+	/**
+	 * Produces our menu bar (a JDasherMenuBar) and returns it.
+	 * <p>
+	 * After instantiating, its options are set from Dasher's
+	 * current settings. For example, we cause the current Alphabet
+	 * to be set as 'selected' in the menu bar.
+	 * 
+	 * @return MenuBar to be added to our Applet
+	 */
+	public JDasherMenuBar constructMenus() {
+		
+		JDasherMenuBar MenuBar = new JDasherMenuBar(this);
+		
+		ArrayList<String> colours = new ArrayList<String>();
+		Dasher.GetColours(colours);
+		MenuBar.setColours(colours, Dasher.GetStringParameter(Esp_parameters.SP_COLOUR_ID));
+		
+		ArrayList<String> alphs = new ArrayList<String>();
+		Dasher.GetAlphabets(alphs);
+		MenuBar.setAlphabets(alphs, Dasher.GetStringParameter(Esp_parameters.SP_ALPHABET_ID));
+		
+		MenuBar.setSelectedFontSize((int)Dasher.GetLongParameter(Elp_parameters.LP_DASHER_FONTSIZE));
+		MenuBar.setInputFilter(Dasher.GetStringParameter(Esp_parameters.SP_INPUT_FILTER));
+		MenuBar.setMouseLine(Dasher.GetBoolParameter(Ebp_parameters.BP_DRAW_MOUSE_LINE));
+		MenuBar.setStartMouse(Dasher.GetBoolParameter(Ebp_parameters.BP_START_MOUSE));
+		MenuBar.setStartSpace(Dasher.GetBoolParameter(Ebp_parameters.BP_START_SPACE));
+		MenuBar.setSelectedLM((int)Dasher.GetLongParameter(Elp_parameters.LP_LANGUAGE_MODEL_ID));
+		MenuBar.setSpeedAuto(Dasher.GetBoolParameter(Ebp_parameters.BP_AUTO_SPEEDCONTROL));
+		MenuBar.setLangModelLearns(Dasher.GetBoolParameter(Ebp_parameters.BP_LM_ADAPTIVE));
+		
+		m_Clipboard.addFlavorListener(MenuBar);
+		
+		return MenuBar;
+		
+	}
+
+	/**
+	 * The Applet responds to the following parameter events:
+	 * <p>
+	 * <i>BP_DASHER_PAUSED</i>: We start/stop requesting frames
+	 * at a regular interval depending on whether Dasher is
+	 * currently paused.
+	 * <p>
+	 * <i>LP_LANGUAGE_MODEL_ID</i>: Updates our MenuBar's currently
+	 * selected language model to reflect that which has been
+	 * chosen.
+	 * <p>
+	 * <i>SP_COLOUR_ID</i>: Updates our MenuBar's currently selected
+	 * colour scheme to reflect that which has been chosen. Usually
+	 * this occurs in response to an alphabet specifying its own
+	 * colour scheme.
+	 * <p>
+	 * The Applet also responds to LockEvents by showing our ScreenOverlay
+	 * when locked and updating its progress bar, and MessageEvents
+	 * by showing a message dialog.
+	 * <p>
+	 * Finally we pass the event on to the EditBox, in case some
+	 * handling is required there as well. 
+	 */
+	public void handleEvent(dasher.CEvent event) {
+		
+		if(event.m_iEventType == 1) { // Parameter change notification
+			
+			dasher.CParameterNotificationEvent evt = (dasher.CParameterNotificationEvent)event;
+			
+			if(evt.m_iParameter == dasher.Ebp_parameters.BP_DASHER_PAUSED) {
+				if(Dasher.GetBoolParameter(dasher.Ebp_parameters.BP_DASHER_PAUSED)) {
+					taskScheduler.cancel();
+					taskScheduler = null;
+				}
+				else {
+					TimerTask doFrame = new DoFrameTask(this);
+					taskScheduler = new Timer();
+					taskScheduler.scheduleAtFixedRate(doFrame, 0, 20);
+				}
+			}
+			else if(evt.m_iParameter == dasher.Elp_parameters.LP_LANGUAGE_MODEL_ID) {
+				if(MenuBar != null) MenuBar.setSelectedLM((int)Dasher.GetLongParameter(dasher.Elp_parameters.LP_LANGUAGE_MODEL_ID));
+			}
+			else if(evt.m_iParameter == dasher.Esp_parameters.SP_COLOUR_ID) {
+				if(MenuBar != null) MenuBar.setSelectedColour(Dasher.GetStringParameter(dasher.Esp_parameters.SP_COLOUR_ID));
+			}
+			
+		}
+		else if(event.m_iEventType == 7) { // Lock event (training progress report) 
+			dasher.CLockEvent evt = (dasher.CLockEvent)event;
+			
+			if(evt.m_bLock) {
+				ProgressMeter.setVisible(true);
+				ProgressMeter.setProgressBarVisible(true);
+				
+				try { 
+					java.awt.Point myloc = this.getLocationOnScreen();
+					ProgressMeter.setLocation(((myloc.x + this.getWidth()) / 2) - 100, ((myloc.y + this.getHeight()) / 2) - 50);
+				}
+				catch(Exception e) {
+					// ignore; this means we're not visible.
+				}
+							
+				ProgressMeter.setText(evt.m_strMessage);
+				
+				ProgressMeter.setProgress(evt.m_iPercent, 100);
+			}
+			else {
+				ProgressMeter.setVisible(false);
+			}
+			
+			
+		}
+		else if(event.m_iEventType == 8) { // Requested message display
+			
+			dasher.CMessageEvent evt = (dasher.CMessageEvent)event;
+			
+			JOptionPane.showMessageDialog(this, evt.m_strMessage, "JDasher", getMessageType(evt.m_iType));
+			
+		}
+		if(EditBox != null) EditBox.handleEvent(event);
+				
+	}
+	
+	/**
+	 * Converts Dasher's message dialog types into JOptionPane's
+	 * constants with the same meaning. For example, type 0 becomes
+	 * JOptionPane.INFORMATION_MESSAGE.
+	 * <p>
+	 * If asked to convert an invalid message type, -1 is returned. 
+	 * 
+	 * @param type Type to convert.
+	 * @return JOptionPane equivalent constant
+	 */
+	private int getMessageType(int type) {
+		
+		// Convert internal message types to those used by JOptionPane.
+		
+		if(type == 0) return JOptionPane.INFORMATION_MESSAGE;
+		if(type == 1) return JOptionPane.WARNING_MESSAGE;
+		if(type == 2) return JOptionPane.ERROR_MESSAGE;
+		
+		return -1;
+	}
+	
+	/**
+	 * MouseClicks are responded to by feeding Dasher a KeyDown
+	 * event. See CDasherInterfaceBase.KeyDown.
+	 */
+	public void mouseClicked(MouseEvent e) {
+		
+		if(e.getButton() == MouseEvent.BUTTON1) {
+			Dasher.KeyDown(System.currentTimeMillis(), 100);
+		}
+		
+	}
+
+	/**
+	 * Ignored
+	 */
+	public void mouseEntered(MouseEvent arg0) {
+	}
+
+	/**
+	 * Ignored
+	 */
+	public void mouseExited(MouseEvent arg0) {
+	}
+	
+	/**
+	 * Ignored
+	 */
+	public void mousePressed(MouseEvent arg0) {
+	}
+
+	/**
+	 * Ignored
+	 */
+	public void mouseReleased(MouseEvent arg0) {
+	}
+	
+	/**
+	 * We respond to the following key presses:
+	 * <p>
+	 * CTRL: Set speed boost factor to 175<br>
+	 * SHIFT: Set speed boost factor to 25.
+	 * </p>
+	 */	
+	public void keyPressed(KeyEvent e) {
+		
+		if(e.getKeyCode() == KeyEvent.VK_CONTROL) {
+			panel.addTasklet(new DasherTasklet() {
+				public void run() {
+					Dasher.SetLongParameter(Elp_parameters.LP_BOOSTFACTOR,175);
+				}
+			});
+			
+		}
+		
+		// Speed boost for pressing CTRL. Should this be in the interface?
+		
+		if(e.getKeyCode() == KeyEvent.VK_SHIFT) {
+			panel.addTasklet(new DasherTasklet() {
+				public void run() {
+					Dasher.SetLongParameter(Elp_parameters.LP_BOOSTFACTOR,25);
+				}
+			});
+		}
+		
+		// Speed reduced when SHIFT pressed. As above?
+		
+	}
+	
+	/**
+	 * Upon releasing the space bar, we signal Dasher a KeyDown
+	 * event with a key of zero.
+	 * <p>
+	 * If either CTRL or SHIFT are released, the speed boost
+	 * constant is reset to 100, 175 or 25, dependent on which
+	 * keys are still down.
+	 */
+	public void keyReleased(KeyEvent e) {
+		
+		/* Dasher will start when SPACE is pressed. */
+		
+		if(e.getKeyCode() == KeyEvent.VK_SPACE) {
+			Dasher.KeyDown(System.currentTimeMillis(), 0);
+		}
+		
+		
+		/* This completes the boost-key implementation by considering
+		 * whether the other boost key is currently pressed when one
+		 * is released.
+		 */
+		
+		if(e.getKeyCode() == KeyEvent.VK_CONTROL) {
+			if(e.isShiftDown()) {
+				panel.addTasklet(new DasherTasklet() {
+					public void run() {
+						Dasher.SetLongParameter(Elp_parameters.LP_BOOSTFACTOR,25);
+					}
+				});
+			}
+			else {
+				panel.addTasklet(new DasherTasklet() {
+					public void run() {
+						Dasher.SetLongParameter(Elp_parameters.LP_BOOSTFACTOR,100);
+					}
+				});
+			}
+		}
+		if(e.getKeyCode() == KeyEvent.VK_SHIFT) {
+			if(e.isControlDown()) {
+				panel.addTasklet(new DasherTasklet() {
+					public void run() {
+						Dasher.SetLongParameter(Elp_parameters.LP_BOOSTFACTOR,175);
+					}
+				});
+			}
+			else {
+				panel.addTasklet(new DasherTasklet() {
+					public void run() {
+						Dasher.SetLongParameter(Elp_parameters.LP_BOOSTFACTOR,100);
+					}
+				});
+			}
+		}
+	}
+
+	/**
+	 * Ignored
+	 */
+	public void keyTyped(KeyEvent arg0) {
+	}
+
+	/**
+	 * Cancels our new frame scheduler, and calls Dasher's
+	 * DestroyInterface method to give it an opportunity to
+	 * clean up if necessary.
+	 * <p>
+	 * Ultimately any neglected cleaning is likely not to
+	 * cause a problem, as we are about to stop the application.
+	 */
+	public void stop() {
+		if(taskScheduler != null) taskScheduler.cancel();
+		Dasher.DestroyInterface();
+	}
+	
+	/**
+	 * Calls the applet's repaint method to trigger a redraw
+	 * of Dasher.
+	 * <p>
+	 * This method is called by Dasher when it wishes to be redrawn;
+	 * the process has to be started from the top because it is
+	 * tied in with Swing's painting architecture.
+	 */
+	public void Redraw() {
+		repaint();
+	}
+
+	/**
+	 * Adds a MouseMotionListener; requested by Dasher in order
+	 * to hook its JMouseInput object up to hear mouse events.
+	 */
+	public void regMouseMotionListener(MouseMotionListener e) {
+		this.addMouseMotionListener(e);
+	}
+
+	/**
+	 * Sets our edit box font
+	 * 
+	 * @param f New font
+	 */
+	public void setNewFont(Font f) {
+		
+		EditBox.setFont(f);
+		
+	}
+
+	/**
+	 * Copies the current edit box selection to the clipboard if
+	 * possible.
+	 */
+	public void menuCopy() {
+		try {
+			m_Clipboard.setContents(new java.awt.datatransfer.StringSelection(EditBox.getSelectedText()), null);
+		}
+		catch (Exception ex) {
+			System.out.printf("Copy to clipboard failed: %s%n", ex.toString());
+		}
+	}
+	
+	/**
+	 * Cuts the current edit box selection to the clipboard if
+	 * possible.
+	 */
+	public void menuCut() {
+		try {
+			m_Clipboard.setContents(new java.awt.datatransfer.StringSelection(EditBox.getSelectedText()), null);
+			EditBox.replaceSelection("");
+		}
+		catch (Exception ex) {
+			System.out.printf("Cut to clipboard failed: %s%n", ex.toString());
+		}
+	}
+
+	/**
+	 * Quits Dasher
+	 */
+	public void menuExit() {
+		System.exit(0); // Should make this tidier...
+	}
+
+	/**
+	 * Displays an About dialog showing the compilation date.
+	 */
+	public void menuHelpAbout() {
+		
+		JOptionPane.showMessageDialog(this, "JDasher\nVersion compiled: " + buildDate);
+		
+	}
+
+	/**
+	 * Blanks the EditBox and invalidates our current context.
+	 */
+	public void menuNew() {
+		this.EditBox.setText("");
+		this.Dasher.InvalidateContext(true);
+	}
+
+	/**
+	 * Attempts to paste from the clipboard, overwriting our current
+	 * EditBox selection if there is one.
+	 */
+	public void menuPaste() {
+		try {
+			java.awt.datatransfer.Transferable clipContents = m_Clipboard.getContents(null);
+			String temp = (String)clipContents.getTransferData(java.awt.datatransfer.DataFlavor.stringFlavor);
+			EditBox.replaceSelection(temp);
+		}
+		catch (Exception ex) {
+			System.out.printf("Paste from clipboard failed: %s%n", ex.toString());
+		}
+	}
+
+	/**
+	 * Opens the Select Font dialog in order to choose a new
+	 * EditBox font
+	 */
+	public void menuSelFont() {
+		new dasher.applet.font.JFontDialog(this, EditBox.getFont());
+	}
+
+	/**
+	 * Sets Dasher's LP_MAX_BITRATE parameter to a given value
+	 * 
+	 * @param speed New LP_MAX_BITRATE
+	 */
+	public void menuSetDasherSpeed(int speed) {
+		
+		final int f_speed = speed;
+		
+		panel.addTasklet(new DasherTasklet() {
+			public void run() {
+				Dasher.SetLongParameter(Elp_parameters.LP_MAX_BITRATE, f_speed);
+			}
+		});
+		
+	}
+
+	/**
+	 * Sets the Dasher font size (LP_DASHER_FONTSIZE) to a given value.
+	 * 
+	 * @param size New size; either 1, 2 or 4.
+	 */
+	public void menuSetFontSize(int size) {
+		
+		final int f_size = size;
+		
+		panel.addTasklet(new DasherTasklet() {
+			public void run() {
+				Dasher.SetLongParameter(Elp_parameters.LP_DASHER_FONTSIZE, f_size);
+			}
+		});
+
+	}
+
+	/**
+	 * Sets the input filter (SP_INPUT_FILTER) to a given String.
+	 * 
+	 * @param filter Name of new input filter
+	 */
+	public void menuSetInputFilter(String filter) {
+		
+		final String f_filter = filter;
+		
+		panel.addTasklet(new DasherTasklet() {
+			public void run() {
+				Dasher.SetStringParameter(Esp_parameters.SP_INPUT_FILTER, f_filter);
+			}
+		});
+		
+	}
+
+	/**
+	 * Sets the currently selected language model to a given ID.
+	 * <p>
+	 * If an ID of 5 (corresponding to the RemotePPM language model)
+	 * is selected, we first prompt the user to name a host and set
+	 * the SP_LM_HOST parameter to their chosen value.
+	 * <p>
+	 * In any case, we end up setting LP_LANGUAGE_MODEL_ID.
+	 * 
+	 * @param LMID New LM ID 
+	 */
+	public void menuSetLMID(final int LMID) {
+		if(LMID == 5) { // Network PPM
+			final String hostName = JOptionPane.showInputDialog("Please enter the language model host address", Dasher.GetStringParameter(Esp_parameters.SP_LM_HOST));
+			
+			if(hostName != null) {
+				
+				panel.addTasklet(new DasherTasklet() {
+					public void run() {
+						Dasher.SetBoolParameter(Ebp_parameters.BP_CONNECT_LOCK, true);
+						// Set the connect lock so the user can't move whilst establishing connection.
+
+						Dasher.SetStringParameter(Esp_parameters.SP_LM_HOST, hostName);
+
+						Dasher.SetLongParameter(Elp_parameters.LP_LANGUAGE_MODEL_ID, 5);
+					}
+				});
+				
+
+			}
+		}
+		else {
+			
+			panel.addTasklet(new DasherTasklet() {
+				public void run() {
+					Dasher.SetLongParameter(Elp_parameters.LP_LANGUAGE_MODEL_ID, LMID);				
+				}
+			});
+
+		}
+			
+	}
+
+	/**
+	 * Sets BP_LM_ADAPTIVE
+	 * 
+	 * @param enabled New value
+	 */
+	public void menuSetLMLearn(final boolean enabled) {
+		
+		panel.addTasklet(new DasherTasklet() {
+			public void run() {
+				Dasher.SetBoolParameter(Ebp_parameters.BP_LM_ADAPTIVE, enabled);				
+			}
+		});
+		
+	}
+
+	/**
+	 * Sets BP_DRAW_MOUSE_LINE
+	 * 
+	 * @param enabled New value
+	 */
+	public void menuSetMouseLine(final boolean enabled) {
+		
+		panel.addTasklet(new DasherTasklet() {
+			public void run() {
+				Dasher.SetBoolParameter(Ebp_parameters.BP_DRAW_MOUSE_LINE, enabled);				
+			}
+		});
+
+	}
+
+	/**
+	 * Sets BP_AUTO_SPEEDCONTROL
+	 * 
+	 * @param enabled New value
+	 */
+	public void menuSetSpeedAuto(final boolean enabled) {
+		
+		panel.addTasklet(new DasherTasklet() {
+			public void run() {
+				Dasher.SetBoolParameter(Ebp_parameters.BP_AUTO_SPEEDCONTROL, enabled);				
+			}
+		});
+		
+	}
+
+	/**
+	 * Sets BP_START_MOUSE
+	 * 
+	 * @param enabled New value
+	 */
+	public void menuSetStartMouse(final boolean enabled) {
+		panel.addTasklet(new DasherTasklet() {
+			public void run() {
+				Dasher.SetBoolParameter(Ebp_parameters.BP_START_MOUSE, enabled);				
+			}
+		});
+		
+	}
+
+	/**
+	 * Sets BP_START_SPACE
+	 * 
+	 * @param enabled New value
+	 */
+	public void menuSetStartSpace(final boolean enabled) {
+			panel.addTasklet(new DasherTasklet() {
+				public void run() {
+					Dasher.SetBoolParameter(Ebp_parameters.BP_START_SPACE, enabled);				
+				}
+			});
+	}
+
+	/**
+	 * Sets the currently selected alphabet
+	 * 
+	 * @param newalph Alphabet to select
+	 */
+	public void menuSetAlph(final String newalph) {
+		
+		ArrayList<String> Alphs = new ArrayList<String>();
+		Dasher.GetAlphabets(Alphs);
+
+		for(String thisAlph : Alphs) {
+			if(thisAlph.equals(newalph)) {
+				panel.addTasklet(new DasherTasklet() {
+					public void run() {
+						Dasher.SetStringParameter(Esp_parameters.SP_ALPHABET_ID, newalph);
+					}
+				});
+				return;
+			}
+		}
+		
+	}
+
+	/**
+	 * Sets the currently selected colourscheme
+	 * 
+	 * @param newcolours Colour scheme to select
+	 */
+	public void menuSetColours(String newcolours) {
+		
+		ArrayList<String> Colours = new ArrayList<String>();
+		Dasher.GetColours(Colours);
+		
+		for(String thisColour : Colours) {
+			if(thisColour.equals(newcolours)) {
+				final String col = thisColour;
+				panel.addTasklet(new DasherTasklet() { public void run() {
+					Dasher.SetStringParameter(Esp_parameters.SP_COLOUR_ID, col);
+				}});
+				return;
+			}
+		}
+		
+	}
+	
+	/**
+	 * Checks with the clipboard whether a given data flavour
+	 * is enabled.
+	 * <p>
+	 * Typically this is used to check whether it is sensible
+	 * to attempt Paste at the moment.
+	 * 
+	 * @param flavour Flavour to check availability
+	 * @return True if available at present, false otherwise. 
+	 */
+	public boolean isDataFlavorAvailable(java.awt.datatransfer.DataFlavor flavour) {
+		return m_Clipboard.isDataFlavorAvailable(flavour);
+	}
+	
+	/**
+	 * Retrieves the current EditBox text. This method exists
+	 * for the purposes of JavaScript calling in to invoke unsafe
+	 * functions.
+	 * <p>
+	 * Thankfully, this doesn't work on FireFox.
+	 * 
+	 * @return Current EditBox contents
+	 */
+	public String getCurrentEditBoxText() {
+		
+		return EditBox.getText();
+		
+	}
+}

Added: trunk/java/dasher/applet/JDasherEdit.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/JDasherEdit.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,198 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher.applet;
+
+import javax.swing.event.CaretEvent;
+import javax.swing.event.CaretListener;
+import javax.swing.JTextArea;
+
+/**
+ * JDasherEdit is essentially an ordinary JTextArea with an added
+ * event handler to respond to Dasher's Edit Events. It responds
+ * to EditEvents to update the contents of the text box, and to
+ * EditContextEvents to supply a context if it knows of one.
+ * 
+ */
+public class JDasherEdit extends JTextArea implements CaretListener {
+	
+	/**
+	 * Interface which this EditBox will control when text is
+	 * entered, typically by calling InvalidateContext if the
+	 * user manually edits the text.
+	 */
+	private dasher.CDasherInterfaceBase m_Interface;
+	
+	/**
+	 * Where the TextArea's Dot was last event; useful in determining
+	 * what kind of edit the user has made. 
+	 */
+	private int iPrevDot;
+	
+	/**
+	 * Where the TextArea's Mark was last event; useful in determining
+	 * what kind of edit the user has made. 
+	 */
+	private int iPrevMark;
+	
+	/**
+	 * Flag to supress events which we generate by acting on the
+	 * Dasher interface. Duplicate events may be generated because
+	 * we listen to both Dasher's internal event system and also
+	 * Java's EditEvents to spot when the user makes changes
+	 * to the TextArea's contents.
+	 */
+	private boolean supressNextEvent;
+	
+	/**
+	 * Creates a new EditBox with a given width and height in characters
+	 * and with the ability to control a given interface.
+	 * <p>
+	 * The interface can be null; in this case user changes to the
+	 * edit box will not be reflected in Dasher's behaviour.
+	 * 
+	 * @param rows EditBox width in characters
+	 * @param cols EditBox height in characters
+	 * @param Interface Interface to control
+	 */
+	public JDasherEdit(int rows, int cols, dasher.CDasherInterfaceBase Interface) {
+		super(rows, cols);
+		m_Interface = Interface;
+		
+		this.addCaretListener(this);
+	}
+	
+	/**
+	 * Handles a given event; typically called by Dasher to signal
+	 * text edit events.
+	 * <p>
+	 * If text is added whilst there is a selection, we delete it
+	 * just as if the user had typed over the selection;
+	 * likewise removing a character whilst something is selected
+	 * removes both the selection and its preceding character.
+	 * <p>
+	 * When asked for context with an EditContextEvent, the EditBox
+	 * responds with the x characters before the caret.
+	 * 
+	 * @param event Event to be handled
+	 */	
+	public void handleEvent(dasher.CEvent event) {
+		if(event.m_iEventType == 2) {  // EV_EDIT
+			
+			dasher.CEditEvent evt = (dasher.CEditEvent)event;
+			if(evt.m_iEditType == 1) { // New text!
+				
+				if(this.getSelectedText() != "") {
+					supressNextEvent = true;
+					this.replaceSelection("");
+				}
+				supressNextEvent = true;
+				int oldCaret = this.getCaretPosition();
+				this.insert(evt.m_sText, oldCaret);
+				this.setCaretPosition(oldCaret + 1);
+				
+			}
+			
+			else if(evt.m_iEditType == 2) { // Delete text
+				if(this.getText() != "") {
+
+					supressNextEvent = true;
+
+					if(this.getSelectedText() != "") {
+						this.replaceSelection("");
+					}
+
+					supressNextEvent = true;
+					this.replaceRange("", this.getCaretPosition() - (evt.m_sText.length()), this.getCaretPosition());
+				}
+			}
+			
+			/* The supressNextEvent attribute is to permit us to differentiate
+			 * between events originated in Dasher and those originated by the
+			 * edit box. Dasher-originated DocumentEvents will be immediately preceded
+			 * by an EDIT_EVENT, so we should ignore them.
+			 */
+			
+		}
+		
+		if(event.m_iEventType == 3) { // Request for context
+			
+			dasher.CEditContextEvent evt = (dasher.CEditContextEvent)event;
+			
+			String NewContext;
+			
+			int StartPosition = java.lang.Math.max(0, this.getSelectionStart() - evt.m_iMaxLength);
+			
+			try {
+				if(StartPosition == 0) {
+					NewContext = this.getText(0, this.getSelectionStart());
+				}
+				else {
+					NewContext = this.getText(StartPosition, evt.m_iMaxLength);
+				}
+			}
+			catch(Exception e) {
+				return;
+			}
+			
+			evt.newContext = NewContext;
+						
+		}
+	}
+
+	/**
+	 * Called by Java's event handling subsystem when the user moves
+	 * the caret, either by typing or clicking.
+	 * <p>
+	 * If the supressEvent flag is false, we respond by invalidating
+	 * our current context so that the interface will request a new one,
+	 * which we will respond to with that which is appropriate
+	 * to the new position.
+	 * <p>
+	 * If the supressEvent flag is true we set it to false and
+	 * do nothing else.
+	 * <p>
+	 * If m_Interface is null, nothing is ever done. 
+	 */
+	public void caretUpdate(CaretEvent e) {
+		
+		if(e.getDot() == iPrevDot && e.getMark() == iPrevMark) return;
+		
+		if(!supressNextEvent && m_Interface != null) {
+			
+			m_Interface.InvalidateContext(true);
+			// Used to be false. Changed so we can type when at zero-length.
+			
+		}
+		else {
+			// Event caused by Dasher performing modifications; ignore.
+			supressNextEvent = false;
+		}
+		
+		iPrevDot = e.getDot();
+		iPrevMark = e.getMark();
+		
+	}	
+}

Added: trunk/java/dasher/applet/JDasherHost.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/JDasherHost.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,65 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher.applet;
+
+/** Capabilities required of anything which contains a Dasher control.
+ * This provides decoupling between the Applet and the core, so that Dasher
+ * can be integrated into any Java app.
+ */
+public interface JDasherHost {
+
+	/**
+	 * Should trigger a redraw of Dasher by any means necessary.
+	 * <p>
+	 * This may mean simply calling Dasher.Draw if no user interface
+	 * setup is necessary.
+	 * <p>
+	 * Under Swing this typically means starting a top-level repaint.
+	 *
+	 */
+	public void Redraw();
+	
+	/**
+	 * Register ourselves to receive mouse motion events from the host.
+	 * <p>
+	 * The host should either register the submitted object as a MouseMotionListener
+	 * or supply its own events by some other means.
+	 * 
+	 * @param e Listener to add
+	 */
+	public void regMouseMotionListener(java.awt.event.MouseMotionListener e);
+	
+	/**
+	 * Passes an event to the host; the host need not do anything
+	 * if it doesn't want to.
+	 * <p>
+	 * At present, all events are passed up.
+	 * 
+	 * @param event Event being passed
+	 */
+	public void handleEvent(dasher.CEvent event);
+	
+}

Added: trunk/java/dasher/applet/JDasherMenuBar.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/JDasherMenuBar.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,372 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher.applet;
+
+import java.awt.datatransfer.FlavorEvent;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.util.ArrayList;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JRadioButtonMenuItem;
+
+/** 
+ * The menu bar is entirely dumb. Its purpose is to do the donkey work of setting
+ * up the menus; it then simply listens for events and calls the appropriate methods
+ * belonging to its host. It is the responsibility of the host to ensure it is
+ * properly set up to begin with, including setting which options are selected
+ * at application startup.
+ * <p>
+ * Members and functions not documented; largely everything means
+ * what its name suggests. If new menu items are desired, one should
+ * create a new local variable referencing the new menu items,
+ * and add lines to the Constructor which create the new menus.
+ */
+public class JDasherMenuBar extends JMenuBar implements ActionListener, ItemListener, java.awt.datatransfer.FlavorListener {
+	
+	private JMenu file, edit, options, control, prediction, help;
+	
+	private JMenuItem file_new, file_exit;
+	
+	private JMenuItem edit_cut, edit_copy, edit_paste;
+	
+	private JMenu control_speed; 
+	private JRadioButtonMenuItem control_speed_slow, control_speed_medium, control_speed_fast, control_speed_fastest;
+	private JCheckBoxMenuItem control_speed_auto;
+	private JMenu control_style;
+	private JRadioButtonMenuItem control_style_normal, control_style_click;
+	private JCheckBoxMenuItem control_mousestart, control_spacestart;
+		
+	private JMenuItem options_editfont;
+	private JMenu options_fontsize;
+	private JRadioButtonMenuItem options_fontsize_small, options_fontsize_medium, options_fontsize_large;
+	private JCheckBoxMenuItem options_mouseline;
+	private JMenu options_alphabet, options_colours;
+	
+	private JMenu prediction_langmodel;
+	private JRadioButtonMenuItem prediction_langmodel_ppm, prediction_langmodel_net; 
+	private JCheckBoxMenuItem prediction_langmodel_learn;
+	
+	private JMenuItem help_about;
+	
+	private ButtonGroup options_colours_group, options_alphabet_group;
+	
+	private JDasherMenuBarListener m_Host;
+	
+	/**
+	 * Creates a JDasherMenuBar which signals a given listener
+	 * when the user selects menu items.
+	 * 
+	 * @param listener Listener whose methods are to be
+	 * invoked upon user commands
+	 */
+	public JDasherMenuBar(JDasherMenuBarListener listener) {
+		
+		m_Host = listener;
+			
+		file = new JMenu("File"); this.add(file);
+		edit = new JMenu("Edit"); this.add(edit);
+		options = new JMenu("Options"); this.add(options);
+		control = new JMenu("Control"); this.add(control);
+		prediction = new JMenu("Prediction"); this.add(prediction);
+		help = new JMenu("Help"); this.add(help);
+		
+		file_new = new JMenuItem("New"); file.add(file_new); file_new.addActionListener(this);
+		file_exit = new JMenuItem("Exit"); file.add(file_exit); file_exit.addActionListener(this);
+		
+		edit_cut = new JMenuItem("Cut"); edit.add(edit_cut); edit_cut.addActionListener(this);
+		edit_copy = new JMenuItem("Copy"); edit.add(edit_copy); edit_copy.addActionListener(this);
+		edit_paste = new JMenuItem("Paste"); edit.add(edit_paste); edit_paste.addActionListener(this);
+		
+		edit_paste.setEnabled(false);
+				
+		options_editfont = new JMenuItem("Select Font..."); options.add(options_editfont); options_editfont.addActionListener(this);
+		
+		options_fontsize = new JMenu("Dasher Font Size"); options.add(options_fontsize);
+			
+		ButtonGroup options_fontsize_group = new ButtonGroup();
+		options_fontsize_large = new JRadioButtonMenuItem("Large"); options_fontsize_group.add(options_fontsize_large); options_fontsize.add(options_fontsize_large); options_fontsize_large.addActionListener(this);
+		options_fontsize_medium = new JRadioButtonMenuItem("Medium"); options_fontsize_group.add(options_fontsize_medium); options_fontsize.add(options_fontsize_medium); options_fontsize_medium.addActionListener(this);
+		options_fontsize_small = new JRadioButtonMenuItem("Small"); options_fontsize_group.add(options_fontsize_small); options_fontsize.add(options_fontsize_small); options_fontsize_small.addActionListener(this);
+		
+		options_mouseline = new JCheckBoxMenuItem("Display Mouse Line"); options.add(options_mouseline); options_mouseline.addItemListener(this);
+		
+		options_alphabet = new JMenu("Alphabet"); options.add(options_alphabet); 
+
+		options_alphabet_group = new ButtonGroup();
+				
+		options_colours = new JMenu("Colour Scheme"); options.add(options_colours);
+		
+		options_colours_group = new ButtonGroup();
+		
+		control_style = new JMenu("Control Style"); control.add(control_style);
+		ButtonGroup control_style_group = new ButtonGroup();
+		control_style_normal = new JRadioButtonMenuItem("Normal Control (hover)"); control_style_group.add(control_style_normal); control_style.add(control_style_normal); control_style_normal.addActionListener(this);
+		control_style_click = new JRadioButtonMenuItem("Click Mode"); control_style_group.add(control_style_click); control_style.add(control_style_click); control_style_click.addActionListener(this);
+		
+		control_mousestart = new JCheckBoxMenuItem("Start on Mouse"); control.add(control_mousestart); control_mousestart.addItemListener(this);
+						
+		control_spacestart = new JCheckBoxMenuItem("Start on Space"); control.add(control_spacestart); control_spacestart.addItemListener(this);
+				
+		control_speed = new JMenu("Dasher Speed"); control.add(control_speed);
+		ButtonGroup control_speed_group = new ButtonGroup();
+		control_speed_slow = new JRadioButtonMenuItem("Slow"); control_speed_group.add(control_speed_slow); control_speed.add(control_speed_slow); control_speed_slow.addActionListener(this);
+		control_speed_medium = new JRadioButtonMenuItem("Normal"); control_speed_group.add(control_speed_medium); control_speed.add(control_speed_medium); control_speed_medium.addActionListener(this);
+		control_speed_fast = new JRadioButtonMenuItem("Fast"); control_speed_group.add(control_speed_fast); control_speed.add(control_speed_fast); control_speed_fast.addActionListener(this);
+		control_speed_fastest = new JRadioButtonMenuItem("Fastest"); control_speed_group.add(control_speed_fastest); control_speed.add(control_speed_fastest); control_speed_fastest.addActionListener(this);
+		control_speed.addSeparator();
+		control_speed_auto = new JCheckBoxMenuItem("Auto-adjust"); control_speed.add(control_speed_auto); control_speed_auto.addItemListener(this);
+		
+		prediction_langmodel = new JMenu("Language Model"); prediction.add(prediction_langmodel);
+		ButtonGroup prediction_langmodel_group = new ButtonGroup();
+		prediction_langmodel_ppm = new JRadioButtonMenuItem("Prediction by Partial Match"); prediction_langmodel.add(prediction_langmodel_ppm); prediction_langmodel_group.add(prediction_langmodel_ppm); prediction_langmodel_ppm.addActionListener(this);
+		prediction_langmodel_net = new JRadioButtonMenuItem("Networked PPM"); prediction_langmodel.add(prediction_langmodel_net); prediction_langmodel_group.add(prediction_langmodel_net); prediction_langmodel_net.addActionListener(this);
+		prediction_langmodel.addSeparator();
+		prediction_langmodel_learn = new JCheckBoxMenuItem("Language Model Learns"); prediction_langmodel.add(prediction_langmodel_learn); prediction_langmodel_learn.addItemListener(this);
+	
+		help_about = new JMenuItem("About..."); help.add(help_about); help_about.addActionListener(this);
+
+	}
+	
+	public void actionPerformed(ActionEvent e) {
+		// Handles all ordinary and radio-button menus.
+		
+		if(e.getActionCommand().equals("New")) {
+			m_Host.menuNew();
+		}
+		else if(e.getActionCommand().equals("Exit")) {
+			m_Host.menuExit();
+		}
+		else if(e.getActionCommand().equals("Cut")) {
+			m_Host.menuCut();
+		}
+		else if(e.getActionCommand().equals("Copy")) {
+			m_Host.menuCopy();
+		}
+		else if(e.getActionCommand().equals("Paste")) {
+			m_Host.menuPaste();
+		}
+		else if(e.getActionCommand().equals("Select Font...")) {
+			m_Host.menuSelFont();
+		}
+		else if(e.getActionCommand().equals("Large")) {
+			m_Host.menuSetFontSize(4);
+		}
+		else if(e.getActionCommand().equals("Medium")) {
+			m_Host.menuSetFontSize(2);
+		}
+		else if(e.getActionCommand().equals("Small")) {
+			m_Host.menuSetFontSize(1);
+		}
+		else if(e.getActionCommand().equals("Normal Control (hover)")) {
+			m_Host.menuSetInputFilter("Normal Control");
+		}
+		else if(e.getActionCommand().equals("Click Mode")) {
+			m_Host.menuSetInputFilter("Click Mode");
+		}
+		else if(e.getActionCommand().equals("Slow")) {
+			m_Host.menuSetDasherSpeed(100);
+			setSpeedAbs();
+		}
+		else if(e.getActionCommand().equals("Normal")) {
+			m_Host.menuSetDasherSpeed(200);
+			setSpeedAbs();
+		}
+		else if(e.getActionCommand().equals("Fast")) {
+			m_Host.menuSetDasherSpeed(400);
+			setSpeedAbs();
+		}
+		else if(e.getActionCommand().equals("Fastest")) {
+			m_Host.menuSetDasherSpeed(800);
+			setSpeedAbs();
+		}
+		else if(e.getActionCommand().equals("Prediction by Partial Match")) {
+			m_Host.menuSetLMID(0);
+		}
+		else if(e.getActionCommand().equals("Networked PPM")) {
+			m_Host.menuSetLMID(5);					
+		}
+		else if(e.getActionCommand().equals("About...")) {
+			m_Host.menuHelpAbout();			
+		}
+	}
+	
+	public void itemStateChanged(ItemEvent e) {
+		JCheckBoxMenuItem tickbox = ((JCheckBoxMenuItem)e.getItem());
+		
+		if(tickbox.getText().equals("Display Mouse Line")) {
+			m_Host.menuSetMouseLine(tickbox.isSelected());
+		}
+		else if(tickbox.getText().equals("Start on Mouse")) {
+			m_Host.menuSetStartMouse(tickbox.isSelected());
+		}
+		else if(tickbox.getText().equals("Start on Space")) {
+			m_Host.menuSetStartSpace(tickbox.isSelected());
+		}
+		else if(tickbox.getText().equals("Auto-adjust")) {
+			m_Host.menuSetSpeedAuto(tickbox.isSelected());
+			setSpeedAuto(tickbox.isSelected());
+		}
+		else if(tickbox.getText().equals("Language Model Learns")) {
+			m_Host.menuSetLMLearn(tickbox.isSelected());
+		}
+	}
+	
+	public void setSelectedFontSize(int size) {
+		switch(size) {
+		case 1:
+			options_fontsize_small.setSelected(true);
+			break;
+		case 2:
+			options_fontsize_medium.setSelected(true);
+			break;
+		case 4:
+			options_fontsize_large.setSelected(true);
+			break;
+		}
+	}
+	
+	public void setAlphabets(ArrayList<String> alphs, String current) {
+		
+		ActionListener alphHandler = new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				m_Host.menuSetAlph(e.getActionCommand());
+			}
+		};
+		
+		for(String alph : alphs) {
+			String AlphName = alph;
+			JRadioButtonMenuItem newAlph = new JRadioButtonMenuItem(AlphName);
+			newAlph.addActionListener(alphHandler);
+			options_alphabet.add(newAlph);
+			options_alphabet_group.add(newAlph);
+			if(current.equals(AlphName)) {
+				newAlph.setSelected(true);
+			}
+			
+		}
+		
+	}
+	
+	public void setColours(ArrayList<String> colours, String current) {
+		
+		ActionListener colourHandler = new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				m_Host.menuSetColours(e.getActionCommand());
+			}
+		};
+		
+		
+		for(String ColourName : colours) {
+			JMenuItem newColour = new JRadioButtonMenuItem(ColourName);
+			newColour.addActionListener(colourHandler);
+			options_colours.add(newColour);
+			options_colours_group.add(newColour);
+			if(ColourName.equals(current)) {
+				newColour.setSelected(true);
+			}
+		}
+	}
+	
+	public void setInputFilter(String filter) {
+		if(filter.equals("Normal Control")) control_style_normal.setSelected(true);
+		if(filter.equals("Click Mode")) control_style_click.setSelected(true);
+	}
+	
+	
+	
+	public void setMouseLine(boolean enabled) {
+		options_mouseline.setSelected(enabled);
+	}
+	
+	public void setStartMouse(boolean enabled) {
+		control_mousestart.setSelected(enabled);
+	}
+	
+	public void setStartSpace(boolean enabled) {
+		control_spacestart.setSelected(enabled);
+	}
+
+	public void setSelectedLM(int LMID) {
+		if(LMID == 0) {
+			prediction_langmodel_ppm.setSelected(true);
+		}
+		else if(LMID == 5) {
+			prediction_langmodel_net.setSelected(true);
+		}
+	}
+	
+	public void setPasteEnabled(boolean enabled) {
+		edit_paste.setEnabled(enabled);
+	}
+	
+	public void setSpeedAbs() {
+		control_speed_auto.setSelected(false);
+	}
+	
+	public void setSpeedAuto(boolean enabled) {
+		control_speed_slow.setSelected(false);
+		control_speed_medium.setSelected(false);
+		control_speed_fast.setSelected(false);
+		control_speed_fastest.setSelected(false);
+		control_speed_auto.setSelected(enabled);
+	}
+	
+	public void setLangModelLearns(boolean enabled) {
+		prediction_langmodel_learn.setSelected(enabled);
+	}
+	
+	public void setSelectedColour(String colour) {
+		
+		JMenuItem item;
+		for(int i = 0; i < options_colours.getItemCount(); i++) {
+			item = options_colours.getItem(i);
+			if(item.getText().equals(colour)) {
+				item.setSelected(true);
+			}
+		}
+	}
+
+	public void flavorsChanged(FlavorEvent arg0) {
+		
+		if(m_Host.isDataFlavorAvailable(java.awt.datatransfer.DataFlavor.stringFlavor)) {
+			setPasteEnabled(true);
+		}
+		else {
+			setPasteEnabled(false);
+		}
+		
+	}
+	
+	
+	
+}

Added: trunk/java/dasher/applet/JDasherMenuBarListener.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/JDasherMenuBarListener.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,76 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher.applet;
+
+/**
+ * Interface which must be implemented by all classes that wish
+ * to hear about events spawned by the JDasherMenuBar.  
+ * <p>
+ * The functions will each be called when the menu item corresponding
+ * to their name is invoked.
+ */
+public interface JDasherMenuBarListener {
+	
+	public void menuNew();
+	
+	public void menuCut();
+	
+	public void menuCopy();
+	
+	public void menuPaste();
+	
+	public void menuExit();
+	
+	public void menuSelFont();
+	
+	public void menuSetFontSize(int size);
+	
+	public void menuSetInputFilter(String filter);
+	
+	public void menuSetDasherSpeed(int speed);
+	
+	public void menuSetLMID(int LMID);
+	
+	public void menuHelpAbout();
+	
+	public void menuSetMouseLine(boolean enabled);
+	
+	public void menuSetStartMouse(boolean enabled);
+	
+	public void menuSetStartSpace(boolean enabled);
+	
+	public void menuSetLMLearn(boolean enabled);
+	
+	public void menuSetSpeedAuto(boolean enabled);
+	
+	public void menuSetAlph(String newalph);
+	
+	public void menuSetColours(String newcolours);
+	
+	public boolean isDataFlavorAvailable(java.awt.datatransfer.DataFlavor flavour);
+	// For clipboard control
+	
+}

Added: trunk/java/dasher/applet/JDasherPanel.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/JDasherPanel.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,33 @@
+package dasher.applet;
+
+import java.awt.Graphics;
+
+import javax.swing.*;
+import java.awt.Image;
+
+public class JDasherPanel extends JPanel {
+
+	private JDasherThread worker;
+	
+	public JDasherPanel(JDasherScreen screen, JDasher dasher, int width, int height) {
+
+		this.worker = new JDasherThread(screen, dasher, width, height);
+		worker.start();
+
+	}
+	
+	protected void paintComponent(Graphics g) {
+
+		worker.setSize(this.getWidth(), this.getHeight());
+		Image buffer = worker.getCurrentFrontbuffer();
+		g.drawImage(buffer, 0, 0, null);
+		
+	}
+	
+	public void addTasklet(DasherTasklet t) {
+		worker.addTasklet(t);
+	}
+	
+	
+
+}

Added: trunk/java/dasher/applet/JDasherScreen.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/JDasherScreen.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,445 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher.applet;
+
+import java.awt.*;
+import java.util.HashMap;
+import java.awt.geom.Rectangle2D;
+
+import dasher.CCustomColours;
+import dasher.CDasherView;
+
+import dasher.EColorSchemes;
+
+/**
+ * This implementation of JDasherScreen is an extension of the Swing
+ * basic object JPanel, and works by drawing a frame of Dasher onto
+ * the panel whenever its paintComponent method is called.
+ * <p>
+ * For a general description of the Screen's contract and specifications of
+ * what its methods ought to do, see CDasherScreen. Only details of the implementation
+ * will be noted here.
+ */
+public class JDasherScreen implements dasher.CDasherScreen {
+
+	/**
+	 * Graphics context in which to draw 
+	 */
+	private Graphics paint;
+	
+	/**
+	 * Dasher instance which draws onto this Screen
+	 */
+	private JDasher m_Dasher;
+	
+	/**
+	 * Custom colour scheme against which colour indices are resolved
+	 */
+	private CCustomColours m_Colours;
+		
+	/**
+	 * Map of known sizes of differing characters at different font sizes.
+	 */
+	private HashMap<TextSize, CDasherView.Point> TextSizes;
+	
+	/**
+	 * Map from font sizes to the Font objects used to draw them.
+	 */
+	private HashMap<Long, DasherFont> DrawFonts;
+	
+	/**
+	 * Width of this screen in pixels
+	 */
+	protected int m_iWidth;
+	
+	/**
+	 * Height of this screen in pixels
+	 */
+	protected int m_iHeight;
+	
+	/**
+	 * Creates a new Screen tied to a given Dasher and with given dimensions
+	 * 
+	 * @param Dasher Dasher which is displaying using this screen.
+	 * @param width Width of this screen
+	 * @param height Height of this screen
+	 */
+	public JDasherScreen(JDasher Dasher, int width, int height) {
+		
+		m_Dasher = Dasher;
+		
+		/* We need this back-reference so that we can request new frames to be drawn
+		 * when a paint event arises.
+		 */
+		
+		m_iWidth = width;
+		m_iHeight = height;
+				
+		TextSizes = new HashMap<TextSize, CDasherView.Point>();
+		DrawFonts = new HashMap<Long, DasherFont>();
+		
+	}
+	
+	
+	public int GetWidth() {
+		
+		return m_iWidth;
+		
+	}
+	
+	
+	public int GetHeight() {
+		
+		return m_iHeight;
+		
+	}
+	
+	/**
+	 * Clears the screen using the clearRect method
+	 */
+	public void Blank() {
+		
+		paint.setColor(Color.WHITE);
+		paint.fillRect(0,0,m_iWidth, m_iHeight);
+	}
+
+	public void setSize(int width, int height) {
+		m_iWidth = width;
+		m_iHeight = height;
+	}
+	
+	/**
+	 * Method ignored; as we're drawing to Swing's provided surface, the actual displaying of the image will
+	 * be taken care of for us.
+	 */
+	public void Display() {
+		/* No need to do anything; we've been drawing to the content
+		 * surface all along, and Swing will take care of showing it.
+		 */
+	}
+
+	public void DrawCircle(int iCX, int iCY, int iR, int iColour, boolean bFill) {
+		
+		/* CSFS: This is probably still wrong for reasons described in
+		 * DrawRectangle. I've left it alone for the time being since
+		 * it's very rarely used by Dasher.
+		 */
+		
+		setColour(iColour);
+		
+		if(bFill) {
+			paint.fillOval(iCX - iR, iCY - iR, iR, iR);		
+		}
+		else {
+			paint.drawOval(iCX - iR, iCY - iR, iR, iR);
+		}
+	}
+
+	
+	/** Dasher specifies its co-ordinates like
+	 * <pre>
+	 * y2---------x2
+	 * |           |
+	 * |           |
+	 * x1,y1-------/</pre>
+	 * <p>Whereas Java wants
+	 * <pre>
+	 * 			width
+	 * x,y---------------\
+	 * |				 |
+	 * |				 | height
+	 * |				 |
+	 * \-----------------/
+	 * </pre><p>
+	 * Therefore, I use (x1, y2) as the point to feed to Java, and calculate
+	 * height and width.
+	 * 
+	 */
+	
+	public void DrawRectangle(int x1, int y1, int x2, int y2, int Color, int iOutlineColour, EColorSchemes ColorScheme, boolean bDrawOutline, boolean bFill, int iThickness) {
+				
+		if(bFill) {
+			setColour(Color);
+			paint.fillRect(x1, y2, x2 - x1, y1 - y2);
+		}
+		
+		if(bDrawOutline) {
+			
+			setColour(iOutlineColour);
+
+			paint.drawRect(x1, y2, x2 - x1, y1 - y2); // xtop, yleft, width, height
+		}
+
+		
+	}
+
+	
+	/** Here be more trouble! Dasher is specifying its strings by
+	 * the co-ordinates of the top-left corner of a rectangle in which
+	 * the text will be drawn. So,
+	 * <pre>
+	 *   x,y------------\
+	 *   | Some String  |
+	 *   \--------------/
+	 *  </pre><p>
+	 *   Java's DrawString method however specifies the baseline of the
+	 *   first character, which is the bottom in the case of non-descenders
+	 *   such as a and b, but is not for descenders such as g.
+	 *   <p>
+	 *   Therefore we must figure out the height and adjust x appropriately
+	 *   before drawing the string.
+	 *   <p>
+	 *   It's important to note also that some work in this direction is done
+	 *   by DasherView calling the Screen's TextSize method. This supplies
+	 *   a height and width of a given string in pixels, using a HashMap to
+	 *   do so efficiently.
+	 *
+	 */
+	
+	public void DrawString(String string, int x1, int y1, long Size) {
+				
+		
+		int thisOffset;
+		
+		if(DrawFonts.containsKey(Size)) {
+			paint.setFont(DrawFonts.get(Size).font);
+			thisOffset = DrawFonts.get(Size).drawOffset;
+		}
+		else {
+			Font newFont = new Font("sans", 0, (int)Size);
+			paint.setFont(newFont);
+			FontMetrics fm = paint.getFontMetrics();
+			thisOffset = fm.getAscent();
+			
+			DasherFont newDasherFont = new DasherFont(newFont, thisOffset, (int)Size);
+			
+			DrawFonts.put(Size, newDasherFont);
+		}
+			
+		
+		
+		/* CSFS: Since it is necessary to generate lots of fonts in the course
+		 * of Dashing AND I need to store a drawing offset for each one, 
+		 * (although I may address this later by modifying the drawing code),
+		 * I've adapted the hashmap method found in the GetFont method in
+		 * Screen.inl to save work.
+		 */
+				
+		paint.setColor(Color.BLACK);
+		paint.drawString(string, x1, y1 + (thisOffset / 2));
+	}
+	
+	
+	
+	public void Polygon(CDasherView.Point[] Points, int Number, int Color) {
+		
+		Polygon(Points, Number, Color, 0);
+		
+	}
+
+	public void Polygon(CDasherView.Point[] Points, int Number, int Color, int iWidth) {
+		
+		setColour(Color);
+		int[] xs = new int[Points.length];
+		int[] ys = new int[Points.length];
+		for(int i = 0; i < xs.length; i++) {
+			xs[i] = Points[i].x;
+			ys[i] = Points[i].y;
+		}
+		
+		paint.fillPolygon(xs, ys, xs.length);
+		
+		
+	}
+
+	
+	
+	public void Polyline(CDasherView.Point[] Points, int Number, int iWidth) {
+		
+		Polyline(Points, Number, iWidth, 0);
+		
+	}
+
+	public void Polyline(CDasherView.Point[] Points, int Number, int iWidth, int Colour) {
+		
+		setColour(Colour);
+		int[] xs = new int[Points.length];
+		int[] ys = new int[Points.length];
+		for(int i = 0; i < xs.length; i++) {
+			xs[i] = Points[i].x;
+			ys[i] = Points[i].y;
+		}
+		
+		paint.drawPolygon(xs, ys, xs.length);
+		
+		
+	}
+
+	
+	public void SetColourScheme(CCustomColours ColourScheme) {
+		
+		m_Colours = ColourScheme;
+		
+	}
+
+	
+	/**
+	 * Graphics.getFontMetrics().getStringBounds is used to determine a probable text size.
+	 * <p>
+	 * Results, referenced by a struct containing information about both the character and font size concerned,
+	 * are stored in a HashMap for quick access in the future.
+	 * <p>
+	 * At present, StringBounds' returned answer is augmented by one pixel in the x direction in the interests
+	 * of readability.
+	 * 
+	 * @param string String whose size we want to determine
+	 * @param Size Font size to use
+	 * 
+	 * @return Point defining its size.
+	 */
+	public CDasherView.Point TextSize(String string, int Size) {
+		
+		TextSize testValue = new TextSize();
+		testValue.glyph = string;
+		testValue.size = Size;
+		
+		if(TextSizes.containsKey(testValue)) {
+			return TextSizes.get(testValue);
+		}
+		else {
+			paint.setFont(paint.getFont().deriveFont((float)Size));
+			Rectangle2D newsize = paint.getFontMetrics().getStringBounds(string ,paint);
+			CDasherView.Point newpoint = new CDasherView.Point();
+			newpoint.x = (int)newsize.getWidth() + 1;
+			newpoint.y = (int)newsize.getHeight();
+			
+			TextSizes.put(testValue, newpoint);
+			
+			// System.out.printf("Glyph %s at size %d (%d) has dimensions (%dx%d)%n", string, Size, paint.getFont().getSize(), newpoint.x, newpoint.y);
+	
+			return newpoint;
+			
+			
+		}
+		
+	}
+
+	/**
+	 * Sets the current Graphics context's colour by querying m_Colours for its RGB values.
+	 * <p>
+	 * A colour of -1 is read as being the same as colour 3.
+	 * 
+	 * @param iColour Colour to set
+	 */
+	private void setColour(int iColour) {
+		if(iColour == -1) iColour = 3; // Special value used in Dasher, seems to mean 3.
+		paint.setColor(new Color(m_Colours.GetRed(iColour), m_Colours.GetGreen(iColour), m_Colours.GetBlue(iColour)));
+	}
+
+	public void SendMarker(int iMarker) {
+	
+		// Stub: This method is, for the time being, useless since Display() and Blank() serve the same purpose.
+		
+	}
+
+	/**
+	 * Sets our Graphics context and calls NewFrame; Dasher will do the rest.
+	 */
+	public void drawToComponent(Graphics g) {
+		
+		paint = g;
+		m_Dasher.NewFrame(System.currentTimeMillis());
+		
+	}
+
+}
+
+/**
+ * Small struct representing a Font and detailing both its size
+ * and the offset required to draw it using top-left co-ordinates
+ * as opposed to Java's baseline co-ordinates.
+ */
+class DasherFont {
+	/**
+	 * Font
+	 */
+	Font font;
+	
+	/**
+	 * Vertical offset from baseline to top-left corner in this font
+	 */
+	int drawOffset;
+	
+	/**
+	 * Font size
+	 */
+	int size;
+	
+	public DasherFont(Font i_Font, int i_drawOffset, int iSize) {
+		font = i_Font;
+		drawOffset = i_drawOffset;
+		size = iSize;
+	}
+}
+
+/**
+ * Small struct used to store a glyph and font-size pair in the
+ * character-to-drawn-size map.
+ */
+class TextSize {
+	/**
+	 * Character(s)
+	 */
+	String glyph;
+	
+	/**
+	 * Font size
+	 */
+	int size;
+	
+	/**
+	 * Returns true if the String and font size both match.
+	 */
+	public boolean equals(Object otherone) {
+		if(otherone == null) {
+			return false;
+		}
+		if(otherone instanceof TextSize) {
+			TextSize theother = (TextSize)otherone;
+			return (this.glyph.equals(theother.glyph) && this.size == theother.size);
+		}
+		else {
+			return false;
+		}
+	}
+	
+	/**
+	 * Overridden to use the String's hashCode plus the size.
+	 */
+	public int hashCode() {
+		return this.glyph.hashCode() + size;
+	}
+}

Added: trunk/java/dasher/applet/JDasherThread.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/JDasherThread.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,119 @@
+package dasher.applet;
+import java.util.*;
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+
+public class JDasherThread extends Thread {
+
+	private JDasherScreen screen;
+	private Image backbuffer;
+	private Image frontbuffer;
+	private int state;
+	private boolean frontbufferValid;
+	/* Possible state values: 
+	 * 0 - the backbuffer is not ready yet; the user should show the front.
+	 * 1 - the backbuffer is ready for viewing; the user should show this,
+	 *     flip the buffers and toggle this value.
+	 * 2 - the thread should stop at the next possible opportunity.
+	 */
+	private Queue<DasherTasklet> events;
+	
+	private int width, height;
+	
+	public JDasherThread(JDasherScreen screen, JDasher dasher, int width, int height) {
+		
+		this.screen = screen;
+		backbuffer = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
+		frontbuffer = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
+		frontbufferValid = false;
+		this.width = width;
+		this.height = height;
+		events = new LinkedList<DasherTasklet>();
+		
+	}
+	
+	public synchronized void addTasklet(DasherTasklet t) {
+		events.add(t);
+		this.notifyAll();
+	}
+	
+	private synchronized int getEvent() {
+
+		while(this.state == 1 && events.isEmpty()) {
+			try {
+				wait();
+			}
+			catch(InterruptedException e) {
+				return 2;
+			}
+		}
+		
+		if(!events.isEmpty()) {
+			return 3;
+		}
+		else {		
+			return this.state;
+		}
+		
+	}
+	
+	public synchronized void setSize(int width, int height) {
+		
+		if(this.width == width && this.height == height) {
+			return;
+		}
+		else {
+			frontbufferValid = false;
+			state = 0;
+			backbuffer = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
+			frontbuffer = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
+			this.width = width;
+			this.height = height;
+			screen.setSize(width, height);
+			this.notifyAll();
+		}
+		
+	}
+	
+	public synchronized Image getCurrentFrontbuffer() {
+		
+		while(!frontbufferValid) {
+			try { wait();} catch(InterruptedException e) {}
+		}
+			
+		state = 0;
+		this.notifyAll();
+		return frontbuffer;
+		
+	}
+	
+	public void run() {
+		
+		while(true) {
+			int event = getEvent();
+			
+			if(event == 2) return;
+			// Thread should stop
+			
+			if(event == 0) {			
+				screen.drawToComponent(backbuffer.getGraphics());
+			
+				synchronized(this) {
+					Image temp = frontbuffer;
+					frontbuffer = backbuffer;
+					backbuffer = temp;
+					frontbufferValid = true;
+					state = 1;
+					this.notifyAll();
+				}
+			}
+			else if(event == 3) {
+				DasherTasklet toRun = events.remove();
+				toRun.run();
+			}
+			
+		}
+		
+	}
+	
+}

Added: trunk/java/dasher/applet/JMouseInput.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/JMouseInput.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,96 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher.applet;
+
+import java.awt.event.*;
+
+/**
+ * Simple mouse input device which uses a mouse motion listener to
+ * track the mouse position and reports the latest reading when
+ * GetCoordinates is called.
+ * <p>
+ * Only methods which differ significantly from their abstract meanings
+ * documented in CDasherInput are documented here; for further details
+ * see CDasherInput.
+ */
+public class JMouseInput extends dasher.CDasherInput implements MouseMotionListener {
+
+	/**
+	 * Last seen mouse X co-ordinate
+	 */
+	private int mouseX;
+	
+	/**
+	 * Last seen mouse Y co-ordinate
+	 */
+	private int mouseY;
+	
+	public JMouseInput(dasher.CEventHandler EventHandler, dasher.CSettingsStore SettingsStore) {
+		super(EventHandler, SettingsStore, 0, 0, "Mouse Input"); 
+	}
+
+	
+	public int GetCoordinateCount() {
+	
+		return 2;
+		
+	}
+
+	/**
+	 * Ignored
+	 */
+	public void mouseDragged(MouseEvent e) {
+		// Do nothing		
+	}
+
+	/**
+	 * Nasty hack alert! At present, this stores the read
+	 * mouse co-ordinates less 10 in the X direction and 30 in the
+	 * Y direction, since this is the border in the current setup
+	 * of JDasher. This means that it will break if the Panel
+	 * is moved elsewhere on the screen.
+	 * <p>
+	 * This needs to be generalised so that we offset the co-ordinates
+	 * appropriately and respond to changes in the Screen's position.
+	 */
+	public void mouseMoved(MouseEvent e) {
+		mouseX = e.getX() - 10;
+		mouseY = e.getY() - 30;
+		
+		// Nasty hack whilst I figure out how to do this properly...
+	}
+
+	public int GetCoordinates(int iN, long[] Coordinates) {
+		
+		Coordinates[0] = mouseX;
+		Coordinates[1] = mouseY;
+		return 0;
+		
+	}
+	
+	
+	
+}

Added: trunk/java/dasher/applet/JSettings.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/JSettings.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,169 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher.applet;
+
+import java.security.AccessControlException;
+import java.util.prefs.Preferences;
+
+import dasher.CEventHandler;
+import dasher.CParameterNotFoundException;
+import dasher.CSettingsStore;
+
+/**
+ * Extension of CSettingsStore which uses a Java Preferences
+ * object to store settings between sessions.
+ * <p>
+ * This boils down to using the registry in Windows, and a hidden
+ * file in the user's profile on Unix-style systems including
+ * MacOSX.
+ * <p>
+ * In the current unsigned applet setup this will not get used,
+ * as a security exception is thrown on trying to instantiate
+ * Preferences and a plain old CSettingsStore will be used in lieu.
+ * <p>
+ * Should JDasher ever get converted to a standalone Java application
+ * or signed applet, however, this will spring into life and provide
+ * persistent settings.
+ * <p>
+ * I have not documented these functions, as they all implement
+ * precisely the behaviour specified in CSettingsStore.
+ * <p>
+ * The only noteworthy feature is that the Constructor will throw
+ * a StoreUnavailableException if unable to open the registry
+ * and/or user profile.
+ */
+public class JSettings extends CSettingsStore {
+
+	private Preferences appSettings;
+	
+	public JSettings(CEventHandler handler) throws StoreUnavailableException {
+		
+		super(handler, false);
+		
+		try {
+			appSettings = Preferences.userRoot();
+		}
+		catch(AccessControlException e) {
+			throw new StoreUnavailableException();
+		}
+		
+		LoadPersistent();
+			
+	}
+	
+	
+	protected boolean LoadBoolSetting(String Key) throws CParameterNotFoundException {
+	
+		/* CSFS: This annoying hack is to work around the fact that any
+		 * failure to return a value is responded to by returning the default!
+		 */
+		
+		try {
+			int retval = appSettings.getInt("JDasher/B_" + Key, 2);
+			if(retval == 0) return false;
+			else if(retval == 1) return true;
+			else throw new CParameterNotFoundException(Key);
+		}
+		catch (AccessControlException e) {
+			throw new CParameterNotFoundException(Key);
+		}
+		
+	}
+
+
+	protected long LoadLongSetting(String Key) throws CParameterNotFoundException {
+		
+		try {
+			long retval = appSettings.getLong("JDasher/L_" + Key, -999);
+			if (retval == -999) throw new CParameterNotFoundException(Key);
+			else return retval;
+		}
+		catch (AccessControlException e) {
+			throw new CParameterNotFoundException(Key);
+		}
+	}
+
+
+	protected String LoadStringSetting(String Key) throws CParameterNotFoundException {
+	
+		try {
+			String retval = appSettings.get("JDasher/S_" + Key, "Parameter Error");
+			if(retval.equals("Parameter Error")) throw new CParameterNotFoundException("Key");
+			else return retval;
+		}
+		catch (AccessControlException e) {
+			throw new CParameterNotFoundException(Key);
+		}
+	}
+
+
+	protected void SaveSetting(String Key, boolean Value) {
+		int val;
+		if (Value == false) {
+			val = 0;
+		}
+		else {
+			val = 1;
+		}
+		try {
+			appSettings.putInt("JDasher/B_" + Key, val);
+		}
+		catch (AccessControlException e) {
+			return; // Fail silently; we will use the default next time
+		}
+	}
+
+
+	protected void SaveSetting(String Key, long Value) {
+		try {
+			appSettings.putLong("JDasher/L_" + Key, Value);
+		}
+	
+		catch (AccessControlException e) {
+			return; // Fail silently; we will use the default next time
+		}	
+	}
+
+
+	protected void SaveSetting(String Key, String Value) {
+		try {
+			appSettings.put("JDasher/S_" + Key, Value);
+		}
+		catch (AccessControlException e) {
+			return; // Fail silently; we will use the default next time
+		}
+	}
+		
+}
+
+/**
+ * Exception indicating that JSettings was unable to initialise
+ * due to the Preferences object's backing store being unavailable,
+ * probably due to security limitations.
+ */
+class StoreUnavailableException extends Exception {
+	// No properties
+}

Added: trunk/java/dasher/applet/ScreenOverlay.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/ScreenOverlay.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,106 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher.applet;
+
+import javax.swing.JFrame;
+import javax.swing.JProgressBar;
+import javax.swing.JLabel;
+import javax.swing.BoxLayout;
+
+/**
+ * Small JFrame containing a label and progress bar which is shown
+ * by Dasher when training or otherwise Locked.
+ * <p>
+ * At present this doesn't fully work because the Frame's screen
+ * is not redrawn whilst another event is in progress -- and most
+ * time consuming work in Dasher takes place in response to menu
+ * events.
+ * <p>
+ * This could potentially be fixed by using marking events triggered
+ * by menu clicks as to be done by the redraw thread.
+ */
+public class ScreenOverlay extends JFrame {
+
+	/**
+	 * Our progress bar
+	 */
+	private JProgressBar m_ProgressBar;
+	
+	/**
+	 * Our label
+	 */
+	private JLabel m_Label;
+	
+	/**
+	 * Creates the frame with a size of 200x100 and currently invisible.
+	 *
+	 */
+	public ScreenOverlay() {
+		
+		this.setLayout(new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS));
+		
+		m_Label = new JLabel("JDasher");
+		m_ProgressBar = new JProgressBar();
+		
+		m_ProgressBar.setVisible(false);
+		
+		this.setSize(200, 100);
+		
+		this.add(m_Label);
+		this.add(m_ProgressBar);
+		
+	}
+	
+	/**
+	 * Sets the Frame's label
+	 * 
+	 * @param newMessage Message to show the user
+	 */
+	public void setText(String newMessage) {
+		m_Label.setText(newMessage);
+	}
+	
+	/**
+	 * Sets the current progress
+	 * 
+	 * @param done Amount done
+	 * @param max Maximum amount
+	 */	
+	public void setProgress(int done, int max) {
+		m_ProgressBar.setMaximum(max);
+		m_ProgressBar.setValue(done);
+	}
+	
+	/**
+	 * Shows or hides the progress bar
+	 * 
+	 * @param visible Should the bar be visible?
+	 */
+	public void setProgressBarVisible(boolean visible) {
+		m_ProgressBar.setVisible(visible);
+	}
+	
+}

Added: trunk/java/dasher/applet/font/FontListener.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/font/FontListener.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,32 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher.applet.font;
+
+public interface FontListener {
+	
+	public void setNewFont(java.awt.Font f);
+	
+}

Added: trunk/java/dasher/applet/font/JFontDialog.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/font/JFontDialog.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,176 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher.applet.font;
+
+import javax.swing.BoxLayout;
+
+import java.awt.Font;
+import java.awt.Dimension;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+import javax.swing.JDialog;
+import javax.swing.JList;
+import javax.swing.JScrollPane;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+
+public class JFontDialog extends JDialog implements ActionListener {
+
+	private JList m_FontList;
+	private JList m_SizeList;
+	private JList m_StyleList;
+	private FontListener m_Owner;
+	private Font originalFont;
+	
+	public JFontDialog(FontListener callback) {
+		super();
+		
+		m_Owner = callback;
+		originalFont = null;
+		
+		createDialog();
+		
+	}
+	
+	public JFontDialog(FontListener callback, Font currentFont) {
+		super();
+		
+		m_Owner = callback;
+		originalFont = currentFont;
+		
+		createDialog();
+		
+	}
+	
+	public void createDialog() {
+		
+		this.setSize(330, 375);
+		this.setResizable(false);
+							
+		this.setLayout(new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS));
+		
+		JPanel listPanel = new JPanel();
+		listPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));
+		this.add(listPanel);
+		
+		JPanel buttonPanel = new JPanel();
+		buttonPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));
+		this.add(buttonPanel);
+		
+		m_FontList = new JList(java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
+		JScrollPane FontPane = new JScrollPane(m_FontList);
+		Dimension FontPaneSize = new Dimension(150, 300);
+		FontPane.setSize(FontPaneSize); FontPane.setPreferredSize(FontPaneSize);
+		listPanel.add(FontPane);
+		
+		if(originalFont != null) m_FontList.setSelectedValue(originalFont.getFamily(), true);
+		
+		Integer[] sizes = {8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72};
+		m_SizeList = new JList(sizes);
+		JScrollPane SizePane = new JScrollPane(m_SizeList);
+		Dimension SizePaneSize = new Dimension(50, 300);
+		SizePane.setSize(SizePaneSize); SizePane.setPreferredSize(SizePaneSize);
+		listPanel.add(SizePane);
+		
+		if(originalFont != null) m_SizeList.setSelectedValue(originalFont.getSize(), true);
+		
+		String[] styles = {"Normal","Bold","Italic","Bold Italic"};
+		m_StyleList = new JList(styles);
+		JScrollPane StylePane = new JScrollPane(m_StyleList);
+		Dimension StylePaneSize = new Dimension(100, 300);
+		StylePane.setSize(StylePaneSize); StylePane.setPreferredSize(StylePaneSize);
+		listPanel.add(StylePane);
+				
+		if(originalFont != null ) { 
+			int currentStyle = originalFont.getStyle();
+			if(currentStyle == Font.PLAIN) {
+				m_StyleList.setSelectedValue("Normal", true);
+			}
+			else if(currentStyle == Font.BOLD) {
+				m_StyleList.setSelectedValue("Bold", true);
+			}
+			else if(currentStyle == Font.ITALIC) {
+				m_StyleList.setSelectedValue("Italic", true);
+			}
+			else {
+				m_StyleList.setSelectedValue("Bold Italic", true);
+			}
+		}
+		
+		
+		Dimension ButtonSize = new Dimension(70, 25);
+		
+		JButton OKButton = new JButton("OK");
+		OKButton.setSize(ButtonSize); OKButton.setPreferredSize(ButtonSize);
+
+		OKButton.addActionListener(this);
+		
+		buttonPanel.add(OKButton);
+		
+		JButton CancelButton = new JButton("Cancel");
+		CancelButton.setSize(ButtonSize); CancelButton.setPreferredSize(ButtonSize);
+		
+		CancelButton.addActionListener(this);
+		
+		buttonPanel.add(CancelButton);
+		
+		this.setVisible(true);
+		
+	}
+	
+	public void actionPerformed(ActionEvent e) {
+		if(e.getActionCommand() == "OK") {
+			if(m_FontList.getSelectedValue() == null) {
+				this.setVisible(false);
+				return;
+			}
+			if(m_SizeList.getSelectedValue() == null) {
+				m_SizeList.setSelectedValue(Integer.toString(originalFont.getSize()), false);
+				if(m_SizeList.getSelectedValue() == null) {
+					m_SizeList.setSelectedValue(10, false);
+				}
+			}
+			if(m_StyleList.getSelectedValue() == null) {
+				m_StyleList.setSelectedValue("Normal", false);
+			}
+			
+			m_Owner.setNewFont(new Font(m_FontList.getSelectedValue().toString(), translateStyle(m_StyleList.getSelectedValue().toString()), (Integer)m_SizeList.getSelectedValue()));
+			this.setVisible(false);
+		}
+		else if(e.getActionCommand() == "Cancel") {
+			this.setVisible(false);
+		}
+	}
+	
+	public int translateStyle(String in) {
+		if(in == "Normal") return Font.PLAIN;
+		if(in == "Bold") return Font.BOLD;
+		if(in == "Italic") return Font.ITALIC;
+		return Font.BOLD | Font.ITALIC;
+	}
+	
+}

Added: trunk/java/dasher/applet/system.rc/alphabet.Thai.xml
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/system.rc/alphabet.Thai.xml	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,161 @@
+<?xml version="1.0"?>
+<!DOCTYPE alphabets SYSTEM "alphabet.dtd">
+<?xml-stylesheet type="text/xsl" href="alphabet.xsl"?>
+<alphabets>
+<alphabet name="Thai / &#3616;&#3634;&#3625;&#3634;&#3652;&#3607;&#3618; with punctuation and numerals">
+<!-- the Thai alphabet does not distinguish minuscule and majuscule letters. It is usually written with no space between words; most Thai words have only one syllable. The end of sentences is marked by a space  -->
+<orientation type="LR"/>
+<encoding type="Western"/>
+<palette>Thai</palette>
+<train>training_Thai_TH.txt</train>
+<space d="&#x25a1;" t=" " b="9" />
+<paragraph d="&#182;" b="9"/>
+<control d="Control" t="" b="8"/>
+<group name="Vowels"  b="111"  visible="on">
+<s d="&#x25cc;&#x0E4D;" t="&#x0E4D;" b="82" note="NIKHAHIT    UNUSED?" />
+<s d="&#x25cc;&#x0E30;" t="&#x0E30;" b="72" note="SARA A" />
+<s d="&#x25cc;&#x0E31;" t="&#x0E31;" b="82" note="tone MAI HAN-AKAT" />
+<s d="&#x25cc;&#x0E32;" t="&#x0E32;" b="72" note=" SARA AA"/>
+<s d="&#x25cc;&#x0E45;" t="&#x0E45;" b="82" note=" LAKKHANGYAO  UNUSED?" />
+<s d="&#x25cc;&#x0E33;" t="&#x0E33;" b="72" note="SARA AM"/>
+<s d="&#x25cc;&#x0E34;" t="&#x0E34;" b="82" />
+<s d="&#x25cc;&#x0E35;" t="&#x0E35;" b="72" />
+<s d="&#x25cc;&#x0E36;" t="&#x0E36;" b="82" />
+<s d="&#x25cc;&#x0E37;" t="&#x0E37;" b="72" />
+<s d="&#x25cc;&#x0E38;" t="&#x0E38;" b="82" />
+<s d="&#x25cc;&#x0E39;" t="&#x0E39;" b="72" />
+<s d="&#x0E40;&#x25cc;" t="&#x0E40;" b="82" note="0E40	 SARA E"/>	    
+<s d="&#x0E41;&#x25cc;" t="&#x0E41;" b="72" note="0E41	 SARA AE"/>	    
+<s d="&#x0E42;&#x25cc;" t="&#x0E42;" b="82" note="0E42	 SARA O"/>	    
+<s d="&#x0E43;&#x25cc;" t="&#x0E43;" b="72" note="0E43	 SARA AI MAIMUAN"/> 
+<s d="&#x0E44;&#x25cc;" t="&#x0E44;" b="82" note="0E44	 SARA AI MAIMALAI"/>
+<s d="&#x25cc;&#x0E3A;" t="&#x0E3A;" b="72" note="0E3A PHINTHU -     UNUSED?"/>
+<s d="&#x25cc;&#x0E4C;" t="&#x0E4C;" b="82" note="0E4C	 THANTHAKHAT - CHECK"/>
+<s d="&#x25cc;&#x0E4E;" t="&#x0E4E;" b="82" note="0E4E	 YAMAKKAN -     UNUSED?"/>
+</group>
+<group name="Tones"  b="193"  visible="on">
+<s d="&#x25cc;&#x0E47;" t="&#x0E47;" b="83" note="0E47 tone MAITAIKHU"/>
+<s d="&#x25cc;&#x0E48;" t="&#x0E48;" b="73" note="0E48 tone MAI EK"/>
+<s d="&#x25cc;&#x0E49;" t="&#x0E49;" b="83" note="0E49 tone MAI THO"/>
+<s d="&#x25cc;&#x0E4A;" t="&#x0E4A;" b="73" note="0E4A tone MAI TRI"/>
+<s d="&#x25cc;&#x0E4B;" t="&#x0E4B;" b="83" note="0E4B tone MAI CHATTAWA"/>
+</group>
+<group name="Thai letters" b="0" visible="off">
+<s d="&#x0E01;" t="&#x0E01;" b="10" note="middle-tone 0E01 KO KAI"/>
+<s d="&#x0E02;" t="&#x0E02;" b="11" note="high-tone 0E02 KHO KHAI"/>
+<s d="&#x0E03;" t="&#x0E03;" b="12" note="high-tone 0E03 KHO KHUAT  UNUSED?"/>
+<s d="&#x0E04;" t="&#x0E04;" b="13" note="low-tone 0E04 KHO KHWAI "/>
+<s d="&#x0E05;" t="&#x0E05;" b="14" note="low-tone 0E05 KHO KHON    UNUSED?"/>
+<s d="&#x0E06;" t="&#x0E06;" b="15" note="low-tone 0E06 KHO RAKHANG"/>
+<s d="&#x0E07;" t="&#x0E07;" b="16" note="low-tone 0E07 NGO NGU"/>
+<s d="&#x0E08;" t="&#x0E08;" b="17" note="middle-tone 0E08 CHO CHAN"/>
+<s d="&#x0E09;" t="&#x0E09;" b="18" note="high-tone 0E09 CHO CHING"/>
+<s d="&#x0E0A;" t="&#x0E0A;" b="19" note="low-tone 0E0A CHO CHANG"/>
+<s d="&#x0E0B;" t="&#x0E0B;" b="20" note="low-tone 0E0B SO SO"/>
+<s d="&#x0E0C;" t="&#x0E0C;" b="21" note="low-tone 0E0C CHO CHOE"/>
+<s d="&#x0E0D;" t="&#x0E0D;" b="22" note="low-tone 0E0D YO YING"/>
+<s d="&#x0E0E;" t="&#x0E0E;" b="23" note="middle-tone 0E0E DO CHADA"/>
+<s d="&#x0E0F;" t="&#x0E0F;" b="24" note="middle-tone 0E0F TO PATAK"/>
+<s d="&#x0E10;" t="&#x0E10;" b="25" note="high-tone 0E10 THO THAN"/>
+<s d="&#x0E11;" t="&#x0E11;" b="26" note="low-tone 0E11 THO NANGMONTHO"/>
+<s d="&#x0E12;" t="&#x0E12;" b="27" note="low-tone 0E12 THO PHUTHAO"/>
+<s d="&#x0E13;" t="&#x0E13;" b="28" note="low-tone 0E13 NO NEN"/>
+<s d="&#x0E14;" t="&#x0E14;" b="29" note="middle-tone 0E14 DO DEK"/>
+<s d="&#x0E15;" t="&#x0E15;" b="30" note="middle-tone 0E15 TO TAO"/>
+<s d="&#x0E16;" t="&#x0E16;" b="31" note="high-tone 0E16 THO THUNG"/>
+<s d="&#x0E17;" t="&#x0E17;" b="32" note="low-tone 0E17 THO THAHAN"/>
+<s d="&#x0E18;" t="&#x0E18;" b="33" note="low-tone 0E18 THO THONG"/>
+<s d="&#x0E19;" t="&#x0E19;" b="34" note="low-tone 0E19 NO NU"/>
+<s d="&#x0E1A;" t="&#x0E1A;" b="35" note="middle-tone 0E1A BO BAIMAI"/>
+<s d="&#x0E1B;" t="&#x0E1B;" b="36" note="middle-tone 0E1B PO PLA"/>
+<s d="&#x0E1C;" t="&#x0E1C;" b="37" note="high-tone 0E1C PHO PHUNG"/>
+<s d="&#x0E1D;" t="&#x0E1D;" b="38" note="high-tone 0E1D FO FA"/>
+<s d="&#x0E1E;" t="&#x0E1E;" b="39" note="low-tone 0E1E PHO PHAN"/>
+<s d="&#x0E1F;" t="&#x0E1F;" b="40" note="low-tone 0E1F FO FAN"/>
+<s d="&#x0E20;" t="&#x0E20;" b="41" note="low-tone 0E20 PHO SAMPHAO"/>
+<s d="&#x0E21;" t="&#x0E21;" b="42" note="low-tone 0E21 MO MA"/>
+<s d="&#x0E22;" t="&#x0E22;" b="43" note="low-tone 0E22 YO YAK"/>
+<s d="&#x0E23;" t="&#x0E23;" b="44" note="low-tone 0E23 RO RUA"/>
+<s d="&#x0E24;" t="&#x0E24;" b="45" note="0E24 RU      WHAT TONE GROUP?"/>
+<s d="&#x0E25;" t="&#x0E25;" b="46" note="low-tone 0E25 LO LING"/>
+<s d="&#x0E26;" t="&#x0E26;" b="47" note="0E26 LU    UNUSED?"/>
+<s d="&#x0E27;" t="&#x0E27;" b="48" note="low-tone 0E27 WO WAEN"/>
+<s d="&#x0E28;" t="&#x0E28;" b="49" note="high-tone 0E28 SO SALA"/>
+<s d="&#x0E29;" t="&#x0E29;" b="50" note="high-tone 0E29 SO RUSI"/>
+<s d="&#x0E2A;" t="&#x0E2A;" b="51" note="high-tone 0E2A SO SUA"/>
+<s d="&#x0E2B;" t="&#x0E2B;" b="52" note="high-tone 0E2B HO HIP"/>
+<s d="&#x0E2C;" t="&#x0E2C;" b="53" note="low-tone 0E2C LO CHULA"/>
+<s d="&#x0E2D;" t="&#x0E2D;" b="54" note="middle-tone 0E2D O ANG (null consonant)"/>
+<s d="&#x0E2E;" t="&#x0E2E;" b="55" note="low-tone 0E2E HO NOKHUK"/>                 
+</group>		    
+<group name="Numbers" b="113">
+<s d="1" t="1" b="90"/>
+<s d="2" t="2" b="91"/>
+<s d="3" t="3" b="92"/>
+<s d="4" t="4" b="93"/>
+<s d="5" t="5" b="94"/>
+<s d="6" t="6" b="90"/>
+<s d="7" t="7" b="91"/>
+<s d="8" t="8" b="92"/>
+<s d="9" t="9" b="93"/>
+<s d="0" t="0" b="94"/>
+</group>
+<group name="Thai digits" b="113">
+<s d="&#x0E51;" t="&#x0E51;" b="90" note="0E51	THAI DIGIT ONE"/>
+<s d="&#x0E52;" t="&#x0E52;" b="91" note="0E52	THAI DIGIT TWO"/>
+<s d="&#x0E53;" t="&#x0E53;" b="92" note="0E53	THAI DIGIT THREE"/>
+<s d="&#x0E54;" t="&#x0E54;" b="93" note="0E54	THAI DIGIT FOUR"/>
+<s d="&#x0E55;" t="&#x0E55;" b="94" note="0E55	THAI DIGIT FIVE"/>
+<s d="&#x0E56;" t="&#x0E56;" b="90" note="0E56	THAI DIGIT SIX"/>
+<s d="&#x0E57;" t="&#x0E57;" b="91" note="0E57	THAI DIGIT SEVEN"/>
+<s d="&#x0E58;" t="&#x0E58;" b="92" note="0E58	THAI DIGIT EIGHT"/>
+<s d="&#x0E59;" t="&#x0E59;" b="93" note="0E59	THAI DIGIT NINE"/>
+<s d="&#x0E50;" t="&#x0E50;" b="94" note="0E50	THAI DIGIT ZERO"/>
+</group>
+<group name="Punctuation" b="112">
+<s d="&#x0E4F;" t="&#x0E4F;" b="90" note="0E4F	 FONGMAN -    UNUSED?"/>
+<s d="&#x0E5A;" t="&#x0E5A;" b="91" note="0E5A	THAI CHARACTER ANGKHANKHU -    UNUSED?"/>
+<s d="&#x0E5B;" t="&#x0E5B;" b="92" note="0E5B	THAI CHARACTER KHOMUT  -    UNUSED?"/>
+<s d="&#x0E2F;" t="&#x0E2F;" b="93" note="0E2F PAIYANNOI - means preceding word is abbreviated  CHECK"/>
+<s d="&#x0E46;" t="&#x0E46;" b="94" note="THAI CHARACTER MAIYAMOK - means preceding word or phrase is repeated - CHECK" />
+<s b="90" d="%" t="%"/>	   
+<s b="91" d="*" t="*"/>	   
+<s b="92" d="+" t="+"/>	   
+<s b="93" d="=" t="="/>	   
+<s b="94" d="/" t="/"/>	   
+<s b="95" d="#" t="#"/>
+<s d="&#x0E3F;" t="&#x0E3F;"  b="90"  note="0E3F	THAI CURRENCY SYMBOL BAHT"/>
+<s b="98" d="$" t="$"/>
+<s b="99" d="|" t="|"/>
+<s b="95" d="\" t="\"/>
+<s b="96" d="~" t="~"/>
+<s b="97" d="^" t="^"/>
+<s b="98" d="_" t="_"/>
+<s b="99" d="&amp;" t="&amp;"/> 
+<s b="95" d="@" t="@"/>
+<s b="105" d="[" t="["/>
+<s b="106" d="]" t="]"/>
+<s b="107" d="{" t="{"/>
+<s b="108" d="}" t="}"/>
+<s b="109" d="&lt;" t="&lt;"/>
+<s b="105" d="&gt;" t="&gt;"/>
+<s b="106" d="(" t="("/>
+<s b="107" d=")" t=")"/>
+<s b="108" d="&#x201C;" t="&#x201C;" note="left double quotation mark" />
+<s b="109" d="&#x0022;" t="&#x0022;" note="deprecated vertical double quotation mark" />
+<s b="106" d="&#x201D;" t="&#x201D;" note="right double quotation mark" />
+<s b="107" d="&#x2018;" t="&#x2018;" note="left single quotation mark" />
+<s b="108" d="&#x2019;" t="&#x2019;" note="right single quotation mark and apostrophe" />
+<s b="109" d="`" t="`" note="left quote from keyboard" />
+<s b="105" d="&#x25cc;&#x0313;" t="&apos;" note=" apostrophe"/>
+<s b="9"  d="&#x25CA;" t="&#x9;" note="TAB (represented by a diamond)"/>
+<s b="100" d="-" t="-"/>
+<s b="101" d=":" t=":"/>
+<s b="102" d=";" t=";"/>
+<s b="103" d="?" t="?"/>
+<s b="104" d="!" t="!"/>
+<s b="100" d="," t=","/>
+<s d="&#183;" t="." b="104"/>
+</group>
+</alphabet>
+</alphabets>

Added: trunk/java/dasher/applet/system.rc/alphabet.dtd
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/system.rc/alphabet.dtd	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,63 @@
+<!-- alphabets contains groups of valid symbols for use in Dasher,
+along with some useful information. It does nothing to tell Dasher,
+how those symbols may be used. -->
+
+<!ELEMENT alphabets (alphabet*)>
+
+<!ELEMENT alphabet (orientation, encoding, train, paragraph, space, control, group*)>
+<!ATTLIST alphabet name CDATA #REQUIRED>
+
+<!-- Left-Right, Right-Left, Top-Bottom or Bottom-Top?
+Which way up should Dasher do its rendering by default? -->
+<!ELEMENT orientation EMPTY>
+<!ATTLIST orientation type (LR|RL|TB|BT) #REQUIRED>
+
+<!-- The encoding field just helps Dasher decide on some Localisation
+issues. In theory it could see which characters are there and pick
+a suitable file encoding and font. Sometimes this is difficult.
+It does not dictate the file format. For example, traditionally Unix
+and Windows use different encodings for some languages. A platform
+should do what what it thinks best given the vague group Dasher
+has put the alphabet into. If this doesn't work out, the user
+can over-ride the alphabet anyway. -->
+<!ELEMENT encoding EMPTY>
+<!ATTLIST encoding type CDATA #REQUIRED>
+
+<!-- Default training file for this alphabet -->
+<!ELEMENT train (#PCDATA)>
+
+<!-- Traditionally the paragraph character is rendered differently to all
+others. Can set d (display) to "" to disable. -->
+<!ELEMENT paragraph EMPTY>
+<!ATTLIST paragraph d CDATA #REQUIRED>
+<!ATTLIST paragraph f CDATA #IMPLIED>
+<!ATTLIST paragraph b CDATA #IMPLIED>
+
+<!-- Traditionally the space character is rendered differently to all
+others. Can set both d (display) and t (text) to "" to disable. -->
+<!ELEMENT space EMPTY>
+<!ATTLIST space d CDATA #REQUIRED>
+<!ATTLIST space t CDATA #REQUIRED>
+<!ATTLIST space f CDATA #IMPLIED>
+<!ATTLIST space b CDATA #IMPLIED>
+
+<!-- The control character is special, and not part of the main alphabet. -->
+
+<!ELEMENT control EMPTY>
+<!ATTLIST control d CDATA #REQUIRED>
+<!ATTLIST control t CDATA #REQUIRED>
+<!ATTLIST control f CDATA #IMPLIED>
+<!ATTLIST control b CDATA #IMPLIED>
+
+<!-- Logical groups of symbols, eg name="Lower case letters" -->
+<!ELEMENT group (s*)>
+<!ATTLIST group name CDATA #REQUIRED>
+<!ATTLIST group b CDATA #IMPLIED>
+
+<!-- Symbols Dasher can use. It shows text d in the nodes and sends
+text t to the edit box -->
+<!ELEMENT s EMPTY>
+<!ATTLIST s d CDATA #REQUIRED>
+<!ATTLIST s t CDATA #REQUIRED>
+<!ATTLIST s f CDATA #IMPLIED>
+<!ATTLIST s b CDATA #IMPLIED>

Added: trunk/java/dasher/applet/system.rc/alphabet.english.xml
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/system.rc/alphabet.english.xml	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,330 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE alphabets SYSTEM "alphabet.dtd">
+<?xml-stylesheet type="text/xsl" href="alphabet.xsl"?>
+<alphabets>
+<alphabet name="English with limited punctuation">
+<orientation type="LR"/>
+<encoding type="Western"/>
+<palette>European/Asian</palette>
+<train>training_english_GB.txt</train>
+<paragraph d="&#182;" b="9"/>
+<space d="&#x25a1;" t=" " b="9" note="box" />
+<control d="Control" t="" b="8"/>
+<group name="Lower case Latin letters" b="0">
+<s d="a" t="a" b="10"/>
+<s d="b" t="b" b="11"/>
+<s d="c" t="c" b="12"/>
+<s d="d" t="d" b="13"/>
+<s d="e" t="e" b="14"/>
+<s d="f" t="f" b="15"/>
+<s d="g" t="g" b="16"/>
+<s d="h" t="h" b="17"/>
+<s d="i" t="i" b="18"/>
+<s d="j" t="j" b="19"/>
+<s d="k" t="k" b="20"/>
+<s d="l" t="l" b="21"/>
+<s d="m" t="m" b="22"/>
+<s d="n" t="n" b="23"/>
+<s d="o" t="o" b="24"/>
+<s d="p" t="p" b="25"/>
+<s d="q" t="q" b="26"/>
+<s d="r" t="r" b="27"/>
+<s d="s" t="s" b="28"/>
+<s d="t" t="t" b="29"/>
+<s d="u" t="u" b="30"/>
+<s d="v" t="v" b="31"/>
+<s d="w" t="w" b="32"/>
+<s d="x" t="x" b="33"/>
+<s d="y" t="y" b="34"/>
+<s d="z" t="z" b="35"/>
+</group>
+<group name="Upper case Latin letters" b="111">
+<s d="A" t="A" b="10"/>
+<s d="B" t="B" b="11"/>
+<s d="C" t="C" b="12"/>
+<s d="D" t="D" b="13"/>
+<s d="E" t="E" b="14"/>
+<s d="F" t="F" b="15"/>
+<s d="G" t="G" b="16"/>
+<s d="H" t="H" b="17"/>
+<s d="I" t="I" b="18"/>
+<s d="J" t="J" b="19"/>
+<s d="K" t="K" b="20"/>
+<s d="L" t="L" b="21"/>
+<s d="M" t="M" b="22"/>
+<s d="N" t="N" b="23"/>
+<s d="O" t="O" b="24"/>
+<s d="P" t="P" b="25"/>
+<s d="Q" t="Q" b="26"/>
+<s d="R" t="R" b="27"/>
+<s d="S" t="S" b="28"/>
+<s d="T" t="T" b="29"/>
+<s d="U" t="U" b="30"/>
+<s d="V" t="V" b="31"/>
+<s d="W" t="W" b="32"/>
+<s d="X" t="X" b="33"/>
+<s d="Y" t="Y" b="34"/>
+<s d="Z" t="Z" b="35"/>
+</group>
+<group name="Punctuation" b="112">
+<s d="&amp;" t="&amp;" b="99"/>
+<s d="&quot;" t="&quot;" b="109"/>
+<s b="105" d="&#x25cc;&#x0313;" t="&apos;" note=" apostrophe"/>
+<!-- <s b="105" d="&#x25cc;&#x0313;" t="&apos;" note=" apostrophe"/> -->
+<!-- <s b="105" d="&#x2323;&#x0313;" t="&apos;" note=" apostrophe above a smile arc"/> -->
+<!-- <s b="105" d="&#x2319;&#x0313;" t="&apos;" note=" apostrophe"/> -->
+<s d="?" t="?" b="103"/>
+<s d="!" t="!" b="104"/>
+<!-- <s d="&#x2312;&#x0326;" t="," b="100" note="overarced comma"/> -->
+<s d="," t="," b="100" note="&#x236A; overlined comma"/>
+<s d="&#183;" t="." b="104"/>
+</group>
+</alphabet>
+<alphabet name="English with numerals and limited punctuation">
+<orientation type="LR"/>
+<encoding type="Western"/>
+<palette>European/Asian</palette>
+<train>training_english_GB.txt</train>
+<paragraph d="&#182;" b="9"/>
+<space d="&#x25a1;" t=" " b="9" note="box" />
+<control d="Control" t="" b="8"/>
+<group name="Lower case Latin letters" b="0">
+<s d="a" t="a" b="10"/>
+<s d="b" t="b" b="11"/>
+<s d="c" t="c" b="12"/>
+<s d="d" t="d" b="13"/>
+<s d="e" t="e" b="14"/>
+<s d="f" t="f" b="15"/>
+<s d="g" t="g" b="16"/>
+<s d="h" t="h" b="17"/>
+<s d="i" t="i" b="18"/>
+<s d="j" t="j" b="19"/>
+<s d="k" t="k" b="20"/>
+<s d="l" t="l" b="21"/>
+<s d="m" t="m" b="22"/>
+<s d="n" t="n" b="23"/>
+<s d="o" t="o" b="24"/>
+<s d="p" t="p" b="25"/>
+<s d="q" t="q" b="26"/>
+<s d="r" t="r" b="27"/>
+<s d="s" t="s" b="28"/>
+<s d="t" t="t" b="29"/>
+<s d="u" t="u" b="30"/>
+<s d="v" t="v" b="31"/>
+<s d="w" t="w" b="32"/>
+<s d="x" t="x" b="33"/>
+<s d="y" t="y" b="34"/>
+<s d="z" t="z" b="35"/>
+</group>
+<group name="Upper case Latin letters" b="111">
+<s d="A" t="A" b="10"/>
+<s d="B" t="B" b="11"/>
+<s d="C" t="C" b="12"/>
+<s d="D" t="D" b="13"/>
+<s d="E" t="E" b="14"/>
+<s d="F" t="F" b="15"/>
+<s d="G" t="G" b="16"/>
+<s d="H" t="H" b="17"/>
+<s d="I" t="I" b="18"/>
+<s d="J" t="J" b="19"/>
+<s d="K" t="K" b="20"/>
+<s d="L" t="L" b="21"/>
+<s d="M" t="M" b="22"/>
+<s d="N" t="N" b="23"/>
+<s d="O" t="O" b="24"/>
+<s d="P" t="P" b="25"/>
+<s d="Q" t="Q" b="26"/>
+<s d="R" t="R" b="27"/>
+<s d="S" t="S" b="28"/>
+<s d="T" t="T" b="29"/>
+<s d="U" t="U" b="30"/>
+<s d="V" t="V" b="31"/>
+<s d="W" t="W" b="32"/>
+<s d="X" t="X" b="33"/>
+<s d="Y" t="Y" b="34"/>
+<s d="Z" t="Z" b="35"/>
+</group>
+<group name="Numbers" b="113">
+<s d="1" t="1" b="90"/>
+<s d="2" t="2" b="91"/>
+<s d="3" t="3" b="92"/>
+<s d="4" t="4" b="93"/>
+<s d="5" t="5" b="94"/>
+<s d="6" t="6" b="90"/>
+<s d="7" t="7" b="91"/>
+<s d="8" t="8" b="92"/>
+<s d="9" t="9" b="93"/>
+<s d="0" t="0" b="94"/>
+</group>
+<group name="Punctuation" b="112">
+<s d="&amp;" t="&amp;" b="99"/>
+<s d="&quot;" t="&quot;" b="109"/>
+<s b="105" d="&#x25cc;&#x0313;" t="&apos;" note=" apostrophe"/>
+<s d="?" t="?" b="103"/>
+<s d="!" t="!" b="104"/>
+<s d="," t="," b="100"/>
+<s d="&#183;" t="." b="104"/>
+</group>
+</alphabet>
+<alphabet name="English with numerals and lots of punctuation">
+<orientation type="LR"/>
+<encoding type="Western"/>
+<palette>European/Asian</palette>
+<train>training_english_GB.txt</train>
+<space d="&#x25a1;" t=" "  b="9"/>
+<control d="Control" t=""/>
+<paragraph d="&#182;" b="9"/>
+<group name="Lower case Latin letters" b="0">
+<s d="a" t="a" b="10"/>
+<s d="b" t="b" b="11"/>
+<s d="c" t="c" b="12"/>
+<s d="d" t="d" b="13"/>
+<s d="e" t="e" b="14"/>
+<s d="f" t="f" b="15"/>
+<s d="g" t="g" b="16"/>
+<s d="h" t="h" b="17"/>
+<s d="i" t="i" b="18"/>
+<s d="j" t="j" b="19"/>
+<s d="k" t="k" b="20"/>
+<s d="l" t="l" b="21"/>
+<s d="m" t="m" b="22"/>
+<s d="n" t="n" b="23"/>
+<s d="o" t="o" b="24"/>
+<s d="p" t="p" b="25"/>
+<s d="q" t="q" b="26"/>
+<s d="r" t="r" b="27"/>
+<s d="s" t="s" b="28"/>
+<s d="t" t="t" b="29"/>
+<s d="u" t="u" b="30"/>
+<s d="v" t="v" b="31"/>
+<s d="w" t="w" b="32"/>
+<s d="x" t="x" b="33"/>
+<s d="y" t="y" b="34"/>
+<s d="z" t="z" b="35"/>
+</group>
+<group name="Upper case Latin letters" b="111">
+<s d="A" t="A" b="10"/>
+<s d="B" t="B" b="11"/>
+<s d="C" t="C" b="12"/>
+<s d="D" t="D" b="13"/>
+<s d="E" t="E" b="14"/>
+<s d="F" t="F" b="15"/>
+<s d="G" t="G" b="16"/>
+<s d="H" t="H" b="17"/>
+<s d="I" t="I" b="18"/>
+<s d="J" t="J" b="19"/>
+<s d="K" t="K" b="20"/>
+<s d="L" t="L" b="21"/>
+<s d="M" t="M" b="22"/>
+<s d="N" t="N" b="23"/>
+<s d="O" t="O" b="24"/>
+<s d="P" t="P" b="25"/>
+<s d="Q" t="Q" b="26"/>
+<s d="R" t="R" b="27"/>
+<s d="S" t="S" b="28"/>
+<s d="T" t="T" b="29"/>
+<s d="U" t="U" b="30"/>
+<s d="V" t="V" b="31"/>
+<s d="W" t="W" b="32"/>
+<s d="X" t="X" b="33"/>
+<s d="Y" t="Y" b="34"/>
+<s d="Z" t="Z" b="35"/>
+</group>
+<group name="Numbers" b="113">
+<s d="1" t="1" b="90"/>
+<s d="2" t="2" b="91"/>
+<s d="3" t="3" b="92"/>
+<s d="4" t="4" b="93"/>
+<s d="5" t="5" b="94"/>
+<s d="6" t="6" b="90"/>
+<s d="7" t="7" b="91"/>
+<s d="8" t="8" b="92"/>
+<s d="9" t="9" b="93"/>
+<s d="0" t="0" b="94"/>
+</group>
+<group name="Punctuation" b="112">
+<s b="90" d="%" t="%"/>
+<s b="91" d="*" t="*"/>
+<s b="92" d="+" t="+"/>
+<s b="93" d="=" t="="/>
+<s b="94" d="/" t="/"/>
+<s b="95" d="#" t="#"/>
+<s d="&#8364;" t="&#8364;" b="96" note="euro" />
+<s b="97"  d="&#163;" t="&#163;" note="Pound" />
+<s b="98" d="$" t="$"/>
+<s b="99" d="|" t="|"/>
+<s b="95" d="\" t="\"/>
+<s b="96" d="~" t="~"/>
+<s b="97" d="^" t="^"/>
+<s b="98" d="_" t="_"/>
+<s b="99" d="&amp;" t="&amp;"/> 
+<s b="95" d="@" t="@"/>
+<s b="105" d="[" t="["/>
+<s b="106" d="]" t="]"/>
+<s b="107" d="{" t="{"/>
+<s b="108" d="}" t="}"/>
+<s b="109" d="&lt;" t="&lt;"/>
+<s b="105" d="&gt;" t="&gt;"/>
+<s b="106" d="(" t="("/>
+<s b="107" d=")" t=")"/>
+<s b="108" d="&#x201C;" t="&#x201C;" note="left double quotation mark" />
+<s b="109" d="&#x0022;" t="&#x0022;" note="deprecated vertical double quotation mark" />
+<s b="106" d="&#x201D;" t="&#x201D;" note="right double quotation mark" />
+<s b="107" d="&#x2018;" t="&#x2018;" note="left single quotation mark" />
+<s b="108" d="&#x2019;" t="&#x2019;" note="right single quotation mark and apostrophe" />
+<s b="109" d="`" t="`" note="left quote from keyboard" />
+<s b="105" d="&#x25cc;&#x0313;" t="&apos;" note=" apostrophe"/>
+<s b="9"  d="&#x25CA;" t="&#x9;" note="TAB (represented by a diamond)"/>
+<s b="100" d="-" t="-"/>
+<s b="101" d=":" t=":"/>
+<s b="102" d=";" t=";"/>
+<s b="103" d="?" t="?"/>
+<s b="104" d="!" t="!"/>
+<s b="100" d="," t=","/>
+<s d="&#183;" t="." b="104"/>
+</group>
+</alphabet>
+<alphabet name="English, lower case">
+<orientation type="LR"/>
+<encoding type="Western"/>
+<palette>European/Asian</palette>
+<train>training_englishLC_GB.txt</train>
+<space d="&#x25a1;" t=" " b="9" note="box" />
+<control d="Control" t="" b="8"/>
+<group name="Lower case Latin letters" b="0">
+<s d="a" t="a" b="10"/>
+<s d="b" t="b" b="11"/>
+<s d="c" t="c" b="12"/>
+<s d="d" t="d" b="13"/>
+<s d="e" t="e" b="14"/>
+<s d="f" t="f" b="15"/>
+<s d="g" t="g" b="16"/>
+<s d="h" t="h" b="17"/>
+<s d="i" t="i" b="18"/>
+<s d="j" t="j" b="19"/>
+<s d="k" t="k" b="20"/>
+<s d="l" t="l" b="21"/>
+<s d="m" t="m" b="22"/>
+<s d="n" t="n" b="23"/>
+<s d="o" t="o" b="24"/>
+<s d="p" t="p" b="25"/>
+<s d="q" t="q" b="26"/>
+<s d="r" t="r" b="27"/>
+<s d="s" t="s" b="28"/>
+<s d="t" t="t" b="29"/>
+<s d="u" t="u" b="30"/>
+<s d="v" t="v" b="31"/>
+<s d="w" t="w" b="32"/>
+<s d="x" t="x" b="33"/>
+<s d="y" t="y" b="34"/>
+<s d="z" t="z" b="35"/>
+</group>
+<group name="Punctuation" b="112">
+<s b="105" d="&#x25cc;&#x0313;"  t="&apos;" />
+<s b="103" d="?" t="?" />
+<s b="104" d="!" t="!" />
+<s b="100" d="," t="," />
+<s b="104" d="&#183;" t="." />
+</group>
+</alphabet>
+</alphabets>

Added: trunk/java/dasher/applet/system.rc/alphabet.englishC.xml
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/system.rc/alphabet.englishC.xml	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE alphabets SYSTEM "alphabet.dtd">
+<?xml-stylesheet type="text/xsl" href="alphabet.xsl"?>
+<alphabets>
+<alphabet name="English with accents, numerals, punctuation">
+<orientation type="LR"/>
+<encoding type="Western"/>
+<palette>European/Asian (New)</palette>
+<train>training_english_GB.txt</train>
+<space d="&#x25a1;" t=" "  b="9"/>
+<control d="Control" t=""  b="8"/>
+<paragraph d="&#182;" b="9"/>
+<group name="Combining accents" b="47" visible="on">
+<s d="&#x25cc;&#x0300;"  t="&#x0300;" b="40" note="&#x0060; COMBINING GRAVE ACCENT  "/>
+<s d="&#x25cc;&#x0301;"  t="&#x0301;" b="41" note="&#x00B4; COMBINING ACUTE ACCENT  "/>
+<s d="&#x25cc;&#x0302;"  t="&#x0302;" b="40" note="&#x005E; COMBINING CIRCUMFLEX ACCENT  "/>
+<s d="&#x25cc;&#x0303;"  t="&#x0303;" b="41" note="&#x007E; COMBINING TILDE  "/>
+<s d="&#x25cc;&#x0304;"  t="&#x0304;" b="40" note="&#x00AF; COMBINING MACRON  "/>
+<s d="&#x25cc;&#x0306;"  t="&#x0306;" b="41" note="&#x02D8; COMBINING BREVE"/>
+<s d="&#x25cc;&#x0307;"  t="&#x0307;" b="40" note="&#x02D9; COMBINING DOT ABOVE"/>
+<s d="&#x25cc;&#x0308;"  t="&#x0308;" b="41" note="&#x00A8; COMBINING DIAERESIS or UMLAUT "/>
+<s d="&#x25cc;&#x030A;"  t="&#x030A;" b="40" note="&#x02DA; COMBINING RING ABOVE"/>
+<s d="&#x25cc;&#x030B;"  t="&#x030B;" b="41" note="&#x02DD; COMBINING DOUBLE ACUTE ACCENT"/>
+<s d="&#x25cc;&#x030C;"  t="&#x030C;" b="40" note="&#x02C7; COMBINING CARON"/>
+<s d="&#x25cc;&#x0326;"  t="&#x0326;" b="41" note="       COMBINING COMMA BELOW"/>
+<s d="&#x25cc;&#x0327;"  t="&#x0327;" b="40" note="&#x00B8; COMBINING CEDILLA  "/>
+<s d="&#x25cc;&#x0328;"  t="&#x0328;" b="41" note="&#x02DB; COMBINING OGONEK"/>
+</group>
+<group name="Lower case Latin letters" b="0" visible="off">
+<s d="a" t="a" b="10"/>
+<s d="b" t="b" b="11"/>
+<s d="c" t="c" b="12"/>
+<s d="d" t="d" b="13"/>
+<s d="e" t="e" b="14"/>
+<s d="f" t="f" b="15"/>
+<s d="g" t="g" b="16"/>
+<s d="h" t="h" b="17"/>
+<s d="i" t="i" b="18"/>
+<s d="j" t="j" b="19"/>
+<s d="k" t="k" b="20"/>
+<s d="l" t="l" b="21"/>
+<s d="m" t="m" b="22"/>
+<s d="n" t="n" b="23"/>
+<s d="o" t="o" b="24"/>
+<s d="p" t="p" b="25"/>
+<s d="q" t="q" b="26"/>
+<s d="r" t="r" b="27"/>
+<s d="s" t="s" b="28"/>
+<s d="t" t="t" b="29"/>
+<s d="u" t="u" b="30"/>
+<s d="v" t="v" b="31"/>
+<s d="w" t="w" b="32"/>
+<s d="x" t="x" b="33"/>
+<s d="y" t="y" b="34"/>
+<s d="z" t="z" b="35"/>
+</group>
+<group name="Upper case Latin letters" b="46">
+<s d="A" t="A" b="10"/>
+<s d="B" t="B" b="11"/>
+<s d="C" t="C" b="12"/>
+<s d="D" t="D" b="13"/>
+<s d="E" t="E" b="14"/>
+<s d="F" t="F" b="15"/>
+<s d="G" t="G" b="16"/>
+<s d="H" t="H" b="17"/>
+<s d="I" t="I" b="18"/>
+<s d="J" t="J" b="19"/>
+<s d="K" t="K" b="20"/>
+<s d="L" t="L" b="21"/>
+<s d="M" t="M" b="22"/>
+<s d="N" t="N" b="23"/>
+<s d="O" t="O" b="24"/>
+<s d="P" t="P" b="25"/>
+<s d="Q" t="Q" b="26"/>
+<s d="R" t="R" b="27"/>
+<s d="S" t="S" b="28"/>
+<s d="T" t="T" b="29"/>
+<s d="U" t="U" b="30"/>
+<s d="V" t="V" b="31"/>
+<s d="W" t="W" b="32"/>
+<s d="X" t="X" b="33"/>
+<s d="Y" t="Y" b="34"/>
+<s d="Z" t="Z" b="35"/>
+</group>
+<group name="Numbers" b="48">
+<s d="1" t="1" b="42"/>
+<s d="2" t="2" b="41"/>
+<s d="3" t="3" b="42"/>
+<s d="4" t="4" b="41"/>
+<s d="5" t="5" b="42"/>
+<s d="6" t="6" b="41"/>
+<s d="7" t="7" b="42"/>
+<s d="8" t="8" b="41"/>
+<s d="9" t="9" b="42"/>
+<s d="0" t="0" b="41"/>
+</group>
+<group name="Punctuation" b="49">
+<s b="40" d="[" t="["/>
+<s b="41" d="]" t="]"/>
+<s b="40" d="{" t="{"/>
+<s b="41" d="}" t="}"/>
+<s b="40" d="&lt;" t="&lt;"/>
+<s b="41" d="&gt;" t="&gt;"/>
+<s b="40" d="(" t="("/>
+<s b="41" d=")" t=")"/>
+<s b="40" d="&amp;" t="&amp;"/> 
+<s b="42" d="$" t="$"/>
+<s b="41" d="%" t="%"/>
+<s b="42" d="=" t="="/>
+<s b="41" d="+" t="+"/>
+<s b="42" d="-" t="-"/>
+<s b="41" d="*" t="*"/>
+<s b="42" d="/" t="/"/>
+<s b="40" d="\" t="\"/>
+<s b="41" d="#" t="#"/>
+<s b="40" d="|" t="|"/>
+<s b="41" d="~" t="~"/>
+<s b="40" d="^" t="^"/>
+<s b="41" d="@" t="@"/>
+<s b="40" d="_" t="_"/>
+<s b="42" d="&#x201C;" t="&#x201C;" note="left double quotation mark" />
+<s b="41" d="&#x0022;" t="&#x0022;" note="deprecated vertical double quotation mark" />
+<s b="42" d="&#x201D;" t="&#x201D;" note="right double quotation mark" />
+<s b="41" d="&#x2018;" t="&#x2018;" note="left single quotation mark" />
+<s b="42" d="&#x2019;" t="&#x2019;" note="right single quotation mark and apostrophe" />
+<s b="41" d="`" t="`" note="left quote from keyboard" />
+<s b="42" d="&#x25cc;&#x0313;" t="&apos;" note=" apostrophe"/>
+<s b="40"  d="&#x25CA;" t="&#x9;" note="TAB (represented by a diamond)"/>
+<s b="41" d=":" t=":"/>
+<s b="40" d=";" t=";"/>
+<s b="41" d="?" t="?"/>
+<s b="40" d="!" t="!"/>
+<s b="41" d="," t=","/>
+<s d="&#183;" t="." b="40"/>
+</group>
+</alphabet>
+</alphabets>

Added: trunk/java/dasher/applet/system.rc/colour.dtd
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/system.rc/colour.dtd	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,13 @@
+<!-- Colour schemes contain lists of colours to be used by Dasher -->
+
+<!ELEMENT colours (palette*)>
+
+<!ELEMENT palette (colour*)>
+<!ATTLIST palette name CDATA #REQUIRED>
+
+<!-- A list of rgb values -->
+<!ELEMENT colour EMPTY>
+<!ATTLIST colour r CDATA #REQUIRED>
+<!ATTLIST colour g CDATA #REQUIRED>
+<!ATTLIST colour b CDATA #REQUIRED>
+

Added: trunk/java/dasher/applet/system.rc/colour.euroasian-new.xml
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/system.rc/colour.euroasian-new.xml	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,420 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE colours SYSTEM "colour.dtd">
+<?xml-stylesheet type="text/xsl" href="colour.xsl"?>
+<colours>
+<palette name="European/Asian (New)">
+<!-- Summary: 
+ Letters 10-109 are divided up as follows:
+   10-35: for(a-z)&(A-Z)letters. 
+   40-45: 6 different colours for characters( c1,c2,c3,c1',c2',c3')
+		  these are used in Accent, Numerals and Puctuation groups 
+   46-49: colour for character sets( Capital Letters, Accent, Numerals & Punctuation)	     
+   70-79: 10 Hiragana rainbow colours
+   80-89: 10 Hiragana rainbow colours, slightly different shades
+   90-: Distinctive Colours 
+       90-94: five shades of pink, can be used periodically 
+       95-99: five shades of grey, can be used periodically 
+       100-104: redundant; filled with greys at the moment
+       105-109: five shades of purple, can be used periodically
+ Groups:
+    110-113: contain the colours for groups (Capital Letters, Accent, Numerals & Punctuation)
+    115-129: other group colour schemes for use when there are many groups
+       115-119: pinks
+       120-124: purples
+       125-129:  greys
+  -->
+<!-- background 0 -->
+<colour r="255" g="255" b="255"/>
+<!-- mouse line 1 (red) -->
+<colour r="255" g="0" b="0"/>
+<!-- mouse position 2 (black) -->
+<colour r="0" g="0" b="0"/>
+<!-- box outlines 3 (grey) -->
+<colour r="218" g="218" b="218"/>
+<!-- text 4 (black) -->
+<colour r="0" g="0" b="0"/>
+<!-- crosshairs 5 (black) -->
+<colour r="0" g="0" b="0"/>
+<!-- keyboard positioning 6 (black) -->
+<colour r="0" g="0" b="0"/>
+<!-- root node 7 (soft blue) -->
+<colour r="181" g="207" b="221"/>
+<!-- control node 8 (dark grey ) -->
+<colour r="80" g="80" b="80"/>
+<!-- space 9  (off-white)  -->
+<colour r="235" g="235" b="235"/>
+<!-- letters (10-109) -->
+<!-- colours for use by european alphabets(Sr.no.-10-35) -->
+<colour r="181" g="207" b="221"/>
+<colour r="113" g="173" b="187"/>
+<colour r="181" g="207" b="221"/>
+<colour r="113" g="173" b="187"/>
+<colour r="181" g="207" b="221"/>
+<colour r="113" g="173" b="187"/>
+<colour r="181" g="207" b="221"/>
+<colour r="113" g="173" b="187"/>
+<colour r="181" g="207" b="221"/>
+<colour r="113" g="173" b="187"/>
+<colour r="181" g="207" b="221"/>
+<colour r="113" g="173" b="187"/>
+<colour r="98" g="145" b="169"/>
+<colour r="181" g="207" b="221"/>
+<colour r="113" g="173" b="187"/>
+<colour r="98" g="145" b="169"/>
+<colour r="113" g="173" b="187"/>
+<colour r="98" g="145" b="169"/>
+<colour r="113" g="173" b="187"/>
+<colour r="98" g="145" b="169"/>
+<colour r="113" g="173" b="187"/>
+<colour r="98" g="145" b="169"/>
+<colour r="113" g="173" b="187"/>
+<colour r="98" g="145" b="169"/>
+<colour r="113" g="173" b="187"/>
+<colour r="98" g="145" b="169"/>
+<!-- (Sr.no.-36-39) -->
+<colour r="113" g="173" b="187"/>
+<colour r="98" g="145" b="169"/>
+<colour r="113" g="173" b="187"/>
+<colour r="98" g="145" b="169"/>
+<!-- 6 differenr colours used for characters (c1,c2,c3,c1',c2'& c3') (Sr.no.-40-45) -->
+<colour r="181" g="207" b="221"/>
+<colour r="113" g="173" b="187"/>
+<colour r="98" g="145" b="169"/>
+<colour r="170" g="208" b="162"/>
+<colour r="111" g="188" b="133"/>
+<colour r="85" g="165" b="124"/>
+<!--remaining 4 colours for character grops,(Sr.no.-46-49)(46-Capital Letters, 47-Accents, 48-Numerals, 49-Punctuation)-->
+<colour r="160" g="160" b="160"/>
+<colour r="236" g="189" b="32"/>
+<colour r="65" g="195" b="216"/>
+<colour r="247" g="91" b="70"/>
+<!-- that is the first 40 letters --> 
+<!-- Here I have a DARK, INTENSE Hiragana section, for use as an additional group  resource -->
+<!-- red colour 50+10 -->
+<colour r="245" g="0" b="0"/>
+<!-- orange 50+11 -->
+<colour r="249" g="139" b="0"/>
+<!-- yel  50+12 -->
+<colour r="255" g="250" b="0"/>
+<!-- NEW lime yel/green  50+13 <colour r="190" g="255" b="0"/> -->
+<colour r="223" g="255" b="0"/>
+<!-- green 14 -->
+<colour r="0" g="250" b="0"/>
+<!-- NEW greenblue  60+15 -->
+<colour r="0" g="255" b="200"/>
+<!-- NEW light blue 16  -->
+<colour r="0" g="215" b="240"/>
+<!-- darkerblue 17   -->
+<colour r="0" g="100" b="245"/>
+<!-- blue purple 18  -->
+<colour r="215" g="0" b="250"/>
+<!-- red purple  60+19   -->
+<colour r="250" g="0" b="209"/>
+<!-- that is the first 50 letters --> 
+<!-- Here I have a pale Hiragana section, for use as an additional group  resource -->
+<!-- red colour 50+10 -->
+<colour r="255" g="119" b="119"/>
+<!-- orange 50+11 -->
+<colour r="255" g="200" b="136"/>
+<!-- yel  50+12 -->
+<colour r="255" g="240" b="130"/>
+<!-- NEW lime yel/green  50+13 <colour r="190" g="255" b="0"/> -->
+<colour r="230" g="255" b="160"/>
+<!-- green 14 -->
+<colour r="100" g="255" b="120"/>
+<!-- NEW greenblue  60+15 -->
+<colour r="100" g="255" b="200"/>
+<!-- NEW light blue 16  -->
+<colour r="140" g="215" b="255"/>
+<!-- darkerblue 17   -->
+<colour r="140" g="140" b="255"/>
+<!-- blue purple 18  -->
+<colour r="215" g="110" b="255"/>
+<!-- red purple  60+19   -->
+<colour r="255" g="119" b="209"/>
+<!-- that is the first 60 letters --> 
+<!-- now 20 colours for hiragana rainbow.
+  10 and 10, almost identical, just intensity difference
+  between the two groups
+  -->
+<!-- red colour 60+10 -->
+<colour r="255" g="69" b="69"/>
+<!-- orange 60+11 -->
+<colour r="255" g="156" b="96"/>
+<!-- yel  60+12 -->
+<colour r="255" g="230" b="0"/>
+<!-- NEW lime yel/green  60+13 <colour r="190" g="255" b="0"/> -->
+<colour r="200" g="255" b="80"/>
+<!-- green 14 -->
+<colour r="0" g="247" b="20"/>
+<!-- NEW greenblue  60+15 -->
+<colour r="0" g="255" b="185"/>
+<!-- NEW light blue 16  -->
+<colour r="0" g="205" b="255"/>
+<!-- darkerblue 17   -->
+<colour r="90" g="90" b="255"/>
+<!-- blue purple 18  -->
+<colour r="195" g="90" b="255"/>
+<!-- red purple  60+19   -->
+<colour r="255" g="90" b="192"/>
+<!-- end of first 10 hiragana letter colours -->
+<!-- the second rainbow is slightly less bright -->
+<!-- red colour 70+10 -->
+<colour r="240" g="56" b="56"/>
+<!-- orange 11 r="255" g="156" b="96" -->
+<colour r="240" g="145" b="80"/>
+<!-- yel  12  r="255" g="230" b="0"  or dirty yellow r="240" g="220" b="0" -->
+<colour r="255" g="230" b="110"/>
+<!-- NEW yel/green  13   r="190" g="255" b="0"  <colour r="176" g="240" b="0"/> -->
+<colour r="186" g="248" b="0"/>
+<!-- green 14 -->
+<colour r="0" g="240" b="0"/>
+<!-- NEW greenblue  15 -->
+<colour r="0" g="240" b="177"/>
+<!-- NEW light blue  -->
+<colour r="0" g="189" b="240"/>
+<!-- darkerblue 17   -->
+<colour r="90" g="70" b="230"/>
+<!-- blue purple 18 (19 is biggest colour used by hiragana) -->
+<colour r="182" g="72" b="235"/>
+<!-- red purple  70+19   -->
+<colour r="235" g="72" b="182"/>
+<!-- end of first 20 hiragana letter colours -->
+<!-- 20 shades of pink and grey useful for punctuation -->
+<!-- pink recommend using all five periodically -->
+<!-- pinks 90 91 92 93 94 --> 
+<!-- pink  used by old Hiragana  90  had g,b 192 -->
+<colour r="255" g="172" b="172"/>
+<colour r="255" g="132" b="132"/>
+<colour r="255" g="192" b="192"/>
+<colour r="255" g="154" b="154"/>
+<colour r="255" g="210" b="210"/>
+<!-- greys: recommend using 95..99 periodically (five colours) -->
+<!-- light grey 95   -->
+<colour r="170" g="170" b="170"/>
+<!--  dark grey 96  -->
+<colour r="120" g="120" b="120"/>
+<!--  grey  97  -->
+<colour r="195" g="195" b="195"/>
+<!--  v light grey  98  -->
+<colour r="145" g="145" b="145"/>
+<!--  v light grey  99  -->
+<colour r="220" g="220" b="220"/>
+<!-- slate blues     100  101 102 103 104  -->
+<colour r="142" g="172" b="222"/>
+<colour r="110" g="130" b="188"/>
+<colour r="170" g="200" b="232"/>
+<colour r="114" g="154" b="204"/>
+<colour r="200" g="228" b="243"/>
+<!-- light purple  used by old hiragana, (182) in 5 shades 105 106 107 108 109  -->
+<colour r="255" g="145" b="255"/>
+<colour r="255" g="82"  b="255"/>
+<colour r="255" g="162" b="255"/>
+<colour r="255" g="128" b="255"/>
+<colour r="255" g="182" b="255"/>
+<!-- end of first 90 letter colours -->
+<!-- groups (110-129)-->
+<!-- slate blue  110  -->
+<colour r="100" g="155" b="200"/>
+<!-- yellow = capitals 111  -->
+<colour r="255" g="255" b="0"/>
+<!-- NOW GREEN - was dark red 112  (punctuation 112 is usually green)  -->
+<colour r="0" g="200" b="0"/>
+<!-- NOW RED   - was green 113 - (red 113 usually used for numbers) -->
+<colour r="255" g="0" b="0"/>
+<!-- dark purple  114 -->
+<colour r="200" g="0" b="200"/>
+<!-- khaki (as used in english)  115 -->
+<colour r="155" g="205" b="155"/>
+ <!-- pink as used by old Hiragana  115-119  (116-120?) -->
+<colour r="255" g="172" b="172"/>
+<colour r="255" g="132" b="132"/>
+<!-- pink  19  used by old Hiragana  -->
+<colour r="255" g="192" b="192"/>
+<colour r="255" g="154" b="154"/>
+<colour r="255" g="210" b="210"/>
+<!-- light purple as used by old hiragana 120-124 five shades  -->
+<colour r="255" g="145" b="255"/>
+<colour r="255" g="82"  b="255"/>
+<colour r="255" g="162" b="255"/>
+<!-- light purple 18 used by old hiragana  -->
+<colour r="255" g="128" b="255"/>
+<colour r="255" g="182" b="255"/>
+<!-- FIVE greys 125-129 for use in groups, identical to five in the punctuation letters area --> 
+<!-- light grey 125   -->
+<colour r="170" g="170" b="170"/>
+<!--  dark grey 126  -->
+<colour r="120" g="120" b="120"/>
+<!--  grey  127  -->
+<colour r="195" g="195" b="195"/>
+<!--  v light grey  128  -->
+<colour r="145" g="145" b="145"/>
+<!--  v light grey  129  -->
+<colour r="220" g="220" b="220"/>
+<!-- end of groups -->
+<!-- currently unused (130-137) -->
+<colour r="255" g="128" b="255"/>
+<colour r="255" g="192" b="192"/>
+<!-- light grey  -->
+<colour r="192" g="192" b="192"/>
+<!--  orange, pink, and fluorescent green; to be used for decorations like arrows  -->
+<colour r="255" g="160" b="100"/>
+<colour r="255" g="100" b="204"/>
+<colour r="200" g="255" b="20"/>
+<colour r="150" g="255" b="50"/>
+<!-- and that ^^ is 137 -->
+<!-- alternate colours, used in alternation with the ones above -->
+<!-- alternate control node -->
+<colour r="80" g="80" b="80"/>
+<!-- alternate space -->
+<colour r="255" g="255" b="255"/>
+<!-- alternate colours for letters (Sr.no.140-165) -->
+<colour r="170" g="208" b="162"/>
+<colour r="111" g="188" b="133"/>
+<colour r="170" g="208" b="162"/>
+<colour r="111" g="188" b="133"/>
+<colour r="170" g="208" b="162"/>
+<colour r="111" g="188" b="133"/>
+<colour r="170" g="208" b="162"/>
+<colour r="111" g="188" b="133"/>
+<colour r="170" g="208" b="162"/>
+<colour r="111" g="188" b="133"/>
+<colour r="170" g="208" b="162"/>
+<colour r="111" g="188" b="133"/>
+<colour r="170" g="208" b="162"/>
+<colour r="85" g="165" b="124"/>
+<colour r="111" g="188" b="133"/>
+<colour r="85" g="165" b="124"/>
+<colour r="111" g="188" b="133"/>
+<colour r="85" g="165" b="124"/>
+<colour r="111" g="188" b="133"/>
+<colour r="85" g="165" b="124"/>
+<colour r="111" g="188" b="133"/>
+<colour r="85" g="165" b="124"/>
+<colour r="111" g="188" b="133"/>
+<colour r="85" g="165" b="124"/>
+<colour r="111" g="188" b="133"/>
+<colour r="85" g="165" b="124"/>
+<!--  (Sr.no.166-169) -->
+<colour r="111" g="188" b="133"/>
+<colour r="85" g="165" b="124"/>
+<colour r="111" g="188" b="133"/>
+<colour r="85" g="165" b="124"/>
+<!-- 6 differenr colours used for characters (c1',c2',c3',c1,c2& c3) (Sr.no.170-175) -->
+<colour r="170" g="208" b="162"/>
+<colour r="111" g="188" b="133"/>
+<colour r="85" g="165" b="124"/>
+<colour r="181" g="207" b="221"/>
+<colour r="113" g="173" b="187"/>
+<colour r="98" g="145" b="169"/>
+<!--remaining 4 colours for character grops,(Sr.no.-176-179)(46-Capital Letters, 47-Accents, 48-Numerals, 49-Punctuation)-->
+<colour r="153" g="153" b="153"/>
+<colour r="236" g="189" b="32"/>
+<colour r="65" g="195" b="216"/>
+<colour r="247" g="91" b="70"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<!-- end of 60 letters -->
+<!-- red colour 10 -->
+<colour r="255" g="69" b="69"/>
+<!-- orange 11 -->
+<colour r="255" g="156" b="96"/>
+<!-- yel  12 -->
+<colour r="255" g="230" b="0"/>
+<!-- NEW yel/green  13 -->
+<colour r="200" g="255" b="80"/>
+<!-- green 14 -->
+<colour r="0" g="247" b="20"/>
+<!-- NEW greenblue  15 -->
+<colour r="0" g="255" b="185"/>
+<!-- NEW light blue 16  -->
+<colour r="0" g="205" b="255"/>
+<!-- darkerblue 17   -->
+<colour r="90" g="90" b="255"/>
+<!-- blue purple 18 (19 is biggest colour used by hiragana) -->
+<colour r="195" g="90" b="255"/>
+<!-- red purple  19   -->
+<colour r="255" g="90" b="192"/>
+<!-- end of first 10 letter colours -->
+<!-- the second rainbow is slightly less bright -->
+<!-- red colour 70+10 -->
+<colour r="240" g="56" b="56"/>
+<!-- orange 11 r="255" g="156" b="96" -->
+<colour r="240" g="145" b="80"/>
+<!-- yel  12  r="255" g="230" b="0" -->
+<colour r="255" g="230" b="110"/>
+<!-- NEW yel/green  13   r="190" g="255" b="0" -->
+<colour r="186" g="248" b="50"/>
+<!-- green 14 -->
+<colour r="0" g="240" b="0"/>
+<!-- NEW greenblue  15 -->
+<colour r="0" g="240" b="177"/>
+<!-- NEW light blue  -->
+<colour r="0" g="189" b="240"/>
+<!-- darkerblue 17   -->
+<colour r="90" g="70" b="230"/>
+<!-- blue purple 18 (19 is biggest colour used by hiragana) -->
+<colour r="182" g="72" b="235"/>
+<!-- red purple  70+19   -->
+<colour r="235" g="72" b="182"/>
+<!-- end of first 20 hiragana letter colours -->
+<!-- end of  20 hiragana  letter colours -->
+<!-- 20 shades of pink and grey useful for punctuation -->
+<!-- pink  used by old Hiragana  90  was 192 -->
+<!-- other  pinks 91 92 93 94 --> 
+<colour r="255" g="172" b="172"/>
+<colour r="255" g="132" b="132"/>
+<colour r="255" g="192" b="192"/>
+<colour r="255" g="154" b="154"/>
+<colour r="255" g="210" b="210"/>
+<!-- greys: recommend using 95..99 periodically (five colours) -->
+<!-- light grey 95   -->
+<colour r="170" g="170" b="170"/>
+<!--  dark grey 96  -->
+<colour r="120" g="120" b="120"/>
+<!--  grey  97  -->
+<colour r="195" g="195" b="195"/>
+<!--  v light grey  98  -->
+<colour r="145" g="145" b="145"/>
+<!--  v light grey  99  -->
+<colour r="220" g="220" b="220"/>
+<!-- slate blues     100  101 102 103 104  -->
+<colour r="142" g="172" b="222"/>
+<colour r="110" g="130" b="188"/>
+<colour r="170" g="200" b="232"/>
+<colour r="114" g="154" b="204"/>
+<colour r="200" g="228" b="243"/>
+<!-- light purple  105-109 used by old hiragana, in 5 shades  -->
+<colour r="255" g="145" b="255"/>
+<colour r="255" g="82"  b="255"/>
+<colour r="255" g="162" b="255"/>
+<colour r="255" g="128" b="255"/>
+<colour r="255" g="182" b="255"/>
+<!-- end of first 90 letter colours -->
+<!-- Control mode colours -->
+<!-- Green (240) -->
+<colour r="0" g="255" b="0"/>
+<!-- Amber (241) -->
+<colour r="240" g="240" b="0"/>
+<!-- Red (242) -->
+<colour r="255" g="0" b="0"/>
+</palette>
+</colours>

Added: trunk/java/dasher/applet/system.rc/colour.euroasian.xml
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/system.rc/colour.euroasian.xml	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,415 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE colours SYSTEM "colour.dtd">
+<?xml-stylesheet type="text/xsl" href="colour.xsl"?>
+<colours>
+<palette name="European/Asian">
+<!-- Summary: 
+ Letters 10-109 are divided up as follows:
+   10-39: principal European area. Currently coloured with 3 cycling colours. 
+   40-69: unused    European area. Currently coloured with 3 cycling colours. 
+   70-79: 10 Hiragana rainbow colours
+   80-89: 10 Hiragana rainbow colours, slightly different shades
+   90-: Distinctive Colours recommended for use in Punctuation, numerals
+       90-94: five shades of pink, can be used periodically 
+       95-99: five shades of grey, can be used periodically 
+       100-104: redundant; filled with greys at the moment
+       105-109: five shades of purple, can be used periodically
+ Groups:
+    110-113: contain the yellow, green, red groups used in European alphabets
+    115-129: other group colour schemes for use when there are many groups
+       115-119: pinks
+       120-124: purples
+       125-129:  greys
+  -->
+<!-- background 0 -->
+<colour r="255" g="255" b="255"/>
+<!-- mouse line 1 (red) -->
+<colour r="255" g="0" b="0"/>
+<!-- mouse position 2 (black) -->
+<colour r="0" g="0" b="0"/>
+<!-- box outlines 3 (grey) -->
+<colour r="218" g="218" b="218"/>
+<!-- text 4 (black) -->
+<colour r="0" g="0" b="0"/>
+<!-- crosshairs 5 (black) -->
+<colour r="0" g="0" b="0"/>
+<!-- keyboard positioning 6 (black) -->
+<colour r="0" g="0" b="0"/>
+<!-- root node 7 (soft green) -->
+<colour r="180" g="238" b="180"  />
+<!-- control node 8 (dark grey ) -->
+<colour r="80" g="80" b="80"/>
+<!-- space 9  (off-white)  -->
+<colour r="235" g="235" b="235"/>
+<!-- letters (10-109) -->
+<!-- first 30 colours for use by european alphabets -->
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<!-- next 10 letters unallocated -->
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<colour r="0" g="255" b="255"/>
+<!-- that is the first 40 letters   Here are restored bland colours for 50-59 --> 
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<!-- that is the first 50 letters --> 
+<!-- Here I have a pale Hiragana section, for use as an additional group  resource. See also 190-199 -->
+<!-- red colour 50+10 -->
+<colour r="255" g="119" b="119"/>
+<!-- orange 50+11 -->
+<colour r="255" g="200" b="136"/>
+<!-- yel  50+12 -->
+<colour r="255" g="240" b="130"/>
+<!-- NEW lime yel/green  50+13 <colour r="190" g="255" b="0"/> -->
+<colour r="230" g="255" b="160"/>
+<!-- green 14 -->
+<colour r="100" g="255" b="120"/>
+<!-- NEW greenblue  60+15 -->
+<colour r="100" g="255" b="200"/>
+<!-- NEW light blue 16  -->
+<colour r="140" g="215" b="255"/>
+<!-- darkerblue 17   -->
+<colour r="140" g="140" b="255"/>
+<!-- blue purple 18  -->
+<colour r="215" g="110" b="255"/>
+<!-- red purple  60+19   -->
+<colour r="255" g="119" b="209"/>
+<!-- that is the first 60 letters --> 
+<!-- now 20 colours for hiragana rainbow.
+  10 and 10, almost identical, just intensity difference
+  between the two groups
+  -->
+<!-- red colour 60+10 -->
+<colour r="255" g="69" b="69"/>
+<!-- orange 60+11 -->
+<colour r="255" g="156" b="96"/>
+<!-- yel  60+12 -->
+<colour r="255" g="230" b="0"/>
+<!-- NEW lime yel/green  60+13 <colour r="190" g="255" b="0"/> -->
+<colour r="200" g="255" b="80"/>
+<!-- green 14 -->
+<colour r="0" g="247" b="20"/>
+<!-- NEW greenblue  60+15 -->
+<colour r="0" g="255" b="185"/>
+<!-- NEW light blue 16  -->
+<colour r="0" g="205" b="255"/>
+<!-- darkerblue 17   -->
+<colour r="90" g="90" b="255"/>
+<!-- blue purple 18  -->
+<colour r="195" g="90" b="255"/>
+<!-- red purple  60+19   -->
+<colour r="255" g="90" b="192"/>
+<!-- end of first 10 hiragana letter colours -->
+<!-- the second rainbow is slightly less bright -->
+<!-- red colour 70+10 -->
+<colour r="240" g="56" b="56"/>
+<!-- orange 11 r="255" g="156" b="96" -->
+<colour r="240" g="145" b="80"/>
+<!-- yel  12  r="255" g="230" b="0"  or dirty yellow r="240" g="220" b="0" -->
+<colour r="255" g="230" b="110"/>
+<!-- NEW yel/green  13   r="190" g="255" b="0"  <colour r="176" g="240" b="0"/> -->
+<colour r="186" g="248" b="0"/>
+<!-- green 14 -->
+<colour r="0" g="240" b="0"/>
+<!-- NEW greenblue  15 -->
+<colour r="0" g="240" b="177"/>
+<!-- NEW light blue  -->
+<colour r="0" g="189" b="240"/>
+<!-- darkerblue 17   -->
+<colour r="90" g="70" b="230"/>
+<!-- blue purple 18 (19 is biggest colour used by hiragana) -->
+<colour r="182" g="72" b="235"/>
+<!-- red purple  70+19   -->
+<colour r="235" g="72" b="182"/>
+<!-- end of first 20 hiragana letter colours -->
+<!-- 20 shades of pink and grey useful for punctuation -->
+<!-- pink recommend using all five periodically -->
+<!-- pinks 90 91 92 93 94 --> 
+<!-- pink  used by old Hiragana  90  had g,b 192 -->
+<colour r="255" g="172" b="172"/>
+<colour r="255" g="132" b="132"/>
+<colour r="255" g="192" b="192"/>
+<colour r="255" g="154" b="154"/>
+<colour r="255" g="210" b="210"/>
+<!-- greys: recommend using 95..99 periodically (five colours) -->
+<!-- light grey 95   -->
+<colour r="170" g="170" b="170"/>
+<!--  dark grey 96  -->
+<colour r="120" g="120" b="120"/>
+<!--  grey  97  -->
+<colour r="195" g="195" b="195"/>
+<!--  v light grey  98  -->
+<colour r="145" g="145" b="145"/>
+<!--  v light grey  99  -->
+<colour r="220" g="220" b="220"/>
+<!-- slate blues     100  101 102 103 104  -->
+<colour r="142" g="172" b="222"/>
+<colour r="110" g="130" b="188"/>
+<colour r="170" g="200" b="232"/>
+<colour r="114" g="154" b="204"/>
+<colour r="200" g="228" b="243"/>
+<!-- light purple  used by old hiragana, (182) in 5 shades 105 106 107 108 109  -->
+<colour r="255" g="145" b="255"/>
+<colour r="255" g="82"  b="255"/>
+<colour r="255" g="162" b="255"/>
+<colour r="255" g="128" b="255"/>
+<colour r="255" g="182" b="255"/>
+<!-- end of first 90 letter colours -->
+<!-- groups (110-129)-->
+<!-- slate blue  110  -->
+<colour r="100" g="155" b="200"/>
+<!-- yellow = capitals 111  -->
+<colour r="255" g="255" b="0"/>
+<!-- NOW GREEN - was dark red 112  (punctuation 112 is usually green)  -->
+<colour r="0" g="200" b="0"/>
+<!-- NOW RED   - was green 113 - (red 113 usually used for numbers) -->
+<colour r="255" g="0" b="0"/>
+<!-- dark purple  114 -->
+<colour r="200" g="0" b="200"/>
+<!-- khaki (as used in english)  115 -->
+<colour r="155" g="205" b="155"/>
+ <!-- pink as used by old Hiragana  115-119  (116-120?) -->
+<colour r="255" g="172" b="172"/>
+<colour r="255" g="132" b="132"/>
+<!-- pink  19  used by old Hiragana  -->
+<colour r="255" g="192" b="192"/>
+<colour r="255" g="154" b="154"/>
+<colour r="255" g="210" b="210"/>
+<!-- light purple as used by old hiragana 120-124 five shades  -->
+<colour r="255" g="145" b="255"/>
+<colour r="255" g="82"  b="255"/>
+<colour r="255" g="162" b="255"/>
+<!-- light purple 18 used by old hiragana  -->
+<colour r="255" g="128" b="255"/>
+<colour r="255" g="182" b="255"/>
+<!-- FIVE greys 125-129 for use in groups, identical to five in the punctuation letters area --> 
+<!-- light grey 125   -->
+<colour r="170" g="170" b="170"/>
+<!--  dark grey 126  -->
+<colour r="120" g="120" b="120"/>
+<!--  grey  127  -->
+<colour r="195" g="195" b="195"/>
+<!--  v light grey  128  -->
+<colour r="145" g="145" b="145"/>
+<!--  v light grey  129  -->
+<colour r="220" g="220" b="220"/>
+<!-- end of groups -->
+<!-- currently unused (130-137) -->
+<colour r="255" g="128" b="255"/>
+<colour r="255" g="192" b="192"/>
+<!-- light grey  -->
+<colour r="192" g="192" b="192"/>
+<!--  orange, pink, and fluorescent green; to be used for decorations like arrows  -->
+<colour r="255" g="160" b="100"/>
+<colour r="255" g="100" b="204"/>
+<colour r="200" g="255" b="20"/>
+<colour r="150" g="255" b="50"/>
+<!-- and that ^^ is 137 -->
+<!-- alternate colours, used in alternation with the ones above -->
+<!-- alternate control node -->
+<colour r="80" g="80" b="80"/>
+<!-- alternate space -->
+<colour r="255" g="255" b="255"/>
+<!-- alternate colours for letters (140-239) -->
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<!-- end of first 30 letters -->
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<!-- Here I have a DARK, INTENSE Hiragana section, for use as an additional group  resource. Used to be known as 50-59.
+     Now known as 130+60 = 190-199 -->
+<!-- red colour 50+10 -->
+<colour r="245" g="0" b="0"/>
+<!-- orange 50+11 -->
+<colour r="249" g="139" b="0"/>
+<!-- yel  50+12 -->
+<colour r="255" g="250" b="0"/>
+<!-- NEW lime yel/green  50+13 <colour r="190" g="255" b="0"/> -->
+<colour r="223" g="255" b="0"/>
+<!-- green 14 -->
+<colour r="0" g="250" b="0"/>
+<!-- NEW greenblue  60+15 -->
+<colour r="0" g="255" b="200"/>
+<!-- NEW light blue 16  -->
+<colour r="0" g="215" b="240"/>
+<!-- darkerblue 17   -->
+<colour r="0" g="100" b="245"/>
+<!-- blue purple 18  -->
+<colour r="215" g="0" b="250"/>
+<!-- red purple  60+19   -->
+<colour r="250" g="0" b="209"/>
+<!-- end of 60 letters -->
+<!-- red colour 10 -->
+<colour r="255" g="69" b="69"/>
+<!-- orange 11 -->
+<colour r="255" g="156" b="96"/>
+<!-- yel  12 -->
+<colour r="255" g="230" b="0"/>
+<!-- NEW yel/green  13 -->
+<colour r="200" g="255" b="80"/>
+<!-- green 14 -->
+<colour r="0" g="247" b="20"/>
+<!-- NEW greenblue  15 -->
+<colour r="0" g="255" b="185"/>
+<!-- NEW light blue 16  -->
+<colour r="0" g="205" b="255"/>
+<!-- darkerblue 17   -->
+<colour r="90" g="90" b="255"/>
+<!-- blue purple 18 (19 is biggest colour used by hiragana) -->
+<colour r="195" g="90" b="255"/>
+<!-- red purple  19   -->
+<colour r="255" g="90" b="192"/>
+<!-- end of first 10 letter colours -->
+<!-- the second rainbow is slightly less bright -->
+<!-- red colour 70+10 -->
+<colour r="240" g="56" b="56"/>
+<!-- orange 11 r="255" g="156" b="96" -->
+<colour r="240" g="145" b="80"/>
+<!-- yel  12  r="255" g="230" b="0" -->
+<colour r="255" g="230" b="110"/>
+<!-- NEW yel/green  13   r="190" g="255" b="0" -->
+<colour r="186" g="248" b="50"/>
+<!-- green 14 -->
+<colour r="0" g="240" b="0"/>
+<!-- NEW greenblue  15 -->
+<colour r="0" g="240" b="177"/>
+<!-- NEW light blue  -->
+<colour r="0" g="189" b="240"/>
+<!-- darkerblue 17   -->
+<colour r="90" g="70" b="230"/>
+<!-- blue purple 18 (19 is biggest colour used by hiragana) -->
+<colour r="182" g="72" b="235"/>
+<!-- red purple  70+19   -->
+<colour r="235" g="72" b="182"/>
+<!-- end of first 20 hiragana letter colours -->
+<!-- end of  20 hiragana  letter colours -->
+<!-- 20 shades of pink and grey useful for punctuation -->
+<!-- pink  used by old Hiragana  90  was 192 -->
+<!-- other  pinks 91 92 93 94 --> 
+<colour r="255" g="172" b="172"/>
+<colour r="255" g="132" b="132"/>
+<colour r="255" g="192" b="192"/>
+<colour r="255" g="154" b="154"/>
+<colour r="255" g="210" b="210"/>
+<!-- greys: recommend using 95..99 periodically (five colours) -->
+<!-- light grey 95   -->
+<colour r="170" g="170" b="170"/>
+<!--  dark grey 96  -->
+<colour r="120" g="120" b="120"/>
+<!--  grey  97  -->
+<colour r="195" g="195" b="195"/>
+<!--  v light grey  98  -->
+<colour r="145" g="145" b="145"/>
+<!--  v light grey  99  -->
+<colour r="220" g="220" b="220"/>
+<!-- slate blues     100  101 102 103 104  -->
+<colour r="142" g="172" b="222"/>
+<colour r="110" g="130" b="188"/>
+<colour r="170" g="200" b="232"/>
+<colour r="114" g="154" b="204"/>
+<colour r="200" g="228" b="243"/>
+<!-- light purple  105-109 used by old hiragana, in 5 shades  -->
+<colour r="255" g="145" b="255"/>
+<colour r="255" g="82"  b="255"/>
+<colour r="255" g="162" b="255"/>
+<colour r="255" g="128" b="255"/>
+<colour r="255" g="182" b="255"/>
+<!-- end of first 90 letter colours -->
+<!-- Control mode colours -->
+<!-- Green (240) -->
+<colour r="0" g="255" b="0"/>
+<!-- Amber (241) -->
+<colour r="240" g="240" b="0"/>
+<!-- Red (242) -->
+<colour r="255" g="0" b="0"/>
+</palette>
+</colours>

Added: trunk/java/dasher/applet/system.rc/colour.rainbow.xml
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/system.rc/colour.rainbow.xml	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,414 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE colours SYSTEM "colour.dtd">
+<?xml-stylesheet type="text/xsl" href="colour.xsl"?>
+<colours>
+<palette name="Rainbow">
+<!-- Summary: 
+ Letters 10-109 are divided up as follows:
+   10-39: principal European area. Currently coloured with 3 cycling colours. 
+   40-69: unused    European area. Currently coloured with 3 cycling colours. 
+   70-79: 10 Hiragana rainbow colours
+   80-89: 10 Hiragana rainbow colours, slightly different shades
+   90-: Distinctive Colours recommended for use in Punctuation, numerals
+       90-94: five shades of pink, can be used periodically 
+       95-99: five shades of grey, can be used periodically 
+       100-104: redundant; filled with greys at the moment
+       105-109: five shades of purple, can be used periodically
+ Groups:
+    110-113: contain the yellow, green, red groups used in European alphabets
+    115-129: other group colour schemes for use when there are many groups
+       115-119: pinks
+       120-124: purples
+       125-129:  greys
+  -->
+<!-- background 0 -->
+<colour r="255" g="255" b="255"/>
+<!-- mouse line 1 (red) -->
+<colour r="255" g="0" b="0"/>
+<!-- mouse position 2 (black) -->
+<colour r="0" g="0" b="0"/>
+<!-- box outlines 3 (grey) -->
+<colour r="218" g="218" b="218"/>
+<!-- text 4 (black) -->
+<colour r="0" g="0" b="0"/>
+<!-- crosshairs 5 (black) -->
+<colour r="0" g="0" b="0"/>
+<!-- keyboard positioning 6 (black) -->
+<colour r="0" g="0" b="0"/>
+<!-- root node 7 (soft green) -->
+<colour r="180" g="238" b="180"  />
+<!-- control node 8 (dark grey ) -->
+<colour r="80" g="80" b="80"/>
+<!-- space 9  (off-white)  -->
+<colour r="235" g="235" b="235"/>
+<!-- letters (10-109) -->
+<!-- first 30 colours for use by european alphabets -->
+<colour r="255" g="119" b="119"/>
+<colour r="245" g="0" b="0"/>
+<colour r="255" g="69" b="69"/>
+<colour r="249" g="139" b="0"/>
+<colour r="255" g="156" b="96"/>
+<colour r="255" g="200" b="136"/>
+<colour r="255" g="230" b="0"/>
+<colour r="255" g="250" b="0"/>
+<colour r="255" g="240" b="130"/>
+<colour r="230" g="255" b="160"/>
+<colour r="223" g="255" b="0"/>
+<colour r="200" g="255" b="80"/>
+<colour r="0" g="250" b="0"/>
+<colour r="0" g="247" b="20"/>
+<colour r="100" g="255" b="120"/>
+<colour r="100" g="255" b="200"/>
+<colour r="0" g="255" b="185"/>
+<colour r="0" g="255" b="200"/>
+<colour r="0" g="215" b="240"/>
+<colour r="140" g="215" b="255"/>
+<colour r="0" g="205" b="255"/>
+<colour r="90" g="90" b="255"/>
+<colour r="0" g="100" b="245"/>
+<colour r="140" g="140" b="255"/>
+<colour r="195" g="90" b="255"/>
+<colour r="215" g="110" b="255"/>
+<colour r="255" g="119" b="209"/>
+<colour r="215" g="0" b="250"/>
+<colour r="250" g="0" b="209"/>
+<colour r="255" g="90" b="192"/>
+<!-- next 10 letters unallocated -->
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<colour r="0" g="255" b="255"/>
+<colour r="180" g="238" b="180"/>
+<colour r="155" g="205" b="155"/>
+<colour r="0" g="255" b="255"/>
+<!-- that is the first 40 letters --> 
+<!-- Here I have a DARK, INTENSE Hiragana section, for use as an additional group  resource -->
+<!-- red colour 50+10 -->
+<colour r="245" g="0" b="0"/>
+<!-- orange 50+11 -->
+<colour r="249" g="139" b="0"/>
+<!-- yel  50+12 -->
+<colour r="255" g="250" b="0"/>
+<!-- NEW lime yel/green  50+13 <colour r="190" g="255" b="0"/> -->
+<colour r="223" g="255" b="0"/>
+<!-- green 14 -->
+<colour r="0" g="250" b="0"/>
+<!-- NEW greenblue  60+15 -->
+<colour r="0" g="255" b="200"/>
+<!-- NEW light blue 16  -->
+<colour r="0" g="215" b="240"/>
+<!-- darkerblue 17   -->
+<colour r="0" g="100" b="245"/>
+<!-- blue purple 18  -->
+<colour r="215" g="0" b="250"/>
+<!-- red purple  60+19   -->
+<colour r="250" g="0" b="209"/>
+<!-- that is the first 50 letters --> 
+<!-- Here I have a pale Hiragana section, for use as an additional group  resource -->
+<!-- red colour 50+10 -->
+<colour r="255" g="119" b="119"/>
+<!-- orange 50+11 -->
+<colour r="255" g="200" b="136"/>
+<!-- yel  50+12 -->
+<colour r="255" g="240" b="130"/>
+<!-- NEW lime yel/green  50+13 <colour r="190" g="255" b="0"/> -->
+<colour r="230" g="255" b="160"/>
+<!-- green 14 -->
+<colour r="100" g="255" b="120"/>
+<!-- NEW greenblue  60+15 -->
+<colour r="100" g="255" b="200"/>
+<!-- NEW light blue 16  -->
+<colour r="140" g="215" b="255"/>
+<!-- darkerblue 17   -->
+<colour r="140" g="140" b="255"/>
+<!-- blue purple 18  -->
+<colour r="215" g="110" b="255"/>
+<!-- red purple  60+19   -->
+<colour r="255" g="119" b="209"/>
+<!-- that is the first 60 letters --> 
+<!-- now 20 colours for hiragana rainbow.
+  10 and 10, almost identical, just intensity difference
+  between the two groups
+  -->
+<!-- red colour 60+10 -->
+<colour r="255" g="69" b="69"/>
+<!-- orange 60+11 -->
+<colour r="255" g="156" b="96"/>
+<!-- yel  60+12 -->
+<colour r="255" g="230" b="0"/>
+<!-- NEW lime yel/green  60+13 <colour r="190" g="255" b="0"/> -->
+<colour r="200" g="255" b="80"/>
+<!-- green 14 -->
+<colour r="0" g="247" b="20"/>
+<!-- NEW greenblue  60+15 -->
+<colour r="0" g="255" b="185"/>
+<!-- NEW light blue 16  -->
+<colour r="0" g="205" b="255"/>
+<!-- darkerblue 17   -->
+<colour r="90" g="90" b="255"/>
+<!-- blue purple 18  -->
+<colour r="195" g="90" b="255"/>
+<!-- red purple  60+19   -->
+<colour r="255" g="90" b="192"/>
+<!-- end of first 10 hiragana letter colours -->
+<!-- the second rainbow is slightly less bright -->
+<!-- red colour 70+10 -->
+<colour r="240" g="56" b="56"/>
+<!-- orange 11 r="255" g="156" b="96" -->
+<colour r="240" g="145" b="80"/>
+<!-- yel  12  r="255" g="230" b="0"  or dirty yellow r="240" g="220" b="0" -->
+<colour r="255" g="230" b="110"/>
+<!-- NEW yel/green  13   r="190" g="255" b="0"  <colour r="176" g="240" b="0"/> -->
+<colour r="186" g="248" b="0"/>
+<!-- green 14 -->
+<colour r="0" g="240" b="0"/>
+<!-- NEW greenblue  15 -->
+<colour r="0" g="240" b="177"/>
+<!-- NEW light blue  -->
+<colour r="0" g="189" b="240"/>
+<!-- darkerblue 17   -->
+<colour r="90" g="70" b="230"/>
+<!-- blue purple 18 (19 is biggest colour used by hiragana) -->
+<colour r="182" g="72" b="235"/>
+<!-- red purple  70+19   -->
+<colour r="235" g="72" b="182"/>
+<!-- end of first 20 hiragana letter colours -->
+<!-- 20 shades of pink and grey useful for punctuation -->
+<!-- pink recommend using all five periodically -->
+<!-- pinks 90 91 92 93 94 --> 
+<!-- pink  used by old Hiragana  90  had g,b 192 -->
+<colour r="255" g="172" b="172"/>
+<colour r="255" g="132" b="132"/>
+<colour r="255" g="192" b="192"/>
+<colour r="255" g="154" b="154"/>
+<colour r="255" g="210" b="210"/>
+<!-- greys: recommend using 95..99 periodically (five colours) -->
+<!-- light grey 95   -->
+<colour r="170" g="170" b="170"/>
+<!--  dark grey 96  -->
+<colour r="120" g="120" b="120"/>
+<!--  grey  97  -->
+<colour r="195" g="195" b="195"/>
+<!--  v light grey  98  -->
+<colour r="145" g="145" b="145"/>
+<!--  v light grey  99  -->
+<colour r="220" g="220" b="220"/>
+<!-- slate blues     100  101 102 103 104  -->
+<colour r="142" g="172" b="222"/>
+<colour r="110" g="130" b="188"/>
+<colour r="170" g="200" b="232"/>
+<colour r="114" g="154" b="204"/>
+<colour r="200" g="228" b="243"/>
+<!-- light purple  used by old hiragana, (182) in 5 shades 105 106 107 108 109  -->
+<colour r="255" g="145" b="255"/>
+<colour r="255" g="82"  b="255"/>
+<colour r="255" g="162" b="255"/>
+<colour r="255" g="128" b="255"/>
+<colour r="255" g="182" b="255"/>
+<!-- end of first 90 letter colours -->
+<!-- groups (110-129)-->
+<!-- slate blue  110  -->
+<colour r="100" g="155" b="200"/>
+<!-- yellow = capitals 111  -->
+<colour r="255" g="255" b="0"/>
+<!-- NOW GREEN - was dark red 112  (punctuation 112 is usually green)  -->
+<colour r="0" g="200" b="0"/>
+<!-- NOW RED   - was green 113 - (red 113 usually used for numbers) -->
+<colour r="255" g="0" b="0"/>
+<!-- dark purple  114 -->
+<colour r="200" g="0" b="200"/>
+<!-- khaki (as used in english)  115 -->
+<colour r="155" g="205" b="155"/>
+ <!-- pink as used by old Hiragana  115-119  (116-120?) -->
+<colour r="255" g="172" b="172"/>
+<colour r="255" g="132" b="132"/>
+<!-- pink  19  used by old Hiragana  -->
+<colour r="255" g="192" b="192"/>
+<colour r="255" g="154" b="154"/>
+<colour r="255" g="210" b="210"/>
+<!-- light purple as used by old hiragana 120-124 five shades  -->
+<colour r="255" g="145" b="255"/>
+<colour r="255" g="82"  b="255"/>
+<colour r="255" g="162" b="255"/>
+<!-- light purple 18 used by old hiragana  -->
+<colour r="255" g="128" b="255"/>
+<colour r="255" g="182" b="255"/>
+<!-- FIVE greys 125-129 for use in groups, identical to five in the punctuation letters area --> 
+<!-- light grey 125   -->
+<colour r="170" g="170" b="170"/>
+<!--  dark grey 126  -->
+<colour r="120" g="120" b="120"/>
+<!--  grey  127  -->
+<colour r="195" g="195" b="195"/>
+<!--  v light grey  128  -->
+<colour r="145" g="145" b="145"/>
+<!--  v light grey  129  -->
+<colour r="220" g="220" b="220"/>
+<!-- end of groups -->
+<!-- currently unused (130-137) -->
+<colour r="255" g="128" b="255"/>
+<colour r="255" g="192" b="192"/>
+<!-- light grey  -->
+<colour r="192" g="192" b="192"/>
+<!--  orange, pink, and fluorescent green; to be used for decorations like arrows  -->
+<colour r="255" g="160" b="100"/>
+<colour r="255" g="100" b="204"/>
+<colour r="200" g="255" b="20"/>
+<colour r="150" g="255" b="50"/>
+<!-- and that ^^ is 137 -->
+<!-- alternate colours, used in alternation with the ones above -->
+<!-- alternate control node -->
+<colour r="80" g="80" b="80"/>
+<!-- alternate space -->
+<colour r="255" g="255" b="255"/>
+<!-- alternate colours for letters (140-239) -->
+<colour r="255" g="119" b="119"/>
+<colour r="245" g="0" b="0"/>
+<colour r="255" g="69" b="69"/>
+<colour r="249" g="139" b="0"/>
+<colour r="255" g="156" b="96"/>
+<colour r="255" g="200" b="136"/>
+<colour r="255" g="230" b="0"/>
+<colour r="255" g="250" b="0"/>
+<colour r="255" g="240" b="130"/>
+<colour r="230" g="255" b="160"/>
+<colour r="223" g="255" b="0"/>
+<colour r="200" g="255" b="80"/>
+<colour r="0" g="250" b="0"/>
+<colour r="0" g="247" b="20"/>
+<colour r="100" g="255" b="120"/>
+<colour r="100" g="255" b="200"/>
+<colour r="0" g="255" b="185"/>
+<colour r="0" g="255" b="200"/>
+<colour r="0" g="215" b="240"/>
+<colour r="140" g="215" b="255"/>
+<colour r="0" g="205" b="255"/>
+<colour r="90" g="90" b="255"/>
+<colour r="0" g="100" b="245"/>
+<colour r="140" g="140" b="255"/>
+<colour r="195" g="90" b="255"/>
+<colour r="215" g="110" b="255"/>
+<colour r="255" g="119" b="209"/>
+<colour r="215" g="0" b="250"/>
+<colour r="250" g="0" b="209"/>
+<colour r="255" g="90" b="192"/>
+<!-- end of first 30 letters -->
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<!-- end of 60 letters -->
+<!-- red colour 10 -->
+<colour r="255" g="69" b="69"/>
+<!-- orange 11 -->
+<colour r="255" g="156" b="96"/>
+<!-- yel  12 -->
+<colour r="255" g="230" b="0"/>
+<!-- NEW yel/green  13 -->
+<colour r="200" g="255" b="80"/>
+<!-- green 14 -->
+<colour r="0" g="247" b="20"/>
+<!-- NEW greenblue  15 -->
+<colour r="0" g="255" b="185"/>
+<!-- NEW light blue 16  -->
+<colour r="0" g="205" b="255"/>
+<!-- darkerblue 17   -->
+<colour r="90" g="90" b="255"/>
+<!-- blue purple 18 (19 is biggest colour used by hiragana) -->
+<colour r="195" g="90" b="255"/>
+<!-- red purple  19   -->
+<colour r="255" g="90" b="192"/>
+<!-- end of first 10 letter colours -->
+<!-- the second rainbow is slightly less bright -->
+<!-- red colour 70+10 -->
+<colour r="240" g="56" b="56"/>
+<!-- orange 11 r="255" g="156" b="96" -->
+<colour r="240" g="145" b="80"/>
+<!-- yel  12  r="255" g="230" b="0" -->
+<colour r="255" g="230" b="110"/>
+<!-- NEW yel/green  13   r="190" g="255" b="0" -->
+<colour r="186" g="248" b="50"/>
+<!-- green 14 -->
+<colour r="0" g="240" b="0"/>
+<!-- NEW greenblue  15 -->
+<colour r="0" g="240" b="177"/>
+<!-- NEW light blue  -->
+<colour r="0" g="189" b="240"/>
+<!-- darkerblue 17   -->
+<colour r="90" g="70" b="230"/>
+<!-- blue purple 18 (19 is biggest colour used by hiragana) -->
+<colour r="182" g="72" b="235"/>
+<!-- red purple  70+19   -->
+<colour r="235" g="72" b="182"/>
+<!-- end of first 20 hiragana letter colours -->
+<!-- end of  20 hiragana  letter colours -->
+<!-- 20 shades of pink and grey useful for punctuation -->
+<!-- pink  used by old Hiragana  90  was 192 -->
+<!-- other  pinks 91 92 93 94 --> 
+<colour r="255" g="172" b="172"/>
+<colour r="255" g="132" b="132"/>
+<colour r="255" g="192" b="192"/>
+<colour r="255" g="154" b="154"/>
+<colour r="255" g="210" b="210"/>
+<!-- greys: recommend using 95..99 periodically (five colours) -->
+<!-- light grey 95   -->
+<colour r="170" g="170" b="170"/>
+<!--  dark grey 96  -->
+<colour r="120" g="120" b="120"/>
+<!--  grey  97  -->
+<colour r="195" g="195" b="195"/>
+<!--  v light grey  98  -->
+<colour r="145" g="145" b="145"/>
+<!--  v light grey  99  -->
+<colour r="220" g="220" b="220"/>
+<!-- slate blues     100  101 102 103 104  -->
+<colour r="142" g="172" b="222"/>
+<colour r="110" g="130" b="188"/>
+<colour r="170" g="200" b="232"/>
+<colour r="114" g="154" b="204"/>
+<colour r="200" g="228" b="243"/>
+<!-- light purple  105-109 used by old hiragana, in 5 shades  -->
+<colour r="255" g="145" b="255"/>
+<colour r="255" g="82"  b="255"/>
+<colour r="255" g="162" b="255"/>
+<colour r="255" g="128" b="255"/>
+<colour r="255" g="182" b="255"/>
+<!-- end of first 90 letter colours -->
+<!-- Control mode colours -->
+<!-- Green (240) -->
+<colour r="0" g="255" b="0"/>
+<!-- Amber (241) -->
+<colour r="240" g="240" b="0"/>
+<!-- Red (242) -->
+<colour r="255" g="0" b="0"/>
+</palette>
+</colours>

Added: trunk/java/dasher/applet/system.rc/colour.thai.xml
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/system.rc/colour.thai.xml	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,448 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE colours SYSTEM "colour.dtd">
+<?xml-stylesheet type="text/xsl" href="colour.xsl"?>
+<colours>
+<palette name="Thai">
+<!-- Summary: 
+ Letters 10-109 are divided up as follows:
+   10-50: Coloured with high, mid, and low tone groups
+   70-79: 10 Hiragana rainbow colours
+   80-89: 10 Hiragana rainbow colours, slightly different shades
+   90-: Distinctive Colours recommended for use in Punctuation, numerals
+       90-94: five shades of pink, can be used periodically 
+       95-99: five shades of grey, can be used periodically 
+       100-104: redundant; filled with greys at the moment
+       105-109: five shades of purple, can be used periodically
+ Groups:
+    110-113: contain the yellow, green, red groups used in European alphabets
+    115-129: other group colour schemes for use when there are many groups
+       115-119: pinks
+       120-124: purples
+       125-129:  greys
+  -->
+<!-- background 0 -->
+<colour r="255" g="255" b="255"/>
+<!-- mouse line 1 (red) -->
+<colour r="255" g="0" b="0"/>
+<!-- mouse position 2 (black) -->
+<colour r="0" g="0" b="0"/>
+<!-- box outlines 3 (grey) -->
+<colour r="218" g="218" b="218"/>
+<!-- text 4 (black) -->
+<colour r="0" g="0" b="0"/>
+<!-- crosshairs 5 (black) -->
+<colour r="0" g="0" b="0"/>
+<!-- keyboard positioning 6 (black) -->
+<colour r="0" g="0" b="0"/>
+<!-- root node 7 (soft green) -->
+<colour r="180" g="238" b="180"  />
+<!-- control node 8 (dark grey ) -->
+<colour r="80" g="80" b="80"/>
+<!-- space 9  (off-white)  -->
+<colour r="235" g="235" b="235"/>
+<!-- letters (10-109) -->
+<!--
+  The colours for hi, middle, low tone will be chosen from
+
+  Blue is high  
+  bright cyan       <colour r="0" g="255" b="255"/>
+  medium blue       <colour r="135" g="206" b="255"/>
+some slate blues of which the last is lightest
+<colour r="142" g="172" b="222"/>
+<colour r="110" g="130" b="188"/>
+<colour r="170" g="200" b="232"/>
+<colour r="114" g="154" b="204"/>
+<colour r="200" g="228" b="243"/>
+
+mid: 
+  magenta           <colour r="255" g="187" b="255"/>
+<colour r="255" g="145" b="255"/>
+<colour r="255" g="82"  b="255"/>
+<colour r="255" g="162" b="255"/>
+<colour r="255" g="128" b="255"/>
+<colour r="255" g="182" b="255"/>
+
+low
+  soft salmon pink  <colour r="255" g="174" b="185"/>
+  some more sand/pinks
+<colour r="255" g="172" b="172"/>
+<colour r="255" g="132" b="132"/>
+<colour r="255" g="192" b="192"/>
+<colour r="255" g="154" b="154"/>
+<colour r="255" g="210" b="210"/>
+  
+Unassigned:   
+  khaki             <colour r="180" g="238" b="180"/>
+
+-->
+<!-- thai colour scheme -->
+<colour r="255" g="187" b="255" note="10 middle-tone 0E01 KO KAI"/>		     
+<colour r="200" g="228" b="243" note="11 high-tone 0E02 KHO KHAI"/>		     
+<colour r="170" g="200" b="232" note="12 high-tone 0E03 KHO KHUAT  UNUSED?"/>	     
+<colour r="255" g="174" b="185" note="13 low-tone 0E04 KHO KHWAI "/>		     
+<colour r="255" g="210" b="210" note="14 low-tone 0E05 KHO KHON    UNUSED?"/>	     
+<colour r="255" g="154" b="154" note="15 low-tone 0E06 KHO RAKHANG"/>		     
+<colour r="255" g="174" b="185" note="16 low-tone 0E07 NGO NGU"/>		     
+<colour r="255" g="187" b="255" note="17 middle-tone 0E08 CHO CHAN"/>		     
+<colour r="200" g="228" b="243" note="18 high-tone 0E09 CHO CHING"/>		     
+<colour r="255" g="174" b="185" note="19 low-tone 0E0A CHO CHANG"/>		     
+<colour r="255" g="210" b="210" note="20 low-tone 0E0B SO SO"/>		     
+<colour r="255" g="154" b="154" note="21 low-tone 0E0C CHO CHOE"/>		     
+<colour r="255" g="174" b="185" note="22 low-tone 0E0D YO YING"/>		     
+<colour r="255" g="187" b="255" note="23 middle-tone 0E0E DO CHADA"/>		     
+<colour r="255" g="128" b="255" note="24 middle-tone 0E0F TO PATAK"/>		     
+<colour r="200" g="228" b="243" note="25 high-tone 0E10 THO THAN"/>		     
+<colour r="255" g="174" b="185" note="26 low-tone 0E11 THO NANGMONTHO"/>	     
+<colour r="255" g="210" b="210" note="27 low-tone 0E12 THO PHUTHAO"/>		     
+<colour r="255" g="154" b="154" note="28 low-tone 0E13 NO NEN"/>		     
+<colour r="255" g="187" b="255" note="29 middle-tone 0E14 DO DEK"/>		     
+<colour r="255" g="128" b="255" note="30 middle-tone 0E15 TO TAO"/>		     
+<colour r="200" g="228" b="243" note="31 high-tone 0E16 THO THUNG"/>		     
+<colour r="255" g="174" b="185" note="32 low-tone 0E17 THO THAHAN"/>		     
+<colour r="255" g="210" b="210" note="33 low-tone 0E18 THO THONG"/>		     
+<colour r="255" g="154" b="154" note="34 low-tone 0E19 NO NU"/>		     
+<colour r="255" g="187" b="255" note="35 middle-tone 0E1A BO BAIMAI"/>		     
+<colour r="255" g="128" b="255" note="36 middle-tone 0E1B PO PLA"/>		     
+<colour r="200" g="228" b="243" note="37 high-tone 0E1C PHO PHUNG"/>		     
+<colour r="170" g="200" b="232" note="38 high-tone 0E1D FO FA"/>		     
+<colour r="255" g="174" b="185" note="39 low-tone 0E1E PHO PHAN"/>		     
+<colour r="255" g="210" b="210" note="40 low-tone 0E1F FO FAN"/>		     
+<colour r="255" g="154" b="154" note="41 low-tone 0E20 PHO SAMPHAO"/>		     
+<colour r="255" g="174" b="185" note="42 low-tone 0E21 MO MA"/>		     
+<colour r="255" g="210" b="210" note="43 low-tone 0E22 YO YAK"/>		     
+<colour r="255" g="154" b="154" note="44 low-tone 0E23 RO RUA"/>		     
+<colour r="180" g="238" b="180" note="45 0E24 RU      WHAT TONE GROUP?"/>	     
+<colour r="255" g="174" b="185" note="46 low-tone 0E25 LO LING"/>		     
+<colour r="180" g="238" b="180" note="47 0E26 LU    UNUSED?"/>			     
+<colour r="255" g="174" b="185" note="48 low-tone 0E27 WO WAEN"/>		     
+<colour r="200" g="228" b="243" note="49 high-tone 0E28 SO SALA"/>		     
+<colour r="170" g="200" b="232" note="50 high-tone 0E29 SO RUSI"/>		     
+<colour r="0" g="255" b="255"   note="51 high-tone 0E2A SO SUA"/>		     
+<colour r="200" g="228" b="243" note="52 high-tone 0E2B HO HIP"/>		     
+<colour r="255" g="174" b="185" note="53 low-tone 0E2C LO CHULA"/>		     
+<colour r="255" g="187" b="255" note="54 middle-tone 0E2D O ANG (null consonant)"/> 
+<colour r="255" g="174" b="185" note="55 low-tone 0E2E HO NOKHUK"/>
+<!-- from here on, leave Euro/Asian colours -->
+<colour r="0" g="215" b="240"/>
+<colour r="0" g="100" b="245"/>
+<colour r="215" g="0" b="250"/>
+<colour r="250" g="0" b="209"/>
+<!-- that is the first 50 letters --> 
+<!-- Here I have a pale Hiragana section, for use as an additional group  resource -->
+<!-- red colour 50+10 -->
+<colour r="255" g="119" b="119"/>
+<!-- orange 50+11 -->
+<colour r="255" g="200" b="136"/>
+<!-- yel  50+12 -->
+<colour r="255" g="240" b="130"/>
+<!-- NEW lime yel/green  50+13 <colour r="190" g="255" b="0"/> -->
+<colour r="230" g="255" b="160"/>
+<!-- green 14 -->
+<colour r="100" g="255" b="120"/>
+<!-- NEW greenblue  60+15 -->
+<colour r="100" g="255" b="200"/>
+<!-- NEW light blue 16  -->
+<colour r="140" g="215" b="255"/>
+<!-- darkerblue 17   -->
+<colour r="140" g="140" b="255"/>
+<!-- blue purple 18  -->
+<colour r="215" g="110" b="255"/>
+<!-- red purple  60+19   -->
+<colour r="255" g="119" b="209"/>
+<!-- that is the first 60 letters --> 
+<!-- now 20 colours for hiragana rainbow.
+  10 and 10, almost identical, just intensity difference
+  between the two groups
+  -->
+<!-- red colour 60+10 -->
+<colour r="255" g="69" b="69"/>
+<!-- orange 60+11 -->
+<colour r="255" g="156" b="96"/>
+<!-- yel  60+12 -->
+<colour r="255" g="230" b="0"/>
+<!-- NEW lime yel/green  60+13 <colour r="190" g="255" b="0"/> -->
+<colour r="200" g="255" b="80"/>
+<!-- green 14 -->
+<colour r="0" g="247" b="20"/>
+<!-- NEW greenblue  60+15 -->
+<colour r="0" g="255" b="185"/>
+<!-- NEW light blue 16  -->
+<colour r="0" g="205" b="255"/>
+<!-- darkerblue 17   -->
+<colour r="90" g="90" b="255"/>
+<!-- blue purple 18  -->
+<colour r="195" g="90" b="255"/>
+<!-- red purple  60+19   -->
+<colour r="255" g="90" b="192"/>
+<!-- end of first 10 hiragana letter colours -->
+<!-- the second rainbow is slightly less bright -->
+<!-- red colour 70+10 -->
+<colour r="240" g="56" b="56"/>
+<!-- orange 11 r="255" g="156" b="96" -->
+<colour r="240" g="145" b="80"/>
+<!-- yel  12  r="255" g="230" b="0"  or dirty yellow r="240" g="220" b="0" -->
+<colour r="255" g="230" b="110"/>
+<!-- NEW yel/green  13   r="190" g="255" b="0"  <colour r="176" g="240" b="0"/> -->
+<colour r="186" g="248" b="0"/>
+<!-- green 14 -->
+<colour r="0" g="240" b="0"/>
+<!-- NEW greenblue  15 -->
+<colour r="0" g="240" b="177"/>
+<!-- NEW light blue  -->
+<colour r="0" g="189" b="240"/>
+<!-- darkerblue 17   -->
+<colour r="90" g="70" b="230"/>
+<!-- blue purple 18 (19 is biggest colour used by hiragana) -->
+<colour r="182" g="72" b="235"/>
+<!-- red purple  70+19   -->
+<colour r="235" g="72" b="182"/>
+<!-- end of first 20 hiragana letter colours -->
+<!-- 20 shades of pink and grey useful for punctuation -->
+<!-- pink recommend using all five periodically -->
+<!-- pinks 90 91 92 93 94 --> 
+<!-- pink  used by old Hiragana  90  had g,b 192 -->
+<colour r="255" g="172" b="172"/>
+<colour r="255" g="132" b="132"/>
+<colour r="255" g="192" b="192"/>
+<colour r="255" g="154" b="154"/>
+<colour r="255" g="210" b="210"/>
+<!-- greys: recommend using 95..99 periodically (five colours) -->
+<!-- light grey 95   -->
+<colour r="170" g="170" b="170"/>
+<!--  dark grey 96  -->
+<colour r="120" g="120" b="120"/>
+<!--  grey  97  -->
+<colour r="195" g="195" b="195"/>
+<!--  v light grey  98  -->
+<colour r="145" g="145" b="145"/>
+<!--  v light grey  99  -->
+<colour r="220" g="220" b="220"/>
+<!-- slate blues     100  101 102 103 104  -->
+<colour r="142" g="172" b="222"/>
+<colour r="110" g="130" b="188"/>
+<colour r="170" g="200" b="232"/>
+<colour r="114" g="154" b="204"/>
+<colour r="200" g="228" b="243"/>
+<!-- light purple  used by old hiragana, (182) in 5 shades 105 106 107 108 109  -->
+<colour r="255" g="145" b="255"/>
+<colour r="255" g="82"  b="255"/>
+<colour r="255" g="162" b="255"/>
+<colour r="255" g="128" b="255"/>
+<colour r="255" g="182" b="255"/>
+<!-- end of first 90 letter colours -->
+<!-- groups (110-129)-->
+<!-- slate blue  110  -->
+<colour r="100" g="155" b="200"/>
+<!-- yellow = capitals 111  -->
+<colour r="255" g="255" b="0"/>
+<!-- NOW GREEN - was dark red 112  (punctuation 112 is usually green)  -->
+<colour r="0" g="200" b="0"/>
+<!-- NOW RED   - was green 113 - (red 113 usually used for numbers) -->
+<colour r="255" g="0" b="0"/>
+<!-- dark purple  114 -->
+<colour r="200" g="0" b="200"/>
+<!-- khaki (as used in english)  115 -->
+<colour r="155" g="205" b="155"/>
+ <!-- pink as used by old Hiragana  115-119  (116-120?) -->
+<colour r="255" g="172" b="172"/>
+<colour r="255" g="132" b="132"/>
+<!-- pink  19  used by old Hiragana  -->
+<colour r="255" g="192" b="192"/>
+<colour r="255" g="154" b="154"/>
+<colour r="255" g="210" b="210"/>
+<!-- light purple as used by old hiragana 120-124 five shades  -->
+<colour r="255" g="145" b="255"/>
+<colour r="255" g="82"  b="255"/>
+<colour r="255" g="162" b="255"/>
+<!-- light purple 18 used by old hiragana  -->
+<colour r="255" g="128" b="255"/>
+<colour r="255" g="182" b="255"/>
+<!-- FIVE greys 125-129 for use in groups, identical to five in the punctuation letters area --> 
+<!-- light grey 125   -->
+<colour r="170" g="170" b="170"/>
+<!--  dark grey 126  -->
+<colour r="120" g="120" b="120"/>
+<!--  grey  127  -->
+<colour r="195" g="195" b="195"/>
+<!--  v light grey  128  -->
+<colour r="145" g="145" b="145"/>
+<!--  v light grey  129  -->
+<colour r="220" g="220" b="220"/>
+<!-- end of groups -->
+<!-- currently unused (130-137) -->
+<colour r="255" g="128" b="255"/>
+<colour r="255" g="192" b="192"/>
+<!-- light grey  -->
+<colour r="192" g="192" b="192"/>
+<!--  orange, pink, and fluorescent green; to be used for decorations like arrows  -->
+<colour r="255" g="160" b="100"/>
+<colour r="255" g="100" b="204"/>
+<colour r="200" g="255" b="20"/>
+<colour r="150" g="255" b="50"/>
+<!-- and that ^^ is 137 -->
+<!-- alternate colours, used in alternation with the ones above -->
+<!-- alternate control node -->
+<colour r="80" g="80" b="80"/>
+<!-- alternate space -->
+<colour r="255" g="255" b="255"/>
+<!-- alternate colours for letters (140-239) -->
+<colour r="255" g="187" b="255" note="10 middle-tone 0E01 KO KAI"/>		     
+<colour r="200" g="228" b="243" note="11 high-tone 0E02 KHO KHAI"/>		     
+<colour r="170" g="200" b="232" note="12 high-tone 0E03 KHO KHUAT  UNUSED?"/>	     
+<colour r="255" g="174" b="185" note="13 low-tone 0E04 KHO KHWAI "/>		     
+<colour r="255" g="210" b="210" note="14 low-tone 0E05 KHO KHON    UNUSED?"/>	     
+<colour r="255" g="154" b="154" note="15 low-tone 0E06 KHO RAKHANG"/>		     
+<colour r="255" g="174" b="185" note="16 low-tone 0E07 NGO NGU"/>		     
+<colour r="255" g="187" b="255" note="17 middle-tone 0E08 CHO CHAN"/>		     
+<colour r="200" g="228" b="243" note="18 high-tone 0E09 CHO CHING"/>		     
+<colour r="255" g="174" b="185" note="19 low-tone 0E0A CHO CHANG"/>		     
+<colour r="255" g="210" b="210" note="20 low-tone 0E0B SO SO"/>		     
+<colour r="255" g="154" b="154" note="21 low-tone 0E0C CHO CHOE"/>		     
+<colour r="255" g="174" b="185" note="22 low-tone 0E0D YO YING"/>		     
+<colour r="255" g="187" b="255" note="23 middle-tone 0E0E DO CHADA"/>		     
+<colour r="255" g="128" b="255" note="24 middle-tone 0E0F TO PATAK"/>		     
+<colour r="200" g="228" b="243" note="25 high-tone 0E10 THO THAN"/>		     
+<colour r="255" g="174" b="185" note="26 low-tone 0E11 THO NANGMONTHO"/>	     
+<colour r="255" g="210" b="210" note="27 low-tone 0E12 THO PHUTHAO"/>		     
+<colour r="255" g="154" b="154" note="28 low-tone 0E13 NO NEN"/>		     
+<colour r="255" g="187" b="255" note="29 middle-tone 0E14 DO DEK"/>		     
+<colour r="255" g="128" b="255" note="30 middle-tone 0E15 TO TAO"/>		     
+<colour r="200" g="228" b="243" note="31 high-tone 0E16 THO THUNG"/>		     
+<colour r="255" g="174" b="185" note="32 low-tone 0E17 THO THAHAN"/>		     
+<colour r="255" g="210" b="210" note="33 low-tone 0E18 THO THONG"/>		     
+<colour r="255" g="154" b="154" note="34 low-tone 0E19 NO NU"/>		     
+<colour r="255" g="187" b="255" note="35 middle-tone 0E1A BO BAIMAI"/>		     
+<colour r="255" g="128" b="255" note="36 middle-tone 0E1B PO PLA"/>		     
+<colour r="200" g="228" b="243" note="37 high-tone 0E1C PHO PHUNG"/>		     
+<colour r="170" g="200" b="232" note="38 high-tone 0E1D FO FA"/>		     
+<colour r="255" g="174" b="185" note="39 low-tone 0E1E PHO PHAN"/>		     
+<colour r="255" g="210" b="210" note="40 low-tone 0E1F FO FAN"/>		     
+<colour r="255" g="154" b="154" note="41 low-tone 0E20 PHO SAMPHAO"/>		     
+<colour r="255" g="174" b="185" note="42 low-tone 0E21 MO MA"/>		     
+<colour r="255" g="210" b="210" note="43 low-tone 0E22 YO YAK"/>		     
+<colour r="255" g="154" b="154" note="44 low-tone 0E23 RO RUA"/>		     
+<colour r="180" g="238" b="180" note="45 0E24 RU      WHAT TONE GROUP?"/>	     
+<colour r="255" g="174" b="185" note="46 low-tone 0E25 LO LING"/>		     
+<colour r="180" g="238" b="180" note="47 0E26 LU    UNUSED?"/>			     
+<colour r="255" g="174" b="185" note="48 low-tone 0E27 WO WAEN"/>		     
+<colour r="200" g="228" b="243" note="49 high-tone 0E28 SO SALA"/>		     
+<colour r="170" g="200" b="232" note="50 high-tone 0E29 SO RUSI"/>		     
+<colour r="0" g="255" b="255"   note="51 high-tone 0E2A SO SUA"/>		     
+<colour r="200" g="228" b="243" note="52 high-tone 0E2B HO HIP"/>		     
+<colour r="255" g="174" b="185" note="53 low-tone 0E2C LO CHULA"/>		     
+<colour r="255" g="187" b="255" note="54 middle-tone 0E2D O ANG (null consonant)"/> 
+<colour r="255" g="174" b="185" note="55 low-tone 0E2E HO NOKHUK"/>
+<!-- from here on, leave Euro/Asian colours -->
+<colour r="255" g="174" b="185"/>
+<colour r="255" g="187" b="255"/>
+<colour r="135" g="206" b="255"/>
+<colour r="255" g="174" b="185"/>
+<!-- that is the first 50 letters --> 
+<!-- Here I have a DARK, INTENSE Hiragana section, for use as an additional group  resource. Used to be known as 50-59.
+     Now known as 130+60 = 190-199 -->
+<!-- red colour 50+10 -->
+<colour r="245" g="0" b="0"/>
+<!-- orange 50+11 -->
+<colour r="249" g="139" b="0"/>
+<!-- yel  50+12 -->
+<colour r="255" g="250" b="0"/>
+<!-- NEW lime yel/green  50+13 <colour r="190" g="255" b="0"/> -->
+<colour r="223" g="255" b="0"/>
+<!-- green 14 -->
+<colour r="0" g="250" b="0"/>
+<!-- NEW greenblue  60+15 -->
+<colour r="0" g="255" b="200"/>
+<!-- NEW light blue 16  -->
+<colour r="0" g="215" b="240"/>
+<!-- darkerblue 17   -->
+<colour r="0" g="100" b="245"/>
+<!-- blue purple 18  -->
+<colour r="215" g="0" b="250"/>
+<!-- red purple  60+19   -->
+<colour r="250" g="0" b="209"/>
+<!-- end of 60 letters -->
+<!-- red colour 10 -->
+<colour r="255" g="69" b="69"/>
+<!-- orange 11 -->
+<colour r="255" g="156" b="96"/>
+<!-- yel  12 -->
+<colour r="255" g="230" b="0"/>
+<!-- NEW yel/green  13 -->
+<colour r="200" g="255" b="80"/>
+<!-- green 14 -->
+<colour r="0" g="247" b="20"/>
+<!-- NEW greenblue  15 -->
+<colour r="0" g="255" b="185"/>
+<!-- NEW light blue 16  -->
+<colour r="0" g="205" b="255"/>
+<!-- darkerblue 17   -->
+<colour r="90" g="90" b="255"/>
+<!-- blue purple 18 (19 is biggest colour used by hiragana) -->
+<colour r="195" g="90" b="255"/>
+<!-- red purple  19   -->
+<colour r="255" g="90" b="192"/>
+<!-- end of first 10 letter colours -->
+<!-- the second rainbow is slightly less bright -->
+<!-- red colour 70+10 -->
+<colour r="240" g="56" b="56"/>
+<!-- orange 11 r="255" g="156" b="96" -->
+<colour r="240" g="145" b="80"/>
+<!-- yel  12  r="255" g="230" b="0" -->
+<colour r="255" g="230" b="110"/>
+<!-- NEW yel/green  13   r="190" g="255" b="0" -->
+<colour r="186" g="248" b="50"/>
+<!-- green 14 -->
+<colour r="0" g="240" b="0"/>
+<!-- NEW greenblue  15 -->
+<colour r="0" g="240" b="177"/>
+<!-- NEW light blue  -->
+<colour r="0" g="189" b="240"/>
+<!-- darkerblue 17   -->
+<colour r="90" g="70" b="230"/>
+<!-- blue purple 18 (19 is biggest colour used by hiragana) -->
+<colour r="182" g="72" b="235"/>
+<!-- red purple  70+19   -->
+<colour r="235" g="72" b="182"/>
+<!-- end of first 20 hiragana letter colours -->
+<!-- end of  20 hiragana  letter colours -->
+<!-- 20 shades of pink and grey useful for punctuation -->
+<!-- pink  used by old Hiragana  90  was 192 -->
+<!-- other  pinks 91 92 93 94 --> 
+<colour r="255" g="172" b="172"/>
+<colour r="255" g="132" b="132"/>
+<colour r="255" g="192" b="192"/>
+<colour r="255" g="154" b="154"/>
+<colour r="255" g="210" b="210"/>
+<!-- greys: recommend using 95..99 periodically (five colours) -->
+<!-- light grey 95   -->
+<colour r="170" g="170" b="170"/>
+<!--  dark grey 96  -->
+<colour r="120" g="120" b="120"/>
+<!--  grey  97  -->
+<colour r="195" g="195" b="195"/>
+<!--  v light grey  98  -->
+<colour r="145" g="145" b="145"/>
+<!--  v light grey  99  -->
+<colour r="220" g="220" b="220"/>
+<!-- slate blues     100  101 102 103 104  -->
+<colour r="142" g="172" b="222"/>
+<colour r="110" g="130" b="188"/>
+<colour r="170" g="200" b="232"/>
+<colour r="114" g="154" b="204"/>
+<colour r="200" g="228" b="243"/>
+<!-- light purple  105-109 used by old hiragana, in 5 shades  -->
+<colour r="255" g="145" b="255"/>
+<colour r="255" g="82"  b="255"/>
+<colour r="255" g="162" b="255"/>
+<colour r="255" g="128" b="255"/>
+<colour r="255" g="182" b="255"/>
+<!-- end of first 90 letter colours -->
+<!-- Control mode colours -->
+<!-- Green (240) -->
+<colour r="0" g="255" b="0"/>
+<!-- Amber (241) -->
+<colour r="240" g="240" b="0"/>
+<!-- Red (242) -->
+<colour r="255" g="0" b="0"/>
+</palette>
+</colours>

Added: trunk/java/dasher/applet/system.rc/training_english_GB.txt
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/system.rc/training_english_GB.txt	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,664 @@
+hello there! Hi. 
+The Dasher Project. Dasher is an information-efficient text-entry interface, driven by natural continuous pointing gestures.
+Dasher is a competitive text-entry system wherever a full-size keyboard cannot be used - for example, (1) on a palmtop computer; (2) on a wearable computer; (3) when operating a computer one-handed, by joystick, touchscreen, trackball, or mouse; (4) when operating a computer with zero hands (i.e., by eyetracker).
+We expect the eyetracking  version of Dasher to be an especially big hit,  as it allows the user to write text as fast as normal handwriting.
+Dasher is fast, efficient, easy to learn, and fun to use.
+<em>Dasher is like an arcade game: `Attack of the killer alphabets', perhaps.</em>
+<small>Financial Times, 5th February 2002</small>.
+Dasher is a zooming interface. You point  where you want to go, and the display zooms in  wherever you point.
+The world into which you are zooming is painted with  letters, so that any point you zoom in on corresponds to a piece of text.
+The more you zoom in, the longer the piece of text you have written. You choose what you write by choosing where to zoom.
+To make the interface efficient, our software uses the predictions of a language model to determine how much of the world is devoted to each piece of text.
+Probable pieces of text are given more real-estate, so they are quick and easy to select.
+Improbable pieces of text (for example, text with spelling mistakes) are given less space, so they are harder to write.
+The language model learns all the time: if you use a novel word once, it  is easier to write next time.
+A big advantage of Dasher over other predictive text-entry interfaces is that it is <b>mode-free</b>: the user does not need to switch from a writing mode to an "accept-model-predictions" mode.
+Another advantage is that it is easy to train the model	on any writing style: simply load up an example	file, then write away!
+Imagine <b>a library containing all possible books</b>, ordered alphabetically on a single shelf.
+Books in which the first letter is "a" are at the left hand side.
+Books in which the first letter is "z" are at the right.
+The first book in the "a" section reads "aaaa..."; somewhere to its right are books that start "all good things must come to an end..."; a tiny bit further to the right are books that start "all good things must come to an enema...".
+When someone writes a piece of text, their choice of the text string can be viewed as a choice of a book from this library of all books - the book that contains exactly the chosen text.
+How do they choose that book? Let's imagine they want to write "all good things..."
+First, they walk into the "a" section of the library.
+There, they are confronted by books starting "aa", "ab", 
+Looking more closely at the "al" section, they can find books starting "ala", "alb",... "alz"
+By looking ever more closely at the shelf, the writer can find the book containing the text he wishes to write.
+Thus writing can be described as  <b>zooming in on an alphabetical library, steering as you go</b>.
+This is exactly how Dasher works, except for one crucial point ...
+<em>we alter the SIZE of the shelf space devoted to each book in proportion to <b>the probability</b> of the corresponding text.</em>
+For example, not very many books start with an "x", so we devote less space to "x..." books, and more to the more plausible books, thus making it easier to find books that contain probable text.
+<h2> Tips for Novices </h2>
+<b>The single most important concept</b> that a novice user needs to understand is that one should always continue <em>inside</em> the text written so far: to select the book that contains "all" as its first word, one does <b>not</b> enter the "a" section of the library, then exit the "a" section, and enter the "l" section.
+One enters the "a" section, then finds the "al" section that is <em>within</em> the "a" section, then enters the "all" section <em>within</em> the "al" section.
+<b>The second most important idea</b> is that what you have written depends <em>only</em> on where you finally end up in the library, not on how you got there; so there is no need to steer carefully on your way to your destination. <b>You are allowed to cut corners.</b> 
+The dasher software consists of a language-modelling module, a rendering module, and a dynamics module.
+Dasher is brought to you by the Inference Group, led by David MacKay, Cavendish Laboratory, Madingley Road, Cambridge.
+The research version of the software was developed by David Ward. The project manager is Phil Cowans. 
+The Dasher project is supported by the Gatsby charitable foundation.
+The programmer's favourite phrase is Hello how are you? - or hello world. Hi hi 
+Only the crumbliest flakiest chocolate 
+London is the capital of Paris, and Paris is the capital of Rome, and Rome -- no, THAT'S all wrong, I'm certain! By contrast, the Big Bang is a beginning that is required by the dynamical laws that govern the universe. Ask jail deputies on other matters, the jury recommended that : 1 four additional deputies be employed at the Fulton County Jail and a doctor, medical intern or extern be employed for night and weekend duty at the jail. Oh, that way madness lies. There was nothing so VERY remarkable in that; nor did Juliette think it so VERY much out of the way to hear the rabbit say to itself, `Oh dear! 
+He always waxes lyrical about his school. Far out, man! It's a different planet. The supreme court justice has a swing vote. Roe versus Wade may be overturned. The court might overturn Roe versus Wade. George Bush might put up a moderate nominee. 
+I told you so. What did I tell you? I use a Nokia phone. 
+The speaker waxed lyrical about his invention's benefits. He's mad as a hatter. As any economist could have predicted, the result of all that borrowing was inflation. Henry L. Bowden was listed on the petition as the mayor's attorney. His beard was as white as snow. `I told you butter wouldn't suit the works!' he added looking angrily at the March hare. God might have created such a warped universe, but we have no reason to think that He did. 
+Bellows made the disclosure when he asked Judge Parsons to grant his client, Alan Clements, 30, a separate trial. He gets on my wick. `And what an ignorant little girl she'll think me for asking! What does the no boundary proposal predict for the future of the universe? A glutton for punishment.
+`Perhaps it doesn't understand English,' thought Juliette; `I daresay it's a French mouse, come over with William the Conqueror.' The predictions of the no boundary proposal seem to agree with observation. All Dallas members voted with Roberts, except Rep. Bill Jones, who was absent. Take with a grain of salt. `But perhaps he can't help it,' she said to herself; `his eyes are so VERY nearly at the top of his head. 
+This view had to be modified, when Heisenberg put forward his Uncertainty Principle, which said that one could not know both the position, and the speed, accurately. Indeed, she had quite a long argument with the Lory, who at last turned sulky, and would only say, `I am older than you, and must know better'; and this Laura would not allow without knowing how old it was, and, as the Lory positively refused to tell its age, there was no more to be said. We know that General Relativity can not be quite correct on very small distances, because it is a classical theory. To be or not to be, that is the question. 
+She was a good deal frightened by this very sudden change, but she felt that there was no time to be lost, as she was shrinking rapidly; so she set to work at once to eat some of the other bit. 
+His contention was denied by several bankers, including Scott Hudson of Sherman, Gaynor B. Jones of Houston, J. B. Brady of Harlingen and Howard Cox of Austin. The girl with colitis goes by. Oh! won't she be savage if I've kept her waiting!' I have not been there myself. I didn't smell a drop of liquor, and we didn't have a bit of trouble.
+I spy with my little eye. To show this diagram properly, I would really need a four dimensional screen. This is not a program of socialized medicine. Shuffle off this mortal coil. The West Texan reported that he had finally gotten Chairman Bill Hollowell of the committee to set it for public hearing on Feb. 22.
+If I had my druthers. Events before the Big Bang are simply not defined, because there's no way one could measure what happened at them. Nursing home care the aged care plan carries these benefits for persons over 65 who are under the social security and railroad retirement systems : 1 full payment of hospital bills for stays up to 90 days for each illness, except that the patient would pay $10 a day of the cost for the first nine days. Some men are born mediocre, some men achieve mediocrity, and some men, have. I shall be a great deal too far off to trouble myself about you: you must manage the best way you can; -- but I must be kind to them,' thought Laura, `or perhaps they won't walk the way I want to go! 
+The expansion will start with an inflationary phase, but the collapse will not in general end with an anti inflationary phase. He calls for help while saying he is against centralization, but you can't have it both ways, Jones said. But screw your courage to the sticking-place. The Queen turned angrily away from him, and said to the Knave `Turn them over!' They would say that UFO's come from the future, and that governments are engaged in a gigantic conspiracy to cover them up, and keep for themselves, the scientific knowledge that these visitors bring. 
+Strenuous efforts were made to remove pin pricking from administration statements. Doesn't know shit from Shinola. `I have answered three questions, and that is enough,' Said his father; `don't give yourself airs! The sideways velocities could have meant that the galaxies didn't collide, but rushed past each other, and then started to move apart. 
+In the last eight years, all Presidential appointments, including those of cabinet rank, have been denied immediate action because of a Senate rule requiring at least a 24 hour delay after they are reported to the floor.
+Forgive them for they know not what they do. * `Come, my head's free at last!' said Mary in a tone of delight, which changed into alarm in another moment, when she found that her shoulders were nowhere to be found: all she could see, when she looked down, was an immense length of neck, which seemed to rise like a stalk out of a sea of green leaves that lay far below her. They claimed that there would be no singularities in a solution of the field equations of general relativity, which was fully general, in the sense that it didn't have any exact symmetry. The largest hurdle the Republicans would have to face is a state law which says that before making a first race, one of two alternative courses must be taken : 1 five per cent of the voters in each county must sign petitions requesting that the Republicans be allowed to place names of candidates on the general election ballot, or 2 the Republicans must hold a primary under the county unit system -- a system which the party 
 opposes in its platform. Know which way the wind blows.
+It was the white rabbit returning, splendidly dressed, with a pair of white kid gloves in one hand and a large fan in the other: he came trotting along in a great hurry, muttering to himself as he came, `Oh! the Duchess, the Duchess! Genius is one percent inspiration and 99 percent perspiration. If you have a positive bank balance, you can distribute it in various ways. All you need is love. If there were a passage right the way through, like we have, the poor animal would fall apart. 
+Gorgeous Doris Day and her producer-hubby, Marty Melcher, drive in today from a motor tour thru New England. Butter wouldn't melt in her mouth. There was a young lady of Wight, who traveled much faster than light; she departed one day, in a relative way, and arrived on the previous night. Mrs. Harry K. Cohen is chairman of this phase and she is getting an artistic assist from A. Van Hollander, display director of Gimbel Brothers. There she blows! It isn't over until the fat lady sings. I will survive. 
+The jury did not elaborate, but it added that there should be periodic surveillance of the pricing practices of the concessionaires for the purpose of keeping the prices reasonable. Would you Adam and Eve it?. `Whoever lives there,' thought Mary, `it'll never do to come upon them THIS size: why, I should frighten them out of their wits!' To the French, this just confirmed their suspicions. To deal with principles the meetings in Zurich, the statement said, would deal only with principles that would guide the three factors in their search for a coalition Government.
+Men's evil manners live in brass; their virtues we write in water. `We won't talk about her any more if you'd rather not.' All the evidence points to him being an inveterate gambler, who throws the dice on every possible occasion. He broke that boy (Air Force fullback Nick Arshinkoff) in two and knocked him loose from the football. 
+He understands every word I say to him. Tony Blair misled the country over weapons of mass destruction. 
+`And yet what a dear little puppy it was!' said he, as she leant against a buttercup to rest herself, and fanned herself with one of the leaves: `I should have liked teaching it tricks very much, if -- if I'd only been the right size to do it! You look as if you've been dragged through a hedge backwards. [later editions continued as follows: When the sands are all dry, he is gay as a lark, And will talk in contemptuous tones of the Shark, But, when the tide rises and sharks are around, His voice has a timid and tremulous sound.] `That's different from what I used to say when I was a child,' said the octopus. Although quantum mechanics has been around for nearly 70 years, it is still not generally understood or appreciated, even by those that use it to do calculations. A veteran Jackson County legislator will ask the Georgia House Monday to back federal aid to education, something it has consistently opposed in the past.
+Elvis has left the building. Killed in a bar when he was only three. He who can, does; he who cannot, teaches. He will give the Devil his due. He was more famous for proving you couldn't prove everything that is true, even in such an apparently simple subject as arithmetic. 
+In 1960 more than 6,000 Communist technicians were present in those countries. More honoured in the breach than in the observance. No religious group, he declared in an interview, will receive Peace Corps funds unless it forswears all proselytizing on the project it proposes. No pain, no gain. If Barnett doesn't call a special session in 1961, it will be the first year in the last decade that the Legislature has not met in regular or special session.
+All the evidence is, that the universe started out in the Big Bang, without the kind of warping needed, to allow travel into the past. While details are still to be worked out, Ratcliff said he expects to tell home folks in Dallas why he thinks Berry's proposed constitutional amendment should be rejected. Let the cat out of the bag. There were attempts to explain away this number count graph, by claiming that some of the faint radio sources, were within our own galaxy, and so did not tell us anything about cosmology. This is being done so that Georgia Tech can complete the final phase of a traffic survey on the North Expressway.
+As you sow so shall you reap. The Louisiana city is known, of course, for its fine food, good music and its colorful hospitality and, when guests arrive at Philmont that night, says Mrs. Grinsfelder, that is exactly what we expect to offer them. No, I've made up my mind about it; if I'm Mabel, I'll stay down here! A balls up. 
+Instead, the universe has every single possible history, each with its own probability. 
+Like a chicken with its head cut off. Of course, this isn't taking into consideration the population of Nevada and New York city, but it's the way things look from here at this point. It's no skin off my nose. Certain people must have known about it. About turn.
+Then Throneberry rapped into a fast double play. Press into service. However, because of government cuts, we could manage to provide only a two dimensional screen. Pass over to the other side. This was such a new idea to her, that she was quite silent for a minute or two, which gave the Pigeon the opportunity of adding, `You're looking for eggs, I know THAT well enough; and what does it matter to me whether you're a little girl or a serpent?' 
+When they arrived at a new star, they could land on a suitable planet, and mine material to produce more machines, which could be sent on to yet more stars. The new school superintendent is Harry Davis, a veteran agriculture teacher, who defeated Felix Bush, a school principal and chairman of the Miller County Democratic Executive Committee. Turn over a new leaf. And then, some churchmen remarked, there is a more classical church-state problem : can religious agencies use Government funds and Peace Corps personnel in their projects and still preserve the constitutional requirement on separation of church and state? So the time of zero separation, would have been less than twenty billion years ago. 
+But I am not in favor of a sales or state income tax at this time, Mitchell said. It's a legend in his own life time. He could terminate special sessions of the Legislature. It's a face that only a mother could love. `And who are THESE?' said the Queen, pointing to the three gardeners who were lying round the rosetree; for, you see, as they were lying on their faces, and the pattern on their backs was the same as the rest of the pack, she could not tell whether they were gardeners, or soldiers, or courtiers, or three of her own children. 
+Put two and two together. `Here! you may nurse it a bit, if you like!' the lady said to her, flinging the baby at her as she spoke. The forsaken particle may fall into the hole as well, but it may also escape to a large distance from the hole, where it will become a real particle, that can be measured by a particle detector. The issue which may make it necessary to have a session is the highly sensitive problem of cutting the state's congressional districts from six to five to eliminate one congressional seat. 
+May you live in interesting times.
+And then a voice she had never heard before, `Sure then I'm here! The female of the species is more deadly then the male. No, it'll never do to ask: perhaps I shall see it written up somewhere.' Mr. Hawksley said he was not critical of city residents for not knowing what to do or where to assemble in case of an air attack. So she began again: `Ou est ma chatte?' which was the first sentence in her French lesson-book. 
+At first sight, all these seem possible. First blood. But there never is any need. What's in a name? That which we call a rose by any other name would smell as. Dirac was my predecessor but one, as the Lucasian Professor in Cambridge. 
+My experience as public safety commissioner, Roos said, has shown me that the office of sheriff is best filled by a man with law enforcement experience, and preferably one who is a lawyer. Just then she heard something splashing about in the pool a little way off, and she swam nearer to make out what it was: at first she thought it must be a walrus or hippopotamus, but then she remembered how small she was now, and she soon made out that it was only a mouse that had slipped in like herself. Einstein's view was what would now be called, a hidden variable theory. The famed Yankee Clipper, now retired, has been assisting as a batting coach. Now is the winter of our discontent.
+I never knew there were such neighbors and friends around me and my family. Such stuff as dreams are made on. Foods, which long had been considered recession resistant but hardly dynamic stocks, have been acting like growth stocks, going to higher price-earnings ratios. And yet I wish I could show you our cat Dinah: I think you'd take a fancy to cats if you could only see her. The navy captain disclosed also that a list of questions found in Miss Gee's purse would, if completed and handed back, have given the Kremlin a complete picture of our current anti-submarine effort and would have shown what we are doing in research and development for the future.
+But what distinguishes us from them, is the knowledge that we have accumulated over the last ten thousand years, and particularly, over the last three hundred. You MUST have meant some mischief, or else you'd have signed your name like an honest man.' But although Laplace may not have realised it, the same idea had been put forward 16 years earlier by a Cambridge man, John Mitchell, in a paper in the Philosophical Transactions of the Royal Society. No man is an island. 
+This result came as a total surprise to me, and everyone else. 
+Beats me. `Why, you don't even know what they're about!' A young man doesn't like to be driven up in front of a school in a car driven by a girl who isn't even in a higher class than he is, and is also a girl. Even Steven. `I've seen hatters before,' she said to herself; `the tiger will be much the most interesting, and perhaps as this is May it won't be raving mad -- at least not so mad as it was in March.' 
+This is probably the most remarkable discovery of modern cosmology. The most valuable player award was split three ways, among Glen Mankowski, Gordon Hartweger and Tom Kieffer. If one made a research grant application to work on time travel, it would be dismissed immediately. And oh, I wish you could see her after the birds! People will continue to get older, even after the universe has begun to contract. 
+He was a man after his own heart. Seven flung down his brush, and had just begun `Well, of all the unjust things --' when his eye chanced to fall upon him, as she stood watching them, and he checked himself suddenly: the others looked round also, and all of them bowed low. At Berger's direction, the city also intervened in the Hughes bankruptcy case in U. S. District Court in a move preliminary to filing a claim there. The Butler did it. `I didn't know it was YOUR table,' she said; `it's laid for a great many more than three.' 
+To achieve such an equilibrium, it is necessary for the radiation to be scattered by matter, many times. After it allotted shares to 41 underwriters and 52 selling group members from coast to coast there were not many shares for anyone. Many are called but few are chosen. Is this a dagger which I see before me?. Like the argument about human progress, it indicates that there must have been a beginning. 
+All things must pass. Please, Ma'am, is this New Zealand or Australia?' (and she tried to curtsey as she spoke -- fancy CURTSEYING as you're falling through the air! While emphasizing that technical details were not fully worked out, Pelham said his resolution would seek to set aside the privilege resolution which the House voted through 87-31. Hardly knowing what she did, she picked up a little bit of stick, and held it out to the puppy; whereupon the puppy jumped into the air off all its feet at once, with a yelp of delight, and rushed at the stick, and made believe to worry it; then he dodged behind a great thistle, to keep herself from being run over; and the moment she appeared on the other side, the puppy made another rush at the stick, and tumbled head over heels in its hurry to get hold of it; then, thinking it was very like having a game of play with a cart-horse, and expecting every moment to be trampled under its feet, ran round the thistle again; then the puppy b
 egan a series of short charges at the stick, running a very little way forwards each time and a long way back, and barking hoarsely all the while, till at last it sat down a good way off, panting, with its tongue hanging out of its mouth, and its great eyes half shut. 
+Their explanation for human progress was that there had been periodic floods, or other natural disasters, which repeatedly set back the human race to a primitive state. 
+I scratch your back and you scratch mine. Lastly, she pictured to herself how this same little sister of hers would, in the after-time, be herself a grown woman; and how she would keep, through all her riper years, the simple and loving heart of her childhood: and how she would gather about her other little children, and make THEIR eyes bright and eager with many a strange tale, perhaps even with the dream of Wonderland of long ago: and how she would feel with all their simple sorrows, and find a pleasure in all their simple joys, remembering her own child-life, and the happy summer days. Donkey's years. `I don't know where Dinn may be,' said the Mock Turtle, `but if you've seen them so often, of course you know what they're like.' Where there's muck there's brass.
+It was a nice round figure, that 12, he said as he headed for the clubhouse, not too much perturbed. Much Ado about Nothing. You can throw television sets, diamond rings, or even your worst enemies into a black hole, and all the black hole will remember, is the total mass, and the state of rotation. For if ye forgive men their trespasses, your heavenly Father will also forgive you : but if ye forgive not men their trespasses, neither will your Father forgive -- your trespasses. He came all the way around on Gardner's hit before 5777 fans.
+The outlook the Vienna meeting will bring together a seasoned, 67-year-old veteran of the cold war who, in Mr. Kennedy's own words, is shrewd, tough, vigorous, well-informed and confident, and a 44-year-old President (his birthday is May 29) with a demonstrated capacity for political battle but little experience in international diplomacy. Leave well enough alone. But the wave function will vary very rapidly near the peak, up on one side, and down on the other. Since the constitution forbids introduction of a tax bill at a fiscal session, the administration will either have to cut down expenses or inflate its estimates of anticipated revenues. Down the hatch.
+Some people have questioned whether viruses should count as life, because they are parasites, and can not exist independently of their hosts. I did not much like keeping so close to her: first, because the Duchess was VERY ugly; and secondly, because she was exactly the right height to rest her chin upon her shoulder, and it was an uncomfortably sharp chin. He was also pleased with the wide distribution because he thought it proved again his argument that Dallas investment men can do just as good a job as the big New York investment bankers claim only they can do. Just in time. `I don't know the meaning of half those long words, and, what's more, I don't believe you do either!' 
+They're dreadfully fond of beheading people here; the great wonder is, that there's any one left alive!' We do not know how DNA molecules first appeared. While he declined to suggest how, he said that sooner or later we must get rid of Castro, for unless we do we're liable to face similar situations in this hemisphere. How now brown cow?. 
+It is difficult to imagine that one could build a living system, out of just hydrogen and helium, and anyway the early universe was still far too hot for atoms to combine into molecules. 
+The lady doth protest too much, methinks. For example, it was found that elementary particles behaved rather like little tops, spinning about an axis. `What I was going to say,' said the Dodo in an offended tone, `was, that the best thing to get us dry would be a Caucus-race.' That permitted us to start controlling the ball right away, said Stram, quipping, I think I'll put that play in the book. Here was another puzzling question; and as he could not think of any good reason, and as the caterpillar seemed to be in a VERY unpleasant state of mind, she turned away. 
+Something is rotten in the state of Denmark. That wouldn't be much good for space Westerns. Fight the good fight. Naturally, enterprises of the size of General Electric are in a position to structure their prices in such a way that the relatively small competitors can be forced to the wall in a very short time. This is very midsummer madness.
+It might be possible to use genetic engineering, to make DNA based life survive indefinitely, or at least for a hundred thousand years. You can lead a whore to culture but you can't make her think. `If everybody minded their own business,' the lady said in a hoarse growl, `the world would go round a deal faster than it does.' In ancient times, the world must have seemed pretty arbitrary. The company sells a complete line of gin machinery all over the cotton-growing world.
+Come the three corners of the world in arms. So she stood still where she was, and waited. It involved scanning the radio frequencies, to see if we could pick up signals from alien civilisations. Said he : we will see whether whites and Negroes are treated the same around here. However, `jury-men' would have done just as well. 
+Aggression, in the form of subjugating or killing other men, and taking their women and food, has had definite survival advantage, up to the present time. The third belief, in six points, emphasizes the Deity of the Lord Jesus Christ, and : -- emphasizes the Virgin birth -- the sinless life of Christ -- his miracles -- his substitutionary work on the cross -- his bodily resurrection from the dead -- and His exaltation to the right hand of God. What a piece of work is man. However, long distance space travel, will be difficult for chemically based life forms, like DNA. 
+The live-long day.
+If they weren't, we wouldn't be here. After Thursday's open date, Solly plans to open with Larry Jackson against the Cubs here Friday night. Overpaid, oversexed, and over here. Districts issue legislators always get restless for a special session (whether for the companionship or the $22.50 per diem is not certain) and if they start agitating. Get thee behind me Satan.
+And she kept on puzzling about it while the Mouse was speaking, so that her idea of the tale was something like this:-- `Fury said to a mouse, That he met in the house, "Let us both go to law: I will prosecute YOU. A plague o' both your houses. `Yes, that's it,' said the Hatter with a sigh: `it's always tea-time, and we've no time to wash the things between whiles.' This could lead to the graph of the separation between two galaxies, being a curve that approached zero, but didn't actually pass through it, at any finite time in the past. Skorich received a three-year contract at a salary believed to be between $20,000 and $25,000 a year.
+Between the Devil and the deep blue sea. The smallest worm will turn, being trodden on. Because they are under such great tension, one might have expected them to accelerate to almost the speed of light. Sailing under false colours. Not only do the particles and unlucky astronauts that fall into a black hole, never come out again, but also the information that they carry, is lost forever, at least from our region of the universe. 
+Never never land. `As if it wasn't trouble enough hatching the eggs,' said the Pigeon; `but I must be on the look-out for serpents night and day! Singing from the same hymn sheet. But if you can travel from one side of the galaxy, to the other, in a week or two, you could go back through another wormhole, and arrive back before you set out. Price support loans may total another $1 billion this year.
+If you think that you have another think coming. Speaking of the present status of civil defense in the city, Mr. Hawksley said he would be willing to bet that not more than one person in a hundred would know what to do or where to go in the event of an enemy attack. `Does YOUR watch tell you what year it is?' So the rate of biological evolution in humans, is about a bit a year. 
+Barber, who is in his 13th year as a legislator, said there are some members of our congressional delegation in Washington who would like to see it (the resolution) passed.
+This could connect the two sides of the galaxy, and act as a short cut, to get from one to the other and back while your friends were still alive. Fiddling while Rome burns. He who laughs last laughs longest. `Poor little thing!' said Diana, in a coaxing tone, and she tried hard to whistle to it; but she was terribly frightened all the time at the thought that it might be hungry, in which case it would be very likely to eat her up in spite of all her coaxing. He did not want the effort weakened by any illusion that summit magic might make it unnecessary.
+The Belgians also placed great emphasis on education. Some are born great, some achieve greatness, and some have greatness thrust. One would also expect to have seen large numbers of tourists from the future, curious to look at our quaint, old-fashioned ways. The 53-year-old Shea, a prominent corporation lawyer with a sports background, is generally recognized as the man most responsible for the imminent return of a National League club to New York. Old lang syne.
+Even if there were sound reasons for keeping us in ignorance, human nature being what it is, it is difficult to believe that someone wouldn't show off, and tell us poor benighted peasants, the secret of time travel. We'll work out about an hour on Saturday, then we'll work Monday and Tuesday of next week, then taper off. He promised nearly 200 Democratic county committee members at the meeting in the Puddingstone Inn : when I come back here after the November election you'll think, you're my man -- elected. I guessed in a moment that it was looking for the fan and the pair of white kid gloves, and she very good-naturedly began hunting about for them, but they were nowhere to be seen -- everything seemed to have changed since her swim in the pool, and the great hall, with the glass table and the little door, had vanished completely. Since we haven't cracked time travel yet, I have run out of time. 
+Go Cap in hand. Laws will be passed, against genetic engineering with humans. Against the grain. It came like a bolt from the blue. The Customer is always right.
+What it shows is that there are many initial states, containing television sets, diamond rings, and even people, that evolve to the same final state, at least outside the black hole. Offenses multiply the President has also called upon the Attorney General, the Secretary of Health, Education and Welfare, and the Secretary of Labor to coordinate their efforts in the development of a program of federal leadership to assist states and local communities in their efforts to cope with the problem. There used to be a project called SETI, the search for extra-terrestrial intelligence. The United States, State Department officials explain, now is mainly interested in setting up an international inspection system which will prevent Laos from being used as a base for Communist attacks on neighboring Thailand and South Viet Nam. 
+Olive the other reindeer used to laugh and call him names.
+This means, it doesn't take into account, the Uncertainty Principle of Quantum Mechanics, which says that an object can not have both a well defined position, and a well defined speed: the more accurately one measures the position, the less accurately one can measure the speed, and vice versa. Mrs. Molvar, who kept reiterating her request that they please take a stand, said, we must have faith in somebody -- on the local level, and it wouldn't be possible for everyone to rush to a school to get their children. Interestingly enough, Laplace himself wrote a paper in 1799 on how some stars could have a gravitational field so strong that light could not escape, but would be dragged back onto the star. The biggest single act would doubtless be staged by Frankie himself : his Inaugural wardrobe had been designed by Hollywood Couturier Don Loper, who regularly makes up ladies' ensembles. He is a law unto himself.
+It was so long since she had been anything near the right size, that it felt quite strange at first; but she got used to it in a few minutes, and began talking to herself, as usual. This indicates that the present phase of human history can not have been going for more than a few thousand years. Except for a few months in late 1960 and early 1961, retail farm equipment sales have trailed year-earlier levels since the latter part of 1959. Or the green house effect becoming unstable. Eaten out of house and home.
+`Come, there's no use in crying like that!' she said to herself, rather sharply; `I advise you to leave off this minute!' During that time, the useful information in our DNA, has probably changed by only a few million bits. During his college career, Dr. Clark was captain of his basketball team and was a football letterman. Several signers affixed their names, it was learned, after being told that no tax increase would be possible without consent of the General Assembly and that a provision could be included in the charter to have the town take over the Johnston Sanitary District sewer system. Absent without leave.
+Born again. `I want a clean cup,' interrupted the Joker: `let's all move one place on.' What would stop you blowing up the rocket on its launch pad, or otherwise preventing you from setting out in the first place. Such objects were given the name Black Holes, by the American physicist John Wheeler, who was one of the first to recognise their importance, and the problems they pose. The trial will be held, probably the first week of March, in the famous Old Bailey central criminal court where Klaus Fuchs, the naturalized British German born scientist who succeeded in giving American and British atomic bomb secrets to Russia and thereby changed world history during the 1950s, was sentenced to 14 years in prison.
+The American dream. Green around the gills. An Emory spokesman indicated, however, that the university itself did not intend to make any test of the laws. Run home this moment, and fetch me a pair of gloves and a fan! 
+A small step for man, a giant leap for mankind.
+However, in a remarkable paper written in 1905, when he was a clerk in the Swiss patent office, Einstein showed that the time and position at which one thought an event occurred, depended on how one was moving. The rabbit-hole went straight on like a tunnel for some way, and then dipped suddenly down, so suddenly that she had not a moment to think about stopping herself before she found herself falling down a very deep well. However, the graph of the number of radio sources, against there strength, went up much more sharply at low source strengths, than the Steady State theory predicted. He ran his string of successful conversions this season to 13 straight before one went astray last Saturday night in the 41-8 slaughter of Washington State. You'll wonder where the chartreuse went when you brush your teeth with Pepsodent.
+He did not say by how much. Her listeners were perfectly quiet till she got to the part about her repeating `YOU ARE OLD, FATHER WILLIAM,' to the caterpillar, and the words all coming different, and then the whale drew a long breath, and said `That's very curious.' These irregularities are so little, only one part in a hundred thousand, that for years people looked for them in vain. But, for my own part, it was Greek to me. The cosmologist, Sir Arthur Eddington, once said, 'Don't worry if your theory doesn't agree with the observations, because they are probably wrong.' 
+If working in a zinc mine, which he once did for 87-1/2 cents an hour, paid more than playing center field for the Yankees, Mantle would work in a zinc mine. Once in a blue moon. It was high time to go, for the pool was getting quite crowded with the birds and animals that had fallen into it: there were a Duck and a Dodo, a Lory and an Eaglet, and several other curious creatures. But in extreme conditions, like in the early universe, or in high energy particle collisions, there could be significant loss of information. Students have been using electric computers and high speed movie cameras during the study.
+Knee high to a grasshopper. There was a general clapping of hands at this: it was the first really clever thing the King had said that day. I will wear my heart upon my sleeve. `When we were little,' the Mock Turtle went on at last, more calmly, though still sobbing a little now and then, `we went to school in the sea. As those of you that were forced to learn Euclidean geometry at school may remember, one of the consequences of these axioms is, that the angles of a triangle, add up to a hundred and 80 degrees. 
+And shining morning face, creeping like a snail unwillingly to school. When I was a kid, Maris told a sportswriter last week, I used to follow Williams every day in the box score, just to see whether he got a hit or not. But if they show self-restraint, they don't get the orders. Don't look a gift horse in the mouth. 
+Break in Georgia the University of Georgia has long claimed that it does not discriminate against any applicant on the basis of race or color.
+Unfortunately, in the same paper, Einstein showed that the rocket power needed to accelerate a space ship, got greater and greater, the nearer it got to the speed of light. Soviet Premier Khrushchev sent New Year's hopes for peace to President-elect Kennedy, and got a cool acknowledgment in reply. Got the hump. Information requires energy to carry it, and there won't be enough energy left when the black hole disappears. Party leaders came out of the final meeting apparently satisfied and stated that complete agreement had been reached on a solution to the crisis created by the elections which left no party with enough strength to form a government on its own.
+(He had been to the seaside once in her life, and had come to the general conclusion, that wherever you go to on the English coast you find a number of bathing machines in the sea, some children digging in the sand with wooden spades, then a row of lodging houses, and behind them a railway station.) Only a relative handful of such reports was received, the jury said, considering the widespread interest in the election, the number of voters and the size of this city. Of course, some people would claim that we have been visited from the future. The course of true love never did run smooth. A nuclear war, is still the most immediate danger, but there are others, such as the release of a genetically engineered virus. 
+Cry havoc and let slip the dogs of war. But she went on all the same, shedding gallons of tears, until there was a large pool all round her, about four inches deep and reaching half down the hall. This may have been reasonable, given the notoriously unreliable character of cosmological observations, until fairly recently. The 187-mile Illinois State Toll Highway, for example, was not opened over its entire length until December, 1958. Until Hell freezes over.
+This says that the total amount of disorder, or entropy, in the universe, always increases with time. Beaver away at. So the total amount of useful information in our genes, is probably something like a hundred million bits. Two began in a low voice, `Why the fact is, you see, Miss, this here ought to have been a RED rose-tree, and we put a white one in by mistake; and if the Queen was to find it out, we should all have our heads cut off, you know. But I shall see what conclusions can be drawn, from the fact that life exists on this planet, at this stage in the history of the universe. 
+This is the key fact emerging from Sunday's national election. The Mouse gave a sudden leap out of the water, and seemed to quiver all over with fright. This is not only a compliment to Mijbil, of whom there are a fine series of photographs and drawings in the book, but to the author who has catalogued the saga of a frightened otter cub's journey by plane from Iraq to London, then by train (where he lay curled in the wash basin playing with the water tap) to Camusfearna, with affectionate detail. There must be a possible history in which there is a lasting peace in the Middle East, though maybe the probability is low. 
+Though Walter Ulbricht, by grace of Soviet tanks, may be head man in East Germany, that does not give him any right to usurp the government of East Berlin or to absorb that semi-city into the Soviet zone.
+Though last, not least in love. This time there could be NO mistake about it: it was neither more nor less than a pig, and she felt that it would be quite absurd for her to carry it further. If this choice is less exciting than New York Democrats may wish, it nevertheless must be made. Less is more. No government agency could afford to be seen to be spending public money, on anything as way out as time travel. 
+Now, if you only kept on good terms with him, he'd do almost anything you liked with the clock. To almost two generations of Americans it must have seemed as though the existence of Mr. Sam coincided with that of the House. On the other hand, the remaining four directions are fairly flat, and are what we call space-time. Although the resolution might have been far more specific, it was considerably tougher than the earlier one. Thus far into the bowels of the land.
+Just then her head struck against the roof of the hall: in fact she was now more than nine feet high, and she at once took up the little golden key and hurried off to the garden door. It took two and a half billion years, to evolve from the earliest cells to multi-cell animals, and another billion years to evolve through fish and reptiles, to mammals. The Bears took the lead in the first inning, as they did in Sunday's opener, and never lagged. Yet your editorial said : now the Attorney General writes that no considerations justify any loss of revenue of this proportion. Though this be madness, yet there is method in it.
+This precious stone set in the silver sea, this sceptered isle. Because time is not going to go backwards, I think I better stop now. This time, they were much better prepared and organized, and the political climate was favorable. Better to have loved and lost than never to have loved at all. Instead, it would be an ordinary point of space and time, like the North Pole is an ordinary point on the Earth, or so I'm told. 
+A little bird told me. Eventually, at a critical weight and size, they will make a bottomless hole in the sheet, which particles can fall into, but nothing can get out of. Nothing that is likely to happen, however, should prompt the sending of United States soldiers for other than instructional missions. Night soil. 
+And with that she began nursing her child again, singing a sort of lullaby to it as she did so, and giving it a violent shake at the end of every line: `Speak roughly to your little boy, And beat him when he sneezes: He only does it to annoy, Because he knows it teases.' 
+But it also briefly suggested the possibility of a meeting with Mr. Khrushchev before the end of the year if the international climate were favorable and schedules permitted. At his wits end. That is why we don't get sunburn from a cup of coffee. He called after it; and the others all joined in chorus, `Yes, please do!' but the Mouse only shook its head impatiently, and walked a little quicker. Look to Coosa Valley for industrial progress cities and counties interested in industrial development would do well in the months ahead to keep their eyes peeled toward the 13 northwest Georgia counties that are members of the Coosa Valley Area Planning and Development Commission.
+Sans teeth, sans eyes, sans taste, sans everything. But they have not managed to find any mechanism that would return the information. I'll need more than a single day to find the words to properly express my thanks to them. A hard man is good to find. Going, going, gone.
+`After that,' continued the idiot, `I cut some more bread- and-butter --' `But what did the dormouse say?' one of the jury asked. When I gave a lecture in Japan, I was asked not to mention the possible re-collapse of the universe, because it might affect the stock market. After that, some of the stars would have exploded as supernovas, and scattered the heavy elements back into space, to form the raw material for later generations of stars. Point Percy at the porcelain. And she began thinking over all the children she knew that were of the same age as herself, to see if she could have been changed for any of them. 
+If you knew the state of the universe at some time in the past, you could predict it in the future. Alas, poor Yorick! I knew him, Horatio. I suppose you'll be telling me next that you never tasted an egg!' This is shown on this next diagram, which is not to scale, because there's no way one can show a period of ten thousand years, on the same scale as billions of years. Sitting next to Nellie.
+For example, a computer virus is a program that will make copies of itself in the memory of a computer, and will transfer itself to other computers. It also indicated that space travel to other stars, was going to be a very slow and tedious business. Admitting that main streets and the central business district should have priority, the Councilman said it is also essential that small shopping areas not be overlooked if our small merchants are to survive. Do your business. 
+So I will give a different argument, to show that the universe contains enough matter, to focus our past light cone. 
+Happy hitting if it's true that contented cows give more milk, why shouldn't happy ball players produce more base hits? An even greater limitation and danger for future generations, is that we still have the instincts, and in particular, the aggressive impulses, that we had in cave man days. We have seen better days. `Hold your tongue, Ma!' said the young Crab, a little snappishly. An Angry young man.
+A scientific law is not a scientific law, if it only holds when some supernatural being decides to let things run, and not intervene. He said, let's work for peace instead of protection from aggression. Just at this moment She felt a very curious sensation, which puzzled her a good deal until she made out what it was: she was beginning to grow larger again, and she thought at first she would get up and leave the court; but on second thoughts she decided to remain where she was as long as there was room for her. A $12,500 payment Leavitt, as he entered the jury room, said he was prepared to answer questions about the $12,500 his liquor firm paid to Stein for labor consultant work with five unions which organized Leavitt's workers. Leave the room.
+He was a teflon president. League regularly stands on the side of right the League of Women Voters, 40 now and admitting it proudly, is inviting financial contributions in the windup of its fund drive. `A cheap sort of present!' I thought. All present and correct. `We quarrelled last March -- just before HE went mad, you know --' (pointing with his tea spoon at the American girl,) `-- it was at the great concert given by the Queen of Hearts, and I had to sing "Twinkle, twinkle, little bat! 
+But, the fact that several pulsars are observed to have planets suggests that a reasonable fraction of the hundred billion stars in our galaxy may also have planets. The Frog-Footman repeated, in the same solemn tone, only changing the order of the words a little, `From the Queen. In order to understand this, considered a sheet of rubber, with a weight placed on it, to represent a star. Apologies are in order from anybody who said, are you sure you're not making a mistake? Apple pie order.
+A major national library can contain about five million books, or about ten trillion bits. This observation can be elevated to the status of a law, the so-called Second Law of Thermodynamics. Salem (special) -- for a second month in a row, Multnomah County may be short of general assistance money in its budget to handle an unusually high summer month's need, the state public welfare commission was told Friday. Second wind. 
+She did not get hold of anything, but she heard a little shriek and a fall, and a crash of broken glass, from which she concluded that it was just possible it had fallen into a cucumber-frame, or something of the sort. 
+The deeper wonder is how this miracle was accomplished in decades, rather than in centuries and by immigrant minorities at that. He was rather doubtful whether she ought not to lie down on her face like the three gardeners, but she could not remember ever having heard of such a rule at processions; `and besides, what would be the use of a procession,' thought she, `if people had all to lie down upon their faces, so that they couldn't see it?' She had just succeeded in curving it down into a graceful zigzag, and was going to dive in among the leaves, which she found to be nothing but the tops of the trees under which she had been wandering, when a sharp hiss made her draw back in a hurry: a large pigeon had flown into her face, and was beating her violently with its wings. `Why,' said the Gryphon, `you first form into a line along the sea-shore --' `Two lines!' cried the turtle. Some of the jury wrote it down `important,' and some `unimportant.' 
+But for tops as small as atoms, the discrete nature of spin is very important. The Illinois Commission for Handicapped Children, which for 20 years has had the responsibility of coordinating the services of tax supported and voluntary organizations serving handicapped children, of studying the needs of handicapped children in Illinois, and of promoting more adequate services for them, indeed welcomes this new important resource which will help the people of Illinois toward the goal of providing an education for all of its children. It is difficult to say how often such collisions occur, but a reasonable guess might be every twenty million years, on average. Point is that developing countries often build up a textile industry first, need encouragement to get on their feet. Some good news although it looked like a routine technical snapback to Wall Streeters it was accompanied by some good news.
+The mother of young queen, Mrs. G. Henry Pierson Jr. chose a white brocade gown made on slim lines with panels of tomato-red and bright green satin extending down the back. Survivors include two brothers, C. E. Killingsworth, Atlanta, and John Killingsworth, Warren, Ohio; and two sisters, Minnie  and Mrs. Bessie Bloom, both of Gettysburg, Pa.. If this were the case, it would raise a whole host of questions and problems. It is a basket case. She folded her hands, and began:-- `You are old, Father William,' the young man said, `And your hair has become very white; And yet you incessantly stand on your head -- Do you think, at your age, it is right?' 
+In other words, the anti-trust laws, designed to reduce prices to the consumer on Monday, Wednesday and Friday, become a tool to protect the marginal manufacturer on Tuesday, Thursday and Saturday. This is an area nearly as large as Western Europe; and it was filled then as now by quarreling tribes with no political or historical unity. By and large. Big in Japan. Four corners of the earth.
+While she was trying to fix on one, the cook took the cauldron of soup off the fire, and at once set to work throwing everything within her reach at the woman and the baby -- the fire-irons came first; then followed a shower of saucepans, plates, and dishes. But at the same time he moved his helicopter-borne marines to within an hour of the fighting. Born within the sound of Bow Bells. Although this lecture is partly about time travel, I felt I had to give it the scientifically more respectable title, Space and Time warps. 
+By the end of the century the Roman Catholic Church was beginning to make itself felt, mainly through such institutions as hospitals but also through its attitude towards organized labour.
+The week went along briskly enough. So she began telling them her adventures from the time when she first saw the rabbit. We saw back to the origin of the universe. (the last doorman that saw me do that should calm himself. According to string theory, which is our best hope of uniting General Relativity and Quantum Theory, into a Theory of Everything, space-time ought to have ten dimensions, not just the four that we experience. 
+Six of the best. The idea that the state of the universe at one time determines the state at all other times, has been a central tenet of science, ever since Laplace's time. Holmes was asked if he had ever visited a house of prostitution, or a beatnik parlor or teahouse. For ever and a day. Fair Dealer Humphrey upped the ante, asked cloture power for a mere majority of Senators.
+Power dressing. But with the human race, evolution reached a critical stage, comparable in importance with the development of DNA. The nearest thing to a straight line on the surface of the Earth, is what is called, a great circle. There is one thing I know; a person will never have spiritual poise and inner peace as long as the heart holds a grudge. A thing of beauty is a joy forever.
+At the left is a pair of dressy straw pumps in a light, but crisp texture. It's a trick of the light. Our family always HATED cats: nasty, low, vulgar things! The Black sheep of the family. `Once upon a time there were three little sisters,' the carrot began in a great hurry; `and their names were Elsie, Lacie, and Tillie; and they lived at the bottom of a well --' `What did they live on?' said Jane, who always took a great interest in questions of eating and drinking. 
+I therefore want to show you, that observational evidence indicates the universe contains sufficient matter, that it is like the time reverse of a black hole, and so contains a singularity. In the case of a black hole, this definite prediction involves both members of a particle pair. Two of these are in or near Dallas and the others away from the vicinity. It has been championed by the physicist David Deutsch, and it seems to have been what Steven Spielberg had in mind when he filmed, Back to the Future. 
+We have not the leisure, or the patience, or the skill, to comprehend what was working in the mind and heart of a then recent graduate from the Harvard Divinity School who would muster the audacity to contradict his most formidable instructor, the majesterial Andrews Norton, by saying that, while he believed Jesus like other religious teachers, worked miracles, I see not how a miracle proves a doctrine.
+Have Half a mind to. The Antipathies, I think --' (she was rather glad there WAS no one listening, this time, as it didn't sound at all the right word) `-- but I shall have to ask them what the name of the country is, you know. He pointed out to the young musicians that the National Gallery is the only museum in the country to have a full-time music director, Richard Bales. As one goes back in time on the diagram, the light cone spreads out to greater distances, and its area increases. Done in.
+In a universe that was essentially static, there would not have been any dynamical reason, why the stars should have suddenly turned on, at some time. As we know, the Soviet peasant today still very largely thrives on being able to sell the produce grown on his private plot; and it is still very far from certain how valid the party's claim is that in a growing number of kolkhozes the peasants are finding it more profitable, to surrender their private plots to the kolkhoz and to let the latter be turned into something increasingly like a state farm. That is a well turned calf. Suddenly she came upon a little three-legged table, all made of solid glass; there was nothing on it except a tiny golden key, and Diane's first thought was that it might belong to one of the doors of the hall; but, alas! either the locks were too large, or the key was too small, but at any rate it would not open any of them. How long the self-design phase will last is open to question. 
+Open house. man to enter into the kingdom of God. William Smythe, director of field service, told the commissioners that Multnomah, as of Aug. 22, had spent $58,918 out of its budgeted $66,000 in the category, leaving only $7,082 for the rest of the month. The only way of avoiding this problem would be if, for some reason, the stars did not shine before a certain time. Houston, we have a problem.
+Nothing is certain but death and taxes. The pattern here pictured is clearly not peculiar to Notre Dame : it is simply that the paradox involved in this kind of control of the institution by the organization which actually owns it, becomes more obvious where there is a larger and more distinguished outside faculty. If so, it might be worth while to assign a future jazz show to a different department -- one with enough confidence in the musical material to cut down on the number of performers and give them a little room to display their talents. Thus it would require the direct intervention of God, if the universe began at that date. Thus he will be in a position to disabuse the Soviet leader of any notions he may have about grave Allied disunity.
+The company began operation in 1900 with hardware and oil mill supplies. The answer lies in a bumper sticker that I used to have on the door of my office: Black Holes are Out of Sight. The door panels are designed to accommodate standard doors which should be of exterior grade. Katy bar the door. 
+And even if it could, it would not really help explain the origin of life, because the time available since the formation of carbon is only just over double the age of the Earth. 
+They were just beginning to write this down on their slates, when the white rabbit interrupted: `UNimportant, your Majesty means, of course,' he said in a very respectful tone, but frowning and making faces at him as he spoke. Mr. Balaguer's troubles are by no means over. Who wooed in haste, and means to wed at leisure. `Ah, well! It means much the same thing,' said the woman, digging her sharp little chin into Melanie's shoulder as she added, `and the moral of THAT is --"Take care of the sense, and the sounds will take care of themselves."' There is no need here to spell out the conditions of creative teaching except to point out that, at the college level, the sense of community and of community responsibility is even more necessary than it is at other levels.
+Why, it fills the whole window!' For it was the millions of buffalo and prairie chicken and the endless seas of grass that symbolized for a whole generation of Americans the abundant supply that was to take many of them westward when the Ohio and Mississippi valleys began to fill. The whole nine yards. This matter is of great importance, and the outcome may mean the difference between life or death, or at least serious injuries, for many veterans. The Root of the matter.
+It is perhaps too late now to talk of mandate because it is inconsistent with what is termed political realism. A house divided against itself cannot stand. A butterfly flapping its wings can cause rain in Central Park, New York. Richard of York gave battle in vain. Let me see: four times five is twelve, and four times six is thirteen, and four times seven is -- oh dear! 
+Each had been shot in the back several times with a.22-CALIBER As the new clouds of radioactive fallout spread silently and invisibly around the earth, the Soviet Union stands guilty of a monstrous crime against the human race. Milk of human kindness. The thin red line. `It goes on, you know,' the sport continued, `in this way:-- "Up above the world you fly, Like a tea-tray in the sky. 
+They could be miles north and east of Oxford circus, and height above sea level. Seven of the eight companies that turn out full lines of farm machinery say sales by their dealers since the start of August have shown gains averaging nearly 10% above last year. Above board. Even though headquarters actually have been moved into the Chatham building, do they believe that they can make the new name stick? 
+Action man.
+`Come on, then,' said the Queen, `and he shall tell you his history,' As they walked off together, Dorothy heard the King say in a low voice, to the company generally, `You are all pardoned.' Such a decision should have placed a powerful weapon in the hands of the entire housing industry, but there is little evidence that realtors, or at least their associations, have repudiated the principle in such clauses. He is a safe pair of hands. Local derby. Five figures.
+History is bunk. Whee the people : lovely thrush Annamorena gave up a promising show biz career to apply glamor touches to her hubby, Ray Lenobel's fur firm here. `But everything's curious today. But today's science fiction, is often tomorrow's science fact. If these constants had significantly different values, either the nucleus of the carbon atom would not be stable, or the electrons would collapse in on the nucleus. 
+The chief difficulty Kate found at first was in managing her flamingo: she succeeded in getting its body tucked away, comfortably enough, under her arm, with its legs hanging down, but generally, just as she had got its neck nicely straightened out, and was going to give the hedgehog a blow with its head, it WOULD twist itself round and look up in her face, with such a puzzled expression that she could not help bursting out laughing: and when she had got its head down, and was going to begin again, it was very provoking to find that the hedgehog had unrolled itself, and was in the act of crawling away: besides all this, there was generally a ridge or furrow in the way wherever she wanted to send the hedgehog to, and, as the doubled-up soldiers were always getting up and walking off to other parts of the ground, Katharine soon came to the conclusion that it was a very difficult game indeed. Act the fool. Run off your feet. Oh dear! I shall be late!' (when she thought it over 
 afterwards, it occurred to her that she ought to have wondered at this, but at the time it all seemed quite natural); but when the hedgehog actually TOOK A WATCH OUT OF ITS WAISTCOAT-POCKET, and looked at it, and then hurried on, Catharine started to her feet, for it flashed across her mind that she had never before seen a rabbit with either a waistcoat-pocket, or a watch to take out of it, and burning with curiosity, she ran across the field after it, and fortunately was just in time to see it pop down a large rabbit-hole under the hedge. These regularities were most obvious, in the motion of the heavenly bodies across the sky. 
+There has been more activity across the state line in Massachusetts than in Rhode Island in recent weeks toward enforcement of the Sunday sales laws. That is a shot across the bows. The other guests had taken advantage of the Queen's absence, and were resting in the shade: however, the moment they saw her, they hurried back to the game, the Queen merely remarking that a moment's delay would cost them their lives. This could have taken only a few hundred million years. Taken aback.
+`Not at first, perhaps,' said the teacher: `but you could keep it to half-past one as long as you liked.' Past it. In Donnybrook, there is quite a different Eire, a rural land where singing, dancing, fist-fighting and romancing are the thing. I am not doing anything, of myself. 
+Before memory, too, clouds over, let us make a note or two of what could be seen.
+However, physicists began to find other behaviour, that could be explained only in terms of quantities having discrete, or quantised values, rather than continuously variable ones. He gave the impression of never having read a word about art, but there was no doubt that he had an eye for the best. "I'll be judge, I'll be jury," Said cunning old Fury: "I'll try the whole cause, and condemn you to death."' If it does not, it should be able to survive the death of the Sun, in about 5 billion years, by moving to planets around other stars. `I'm a poor man, your Majesty,' the royal began, in a trembling voice, `-- and I hadn't begun my tea -- not above a week or so -- and what with the bread-and-butter getting so thin -- and the twinkling of the tea --' `The twinkling of the what?' said the King. 
+It is thought the collision of a rather smaller body with the Earth, about 70 million years ago, was responsible for the extinction of the dinosaurs. The appestat, which adjusts the appetite to keep weight constant, is located, says Jolliffe, in the hypothalamus -- near the body's temperature, sleep and water-balance controls. Keep body and soul together. Toying with her field in the early stages, Garden Fresh was asked for top speed only in the stretch by Jockey Philip Grimm and won by a length and a half in 1.24 3-5 for the 7 furlongs. Further, do our reforming friends really believe that the cartoonists will consent to the banishment of the tiger from their zoo?
+Back the field. Nevertheless, I am sure that during the next century, people will discover how to modify both intelligence, and instincts like aggression. Am I my brother's keeper?. Friday afternoon car. thought I would like to quote you Laplace's actual words, so I asked a friend to track them down. 
+To Have words with. She had already heard her sentence three of the players to be executed for having missed their turns, and she did not like the look of things at all, as the game was in such confusion that she never knew whether it was her turn or not. On this view, you couldn't set out on the rocket ship to travel into the past, unless you had already come back, and failed to blow up the launch pad. Judge Bootle's decision : the two plaintiffs are qualified for admission to said university and would already have been admitted had it not been for their race and color. There have even been serious errors in the U. S. Forest Service, whose officials pride themselves in their scientific training, he added.
+Many of you are familiar, I'm sure, with the story of my early struggles : the fire in January, 1947, that destroyed everything -- even our precious list of subscribers. I'm not so green as I am cabbage looking. A couple of days later an assistant told me he had telephoned Allied Arts for ticket information and was told the newspapers had made a mistake. Kiss and tell. 
+In fact, James Hartle of the University of California Santa Barbara, and I have proposed that space and imaginary time together, are indeed finite in extent, but without boundary. 
+The Charter does stipulate that due regard shall be paid to the importance of recruiting the staff on as wide a geographical basis as possible. Money makes the world go round. But by the end of the three-month period, in October 1960, something approaching calm settled on the Congo. They form the basis of the mental picture of the universe, held by many scientists, and almost all philosophers of science. That is a sure thing.
+There could be no doubt that it had a VERY turn-up nose, much more like a snout than a real nose; also its eyes were getting extremely small for a baby: altogether Elizabeth did not like the look of the thing at all. The progress reported by the advisory committee is real. The Real McCoy. So much for free will. His reference to discredited carcass or tattered remains of the president's leadership is an insult to the man who led our forces to victory in the greatest war in all history, to the man who was twice elected overwhelmingly by the American people as president of the United States, and who has been the symbol to the world of the peace-loving intentions of the free nations.
+Scot free. `How cheerfully he seems to grin, How neatly spread his claws, And welcome little fishes in With gently smiling jaws!' And Walker looks stronger, seems to be throwing better than he did last year. Once such super humans appear, there are going to be major political problems, with the unimproved humans, who won't be able to compete. `The trial cannot proceed,' said the King in a very grave voice, `until all the jurymen are back in their proper places -- ALL,' he repeated with great emphasis, looking hard at George as he said do. 
+A more dangerous formula for national frustration cannot be imagined. However much we may have to criticize liberal theology's constructive formulations, the theology we ourselves must strive to formulate can only go beyond liberalism, not behind it. A miss is as good as a mile. There remains, of course, the question of what the West can do beyond diplomatic protest to prevent the illegal efforts from becoming accomplished facts. These are the shortest paths between two points, so they are the roots that air lines use. 
+Castles in the air. Thus it seems there may be a Chronology Protection Agency at work, making the world safe for historians. Making out. So she began nibbling at the righthand bit again, and did not venture to go near the house till she had brought herself down to nine inches high. 
+Unlike Einstein, they have accepted the reduction in our ability to predict, that quantum theory brought about. 
+It was their conviction that the people should be brought up together, a grade at a time, until in some indefinite future some might be ready to tackle history, economics and political science. "William the Conqueror, whose cause was favoured by the pope, was soon submitted to by the English, who wanted leaders, and had been of late much accustomed to usurpation and conquest. If this had been all that happened, all the matter in the universe would have ended up as the simplest element, hydrogen, whose nucleus consists of a single proton. The population of the Congo is 13.5 million, divided into at least seven major culture clusters and innumerable tribes speaking 400 separate dialects. Oddly, the calls were still heard 11 days after the five were arrested.
+And you think you have language problems. But her sister sat still just as she left her, leaning her head on her hand, watching the setting sun, and thinking of little Georgette and all her wonderful Adventures, till she too began dreaming after a fashion, and this was her dream:-- First, she dreamed of little Charlotte herself, and once again the tiny hands were clasped upon her knee, and the bright eager eyes were looking up into hers -- she could hear the very tones of her voice, and see that queer little toss of her head to keep back the wandering hair that WOULD always get into her eyes -- and still as she listened, or seemed to listen, the whole place around her became alive the strange creatures of her little sister's dream. One suggestion was to modify the law of gravity, so that it became repulsive. At one time I became disturbed in the faith in which I had grown up by the apparent inroads being made upon both Old and New Testaments by a Higher Criticism of the Bibl
 e, to refute which I felt the need of a better knowledge of Hebrew and of archaeology, for it seemed to me that to pull out some of the props of our faith was to weaken the entire structure. Goedel was at the Institute of Advanced Study, in Princeton, where Einstein also spent his last years. 
+As roommates, teammates, and home-run mates, Mantle, 29, who broke in with the Yankees ten years ago, and Maris, 26, who came to the Yankees from Kansas City two years ago, have strikingly similar backgrounds. That is all I have to say for the moment. He sits there remembering the tense moment before the ball was snapped; the churning of straining feet, the rasp of the canvas pants; the smell and feel of hot, wet woolen sleeves across his face. There is no question as to just what is available. The first question of course was, how to get dry again: they had a consultation about this, and after a few minutes it seemed quite natural to Melanie to find herself talking familiarly with them, as if she had known them all her life. 
+However, one has to be careful about such arguments, because of what is known as the Anthropic Principle. She was moving them about as she spoke, but no result seemed to follow, except a little shaking among the distant green leaves. And there is the bright note : the gains were achieved in the face of temporary traffic lags late in 1960 and early in 1961 as a result of business recession. The division said it would be impossible to work on the line until then because of the large amount of acid sewage from jewelry plants in the area flowing through the line, heavy vehicle traffic on Eddy Street and tide Easy street.
+The Belgians were interested primarily in the economic development of the Congo, which is rich in copper, tin, cobalt, manganese, zinc, and uranium, and cotton and palm oil. He is a whipping boy. `It's the first position in dancing.' Pole position. 
+While he was at it, the philosopher of the Kremlin contributed an additional assist to the rule of reason by bellowing at those in the west who can't appreciate coexistence thru suicide.
+Rhyme nor reason. Since we can't change the way the universe began, the question of whether time travel is possible, is one of whether we can subsequently make space-time so warped, that one can go back to the past. Rather, they are impressed with the British Government's success in forcing -- and helping -- the British textile industry to shrink and to change over to other products. Chop and change. That is, you can move on the surface of the Earth, in two directions at right angles to each other: you can move north south, or east west. 
+North and south. If the space ship went very near the speed of light, it might seem to the people on board, that the trip to the galactic center had taken only a few years. Oak Grove (special) -- three positions on the Oak Lodge Water district board of directors have attracted 11 candidates. The impression has nevertheless been given during these three days, despite Mr. Rusk's personal popularity, that the United States delegation came to Oslo in a somewhat tentative and exploratory frame of mind, more ready to listen and learn than to enunciate firm policy on a global scale with detailed application to individual danger spots. All I can say is, that if governments were hiding something, they are doing a pretty poor job, of extracting useful information from the aliens. 
+An Inside job. The countries are trying to build in a decade the kind of society we took a century to build, he said. We can actually observe this warping of space-time, produced by the mass of the Sun, in the slight bending of light or radio waves, passing close to the Sun. Only the families and a dozen close friends will be present. That was a close shave.
+`'Tis so,' said the countess: `and the moral of that is --"Oh, 'tis love, 'tis love, that makes the world go round!"' One of the finest soft shoe tunes ever invented, Once In Love With Amy is also, of course, one of the most tantalizingly persistent of light love lyrics to come out of American musical comedy in our era. `All right, so far,' said the King, and he went on muttering over the verses to himself: `"WE KNOW IT TO BE TRUE --" that's the jury, of course -- "I GAVE HER ONE, THEY GAVE HIM TWO --" why, that must be what he did with the tarts, you know --' `But, it goes on "THEY ALL RETURNED FROM HIM TO YOU,"' said Claire. The Ball is in your court. There is thus a slight force pushing the plates together. 
+Come on!' So they went up to the hippopotamus, who looked at them with large eyes full of tears, but said nothing. But, the Uncertainty Principle implies that every region of space should be full of tiny virtual black holes, which appear and disappear again. Full tilt. It will cost a few billion dollars, but that is chicken feed, for a project of this importance. 
+Cost an arm and a leg.
+`Shy, they seem to put everything upon Bill! The British defending lawyers, who today increased from three to four, demanded to know if they could make the information involved seem of little value to a jury, the chances of their clients would improve. `In my youth,' said his father, `I took to the law, And argued each case with my wife; And the muscular strength, which it gave to my jaw, Has lasted the rest of my life.' A frequent pitfall in this sort of arrangement, experts warn, is a tendency to pay the wife more than her job is worth and to set aside an excessive amount for her as retirement income. Certainly all can applaud passage of an auto title law, the school bills, the increase in teacher pensions, the ban on drag racing, acceptance by the state of responsibility for maintenance of state roads in municipalities at the same rate as outside city limits, repeal of the college age limit law and the road maintenance bond issue.
+Act your age. They were the suffragettes and they wanted to vote. Suddenly one young voice rose above the others. With a lefthander going for Pittsburgh, I may use Don Taussig in center. He may be interested in another woman, or just like being with the boys.
+Hell has no fury like a woman scorned. Which way?', holding her hand on the top of her head to feel which way it was growing, and she was quite surprised to find that she remained the same size: to be sure, this generally happens when one eats cake, but Clare had got so much into the way of expecting nothing but out-of-the-way things to happen, that it seemed quite dull and stupid for life to go on in the common way. It is a matter of common experience, that things get more disordered and chaotic with time. If it is not enough that all of our internationalist One Worlders are advocating that we join this market, I refer you to an article in the New York Times' magazine section (Nov. 12, 1961), by Mr. Eric Johnston, entitled We Must Join The Common Market. The answer is given in the following Limerick. 
+A Catholic priest recently recounted how in the chapel of a large city university, following Anglican evensong, at which there was a congregation of twelve, he celebrated Mass before more than a hundred.  A mad tea-party.  There was a table set out under a tree in front of the house, and the Scotsman and the Irishman were having tea at it: a guinea-pig was sitting between them, fast asleep, and the other two were using it as a cushion, resting their elbows on it, and talking over its head. After a while she remembered that she still held the pieces of mushroom in her hands, and she set to work very carefully, nibbling first at one and then at the other, and growing sometimes taller and sometimes shorter, until she had succeeded in bringing herself down to her usual height. Not only does God definitely play dice, but He sometimes confuses us by throwing them where they can't be seen. The government pays a subsidy for revival of the classics, and this policy attracts experimen
 ters who sometimes put Moliere's characters in modern dress and often achieve interesting results.
+The idea is that six of these ten dimensions are curled up into a space so small, that we don't notice them. `Right, as usual,' said the countess: `what a clear way you have of putting things!' This explanation of how black holes ain't so black, makes it clear that the emission will depend on the size of the black hole, and the rate at which it is rotating. In any case it is by no means clear that formally structured organs of participation are what is called for at all. 
+Clear blue water.
+The two chains can then separate and each act as templates to build further chains. `Back to land again, and that's all the first figure,' said the emu, suddenly dropping his voice; and the two creatures, who had been jumping about like mad things all this time, sat down again very sadly and quietly, and looked at Joyce. The Orioles got a run in the first inning when Breeding, along with Robinson, the two Birds who got a pair of hits, doubled to right center, moved to third on Russ Snyder's single to right and crossed on Kunkel's wild pitch into the dirt in front of the plate. The bill is designed to provide special schooling for more deaf students in the scholastic age at a reduced cost to the state. I feel these scientists have not learnt the lesson of history. 
+I'm sure _I_ shan't be able! I'm even going to try to get the whirling dervishes of Damascus ] the last obstacle in Mrs. Geraghty's globe-girdling trip was smoothed out when a representative of Syria called upon her to explain that his brother would meet her at the border of that country -- so newly separated from Egypt and the United Arab Republic that she hadn't been able to obtain a visa. `Now at OURS they had at the end of the bill, "French, music, AND WASHING -- extra."' Face the music. Ordinarily a father permits his children to grow up in due time -- but when the colony received independence in 1960 the Congolese child, if one imagines him to have been born in 1908, was 52 and had until then been treated as an infant.
+With child. Luckily for Hannah, the little magic bottle had now had its full effect, and she grew no larger: still it was very uncomfortable, and, as there seemed to be no sort of chance of her ever getting out of the room again, no wonder she felt unhappy. These actions should serve to protect in fact and in effect the court's wards from undue costs and its appointed and elected servants from unmeritorious criticisms, the jury said. Level playing field. On last May 1, the Cardinals stood at 7-6, ending a two-season fall-off on that milestone.
+It would be like fighting the French and Indian War all over again, said one military man. Paint the town red. A Day late and a dollar short. -- Come, I'll take no denial; We must have a trial: For really this morning I've nothing to do." In the morning she found rooms directly across from the Excelsior at the equally luxurious Hotel Ambassador.
+And so she went on, taking first one side and then the other, and making quite a conversation of it altogether; but after a few minutes she heard a voice outside, and stopped to listen. That is a Rate of knots. If this figure is correct, it would mean that intelligent life on Earth has developed only because of the lucky chance that there have been no major collisions in the last 70 million years. Go figure. 
+O Romeo, Romeo! wherefore art thou Romeo.
+This question the Dodo could not answer without a great deal of thought, and it sat for a long time with one finger pressed upon its forehead (the position in which you usually see Shakespeare, in the pictures of him), while the rest waited in silence. A living being usually has two elements: a set of instructions that tell the system how to sustain and reproduce itself, and a mechanism to carry out the instructions. So junior's bedroom was usually tricked out with heavy, nondescript pieces that supposedly could take the hard knocks, while the fine secretary was relegated to the parlor where it was for show only. It sounded an excellent plan, no doubt, and very neatly and simply arranged; the only difficulty was, that she had not the smallest idea how to set about it; and while she was peering about anxiously among the trees, a little sharp bark just over her head made her look up in a great hurry. As we look out at the universe, we are looking back in time, because light ha
 d to leave distant objects a long time ago, to reach us at the present time. 
+Happily for posterity, then, the Boston Association did not actually command Parker to leave the room, though it came too close for comfort to what would have been an unforgivable brutality. Therefore I'm mad.' Therefore will not we fear, though the earth be removed, and though the mountains be carried into the midst of the sea come, behold the works of the Lord, what desolations He hath made in the earth. `There's more evidence to come yet, please your Majesty,' said the wolf, jumping up in a great hurry; `this paper has just been picked up.' The Fulton County Grand Jury said Friday an investigation of Atlanta's recent primary election produced no evidence that any irregularities took place.
+Because this unit is very small, one does not notice that a normal top really slows down in a rapid sequence of discrete steps, rather than as a continuous process. Top notch. Vandiver opened his race for governor in 1958 with a battle in the Legislature against the issuance of $50 million worth of additional rural roads bonds proposed by then Gov. Marvin Griffin. The Jazz Three displayed their sound musicianship, not only in their own chosen set, but as the emergency accompanists for Al Minns & Leon James, the superb jazz dancers who have now been Newport performers for three successive years, gradually moving up from a morning seminar on the evolution of the blues to a spot on the evening program. During the war, we set up schools for the teaching of psychological warfare, which included the teaching of propaganda, both black and white and the various shades of grey in between.
+Dissenting views of senators two strong dissents from the majority report of the Joint Economic Committee (May 2) by Senators Proxmire and Butler allege that the New Deal fiscal policy of the Thirties did not work. On various pretexts they all moved off, and Hannah was soon left alone. He says it kills all the rats and -- oh dear!' cried Katie in a sorrowful tone, `I'm afraid I've offended it again!' The company has billed the United States Government for $7,500,000 of these expenses under the Defense Department regulation allowing costs of a type generally recognized as ordinary and necessary for the conduct of the contractor's business. It is not clear that intelligence has any long-term survival value. 
+Play by ear. Back of clay scored or roughened for proper gripping surface. Emory University's Board of Trustees announced Friday that it was prepared to accept students of any race as soon as the state's tax laws made such a step possible. `Do you mean that you think you can find out the answer to it?' said the Welshman. 
+Near the knuckle.
+Five years ago a House & Home Round Table cosponsored by the Lumber Dealers' Research Council reported unhappily : only one lumber dealer in ten is equipped to handle unit loads; only one box car in eight has the wide doors needed for unit loads; only one producer in a hundred is equipped to package and ship unit loads; only one builder in a thousand is equipped to receive unit loads. Peace dividend. `Well, there was Mystery,' the ostrich replied, counting off the subjects on his flappers, `-- Mystery, ancient and modern, with Seaography: then Drawling -- the Drawling-master was an old conger-eel, that used to come once a week: HE taught us Drawling, Stretching, and Fainting in Coils.' Middle of the road. The energy in the packets or quanta, is higher for ultra violet and x-rays, than for infra red or visible light. 
+There is no dynamical reason why the motion of bodies in the solar system can not be extrapolated back in time, far beyond four thousand and four BC, the date for the creation of the universe, according to the book of Genesis. Go By the book. `Who's making personal remarks now?' the American asked triumphantly. These voters view the political process as a secret conspiracy, the object of which is to plunder them. The situation was different, however, when it was realised that the universe is not static, but expanding. 
+In view of the present situation in Laos, said the Pentagon's announcement, we are taking normal precautionary actions to increase the readiness of our forces in the Pacific. and third shots, but then there was an agonizing wait of several minutes while Coe graciously putted out, giving Palmer a chance to recover his composure, which he had quite visibly lost. The order in one body can increase, provided that the amount of disorder in its surroundings increases by a greater amount. Some schools were technical -- the Belgians needed carpenters and mechanics to help exploit the land, and trained many. Without these massive trucks highways would still be just an idea of the future.
+By contrast, there are about 50,000 new books published in the English language each year, containing of the order of a hundred billion bits of information. This is not contemporary English. She speaks the Queen's English. One can not make nucleic acids in the laboratory, from non-living material, let alone RNA. The Kennedy plan alone would boost the base to $5,000 a year and the payroll tax to 6.5 per cent -- 3.25 per cent each.
+All the world's a stage, and all the men and women merely players. `I -- I'm a little girl,' said Katy, rather doubtfully, as she remembered the number of changes she had gone through that day. The objectification of the world of spirit in popular superstition had certainly gone far beyond what the experience of spirit could justify or support. Nor can we be sure that every line of sight from us will pass through a galaxy. 
+The integrity of the office not merely requires that the Secretary General shall be, as the Charter puts it, the chief administrative officer of the Organization, but that neither he nor his staff shall seek or receive instructions from any government or any other authority external to the Organization.
+Joanne tried to fancy to herself what such an extraordinary ways of living would be like, but it puzzled her too much, so she went on: `But why did they live at the bottom of a well?' The burden of Mr. Wesker's message is that people living close to the soil (at least in England) are not the happy, fine, strong, natural, earthy people city-bred intellectuals imagine. Living together. Meeting a more advanced civilisation, at our present stage, might be a bit like the original inhabitants of America meeting Columbus. The editorial Confrontation was certainly direct in its appeal to those of us living here in America.
+Patrolman James F. Simms said he started in pursuit when he saw young Stickney speeding north in Stewart Avenue at Central Street. `Pray don't trouble yourself to say it any longer than that,' said Jo. In this, space and time were no longer separate and independent entities. But can we any longer afford the luxury of such smug indigation? Even the information, about what fell into the hole, could not come out again when the hole finally disappears. 
+But of course, there is a third direction at right angles to these two, and that is up or down. Third time's a charm. With justified bitterness the author speaks of what seems to me to have been an inexcusable body of ignorance about the nature of the Russian Communist movement, about the history of its diplomacy, about what had happened in the purges, and about what had been going on in Poland and the Baltic States. The call of nature. Private parts.
+As their name suggests, they are like string, in that they have length, but a tiny cross section. He and other Soviet leaders responsible for the document were proud of having brought forward some new formulas, such as the early replacement of the dictatorship of the proletariat by an All People's State, and also of having laid down the lines for a much greater democratization of the whole hierarchy of Soviets, starting with the Supreme Soviet itself. `Call the next witness!' said the King. Expresses thanks Kowalski has spoken but little since the fire last Saturday. Double, double toil and trouble, fire burn, and cauldron bubble.
+It did so indeed, and much sooner than she had expected: before she had drunk half the bottle, she found her head pressing against the ceiling, and had to stoop to save her neck from being broken. Mr. Trimble has been in the hospital but is expected back Tuesday. If most of them weren't exactly specific -- well, that's the way it is in life, I guess. That's all folks. 
+Eleven men, a woman and a teen-age boy tramped over cold, damp, fog-enshrouded ground during a two-hour field drill in the problems of guerrilla warfare.
+Hit the ground running. Bird's eye view. The easiest way to describe this release is to say that it reproduces an interesting and effective Steinberg performance with minimal alteration of its musical values. The reduction in the number of virtual particles between the plates means that they don't hit the plates so often, and thus don't exert as much pressure on the plates, as the virtual particles outside. To be quite alone where there are no other human beings is sharply exhilarating; it is as though some pressure had suddenly been lifted, allowing an intense awareness a sharpening of the senses.
+Margaret was not a bit hurt, and she jumped up on to her feet in a moment: she looked up, but it was all dark overhead; before her was another long passage, and the fox was still in sight, hurrying down it. To Americans, it suggested something dark and mysterious, while to the British, there was the added resonance of the Black Hole of Calcutta. Pass the iron rations, please, and light another candle, for it's getting dark down here and we're minded to read a bit of world law just to pass the time away. He is a Dark horse. Four hundred million dollars of the increase is for the expanded space program, a responsibility similarly neglected by Mr. Eisenhower.
+He's a waste of space. How's your father?. He said he would not be surprised if some of the more than 30 members of the group are interested in running on the required non-partisan ballot for posts on the charter commission. The deodorant firm run by Pesce has offices in the headquarters of Glimco's discredited taxi drivers' union at 1213-15 Blue Island Av.. He seemed to have felt that the uncertainty was only provisional: but that there was an underlying reality, in which particles would have well defined positions and speeds, and would evolve according to deterministic laws, in the spirit of Laplace. 
+Robert Riefling, who gave the only piano recital of the recently concluded 23rd Beethoven Festival, penetrated deep into the spirit of the style. The spirit is willing but the flesh is weak. This reality might be known to God, but the quantum nature of light would prevent us seeing it, except through a glass darkly. However, in the 20th century, there have been two developments that show that Laplace's vision, of a complete prediction of the future, can not be realised. I visited the bank in March and wrote a story about the situation.
+I'll go to the foot of our stairs. Instead, the idea was that, as the galaxies moved apart, new galaxies were formed in between, from matter that was supposed to be continually created. There is support for the view that intelligence, was an unlikely development for life on Earth, from the chronology of evolution. It was therefore natural to believe that the human race, and maybe the whole universe, had a beginning in the fairly recent past. 
+Can you bring the networks' attention to this?
+She waited for some time without hearing anything more: at last came a rumbling of little cartwheels, and the sound of a good many voices all talking together: she made out the words: `Where's the other ladder?-- Why, I hadn't to bring but one; Bill's got the other -- Bill! fetch it here, lad!-- Here, put 'em up at this corner -- No, tie 'em together first -- they don't reach half high enough yet -- Oh! they'll do well enough; don't be particular -- Here, Bill! catch hold of this rope -- Will the roof bear?-- Mind that loose slate -- Oh, it's coming down! The violinist, in particular, is very indulgent with swoops and slides, and his tone is pinched and edgy. I do hope it'll make me grow large again, for really I'm quite tired of being such a tiny little thing!' It was, the brief writers decided, man's best hope for a peaceful and law abiding world. Abandon hope all ye who enter here.
+Since we must live in one of these universes, we should not be surprised that the physical constants are finely tuned. Does this man live in a neighborhood where all are free loaders unwilling to help themselves, but ready to demand that the community help and protect them? Confronted with this situation, most libraries either endure the severe limitations of their budgets and do what they can with what they have, or else depend on the bounty of patrons and local governments to supplement their annual funds. A little bright-eyed terrier, you know, with oh, such long curly brown hair! Since 1953 California has led the nation in enacting guarantees that public business shall be publicly conducted, but not until this year did the lawmakers in Sacramento plug the remaining loopholes in the Brown Act.
+Like taking candy from a baby. He knew he couldn't. Couldn't make head or tail of it. Janet glanced rather anxiously at the cook, to see if she meant to take the hint; but the cook was busily stirring the soup, and seemed not to be listening, so she went on again: `Twenty-four hours, I THINK; or is it twelve? My husband's hours away from home for the past years have been from 7 a.m. to 7 p.m. the early part of the week, and as late as 8 or 9 on week-ends.
+Why, there's hardly enough of me left to make ONE respectable person!' This has meant that no one person can be the master of more than a small corner of human knowledge. Beyond the pale. The Jackson report will provide some of the political support Mr. Rusk will need if he is to get rid of department personnel engaged, as Sen. Jackson puts it, in work that does not really need doing. Each man can identify himself with the history and the death of Jesus Christ because Jesus Christ has identified himself with human history and human death, coming as the head of a new humanity.
+For instance, if you were INSIDE, you might knock, and I could let you out, you know.' One could say that the information still existed inside the black hole. And to see the meaning of this new picture, imagine that you can put on more powerful glasses and go back inside the atom and have a look at it in the way we view it today. There was a dead silence instantly, and Eleanor thought to herself, `I wonder what they WILL do next! 
+It may be unstable, and life may destroy itself, or get into a dead end. 
+God is dead. As this tax base grows so then can your medium and low density residential areas grow. The builtin headache of the Barnett regime thus far has been the steady stream of job-seekers and others who feel they were given commitments by Barnett at some stage of his eight-year quest for the governor's office. `I've read that in some book, but I don't remember where.' But nowadays, if you read one book a day, it would take you about 15,000 years to read through the books in a national Library. 
+Read up. `Yes, it IS his business!' said Five, `and I'll tell him -- it was for bringing the cook tulip-roots instead of onions.' St. Johns, Mich., April 19. But science fiction fans need not lose heart. Even apart from the fact that now at the age of 31 my personal life is being totally disrupted for the second time for no very compelling reason -- I cannot help looking around at the black leather jacket brigades standing idly on the street corners and in the taverns of every American city and asking myself if our society has gone mad.
+`I wonder how many miles I've fallen by this time?' she said aloud. The scientists have also warned that no life above ground or underground, sheltered or unsheltered could be expected to survive in an area at least 50 miles in diameter. No matter how powerful a computer you have, if you put lousy data in, you will get lousy predictions out. Whitehead is here questioning David Hume's understanding of the nature of experience; he is questioning, also, every epistemology which stems from Hume's presupposition that experience is merely sense data in abstraction from causal efficacy, and that causal efficacy is something intellectually imputed to the world, not directly perceived. Hell to pay.
+They recommended, also, that at a fixed hour, let the entire family be assembled for night prayers, followed by a short reading of the Holy Scriptures. `I don't know of any that do,' Janet said very politely, feeling quite pleased to have got into a conversation. But if any realism and feeling for truth remain in the General Assembly, it is time for men of courage to measure the magnitude of the failure and urge some new approach. When sorrows come, they come not single spies, but in battalions. The Earth was formed largely out of the heavier elements, including carbon and oxygen. 
+It had to be some multiple of a basic unit. Yet with all their skills, the appeal of Mantle and Maris in 1961 comes down to one basic : the home run. And it'll fetch things when you throw them, and it'll sit up and beg for its dinner, and all sorts of things -- I can't remember half of them -- and it belongs to a farmer, you know, and he says it's so useful, it's worth a hundred pounds! Move heaven and earth. 
+It was a hive of industry.
+Margaret kept her eyes anxiously fixed on it, for she felt sure she would catch a bad cold if she did not get dry very soon. As cold as any stone. New York State has what is probably the most advanced of these co-operative systems, so well developed that it has become a model for others to follow. The Georgia State Chamber of Commerce tried to guard against the danger of eliminating potential candidates. The no boundary condition, is the statement that the laws of physics hold everywhere. 
+Hold the fort. `In my youth,' Father William replied to his son, `I feared it might injure the brain; But, now that I'm perfectly sure I have none, Why, I do it again and again.' Mrs. Blanche Dunkel, 60, who has spent 25 years in the Dwight reformatory for women for the murder in 1935 of her son-in-law, Ervin Lang, then 28, appealed for a parole at a hearing yesterday before two Illinois pardon and parole board members, John M. Bookwalter and Joseph Carpentier. Son of a gun. This may be why many religious leaders, were ready to accept the Big Bang, and the singularity theorems. 
+And so it was indeed: she was now only ten inches high, and her face brightened up at the thought that she was now the right size for going through the little door into that lovely garden. One additional lane would then be directional with the traffic burden and effectively increase the traffic carrying capability of the East River Drive by fifty percent. Sold down the river. So we will keep on getting older, and we won't return to our youth. One would still expect some sort of Big Bang singularity in real time. 
+When the pie was all finished, the Owl, as a boon, Was kindly permitted to pocket the spoon: While the Panther received knife and fork with a growl, And concluded the banquet --] `What IS the use of repeating all that stuff,' the walrus interrupted, `if you don't explain it as you go on? `What are they doing?' Left hand doesn't know what the right hand is doing. Terms and rates of interest for motors generally follow those for home appliances. But that was a bit like trying to stand against le weekend, and other franglais. 
+`No, I'll look first,' she said, `and see whether it's marked "poison" or not'; for she had read several nice little histories about children who had got burnt, and eaten up by wild beasts and other unpleasant things, all because they WOULD not remember the simple rules their friends had taught them: such as, that a red-hot poker will burn you if you hold it too long; and that if you cut your finger VERY deeply with a knife, it usually bleeds; and she had never forgotten that, if you drink much from a bottle marked `poison,' it is almost certain to disagree with you, sooner or later. Once more unto the breach, dear friends, once more. But now it could destroy the entire human race, and much of the rest of life on Earth. A Mars a day helps you work rest and play. 
+This is especially in evidence among the present generation of the suburban middle class.
+(If you don't know what a griffin is, look at the picture.) A picture paints a thousand words. A friend in need is a friend indeed. `A fine day, your Majesty!' the princess began in a low, weak voice. All that was required to evolve from early mammals, like lemurs, to humans, was a bit of fine-tuning. 
+Diana did not at all like the tone of this remark, and thought it would be as well to introduce some other subject of conversation. The major part of this collection is in the central headquarters building, and the remainder is divided among five libraries in the system designated as subject centers. The mother of a difficult child can do a great deal to help her own child and often, by sharing her experiences, she can help other mothers with the same problem. If we have not thought and made a decision entirely in these terms, then we need to submit ourselves to the following simple test : have we decided how we are to kill the other members of our household in the event of our being less injured than they are? ) from the technical standpoint, records differ from live music to the degree that they fail to convey the true color, texture, complexity, range, intensity, pulse, and pitch of the original.
+In a small number, the values will allow the existence of objects like carbon atoms, which can act as the building blocks of living systems. Off the wall. `In that case,' said the Dodo solemnly, rising to its feet, `I move that the meeting adjourn, for the immediate adoption of more energetic remedies --' `Speak English!' said the Eaglet. A new red carpet had been laid for their coming, but I walked on it, too. She went on growing, and growing, and very soon had to kneel down on the floor: in another minute there was not even room for this, and she tried the effect of lying down with one elbow against the door, and the other arm curled round her head. 
+The President also conferred with emissaries from Guatemala and Nepal who are seeking more foreign aid. Bring home the bacon. In this, the human race makes a tremendous effort to build a space ship, but just before it is due to be launched, a similar space ship appears from the other side of the galaxy, and destroys it. Alice did not dare to disobey, though she felt sure it would all come wrong, and she went on in a trembling voice:-- `I passed by his garden, and marked, with one eye, How the Owl and the Panther were sharing a pie --' [later editions continued as follows The Panther took pie-crust, and gravy, and meat, While the Owl had the dish as its share of the treat. For years he wore hand-me-down suits and homemade paper collars, was even driven to scrounging for cigarette butts in Vienna's gutters.
+Stephen was a paper tiger. He even calculated that a star of the same density as the Sun, but two hundred and fifty times the size, would have this property. The Georgia Constitution gives the Legislature the power to exempt colleges from property taxation if, among other criteria, all endowments to institutions established for white people shall be limited to white people, and all endowments to institutions established for colored people shall be limited to colored people. Space, the final frontier. 
+Barber summoned he called Vincent L. Piraro, proprietor of the shop, who summoned police and an ambulance.
+It was defeated in Congress last year. We certainly can not continue, for long, with the exponential rate of growth of knowledge that we have had in the last three hundred years. Not all St. Louis industries, of course, have a market area confined to the immediate neighborhood. Another said that her arm did not go up at first because I wouldn't let it; I thought it wasn't supposed to. Talk about creating life in our own image. 
+Talk through your hat. The further off from England the nearer is to France -- Then turn not pale, beloved snail, but come and join the dance. Lie back and think of England. Her day starts early, but no matter how many pressing letters there are to be written (and during May, which is National Salvation Army Week, there are plenty), schedules to be made or problems to be solved, Mrs. Marr's office is always open and the welcome mat is out.  IX. The beetle's story. `You can't think how glad I am to see you again, you dear old thing!' said the princess, as she tucked her arm affectionately into Cameron's, and they walked off together. 
+There is a probably apocryphal story, that when Laplace was asked by Napoleon, how God fitted into this system, he replied, 'Sire, I have not needed that hypothesis.' A cock and bull story. One day last week, Nixon faced a painful constitutional chore that required him to officiate at a joint session of Congress to hear the official tally of the Electoral College vote, and then to make sufficient declaration of the election of the man who defeated him in the tight 1960 presidential election. Hear hear. `And just as I'd taken the highest tree in the wood,' continued the Pigeon, raising its voice to a shriek, `and just as I was thinking I should be free of them at last, they must needs come wriggling down from the sky! 
+However, to create a wormhole, one needs matter that warps space-time in the opposite way, like the surface of a saddle. He must needs go that the Devil drives. Henry Hall Wilson, a student at the music camp 25 years ago and now on the President's staff as liaison representative with the House of Representatives, turned guest conductor for a Sousa march, the Stars and Stripes Forever. It is more likely that evolution is a random process, with intelligence as only one of a large number of possible outcomes. Got my mojo working.
+Cameron considered a little, and then said `The fourth.' You see the earth takes twenty-four hours to turn round on its axis --' `Talking of axes,' said the lady, `chop off her head!' The candles were lighted, and we sat on split-bamboo mats among the village notables. `Don't you mean "purpose"?' said Kate. 
+Accidentally on purpose.
+However, when they had been running half an hour or so, and were quite dry again, the Dodo suddenly called out `The race is over!' and they all crowded round it, panting, and asking, `But who has won?' When the experiment was carried out carefully, the results were inconsistent with hidden variables. `-- or next day, maybe,' the Footman continued in the same tone, exactly as if nothing had happened. A funny thing happened on the way to the theatre. The last 10 cases in the investigation of the Nov. 8 election were dismissed yesterday by Acting Judge John M. Karns, who charged that the prosecution obtained evidence by unfair and fundamentally illegal means.
+The Mouse did not notice this question, but hurriedly went on, `"-- found it advisable to go with Edgar Atheling to meet William and offer him the crown. The two lines of longitude also meet each other at the north pole, at a right angle, or 90 degrees. Never the twain shall meet. They may pass into another universe, but that is not something that will make any difference, to those of us prudent enough not to jump into a black hole. Bayreuth next summer the Bayreuth Festival opens July 23 with a new production of Tannhaeuser staged by Wieland Wagner, who is doing all the operas this time, and conducted by Wolfgang Sawallisch.
+John Wheeler called this, 'A black hole has no hair.' I became fifteen, sixteen, then twenty, and still Tessie Alpert sat on the porch with a rose in her hair, and Alfred got richer and sicker with diabetes. Hair of the dog. If I or she should chance to be Involved in this affair, He trusts to you to set them free, Exactly as we were. Fall on your sword.
+The form of Christianity to which they were exposed was for some the Protestantism of the older stock, for others the Protestantism of the nineteenth-century immigration; for still others, mostly of the nineteenth-century immigration, it was Roman Catholicism, and for a small minority it was Eastern Orthodoxy. Lock stock and barrel. If music be the food of love, play on. As the thickness of the paint layer increased, the surface area would go up. Those whom she sentenced were taken into custody by the soldiers, who of course had to leave off being arches to do this, so that by the end of half an hour or so there were no arches left, and all the players, except the King, the Queen, and June, were in custody and under sentence of execution. 
+Too light a feed, particularly with metal or other hard material, causes overheating of the tool and burning of the cutting edge. Jobs for the boys. That put paid to that idea. `I beg pardon, your Majesty,' he began, `for bringing these in: but I hadn't quite finished my tea when I was sent for.' 
+He was sent to Coventry.
+`Which would NOT be an advantage,' said Louise, who felt very glad to get an opportunity of showing off a little of her knowledge. Carnal knowledge. He unfolded the paper as he spoke, and added `It isn't a letter, after all: it's a set of verses.' The letter, dated Feb. 22, was delivered to Premier Khrushchev in Novosibirsk, Siberia, on March 9. It is a red letter day.
+In the club. This will mean that the graph of the separation of two galaxies will bend downwards, below the straight line. On each side of the motor well there's storage for battery, bumpers, line and spare props with six-gallon gas tanks below. Below the salt. We are used to thinking of intelligent life, as an inevitable consequence of evolution. 
+But we had hardly started to adjust our thinking to this new uranium weapon when we were faced with the hydrogen bomb. Put on your thinking cap. One bit of information is the answer to a yes no question. I fled, however, not from what might have been the natural fear of being unable to disguise from you that the things about my bridegroom -- in the sense you meant the word things -- which you had been galvanizing yourself to tell me as a painful part of your maternal duty were things which I had already insisted upon finding out for myself (despite, I may now say, the unspeakable awkwardness of making the discovery on principle, yes, on principle, and in cold blood) because I was resolved, as a modern woman, not to be a mollycoddle waiting for Life but to seize Life by the throat. When and if it can do so without jeopardizing constitutional and statutory tax-exemption privileges essential to the maintenance of its educational program and facilities, Emory University will con
 sider applications of persons desiring to study or work at the University without regard to race, color or creed, continuing university policy that all applications shall be considered on the basis of intellectual and moral standards and other criteria designed to assure the orderly and effective conduct of the university and the fulfillment of its mission as an institution of Christian higher education.
+`I HAVE tasted eggs, certainly,' said Louise, who was a very truthful child; `but little girls eat eggs quite as much as serpents do, you know.' They were further stripped of old wive's tales by seeing the slender, lovely Russian girls performing feats requiring tremendous strength and with not one bulging muscle. Come here directly, and get ready for your walk!" Cable ready. Bill Stickers is innocent.
+Why, I haven't had a wink of sleep these three weeks!' Brownie points. By that time, maybe the GATT trade agreement will have come into effect. Maestro's biggest stock in trade is his personality, and ability to establish a warm rapport with his audience. 
+What will be the effect on the Balance of trade?
+The universe does not behave according to our pre-conceived ideas. His technique is ample and his musical ideas are projected beautifully. But, in spite of all this, enough evidence remains to show that the magic square of three must indeed have been the object of a rather extensive cult -- or series of cults -- reaching fullest expression in the Han period. Back to square one. Austin, Texas -- a Houston teacher, now serving in the Legislature, proposed Thursday a law reducing the time spent learning educational methods.
+In addition, Mr. and Mrs. Allan Goodman are controllers, Mrs. Paul Stone is treasurer and Mrs. Albert Quell is in charge of admittance for the dancing at 9p.m.. That is a Done deal. It will be recalled from the discussion in Section 7 that the position of the right, as represented by Barth, rests on the following thesis : the only tenable alternative to Bultmann's position is a theology that (1) rejects or at least qualifies his unconditioned demand for demythologization and existential interpretation; (2) accepts instead a special biblical hermeneutics or method of interpretation; and (3) in so doing, frees itself to give appropriate emphasis to the event Jesus Christ by means of statements that, from Bultmann's point of view, are mythological. But if your theory disagrees with the Second Law of Thermodynamics, it is in bad trouble. No matter how well work is planned, bad weather or unexpected setbacks can cause extra work that must be caught up.
+In someone's bad books. So I have decided to para-phrase the quotation. Neither fish nor flesh, nor good red herring. They are called virtual particles, because they occur even in the vacuum, and they can't be directly measured by particle detectors. Its ribs showed, it was a yellow nondescript color, it suffered from a variety of sores, hair had scabbed off its body in patches.
+Despite these practical difficulties, scientific determinism, remained the official dogma throughout the 19th century. Bundle centers for the convenience of guests bundle centers have been established throughout the city and suburbs where the donations may be deposited between now and the date of the big event. `I'd rather finish my tea,' said the Iraqi, with an anxious look at the supervisor, who was reading the list of singers. However, I can re-assure anyone who is nervous about their investments that it is a bit early to sell: even if the universe does come to an end, it won't be for at least twenty billion years. Although quantum mechanics leads to uncertainty, when we try to predict both the position and the speed, it still allows us to predict, with certainty, one combination of position and speed. 
+Don't try to teach your Grandma to suck eggs. Teaching, research and study, according to highest standards, under Christian influence, are paramount in the Emory University policy. The dance, dancers and dance enthusiasts (8,500 of them) had a much better time of it at Lewisohn Stadium on Saturday night than all had had two nights earlier, when Stadium Concerts presented the first of two dance programs. It is a nation of shopkeepers. 
+Lay it on with a trowel.
+Excuse my French. I remember Ernest Bloch in the foyer, shouting in his high-pitched voice : it may be a tour de force, mais mon Dieu, can anyone take this music seriously? It makes my work a great deal easier to be able to pray for the Lord's guidance while ministering to the physical needs of my patients. In this, the internal record of information, handed down to succeeding generations in DNA, has not changed significantly. Other lettermen from the team that compiled a 21-9 record and finished as runner-up in the National Invitation Tournament were : Art Hambric, Donnell Reid, Bill Nordmann, Dave Harris, Dave Luechtefeld and George Latinovich.
+Off the record. If there is a black hole around, one member of a particle anti particle pair may fall into the hole, leaving the other member without a partner, with which to annihilate. He said he was confessing that I was a member of the Socialist Party in 1910. Last came a little feeble, squeaking voice, (`That's Bill,' thought Laurie,) `Well, I hardly know -- No more, thank ye; I'm better now -- but I'm a deal too flustered to tell you -- all I know is, something comes at me like a Jack-in-the-box, and up I goes like a sky-rocket!' The greatest opacity over a broad wave band, for a given density, comes from ionised hydrogen. 
+When push comes to shove. This is a way of getting to school, but, I understand, it entails a certain loss of social status. How far that pedimented and pillared style has shed its influence Mr. Sansom reminds us thus : the white colonnaded, cedar-roofed Southern mansion is directly traceable via the grey and buff stone of grey-skied England to the golden stucco of one particular part of the blue South, the Palladian orbit stretching out from Vicenza : the old mind of Andrea Palladio still smiles from behind many an old rocking chair on a Southern porch, the deep friezes of his architectonic music rise firm above the shallower freeze in the kitchen, his feeling for light and shade brings a glitter from a tall mint julep, his sense of columns framing the warm velvet night has brought together a million couple of mating lips. From strength to strength. I shall take this to include the human race, even though much of its behaviour through out history, has been pretty stupid, an
 d not calculated to aid the survival of the species. 
+However, if the three-dimensional space, were really the surface of a sphere in another dimension, its volume would be large but finite. Cylinder volume can be determined mathematically but combustion chamber volume must be measured with a liquid. The fact that Sloan was an extrovert, concerned primarily with what he saw, adds greatly to the value of his art as a human chronicle. `It tells the day of the month, and doesn't tell what o'clock it is!' There's an R in the month.
+With good reason it appeared that a new day was upon divided Christendom. About a minute after the Big Bang, the temperature would have fallen to about a billion degrees, about a hundred times the temperature in the Sun. Indian summer. Margaret waited a little, half expecting to see it again, but it did not appear, and after a minute or two she walked on in the direction in which the African was said to live. 
+Maybe today'll be a good-news day.
+Soo -- oop of the e -- e -- evening, Beautiful, beautiful Soup! The universe would have continued to expand, and cool. The Troop is proud of its camping-out program -- on year-round schedule and was continued even when sub-zero temperatures were registered during the past winter. So she tucked it away under her arm, that it might not escape again, and went back for a little more conversation with her friend. Perhaps the Pirate who will be the unhappiest over the news that Musial probably will sit out most of the series is Bob Friend, who was beaten by The Man twice last season on dramatic home runs.
+After all, the henpecked husband with his shrewish wife is a comic figure of long standing, in literature and on the stage, as Dr. Schillinger points out. Business Week (Aug. 9, 1961) reports that the United Aircraft Company, against which the International Association of Machinists had undertaken a strike, decided to keep its plants operating. Word association football. All-weather roads must be provided next to the feeding floor so access will be possible all year. The door led right into a large kitchen, which was full of smoke from one end to the other: the honey was sitting on a three-legged stool in the middle, nursing a baby; the cook was leaning over the fire, stirring a large cauldron which seemed to be full of soup. 
+Planets going round pulsars are unlikely to have life, because any living beings would have been killed, in the supernova explosion that led to the star becoming a pulsar. Lions led by donkeys. Drummed out of the army. It was argued, that as you plotted the position of the galaxies back in time, the sideways peculiar velocities, would have meant that the galaxies wouldn't have all met up. The next time the butterfly flaps its wings, a host of other things will be different, which will also influence the weather. 
+Under the influence. Then she went to work nibbling at the mushroom (she had kept a piece of it in her pocket) till she was about a foot high: then she walked down the little passage: and THEN -- she found herself at last in the beautiful garden, among the bright flower-beds and the cool fountains. According to the classical 19th century ideas, dating back to Laplace, a hot body, like a piece of red hot metal, should give off radiation. It is indeed true, as stated in the famous novel of our day, For Whom The Bell Tolls, that no man is an island, entirely of itself; every man is a piece of the continent, a part of the main. `I shall sit here,' the Footman remarked, `till tomorrow --' At this moment the door of the house opened, and a large plate came skimming out, straight at the Footman's head: it just grazed his nose, and broke to pieces against one of the trees behind him. 
+The Heavens opened. Mrs. Chase is the former Miss Mary Mullenax. At first, these changes will be confined to the repair of genetic defects, like cystic fibrosis, and muscular dystrophy. Shadow over Washington Square to the editor of the Inquirer : I wish to advocate two drastic changes in Washington Square : 1. 
+Let's ring the changes.
+He had a snowball in hell's chance. My husband and I would like to advise you that it is piping hot. It produced a series of enormous fireballs. In the average situation about one-third of those visited make commitments to Christ and the Church.
+He threw a spanner in the works. In other words, atrocities by savages wearing the uniform of the central government might be condoned, had the victims been serving the cause of dissident Katanga. However, although a way to describe curved spaces, was developed by the German, George Friedrich Riemann, in 1854, it remained just a piece of mathematics for sixty years. George Raft. And she went on planning to herself how she would manage it. 
+However, even this degree of certainty, seems to be threatened by more recent developments. The third degree. Eventually, they would have stopped expanding, and would have collapsed in on themselves, to form stars and galaxies. During one recent day of driving about Los Angeles there were actually a dozen occasions when oncoming drivers stopped an entire lane of traffic to permit me to pull out of an impossible side street. Something is wrong when these things happen.
+The wrong side of the blanket. The opening paragraph of the chapter titled the Theory Of Representative Perception, in the book Philosophies Of Science by Albert G. Ramsperger says, passed on to the brain, and there, by some unexplained process, it causes the mind to have a perception. But life could have taken 7 billion years to develop, and still have left time to evolve to beings like us, who could ask about the origin of life. I have done all this for the freedom of the individuals concerned and also for the states which have been threatened by Communist domination. `I'm afraid I can't put it more clearly,' Pat replied very politely, `for I can't understand it myself to begin with; and being so many different sizes in a day is very confusing.' 
+Clearly, this is something that one would like to believe, but it is a hypothesis. The shift is very small, about a thousandth of a degree, equivalent to a movement of an inch, at a distance of a mile. While patent suits are still among the most complex and expensive forms of litigation, these rules have saved litigants uncounted sums of money. Chuck a 2'' or 3'' piece of 1/8'' dia. drill rod in a drill press or electric hand tool. 
+Interfaith conflicts which spring from psychological deficiencies are the most unfortunate of all, for they have no redeeming features whatsoever.
+No spring chicken. `Consider your verdict,' the King said to the jury. Consider now placing heavier and heavier, and more and more concentrated weights on the rubber sheet. What operational meaning can one give to the existence of all those other universes? It's high time you were all in bed!' 
+Doctor Lee asked her to lie down on a bed and remove her shoes. It is a bed of roses. She went in without knocking, and hurried upstairs, in great fear lest she should meet the real Mary Ann, and be turned out of the house before she had found the fan and gloves. For a neutral Germany Soviets said to fear resurgence of German militarism to the editor of the New York Times : for the first time in history the entire world is dominated by two large, powerful nations armed with murderous nuclear weapons that make conventional warfare of the past a nullity. Thus there must be a lot of matter at a great distance from us. 
+No doubt, there was still a lot in the Draft Program -- and in Khrushchev's speech -- which left many points obscure. The intensive treatment program is working well. Billie was really beautiful ] exclaimed Vera Forbes Adams, batting lovely big eyes behind glitter rimmed glasses. At this moment the King, who had been for some time busily writing in his note-book, cackled out `Silence!' and read out from his book, `Rule Forty-two. As queer as a nine bob note.
+First it marked out a race-course, in a sort of circle, (`the exact shape doesn't matter,' it said,) and then all the party were placed along the course, here and there. When Huff attempted to cash another $100 check there Monday, hotel officials called police. She felt that she was dozing off, and had just begun to dream that she was walking hand in hand with Dinah, and saying to her very earnestly, `Now, Dinah, tell me the truth: did you ever eat a bat?' when suddenly, thump! thump! down she came upon a heap of sticks and dry leaves, and the fall was over. This is based on the self-evident truth, that if the universe had not been suitable for life, we wouldn't be asking why it is so finely adjusted. While you live, tell truth and shame the Devil!.
+A two-run homer by Norm Siebern and a solo blast by Bill Tuttle tied the game, and single runs in the eighth and ninth gave the Athletics their fifth victory in eight starts. The game is up. He asked intimate questions and got frank answers from the members of what he calls the candidates' in-groups. "There's a porpoise close behind us, and he's treading on my tail. 
+She said, when she learned Jackie was heading home : I'm just speculating, but I have to think Jack feels he's hurting Boston's chances.
+With greater investments in plant facilities, with automation growing, you can't switch around, either in volume or in product design, as much as was formerly possible -- or at least not as economically. As soon as she had made out the proper way of nursing it, (which was to twist it up into a sort of knot, and then keep tight hold of its right ear and left foot, so as to prevent its undoing itself,) she carried it out into the open air. `You mean you can't take LESS,' said the Afghan: `it's very easy to take MORE than nothing.' These are controlled by single genes, and so are fairly easy to identify, and correct. For the most part, his writing rambles and jogs, preventing easy access by the reader to his true thoughts.
+The Indian opened his eyes very wide on hearing this; but all he SAID was, `Why is a raven like a writing-desk?' A Wide boy. So she sat on, with closed eyes, and half believed herself in Wonderland, though she knew she had but to open them again, and all would change to dull reality -- the grass would be only rustling in the wind, and the pool rippling to the waving of the reeds -- the rattling teacups would change to tinkling sheep- bells, and the Queen of Spade's shrill cries to the voice of the shepherd boy -- and the sneeze of the baby, the shriek of the lemur, and all thy other queer noises, would change (she knew) to the confused clamour of the busy farm-yard -- while the lowing of the cattle in the distance would take the place of the grasshopper's heavy sobs. Bought the farm. Never in my life have I felt so remorseful about anything I've done as I did about spending that night with my own wife.
+It looked good- natured, she thought: still it had VERY long claws and a great many teeth, so she felt that it ought to be treated with respect. As Hudson resumed his desperate criss-crossing of the little bay, every incident lessened the crew's respect for him. A Man's got to do what a man's got to do. She may well be incapacitated by it when she is confronted with present and future alternatives -- e.g., whether to prepare primarily for a career or for the role of a homemaker; whether to stay financially dependent on her parents or help support herself while attending school; whether to pursue a college education or a job after high school; and whether to attend this or that college and to follow this or that course of study. Then, if the middle number is activated to its greatest potential in terms of this square, through multiplying it by the highest number, 9 (which is the square of the base number), the result is 45; and the latter is the total sum of all the numbers i
 n the square, by which all the other numbers are overshadowed and in which they may be said to be absorbed.
+`They were learning to draw,' the gerbil went on, yawning and rubbing its eyes, for it was getting very sleepy; `and they drew all manner of things -- everything that begins with an M --' `Why with an M?' said Joan. (Babin has acquired some of Schnabel's keyboard manner, but his playing is of limited insight. It is a Whig history of the Tory reaction which preceded the Reform Bill of 1832, and it uses the figure of Grey to give some unity to the narrative. That would be a knee-jerk reaction. Here one of the guinea-pigs cheered, and was immediately suppressed by the officers of the court. 
+Dealers' stocks down with dealer stocks of new equipment averaging about 25% below a year ago, the affects of the rural recovery are being felt almost immediately by the country's farm equipment manufacturers. He also expanded and modernized the radio system with a central control station. The other possibility is what I call, the alternative histories approach. On a larger scale, they could be galactic latitude and longitude, and distance from the center of the galaxy. 
+`I can't go no lower,' said the Pakistani: `I'm on the floor, as it is.' 
+Because there are fewer virtual particles, or vacuum fluctuations, between the plates, they have a lower energy density, than in the region outside. In your sales force, will a smaller number of higher-priced, high-quality salesmen serve you best, or can you make out better with a larger number of lower-paid salesmen? That carbon atoms should exist at all, with the properties that they have, requires a fine adjustment of physical constants, such as the QCD scale, the electric charge, and even the dimension of space-time. o sell you a couple?' A heart attack when she was barely 20 put an end to the 10-hour daily practicing.
+Not the noblest performance we have heard him play, or the most spacious, or even the most eloquent. Oh, she was just the maid there, he replied, waving a hand to indicate how completely unimportant she was. Beware the ides of March. ALL PERSONS MORE THAN A MILE HIGH TO LEAVE THE COURT.' The conclusion of this lecture is that rapid space-travel, or travel back in time, can't be ruled out, according to our present understanding. 
+They had a two-hour luncheon together in an atmosphere of cordial understanding and relaxation, she said. Hilda caught the baby with some difficulty, as it was a queer- shaped little creature, and held out its arms and legs in all directions, `just like a star-fish,' thought Audrey. At present it's available in one model, the fine and familiar Smith & Wesson Magnum revolver (about $110), long a top-quality handgun among target arms. New York : Democrats' choice registered Democrats in New York City this year have the opportunity to elect their party's candidates for Mayor and other municipal posts and the men who will run their party organization. That would be a photo opportunity.
+Sonar can be used to measure the thickness of the heart by placing small crystal transducers at opposite sides of the heart or blood vessel and exciting one with some pulsed ultrasonic energy. Although on average, the galaxies are moving apart from each other at a steady rate, they also have small additional velocities, relative to the uniform expansion. Instead, one has to use technical terms, like closed time like curves, which are code for time travel. Their ham butts, cured in oak-log smoke, were also esteemed when roasted or boiled, and served with this original sauce : Wright's devil sauce; put into a saucepan a cupful of the baked ham gravy, or of the boiled ham liquor, with a half stick of butter, three teaspoonfuls of made mustard, and two mashed garlic cloves. In his 1915 paper, Einstein showed that the effects of gravity could be described, by supposing that space-time was warped or distorted, by the matter and energy in it. 
+A Peace Corps official described the editorial as precisely the message we need to communicate to the men and women who will soon be Peace Corps volunteers. Only I don't think,' Sarah went on, `that they'd let Dinah stop in the house if it began ordering people about like that!' It may be fostered by frustration, depression, insecurity -- or, in children, simply by the desire to stop an anxious mother's nagging. He has a face that could stop a clock. 
+The statement did not mention what steps might be taken to overcome the legal obstacles to desegregation.
+The British physicist, John Bell, who died recently, devised an experimental test that would distinguish hidden variable theories. Acid test. Big white chief. Murray makes a complete line of ginning equipment except for driers and cleaners, and this machinery is purchased from a Dallas-based firm. These so-called "peculiar velocities" of the galaxies, may be directed sideways to the main expansion. 
+Main chance. If you know the wave function at one time, then its values at other times are determined by what is called the Schroedinger equation. The entire concept of cerebral imagery as the physical basis of a mental image can find no logical support. Spitting image. It must be remembered that the fiber plates replace a glass window and a (mica) membrane, in addition to an optical output lens system.
+For example, in Burma and Ceylon many Buddhists argue that Buddhism ought to be the official state religion. Religion is the opiate of the masses. Even at this short distance they were only vague shapes, setting up the machine gun on a small knoll so that it could fire above the heads of the rest of the patrol. Don't miss the pansies that appear from time to time through the winter. Fie, foh, and fum, I smell the blood of a British man.
+These were the verses the hare read:-- `They told me you had been to her, And mentioned me to him: She gave me a good character, But said I could not swim. I would like to propose a toast to the Bride, sung by Clarence Nordstrom, playing a character called Old Man Toomey, is quite simple, direct and touching. `Yes,' said Sara, `we learned French and music.' It fell, February 6, 1827, carrying with it a horse and wagon, two men and four oxen. Once we have red the book of life, we will start writing in corrections. 
+The writing is on the wall. In another minute the whole head appeared, and then Sarah put down her flamingo, and began an account of the game, feeling very glad she had someone to listen to her. I put Arger on the payroll because he promised to get my firm the stevedore account at Navy pier, Stein said. The next thing was to eat the comfits: this caused some noise and confusion, as the large birds complained that they could not taste theirs, and the small ones choked and had to be patted on the back. 
+A large, well-stocked library, surrounded in a county by smaller ones, may feel that the demands on its resources are likely to be too great.
+In fact, the theory that the universe has existed forever is in serious difficulty with the Second Law of Thermodynamics. There are four types of nucleic acid, adenine, cytosine, guanine, and thiamine. Networks illustrating some special types of organization the cocktail party. A little more than twenty years ago the American people turned an important corner. The princess took no notice of them even when they hit her; and the baby was howling so much already, that it was quite impossible to say whether the blows hurt it or not. 
+It could describe curved spaces that existed in the abstract, but there seemed no reason why the physical space we lived in, should be curved. The artist was born in Gilbert Mills, New York, in 1886, and until two years ago when he and his wife moved to California, he lived in western New York, in Batavia. They are in French of course, not that I expect that would be any problem with this audience. There seemed to be no use in waiting by the little door, so she went back to the table, half hoping she might find another key on it, or at any rate a book of rules for shutting people up like telescopes: this time she found a little bottle on it, (`which certainly was not here before,' said Sara,) and round the neck of the bottle was a paper label, with the words `DRINK ME' beautifully printed on it in large letters. He returned in command of an international army of Gurkhas, Indians, Africans, Chinese and British.
+Put your best foot forward. I heard it straight from the horse's mouth. Generally, states reserve for communities the right to have local ordinances regulating speed and other activities. So they began solemnly dancing round and round Nora, every now and then treading on her toes when they passed too close, and waving their forepaws to mark the time, while the bee sang this, very slowly and sadly:-- `"Will you walk a little faster?" said a whiting to a snail. He said the snow plan was put in effect too slowly in December.
+It was a seven day wonder. Nora had never been in a court of justice before, but she had read about them in books, and she was quite pleased to find that she knew the name of nearly everything there. In an age of oratory, he was the king of orators, and both he himself and Chief Justice Marshall were bathed in manly tears, as Uncle Dan'l reached his thundering climax : it is, sir, as I have said, a small college, and yet there are those who love it. Poetic justice. The moving finger writes.
+The quality of mercy is not strained. The design of a mechanical interlocking frame is much like a mechanical puzzle, but once understood, the principles can be applied to any track and signal arrangement. Obviously, it was not designed for molecular biologists. The Lenin tomb is obviously adequate for double occupancy, Moscow is a crowded city, and the creed of Communism deplores waste. 
+Take your choice!' 
+Hobson's choice. Poor winds and fog locked her up in a harbor the crew called Lousie Bay. The responsibility for taking the initiative in generating ideas is that of every officer in the Department who has a policy function, regardless of rank. I --' `Oh, don't bother ME,' said the queen; `I never could abide figures!' Here are some of the newer items currently available : Poster Products Inc., Chicago, Ill. : a changeable copy and display sign which consists of an extruded impact styrene background in choice of colors, onto which are mounted snap-in letters, figures, or words screened on acetate or other types of sheet stock.
+In biology, these two parts are called genes and metabolism. It recommends that the United States seek instead to detach the Castro regime from the Communist bloc by working for a diplomatic detente and a resumption of trade relations; and concentrate its constructive efforts on eliminating in other parts of Latin America the social conditions on which totalitarian nationalism feeds. ) wishing to show that aviation was dependable and here to stay, Bob Fogg always made a point of taking off each morning on the dot of seven, disregarding rain, snow and sleet in true postal tradition. It is a bit like saying that you can't buy sugar loose in the supermarket, but only in kilogram bags. 
+It goes without saying. That goes without saying! 
+There are other versions of this paradox, like going back, and killing your parents before you were born, but they are essentially equivalent. The rate, at which the wave function varies from point to point, gives the speed of the particle. Who gives a rat's ass?. `Nothing whatever,' said Pauline. One will end up with the same state outside the hole, whatever one threw in, provided it has the same mass. 
+Well, whatever you have, that's it. you've got to learn to live with it. A very casual, pleasant program -- one of those easy-going things that make Newport's afternoon programs such a relaxing delight -- was held again under sunny skies, hot sun, and a fresh breeze for an audience of at least a couple of thousands who came to Newport to hear music rather than go to the beach. The Sun is over the yard arm. The hospitals contain patients trampled by elephants or run over by sports cars. O ye, of little faith.
+Eight years ago while we were going through the mud-sweat-and-tears construction period, we were each solaced by the vision of early morning dips and evening home-comings to a cool family collected around the pool with a buffet table laid out nearby for the lord and master's delectation. I thought this project was worth supporting, though it was cancelled due to a lack of funds. When there is employment opportunity for youth, this arrangement -- or lack of arrangement -- works out quite well. Thus, the future of the universe is not completely determined by the laws of science, and its present state, as Laplace thought. 
+And this would mean that we live in a mechanistic universe, governed by the laws of cause and effect, bound in chains of determinism that hold the universe on a completely predetermined course in which there is not room for soul or spirit or human freedom.
+Heavy metal. So it is no good waiting until the universe re-collapses, to return to your youth. We have to tell ourselves that when Parker spoke in this vein, he believed what he said, because he could continue, but the truth, which cost me bitter tears to say, I must speak, though it cost other tears hotter than fire. Speak softly and carry a big stick. If the ball were in a flat three-dimensional space, one could go on adding paint indefinitely, and the ball would get bigger and bigger. 
+Most of it is panelized and utilizes standard materials, and requires the use of only simple tools. Bog standard. The defensiveness has been exaggerated by another bad habit, our tendency to rate the goodness or badness of other nations by the extent to which they applaud the slogans we circulate about ourselves. Visit either you like: they're both mad.' South Viet Nam has received $1,450,000,000 in United States aid since 1954 and the rate of assistance has been stepped up since Vice President Lyndon B. Johnson's visit last May.
+Visit the ladies room. It was put on a firm mathematical basis by Newton, more than 300 years ago, and we still use his theory of gravity to predict the motion of almost all celestial bodies. Many scientists are like Einstein, in that they have a deep emotional attachment to determinism. The effects of earthquakes on civilization have been widely publicized, even overemphasized. Body language.
+Under the proposal the members of the board of trustees of a county college will be appointed; none will be elected. There is a Price on his head. The research center of the University's School of Business and Public Administration is prepared to undertake the analysis Dr. Ellis has been talking about. However nothing on four legs was supposed to be faster than a lion over a short distance, unless it was a cheetah. If one can determine that there is enough matter in the universe, to focus our past light cone, one can then apply the singularity theorems, to show that time must have a beginning. 
+Without agreeing with every phrase in this statement, we must certainly assert the great difference between Christian love and any form of resistance, and then go on beyond the Mennonite position and affirm that Christian love-in-action must first justify and then determine the moral principles limiting resistance. All this will serve to show off the Ory style in fine fashion and is a must for those who want to collect elements of the old-time jazz before it is too late to lay hands on the gems. `It must be a very pretty dance,' said Olive timidly. The basic costs are generally pretty much the same regardless of the agency through which you reserve your car, but some of them offer supplementary advantages. 
+That is a pretty pickle.
+`That WAS a narrow escape!' said Ingrid, a good deal frightened at the sudden change, but very glad to find herself still in existence; `and now for the garden!' and she ran with all speed back to the little door: but, alas! the little door was shut again, and the little golden key was lying on the glass table as before, `and things are worse than ever,' thought the poor child, `for I never was so small as this before, never! Cop, an attitude. Finally, whatever the techniques used, a twin goal is common to all preventive casework service : to cushion or reduce the force of the stress impact while at the same time to encourage and support family members to mobilize and use their ego capacities. In practice, however, our ability to predict the future is severely limited by the complexity of the equations, and the fact that they often have a property called chaos. Fort Lauderdale -- a series of high school assemblies to acquaint junior and senior students with the Junior Achiev
 ement program begins at St. Thomas Aquinas Monday.
+I can't tell when, but I'm positive I witnessed this same scene of this particular gathering at some time in the past ] this experience will have happened to many of you. `But you're so easily offended, you know!' But I questioned, also, professional soldiers, who would not easily be hypnotized by a septuagenarian's dreamy irredentism. Miss Bouton headed up one of the four groups that went on simultaneous tours after the Gallery had closed at 5 p.m.. I feel compelled to write this because I am greatly concerned with the problem of community growth rate and the relation between types of growth in a town such as East Greenwich.
+The only original works attempting to reach any stature : Tennessee Williams' disappointing domestic comedy, Period Of Adjustment, and Arthur Laurents' clever but empty Invitation To A March. Some people would use the term, evolution, only for the internally transmitted genetic material, and would object to it being applied to information handed down externally. Carl has been married to Paula for fifty-three years, and he has not made a single major decision without careful consideration and thorough discussion with his wife. Fiedler was then technical director of Hitler's super-secret Reichenberg project, which remained unknown to the Allies until after the war. Keep the belt just tight enough so the pulleys won't slip when pulled by hand; excess tension will only cause undue wear on the motor and spindle bearings.
+At last the horse said to the cow, `Drive on, old fellow! Season of mists and mellow fruitfulness. If one couldn't go faster than light, the round trip to the nearest star, would take at least eight years, and to the center of the galaxy, at least eighty thousand years. Behind the eight ball. Leave the clay on plaster board to dry slowly, covered lightly with a loose piece of plastic or cloth to prevent warping.
+The victim Darnell Somerville, Negro, 1, was pronounced dead on arrival at Anne Arundel General Hospital in Annapolis. Now a quiet-spoken, middle-aged man, Fiedler is an aeronautical engineer for Lockheed's Missiles and Space Division at Sunnyvale, where he played a key role in the development of the Navy's Polaris missile. The players all played at once without waiting for turns, quarrelling all the while, and fighting for the hedgehogs; and in a very short time the official was in a furious passion, and went stamping about, and shouting `Off with his head!' or `Off with her head!' about once in a minute. My lights would have been a giveaway if I'd tried to shadow him in the conventional manner. 
+Date rape.
+While neighbor women assumed some of the dead mother's duties, fund-raising events were being planned by a homeowners association and a student council for the hard-hit Henry Kowalski family, 34220 Viceroy. Play the race card. The Rev. Richard Freeman of Texas City officiated and Charles Pabor and Mrs. Marvin Hand presented music. We'll not talk out of one side of our mouth in Morris County and out of the other side in Hudson. `There's no sort of use in knocking,' said the Footman, `and that for two reasons. 
+He has -- for unclear reasons -- a 25% higher death rate from cancer. Undertaken by 32 American scholars, under the chairmanship of Rev. Dr. Luther A. Weigle, former dean of Yale University Divinity School, their studies resulted in the publishing of the Revised Standard Version, 1946-52. In the case of the universe, the fact that the microwave background has such an exactly thermal spectrum indicates that it must have been scattered many times. As he applied the applicator extending from the machine -- which consisted of seven differently colored neon tubes superimposed on a rectangular base -- to the supposedly diseased portions of Mrs. Shaefer's body, Lee kept up a steady stream of pseudo-scientific mumbo-jumbo. Maybe there was some simpler form of organisation, which built up DNA. 
+The interlocking frame we built at the model railroader workshop and then installed on Paul Larson's railroad follows the Fig. 1 scheme and is shown beginning in Fig. 7, page 65, and in the photos. Jerry built. A chin too prominent in relation to the rest of the face, a thrusting forward of the lower front teeth, an overdeveloped lower jawbone, and an underdeveloped upper jaw indicate the opposite type of malocclusion. It will be much more difficult to find them, and work out the relations between them. What this would give rise to, we don't yet know. 
+Rise and shine. Closely related to time travel, is the ability to travel rapidly from one position in space, to another. related to the collector, who is actually no more than the amateur who has taken to the field. But Freeman Dyson has shown that, despite this, life could adapt to the ever-decreasing supply of ordered energy, and therefore could, in principle, continue forever. The Sequoia Grove presents another unique aspect of Yosemite, for these ancient giant trees are a sight never to be forgotten.
+But at that point, the system becomes unstable, and the intelligent life destroys itself. A bit of fluff. He looked anxiously over his shoulder as he spoke, and then raised himself upon tiptoe, put his mouth close to her ear, and whispered `She's under sentence of execution.' No one anticipates any radical shift in this situation, but questions concerning reading habits, the availability of such data and the places where it is discussed must surely be raised. 
+The executioner's argument was, that you couldn't cut off a head unless there was a body to cut it off from: that he had never had to do such a thing before, and he wasn't going to begin at HIS time of life. 
+`-- and just take his head off outside,' the mistress added to one of the officers: but the Englishman was out of sight before the officer could get to the door. The miserable policeman dropped his teacup and bread-and-butter, and went down on one knee. Vernon was serviceable on the botanical field trips, but he could arrange no schedule with the cooks, and he was glad when the trips dropped off, and the botanists began to motor out by themselves. All the time they were playing the hostess never left off quarrelling with the other players, and shouting `Off with his head!' or `Off with her head!' The King and Queen of Hearts were seated on their throne when they arrived, with a great crowd assembled about them -- all sorts of little birds and beasts, as well as the whole pack of cards: the Knave was standing before them, in chains, with a soldier on each side to guard him; and near the King was the rabbit, with a trumpet in one hand, and a scroll of parchment in the other. 
+Imaginary time may sound like science fiction, and it has been brought into Doctor Who. Doctor Livingstone I presume. In other words, Quantum Theory allows the energy density to be negative in some places, provided it is positive in others. You will walk some of the narrow, old streets, hemmed in by massive palazzi. Walk on eggshells.
+To sum up, what I have been talking about, is whether the universe evolves in an arbitrary way, or whether it is deterministic. Pressing designs : the size of wooden mold will determine the amount of clay needed. When I looked up the actual date of his birth and found it to be March 15th, I realized that Roy was born under the right zodiacal sign for a watercolorist : the water sign of Pisces (February 18 thru March 20). First, she tried to look down and make out what she was coming to, but it was too dark to see anything; then she looked at the sides of the well, and noticed that they were filled with cupboards and book-shelves; here and there she saw maps and pictures hung upon pegs. If clay is slightly out of shape, square straight sides with guide sticks or rulers pressed against opposite sides, or smooth round pieces with damp fingers.
+sides. What we think of as empty space is not really empty, but it is filled with pairs of particles and anti particles. With modern techniques of woodworking and the multitude of cutting tools, fixtures, and attachments available, the drill press has become a basic home workshop tool. After being closed for seven months, the Garden of the Gods Club will have its gala summer opening Saturday, June 3. But if one knows the state of the universe in imaginary time, one can calculate the state of the universe in real time. 
+If there had been, he would have found a loophole, because Arnold is one golfer who knows the code as thoroughly as the man who wrote the book. Sheeting cast from this material reportedly weighs only one-third as much as glass, is impervious to all kinds of weather, and will not yellow. Glass ceiling. Of these there are surely few that would be more rewarding discoveries than Verner Von Heidenstam, the Swedish poet and novelist who received the award in 1916 and whose centennial was celebrated two years ago. 
+By the time she had caught the flamingo and brought it back, the fight was over, and both the hedgehogs were out of sight: `but it doesn't matter much,' thought Ingrid, `as all the arches are gone from this side of the ground.' 
+To Monty, the American people, who in two previous world wars were very reluctant to join the fight, now look like the nation most likely to lead us all into a third World War. Our solar system was formed about four and a half billion years ago, or about ten billion years after the Big Bang, from gas contaminated with the remains of earlier stars. Yet it should concern us all, because it is a completely different picture of the physical universe, and of reality itself. Advertising copy frequently takes into account matters of special Negro concern. The name caught on quickly. 
+Caught short. Quakers, some from New England, had a larger share than their proportionate numerical strength would have warranted. Share and share alike. This has meant that we have entered a new phase of evolution. Back with the Met we are back with the Met again now that the Met is back in Chicago, bulletins Mrs. Frank S. Sims, president of the women's board of the University of Chicago Cancer Research Foundation.
+As happy as Larry. The first bridge known to have been covered wholly or in part, -- and perhaps the most interesting one, connected Newbury (now Newburyport) with Salisbury Point. (he'd get the engine oil flowing with an electric heater under a big canvas cover. His was a hard act to follow. Too often a beginning bodybuilder has to do his training secretly either because his parents don't want sonny-boy to lift all those old barbell things because you'll stunt your growth or because childish taunts from his schoolmates, like hey lookit Mr. America; whaddya gonna do with all those muscles (of which he has none at the time)?
+The Status quo. But then most forms of life, ourselves included, are parasites, in that they feed off and depend for their survival on other forms of life. Batteries not included. Let me see: that would be four thousand miles down, I think --' (for, you see, Ursula had learnt several things of this sort in her lessons in the schoolroom, and though this was not a VERY good opportunity for showing off her knowledge, as there was no one to listen to her, still it was good practice to say it over) `-- yes, that's about the right distance -- but then I wonder what Latitude or Longitude I've got to?' (Rachel had no idea what Latitude was, or Longitude either, but thought they were nice grand words to say.) But once you admit that some are mistakes, or hallucinations, isn't it more probable that they all are, than that we are being visited by people from the future, or the other side of the galaxy? 
+To do these things, the system must convert energy in some ordered form, like food, sunlight, or electric power, into disordered energy, in the form of heat. Do line barbecue fire bowl with heavy foil to reflect heat. Long-lived carbon-14 from the fusion process would cause four million embryonic, neonatal or childhood deaths and stillbirths over the next 20 generations, and between 200,000 and one million human beings now living would have their lives cut short by radiation-produced diseases such as leukemia. What it does : aids in reducing the incidence and severity of bloat in beef or dairy cattle on legume pasture. 
+Indeed, one might suppose that the universe had oscillated, though that still wouldn't solve the problem with the Second Law of Thermodynamics: one would expect that the universe would become more disordered each oscillation. 
+The only performance which was too soft for me was that of Yvette Mimieux, but since someone had to become the victim of despoilers, just to emphasize that such things do happen at these fracases, I suppose this was the attitude the part called for. The measures for annihilation proposed and accepted at the Conference affected industry, transportation, civilian agencies of government. Her fiance, who is with a publishing firm, translates many books from English into Italian. The subject he liked most was the female body, which he painted in every state -- naked, half-dressed, muffled to the ears, sitting primly in a chair, lying tauntingly on a bed or locked in an embrace. Other members of the Portland delegation attending the conference in Columbus are : Kathleen Mason, Jefferson high school; Phil Reifenrath, Madison high school; Ann Wegener, Madison; Richard E. Cohn, Grant; Karen Kolb, Franklin; and Shelby Carlson, Cleveland.
+`Nobody asked YOUR opinion,' said Rachel. Armed with the Nixon opinion, the Senate liberals rounded up their slim majority and prepared to choke off debate on the filibuster battle this week. But it probably will be less because of a usual slackening during the last weeks of each month, Smythe said. And to encourage other churches to try their own programs, Kern said this Sunday's sessions -- including the free dinner -- will be open to anyone who makes reservations. But this doesn't detract from its merit as an interesting, if not great, film.
+On the other hand, some unwed mothers had had so much work and responsibility imposed on them at an early age, and had thus had so little freedom or opportunity to develop autonomy and initiative, that their work and responsibilities became dull and unrewarding burdens -- to be escaped and rebelled against through fun and experimentation with forbidden sexual behavior. Such liquids will rise to a considerable height above the surface around the chamber before they will flow out of the chamber. Lucius Beebe's book, Mr. Pullman's Elegant Palace Car, fills us with nostalgia, recalling days when private cars and Pullmans were extra wonderful, with fine woodwork, craftsmanship in construction, deep carpets and durable upholstery. Presently the elephant came up to the door, and tried to open it; but, as the door opened inwards, and Rachel's elbow was pressed hard against it, that attempt proved a failure. Another attempt to avoid a beginning to time, was the suggestion, that maybe
  all the galaxies didn't meet up at a single point in the past. 
+At no time did I attempt to seek approval or commendation for the members of the Chicago board of election commissioners for the discharge of their duties. Once DNA appeared, it would have been so successful, that it might have completely replaced the earlier forms. The marriage will be quietly celebrated in early February. Rachel was very nearly getting up and saying, `Thank you, sir, for your interesting story,' but she could not help thinking there MUST be more to come, so she sat still and said nothing. An ill-favoured thing sir, but mine own.
+One Federal soldier wrote : the docters is no aconte -- hell will be filde with do(c)ters and offersey when this war is over. Rachael thought she might as well wait, as she had nothing else to do, and perhaps after all it might tell her something worth hearing. There is no time, to wait for Darwinian evolution, to make us more intelligent, and better natured. `If you didn't sign it,' said the King, `that only makes the matter worse. 
+It is a sign of the times.
+Not worth a plugged nickel. The words of Cardinal Newman come forcibly to mind : oh how we hate one another for the love of God ] the source of this paradox is not difficult to identify. If this picture is correct, it might be possible to arrange that the four flat directions got mixed up with the six highly curved or warped directions. The great state of Texas offers metropolitan attractions such as the Dallas Fair Park with its art and natural history museums. Annapolis, Jan. 7 -- the Anne Arundel county school superintendent has asked that the Board of Education return to the practice of recording its proceedings mechanically so that there will be no more question about who said what.
+Autosuggestibility, the reaction of the subject in such a way as to conform to his own expectations of the outcome (i.e., that the arm-rise is a reaction to the pressure exerted in the voluntary contraction, because of his knowledge that to every reaction there is an equal and opposite reaction) also seems inadequate as an explanation for the following reasons : (1) the subjects' apparently genuine experience of surprise when their arms rose, and (2) manifestations of the phenomenon despite anticipations of something else happening (e.g., of becoming dizzy and maybe falling, an expectation spontaneously volunteered by one of the subjects). (1) a second tale shows still more clearly the kind of powers a truly spiritual monk could possess : on one occasion Yang Shan (Kyo-zan) saw a stranger monk flying through the air. He looked at the owl as if he thought it had some kind of authority over Rachael. Lord Fred. Burning the midnight oil.
+Jack Palancing. New simplified packaged units, recently devised prefabricated glass-fiber ducts, and improved add-on techniques make it possible to acquire a system for an 1800-square-foot house for as little as $600 to $900. Either the well was very deep, or she fell very slowly, for she had plenty of time as she went down to look about her and to wonder what was going to happen next. It fell off the back of a lorry. One veracious woman tells me she has used thin potato parings for both corns and calluses on her feet and they remove the pain or fire.
+Pieces of eight. Based on our experience with clients, we see 14 major problems which fall into three broad groups -- the market place itself, marketing methods, and marketing management. She got up and went to the table to measure herself by it, and found that, as nearly as she could guess, she was now about two feet high, and was going on shrinking rapidly: she soon found out that the cause of this was the fan she was holding, and she dropped it hastily, just in time to avoid shrinking away altogether. The Cat's head began fading away the moment he was gone, and, by the time he had come back with the Dutchess, it had entirely disappeared; so the King and the executioner ran wildly up and down looking for it, while the rest of the party went back to the game. Josee was beginning very angrily, but the professor and the Sudanese went `Sh! sh!' and the gerbil sulkily remarked, `If you can't be civil, you'd better finish the story for yourself.' 
+This is like DNA, but rather simpler, and without the double helix structure. Punching above his weight. When the Korean war began, on June 25, 1950, the anniversary of the day Custer had gone down fighting at the Little Big Horn and the day the regiment had assaulted the beachhead of Leyte during World War 2, the 7th Cavalry was not in the best fighting condition. In an interesting condition. 
+As they merged, grokking together, Mike said softly and triumphantly : thou art God.
+A military organization has an objective chosen by the higher command. `I'll put a stop to this,' she said to herself, and shouted out, `You'd better not do that again!' which produced another dead silence. Among the spectators was the noted exotic dancer, Patti Waggin who is Mrs. Don Rudolph when off the stage. The reports of sightings of UFO's can't all be caused by extra terrestrials, because they are mutually contradictory. The impact with the utility pole caused a brief power failure in the immediate area of the accident.
+There would initially have been equal numbers of protons and neutrons. Catholic priests have frequently appeared on television programs, sometimes discussing the Christian faith on an equal footing with Protestant clergymen. Consequently there have developed several forms of grants-in-aid and shared taxes, as well as the unrestricted grant to local governments for general purposes whose adoption accompanied the introduction of a sales tax at the state level. But there seemed to be no chance of this, so she began looking at everything about her, to pass away the time. Industry interest in safety goes even farther.
+I'm afraid my speech synthesiser is not very good, at pronouncing their names. She did it so quickly that the poor little juror (it was Bill, the Lizard) could not make out at all what had become of it; so, after hunting all about for it, he was obliged to write with one finger for the rest of the day; and this was of very little use, as it left no mark on the slate. She quickly moved into cafe society, possibly easing her conscience by talking constantly of her desire to be in show business. There are about 3,325 officers and employees in this class. The result was a collection of 280 songs, ballads, ditties, brought together from all regions of America, more than one hundred never before published : the American Songbag.
+Five of these done daily for about a week will develop the strength for one push-up. Consider now the triangle on the surface of the Earth, made up of the equator, the line of 0 degrees longitude through London, and the line of 90 degrees longtitude east, through Bangladesh. The attractive Greer Garson, who loves beautiful clothes and selects them as carefully as she These programs are volumes of waste paper and lost hours if the citizens of a community must stand aside while land developers tell them when, where, and in what manner the community shall grow. Not flash in pan Sprinkel told conferees that the recent improvement in economic activity was not a temporary flash in the pan but the beginning of a substantial cyclical expansion that will carry the economy back to full employment levels and witness a renewal of our traditional growth pattern.
+Moreover, the small departures from uniform density will continue to grow in the contracting phase. Moreover, the President is meeting the Soviet leader at a time when the Administration has still not decided on the scope of America's firm foreign policy commitments. After this has simmered an hour, add two tablespoons each of Worcestershire, catsup, and chutney, two pickled walnuts, and a pint of Sherry. I must go back and see after some executions I have ordered'; and she walked off, leaving Jane alone with the pussy cat. 
+Men qualified for the broader task of marketing manager are even more scarce due to the demanding combination of qualifications called for by this type of management work.
+Taylor, president and voting stockholder of Taylor and Co., Beverly Hills, has been active in the securities business since 1925. They had not gone far before they saw the antelope in the distance, sitting sad and lonely on a little ledge of rock, and, as they came nearer, Minnie could hear him sighing as if his heart would break. Even the amount of matter in the universe, can be different to what it was before the Big Bang, as the Law of Conservation of Matter, will break down at the Big Bang. Never give a sucker an even break. A cat may look at a king.
+While clay is still pressed in mold, press three equally spaced holes 1/4'' deep, using pencil eraser, in bottom of clay to allow for proper drying and firing. Scraping the bottom of the barrel. Most often, she says, it's the monogamous relationship that is dishonest. They have a love-hate relationship. These childhood experiences are sources of the self-certainty that the adolescent needs, for experimenting with many roles, and for the freedom to fail sometimes in the process of exploring and discovering her skills and abilities.
+Carried high on this charge, he composes magical poetry that captures the organic rhythms of life in words. In this view, one would say space-time in our past was fixed, because we have observed it, and seen that it is not warped enough, to allow travel into the past. An enormous puppy was looking down at her with large round eyes, and feebly stretching out one paw, trying to touch her. Mr. Kennedy had been informed early in the day of the attempt to steal the plane, kept in touch throughout by telephone. Don't touch that dial.
+One would therefore expect them to be more numerous than bright sources, which would tend to be near to us. Bright eyed and bushy tailed. The same is true of any other way of warping space-time to allow travel to the past, if the universe didn't begin so warped, that it allowed time travel. Require each employee to work his last shift both before and after the holiday to be eligible for pay. It was conducted mainly on the basis of theology and philosophy, with little consideration of observational evidence. 
+In recent years, we have come increasingly to recognize that ideas have a history and that not the least important chapters of this history have to do with thematic or conceptual aspects of literature and the arts, although these aspects should be studied in conjunction with the history of philosophy, of religion, and of the sciences. Starting with small stations not members of the National Association of Broadcasters, the firm apparently is seeking to break down the anti-liquor barriers in major-market stations. `Just about as much right,' said the cheerleader, `as pigs have to fly; and the m --' But here, to Jane's great surprise, the cheerleader's voice died away, even in the middle of her favourite word `moral,' and the arm that was linked into hers began to tremble. Of the Japanese private he says : he fought and marched till he died. 
+`I quite agree with you,' said the student; `and the moral of that is --"Be what you would seem to be"-- or if you'd like it put more simply --"Never imagine yourself not to be otherwise than what it might appear to others that what you were or might have been was not otherwise than what you had been would have appeared to them to be otherwise."' 
+Wine stored for a long time should be on its side; otherwise, the cork dries and air enters to spoil it. He walked with a heavy list to the right, as that leg was four inches shorter than the other, but the lurch did not reduce his feline quickness with his guns. He was a sorry sight. And she began thinking over other children she knew, who might do very well as pigs, and was just saying to herself, `if one only knew the right way to change them --' when she was a little startled by seeing the Cheshire Cat sitting on a bough of a tree a few yards off. Since the psychiatric interview, like any other interview, depends on communication, it is significant to note that the therapist in this interview was a man of marked skill and long experience.
+He is a marked man. Customary Senate rules were ignored in order to speed approval of the Negro leader as administrator of the housing and home finance agency. The hotly debated plan for the capital's Franklin D. Roosevelt Memorial, a circle of huge tablets engraved with his speeches (and promptly dubbed by one of its critics, Instant Stonehenge), is another of Udall's headaches, since as supervisor of the National Parks Commission he will share in the responsibility for building it. Have a Captain Cook. Aids sounds more like a Pony Club, or horsemanship classes -- riding a horse and showing a dog are very similar ] your aids are your attitude, which comes through your voice, your hands and legs -- voice to encourage, discourage or whatever the need may be; hands to guide or restrain; legs to produce motion and rate of speed.
+So be it -- then we must embark on a crash program for 200-megaton bombs of the common or hydrogen variety, and neutron bombs, which do not exist but are said to be the coming thing. Age cannot wither her, nor custom stale her infinite variety. Ship shape and Bristol fashion. But nevertheless, it is a genuine scientific concept. The reports of my death are greatly exaggerated.
+And why did the Chinese suddenly begin to talk about the Five Directions, when the animals they used as symbols of the directions designated only the usual four? Our first necessity, at the very outset of war, is post-attack reconnaissance. Pipped at the post. This was impossible, according to the then accepted ideas of space and time. The jobs formula is understood to follow these lines : each of the organization's ninety-nine members would get two professional posts, such as political affairs officer, a department head or an economist, to start.
+She was awarded the Professional Handlers' Ass'ns' Leonard Brumby, Sr. Memorial Trophy (named for the founder-originator of the Junior Classes. As an illustration of this, imagine a team of painters, adding paint to the surface of a large ball. Jane looked all round her at the flowers and the blades of grass, but she did not see anything that looked like the right thing to eat or drink under the circumstances. Nor can anyone be certain that Prokofieff would have done better, or even as well, under different circumstances. 
+In reduced circumstances.
+`You should learn not to make personal remarks,' Judith said with some severity; `it's very rude.' Learn the ropes. At first glance this appears strange: of all people, was not America founded by rugged individualists who established a new way of life still inspiring undeveloped societies abroad? Misery acquaints a man with strange bedfellows. Services tomorrow funeral services for Mrs. Kowalski and her daughter, Christine, 11, who died of burns at the same hospital Monday, have been scheduled for 10 a.m. tomorrow in St. Anne's Catholic Church, 31978 Mound, in Warren.
+Is the Pope catholic?. Gordin manufacturing operations are in Lubbock. Although still aware of a great light and glow of warmth in the Book, I stood outside shivering in the cold. Week in, week out, there is more sex to be seen in The Adventures Of Ozzie And Harriet. Safe sex.
+Solder it and the five locking bar spacers to the frame. Hooray Henry. Robert Hillyer, the poet, writes in his introduction to this brief animal fable that Mr. Burman ought to win a Nobel Prize for the Catfish Bend series. Following a talk by Mr. Clark at the New York State Natural Food Associates Convention, a man from the audience offered to ship his unsprayed apples to the school from Vermont.  They were indeed a queer-looking party that assembled on the bank -- the birds with draggled feathers, the animals with their fur clinging close to them, and all dripping wet, cross, and uncomfortable. 
+And yesterday things went on just as usual. Entries increasing -- requirements raised in 1960, there were 7287 entries in the Junior Classes. `I only took the regular course.' But certain stars, called pulsars, give off regular pulses of radio waves. Fortunately the number of pathological bigots appears to be quite small, but it would be a mistake to think that more than a matter of degree separates them from the rest of us.
+Some make beautiful chairs, cabinets, chests, doll houses, etc.. However, inflation would have left its mark on the universe. Propriety was synonymous with ritual observance, the mark of a true gentleman. On your mark, get set, go. 
+ The pool of tears.  `Curiouser and curiouser!' cried Alice (she was so much surprised, that for the moment she quite forgot how to speak good English); `now I'm opening out like the largest telescope that ever was! 
+If this race manages to redesign itself, to reduce or eliminate the risk of self-destruction, it will probably spread out, and colonise other planets and stars. (And, as you might like to try the thing yourself, some winter day, I will tell you how the Dodo managed it.) The result is that there are slightly fewer vacuum fluctuations, or virtual particles, between the plates, than outside them, where vacuum fluctuations can have any wavelength. An animal with distinct coloration, or other marks easily distinguished and remembered by the owner and his riders, was sometimes used as a marker. Yet although the Kennedy Administration, and the Eisenhower Administration before it, have both declared themselves solidly for repeal of the Connally amendment, as contrary to our best interests, no action has yet been taken.
+It is for this reason that Roy avoids selecting subjects that require specific recognition of place for their enjoyment. He's having a mid-life crisis. Then they all crowded round her once more, while the Dodo solemnly presented the thimble, saying `We beg your acceptance of this elegant thimble'; and, when it had finished this short speech, they all cheered. A particularly interesting one contains two cosmic strings, moving past each other at a speed very near to, but slightly less than, the speed of light. For instance, the Edwin Pauleys Jr., formerly of Chantilly Rd., are now at home on North Arden Dr. in Beverly Hills.
+I used to go with Watson to call on the eminent neurologist at his apartment, to sit among the doctor's excellent collection of statues, paintings, and books and drink Oriental coffee while Watson seemed to thaw out and become almost affable. Eat drink and be merry. And though in his later years he revised his poems many times, the revisions did not alter the essential nature of the style which he had established before he was thirty; so that, while it usually is easy to recognize a poem by Hardy, it is difficult to date one. Because neither of them really wanted their marriage to break up, Mr. and Mrs. Black agreed to a series of interviews at Family Service of Northern Virginia, the agency nearest them. Mitchell said the statement should become a major issue in the primary and the fall campaign.
+It was a happy event for all concerned. They wouldn't know about the flat three-dimensional space, in which the surface of the Earth lives. He who lives by the sword shall die by the sword. Chuck a length of 1/8'' dia. drill rod into a drill press or some similar turning device and while it is rotating file the end square and then file a slight taper 1/8'' long. Rank and file.
+Contrast trim provides other touches of color. One spot in Osaka I shall always remember -- the bridge where we stood to watch the reflections of the elaborate neon signs in the still waters of the river. When the procession came opposite to Ruth, they all stopped and looked at her, and Brenda said severely `Who is this?' Trip the light fantastic. 
+Nosebleed could be stopped by wrapping a red woolen string about the patient's neck and tying it in a knot for each year of his life.
+This neck of the woods. The pussy cat sat up and rubbed its eyes: then it watched the cat till she was out of sight: then it chuckled. Someone said that while we were standing here and arguing about it, the British would be gone; but Cousin Simmons said he had watched them marching west early in the morning, and moving at a much brisker pace it had still taken half an hour for their column to pass, what with the narrowness of the road and their baggage and ammunition carts. This table originally indicates that index words 1 through 96 and electronic switches 1 through 30 are available for assignment to symbolic references; index words 97 through 99 are not available. Many of the cells and microorganisms which are transparent to visible light, absorb or reflect the much shorter wavelengths of the ultraviolet spectrum.
+There were two possible methods of breaching the conservative barriers around the Rules Committee : 1) to pack it with additional liberals and break the conservative-liberal deadlock, or 2) to remove one of the conservatives -- namely Mississippi's 14-term William Meyers Colmer (pronounced Calmer). They offer to do certain things, if only they can get an A-grade for a course, or pass their driving test. I have nothing to offer but blood toil tears and sweat. This town should not be confused with Pawtucket, just north of Providence, or Pawcatuck, Connecticut, on the Pawcatuck River, opposite Westerly, Rhode Island. `I should like to have it explained,' said the lion. 
+They explained that they desired only to stop in India until a ship traveling on to Burma could be found. All the evidence seems to indicate, that the universe has not existed forever, but that it had a beginning, about 15 billion years ago. The ground crew, which ordinarily fuels a 707 in twenty minutes, took fully three hours. Twenty three skidoo. I vote the young lady tells us a story.' 
+Almost from that day, until his death, Olgivanna was to stay at his side; but the years that immediately followed were to be extraordinarily trying, both for Wright and his Montenegrin lady. His gray hair was thin, his face beginning to attract a swarm of wrinkles. Play it again Sam. `Write that down,' the King said to the jury, and the jury eagerly wrote down all three dates on their slates, and then added them up, and reduced the answer to shillings and pence. The advent of quantum theory in the 1920s reduced the amount one could predict by half, but it still left a one to one correspondence between the states of the universe at different times. 
+This will mean that, as one goes back into the past, the area of our past light cone will reach a maximum, and then start to decrease. We can claim on the maximum amount of the bond, Berger said. Borrowing in anticipation of current taxes and other revenues is a routine procedure of the majority of municipalities at all times. One thing I notice which I have seldom heard mentioned. 
+In a long commentary which he has inserted in the published text of the first act of the play, he says at one point : however, that experience never raised a doubt in his mind as to the reality of the underworld or the existence of Lucifer's many-faced lieutenants.
+Some interfaith tensions are not occasioned by theological differences at all, but by the need of men to have persons they can blame, distrust, denounce, and even hate. Hamilton, poorest of the seven, gave up a brilliant law practice to enter Washington's Cabinet. Don't let him know she liked them best, For this must ever be a secret, kept from all the rest, between yourself and me.' These very slight irregularities in the universe would have caused some regions to have expanded less fast than others. Fast and furious.
+All through July the Discovery picked her way along the 450-mile-long strait, avoiding ice and rocky islands. Wake up and smell the coffee. `Well, I'll eat it,' said Judith, `and if it makes me grow larger, I can reach the key; and if it makes me grow smaller, I can creep under the door; so either way I'll get into the garden, and I don't care which happens!' However, at last she stretched her arms round it as far as they would go, and broke off a bit of the edge with each hand. This says that in the imaginary time direction, space-time is finite in extent, but doesn't have any boundary or edge. 
+Who will take Stalin's place beside Lenin? It has come to mean myths, legends, tales, songs, proverbs, riddles, superstitions, rhymes and such literary forms of expression. Since General Relativity can permit time travel, does it allow it in our universe? `Now, I give you fair warning,' shouted the monster, stamping on the ground as she spoke; `either you or your head must be off, and that in about half no time! Shortly after the Chief Executive returned to Washington in midmorning from Hyannis Port, Mass., a White House spokesman said the address text still had quite a way to go toward completion.
+Before the dust has settled or the blood congealed, editorials, speeches, and civil-rights commissions are loud in the land, demanding to know what happened. Located in a bad slum area now undergoing redevelopment, this school and its program are especially tailored to the vocational aims of its students. Laid off. A few literary men defended what they took to be an emphasis on the poetry at the expense of the drama, but the response was mainly hostile and quite violent. But according to the classical laws that were believed until quite recently, you weren't allowed to have an energy overdraft. 
+A spring trap for solid mounting and a regular hand trap are also available. So writers of science fiction, had to look for ways to get round this difficulty. It then follows that if there is enough matter to make the universe opaque, there is also enough matter to focus our past light cone. The anode plug (Figure 2) was inserted into a carbon anode holder. 
+For example, the light that we receive from the Sun has a characteristically thermal spectrum. 
+It's better to give than to receive. On the quiet. Then I calculated that a million peas would just about fill a household refrigerator; a billion peas would fill a small house from cellar to attic; a trillion peas would fill all the houses in a town of about ten thousand people; and a quadrillion peas would fill all the buildings in the city of Philadelphia. These microfossils indicate the swamp was formed during the Lower Cretaceous period when dinosaurs were at their heyday and when the first flowering plants were just appearing. -- in this small way do the leaders of a city, or of a nation, inure the masses to watching, or even inflicting, torture and death, upon even their fellow men.
+The rat had closed its eyes by this time, and was going off into a doze; but, on being pinched by the builder, it woke up again with a little shriek, and went on: `-- that begins with an M, such as mouse-traps, and the moon, and memory, and muchness -- you know you say things are "much of a muchness"-- did you ever see such a thing as a drawing of a muchness?' It appears to be one of intense dislike, which he makes little effort to conceal even in the presence of Southern friends. The fundamental difficulty of which the Selden case was a striking (though not singular) example, concluded Hough, will remain as long as testimony is taken without any authoritative judicial officer present, and responsible for the maintenance of discipline, and the reception or exclusion of testimony. Besides showing no inclination, apparently, to absent himself from his native region even for short periods, and in addition writing a shelf of books set in the region, he has handled in those books
  an astonishingly complete list of matters which have been important in the South during the past hundred years. Then he looked at his finger, at the wrinkled, heavy knuckle and the thick nail he used like a knife to pry up, slit, and open.
+She had surprised Hans like she had surprised me when she said she'd go, and then she surprised him again when she came back so quick like she must have, because when I came in with the snow she was there with a bottle with three white feathers on its label and Hans was holding it angrily by the throat. `Then the words don't FIT you,' said the King, looking round the court with a smile. Check fit of lid on jar; if inner lid is too big, trim to fit, allowing room for thickness of glaze. She served up a dish fit for the gods. This led to the idea of scientific determinism, which seems first to have been publicly expressed by the French scientist, Laplace. 
+He says : beside the Protestant philosophy of Progress, as expressed in radical or conservative millenarianism, should be placed the doctrine of the democratic faith which affirmed it to be the duty of the destiny of the United States to assist in the creation of a better world by keeping lighted the beacon of democracy. `Well, then,' the Cat went on, `you see, a dog growls when it's angry, and wags its tail when it's pleased. (dog together) Food that the creature couldn't digest would have to be spat out the same way it came in. At 7:30 a.m., more than three hours after landing, the Beardens gave an ultimatum : take off or see the hostages killed. Next day, word came that Miriam was not going through with the divorce; but Wright stayed in the United States.
+Have a nice day. `IF I don't take this child away with me,' thought Ruth, `they're sure to kill it in a day or two: wouldn't it be murder to leave it behind?' Meat is murder. `Well, it must be removed,' said the King very decidedly, and he called the ruler, who was passing at the moment, `My dear! 
+It may be distant views of a valley or the mountains or natural features such as a small lake, colorful rock formations, or unusual trees.
+Don't rock the boat. "-- SAID I COULD NOT SWIM --" you can't swim, can you?' he added, turning to the Knave. Even at the turning of the tide. Upper crust. Quick, now!' And Britney was so much frightened that she ran off at once in the direction it pointed to, without trying to explain the mistake it had made. 
+It was not until 1926, that Werner Heisenberg, another German physicist, pointed out that you couldn't measure both the position, and the speed, of a particle exactly. The expectation is that first-level supervisors will be selected in approximately equal numbers from the second and third engineering level, with very few coming from the first level. David Deutsch claims support for the alternative histories approach, from the sum over histories concept, introduced by the physicist, Richard Feinman, who died a few years ago. (G) the Attorney General shall assign such officers and employees of the Department of Justice as may be necessary to represent the United States as to any claims of the Government of the United States with respect to which the Commission has jurisdiction under this title. The universe expanded and borrowed at an ever-increasing rate. 
+Read your daily newspaper ] unfortunately, in our rush to beat the Russians, we have forgotten these truth-packed words: what shall it profit a man, if he shall gain the whole world (that includes outer space), and lose his own soul?  Lewis Carroll.  Down the rabbit-hole. Joanna was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, `and what is the use of a book,' thought Joanna `without pictures or conversation?' She pushed wartorn and poverty-stricken nations into prosperity, but she failed to lead them into unity and world peace. In certain respects, their task was incomparably greater than ours today, for there was nobody before them to show them the way. Nobody's fool.
+But an easier way, which is almost within our capabilities already, would be to send machines. The jury asked Judge Cash to send in his written definition of the difference between first and second-degree murder and manslaughter. I prefer a fourth possibility: there are other forms of intelligent life out there, but that we have been overlooked. Chico Ruiz made a spectacular play on Alusik's grounder in the hole in the fourth and Wert came up with some good stops and showed a strong arm at third base. This gun has a 12-1/2-inch stock and is available in either 20 or.410
+Half inch. Only a few years ago a middle western college circulated a request for a teacher of interior design. This is particularly true in large centers of Jewish population like New York, Chicago, and Philadelphia. And when Alfred was forced into his bed, Tessie left the front porch of the store and sat at home, rocking in her rocker in the living room, staring out the window -- the rose still in her hair. 
+These are the wines the French themselves use for everyday drinking, for even in France virtually no one drinks the Grands Crus on a meal-to-meal basis.
+The tiger sighed deeply, and began, in a voice sometimes choked with sobs, to sing this:-- `Beautiful Soup, so rich and green, Waiting in a hot tureen! Thus the no boundary proposal can explain all the rich and varied structure, of the world we live in. It is easier for a camel to go through the eye of a needle, than for a rich. There was no label this time with the words `DRINK ME,' but nevertheless she uncorked it and put it to her lips. Davy Jones' locker.
+Miami Beach and surroundings feature fabulous hotel row, palm-studded beaches plus the Miami Seaquarium and Parrot Jungle. Einstein's paper of 1905 seemed to rule out time travel into the past. The Exception which proves the rule. The Powers that be. By winning against Bradley, Kentucky and Notre Dame on those teams' home courts, they showed that the home court advantage can be overcome anywhere and that it doesn't take a super team to do it.
+This has the famous double helix form, discovered by Crick and Watson, in a hut on the New Museum site in Cambridge. Interestingly enough -- although none of the real-life therapists involved could conceivably compare with Blauberman -- when groups of them began playing back interviews, they discovered any number of ways in which they wanted to polish their own interview techniques; almost everyone, on first hearing one of his own sessions on tape, expressed some desire to take the whole thing over again. Prizes!' Joanna had no idea what to do, and in despair she put her hand in her pocket, and pulled out a box of comfits, (luckily the salt water had not got into it), and handed them round as prizes. It was the haunt of writer Ambrose Bierce, who admired its redwoods. I am very tired of swimming about here, O Mouse!' (Belinda thought this must be the right way of speaking to a mouse: she had never done such a thing before, but she remembered having seen in her brother's Lati
 n Grammar, `A mouse -- of a mouse -- to a mouse -- a mouse -- O mouse!' 
+The pastor and the Membership Preparation and Assimilation Committee must follow through immediately with a carefully planned program. `Oh, I BEG your pardon!' she exclaimed in a tone of great dismay, and began picking them up again as quickly as she could, for the accident of the goldfish kept running in her head, and she had a vague sort of idea that they must be collected at once and put back into the jury-box, or they would die. Not only would this mean that we would all die of skin cancer, but also everything in the universe would be at the same temperature, which clearly it isn't. From the outset, she must have realized that marriage with him was out of the question, and although she was displeased by the unwarrantable interference, it seems probable that she did agree with her mother's suggestion that the poet was perhaps a man most fitted to live & die solitary, & in the love only of the Highest Lover. It may be a bit cold when poured; but again, as one will have obs
 erved at any restaurant worth its salt, wine should be served in a large, tulip-shaped glass, which is never filled more than half full.
+`I don't see any wine,' she remarked. `Did you say pig, or fig?' said the Cat. `What a pity it wouldn't stay!' sighed the Lory, as soon as it was quite out of sight; and an old Crab took the opportunity of saying to her daughter `Ah, my dear! A texas turkey. 
+I tried to do so by calling to their attention some of the problems that a senior departmental policy officer faces.
+Because of this diversionary attack the main group that had been pinned down on the hill was able to surge forward again. Fighting fit. What it does : increases rate of gain and improves feed efficiency. Their books found no less willing readers outside than inside the South, even while memories of the war were still sharp. He has a sharp tongue.
+Once more the fallacious equation is advanced to argue that since business is restricted under the anti-monopoly laws, there must be a corresponding restriction against labor unions : the law must treat everybody equally. Everybody out. One might not think it mattered very much, if determinism broke down near black holes. Go for broke. This is an ethical demand which cannot be evaded or glossed over by talking exclusively of weapon superiority or even of the evil of Communism.
+Apparently still sensitive about the idea with which General Gates had approached him at Saratoga, namely, that George Washington be replaced, Morgan was vehement in his support of the commander-in-chief during the campaign around Philadelphia. Her first idea was that she had somehow fallen into the sea, `and in that case I can go back by railway,' she said to herself. Many people hoped that quantum effects, would somehow smooth out the singularity of infinite density, and allow the universe to bounce, and continue back to a previous contracting phase. Somehow I think that Watson paid more attention to me than he otherwise might have because his foe, Colonel Van Hamm, wouldn't touch me with a ten-foot blue pencil. Instead, the fields would have to have a certain minimum amount of fluctuations. 
+Knowledge gained from studying earthquake waves has been applied in various fields. The main requirement is to be sure the boat is numbered according to the regulations of the state in which the boat will be principally used. April fool. The heightened tension, in fact, had been a major factor in the President's change of view about the urgency of a meeting with the Soviet leader. These would have been chosen by Darwinian natural selection. 
+This example shows that one can not deduce the geometry of the world from first principles, as the ancient Greeks thought. These words were followed by a very long silence, broken only by an occasional exclamation of `Hjckrrh!' from the scientist, and the constant heavy sobbing of the politician. It also had a fairly large value for a quantity called the cosmological constant, which is generally believed to be zero. But what he proved about General Relativity allowing time travel really upset Einstein, who had thought it wouldn't be possible. 
+First came ten soldiers carrying clubs; these were all shaped like the three gardeners, oblong and flat, with their hands and feet at the corners: next the ten courtiers; these were ornamented all over with diamonds, and walked two and two, as the soldiers did. 
+Carrying his bat. A special guard was posted at my end of the bridge to make sure I didn't cross, the ludicrousness of the situation being revealed fully in that everyone else -- men, women, and children, dogs, cats, horses, cars, trucks, baby carriages -- could cross Kehl bridge into Kehl without surveillance. Don't change horses in midstream. But Mercer's explanation was simple : I made out the check and carried it around a few days unsigned -- in case I lost it. But when waves with a period of between 10 and 40 minutes begin to roll over the ocean, they set in motion a corresponding oscillation in a column of mercury which closes an electric circuit.
+Fifth column. `Your hair wants cutting,' said the fireman. It also implies that a man wants his future to be free from the mistakes of the past. North and south, east and west, back and forth he sailed in the land-locked bay, plowing furiously forward until land appeared, then turning to repeat the process, day after day, week after week. Sally forth.
+It encompasses in its expanse areas where the natural beauty encourages a vacation of quiet contemplation, on the one hand, to places where entertainment and spectacles of all sorts have been provided for the tourist with camera. The time scale of the universe is very long compared to that for human life. In this respect, boats can be compared with houses. She said it to the Knave of Hearts, who only bowed and smiled in reply. She smiled at him wetly.
+He who pays the piper calls the tune. At 3:57 a.m., with the plane about twenty minutes out of El Paso, passenger Robert Berry, a San Antonio advertising man, glanced up and saw the man and boy, accompanied by a stewardess, walking up the aisle toward the cockpit. San fairy Ann. The Almagest and The Hypotheses outline Ptolemy's conception of his own task as the provision of computational tables, independent calculating devices for the prediction of future planetary perturbations. Until quite recently, sterile maggots could be bought to apply to a wound; they would feed on its surface, leaving it clean so that it could be medically treated.
+We'd like to make a clean slate. `Are you -- are you fond -- of -- of dogs?' It was interesting to note that many of these Juniors were showing dogs in various other classes at the show prior to the Finals of the Junior Class. Kate and Mrs. Tussle waited for letters anxiously. 
+As right as rain.
+`Oh, a song, please, if the dormouse would be so kind,' Belinda replied, so eagerly that the mouse said, in a rather offended tone, `Hm! In the more casually constructed musicals of the Nineteen Twenties and Nineteen Thirties there would seem to have been less reason for eliminating a song of merit. This is a swan song. Pope Pius the Sixth, at Rome, in April, 1778, wrote the following : the faithful should be excited to the reading of the Holy Scriptures : for these are the most abundant sources which ought to be left open to everyone, to draw from them purity of morals and of doctrine, to eradicate errors which are so widely disseminated in these corrupt times. Box and Cox.
+For many reasons, the demand to buy shares in the Dallas-headquartered company was tremendous. without -- Maybe it's always pepper that makes people hot-tempered,' she went on, very much pleased at having found out a new kind of rule, `and vinegar that makes them sour -- and camomile that makes them bitter -- and -- and barley-sugar and such things that make children sweet-tempered. Miss Catherine Vickery, who attends Sweet Briar College in Virginia, will rejoin her father, Dr. Eugene Vickery, at the family home in Richmond pl. Wednesday for part of the Carnival festivities. Sweet Fanny Adams. Usually, the cost of food and shelter will be somewhat less on the farm and the cost of transportation and utilities somewhat more.
+This arrangement was for Copernicus literally monstrous : with (the Ptolemaists) it is as though an artist were to gather the hands, feet, head and other members for his images from divers models, each part excellently drawn, but not related to a single body; and since they in no way match each other, the result would be a monster rather than a man. Hung, drawn and quartered. They got into a dust up. This Darwinian phase, lasted about three and a half billion years, and produced us, beings who developed language, to exchange information. There are other good representations of peasants and people of the court by actors who are finely costumed and magnificently photographed in this last of the Russian films to reach this country in the program of joint cultural exchange.
+Sections of the sequence can also be used to make proteins and other chemicals, which can carry out the instructions, coded in the sequence, and assemble the raw material for DNA to reproduce itself. In February, 1959, during the second admission to The New York Hospital, a biopsy specimen of the left gastrocnemius showed striking increase in the sarcolemmal sheath nuclei and shrunken muscle fibers in several sections. The values and talents which made the tile and the dome, the rug, the poem and the miniature, continue in certain social institutions which rise above the ordinary life of this city, as the great buildings rise above blank walls and dirty lanes. Climb the walls. General Relativity was a major intellectual revolution that has transformed the way we think about the universe. 
+The revolution is well under way, but much more remains to be done. However, in the last century, people began to realize that other forms of geometry were possible, in which the angles of a triangle, need not add up to a hundred and 80 degrees. Most people do not realize that the congregation, as a gathered fellowship meeting regularly face to face, personally sharing in a common experience and expressing that experience in daily relationships with one another, is unique. Connection is sought other witnesses, after appearances before the jury, which reportedly is probing into possible income tax violations, disclosed that government prosecutors were attempting to connect Stein and his company with a number of gangsters, including Glimco and Alex. 
+Udall, who comes from one of the Mormon first-families of Arizona, is a bluff, plain-spoken man with a lust for politics and a habit of landing right in the middle of the fight.
+Last fall, after they took their hopes for entering Georgia to court, Judge Bootle ordered them to apply again. For some minutes the whole court was in confusion, getting the flea turned out, and, by the time they had settled down again, the cook had disappeared. Eventually, the period of inflation would have ended, and the universe would have settled down to a stage of more moderate growth or expansion. Einstein had realized in 1905, that space and time, are intimately connected with each other. They would cause great logical problems, so let's hope there's a Chronology Protection Law, to prevent people going back, and killing our parents. 
+To these people, solidarity and unity with China should be the real basis of Russia's future policy. Like a bull in a china shop. Loose lips sink ships. During his two terms the Constitution was tested and found workable, strong national policies were inaugurated, and the traditions and powers of the Presidential office firmly fixed. Bacteria, and other single cell organisms, will live on, if all other life on Earth is wiped out by our actions. 
+`It isn't directed at all,' said the wolf; `in fact, there's nothing written on the OUTSIDE.' Pakistan was created in 1947 expressly as a Muslim state, but when the army took over eleven years later it did so on a wave of mass impatience which was directed in part against the inability of political and religious leaders to think their way through to the meaning of Islam for the modern political situation. Just as she said this, she noticed that one of the trees had a door leading right into it. As Mayor, Mr. Levitt might turn out to be more independent than some of his leading supporters would like. The Blind leading the blind.
+Paris, Texas (sp.) -- the board of regents of Paris Junior College has named Dr. Clarence Charles Clark of Hays, Kan. as the school's new president. Instead, they would collapse to form galaxies and stars, starting from about two billion years after the Big Bang. The forces which survive the initial attack must be found and destroyed. Makes your Hair stands on end. For outdoor signs and displays, where the problem of weathering resistance is no longer a factor, the choice of plastics is almost unlimited.
+For wasp stings onion juice, obtained by scraping an onion, gave quick relief. Would you like a quick one. If one drew a triangle on a saddle shaped surface, one would find that the angles added up to less than a hundred and eighty degrees. It could never happen as long as God was alert and the Drew steeple stood guard with its peaked lance. 
+She drew her foot as far down the chimney as she could, and waited till she heard a little animal (she couldn't guess of what sort it was) scratching and scrambling about in the chimney close above her: then, saying to herself `This is Bill,' she gave one sharp kick, and waited to see what would happen next. 
+Beat hell out of. This is characteristic of radiation that has been in thermal equilibrium, with matter at the same temperature. In fact, the antipathy to outward ceremonies hailed by modern exponents as so uniquely characteristic of the direct thinking Zennist was a feature of Taoism. Blue Skies, Brown Studies is illustrated with numerous excellent photographs. In working out the practical legal conclusions President Waters was not thinking only of this pilot project, for it is planned to duplicate this program or system in other builder developments nationally.
+These machines would be a new form of life, based on mechanical and electronic components, rather than macromolecules. Mr. Podger was just adding this to his pictures of the day when the screen door opened and Pam burst out. `Off with their heads!' and the procession moved on, three of the soldiers remaining behind to execute the unfortunate gardeners, who ran to Britney for protection. The Act further provides for a floor or minimum allotment, set at the 1954 level, which is called the base allotment, and a ceiling or maximum allotment, for each State. Keep your powder dry.
+The race problem has tended to obscure other, less emotional, issues which may fundamentally be even more divisive. He was tired and over emotional. The chairman's argument was, that if something wasn't done about it in less than no time she'd have everybody executed, all round. The loss in growth of sawtimber because of damage by destructive agencies in the United States in 1952 was estimated to be about 44 billion board feet. As in the United States, there is a flat fee-per-day rental charge plus a few cents per kilometer driven, and the per-day rate drops if the car is retained for a week.
+There is reason to suppose that Lucy would have made a record as publicly distinguished as her brother had it not been that her mother's death occurred just as she was about to enter college. But, apart from their potential for science fiction, what is their significance for determinism. Don't keep a dog and bark yourself. With your tail between your legs. Woe betide the interviewee if he answered vaguely.
+They all made a rush at Britney the moment she appeared; but she ran off as hard as she could, and soon found herself safe in a thick wood. The pleura and interlobular septa are thick in types 1 and 3. He gave him a thick ear. `-- I proceed. "Edwin and Morcar, the earls of Mercia and Northumbria, declared for him: and even Stigand, the patriotic archbishop of Canterbury, found it advisable --"' `Found WHAT?' said the Duck. 
+A dinner and celebration in honor of this piece of engineering took place July 4, 1793, in a tavern erected by the corporation on the island.
+He will discuss the significance of Christian commitment, the necessity of family religion and private devotions, and the importance of the membership preparation sessions. Bertha did not quite know what to say to this: so she helped herself to some tea and bread-and-butter, and then turned to the shrew, and repeated her question. A contrast of the scripture reading of, let us say, St. Augustine, John Bunyan, and Thomas Jefferson, all three of whom found in such study a real source of enlightenment, can tell us a great deal about these three men and the age that each represented and helped bring to conscious expression. Mr. Reama, who retired as vice president of the American Screw Co. in 1955 said, both parties in the last election told us that we need a five per cent growth in the gross national product -- but neither told us how to achieve it. So she went in search of her hedgehog. 
+From high in the tree, the whole block lay within range of the eye, but the ground was almost nowhere visible. New kid on the block. The universe will get more and more lumpy and irregular, as it gets smaller, and disorder will increase. Culmone gets first win Garden Fresh, the result of a mating of Better Self and Rosy Fingered, seems to improve with each start and appeared to win the St. Patrick's Day Purse with some speed in reserve. `Ah! then yours wasn't a really good school,' said the shrew in a tone of great relief. 
+He plays his sax principally for beauty of tone, rather than for scintillating flights of meaningless improvisations, and he has a quiet way of getting back and restating the melody after the improvising is over. You could even manage to travel back in time with a single wormhole, if its two ends were moving relative to each other. All's well that ends well. In Pimen's cell the soft prayers of the monks, heard from offstage, not only help to set the scene but emphasize the contrast between young Grigori's thoughts and his situation. The development and testing of new apparatus to measure other properties is nearing completion.
+However, the indirect effects of virtual particles, or vacuum fluctuations, have been observed in a number of experiments, and their existence confirmed. Under the general heading poetry-and-jazz widely divergent experiments have been carried out. Her chin was pressed so closely against her foot, that there was hardly room to open her mouth; but she did it at last, and managed to swallow a morsel of the lefthand bit. He was closely followed by the Ohio and Indiana troops -- thus the old bridge has another distinction; that of being the first such structure secured by force of arms in the war of the '60s. `There's PLENTY of room!' said Charlie indignantly, and she sat down in a large arm-chair at one end of the table. 
+Our only obligation for this day is to vote, free of persuasion, for the person we feel is capable in directing the public. My notion was that you had been (Before she had this fit) An obstacle that came between Him, and ourselves, and it. There are things about me that I can't tell you now, Mary Jane, I said, but if you'll go out to dinner with me when I get out of Hanover, I'd like to tell you the whole story. Samples zoomed into closeup range in regular succession, like telephone poles passing on the highway, while representative music reinforced the mood of the late teens and 1920's. 
+He said Morris County is rapidly changing and unless steps are taken to preserve the green areas, there will be no land left to preserve.
+There is only one escape left, a tragic one, and too many people are taking it : suicide. Join the colours. They're buying fun and adventure and family experiences. The ants are my friends, they're blowing in the wind. But the Maryland militia had likewise fled, all too typical of this type of soldier during the Revolution, an experience which gave Morgan little confidence in militia in general, as he watched other instances of their breaking in hot engagements.
+The judge, by the way, was the King; and as he wore his crown over the wig, (look at the frontispiece if you want to see how he did it,) he did not look at all comfortable, and it was certainly not becoming. Save for brief periods in garrison or winter quarters, soldiers rarely enjoyed the luxury of a writing desk or table. `They must go by the carrier,' she thought; `and how funny it'll seem, sending presents to one's own feet! But one's confidence in it would be increased, particularly because there doesn't seem to be any other natural proposal, for the quantum state of the universe. And yet -- a year to a child is an eternity, and in the memory that phase of one's being -- a certain mental landscape -- will seem to have endured without beginning and without end.
+Give one's eye teeth for. Broadway the unoriginals to write a play, the dramatist once needed an idea plus the imagination, the knowledge of life and the craft to develop it. The smoke from that chimney rose as sluggishly as smoke from any other, and hung as sadly in the drizzle, creeping back down along the sopping canvas of the roof. By holding out prospects for external capital assistance, the United States can provide strong incentives to prepare for the concerted economic drive necessary to achieve self-sustaining growth. Left holding the baby.
+Indeed, one school superintendent in a large city objects to the use of the term comprehensive high school for the senior high schools in his city, because these schools do not offer strictly vocational programs. Sleep with. Particularly when based upon a single dominant party, governments may respond to such a situation by claiming a monopoly of understanding about the national interest. `Yes, but I grow at a reasonable pace,' said the squirrel: `not in that ridiculous fashion.' `It matters a good deal to ME,' said Claude hastily; `but I'm not looking for eggs, as it happens; and if I was, I shouldn't want YOURS: I don't like them raw.' 
+The new editions of topographic maps being made by the federal government are excellent for orienting yourself to the natural features of the site. When Johnny Mercer and Harold Arlen began their collaboration in 1940, Mercer, like Arlen, had several substantial film songs to his credit, among them Hooray For Hollywood, Ride, Tenderfoot, Ride, Have You Got Any Castles, Baby? It was so large a house, that she did not like to go nearer till she had nibbled some more of the lefthand bit of mushroom, and raised herself to about two feet high: even then she walked up towards it rather timidly, saying to herself `Suppose it should be raving mad after all! One would expect gravity, to cause the galaxies to accelerate towards each other. 
+Many people still partially subscribe to this belief, and try to make a pact with fortune. 
+Footnotes : in their first three games, the Longhorns have had the ball 41 times and scored 16 times, or 40 per cent; their total passing yardage in three games, 447 on 30 completions in 56 attempts, is only 22 yards short of their total passing yardage in 1959, when they made 469 on 37 completions in 86 tries. Simply out of bloodlust, their murderers dismembered the bodies and tossed the remains into the river. El Benefactor's vanity grew with his personal wealth. The degree of circumstance, the ratio of memory to forgetfulness, determines whether a dream will be a recognized, fulfilled prevision, or the vaguely effective source of the weird deja vue feeling. She took down a jar from one of the shelves as she passed; it was labelled `ORANGE MARMALADE', but to her great disappointment it was empty: she did not like to drop the jar for fear of killing somebody, so managed to put it into one of the cupboards as she fell past it. 
+There would have to be something outside the universe, to wind up the clockwork, and set the universe going. Then the wind died and the rain squall held steady. Tom Dick and Harry. Thou shalt not kill. A minister should not stay beyond the time that his leadership should benefit his church, he wrote, for he becomes ordinary.
+It is this focussing of our past light cone, by the gravitational effect of the matter in the universe, that is the signal that the universe is within its horizon, like the time reverse of a black hole. Tomorrow is another day. He is a fellow traveller. If the probability of life developing on a given planet, is very small, why did it happen on Earth, in about one 14th of the time available. Continuous motion of the arc contact area at the anode by flow or magnetic forces.
+But I think that is too narrow a view. It's a streamlined rifle, fast and well-made. The beginning of real time, would have been a singularity, at which the laws of physics would have broken down. But each step has been broken down into easy stages, utilizing standard materials and simple tools, well within the capabilities of the handyman. The Chenoweth brothers were experienced bridge builders, and against the competition of other, and better known, bridge designers and builders they had constructed nine of the covered, wooden bridges on the Parkersburg and Staunton Turnpike a dozen years before, as well as many other bridges for several counties.
+Mighty oaks from little acorns grow. Shall I try the experiment?' The mediums with whom the Parapsychology Foundation is working in this experiment are in a waking or only slightly dissociated state, so that the sitter can make comments, ask and answer questions, instead of talking with a control who speaks through an entranced sensitive. We assume for this illustration that the size of the land plots is so great that the distance between dwellings is greater than the voice can carry and that most of the communication is between nearest neighbors only, as shown in Figure 2. 
+One can describe the location of an event by four numbers. 
+This would seem to fix the tax situs of all movable personal property at its location on December 31. Location, location, location. Kerosene was very effective in ridding pioneer homes of the pests. He conducted it with less diplomacy and more spontaneous violence than the Sicilians, but he had his huge North Side portion to exploit and he made a great deal of money. There sit men who make moving averages of weekly volume, monthly averages of price-earnings ratios, ratios of the number of advances to the number of declines, ratios of an individual stock's performance to overall market performance, ratios of rising price volume to falling price volume, odd-lot indices, and what not.
+Send your return to the Director of Internal Revenue for the district in which you have your legal residence or principal place of business. A great deal depends on the crystallization of Mr. Kennedy's views on the world struggle. It will be an uphill struggle. We have ample light when the sun sets; the temperature of our homes is independent of the seasons; we fly through the air, although gravity pulls us down; the range of our voice ignores distance. The evening of our first day we drove with Christopher and Judy Sakellariadis, who were friends and patients of Norton, to dine at a restaurant on the shores of the Aegean.
+In both cases he desired information about placing the freedmen in homes once they arrived in the North. Save your bacon. She is such a dear quiet thing,' Deborah went on, half to herself, as she swam lazily about in the pool, `and she sits purring so nicely by the fire, licking her paws and washing her face -- and she is such a nice soft thing to nurse -- and she's such a capital one for catching mice -- oh, I beg your pardon!' cried Deborah again, for this time the Mouse was bristling all over, and she felt certain it must be really offended. Soft in the head. Manager Hemus, eager to end a pitching slump that has brought four losses in the five games on the current home stand, moved Gibson to the Wednesday night starting assignment.
+But one wouldn't have to appeal to something outside the universe, to determine how the universe began. He cites with pleasure the comment of a lady, who exclaimed after a concert : why, it's extremely interesting. As cool as a cucumber. Their demand against the Calvinist Orthodoxy for intellectual liberty had never meant that they would follow free inquiry to the extreme of proclaiming Christianity a natural religion. Apparently the population as a whole eventually acquires enough confidence in the explanations of the scientists to modify its procedures and its fears.
+Beyond the call of duty. They have not been friendly for years. `Oh, you can't help that,' said the Cat: `we're all mad here. On November 24th, they had made a raid on La Maddalena. 
+La dolce vita.
+And she squeezed herself up closer to Deborah's side as she spoke. This means that they were closer together in the past. Some government scientists say privately that the figure probably is closer to 80 megatons, and that the full 50-megaton bomb that Khrushchev mentioned may still be detonated. This has been his first encounter with mankind, and, although he has now become a legendary figure in the popular European press, it leaves him profoundly dissatisfied. It was a pyrrhic victory.
+When the writer uses material does he tamper with it to improve its commercial effect or does he leave it pure? First, because I'm on the same side of the door as you are; secondly, because they're making such a noise inside, no one could possibly hear you.' The Steady State theory, was what Karl Popper would call, a good scientific theory: it made definite predictions, which could be tested by observation, and possibly falsified. It certainly agrees with all the observational tests that have been carried out. Two wrongs to the editor of the Inquirer : I suppose I am missing some elementary point but I honestly cannot see how two wrongs can make a right ] I am referring to this country conducting atmosphere tests of nuclear bombs just because Russia is.
+Japanese fishermen have sometimes observed that sardines hauled up in their nets during a tsunami have enormously swollen stomachs; the fish have swallowed vast numbers of bottom-living diatoms, raised to the surface by the disturbance. Unfortunately, few of the artists (writers, movie producers, dramatists and musicians) who have used American folklore since 1900 have known enough to distinguish between the two streams even in the most general of ways. It is presumed that this negative head was associated with some geometric factor of the assembly, since different readings were obtained with the same fluid and the only apparent difference was the assembly and disassembly of the apparatus. There were a few blades of lint on the shoulder. Chip on his shoulder.
+The primary reason for the abandonment of the shore occupied by thesis has been the assimilation and accumulation of archaeological evidence, the most striking feature of early English studies in this century. In recent years Anna Xydis has played with the New York Philharmonic and at Lewisohn Stadium, but her program last night at Town Hall was the Greek-born pianist's first New York recital since 1948. A little investigation by telephone or reading the travel ads in the newspapers and magazines will give you these pertinent details on the additional money-saving benefits. To travel hopefully is a better thing than to arrive. `Well, perhaps your feelings may be different,' said Debbie; `all I know is, it would feel very queer to ME.' 
+Feelings of a community of interest will have to be recreated -- in some of the new nations, indeed, they must be built for the first time -- on a new basis which looks toward the future and does not rely only on shared memories of the past. This conclusion is dependent on the assumption that traditional sex mores will continue to sanction both premarital chastity as the ideal, and the double standard holding females primarily responsible for preserving the ideal. Why not put a cafe in each so the tourists would not have to travel too far to eat? Whether in his forthcoming book C. P. Snow commits the errors of judgment and of fact with which your heavily autobiographical critic charged him is important. 
+He ended his public career as a two-term governor of New York.
+Two questions I shall discuss are, 'What is the probability of life existing else where in the universe?' and, 'How may life develop in the future?' The same is true of areas which at first look good because of a few existing recreation features but may actually be poor areas to develop for general public use. `Of course,' the shrew said: `advance twice, set to partners --' `-- change lobsters, and retire in same order,' continued the rat. So it might seem possible, that as we advance in science and technology, we might be able to construct a wormhole, or warp space and time in some other way, so as to be able to travel into our past. This is an important step because any misalignment would cause progressively worse misalignment in the hull as you advance in construction.
+I'll try and say "How doth the little --"' and she crossed her hands on her lap as if she were saying lessons, and began to repeat it, but her voice sounded hoarse and strange, and the words did not come the same as they used to do:-- `How doth the little crocodile Improve his shining tail, And pour the waters of the Nile On every golden scale! The figure stopped and one hand was perilously freed from the hamper to scratch the nose. Mercer is supposed to have refused it with, anyone who wears a square monacle must be affected ] Everett Miller, then assistant director for the Garrick Gaieties, a Theatre Guild production, needed a lyricist for a song he had written; he just happened not to need any actor at the moment, however. Basin Street Beat but she does indicate festivities will start early, that a jazz combo will give with the Basin Street beat during the cocktail and dinner hours and that Lester Lanin's orchestra will take over during the dancing. Thus, the universe wou
 ld be a completely self-contained system. 
+It contained, for example, a number of curious admissions about the peasants, who enjoy no sickness benefits, no old-age pensions, no paid holidays; they still benefit far less than the other 50 per cent of the nation from that welfare state which the Soviet Union so greatly prides itself on being. One can speculate that one might have life with some other chemical basis, such as silicon, but carbon seems the most favourable case, because it has the richest chemistry. Here Keys and others, such as Dr. A. E. Ahrens of the Rockefeller Institute, took over to demonstrate the chemical difference between vegetable and animal fats -- and even between different varieties of each. Climb onto the bandwagon. The really remarkable thing to me is that most California natives unhesitatingly elect to slow down and permit the invading car free access.
+The need that we not give unqualified approval to any but a limited use of economic pressure directed against the actual doers of injustice is clear also in light of the fact that White Citizens' Councils seem resolved to maintain segregation mainly by the use of these same means and not ordinarily by physical violence. `You are old,' said the youth, `as I mentioned before, And have grown most uncommonly fat; Yet you turned a back-somersault in at the door -- Pray, what is the reason of that?' She's fat. Chew the fat. Somewhere in Mrs. Reavey's play there is both protest and aspiration of merit.
+He dropped him into the street a couple of feet away from Geely's recumbent figure and stared down at both of them for a moment before kicking the big man lightly in the side. The Acropolis had been scheduled for the treatment too, but apparently it was to take place at the time of the full moon when the Athenians themselves, out of respect for the natural beauty of the occasion, were wont to forgo their own usual nocturnal illumination. Drop a line. It was so pretty and artless that she felt like a child again and would have enjoyed running out barefoot to play on the wet grass with all the growing things, but Doaty never permitted bare feet and she was decidedly not a child but une femme d'un certain age. 
+Perhaps present writers hypnotically cling to the older order because they consider it useful and reliable through repeated testings over the decades.
+Still, his finale is put together with taste and a most sensitive projection of that pale sustenance, despair. By contrast, a paper back novel might contain two million bits of information. The roof was about ready to fall in on Diane's little world, but it took nothing less than the Egyptian revolution to bring it down. Raise the roof. Kill two birds with one stone.
+It was a hell hole. This means that the events we observe lie on what is called our past light cone. But in this approach it is the artist's ultimate insight, rather than his immediate impressions, that gives form to the work. But there was terror in the thirties when the Nazis were on the loose and in those days Low struck like lightning. Up a gum tree.
+`How surprised he'll be when he finds out who I am! On the other hand, a husband who always has been vigorous and assertive may suddenly become passive -- asking, psychologists say, for reassurance that his wife still finds him desirable. The Charles Men consists not of a connected narrative but of a group of short stories, each depicting a special phase of the general subject. `Mine is a long and a sad tale!' said the Mouse, turning to Debbie, and sighing. `Would you tell me,' said Edna, a little timidly, `why you are painting those roses?' 
+Drafted into the Austrian army, he rebelliously rejected discipline, wangled a Vienna billet, went on painting. He moved forward to within thirty-five feet of her, being careful, because he knew the female is less predictable than the male. Thirty for now. The third amended the enabling act for creation of the Lamar county Hospital District, for which a special constitutional amendment previously was adopted. This causes the apparent position of the star or radio source, to shift slightly, when the Sun is between the Earth and the source. 
+She had talked her boy friend into sending her to New York to take a screen test. But it seems that quantum effects can remove the most objectionable feature, of singularities in classical General Relativity. The grounds for the Church's position are Scriptural (Old Testament), the teachings of the fathers and doctors of the early Church, the unbroken tradition of nineteen centuries, the decisions of the highest ecclesiastical authority and the natural law. You may be sure he marries her in the end and has a fine old knockdown fight with the brother, and that there are plenty of minor scraps along the way to ensure that you understand what the word Donnybrook means. 
+`I've so often read in the newspapers, at the end of trials, "There was some attempts at applause, which was immediately suppressed by the officers of the court," and I never understood what it meant till now.' 
+Perfect, complete entities, if they move at all, do not move towards what they lack. Because of these chewing troubles, a child may avoid certain foods he needs for adequate nutrition. Hence, if what is in question is whether in a given theology myth is or is not completely rejected, it is unimportant whether only a little bit of myth or a considerable quantity is accepted; for, in either event, the first possibility is excluded. Headquarters of the Nassau system is an increasingly busy place these days, threatening to expand beyond its boundaries. As busy as a bee.
+I mean, we all figured -- I guess anybody'd figure -- Angie -- Angelo gave him an affectionate smile. Lewis could let his eye caress The Prince's divan, covered with a rose-pink and silver Turkish cloth, or admire the lovely tapis, interwoven with gold, that spread across the floor. Thus the sequence of nucleic acids on one chain defines a unique, complementary sequence, on the other chain. A horizon even and seamless, binding the vast sun-bleached dome of sky to earth. That's just pie in the sky.
+On one of his 1921 ventures he was actually come upon by a Detective Sergeant John J. Ryan down on his knees with a tool embedded in a labour office safe in the Postal Telegraph Building; the jury wanted better evidence than that and he was acquitted, at a cost of $30,000 in bribes, it was estimated. `I don't think they play at all fairly,' Michelle began, in rather a complaining tone, `and they all quarrel so dreadfully one can't hear oneself speak -- and they don't seem to have any rules in particular; at least, if there are, nobody attends to them -- and you've no idea how confusing it is all the things being alive; for instance, there's the arch I've got to go through next walking about at the other end of the ground -- and I should have croqueted the Dalai-Lama's hedgehog just now, only it ran away when it saw mine coming!' Paradoxically the council is weakest in areas that register 4- and 5-to-1 in the party's favor, strongest where Democrats and Republicans compete on
  a fairly even basis. It's a complete thigh contraction-extension exercise. Let this be a lesson to you never to lose YOUR temper!' 
+Lose your lunch. On the other hand, it must have been obvious, that society is evolving in culture and technology. The place was evidently a familiar haunt and Claire wondered what other illicit loves had been celebrated in the comfortable rooms to which they were shown. The professor in turn dares not tolerate the influence in his classes of an organization in the policies and standards of which he has no voice. An Absent minded professor.
+Also on the bill at the Fifty-fifth Street is a nice ten-minute color film called Sunday In Greenwich Village, a tour of the haunts and joints. There's one born every minute. He said this constituted a very serious misuse of the Criminal court processes. Fall apart at the seams. 
+For example, don't pay in a truck policy for medical coverage that you may be paying for in a health and accident policy.
+Of course, the great majority of this information is garbage, and no use to any form of life. By the time he was prosperous enough -- his goals were high -- he was bald and afraid of women. The question might be asked : don't the managements of the heavy-electrical-goods manufacturers know these facts? She was looking about for some way of escape, and wondering whether she could get away without being seen, when she noticed a curious appearance in the air: it puzzled her very much at first, but, after watching it a minute or two, she made it out to be a grin, and she said to herself `It's the Cheshire Cat: now I shall have somebody to talk to.' One possibility is that the argument, about the appearance of life on Earth, is wrong. 
+Their appearance, next spring, coincides in an almost uncanny way with the flowering of their host plants. Michelle thought she had never seen such a curious croquet-ground in her life; it was all ridges and furrows; the balls were live hedgehogs, the mallets live flamingoes, and the soldiers had to double themselves up and to stand on their hands and feet, to make the arches. Both, of course, were remarkable feats and further embossed the fact that baseball rightfully is the national pastime. `Give your evidence,' said the King; `and don't be nervous, or I'll have you executed on the spot.' Pick the flowers, keep the soil dampened, and each of the pegged-down branches will take root and become a little plant and go on blooming for the rest of the season.
+Let one thousand flowers bloom. As always, a tape recording or detailed notes are made, and a typescript of this is sent to the absent sitter.  VIII. The Croquet-Ground. A large rose-tree stood near the entrance of the garden: the roses growing on it were white, but there were three gardeners at it, busily painting them red. When words can be used in a more fresh and primitive way so that they strike with the force of sights and sounds, when tones of sound and colors of paint and the carven shape all strike the sensibilities with an undeniable force of data in and of themselves, compelling the observer into an attitude of attention, all this imitates the way experience itself in its deepest character strikes upon the door of consciousness and clamors for entrance. Uncle Dick.
+If I hafta do this to stay alive by God I'll do it. For ten minutes they ran beneath the squall, raising their arms and, for the first time, shouting and capering. By this method it was determined that the normal pressure exerted by a sample of polybutene (molecular weight reported to be 770) was over half an atmosphere. Protons and electrons bear opposite electrical charges which make them attract each other, and when they are joined they make up an atom of hydrogen -- the basic building block of matter. Bear down.
+When entries are being retrieved from this file, the table of dictionary usage indicates which entries to skip and which entries to store in the computer. His voice shook a little. Yet it is now taken for granted. Through which he has granted us the very great and precious promises, so that through them you may become partaker of the divine nature. 
+What God has joined together let no man put asunder.
+The girls are charming children and the men are wonderfully vital and engaging youngsters. It was September 20, 1960, in a lavishly decorated apartment littered with liquor bottles. Understanding, as he did, the difficulty of the art of poetry, and believing that the only technical criticism worth having in poetry is that of poets, he felt obliged to insist upon his duty to be hard to please when it came to the review of a book of verse. Thus, if public pressure sets the effective limit to the price that the industry may charge, this pressure is itself a function of the wage rate. However, on the second time round, she came upon a low curtain she had not noticed before, and behind it was a little door about fifteen inches high: she tried the little golden key in the lock, and to her great delight it fitted! 
+Planck regarded the idea of quanta, as just a mathematical trick, and not as having any physical reality, whatever that might mean. Result is a better prospect for a full payoff by bonds that once were regarded as highly speculative. In order to discuss observations in cosmology, it is helpful to draw a diagram of events in space and time, with time going upward, and the space directions horizontal. Draw a line in the sand. Shayne stepped back to let him slump to the ground, and then dived over him through the open door into Harris who was cursing loudly and trying to drag a gun from a shoulder holster, somewhat impeded by the steering wheel.
+The Vision thing. Wild and woolly. Instead, they are represented by what is called a wave function. `Take off your hat,' the King said to the plumber. He had retained his hat and his horn, and, whatever fun might still be going, he was ready to join it.
+Cosmic strings may sound far-fetched, and pure science fiction, but there are good scientific reasons to believed they could have formed in the very early universe, shortly after the Big Bang. As pure as the driven snow. At this date, it seems probable that the name of Serge Prokofieff will appear in the archives of History, as an effective Traditionalist, who was fully aware of the lure and danger of experimentation, and used it as it served his purpose; yet was never caught up in it -- never a slave to its academic dialectics. It is a consistent picture, but it would imply that we were completely determined: we couldn't change our minds. To his Harvard colleague, Josiah Royce, whose philosophic position differed radically from his own, James could write, different as our minds are, yours has nourished mine, as no other social influence ever has, and in converse with you I have always felt that my life was being lived importantly.
+Anybody's guess. The Szolds, like the Marches, enjoyed and loved living together, even in troubled times; and, as in the March home, any young man who called on the Szolds found himself confronted with a phalanx of femininity which made it rather difficult to direct his particular attention to any one of them. Cut off your nose to spite your face. The superb intellectual and spiritual vitality of William James was never more evident than in his letters. 
+So they go looking for mergers with other firms that have publicly quoted stock, and almost daily they pound on the doors of firms like Frito.
+Joe naturally ruled that a ball be dropped from alongside the spot where it had originally entered the stream. Martin Tahse has established quite a reputation for himself as a successful stager of touring productions. So, can space and time be warped enough, to meet the demands from science fiction, for things like hyper space drives, wormholes, or time travel. Her invitation from Premier Joseph Smallwood is reported to be the only one extended to a woman. `Not at all,' said Michelle: `she's so extremely --' Just then she noticed that Petra was close behind her, listening: so she went on, `-- likely to win, that it's hardly worth while finishing the game.' 
+It is a no win situation: the more accurately you try to measure the position of the particle, the less accurately you can know the speed, and vice versa. Win one for the Gipper. Cherry pick. The work had its beginning in 1938 with an eight-bar musical strain to which Koehler set the words there'll be no more work; there'll be no more worry, matching the spiritual feeling of the jot. Had the situation been reversed, had, for instance, England been the enemy in 1898 because of issues of concern chiefly to New England, there is little doubt that large numbers of Southerners would have happily put on their old Confederate uniforms to fight as allies of Britain.
+This is summed up in the Uncertainty Principle that Heisenberg formulated; the uncertainty in the position of a particle, times the uncertainty in its speed, is always greater than a quantity called Planck's constant, divided by the mass of the particle. In a certain perfectly definite way, the method and the theme of his stories are one and the same. William's conduct at first was moderate. Smooth runs the water where the brook is deep. `That's enough about lessons,' the walrus interrupted in a very decided tone: `tell her something about the games now.' 
+But it would still leave plenty of paradoxes. Many patent contests were waged over automobile components and accessories, among them tires, detachable rims, ball bearings, license brackets, and electric horns. The early appearance of life on Earth suggests that there's a good chance of the spontaneous generation of life, in suitable conditions. Generation X. This absence of boundaries means that the laws of physics would determine the state of the universe uniquely, in imaginary time. 
+Henrietta, however, was at that time engaged in a lengthy correspondence with Joe's older and more serious brother, Morris, who was just about her own age and whom she had got to know well during trips to Philadelphia with Papa, when he substituted for Rabbi Jastrow at Rodeph Shalom Temple there during its Rabbi's absence in Europe. Absence makes the heart grow fonder. First of all, it is now known that Pope John sees the renewal and purification of the Church as an absolutely necessary step toward Christian unity. Power corrupts; absolute power corrupts absolutely. 
+During early childhood, children are more interested in the approval of their parents and teachers than they are in the approval of other children; after they have been in school a few years, their interest in playmates of their own age increases, and their interest in adults decreases; the child who had once considered it a treat to accompany his parents on picnics and family gatherings now considers it a bore.
+For me, these will belong more completely to their surroundings if they are conceived in this early stage, though I freely admit that I do not hesitate to add or eliminate figures on the full sheet when it serves my final purpose. Instead, I shall adopt what is known as the Weak Anthropic Principle. We are forced, in our behavior towards others, to adopt empirically successful patterns in toto because we have such a minimal understanding of their essential elements. After the family has settled in the shelter, the housekeeping rules should be spelled out by the adult in charge. She generally gave herself very good advice, (though she very seldom followed it), and sometimes she scolded herself so severely as to bring tears into her eyes; and once she remembered trying to box her own ears for having cheated herself in a game of croquet she was playing against herself, for this curious child was very fond of pretending to be two people. 
+This organization will differ from existing assistance programs in that its members will supplement technical advisers by offering the specific skills needed by developing nations if they are to put technical advice to work. When the detective left, Andrus phoned his secretary to cancel his work and to advise the network to get a substitute director for his current project. Sometimes we'd have trouble persuading her to make tax-exempt charitable contributions, and I've known her to quarrel with a plumber over a bill for fixing a faucet; the next moment she'd put another half million into the scholarship fund or thirty thousand into something as impractical as this unfortunate Johnston affair. (D) since the shape of the drop conforms to the force field, it does not appreciably affect the distribution of forces in the fluid. `I couldn't afford to learn it.' 
+Only afterwards did an act like that become meaningless, so that he would puzzle over it for days, whereas at the time it had seemed quite real. Almost any travel agent will reserve a car for you. My aim in mentioning this factor obviously is not to give license to wild therapy but rather to encourage us to use the time-honored clinical casework skills we already possess, and to use them with greater confidence, precision, and professional pride. She's a bit of all right. There is no alternative.
+We hope, they said, that no family can be found amongst us without a correct version of the Holy Scriptures. Put the cat amongst the pigeons. But as I have said before, if I announce my candidacy, I will have something definite to say about running mates. All pricks like Coughlin run it anyway, one way or another. (C) payments made pursuant to this Title shall be made only to the person or persons on behalf of whom the award is made, except that -- (1) if such person is deceased or is under a legal disability, payment shall be made to his legal representative : provided, that if the total award is not over $500 and there is no qualified executor or administrator, payment may be made to the person or persons found by the Comptroller General of the United States to be entitled thereto, without the necessity of compliance with the requirements of law with respect to the administration of estates; (2) in the case of a partnership or corporation, the existence of which has been t
 erminated and on behalf of which an award is made, payment shall be made, except as provided in paragraphs (3) and (4), to the person or persons found by the Comptroller General of the United States to be entitled thereto; (3) if a receiver or trustee for any such partnership or corporation has been duly appoint.
+The appointment was made in a move to expand the engineering services offered to the designers of electronic systems through assistance in electro-magnetic compatability problems. I would like to quote from the Charter of the United Nations : Article 17, Section 1 : the General Assembly shall consider and approve the budget of the Organization. `It's really dreadful,' she muttered to herself, `the way all the creatures argue. It may be, of course, that such objectives can be pursued consisently with a policy designed to overthrow Communism; my point is that where conflicts arise they must always be resolved in favor of achieving the indispensable condition for a tolerant world -- the absence of Soviet Communist power. 
+We had stopped before a shop window to assess its autumnal display, when you suddenly turned to me, looking up from beneath one of your wrong hats, and with your nervous ahem ] said : there are things I must tell you about this man you are marrying which he does not know himself.
+This accounts for the wide variance in assessment practices of movable tangible property in the various municipalities in Rhode Island. Their main asset is an abundance of unsaturated fatty acids, so necessary for maintaining the good health of the circulatory system. It has been my lot all through life to associate with eminent scientists and at times to discuss with them the deepest and most vital of all questions, the nature of the hope of a life beyond this. How in the world did one attach a pegboard to a stone wall? Aye-yah-ah-ah ] the Indian was again raising his bottle, but to my astonished relief -- probably only a fraction of Johnson's -- the bottle this time went to the Indian's lips.
+They had a large canvas bag, which tied up at the mouth with strings: into this they slipped the guinea-pig, head first, and then sat upon it.) Pale yellow snapdragons that by pinching could be made to bite; seed-pods of the balsams that snapped like fire-crackers at a touch; red-and-yellow columbines whose round-tipped spurs were picked off and eaten for the honey in them; morning-glory buds which could be so grasped and squeezed that they burst like a blown-up paper bag; bright flowers from the trumpet vine that made gloves on the ends of ten waggling fingers. Everywhere there are little touches of humor, and the leader of the on-stage band of musicians is an ebullient comedian who plays all sorts of odd instruments with winning warmth. We few, we happy few, we band of brothers. The threadbare notion that belief, unlike behaviour, is not subject to objective analysis, has placed intuitive metaphysics squarely against the sociology of knowledge, since it is precisely the jo
 b of the sociology of knowledge to treat beliefs as social facts no less viable than social behaviour.
+The common codes, for religious action as such and in their ethical aspects for everyday moral behavior, bind the devotees together. `Only mustard isn't a bird,' Penelope remarked. The ungainly bird thing ran away, and to David its croaking sounded like the crowing of a tormented rooster. He glanced up in time to see Roberts hurtling down on him from above, literally flying through the air, his bloody face twisted. A good many pages of the first section are taken up with an account of the dogged determination of the prisoners to write to their wives and families -- even when it becomes clear that the Germans are simply allowing the letters to blow away in the wind.
+Blow chunks. `Same as if he had a bone in his throat,' said the unicorn: and it set to work shaking him and punching him in the back. Why it was ever forgotten for even a moment I cannot say because it works perfectly for everyone, no matter whether he has short or long thigh-bone lengths ] it is the one exercise that drastically influences the definition of the thighs at the hipline -- that mark of the champion that sets him apart from all other bodybuilders; a criterion of muscle drama that is unforgettable to judges and audiences alike; the facet of muscular development that wins prizes. Have a Bone to pick. As she said this, she looked up, and there was the Cat again, sitting on a branch of a tree. 
+The first mention of an electric plant in Manchester seems to be one installed in Reuben Colvin's and Houghton's gristmill on the West Branch in Factory Point. Olive branch. Along the 127-mile route through Great Smoky Mountains National Park you can photograph the breath-taking peaks, gorges and valleys which come into view at every turn. A second twitched his shirtsleeve, and he felt a brief burn on his upper arm. 
+As the bus turned into the main highway and headed toward Hanover I settled back in my seat and closed my eyes, thinking over the events of the past two weeks, trying to put the pieces in order.
+She had a face like the back of a bus. County Supervisor Weldon R. Sheets, who is a candidate for the Democratic gubernatorial nomination, today called for an end to paper ballots in those counties in the state which still use them. Use of nomenclature, symbols, units, physical constants for punched-card or tape storage of information all literature values must be conformed to a common language. They all surrounded him, the family circle, Theresa and George as solemn as if they were watching the cat have kittens, and Cousin Emma running back and forth with a kettle of hot water which she poured steaming into a white enamelled pan. For a moment, she could not catch her breath and then, her breath returning in short, frightened spasms, she lifted herself to her feet laboriously.
+Catch 22. `I must be getting somewhere near the centre of the earth. We now have observations that point to black holes in a number of objects, from binary star systems, to the centre of galaxies. The wheel of social life spun around the royal or aristocratic centre. So she was considering in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a rabbit with pink eyes ran close by her. 
+Greasy soils, which are typified by hydrocarbons and fats (esters of glycerol with long-chain organic acids). Ball and chain. As a designer and manufacturer of textile production machinery, Leesona and other companies in its industry have sought to meet this challenge with new or improved equipment and methods that would increase production, yet maintain both quality and flexibility. Here the absent sitter makes a date with a communicator (someone close to him who is deceased), asking him to come in at a certain hour, when a channel will be open for him. At the same time, Roosevelt's Federal Housing Administration, coupled with Henry Morgenthau's cheap-money policy, permitted ordinary lower-middle-class families to build their own homes.
+In general, any outcome we choose may be labeled success. Just as now anyone may hurl insults at a citizen of Mars, or even of Tikopia, and no senatorial investigation will result. After a while, finding that nothing more happened, she decided on going into the garden at once; but, alas for poor Penelope! when she got to the door, she found she had forgotten the little golden key, and when she went back to the table for it, she found she could not possibly reach it: she could see it quite plainly through the glass, and she tried her best to climb up one of the legs of the table, but it was too slippery; and when she had tired herself out with trying, the poor little thing sat down and cried. At least he could climb up on the fence when his tormenters roared by again. In 1922, the United Mine Workers struck the Coronado Coal Company.
+By an effort of historical sympathy we can cast our minds back into the art of a remote past or an alien present, and enjoy the carvings of cavemen and Japanese colour-prints; but the possibility of this effort is bound up with that development of historical thought which is the greatest achievement of our civilization in the last two centuries, and it is utterly impossible to people in whom this development has not taken place. The place was a riot of colour. At one extreme are the systems of upper New York State, where libraries in two or more counties combine to serve a large, sparsely populated area. County college costs to the editor : Sir -- permit me to commend your editorial in which you stress the fact that a program of county colleges will substantially increase local tax burdens and that taxpayers have a right to a clear idea of what such a program would commit them to. 
+Shall I compare thee to a summer's day?.
+Decide first what the place is worth to you and your family as a home in comparison with what it would cost to live in town. It was possible, however, to decompose the compliance into a sum of a frequency-independent component and two viscoelastic mechanisms, each compatible with the Boltzmann superposition principle and with a consistent set of time-temperature equivalence factors. Although there was some variation in results which must be attributed either to trace impurities or to variation in wall effects, the photochemical exchange in the gas phase was sufficiently reproducible so that it seemed meaningful to compare the reaction rates in different series of reaction tubes for the purpose of obtaining information on the effect of chlorine concentration and of carbon tetrachloride concentration on the reaction rate. If the observations disagreed with the predictions of the no boundary hypothesis, we would have to conclude the hypothesis was false. One may conclude that m
 ost of the detected micrometeoritic material is concentrated in orbital streams which intersect the Earth's orbit.
+The reason is, I think, my awareness that my remarks last quarter on pacifism may well have served to confirm the opinion of some that my tendency to skepticism and dissent gets us nowhere, and that I am simply too old to hope. There is a conflict among the defendants. We have every obligation to take seriously their claims to being democratic and free countries; we also have, in consequence, the duty to appraise realistically and honestly their performance and to communicate our judgments to their leaders in frank but friendly ways. Basically, the foam machines that produce such stock consist of two or more pumping units, a variable mixer, a nozzle carriage assembly, and, in many cases, a conveyor belt to transport and contain the liquid during the reaction process and until it solidifies into foam. `Are you content now?' said the caterpillar. 
+This intellectual approach to spiritual life suited me well, because I was never content to lead a divided life. Context is of extreme importance. Such errors would contribute to a gradual genetic drift, which seems to occur in all populations. The State Ballet of Rhode Island, the first incorporated group, was formed for the purpose of extending knowledge of the art of ballet in the Community, to promote interest in ballet performances, to contribute to the cultural life of the State, and to provide opportunity for gifted dance students who, for one reason or another, are unable to pursue a career and to develop others for the professional state; and now, therefore, do I, John A. Notte, Jr., Governor of the State of Rhode Island and Providence Plantations, proclaim the week of Monday, November 13, 1961, as the State Ballet of Rhode Island Week, requesting all Rhode Islanders to give special attention to this unusual event which should contribute to the cultural life of the 
 State. Mr. Nikolais has made a distinctive contribution to the arts of costume and decor.
+But no President ever before referred to his as a lousy job (as Walter Trohan recently quoted President Kennedy as doing in conversation with Sen. Barry Goldwater). According to the new theories, the nineteenth century corporate sovereign was sovereign in a quite new and different sense from his historical predecessors. Several times it came near breaking, and there were in fact some lovely peals of thunder from Jerry Mulligan's big band, which is about as fine an aggregation as has come along in the jazz business since John Hammond found Count Basie working in a Kansas City trap. Folk-lore, superstition and remembered passages from erotic literature can create physical and emotional problems if blindly taken as scientific facts and useful hints. He has a nose for crime.
+Piepsam's fatal rage arises not only because he cannot stop the cyclist, but also because God will not stop him; as Piepsam says to the crowd in his last moments : his justice is not of this world. Far from the madding crowd. `Chorus again!' cried the lion, and the cheetah had just begun to repeat it, when a cry of `The trial's beginning!' was heard in the distance. Today a battle cry may seem an anachronism, for in the modern Army, esprit de corps has been sacrificed to organizational charts and tables. 
+They all three had another cup of coffee.
+My cup runneth over. Other brothers later joined them for instruction with Oldenburg, the wigmaker, and also arithmetic was added to Bible reading, German, and Danish in the informal curriculum. The customer loses again. There was collateral damage. A little knowledge is a dangerous thing.
+Fortunately, the debt of gravitational energy will not have to be repaid until the end of the universe. A third Thomas Bushell (1594-1674), much loved by Bacon, called himself The Superlative Prodigall in The First Part of Youths Errors (1628) and became an expert on silver mines and on the art of running into debt. However, she got up, and began to repeat it, but her head was so full of the Lobster Quadrille, that she hardly knew what she was saying, and the words came very queer indeed:-- `'Tis the voice of the Lobster; I heard him declare, "You have baked me too brown, I must sugar my hair." Bergson and Leroy announce that the secret is the center of a philosophy and thereafter a hundred followers declare secrecy a higher verity. I have nothing to declare but my genius.
+Here are the two Preambles : Federal Constitution, 1789 we the people of the United States, in order to form a more perfect union, establish justice, insure domestic tranquility, provide for the common defence, promote the general welfare, and secure the blessings of liberty to ourselves and our posterity, do ordain and establish this Constitution for the United States of America. In such a case the defendant should serve as a clear example and not have to be tied to the issue by argument. One can define Life to be an ordered system that can sustain itself against the tendency to disorder, and can reproduce itself. Here briefly in this humble tribute I have sought for some simple and succinct summation that would define the immense service of this patriot to his country. Thus it fits the definition of a living system, that I have given. 
+Very soon after his arrival in Little Rock, Pike had joined one of the most influential organizations in town, the Little Rock Debating Society, and it was with this group that he made his debut as an orator, being invited to deliver the annual Fourth of July address the club sponsored every year. Stand and deliver. `I deny it!' said the squirrel. Most of these, with horrible exceptions, were conceived as is a ship, not as an attempt to quell the ocean of mankind, nor to deny its force, but as a means to survive and enjoy it. He or his deputy or one of their seven assistants, all full colonels, mans the heart of the command post twenty-four hours a day.
+The terms renewal and refreshed, which often come up in aesthetic discussion, seem partly to derive their import from the renewal of purpose and a refreshed sense of significance a person may receive from poetry, drama, and fiction. It becomes most evident in his description of Christ as the second Adam, who does indeed come to destroy sin, but whose work culminates in the achievement of immortality. It beggar'd all description. During the first few days of wearing the appliance and immediately following each adjustment, Susan may have a slight discomfort or soreness, but after a short time this will disappear. 
+It would not be easy to discover a more thoroughly Southern pedigree than that of his family.
+But some people won't be able to resist the temptation, to improve human characteristics, such as size of memory, resistance to disease, and length of life. To the middle of September 1918, there had been fewer than 10,000 deaths from disease in the new army. They divide up the household chores : Cerv does most of the cooking (breakfast and sandwich snacks, with dinner out), Mantle supplies the transportation (a white 1961 Oldsmobile convertible), and Maris drives the 25-minute course from the apartment house to Yankee Stadium. The potters, in particular, had virtually eschewed freehand drawing, elaborate motifs, and the curving lines of nature, while yet expressing a belief that there was order in the universe. On the glass partition between me and the driver were three signs : one asked for help for the blind, another help for orphans, and the third for relief for the war refugees.
+He was a back seat driver. All the additives listed here are sanctioned for use by the Food and Drug Administration of the federal government. Mr. Sansom actually writes his with a nice ear for a gracefully composed sentence, with an intense relish in all the metaphorical resources of English, with a thick shower of sophisticated, cultural references. Minors minors must also file returns if they earn $600 or more during the year. Set the apples in the pastry-lined tin, spread over them three tablespoonfuls of softened butter, with as much brown sugar, a sprinkling of nutmeg, and a fresh bay leaf, then lay on a cover of pastry, and gild it with beaten yolk of egg.
+I will give you a nest egg. The electric gadget is most helpful when there are many crowned teeth and in individuals who are elderly, bedfast with a chronic disease, or are handicapped by disorders such as cerebral palsy or muscular dystrophy. There is some indication from a limited number of interviews with members of the population that the element of power, primarily the voluntary influence of non-authoritative power, has been exerted on actors in the system, particularly in regard to mate selection. Some people have therefore suggested that life came to Earth from elsewhere, and that there are seeds of life floating round in the galaxy. An alert dean will confer all through the year on personnel needs, plans for the future, qualifications of those on the job, and bright prospects elsewhere.
+When these fields are surveyed together, important patterns of relationship emerge indicating a vast community of reciprocal influence, a continuity of thought and expression including many traditions, primarily literary, religious, and philosophical, but frequently including contact with the fine arts and even, to some extent, with science. The conversion to magnetic tape is not yet completed, he said, and added Field's long service in state government and welfare employ gave him familiarity with the welfare program. To win her favors, her husband first took an additional job, then desperately began to embezzle from his employer. This is that the classical theory, does not enable one to calculate what would come out of a singularity, because all the Laws of Physics would break down there. What better affirmative step could be taken to this end than repeal of the Connally amendment -- an act which could expose the United States to no practical risk yet would put an end to ou
 r self-judging attitude toward the court, enable us to utilize it, and advance in a tangible way the cause of international law and order?
+This did not seem to encourage the witness at all: he kept shifting from one foot to the other, looking uneasily at Rebecca, and in his confusion he bit a large piece out of his teacup instead of the bread-and-butter. The poor little thing was snorting like a steam-engine when she caught it, and kept doubling itself up and straightening itself out again, so that altogether, for the first minute or two, it was as much as she could do to hold it. While the pupil sang the second verse of the song, she kept tossing the baby violently up and down, and the poor little thing howled so, that Penelope could hardly hear the words:-- `I speak severely to my boy, I beat him when he sneezes; For he can thoroughly enjoy The pepper when he pleases!' In the middle grades, however, he begins to participate more effectively in group activities such as selecting a leader, helping to make plans and carry on group activities, and setting up rules governing the enterprise. 
+The sweep of space, the delicate counterbalance of the white masses, the over-all completeness and unity, the originality and imagination, all entitle it to be called an authentic masterpiece.
+Most entry blanks for competitive events require engine displacement information because of class restrictions. All areas of history were either favorably or adversely affected by the geographical environment, and no respectable historian could pursue the study of history without a thorough knowledge of geography. Simultaneously, a variety of environmental supports -- a calm but not too motherly homemaker, referral for temporary economic aid, intelligent use of nursing care, accompaniment to the well-baby clinic for medical advice on the twins' feeding problem -- combined to prevent further development of predictable pathological mechanisms. They were asked to vote true if they thought they had seen him make the error, false if they thought he had not; and cannot say if they were not certain. A recent, and more pertinent action, has been the establishment of a technical staff reporting to the vice-president for Engineering.
+A fragmented Society (3) over the years, individuals engaged in the sale of real estate have developed remarkable unity in the methods and practices employed. The unshielded flux is given in the last column; these figures constitute the best estimate for the flux in interplanetary space near the Earth. Comprehensive examination of any policy question calls for the performance of the intellectual tasks inseparable from any problem-solving method. And he added in an undertone to Rebecca, `Really, my dear, YOU must cross-examine the next witness. We must, therefore, have a look at the new archaeological material and re-examine the literary and place-name evidence which bears upon the problem.
+So it was that when Mr. Brown and Mr. Sharpe first saw the French tool on exhibition in Paris in 1868, they brought a sample with them to the United States and started Brown & Sharpe in yet another field where it retains its leadership to this day. (B) all research within the United States contracted for, sponsored, cosponsored, or authorized under authority of this Act, shall be provided for in such manner that all information, uses, products, processes, patents, and other developments resulting from such research developed by Government expenditure will (with such exceptions and limitations, if any, as the Secretary may find `-- so long as I get SOMEWHERE,' Sharon added as an explanation. What are the chances that we will encounter some alien form of life, as we explore the galaxy. He bases his present contention on the general right to explore, indicating that he hopes to find some discrepancy in the resume.
+He can be expected, however, to examine and interpret the information already available; to refine and extend his own techniques for studying individual children; and to utilize opportunities, arising in connection with regular classroom activities, for gaining a better understanding of his pupils. A third possibility is that there is a reasonable probability for life to form, and to evolve to intelligent beings, in the external transmission phase. Extra, extra, read all about it. One possibility is that the formation of something like DNA, which could reproduce itself, is extremely unlikely. During the early part of this century, the Brown & Sharpe works in Providence were unchallenged as the largest single manufacturing facility devoted exclusively to precision machinery and tool manufacture anywhere in the world.
+Another way, in which life could fail to develop to an intelligent stage, would be if an asteroid or comet were to collide with the planet. Always troubled by poor circulation in his feet, he experimented with various combinations of socks and shoes before finally adopting old-style felt farmer's boots with his sheepskin flying boots pulled over them. There was no way to predict what they would do, and the only hope was to win favour by gifts or actions. I ask you to do me the last favour of reading them by 8 to-morrow evening, about which time I sh 
+As one added more layers of paint, the ball would eventually fill half the space. 
+In both cases the finger-post represents Pip's heightened awareness of contrary magnetisms. After spending two nights (Wednesday and Thursday) in Catskill, the deputies again headed for the Vermejo to finish their business. Others, which are reached by walking up a single flight of stairs, have balconies. To me you'll always be the girl o' my dreams, an' the sweetest flower that grows. Fly by the seat of your pants.
+Here the war would flame to its focus, and here Lewis Littlepage had come. But it is not too difficult to visualise a two dimensional surface, like a saddle, or the surface of a football. `They're putting down their names,' the giraffe whispered in reply, `for fear they should forget them before the end of the trial.' The concern they felt for me was such as I shall never forget and for which I will always be grateful. In contrast to cocktail parties, military organizations, even in the field, are more formal.
+Along with the fruit they did also fall under the power of death, because they did eat in disobedience; and disobedience to God entails death. Forbidden fruit. If a massive star, which has burnt up its nuclear fuel, cools and shrinks below a critical size, it will quite literally make a bottomless hole in space-time, that light can't get out of. Patterson Moos research our Patterson Moos Research Division has made further very encouraging progress in development of fuel cells. I hadn't been doing as much work as I used to in Westfield and I felt funny about that and wanted to work harder than ever.
+They were staring at him in the same blank and menacing way that the men outside the gate had stared. Hark, hark! the lark at heaven's gate sings. There was considerable contrast between this Mulligan performance and that of Art Blakey and The Jazz Messengers, who are able to generate a tremendous sound for such a small group. This was the Steady State theory, proposed by Bondi, Gold, and Hoyle. To gild refined gold, to paint the lily.
+You grant that?' `In my youth,' said the sage, as he shook his grey locks, `I kept all my limbs very supple By the use of this ointment -- one shilling the box -- Allow me.  A paying guest. But because it is the function of the mind to turn the one into the other by means of the capacities with which words endow it, we do not unwisely examine the type of distinction, in the sphere of politics, on which decisions hang. 
+When the Mouse heard this, it turned round and swam slowly back to her: its face was quite pale (with passion, Sharon thought), and it said in a low trembling voice, `Let us get to the shore, and then I'll tell you my history, and you'll understand why it is I hate cats and dogs.' 
+And the Eaglet bent down its head to hide a smile: some of the other birds tittered audibly. Does the surface hide a quite different picture? Neither hide nor hair. `Then the eleventh day must have been a holiday?' The stranger's eyes were large and sad, as if Phil Haney had hurt his feelings.
+The natural and primary aesthetic attitude is to enjoy contemporary art, to despise and dislike the art of the recent past, and wholly to ignore everything else. Let me illustrate. And our question is, is such an implication consistent with what we meant? In one now-historic first interview, for example, the transcript (reproduced from the book, the First Five Minutes) goes like this : the therapist's level tone is bland and neutral -- he has, for example, avoided stressing you, which would imply disapproval; or surprise, which would set the patient apart from other people. It is always a temptation for a religious organization, especially a powerful or dominant one, to impose through the clenched fist of the law its creedal viewpoint upon others.
+All these emotions were screwed up to new heights when, after acceptance and the first rehearsals, there ensued such a buzz of excitement among Parisian music lovers that Duclos had to come running to Rousseau to inform him that the news had reached the superintendent of the King's amusements, and that he was now demanding that the work be offered first at the royal summer palace of Fontainebleau. Hospital officials said the injury was severe but the youth was in good condition last night. Such a general boycott might still be a blunt or indiscriminating instrument, and therefore of questionable justification. It can put an end to marginal claims which play havoc with your insurance rates. Before they could guess his intention Rankin stepped forward and swung the guard's own gun against the uncovered head, hard.
+Democrat Stanley H. Dent, Chairman of the House Military Affairs Committee, declined to introduce the bill. His assignment was not a new one because Baker had sent him to the Mexican border in 1916 to investigate lurid newspaper stories about lack of discipline, drunkenness, and venereal disease in American military camps. I couldn't invite Viola to our house, for Mother snobbishly refused to receive her. However, this need not involve problems with determinism or free will, if the probabilities are very small, for histories in which space-time is so warped, that time travel is possible over a macroscopic region. The capital expansion programs of business firms involve multi-year budgeting and the same is true of country development programs.
+They would have been hotter than the Sun, and would have burnt the original hydrogen and helium, into heavier elements, such as carbon, oxygen, and iron. An Iron hoof. Determine if the particular State's unadjusted allotment (result obtained in item 11 above) is greater than its maximum allotment, and if so lower its unadjusted allotment to its maximum allotment. Put your nose out of joint. 
+`Of course not,' said the porpoise: `why, if a fish came to ME, and told me he was going on a journey, I should say "With what porpoise?"' 
+Over the rapidly-diminishing outline of a jump seat piled high with luggage Herry's black brushcut was just discernible, near, or enviably near that spot where -- hidden -- more delicately-textured, most beautifully tinted hair must still be streaming back in cool, oh cool wind sweetly perfumed with sagebrush and yucca flowers and engine fumes. Most of the letters were written in the hubbub of camp, on stumps, pieces of bark, drum heads, or the knee. It was a labour of love. Sharon thought the whole thing very absurd, but they all looked so grave that she did not dare to laugh; and, as she could not think of anything to say, she simply bowed, and took the thimble, looking as solemn as she could. You can laugh at His blood-bought salvation, curse His followers, and laugh at hell.
+It was a quarter of seven when the crowd washed me up among the other gallants who had established the Astor steps as the beach-head from which to launch their night of merrymaking. Barrack room lawyer. They went as rigid as black statuary six figures, lean and tall and angular, went still. It is because each side has sought to implement its distinctive theological belief through legislation and thus indirectly force its belief, or at least the practical consequences thereof upon others. Usually premium reductions can be obtained by applying deductibles to your liability plan.
+There was no use in standing there in the drizzle, trying to find a link between Emile's murder and opium in a cup of coffee. She was biting into a small red radish; and that action always caused her to lift her lip from the sting of the thing. Bite your lip. The Carbondale Industrial Development Corp. has obtained a $500,000 loan to help defray the cost of remodeling a city-owned factory to accommodate production that will provide 500 new jobs. In the Piazza Navona there are many delightful cafes where you can sit, have a drink or lunch, and watch the fountains in the square.
+He must deal with the question of how to manage a part when it cannot be handled without relation to the whole -- when the whole is too large to grasp. There is a project now on, to map the entire sequence of human DNA. Various methods of pulsing, scanning, and displaying these sound waves are used to detect submarines, map ocean floors, and even communicate under water. Mary was free to marry again, not knowing that the Sturch had secretly given her a divorce, thinking that death had dissolved her marriage. We will hatch, match and dispatch.
+The long grass rustled at her feet as the porcupine hurried by -- the frightened Mouse splashed his way through the neighbouring pool -- she could hear the rattle of the teacups as the soldier and his friends shared their never-ending meal, and the shrill voice of Tracey ordering off her unfortunate guests to execution -- once more the pig-baby was sneezing on the teacher's knee, while plates and dishes crashed around it -- once more the shriek of the rhino, the squeaking of the Lizard's slate-pencil, and the choking of the suppressed guinea-pigs, filled the air, mixed up with the distant sobs of the miserable whale. She served up a square meal. `May it please your Majesty,' said Two, in a very humble tone, going down on one knee as he spoke, `we were trying --' `I see!' said Tracey, who had meanwhile been examining the roses. Vicky Kowalski meanwhile learned that several of her fellow students had collected almost $25 for her family during the lunch hour yesterday at Fuhrma
 nn Junior High School, 5155 Fourteen Mile road east. 
+The basic difference between the continuous cutting mechanism and that of the chipping mechanism is that instead of shear occurring in the coating ahead of the knife continuously without fracture, rupture intermittently occurs along the shear plane.
+Thus, for aqueous media, we can think of the idealized organic active as an oleophilic or hydrophobic surface-active agent, and of an idealized builder as a oleophobic or hydrophilic surface-active agent. `I hope they'll remember her saucer of milk at tea-time. Both parties and the Ministry of the Interior were busily at work after the elections trying to unearth the political affiliations of the successful candidates and, thereby, give the elections a confidential but known degree of national political significance. Zion was surprised when Roy's buggy stopped beside her on the pike one early summer day as she was walking home from the country school where she was teaching now that Eph Showers had had a call to preach in some mountain town. In a general way, psychiatrists were able to establish on a wide basis what many of them had always felt -- that the most telling cues in psychotherapy are acoustic, that such things as stress and nagging are transmitted by sound alone an
 d not necessarily by words.
+The third choice, negotiation, presupposes, as Russian behavior demonstrates, a great deal of wishful thinking to make it appear reasonable. Gertrude could see, as well as if she were looking over their shoulders, that all the jurors were writing down `stupid things!' on their slates, and she could even make out that one of them didn't know how to spell `stupid,' and that he had to ask his neighbour to tell him. Reliance is therefore not to be placed upon the archaeological particulars in an oral poem; no-one today would hope to discover the unmistakable ruins of Heorot or the palace of Priam. Gavin began to nod. It's as good as a nod and a wink.
+If high accuracy is required in preflight leveling, it is usually necessary to integrate or doubly integrate the accelerometer outputs (this also minimizes the noise problem). There was a big noise. This is called imaginary time, because it is not the kind of time we normally experience. When someone says, for example, they took x-rays to see that there was nothing wrong with me, it pays to consider how this statement would normally be made. When he heard of his brothers' anger, Palfrey was still hopeful that they could be persuaded to accept his notion of paying wages.
+Tenderly and rather tediously, the camera rivets on the abrupt, deep love of a pretty nurse and a uniformed teacher, complicated by nothing more than a friend they don't want to hurt. The 10.3-cm observation of Sloanaker was made on May 20, 1958, using the 84-foot reflector at the Maryland Point Observatory of the U. S. Naval Research Laboratory. Centering around this historic old structure, a group of public-spirited Barbour County citizens have organized and planned a week-long series of events, beginning on May 28th and continuing through June 3rd, to observe most appropriately the centennial of the first land engagement of the Civil War at Philippi. As early as 1913 Ghoreyeb and Karsner demonstrated with perfusion studies in dogs that bronchial artery flow would remain constant at a certain low level when pressure was maintained in the pulmonary artery and vein, but that increases in bronchial artery flow would occur in response to a relative drop in pulmonary artery pre
 ssure. And how odd the directions will look! 
+Okay, Stormy, this isn't the place for fun and games. Okay. Its pretense to operate in the public interest is little more than a sham. Some opposition to the home rule movement started to be heard yesterday, with spokesmen for the town's insurgent Democratic leadership speaking out against the home rule charter in favor of the model municipal league charter. 
+Any adjustments which are made, Mr. Grenier said earlier this month, will appear on the balance of the tax bill since most of the town's taxpayers take the option of paying quarterly with the balance due next year.
+Our objectives, as we have stated many times, are -- (1) to provide some service to all listeners; (2) to provide as many choices of service to as many listeners as possible; (3) to provide service of local origin to as many listeners as possible. Don't go splashing paint over me like that!' Center panel, hand-screened wood, actually is a back of one of the tall bookcases. Girls, my dear parent, are here to stay ] get my old man to bed early. In 1899, Parliament erected a statue to Cromwell in Westminster, facing Whitehall and there, presumably, he still stands.
+`-- you advance twice --' `Each with a lobster as a partner!' cried the giraffe. She was ready for her great adventures and the arrival of her mobile partner. She is a bird of passage. This strange person quarrels with a cyclist because the latter is using the path rather than the highroad. Primrose path.
+He had returned to the pension a week ago. These specialists perform valuable services by helping teachers learn to identify children who need special attention, by suggesting ways of meeting the needs of individual children in the regular classroom, and by providing clinical services for severely maladjusted children. If a child loses a molar at the age of two, the adjoining teeth may shift toward the empty space, thus narrowing the place intended for the permanent ones and producing a jumble. In Revulsion, on the other hand, the pessimism is a case not proven; the poem offers nothing to persuade us of the speaker's right to speak as he does. Information can not be carried free, as those of you with phone bills will know. 
+Phone service criticized to the editor of the New York Times : as a business man I have to use the telephone constantly, from three to four hours a day. China plate. The respectability which money confers implies a different etiquette, and, upon taking up the life of a London gentleman, Pip must learn from Herbert Pocket that the spoon is not generally used over-hand, but under. Out of pocket. I prefer to speak, however, of Sam Rayburn, the person, rather than Sam Rayburn, the American institution.
+A prime objective of the Army Quartermaster Corps program is to find the reasons for beef's low palatability and means of overcoming it, since it is a major and desirable dietary item. `She's in prison,' Tracy said to the executioner: `fetch her here.' `Are they in the prisoner's handwriting?' asked another of they jurymen. 1 Andre Malraux's The Walnut Trees Of Altenburg was written in the early years of the second World War, during a period of enforced leisure when he was taken prisoner by the Germans after the fall of France. 
+`And so these three little sisters -- they were learning to draw, you know --' `What did they draw?' said Chris, quite forgetting her promise. 
+Man was created with the capacity for immortality, but the devil's promise of immortality in exchange for disobedience cost Adam his immortality. I'll give you a lick and a promise. I would propose, first, an abandonment of attempts at a universal lexical list, as intrinsically unachievable, and operationally inadequate in proportion as it is achieved. `I'm afraid I don't know one,' said Harriet, rather alarmed at the proposal. `Please your Majesty,' said the Knave, `I didn't write it, and they can't prove I did: there's no name signed at the end.' 
+What determines the morality, they state, is not the means used, but the motive in general, the means (excluding abortion) that prove most effective are considered the most ethical. If, say, the Russians intended to stop Tom Jones' going to the pub, then Tom Jones would fight the Commies. Have you set specific objectives for your employee publication? To begin with, the all-powerful Los Angeles Times does not publish a transcript of these press conferences. Pull out all the stops.
+He was crouched over his anvil in the courtyard getting his chisels into trim, when a splinter of steel flew into his eye and imbedded itself in his pupil. He sent them word I had not gone (We know it to be true): If she should push the matter on, What would become of you? In the railway station at Berlin, a uniformed attendant was chanting, foreigners this way ] foreigners this way ] one woman -- she could have been either English or American -- went up to him and said, but you are the foreigners. It argued, inter alia, that a divestiture order would severely depress the market value of the stock of both General Motors and Du Pont, with consequent serious loss and hardship to hundreds of thousands of innocent investors, among them thousands of small trusts and charitable institutions; that there would be a similar decline in the market values of other automotive and chemical stocks, with similar losses to the stockholders of those companies; that the tremendous volume of Ge
 neral Motors stock hanging over the market for ten years would hamper the efforts of General Motors and other automobile manufacturers to raise equity capital; and that all this would have a serious adverse effect on the entire stock market and on general business activity. For that matter, Stan Musial is rare, possessing the disposition that enabled him to put out the same for seven managers, reserving his opinions, but not his effort.
+However, I now realise I was wrong, as these solutions show. If the change, at first sight, seems minor, we may recall that it took the Italian painters about two hundred years to make an analogous change, and the Italian painters, by universal consent, were the most brilliant group of geniuses any art has seen. This brief resume hardly does the book justice, but I heartily recommend it to all those who are engages with the major problems of our time. These increased costs are partially offset by a decrease of $56 million in expenditures for the reserve forces, largely because of the planned reduction in strength of the Army Reserve components during 1961. And I was certain he would refuse.
+Give him an offer he can't refuse. Nor have we remembered that in the melting pot of America the hundreds of isolated and semi-isolated ethnic, regional and occupational groups did not fuse into a homogeneous national unit until long after education and industrialization had caused them to cast oral tradition aside as a means of carrying culturally significant material. He does not mean, in fact he addresses himself specifically to reject the proposition, that if we took the risk of surrendering, a new generation in Britain would soon begin to amass its strength in secret in order to reverse the consequences of that surrender. In the areas that do not relate directly to the educational program, expert subordinates will serve the college or university better than close presidential attention. 
+Industry costs we assume that average total unit cost in the relevant region of operation is constant with respect to quantity produced (the average cost curve is horizontal, and therefore is identical with the marginal cost curve), and is the same for every firm (and therefore for the industry).
+Newspaper punditry was inspired to remind everyone that Judas, too, had been able to smile. They could eventually replace DNA based life, just as DNA may have replaced an earlier form of life. It resembles, too, pictures such as Durer and Bruegel did, in which all that looks at first to be solely pictorial proves on inspection to be also literary, the representation of a proverb, for example, or a deadly sin. In this way, the system can satisfy the requirement that the total amount of disorder increases, while, at the same time, increasing the order in itself and its offspring. Still she went on growing, and, as a last resource, she put one arm out of the window, and one foot up the chimney, and said to herself `Now I can do no more, whatever happens. 
+We took the matches -- they were book matches and once they'd been touched might retain fingerprints -- and the change. Simple yes or no answers do not reveal the different shades of opinion that the various respondents may have. Taken for a ride. However, it was over at last, and they sat down again in a ring, and begged the Mouse to tell them something more. This is the tale of one John Enright, an American who has accidentally killed a man in the prize ring and is now trying to forget about it in a quiet place where he may become a quiet man.
+Rock and roll. Route one. `Get up!' said Tracy, in a shrill, loud voice, and the three gardeners instantly jumped up, and began bowing to Robert, Valerie, the royal children, and everybody else. It was a battle royal. Most marketing people agree it is going to take redoubled efforts to satisfy future requirements.
+But the really controversial aspect of customer-cost imputation arises because of the cost analyst's frequent practice of including not just those costs that can be definitely earmarked as incurred for the benefit of specific customers but also a substantial fraction of the annual maintenance and capital costs of the secondary (low-voltage) distribution system -- a fraction equal to the estimated annual costs of a hypothetical system of minimum capacity. More than that, Allied air had complete superiority in the Eighth Army's sector. By the very nature of the situation, it is the union which has been able to select the time and place to bring pressure upon management. The only requirements on dictionary information made by the text-lookup operation are that each form represented by the dictionary be available for lookup in the text-form list and that information for each form be available in a sequence identical with the sequence of the forms. `If you're going to turn into a
  pig, my dear,' said Harriet, seriously, `I'll have nothing more to do with you. 
+Such wormholes have been seriously suggested, as being within the capabilities of a future civilization. The old woman complained to the deputy governor, who ordered the servant brought before the court. The moment Harriet appeared, she was appealed to by all three to settle the question, and they repeated their arguments to her, though, as they all spoke at once, she found it very hard indeed to make out exactly what they said. Could be scramble some predict the administration will settle down during 1961 and iron out the rough edges which it has had thus far. 
+Attorneys for the mayor said that an amicable property settlement has been agreed upon.
+Once again, there was a negative shake. Shake a leg. I'll shoot the first man who doesn't. Shoot a fairy. With shout and slow dance, with tears and song, with scream and contortion, the corner group was beset by hysteria and shivering, wailing, shouting, possession of something that seemed like an alien and outside force. I like cream of mushroom soup. 
+Giselle was reluctant but Alex succeeded in persuading her to come back in five minutes and the door was shut again. Shut your cake hole. There seems to be almost a conspiracy of silence veiling it. It is perhaps difficult to conceive, but imagine that tonight on London bridge the Teddy boys of the East End will gather to sing Marlowe, Herrick, Shakespeare, and perhaps some lyrics of their own. He thought of Joe Harris, the nigger who had gone after his sister.
+A ministering angel shall my sister be. He carried it in a little wallet made of fish skin. A difference of opinion arose between Mr. Martinelli and John P. Bourcier, town solicitor, over the exact manner in which the vote is handled. `I'm very sorry you've been annoyed,' said Ingrid, who was beginning to see its meaning. I am terribly sorry to keep you waiting, she said, but won't you make yourself a little drink while you wait?
+`You're a very poor speaker,' said the King. As to protection, the speaker disapproved of shelters, pointing out that fallout shelters would not save everyone. Fishing interest calls for a check of the species found, quantity and size, the season they are available, and the stocking program of the fish commission. Some manufacturers have had the foresight to provide a socket for the chuck key; otherwise, you'll have to spend a few minutes to either attach a suitable spring clip somewhere on the press head or fit the key to a length of light chain and fasten to the bottom of the motor mount so that the key is out of the way when not in use. Spend a penny.
+It is blind, fundamentalist dogmatism to say, messing around with the King James version seems to us a perilous sport at best. The Sport of kings. More than the fans of Pagnol's old films and of their heroic star, the great Raimu, were looking askance at the project. Star crossed lovers. 
+Steal a march.
+Rector was warming to his over-all strategy by the time he got back to the residential hall. Strike a deal. One can have a wave function that is very strongly peaked in a small region. The twirled, stylized design of winding stems and floral forms strongly suggests the embroidered patterns used so extensively for upholstery during the Jacobean period in England. Exhibition ballroom dancers from the studio of Helen Wick Walters of Hillsboro won the all-county talent contest.
+More potent a charm to bring back that time of life than this record of a few pictures and a few remembered facts would be a catalogue of the minutiae which are of the very stuff of the mind, intrinsic, because they were known in the beginning not by the eye alone but by the hand that held them. With the neutralists maintaining pressure for one of their own to succeed Mr. Clinton, Joe emerged as the only possible candidate unlikely to be waylaid by a veto. I suffer from mixed feelings. Cogito ergo sum. Yet, the idea imbedded in each was identical : to surround the unknown with mystery and to isolate that class which had been given special dominion over the secrets of God.
+Red tape. At the same time, I am aware that my recoil could be interpreted by readers of the tea leaves at the bottom of my psyche as an incestuous sign, since theirs is a science of paradox : if one hates, they say it is because one loves; if one bullies, they say it is because one is afraid; if one shuns, they say it is because one desires; and according to them, whatever one fancies one feels, what one feels in fact is the opposite. Can you see a tea leaf. One of the greatest obstacles to the achievement of this goal is the lack of trained men and women with the skill to teach the young and assist in the operation of development projects -- men and women with the capacity to cope with the demands of swiftly evolving economics, and with the dedication to put that capacity to work in the villages, the mountains, the towns and the factories of dozens of struggling nations. Magwitch terrifies Pip into stealing a pork pie for him by creating the image in the boy's imagination 
 of a bogy man who may softly creep his way to him and tear him open, imbruing his hands in him.
+This has been more evident since our products have incorporated astronomically increased technology. Substances other than detergent actives also tend to be strongly sorbed from aqueous media onto surfaces of other contiguous condensed phases. The rocking is actually felt in the story, a terrible and ominous rhythm that prophesies the tragedy. Thank you for listening. At last he said, Well, thank you for calling, Mr. Benson.
+That society responds by condemning the private eye as a threat to the status quo, a potential criminal. The official military establishment can only threaten to use its nuclear arms; it cannot bring them into actual play. If it fails to pass, he can throw up his hands and say the Legislature would not support him in his efforts to prevent integration. It was a stone's throw from there. 
+Still another group of seeds (sometimes tiny, dry, seed-bearing fruits) provide distinctive flavors and odors to foods, although the nutrients they supply are quite negligible.
+Not tonight Josephine. It expanded from hand screw machines to automatic screw machines, from simple formed-tooth gear cutting machines to gear hobbing machines and a large contract gear manufacturing business, from rudimentary belt-driven universal milling machines to a broad line of elaborately controlled knee-type and manufacturing type milling machines. How sharper than a serpent's tooth it is to have a thankless child. Fast track. The twenty-five-year-old recording offers rather faded string tone, but the balance between the instruments is good and the transfer is very quiet.
+Trick or treat. Catherine's first war against the Grand Turk had ended in 1774 with a peace treaty quite favorable to her. However, in the same three-month period, toll-road bonds, as a group, have bucked this trend. Juliet looked at the jury-box, and saw that, in her haste, she had put the Lizard in head downwards, and the poor little thing was waving its tail about in a melancholy way, being quite unable to move. These gentlemen already have done the party harm by their seeming reluctance to vote aid for the depressed areas and by their criticism of Mr. Kennedy for talking about a recession and unemployment.
+Perhaps the Jewish students at Brooklyn College -- constituting 85 per cent of those who attend the day session -- can serve as a paradigm of the urban, lower-middle class Jewish student. In the final analysis, then, the user becomes either a bull or a bear in a given instance, notwithstanding any amount of forethought and calculation, however elaborate. We observe a slight variation in the rate of some pulsars, and this is interpreted as indicating that they are being disturbed, by having Earth sized planets going round them. Test specimens the preparation of test specimens will vary depending upon the type of dimensional restorability procedure (if any) to be used. Fashion victim.
+The video signal is amplified and then switched, in synchronism with the three ultraviolet light sources which are sequenced by the rotating mirror so that during one-twentieth of a second only one wavelength, corresponding to red, green, or blue, is seen. Pig!' She said the last word with such sudden violence that Juliet quite jumped; but she saw in another moment that it was addressed to the baby, and not to her, so she took courage, and went on again:-- `I didn't know that Cheshire cats always grinned; in fact, I didn't know that cats COULD grin.' Probably every visitor has a favorite time for his first sight of it. If they really want to colonize the Earth, or warn us of some danger, they are being pretty ineffective. The game was a wash out.
+The crowd did a Mexican wave. Analysis in roleplaying is usually done for the purpose of understanding strong and weak points of an individual or as a process to eliminate weak parts and strengthen good parts. Something for the weekend sir?. Whereas the earlier cases turned rather narrowly upon the availability of adequate state remedies, the new emphasis is upon the nature of the state policy at issue. 
+However, in a universe with a very large, or infinite, number of stars, one would expect it to occur in a few stellar systems, but they would be very widely separated. 
+The dark brown bombs hanging under each wing looked large and powerful. On a wing and a prayer. Who can resist a name that is such a winner? The Rocking Horse Winner is also a story about a boy's love for his mother. Maybe I should withdraw my advice - no?
+Knock on wood. Special time off in granting bereavement leaves, specify the maximum time off and list what the worker's relation to the deceased must be to qualify. He boomed a 280-yard drive. Yeah, passed your road block as I drove in, I said, sitting on his polished desk. 
+My name is Jacob. 
+Hello I'm Michael. My name is Matthew. Hello I am Joshua. 
+My name is Christopher. My name is Nicholas. 
+My name is Andrew. My name is Joseph. My name is Daniel. 
+My name is William. 
+My name is Emily. My name is Madison. My name is Hannah. 
+My name is Ashley. 
+My name is Alexis. My name is Samantha. My name is Sarah. 
+My name is Abigail. 
+My name is Elizabeth. My name is Jessica. Hi. I am Emma. 
+Hi, I am Kaitlyn. 
+Hello, I'm Hailey. Hi, my name is Olivia. Hi, my name is Isabella. 
+Hello I am Jacob. Hi my name is Aidan. Hello my name is Ethan. 
+I am Ryan. Hello my name is Matthew. Hi my name is Nicholas. 
+My name is Michael. My name is Joshua. I am Tyler. My name is Ryan. 
+My name is Joshua. My name is Michael. I am Nicholas.
+My name is Zachary. My name is Connor. Hello my name is Tyler.
+Hello Michael. Jessica and Matthew and Ashley and Christopher and Amanda 
+and Joseph and Nicole and Daniel and Samantha and Nicholas and Stephanie
+and Anthony Lauren and John and Jennifer and Kevin and Sarah and Ryan and
+Danielle.
+Michael is Jessica is Matthew is Ashley is Christopher is Amanda is
+Nicholas is Samantha is Daniel is Stephanie is Joseph is Nicole is
+John is Jennifer is Ryan is Christina is Anthony is Brittany is Andrew
+is Melissa is talking nonsense.

Added: trunk/java/dasher/applet/test.htm
==============================================================================
--- (empty file)
+++ trunk/java/dasher/applet/test.htm	Tue Oct 14 16:17:28 2008
@@ -0,0 +1 @@
+<html><applet code="dasher.applet.JDasherApplet.class" width="300" height="300"></applet></html>

Added: trunk/java/dasher/net/NetDashConnectionHandler.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/net/NetDashConnectionHandler.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,290 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher.net;
+
+import java.io.OutputStream;
+import java.util.ArrayList;
+
+import java.util.concurrent.locks.*;
+
+import dasher.CEditEvent;
+
+/**
+ * Wraps an instance of NetDasher and passes commands to it
+ * when asked to by a DasherCommandInterpreterThread.
+ */
+public class NetDashConnectionHandler implements DasherEditListener {
+
+	/**
+	 * Dasher we are wrapping
+	 */
+	private NetDasher Dasher;
+	
+	/**
+	 * Screen attached to this Dasher
+	 */
+	private NetScreen Screen;
+	
+	/**
+	 * System time when this Dasher was last accessed; used to
+	 * determine if this session is idle by NetDashGC
+	 */
+	private long lastUsed;
+	
+	/**
+	 * Session identifier associated with this instance
+	 */
+	private int sessID;
+	
+	/**
+	 * Flag indicating if this Dasher has been destroyed by the
+	 * GC thread.
+	 */
+	private boolean destroyed;
+	
+	/**
+	 * Lock which is set when a thread is operating on this
+	 * Dasher in some way.
+	 */
+	private Lock myLock;
+	
+	/**
+	 * Creates and wraps a new instance of NetDasher and
+	 * creates and registers our helper classes including a NetScreen
+	 * for output and a NetInput for input.
+	 * 
+	 * @param sessID Session identifer associated with this handler
+	 * @param width Screen width to draw for
+	 * @param height Screen height to draw for
+	 * @param dataLocation Where to look for alphabet and colour XML files
+	 * @param alphIO AlphIO object holding alphabet data 
+	 * @param colIO ColourIO object holding colour data
+	 */	
+	public NetDashConnectionHandler(int sessID, int width, int height, String dataLocation, dasher.CAlphIO alphIO, dasher.CColourIO colIO) {
+				
+		myLock = new ReentrantLock();
+		
+		Dasher = new NetDasher(this, alphIO, colIO);
+		
+		Screen = new NetScreen(sessID, width, height);
+		
+		this.sessID = sessID;
+		
+		if(dataLocation != null) Dasher.setUserLoc(dataLocation);
+		
+		Dasher.Realize();
+		
+		Dasher.SetStringParameter(dasher.Esp_parameters.SP_INPUT_FILTER, "Click Mode");
+		Dasher.SetStringParameter(dasher.Esp_parameters.SP_INPUT_DEVICE, "Network Input");
+		Dasher.SetBoolParameter(dasher.Ebp_parameters.BP_DRAW_MOUSE_LINE, false);
+		Dasher.SetBoolParameter(dasher.Ebp_parameters.BP_DRAW_MOUSE, false);
+		Dasher.SetLongParameter(dasher.Elp_parameters.LP_ZOOMSTEPS, 1);
+		
+		Screen.setInitialAlph(Dasher.GetStringParameter(dasher.Esp_parameters.SP_ALPHABET_ID));
+		Screen.setInitialCS(Dasher.GetStringParameter(dasher.Esp_parameters.SP_COLOUR_ID));
+		
+		ArrayList<String> alphs = new ArrayList<String>();
+		
+		Dasher.GetAlphabets(alphs);
+		Screen.setAlphabets(alphs);
+		
+		ArrayList<String> cols = new ArrayList<String>();
+		
+		Dasher.GetColours(cols);
+		Screen.setColours(cols);
+		
+		Dasher.ChangeScreen(Screen);
+		
+	}
+	
+	/**
+	 * Reports a mouse click to our hosted Dasher; this should
+	 * be called by the command interpreter when the client sends
+	 * a document reporting a click.
+	 * <p>
+	 * Internally we pass the co-ordinates on using NetDasher's
+	 * setCoordinates method, call KeyDown to report a click, set
+	 * the Screen's OutputStream, and finally calls NewFrame so that
+	 * a frame is drawn to NetScreen and passes out through the
+	 * given OutputStream.
+	 * <p>
+	 * Finally, our internal lastUsed field is updated to note
+	 * the time when the user last interacted with this session.
+	 * 
+	 * @param x Mouse x co-ordinate
+	 * @param y Mouse y co-ordinate
+	 * @param output Stream to which drawn XML will be output
+	 */
+	public void Clicked(int x, int y, OutputStream output) {		
+		
+		Dasher.setCoordinates(x, y);		
+		Dasher.KeyDown(0, 100);
+
+		Screen.setOutput(output);
+				
+		Dasher.NewFrame(0);
+		
+		lastUsed = System.currentTimeMillis();
+
+	}
+	
+	/**
+	 * Forces Dasher to draw a frame to a given output stream
+	 * immediately.
+	 * <p>
+	 * There is no need to call this when reporting a mouse-click
+	 * as a frame will automatically be drawn as part of the process.
+	 * <p>
+	 * Finally, our internal lastUsed field is updated to note
+	 * the time when the user last interacted with this session.
+	 * 
+	 * @param output OutputStream to which we should output XML
+	 */
+	public void Draw(OutputStream output) {
+		
+		Screen.setOutput(output);
+		
+		Dasher.Draw(true);
+		
+		lastUsed = System.currentTimeMillis();
+		
+	}
+	
+	/**
+	 * Called by the wrapped NetDasher instance to report an EditEvent
+	 * because the user has entered or left a node.
+	 * <p>
+	 * This method just passes it on to the Screen to incorporate
+	 * into the next frame -- given the timing of EditEvents during
+	 * the drawing cycle, this will almost certainly be the same as the
+	 * frame emitted in response to the user interaction which spawned
+	 * the edit event in the first place, producing the illusion
+	 * of almost-instantaneous response.
+	 * 
+	 * @param event Event being reported
+	 */
+	public void HandleEvent(CEditEvent event) {
+	
+		Screen.addEditEvent(event);
+		
+	}
+
+	/**
+	 * Uses the lastUsed timestamp held internally to determine
+	 * whether this session has been idle for 5 minutes or more.
+	 * 
+	 * @return True if idle
+	 */
+	public boolean isIdle() {
+		
+		return (System.currentTimeMillis() - lastUsed > 30000); // 5 minute timeout
+
+	}
+	
+	/**
+	 * Reports whether this session has in fact been destroyed
+	 * by the garbage collector thread; this is to guard against
+	 * situations where a reference to a collected
+	 * object has somehow been held.
+	 * <p>
+	 * Any class which finds itself holding a destroyed reference
+	 * should behave as if it failed to get the reference in the
+	 * first place; typically it indicates a session expired whilst
+	 * a thread was waiting on a lock. 
+	 * 
+	 * @return True if destroyed
+	 */
+	public boolean isDestroyed() {
+		return destroyed;
+	}
+	
+	/**
+	 * Invoked by the garbage collector thread to destory the
+	 * Interface of our wrapped NetDasher, freeing the vast majority
+	 * of memory used.
+	 * <p>
+	 * After destroying an instance, all references to it should
+	 * be nulled to permit the Java garbage collector to reclaim
+	 * this wrapper.
+	 *
+	 */
+	public void destroy() {
+		destroyed = true;
+		Dasher.DestroyInterface();
+	}
+	
+	/**
+	 * Gets the session ID associated with this instance
+	 * 
+	 * @return SessID
+	 */
+	public int getSessID() {
+		return this.sessID;
+	}
+	
+	/**
+	 * Retrieves a reference to the Lock used to prevent concurrent
+	 * modification of this instance of NetDasher.
+	 * 
+	 * @return myLock
+	 */
+	public Lock getLock() {
+		return myLock;
+	}
+	
+	/**
+	 * Changes the alphabet used by our wrapped Dasher.
+	 * <p>
+	 * This does not cause drawing automatically; Draw should
+	 * be called afterwards if this is desired.
+	 * 
+	 * @param alph Name of new alphabet
+	 */
+	public void changeAlphabet(String alph) {
+		
+		System.out.printf("Session #%d: retraining for alphabet '%s'%n", sessID, alph);
+		
+		Dasher.SetStringParameter(dasher.Esp_parameters.SP_ALPHABET_ID, alph);
+		
+		lastUsed = System.currentTimeMillis();
+	}
+	
+	/**
+	 * Changes the colour scheme used by our wrapped Dasher.
+	 * <p>
+	 * This does not cause drawing automatically; Draw should
+	 * be called afterwards if this is desired.
+	 * 
+	 * @param col Name of new colour scheme
+	 */
+	public void changeColours(String col) {
+				
+		Dasher.SetStringParameter(dasher.Esp_parameters.SP_COLOUR_ID, col);
+		
+		lastUsed = System.currentTimeMillis();
+	}
+
+}

Added: trunk/java/dasher/net/NetDashGC.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/net/NetDashGC.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,87 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher.net;
+
+/**
+ * This task is scheduled to run every 60 seconds to identify and
+ * terminate idle NetDasher sessions.
+ * <p>
+ * The scheduling is set up by NetDasherListener.
+ * <p>
+ * Each time the thread is run, the following is checked against
+ * each Dasher in the Map supplied by NetDasherListener.
+ * <p>
+ * <ol><li>First, the Dasher in question is locked.
+ * <li>Next we check if it is both idle and has not already
+ * been destroyed.
+ * <li>If it fulfils both these conditions, its destroy() method.
+ * The NetDashConnectionHandler should free as much of Dasher
+ * as possible at this point.
+ * <li>NetDashConnectionHandlers which have been destroyed are removed
+ * from the Map, such that they can be garbage collected.
+ * <li>Finally, the lock is released.</ol>
+ */
+public class NetDashGC extends java.util.TimerTask {
+
+	/**
+	 * Map which will be checked for idle Dashers when this thread is run
+	 */
+	protected java.util.concurrent.ConcurrentHashMap<Integer, NetDashConnectionHandler> Dashers;
+	
+	/**
+	 * Creates a new GC thread attached to a given Map of Dashers.
+	 * 
+	 * @param Dashs Map to check for idle Dashers when run
+	 */
+	public NetDashGC(java.util.concurrent.ConcurrentHashMap<Integer, NetDashConnectionHandler> Dashs) {
+		Dashers = Dashs;
+	}
+	
+	/**
+	 * Checks for idle dashers; see the class summary for details.
+	 */
+	public void run() {
+		
+		for(NetDashConnectionHandler dash : Dashers.values()) {
+
+			dash.getLock().lock();
+			
+			if(dash.isIdle() && !dash.isDestroyed()) {
+				int nowFree = dash.getSessID();
+
+				System.out.printf("Session #%d idle; destroying Dasher%n", nowFree);
+
+				dash.destroy();
+				
+				Dashers.remove(dash.getSessID(), dash);
+
+			}
+			
+			dash.getLock().unlock();
+		}
+	}
+	
+}

Added: trunk/java/dasher/net/NetDasher.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/net/NetDasher.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,243 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher.net;
+
+import java.util.Collection;
+import java.util.ArrayList;
+
+import java.io.File;
+import java.io.FileFilter;
+
+import dasher.CAlphIO;
+import dasher.CColourIO;
+
+/**
+ * Implementation of DasherInterfaceBase designed for use as part
+ * of a server supplying a remote interface to Dasher, typically
+ * by a web front-end.
+ * <p>
+ * For specification details of the front end, see the information
+ * relating to JSDasher at www.smowton.net/chris (found under Dasher Project).
+ * <p>
+ * As this implementation of Dasher is designed to be instantiated
+ * once for each connection, it includes hooks for some repetitive
+ * work to be externalised; specifically, it expects both a CAlphIO
+ * and CColourIO to have been ready-constructed by its host.
+ */
+public class NetDasher extends dasher.CDasherInterfaceBase {
+	
+	/**
+	 * Reference to the NetInput device which is feeding Dasher
+	 * co-ordinates.
+	 */
+	protected NetInput m_CoordInput;
+	
+	/**
+	 * Reference to our host
+	 */
+	protected DasherEditListener m_Host;
+	
+	/**
+	 * User data location; this is where Dasher should look
+	 * for training texts.
+	 */
+	protected String userDataLocation;
+	
+	/**
+	 * Reference to the AlphIO object handed in by the host
+	 */
+	protected dasher.CAlphIO m_alphIO;
+	
+	/**
+	 * Reference to the ColourIO object handed in by the host
+	 */
+	protected dasher.CColourIO m_ColourIO;
+	
+	/**
+	 * Creates a new NetDasher which passes events out to a given
+	 * host, and which gets its alphabets and colour schemes from
+	 * given sources.
+	 * <p>
+	 * This constructor will call CreateSettingsStore and register
+	 * an instance of NetInput as our input device; however Realize
+	 * still has to be called before it is ready to be used.
+	 * <p>
+	 * See the superclass documentation for more detail on the
+	 * Interface's role.
+	 * 
+	 * @param host Host to whom we should pass EditEvents
+	 * @param alphIO AlphIO object to read alphabets from
+	 * @param colIO ColourIO object to read colour schemes from
+	 */
+	public NetDasher(DasherEditListener host, dasher.CAlphIO alphIO, dasher.CColourIO colIO) {
+		super();
+		
+		m_alphIO = alphIO;
+		m_ColourIO = colIO;
+		m_Host = host;
+		CreateSettingsStore();
+		m_CoordInput = new NetInput(m_EventHandler, m_SettingsStore);
+		RegisterFactory(new dasher.CWrapperFactory(m_EventHandler, m_SettingsStore, m_CoordInput));
+		CreateInput();
+	}
+
+	/**
+	 * Informs the helper NetInput class that when next asked,
+	 * it should supply these co-ordinates.
+	 * 
+	 * @param x Mouse x co-ordinate
+	 * @param y Mouse y co-ordinate
+	 */
+	public void setCoordinates(int x, int y) {
+		m_CoordInput.setNextCoords(x, y);
+	}
+	
+	public void CreateSettingsStore() {
+		
+		m_SettingsStore = new dasher.CSettingsStore(m_EventHandler);
+		
+	}
+	
+	/**
+	 * Supplies the AlphIO object which was supplied to our
+	 * constructor as a source of alphabet information.
+	 */
+	public CAlphIO doAlphIO(ArrayList<String> vFiles) {
+		return m_alphIO;
+	}
+
+	/**
+	 * Supplies the ColourIO object which was supplied to our
+	 * constructor as a source of colour scheme information.
+	 */
+	public CColourIO doColourIO(ArrayList<String> vFiles) {
+		return m_ColourIO;
+	}
+
+	public void ExternalEventHandler(dasher.CEvent event) {
+		
+		if(event.m_iEventType == 2) { // Edit event
+			if(m_Host != null) {
+				m_Host.HandleEvent((dasher.CEditEvent)event);
+			}
+		}
+		
+	}
+	
+	public int GetFileSize(String strFileName) {
+		java.io.File theFile = new java.io.File(strFileName);
+		return (int)theFile.length();
+	}
+
+	
+	public void Redraw(boolean bChanged) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	/**
+	 * Stub; not required in this version of Dasher since our
+	 * host is responsible for constructing a CAlphIO
+	 */
+	public void ScanAlphabetFiles(Collection<String> vFileList) {
+
+		// Stub: shouldn't get used in this version of Dasher.
+		
+	}
+
+	/**
+	 * Stub; not required in this version of Dasher since our
+	 * host is responsible for constructing a CColourIO
+	 */
+	public void ScanColourFiles(Collection<String> vFileList) {
+
+		// Stub: shouldn't get used in this version of Dasher.
+		
+	}
+
+	public void SetupPaths() {
+
+		SetStringParameter(dasher.Esp_parameters.SP_USER_LOC, userDataLocation);
+		
+	}
+	
+	/**
+	 * Sets the location where Dasher should search for training
+	 * texts.
+	 * 
+	 * @param loc New data location
+	 */
+	public void setUserLoc(String loc) {
+		userDataLocation = loc;
+	}
+
+	
+	public void SetupUI() {
+		// TODO Auto-generated method stub
+		
+	}
+}
+
+/**
+ * Simple factory for the production of FileFilters which return
+ * files whose names match a given regular expression.
+ */
+class FilterFactory {
+	
+	/**
+	 * Produces a new FileFilter which accepts
+	 * files whose names match a given regular expression.
+	 * 
+	 * @param regex Regular expression to match
+	 * @return FileFilter class which filters for this regex.
+	 */
+	public static FileFilter makeFilter(String regex) {
+		
+		final String target = regex;
+		
+		return new java.io.FileFilter() {
+			public boolean accept (File file) {
+				return file.getName().matches(target);
+			}
+		};
+	}
+	
+}
+
+/**
+ * Interface to be implemented by any class wanting to play
+ * host to NetDashers and be notified of edit events.
+ */
+interface DasherEditListener {
+	
+	/**
+	 * Called by NetDasher whenever an EditEvent is raised.
+	 * 
+	 * @param event Event being raised
+	 */
+	public void HandleEvent(dasher.CEditEvent event);
+	
+}

Added: trunk/java/dasher/net/NetDasherCommandInterpreterThread.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/net/NetDasherCommandInterpreterThread.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,423 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher.net;
+
+import java.net.Socket;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.StringBuffer;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+/**
+ * This thread is spawned by NetDasherListener every time a connection
+ * is accepted.
+ * <p>
+ * The thread is passed references to most of NetDasherListener's
+ * internal data, and is responsible for interpreting the incoming
+ * request and using these resources to service it appropriately.
+ * <p>
+ * Output should also be organised such that the client has received
+ * a reply by the time this thread ends.
+ * <p>
+ * The input will arrive in XML format; output too should be written
+ * as XML.
+ * <p>
+ * <b>Input XML</b>
+ * <p>
+ * The general format of XML which is expected is:
+ * <p>
+ * &lt;command type="message_type">%lt;attribute_1>value%lt;/attribute_1>&lt;attribute_2>value&lt;/attribute_2>...&lt;/command>
+ * <p>
+ * Where message_type can be any of:
+ * <p>
+ * <b>init</b> -- Starts a new session. Required attributes are 
+ * <i>width</i> (Client's screen width in pixels) and <i>height</i> 
+ * (Client's screen height in pixels).
+ * <p>
+ * <b>click</b> -- Reports a user mouse click at a given location.
+ * Required parameters are <i>x</i> (mouse x co-ordinate) and <i>y</i>
+ * (mouse y co-ordinate).
+ * <p>
+ * <b>changealphabet</b> -- Changes the alphabet currently in use.
+ * Required parameter: <i>name</i> (Name of new alphabet)
+ * <p>
+ * <b>changecolours</b> -- Changes the colour scheme currently in use.
+ * Required parameter: <i>name</i> (Name of new colour scheme)
+ * <p>
+ * <b>Output XML</b>
+ * <p>
+ * This class is responsible for producing XML reporting
+ * errors in parsing input XML.
+ * <p>
+ * For a description of ordinary output returned when the input
+ * XML was successfully parsed, see the documentation for NetScreen.
+ */
+public class NetDasherCommandInterpreterThread extends Thread {
+
+	/**
+	 * idWrapper class to obtain free session IDs.
+	 */
+	protected idWrapper freeID;
+	
+	/**
+	 * Map indexing the available NetDasherConnectionHandlers by their associated
+	 * session identifiers. 
+	 */
+	protected java.util.concurrent.ConcurrentHashMap<Integer, NetDashConnectionHandler> Dashers;
+	
+	/**
+	 * Socket on which the incoming request arrived, and to which
+	 * output should eventually be delivered.
+	 */
+	protected Socket DasherConnection;
+	
+	/**
+	 * DocumentBuilderFactory to be used in the course of all
+	 * XML parsing.
+	 */
+	protected DocumentBuilderFactory db;
+	
+	/**
+	 * Data location any created Dasher should use to locate
+	 * training text.
+	 */
+	protected String dataLocation;
+	
+	/**
+	 * AlphIO instance to be supplied to any Dashers created
+	 */
+	protected dasher.CAlphIO alphIO;
+	
+	/**
+	 * ColourIO instance to be supplied to any Dashers created
+	 */
+	protected dasher.CColourIO colourIO;
+		
+	/**
+	 * Creates a new command interpreter and passes in working 
+	 * data. Given these, the thread is ready to begin interpreting
+	 * and servicing the command given on the supplied socket.
+	 * <p>
+	 * The actual interpreting will take place when the thread's
+	 * start() method is called.  
+	 * 
+	 * @param Connection Socket from which the command should be read
+	 * 		  and to which the answer should be written.
+	 * @param dashs Map indexing Dashers by their session ID
+	 * @param freeIDs Class capable of reliably supplying unique
+	 * 	      free session identifiers. Must be thread-safe.
+	 * @param docbuild DocumentBuilderFactory to use for XML reading and writing
+	 * @param dataloc Data location where Dashers can find training text
+	 * @param alphIO AlphIO object describing available alphabets
+	 * @param colourIO ColourIO object describing available colour schemes
+	 */
+	public NetDasherCommandInterpreterThread(Socket Connection, java.util.concurrent.ConcurrentHashMap<Integer, NetDashConnectionHandler> dashs, idWrapper freeIDs, DocumentBuilderFactory docbuild, String dataloc, dasher.CAlphIO alphIO, dasher.CColourIO colourIO) {
+		
+		this.DasherConnection = Connection;
+		this.Dashers = dashs;
+		this.db = docbuild;
+		this.dataLocation = dataloc;
+		
+		this.alphIO = alphIO;
+		this.colourIO = colourIO;
+		
+		this.freeID = freeIDs;
+			
+	}
+	
+	/**
+	 * Starts the thread. See the class summary for a description
+	 * of the input the class accepts, and the output produced.
+	 */
+	public void run() {
+	
+		InputStream DasherInput;
+		
+		try {
+			DasherInput = DasherConnection.getInputStream();
+		}
+		catch(IOException e) {
+			System.out.printf("Could not retrieve connection stream: %s%n", e);
+			try {
+				DasherConnection.close();
+			}
+			catch(IOException ex) {
+				// Do nothing; clearly it wasn't ever properly established.
+			}
+			return; // Try the next connection!
+		}
+		
+		java.io.OutputStream output;
+		try {
+			output = DasherConnection.getOutputStream();
+		}
+		catch(IOException e) {
+			System.out.printf("Couldn't get an output stream: %s%n", e);
+			try {
+				DasherConnection.close();
+			}
+			catch(IOException ex) {
+				// Do nothing; clearly it wasn't ever properly established.
+			}
+			return; // Try the next connection!
+		}
+
+		java.io.InputStreamReader xmlreader;
+		
+		try {
+			xmlreader = new java.io.InputStreamReader(DasherInput, "utf-8"); 
+		}
+		catch(Exception e) {
+			System.out.printf("Error decoding UTF-8 input: %s%n", e);
+			return;
+		}
+		
+		StringBuffer inputBuffer = new StringBuffer();
+		// Max command size: 1KB. This may be changed in the future.
+		try {
+		while(!inputBuffer.toString().endsWith("</command>")) {
+			inputBuffer.append((char)xmlreader.read());
+		}
+		}
+		
+		catch(IOException e) {
+			System.out.printf("Error whilst reading XML: %s%n", e);
+		}
+		
+		Document dasherCommandDoc;
+		
+		try {
+		
+			dasherCommandDoc = db.newDocumentBuilder().parse(new org.xml.sax.InputSource(new java.io.StringReader(inputBuffer.toString())));
+		
+		}
+		
+		catch(Exception e) {
+			System.out.printf("Error parsing input XML: %s%n", e);
+			
+			try {
+				DasherConnection.close();
+			}
+			catch(IOException ex) {
+				// Do nothing
+			}
+			
+			return;
+		}
+		
+		Element dasherCommand = (Element)dasherCommandDoc.getElementsByTagName("command").item(0);
+								
+		try {
+			DasherConnection.shutdownInput();
+		}
+		catch(IOException e) {
+			System.out.printf("Failed terminating socket input: %s%n", e);
+			try {
+				DasherConnection.close();
+			}
+			catch(IOException ex) {
+				// Do nothing; clearly it wasn't ever properly established.
+			}
+			return; // Try the next connection!
+		}
+
+
+		try {
+			if(dasherCommand.getAttribute("type").equals("init")) {
+
+				// New session request
+				int newSessionID = getFreeID();
+				Dashers.put(newSessionID, new NetDashConnectionHandler(newSessionID, Integer.parseInt(dasherCommand.getElementsByTagName("width").item(0).getChildNodes().item(0).getNodeValue()), Integer.parseInt(dasherCommand.getElementsByTagName("height").item(0).getChildNodes().item(0).getNodeValue()), dataLocation, alphIO, colourIO));
+				Dashers.get(newSessionID).Clicked(0, 0, output);
+				
+				System.out.printf("New session created for %s, session ID %d.%n", DasherConnection.getInetAddress().getHostAddress(), newSessionID);
+
+			}
+			else {
+
+				int sessID = Integer.parseInt(dasherCommand.getElementsByTagName("sessid").item(0).getChildNodes().item(0).getNodeValue());
+
+				NetDashConnectionHandler referencedDasher = Dashers.get(sessID);
+				
+				if(referencedDasher == null) throw new NoSuchSessionException();
+
+				referencedDasher.getLock().lock();
+
+				if(referencedDasher.isDestroyed()) {
+					throw new NoSuchSessionException();
+				}
+				
+				if(dasherCommand.getAttribute("type").equals("click")) {
+
+					referencedDasher.Clicked(Integer.parseInt(dasherCommand.getElementsByTagName("x").item(0).getChildNodes().item(0).getNodeValue()), Integer.parseInt(dasherCommand.getElementsByTagName("y").item(0).getChildNodes().item(0).getNodeValue()), output);
+
+				}
+				else if(dasherCommand.getAttribute("type").equals("changealphabet")) {
+					
+					referencedDasher.changeAlphabet(dasherCommand.getElementsByTagName("name").item(0).getChildNodes().item(0).getNodeValue());
+					referencedDasher.Draw(output);
+					
+				}
+
+				else if(dasherCommand.getAttribute("type").equals("changecolours")) {
+					
+					referencedDasher.changeColours(dasherCommand.getElementsByTagName("name").item(0).getChildNodes().item(0).getNodeValue());
+					referencedDasher.Draw(output);
+					
+				}
+
+				referencedDasher.getLock().unlock();
+			}
+		}
+		catch(NoSuchSessionException e) {
+			System.out.printf("Invalid session ID specified or incorrect number of parameters: %s%n", e);
+			try {
+				// TODO: Return an error document here.
+				writeError("Your session has expired. Please refresh the page to begin a new session.", output);
+				
+				DasherConnection.close();
+			}
+			catch(IOException ex) {
+			}
+			return; // Try the next connection!
+		}
+		
+		try {
+			DasherConnection.close();
+		}
+		catch(IOException e) {
+			System.out.printf("Couldn't close a connection: %s%n", e);
+			
+			return; // Try the next connection!
+		}
+	}
+	
+	/**
+	 * Uses freeID to produce a free ID
+	 * 
+	 * @return Free (unique) session identifier.
+	 */
+	protected int getFreeID() {
+		
+		return freeID.getFreeID();
+		
+	}
+	
+	/**
+	 * Produces an XML document describing a given error and
+	 * serializes the document to a given OutputStream, typically
+	 * a network socket.
+	 * <p>
+	 * This method is for reporting errors encountered whilst
+	 * trying to parse the client's request document; errors
+	 * arising in Dasher itself should be dealt with by other means. 
+	 * 
+	 * @param errorString String to report to the user
+	 * @param m_Output OutputStream to which XML should be serialized
+	 */
+	protected void writeError(String errorString, OutputStream m_Output) {
+		// Create instance of DocumentBuilderFactory
+		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+		// Get the DocumentBuilder
+		DocumentBuilder parser;
+		
+		try {
+			parser = factory.newDocumentBuilder();
+		}
+		catch(ParserConfigurationException e) {
+			System.out.printf("Can't create XML error document: %s%n", e);
+			return;
+		}
+		// Create blank DOM Document
+		Document errorMessage = parser.newDocument();
+		
+		Element messageRoot = errorMessage.createElement("message");
+		errorMessage.appendChild(messageRoot);
+		
+		Element error = errorMessage.createElement("error");
+		messageRoot.appendChild(error);
+		
+		Text theMessage = errorMessage.createTextNode(errorString);
+		error.appendChild(theMessage);
+		
+		TransformerFactory tranFactory = TransformerFactory.newInstance();
+		Transformer aTransformer;
+		try {
+			aTransformer = tranFactory.newTransformer();
+		}
+		catch(TransformerConfigurationException e) {
+			System.out.printf("Failed to create XML transformer: %s%n", e);
+			return;
+		}
+
+		Source src = new DOMSource(errorMessage);
+		Result dest = new StreamResult(m_Output);
+		try {
+			aTransformer.transform(src, dest);
+		}
+		catch(TransformerException e) {
+			System.out.printf("Failed to output XML: %s%n", e);
+			return;
+		}
+		
+		try {
+			m_Output.flush();
+		}
+		catch(java.io.IOException e) {
+			System.out.printf("Failed to flush output: %s%n", e);
+		}
+
+		
+	}
+
+	
+}
+
+/**
+ * Exception indicating that a NetDasherCommandInterpreterThread
+ * found its request to reference a session ID which either does
+ * not exist or has been destroyed.
+ */
+class NoSuchSessionException extends Exception {
+
+	public static final long serialVersionUID = 0;
+	
+}
\ No newline at end of file

Added: trunk/java/dasher/net/NetDasherListener.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/net/NetDasherListener.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,237 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher.net;
+
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+import java.util.ArrayList;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+
+/**
+ * Main class powering NetDasher. This class listens for connections and,
+ * whenever one is received, spawns a NetDasherCommandInterpreterThread to
+ * determine what the client wants, and action their request.
+ * <p>
+ * Alphabet and Colour XML files are also read on startup to produce
+ * central AlphIO and ColourIO objects, which are passed in to
+ * every created Dasher; this way we avoid the tedious work of
+ * repeatedly parsing the same data for each instance of Dasher we create.
+ * <p>
+ * Essentially the goal is to create an instance of Dasher, attached to
+ * a NetScreen, for each client, and to pass the user's clicks and other
+ * requests to the appropriate instance of Dasher as connections come in.
+ * <p>
+ * Since connections are conducted by HTTP for most clients and forwarded
+ * by a simple PHP script, there are no persistent connections -- there is
+ * only one connection per request and vice versa.
+ */
+public class NetDasherListener {
+
+	/**
+	 * HashMap of session identifiers to instances of Dasher, passed to
+	 * each CommandInterpreterThread. 
+	 */
+	private static java.util.concurrent.ConcurrentHashMap<Integer, NetDashConnectionHandler> Dashers;
+	
+	/**
+	 * Location to look for alphabet and colour XML files, as well
+	 * as training texts.
+	 */
+	private static String dataLocation;
+	
+	/**
+	 * DOM parser factory for XML.
+	 */
+	private static DocumentBuilderFactory dbf;
+	
+	/**
+	 * Timer which runs a NetDashGC thread every 60 seconds
+	 */
+	private static Timer GCScheduler;
+	
+	/**
+	 * Next free session identifier
+	 */
+	private static idWrapper nextID;
+	
+	
+	public static void ScanAlphabetFiles(ArrayList<String> vFileList) {
+		
+		ScanFilesByRegex(vFileList, "alphabet.*.xml");
+		
+	}
+
+	
+	public static void ScanColourFiles(ArrayList<String> vFileList) {
+		
+		ScanFilesByRegex(vFileList, "colour.*.xml");
+		
+	}
+	
+	/**
+	 * Delegate method used by both ScanAlphabetFiles and ScanColourFiles.
+	 * <p>
+	 * Fills its first parameter with all files in our systemLocation
+	 * which match the given regex.
+	 * 
+	 * @param vFileList List to fill with matching files
+	 * @param regex Regular expression determining what to add
+	 */
+	public static void ScanFilesByRegex(ArrayList<String> vFileList, String regex) {
+		
+		FileFilter alphFilter = FilterFactory.makeFilter(regex);
+		
+		try {
+			File sysDir = new File(dataLocation);
+			File[] sysFiles = sysDir.listFiles(alphFilter);
+			
+			if(sysFiles != null) {
+				for(File f : sysFiles) {
+					vFileList.add(f.getName());
+				}
+			}
+		}
+		catch(Exception e) {
+			// Do nothing
+		}
+		
+		/*try {
+			File usrDir = new File(GetStringParameter(dasher.Esp_parameters.SP_USER_LOC));
+			File[] usrFiles = usrDir.listFiles(alphFilter);
+			
+			if(usrFiles != null) {
+				for(File f : usrFiles) {
+					vFileList.add(f.getName());
+				}
+			}
+		}
+		catch(Exception e) {
+			// Do nothing
+		}*/
+	}
+	
+	/**
+	 * Creates our listening socket, schedules the garbage collector
+	 * thread to run every 60 seconds, creates instances of
+	 * CAlphIO and CColourIO to read in the appropriate XML
+	 * data, and finally enters a tight loop of accepting connections
+	 * and spawning NetDasherCommandInterpreterThreads to deal with them. 
+	 * <p>
+	 * The first argument is taken as the data location where XML files
+	 * and training texts may be found.
+	 */
+	public static void main(String[] args) {
+		
+		ServerSocket DasherListen;
+		Dashers = new java.util.concurrent.ConcurrentHashMap<Integer, NetDashConnectionHandler>();
+		
+		GCScheduler = new Timer();
+		nextID = new idWrapper();
+				
+		dbf = DocumentBuilderFactory.newInstance();
+		
+		for(int i = 0; i < args.length; i++) {
+			if(args[i].equals("-d")) {
+				if(i + 1 == args.length) {
+					break;
+				}
+				else {
+					dataLocation = args[i+1];
+					
+					if(dataLocation.charAt(dataLocation.length() - 1) != '/' && dataLocation.charAt(dataLocation.length() - 1) != '\\') {
+						dataLocation = dataLocation + "\\";
+					}
+				}
+			}
+		}
+		
+		System.out.printf("Pre-reading alphabet and colour-scheme XML files (data path: %s)%n", dataLocation);
+		
+		ArrayList<String> alphFiles = new ArrayList<String>();
+		ScanFilesByRegex(alphFiles, "alphabet.*.xml");		
+		dasher.CAlphIO centralAlphIO = new dasher.CAlphIO(dataLocation, "", alphFiles, null);
+		
+		ArrayList<String> colourFiles = new ArrayList<String>();
+		ScanFilesByRegex(colourFiles, "colour.*.xml");
+		dasher.CColourIO centralColourIO = new dasher.CColourIO(dataLocation, "", colourFiles, null);
+		
+		System.out.printf("Pre-reading completed.%n");
+		
+		TimerTask GCTask = new NetDashGC(Dashers); 
+		
+		GCScheduler.schedule(GCTask, 60000, 60000);
+		
+		try {
+			DasherListen = new ServerSocket(2112);
+		}
+		catch(IOException e) {
+			System.out.printf("Could not listen on port 2112: %s%n", e);
+			return;
+		}
+			
+		System.out.printf("Listening on port 2112.%n");
+		
+		while(true) {
+			
+			Socket DasherConnection;
+			
+			try {
+				DasherConnection = DasherListen.accept();
+				DasherConnection.setSoLinger(true, 1);
+			}
+			catch(IOException e) {
+				System.out.printf("Could not accept a connection: %s%n", e);
+				continue; // No connection to hang up; let's try again.
+			}
+			
+			NetDasherCommandInterpreterThread newThread = new NetDasherCommandInterpreterThread(DasherConnection, Dashers, nextID, dbf, dataLocation, centralAlphIO, centralColourIO);
+			
+			newThread.start();
+		}
+	}
+}
+
+/**
+ * Responsible for supplying free IDs to use as session IDs.
+ * <p>
+ * At present, simply returns a linear sequence and does not
+ * re-use abandoned session IDs.
+ */
+class idWrapper {
+	int nextID = 0;
+	
+	public int getFreeID() {
+		return nextID++;
+	}
+}

Added: trunk/java/dasher/net/NetInput.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/net/NetInput.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,104 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher.net;
+
+/**
+ * Dummy implementation of CDasherInput which provides input by
+ * virtue of accepting co-ordinates from some external source
+ * and reporting them when next GetCoordinates is called.
+ * <p>
+ * This is used by NetDasher to relay mouse co-ordinates extracted
+ * from an XML document by another class. 
+ */
+public class NetInput extends dasher.CDasherInput {
+
+	/**
+	 * Cache of the most recently specified co-ordinates
+	 * which will be returned next time GetCoordinates is called.
+	 */
+	private long[] nextCoords;
+	
+	/**
+	 * Flag indicating whether new co-ordinates have been supplied
+	 * since the last call to GetCoordinates.
+	 */
+	private boolean coordsAvailable;
+	
+	/**
+	 * Creates a new input device; calls our super-constructor
+	 * with an ID of 12 and a type of 1.
+	 * 
+	 * @param events EventHandler with which to mention ourselves
+	 * @param sets Settings repository to use 
+	 */
+	public NetInput(dasher.CEventHandler events, dasher.CSettingsStore sets) {
+		super(events, sets, 12, 1, "Network Input");
+		nextCoords = new long[2];
+	}
+
+	public int GetCoordinateCount() {
+		return 2;
+	}
+
+	/**
+	 * Returns the last co-ordinates supplied by setNextCoords
+	 * if coordsAvailable is true, or (0,0) otherwise.
+	 * <p>
+	 * Also sets coordsAvailable to false.
+	 * 
+	 * @return 0, since these are always screen co-ordinates.
+	 */
+	public int GetCoordinates(int iN, long[] Coordinates) {
+		
+		if(coordsAvailable) {
+			Coordinates[0] = nextCoords[0];
+			Coordinates[1] = nextCoords[1];
+			
+			coordsAvailable = false;
+		}
+		else {
+			Coordinates[0] = Coordinates[1] = 0;
+		}
+		
+		return 0;
+	}
+	
+	/**
+	 * Sets the next co-ordinates to be reported by GetCoordinates
+	 * 
+	 * @param x X co-ordinate to return
+	 * @param y Y co-ordinate to return
+	 */
+	public void setNextCoords(long x, long y) {
+		nextCoords[0] = x;
+		nextCoords[1] = y;
+		
+		coordsAvailable = true;
+	}
+
+	
+	
+}

Added: trunk/java/dasher/net/NetScreen.java
==============================================================================
--- (empty file)
+++ trunk/java/dasher/net/NetScreen.java	Tue Oct 14 16:17:28 2008
@@ -0,0 +1,607 @@
+/*
+  This file is part of JDasher.
+
+  JDasher is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  JDasher is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with JDasher; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  Copyright (C) 2006      Christopher Smowton <cs448 cam ac uk>
+
+  JDasher is a port derived from the Dasher project; for information on
+  the project see www.dasher.org.uk; for information on JDasher itself
+  and related projects see www.smowton.net/chris
+
+*/
+
+package dasher.net;
+
+import java.util.ArrayList;
+
+import dasher.CCustomColours;
+import dasher.CDasherView;
+import dasher.EColorSchemes;
+
+import java.awt.Color;
+
+import org.w3c.dom.*;
+import javax.xml.transform.*;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import java.util.Queue;
+import java.util.LinkedList;
+
+/**
+ * Specialised implementation of CDasherScreen which, instead of
+ * drawing its output to the screen, produces an XML document
+ * describing drawing primitives.
+ * <p>
+ * The XML is then serialized and output to a specified
+ * OutputStream (in the context of NetDasher typically a Socket's
+ * OutputStream) with the intent that some client application
+ * should render the drawing primitives described by the document
+ * and so reproduce the display.
+ * <p>
+ * The class also currently plays the role of injecting XML tags
+ * informing the client of EditEvents and of delivering some
+ * extra data in the first frame sent to a given client. 
+ * In the future, these roles should ideally be moved into a 
+ * seperate class such that the different classes which want 
+ * to deliver XML to the client could each create an Element, 
+ * and combination and serialization could be co-ordinated by 
+ * some master NetDasherOutput class.
+ * <p>
+ * <b>XML format</b>
+ * <p>The entire document is always surrounded by <pre><message>...</message></pre>
+ * tags.
+ * <p>
+ * <b>init</b>: Sent only with the first produced frame, to notify
+ * the client of initial conditions. Contains the following children:
+ * <p><i>sessid</i>: Contains the session ID associated with
+ * this newly created Dasher.
+ * <p><i>alphabet</i>: An &lt;alphabet/> tag is included
+ * for each alphabet Dasher knows about. The title of each is
+ * described in the tag's name attribute, and the default attribute
+ * will be 'true' for one alphabet, indicating that which Dasher
+ * is using by default. Example: %lt;alphabet name="French" default="true"/>
+ * <p><i>colour</i>: A &lt;colour/> tag is included
+ * for each colour scheme Dasher knows about. The title of each is
+ * described in the tag's name attribute, and the default attribute
+ * will be 'true' for one alphabet, indicating that which Dasher
+ * is using by default. Example: &lt;colour name="Rainbow" default="true"/>
+ * <p>
+ * <b>edit</b>: Records every EditEvent which has been received
+ * by this Screen since the last frame.
+ * <p>
+ * The children of edit are of the form:
+ * <p>
+ * <i>add</i>: Add tags surround text added since the last frame;
+ * the tags are recorded in the XML document in the same order
+ * as the events occured. Example: &lt;add>H&lt;/add>
+ * <p>
+ * <i>remove</i>: Have a single attribute named 'num' which indicates
+ * how many characters have been deleted.
+ * Example: &lt;remove num="3"/>
+ * <p>
+ * <b>frame</b>: Frame tags contain a sequence of tags describing
+ * drawing primitives. The tags which may occur here are each
+ * described in the documentation for the function which may
+ * produce them, below.
+ */
+public class NetScreen implements dasher.CDasherScreen {
+
+	/**
+	 * Flag indicating whether to output an init section with
+	 * our next frame.
+	 */
+	protected boolean firstMessage = true;
+	
+	/**
+	 * Document object which should be populated with data to
+	 * be sent and which will in due time be serialized to our
+	 * OutputStream.
+	 */
+	protected Document drawInstructions;
+	
+	/**
+	 * Element from which all other elements descend; named
+	 * 'message' in the document schema.
+	 */
+	protected Element root;
+		
+	/**
+	 * Element to which all drawing primitives should be attached.
+	 */
+	protected Element frame;
+	
+	/**
+	 * Colour scheme currently in use
+	 */
+	protected dasher.CCustomColours m_ColourScheme;
+	
+	/**
+	 * OutputStream to which XML should be serialized at the end
+	 * of the drawing cycle.
+	 */
+	protected java.io.OutputStream m_Output;
+	
+	/**
+	 * Session ID associated with the Dasher to which this Screen
+	 * is linked.
+	 */
+	protected int sessID;
+	
+	/**
+	 * Queue of EditEvents registered since the last frame was drawn.
+	 */
+	protected Queue<dasher.CEditEvent> editEventQueue;
+	
+	/**
+	 * List of available alphabets
+	 */
+	protected ArrayList<String> Alphabets;
+	
+	/**
+	 * List of available colour schemes
+	 */
+	protected ArrayList<String> Colours;
+	
+	/**
+	 * Default colour scheme
+	 */	
+	protected String initialCS;
+	
+	/**
+	 * Default alphabet name
+	 */
+	protected String initialAlph;
+	
+	/**
+	 * DocumentBuilder to be used in producing XML
+	 */
+	protected DocumentBuilder parser;
+	
+	/**
+	 * Transformer which will render the XML document as text
+	 * prior to output.
+	 */	
+	protected Transformer XMLSerializer;
+	
+	/**
+	 * Width of this screen in pixels
+	 */
+	protected int m_Width;
+	
+	/**
+	 * Height of this screen in pixels
+	 */
+	protected int m_Height;
+	
+	/**
+	 * Creates a new NetScreen.
+	 * <p>
+	 * Sets up a DocumentBuilder and Transformer for the production
+	 * of XML and saves the height, width and session ID associated
+	 * with this screen.
+	 * 
+	 * @param sessID Session ID
+	 * @param width Screen width in pixels
+	 * @param height Screen height in pixels
+	 */
+	public NetScreen(int sessID, int width, int height) {
+		
+		this.sessID = sessID;
+		editEventQueue = new LinkedList<dasher.CEditEvent>();
+		m_Width = width; m_Height = height;
+		
+		// Create instance of DocumentBuilderFactory
+		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+		// Get the DocumentBuilder
+		try {
+			parser = factory.newDocumentBuilder();
+		}
+		catch(Exception e) {
+			System.out.printf("Couldn't create XML parser: %s%n", e);
+		}
+		
+		TransformerFactory tranFactory = TransformerFactory.newInstance();
+		try {
+			XMLSerializer = tranFactory.newTransformer();
+		}
+		catch(TransformerConfigurationException e) {
+			System.out.printf("Failed to create XML transformer: %s%n", e);
+			return;
+		}
+		
+		
+	}
+	
+	/**
+	 * Signals the start of a new frame; see CDasherScreen for
+	 * the general contract of this method.
+	 * <p>
+	 * In this specific case, a new Document is created and stored
+	 * in drawInstructions, and required Elements message and frame are
+	 * created and stored in root and frame respectively for use
+	 * by other means.
+	 * <p>
+	 * Finally, if the firstMessage flag is true, the &lt;init>
+	 * section is created as described above.
+	 */
+	public void Blank() {
+		
+		try {
+
+			// Create blank DOM Document
+			drawInstructions = parser.newDocument();
+			
+			root = drawInstructions.createElement("message");
+			drawInstructions.appendChild(root);
+			
+			if(firstMessage) {
+				Element init = drawInstructions.createElement("init");
+				
+				init.setAttribute("sessid", Integer.toString(sessID));
+				
+				root.appendChild(init);
+				
+				for(String alph : Alphabets) {
+					Element newAlph = drawInstructions.createElement("alphabet");
+					
+					newAlph.setAttribute("name", alph);
+					
+					if(alph.equals(initialAlph)) {
+						newAlph.setAttribute("default", "true");
+					}
+					
+					init.appendChild(newAlph);
+				}
+				
+				for(String col : Colours) {
+					Element newCol = drawInstructions.createElement("colour");
+					
+					newCol.setAttribute("name", col);
+					
+					if(col.equals(initialCS)) {
+						newCol.setAttribute("default", "true");
+					}
+					
+					init.appendChild(newCol);
+				}
+				
+				firstMessage = false;
+			}
+			
+			frame = drawInstructions.createElement("frame");
+			root.appendChild(frame);
+		}
+		catch(Exception e){
+			System.out.println(e.getMessage());
+		}
+		
+	}
+
+	/**
+	 * Calls addEditEvents before serializing the XML document
+	 * produced during the drawing cycle and writing it to m_Output,
+	 * (an OutputStream specified by the setOutput method).
+	 * <p>
+	 * For the general contract of this method, see CDasherScreen.
+	 */
+	public void Display() {
+
+		addEditEvents();		
+		
+		
+		Source src = new DOMSource(drawInstructions);
+		Result dest = new StreamResult(m_Output);
+		try {
+			XMLSerializer.transform(src, dest);
+		}
+		catch(TransformerException e) {
+			System.out.printf("Failed to output XML: %s%n", e);
+			return;
+		}
+		
+		try {
+			m_Output.flush();
+		}
+		catch(java.io.IOException e) {
+			System.out.printf("Failed to flush output: %s%n", e);
+		}
+		
+		
+	}
+	
+	/**
+	 * Sets the list of available alphabets to be recorded
+	 * during the production of the &lt;init> section
+	 * produced for the first frame. 
+	 * 
+	 * @param Alphs List of available alphabets
+	 */
+	public void setAlphabets(ArrayList<String> Alphs) {
+		Alphabets = Alphs;
+	}
+	
+	/**
+	 * Sets the list of available colour schemes to be recorded
+	 * during the production of the &lt;init> section
+	 * produced for the first frame. 
+	 * 
+	 * @param Cols List of available colour schemes
+	 */
+	public void setColours(ArrayList<String> Cols) {
+		Colours = Cols;
+	}
+	
+	/**
+	 * Records an EditEvent to be added to the XML document
+	 * during a call to Display().
+	 * 
+	 * @param event New EditEvent
+	 */
+	public void addEditEvent(dasher.CEditEvent event) {
+		
+		editEventQueue.add(event);
+		
+	}
+	
+	/**
+	 * Adds all EditEvents recorded since the last frame to the
+	 * XML document, in the manner described in the class summary.
+	 */
+	protected void addEditEvents() {
+		dasher.CEditEvent event;
+		
+		Element edits = drawInstructions.createElement("edit");
+		root.appendChild(edits);
+		
+		while((event = editEventQueue.poll()) != null) {
+			
+			if(event.m_iEditType == 1) { // add text
+				Element add = drawInstructions.createElement("add");
+				edits.appendChild(add);
+				
+				Text addtext = drawInstructions.createTextNode(event.m_sText);
+				add.appendChild(addtext);
+			}
+			if(event.m_iEditType == 2) { // remove text
+				Element remove = drawInstructions.createElement("remove");
+				
+				remove.setAttribute("num", Integer.toString(event.m_sText.length()));
+				edits.appendChild(remove);
+			}
+			
+		}
+	}
+
+	/**
+	 * Adds a tag of the form &lt;circle centrex="..." centrey="..." radius="..." fill="..." colour="..."/>
+	 * to the Frame tag of this document.
+	 * <p>
+	 * The colour attributes are recorded in standard #RRGGBB format.
+	 */
+	public void DrawCircle(int iCX, int iCY, int iR, int iColour, boolean bFill) {
+		Element newCircle = drawInstructions.createElement("circle");
+		
+		newCircle.setAttribute("centrex", Integer.toString(iCX));
+		newCircle.setAttribute("centrey", Integer.toString(iCY));
+		newCircle.setAttribute("radius", Integer.toString(iR));
+		newCircle.setAttribute("fill", Boolean.toString(bFill));
+		newCircle.setAttribute("colour", getColour(iColour));
+		
+		frame.appendChild(newCircle);
+		
+	}
+
+	/**
+	 * Adds a tag of the form &lt;rect x="..." y="..." w="..." h="..." colour="..." olcolour="..." thickness="..." fill="..." drawoutline="..."/>
+	 * to the Frame tag of this document.
+	 * <p>
+	 * The colour attributes are recorded in standard #RRGGBB format.
+	 */	
+	public void DrawRectangle(int x1, int y1, int x2, int y2, int Color, int iOutlineColour, EColorSchemes ColorScheme, boolean bDrawOutline, boolean bFill, int iThickness) {
+		
+		// Assuming our client wants co-ordinates for a top-left corner
+		
+		Element newRect = drawInstructions.createElement("rect");
+		
+		newRect.setAttribute("x", Integer.toString(x1));
+		newRect.setAttribute("y", Integer.toString(y2));
+		newRect.setAttribute("w", Integer.toString(Math.abs(x2 - x1)));
+		newRect.setAttribute("h", Integer.toString(Math.abs(y2 - y1)));
+		newRect.setAttribute("colour", getColour(Color));
+		newRect.setAttribute("olcolour", getColour(iOutlineColour));
+		newRect.setAttribute("thickness", Integer.toString(iThickness));
+		
+		newRect.setAttribute("fill", Boolean.toString(bFill));
+		newRect.setAttribute("drawoutline", Boolean.toString(bDrawOutline));
+		
+		frame.appendChild(newRect);
+	}
+
+	/**
+	 * Adds a tag of the form &lt;string size="..." x="..." y="...">The String&lt;/string>
+	 * to the Frame tag of this document.
+	 * <p>
+	 * The co-ordinates describe the top-left corner of a bounding rectangle.
+	 */
+	public void DrawString(String string, int x1, int y1, long Size) {
+		Element newString = drawInstructions.createElement("string");
+		
+		newString.setAttribute("size", Long.toString(Size));
+		newString.setAttribute("x", Integer.toString(x1));
+		newString.setAttribute("y", Integer.toString(y1));
+				
+		Text stringText = drawInstructions.createTextNode(string);
+		
+		newString.appendChild(stringText);
+		
+		frame.appendChild(newString);
+		
+	}
+
+	public int GetHeight() {
+		return m_Height;
+	}
+
+	public int GetWidth() {
+		return m_Width;
+	}
+
+	/**
+	 * See Polygon(CDasherView.Point[], int, int, int, boolean)
+	 */
+	public void Polygon(CDasherView.Point[] Points, int Number, int Color, int iWidth) {
+		
+		Polygon(Points, Number, Color, iWidth, true);
+		
+	}
+	
+	/**
+	 * Adds a polygon to the XML document in the following format:
+	 * <p>
+	 * &lt;poly colour="..." fill="..." thickness="...">
+	 * &lt;point x="..." y="..."/>
+	 * &lt;point x="..." y="..."/>
+	 * ...
+	 * &lt;/poly>
+	 * 
+	 * @param Points Array of Points constituting the polygon
+	 * @param Number Number of points in the polygon
+	 * @param Color Outline colour
+	 * @param iWidth Outline width
+	 * @param fill Fill colour
+	 */
+	protected void Polygon(CDasherView.Point[] Points, int Number, int Color, int iWidth, boolean fill) {
+		
+		Element newPoly = drawInstructions.createElement("poly");
+		newPoly.setAttribute("colour", getColour(Color));
+		newPoly.setAttribute("thickness", Integer.toString(iWidth));
+		newPoly.setAttribute("fill", Boolean.toString(fill));
+		
+		for(CDasherView.Point point : Points) {
+			Element newPoint = drawInstructions.createElement("point");
+			newPoint.setAttribute("x", Integer.toString(point.x));
+			newPoint.setAttribute("y", Integer.toString(point.y));
+			newPoly.appendChild(newPoint);
+		}
+		
+		frame.appendChild(newPoly);
+		
+	}
+	
+	/**
+	 * See Polygon(CDasherView.Point[], int, int, int, boolean)
+	 */
+	public void Polygon(CDasherView.Point[] Points, int Number, int Color) {
+
+		Polyline(Points, Number, Color, 1);
+		
+	}
+
+	/**
+	 * See Polygon(CDasherView.Point[], int, int, int, boolean)
+	 */
+	public void Polyline(CDasherView.Point[] Points, int Number, int iWidth, int Colour) {
+		
+		Polygon(Points, Number, Colour, iWidth, false);
+		
+	}
+
+	/**
+	 * See Polygon(CDasherView.Point[], int, int, int, boolean)
+	 */
+	public void Polyline(CDasherView.Point[] Points, int Number, int iWidth) {
+		
+		Polyline(Points, Number, iWidth, 0);
+		
+	}
+
+	/**
+	 * Stub. For the general contract of this method, see
+	 * CDasherScreen.
+	 */
+	public void SendMarker(int iMarker) {
+				
+	}
+
+	public void SetColourScheme(CCustomColours ColourScheme) {
+		
+		m_ColourScheme = ColourScheme;
+		
+	}
+
+	public CDasherView.Point TextSize(String string, int Size) {
+		
+		CDasherView.Point retval = new CDasherView.Point();
+		retval.x = 10;
+		retval.y = 10;
+		
+		return retval;
+		
+	}
+	
+	/**
+	 * Transforms a Dasher colour identifier into an HTML-style
+	 * #RRGGBB expression describing said colour.
+	 * 
+	 * @param iColour Colour index
+	 * @return HTML colour
+	 */
+	protected String getColour(int iColour) {
+		if(iColour == -1) iColour = 3;
+		
+		Color drawColour = new Color(m_ColourScheme.GetRed(iColour), m_ColourScheme.GetGreen(iColour), m_ColourScheme.GetBlue(iColour));
+		
+		int colournumber = drawColour.getRGB();
+		
+		return "#" + Integer.toHexString(colournumber).substring(2);
+	}
+	
+	/**
+	 * Sets the output stream to which XML should be serialized.
+	 * <p>
+	 * Typically this will be set prior to calling NewFrame, but it
+	 * will take effect if set at any time before Display() is called.
+	 * 
+	 * @param out OutputStream to which the next frame's XML should be written
+	 */
+	public void setOutput(java.io.OutputStream out) {
+		m_Output = out;
+	}
+	
+	/**
+	 * Sets the default alphabet to be reported when this
+	 * Screen draws its first frame.
+	 * 
+	 * @param alph Default alphabet
+	 */
+	public void setInitialAlph(String alph) {
+		initialAlph = alph;
+	}
+	
+	/**
+	 * Sets the default colour scheme to be reported when this
+	 * Screen draws its first frame.
+	 * 
+	 * @param CS Default colour scheme
+	 */
+	public void setInitialCS(String CS) {
+		initialCS = CS;
+	}
+
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]