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 fileName) throws IOException {
041 //System.out.println("Loading " + fileName);
042 this.locale = locale;
043 InputStream is = GateIM.class.getResourceAsStream(GateIM.getIMBase()
044 + fileName);
045 if (is==null) throw 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 if( line.startsWith("#") || line.startsWith("//" ) ||
064 line.length() == 0 ){
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 + 1 ; 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
|