001: /*
002: *******************************************************************************
003: * Copyright (C) 1996-2004, International Business Machines Corporation and *
004: * others. All Rights Reserved. *
005: *******************************************************************************
006: */
007: package com.ibm.icu.dev.demo.translit;
008:
009: import java.awt.event.*;
010: import com.ibm.icu.text.*;
011: import com.ibm.icu.dev.demo.impl.*;
012:
013: /**
014: * A subclass of {@link DumbTextComponent} that passes key events through
015: * a {@link com.ibm.icu.text.Transliterator}.
016: *
017: * <p>Copyright © IBM Corporation 1999. All rights reserved.
018: *
019: * @author Alan Liu
020: */
021: public class TransliteratingTextComponent extends DumbTextComponent {
022:
023: private static boolean DEBUG = false;
024:
025: private Transliterator translit = null;
026:
027: // NOTE: DISABLE THE START AND CURSOR UNTIL WE CAN GET IT TO WORK AT ALL
028:
029: // Index into getText() where the start of transliteration is.
030: // As we commit text during transliteration, we advance
031: // this.
032: //private int start = 0;
033:
034: // Index into getText() where the cursor is; cursor >= start
035: //private int cursor = 0;
036:
037: private static final String COPYRIGHT = "\u00A9 IBM Corporation 1999. All rights reserved.";
038:
039: /**
040: * Constructor.
041: */
042: public TransliteratingTextComponent() {
043: super ();
044: /*
045: addActionListener(new ActionListener() {
046: public void actionPerformed(ActionEvent e) {
047: // We get an ActionEvent only when the selection changes
048: resetTransliterationStart();
049: }
050: });
051: */
052: }
053:
054: /**
055: * {@link DumbTextComponent} API. Framework method that is called
056: * when a <code>KeyEvent</code> is received. This implementation
057: * runs the new character through the current
058: * <code>Transliterator</code>, if one is set, and inserts the
059: * transliterated text into the buffer.
060: */
061: protected void handleKeyTyped(KeyEvent e) {
062: char ch = e.getKeyChar();
063:
064: if (translit == null) {
065: setKeyStart(-1);
066: super .handleKeyTyped(e);
067: return;
068: }
069:
070: transliterate(ch, false);
071: }
072:
073: public void flush() {
074: if (translit != null)
075: transliterate('\uFFFF', true);
076: }
077:
078: protected void transliterate(char ch, boolean flush) {
079:
080: // ------------------------------------------------------------
081: // The following case motivates the two lines that recompute
082: // start and cursor below.
083:
084: // " "
085: // a b c q r|s t u m m
086: // 0 1 2 3 4 5 6 7 8 9
087: // 0 1 2
088:
089: // start 3, cursor 5, sel 6 -> { 0, 3, 2 }
090: // : new int[] { 0, sel - start, cursor - start };
091:
092: // sz>99|9
093:
094: // " { "
095: // a b c q r 9 9|9 t u m m
096: // 0 1 2 3 4 5 6 7 8 9 a b
097: // 0 1 2 3 4
098:
099: // { 3, 5, 4 } -> start 6, cursor 7, sel 8
100: // : start += index[0];
101: // : cursor = start + index[2] - index[0];
102: // ------------------------------------------------------------
103:
104: // Need to save start because calls to replaceRange will update
105: // start and cursor.
106: //int saveStart = start;
107:
108: int end = flush ? getSelectionEnd() : getSelectionStart();
109: String sourceText = getText().substring(0, end);
110: ReplaceableString buf = new ReplaceableString(sourceText);
111: /*buf.replace(0, 1, getText().substring(start,
112: getSelectionStart()));*/
113:
114: Transliterator.Position index = new Transliterator.Position();
115: index.contextLimit = buf.length();
116: index.contextStart = 0;
117: index.start = getKeyStart();
118: if (index.start == -1)
119: index.start = getSelectionStart();
120: index.limit = buf.length();
121:
122: // StringBuffer log = null;
123: if (DEBUG) {
124: System.out.println("Transliterator: " + translit.getID());
125: System.out.println("From:\t" + '"' + buf.toString() + '"'
126: + "; {cs: " + index.contextStart + ", s: "
127: + index.start + ", l: " + index.limit + ", cl: "
128: + index.contextLimit + "}" + "; '" + ch + "'" + " "
129: + getKeyStart());
130: }
131:
132: if (flush) {
133: translit.finishTransliteration(buf, index);
134: } else {
135: translit.transliterate(buf, index, ch);
136: }
137:
138: if (DEBUG) {
139: System.out.println("To:\t" + '"' + buf.toString() + '"'
140: + "; {cs: " + index.contextStart + ", s: "
141: + index.start + ", l: " + index.limit + ", cl: "
142: + index.contextLimit + "}");
143: System.out.println();
144: }
145: /*
146: buf.replace(buf.length(), buf.length(), String.valueOf(ch));
147: translit.transliterate(buf);
148: */
149:
150: String result = buf.toString();
151: //if (result.equals(sourceText + ch)) return;
152:
153: replaceRange(result, 0, getSelectionEnd());
154: setKeyStart(index.start);
155:
156: // At this point start has been changed by the callback to
157: // resetTransliteratorStart() via replaceRange() -- so use our
158: // local copy, saveStart.
159:
160: // The START index is zero-based. On entry to transliterate(),
161: // it was zero. We can therefore just add it to our original
162: // getText()-based index value of start (in saveStart) to get
163: // the new getText()-based start.
164: // start = saveStart + index.contextStart;
165:
166: // Make the cursor getText()-based. The CURSOR index is zero-based.
167: // cursor = start + index.start - index.contextStart;
168:
169: /*
170: if (DEBUG) {
171: String out = buf.toString();
172: log.append(out.substring(0, index.contextStart)).
173: append('{').
174: append(out.substring(index.contextStart, index.start)).
175: append('|').
176: append(out.substring(index.start)).
177: append('"');
178: log.append(", {" + index.contextStart + ", " + index.contextLimit + ", " + index.start + "}, ");
179: // log.append("start " + start + ", cursor " + cursor);
180: log.append(", sel " + getSelectionStart());
181: System.out.println(escape(log.toString()));
182: }
183: */
184: }
185:
186: /**
187: * Set the {@link com.ibm.icu.text.Transliterator} and direction to
188: * use to process incoming <code>KeyEvent</code>s.
189: * @param t the {@link com.ibm.icu.text.Transliterator} to use
190: */
191: public void setTransliterator(Transliterator t) {
192: /*
193: if (translit != t) { // [sic] pointer compare ok; singletons
194: resetTransliterationStart();
195: }
196: */
197: translit = t;
198: }
199:
200: public Transliterator getTransliterator() {
201: return translit;
202: }
203:
204: /**
205: * Reset the start point at which transliteration begins. This
206: * needs to be done when the user moves the cursor or when the
207: * current {@link com.ibm.icu.text.Transliterator} is changed.
208: */
209: /*
210: private void resetTransliterationStart() {
211: start = getSelectionStart();
212: cursor = start;
213: }
214: */
215:
216: /**
217: * Escape non-ASCII characters as Unicode.
218: * JUST FOR DEBUGGING OUTPUT.
219: */
220: public static final String escape(String s) {
221: StringBuffer buf = new StringBuffer();
222: for (int i = 0; i < s.length(); ++i) {
223: char c = s.charAt(i);
224: if (c >= ' ' && c <= 0x007F) {
225: if (c == '\\') {
226: buf.append("\\\\"); // That is, "\\"
227: } else {
228: buf.append(c);
229: }
230: } else {
231: buf.append("\\u");
232: if (c < 0x1000) {
233: buf.append('0');
234: if (c < 0x100) {
235: buf.append('0');
236: if (c < 0x10) {
237: buf.append('0');
238: }
239: }
240: }
241: buf.append(Integer.toHexString(c));
242: }
243: }
244: return buf.toString();
245: }
246: }
|