LocaleHandler.java
001 /*
002  * LocaleHandler.java
003  *
004  * Copyright (c) 1998-2005, The University of Sheffield.
005  *
006  * This file is part of GATE (see http://gate.ac.uk/), and is free
007  * software, licenced under the GNU Library General Public License,
008  * Version 2, June1991.
009  *
010  * A copy of this licence is included in the distribution in the file
011  * licence.html, and is also available at http://gate.ac.uk/gate/licence.html.
012  *
013  * Valentin Tablan, October 2000
014  *
015  * $Id: LocaleHandler.java 13025 2010-08-25 14:06:50Z valyt $
016  */
017 package guk.im;
018 
019 import guk.GukBomStrippingInputStreamReader;
020 
021 import java.awt.event.InputEvent;
022 import java.io.*;
023 import java.util.*;
024 
025 /**
026  * A Handler for a locale.
027  * A locale handler is actually a finite state machine (FSM) that maps
028  * input events (presseed keys) to other input events(typed characters).
029  *
030  */
031 public class LocaleHandler {
032   /**
033    * Creates a locale handler for a given locale using the definitions from
034    * the file provided.
035    *
036    @exception IOException
037    @param locale
038    @param fileName
039    */
040   public LocaleHandler(Locale locale, String fileNamethrows IOException {
041   //System.out.println("Loading " + fileName);
042     this.locale = locale;
043     InputStream is = GateIM.class.getResourceAsStream(GateIM.getIMBase()
044                        + fileName);
045     if (is==nullthrow new IllegalArgumentException
046      ("Failed to retrieve resource '"+fileName+"'. Please reset classpath.");
047     BufferedReader br = new GukBomStrippingInputStreamReader(is);
048     String line = br.readLine();
049     initialState = new State();
050 
051     String remains;
052     String keyStr;
053     String keycapStr;
054     String keymapName;
055     String number;
056     String output;
057     keycap = new HashMap();
058     int start, end;
059     while(line != null){
060   //System.out.println(line);
061       //skip comments and empty lines
062       line = line.trim();
063       ifline.startsWith("#"|| line.startsWith("//" ||
064           line.length() == ){
065         line = br.readLine();
066         continue;
067       }
068       try {
069         remains = line;
070         keycapStr = null;
071         keymapName = null;
072         if(remains.startsWith("bind")){
073           //bind declaration
074           //skip the bind
075           remains = remains.substring(4).trim();
076           //get the key string
077           keyStr = "";
078           start = remains.indexOf('\"');
079           for(end = start + ; remains.charAt(end)!='\"'; end++){
080             if(remains.charAt(end== '\\'end++;
081             keyStr += remains.charAt(end);
082           }
083           remains = remains.substring(end + 1).trim();
084           if(remains.startsWith("digit")) {
085             //digit declaration
086             //skip the "digit"
087             remains = remains.substring(5).trim();
088             //read the hex number(s)
089             output = "";
090             while(remains.startsWith("0x")){
091               //read the hex number(s)
092               number = remains.substring(2,6);
093               output += (char)Integer.parseInt(number, 16);
094               //do not trim so we can get out after the first number is read
095               remains = remains.substring(6);
096             }
097             remains = remains.trim();
098 
099             //read the second number if it exists and ignore the first
100             if(remains.length() 0){
101               output = "";
102               while(remains.startsWith("0x")){
103                 //read the hex number(s)
104                 number = remains.substring(2,6);
105                 output += (char)Integer.parseInt(number, 16);
106                 //do not trim so we can get out after the first number is read
107                 remains = remains.substring(6);
108               }
109             }
110             addAction(keyStr, output, output);
111             //we're through with this line
112           else if(remains.startsWith("send")) {
113             //send declaration
114             //skip the send
115             remains = remains.substring(4).trim();
116             //parse the text to be sent
117             output = "";
118             while(remains.startsWith("0x")) {
119               //read the hex number(s)
120               number = remains.substring(2,6);
121               output += (char)Integer.parseInt(number, 16);
122               remains = remains.substring(6).trim();
123             }
124             //skip the keycap declaration
125             if(remains.startsWith("keycap")){
126               //skip "keycap"
127               remains = remains.substring(6).trim();
128               //skip all the numbers
129               keycapStr = "";
130               while(remains.startsWith("0x")){
131                 //read the hex number(s)
132                 number = remains.substring(2,6);
133                 keycapStr += (char)Integer.parseInt(number, 16);
134                 remains = remains.substring(6).trim();
135               }
136             }
137             //is there a keymap declaration?
138             if (remains.startsWith("keymap")){
139               //skip "keymap"
140               remains = remains.substring(6).trim();
141   //XXXXXXXXXXXXXXXXXX//TO DO handle keymap declaration
142             else if(remains.length() == 0) {
143               //we're done with this line
144               addAction(keyStr, output, keycapStr);
145             else System.err.println("[GATE Unicode input method loader]" +
146                                      " Ignoring line: " + line);
147           else if(remains.startsWith("resetorsend")){
148             //send declaration
149             //skip the resetorsend
150             remains = remains.substring(11).trim();
151   //XXXXXXXXXXXXXXXXXX//TO DO handle resetorsend declaration
152           else System.err.println("[GATE Unicode input method loader]" +
153                                  " Ignoring line: " + line);
154         else if(remains.startsWith("keymap")){
155           //keymap declaration
156         else if(remains.startsWith("inputmethod")){
157           //ignore
158         else if(remains.startsWith("option")){
159           //ignore
160         else System.err.println("[GATE Unicode input method loader]" +
161                                  " Ignoring line: " + line);
162       catch(StringIndexOutOfBoundsException siobe) {
163         System.err.println("[GATE Unicode input method loader]" +
164                            " Ignoring line: " + line);
165       }
166       line = br.readLine();
167     }//while(line != null)
168   }//public LocaleHandler(String fileName)
169 
170   /**    *
171    @param keyDesc
172    @param textToAdd
173    @param keycapStr
174    */
175   protected State addAction(String keyDesc,
176                             String textToAdd,
177                             String keycapStr) {
178     //create the list of keys
179     List keyList = new ArrayList(1);
180     int modifiers = 0;
181     char keyChar;
182     int offset = 0;
183     while(keyDesc.length() 0) {
184   //System.out.println("A");
185       modifiers = 0;
186       offset = 0;
187       if(keyDesc.startsWith("C-")) {
188         //CTRL + ?
189         modifiers |= InputEvent.CTRL_MASK;
190         offset = 2;
191       else if(keyDesc.startsWith("M-")) {
192         //ALT + ?
193         modifiers |= InputEvent.ALT_MASK;
194         offset = 2;
195       }
196       keyChar = keyDesc.charAt(offset);
197       keyDesc = keyDesc.substring(offset + 1).trim();
198       keyList.add(new Key(keyChar, modifiers));
199     }//while(keyDesc.length() > 0)
200 
201     //add the keycap
202     if(keycapStr != null && keyList.size() == 1) {
203       keycap.put(keyList.get(0), keycapStr);
204 //System.out.println("Added keycap: " + keycapStr);
205     }
206 
207     //create the states and actions from the list of keys
208     State nextState, currentState = initialState;
209     Action currentAction = null;
210     Iterator keyIter = keyList.iterator();
211     Key currentKey;
212     while(keyIter.hasNext()) {
213       currentKey = (Key)keyIter.next();
214       currentAction = currentState.getNext(currentKey);
215       if(currentAction == null){
216         nextState = new State();
217         currentAction = new Action(nextState);
218         currentState.addAction(currentKey, currentAction);
219         currentAction.setComposedText("" + currentKey.keyChar);
220       else nextState = currentAction.getNext();
221       currentState = nextState;
222     }//while(keyIter.hasNext())
223     currentAction.setComposedText(textToAdd);
224     currentState.setFinal(true);
225     return currentState;
226   }// State addAction
227 
228   /**
229    * The initial state of the FSM.
230    *
231    */
232   public State getInitialState(){
233     return initialState;
234   }
235 
236   /**
237    * Gets the map with the keycaps (the strings to be painted on virtual keys).
238    *
239    */
240   public Map  getKeyCap(){
241     return keycap;
242   }
243 
244   //the initial state of the fsm
245   /**
246    * The initial state of the fsm.
247    *
248    */
249   State initialState;
250   /** maps from string (the English description of the key) to
251    * string (the string to be displayed on the key)
252    *
253    */
254   Map keycap;
255 
256   /**
257    * The locale this handler handles.
258    *
259    */
260   Locale locale;
261 }//class LocaleHandler