| LocaleHandler.java |
1 /*
2 * LocaleHandler.java
3 *
4 * Copyright (c) 1998-2004, The University of Sheffield.
5 *
6 * This file is part of GATE (see http://gate.ac.uk/), and is free
7 * software, licenced under the GNU Library General Public License,
8 * Version 2, June1991.
9 *
10 * A copy of this licence is included in the distribution in the file
11 * licence.html, and is also available at http://gate.ac.uk/gate/licence.html.
12 *
13 * Valentin Tablan, October 2000
14 *
15 * $Id: LocaleHandler.java,v 1.6 2004/08/06 16:08:26 valyt Exp $
16 */
17 package guk.im;
18
19 import java.awt.event.InputEvent;
20 import java.io.*;
21 import java.util.*;
22
23 /**
24 * A Handler for a locale.
25 * A locale handler is actually a finite state machine (FSM) that maps
26 * input events (presseed keys) to other input events(typed characters).
27 *
28 */
29 public class LocaleHandler {
30 /**
31 * Creates a locale handler for a given locale using the definitions from
32 * the file provided.
33 *
34 * @exception IOException
35 * @param locale
36 * @param fileName
37 */
38 public LocaleHandler(Locale locale, String fileName) throws IOException {
39 //System.out.println("Loading " + fileName);
40 this.locale = locale;
41 InputStream is = GateIM.class.getResourceAsStream(GateIM.getIMBase()
42 + fileName);
43 if (is==null) throw new IllegalArgumentException
44 ("Failed to retrieve resource '"+fileName+"'. Please reset classpath.");
45 BufferedReader br = new BufferedReader(new InputStreamReader(is));
46 String line = br.readLine();
47 initialState = new State();
48
49 String remains;
50 String keyStr;
51 String keycapStr;
52 String keymapName;
53 String number;
54 String output;
55 keycap = new HashMap();
56 int start, end;
57 while(line != null){
58 //System.out.println(line);
59 //skip comments and empty lines
60 line = line.trim();
61 if( line.startsWith("#") || line.startsWith("//" ) ||
62 line.length() == 0 ){
63 line = br.readLine();
64 continue;
65 }
66 try {
67 remains = line;
68 keycapStr = null;
69 keymapName = null;
70 if(remains.startsWith("bind")){
71 //bind declaration
72 //skip the bind
73 remains = remains.substring(4).trim();
74 //get the key string
75 keyStr = "";
76 start = remains.indexOf('\"');
77 for(end = start + 1 ; remains.charAt(end)!='\"'; end++){
78 if(remains.charAt(end) == '\\') end++;
79 keyStr += remains.charAt(end);
80 }
81 remains = remains.substring(end + 1).trim();
82 if(remains.startsWith("digit")) {
83 //digit declaration
84 //skip the "digit"
85 remains = remains.substring(5).trim();
86 //read the hex number(s)
87 output = "";
88 while(remains.startsWith("0x")){
89 //read the hex number(s)
90 number = remains.substring(2,6);
91 output += (char)Integer.parseInt(number, 16);
92 //do not trim so we can get out after the first number is read
93 remains = remains.substring(6);
94 }
95 remains = remains.trim();
96
97 //read the second number if it exists and ignore the first
98 if(remains.length() > 0){
99 output = "";
100 while(remains.startsWith("0x")){
101 //read the hex number(s)
102 number = remains.substring(2,6);
103 output += (char)Integer.parseInt(number, 16);
104 //do not trim so we can get out after the first number is read
105 remains = remains.substring(6);
106 }
107 }
108 addAction(keyStr, output, output);
109 //we're through with this line
110 } else if(remains.startsWith("send")) {
111 //send declaration
112 //skip the send
113 remains = remains.substring(4).trim();
114 //parse the text to be sent
115 output = "";
116 while(remains.startsWith("0x")) {
117 //read the hex number(s)
118 number = remains.substring(2,6);
119 output += (char)Integer.parseInt(number, 16);
120 remains = remains.substring(6).trim();
121 }
122 //skip the keycap declaration
123 if(remains.startsWith("keycap")){
124 //skip "keycap"
125 remains = remains.substring(6).trim();
126 //skip all the numbers
127 keycapStr = "";
128 while(remains.startsWith("0x")){
129 //read the hex number(s)
130 number = remains.substring(2,6);
131 keycapStr += (char)Integer.parseInt(number, 16);
132 remains = remains.substring(6).trim();
133 }
134 }
135 //is there a keymap declaration?
136 if (remains.startsWith("keymap")){
137 //skip "keymap"
138 remains = remains.substring(6).trim();
139 //XXXXXXXXXXXXXXXXXX//TO DO handle keymap declaration
140 } else if(remains.length() == 0) {
141 //we're done with this line
142 addAction(keyStr, output, keycapStr);
143 } else System.err.println("[GATE Unicode input method loader]" +
144 " Ignoring line: " + line);
145 } else if(remains.startsWith("resetorsend")){
146 //send declaration
147 //skip the resetorsend
148 remains = remains.substring(11).trim();
149 //XXXXXXXXXXXXXXXXXX//TO DO handle resetorsend declaration
150 } else System.err.println("[GATE Unicode input method loader]" +
151 " Ignoring line: " + line);
152 } else if(remains.startsWith("keymap")){
153 //keymap declaration
154 } else if(remains.startsWith("inputmethod")){
155 //ignore
156 } else if(remains.startsWith("option")){
157 //ignore
158 } else System.err.println("[GATE Unicode input method loader]" +
159 " Ignoring line: " + line);
160 } catch(StringIndexOutOfBoundsException siobe) {
161 System.err.println("[GATE Unicode input method loader]" +
162 " Ignoring line: " + line);
163 }
164 line = br.readLine();
165 }//while(line != null)
166 }//public LocaleHandler(String fileName)
167
168 /** *
169 * @param keyDesc
170 * @param textToAdd
171 * @param keycapStr
172 */
173 protected State addAction(String keyDesc,
174 String textToAdd,
175 String keycapStr) {
176 //create the list of keys
177 List keyList = new ArrayList(1);
178 int modifiers = 0;
179 char keyChar;
180 int offset = 0;
181 while(keyDesc.length() > 0) {
182 //System.out.println("A");
183 modifiers = 0;
184 offset = 0;
185 if(keyDesc.startsWith("C-")) {
186 //CTRL + ?
187 modifiers |= InputEvent.CTRL_MASK;
188 offset = 2;
189 } else if(keyDesc.startsWith("M-")) {
190 //ALT + ?
191 modifiers |= InputEvent.ALT_MASK;
192 offset = 2;
193 }
194 keyChar = keyDesc.charAt(offset);
195 keyDesc = keyDesc.substring(offset + 1).trim();
196 keyList.add(new Key(keyChar, modifiers));
197 }//while(keyDesc.length() > 0)
198
199 //add the keycap
200 if(keycapStr != null && keyList.size() == 1) {
201 keycap.put(keyList.get(0), keycapStr);
202 //System.out.println("Added keycap: " + keycapStr);
203 }
204
205 //create the states and actions from the list of keys
206 State nextState, currentState = initialState;
207 Action currentAction = null;
208 Iterator keyIter = keyList.iterator();
209 Key currentKey;
210 while(keyIter.hasNext()) {
211 currentKey = (Key)keyIter.next();
212 currentAction = currentState.getNext(currentKey);
213 if(currentAction == null){
214 nextState = new State();
215 currentAction = new Action(nextState);
216 currentState.addAction(currentKey, currentAction);
217 currentAction.setComposedText("" + currentKey.keyChar);
218 } else nextState = currentAction.getNext();
219 currentState = nextState;
220 }//while(keyIter.hasNext())
221 currentAction.setComposedText(textToAdd);
222 currentState.setFinal(true);
223 return currentState;
224 }// State addAction
225
226 /**
227 * The initial state of the FSM.
228 *
229 */
230 public State getInitialState(){
231 return initialState;
232 }
233
234 /**
235 * Gets the map with the keycaps (the strings to be painted on virtual keys).
236 *
237 */
238 public Map getKeyCap(){
239 return keycap;
240 }
241
242 //the initial state of the fsm
243 /**
244 * The initial state of the fsm.
245 *
246 */
247 State initialState;
248 /** maps from string (the English description of the key) to
249 * string (the string to be displayed on the key)
250 *
251 */
252 Map keycap;
253
254 /**
255 * The locale this handler handles.
256 *
257 */
258 Locale locale;
259 }//class LocaleHandler
260