Mega Code Archive

 
Categories / Java by API / Java Awt Im Spi
 

InputMethodEvent CARET_POSITION_CHANGED

/*  * @(#)CodePointInputMethod.java  1.6 05/11/17  *   * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.  *   * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions are met:  *   * -Redistribution of source code must retain the above copyright notice, this  *  list of conditions and the following disclaimer.  *   * -Redistribution in binary form must reproduce the above copyright notice,   *  this list of conditions and the following disclaimer in the documentation  *  and/or other materials provided with the distribution.  *   * Neither the name of Sun Microsystems, Inc. or the names of contributors may   * be used to endorse or promote products derived from this software without   * specific prior written permission.  *   * This software is provided "AS IS," without a warranty of any kind. ALL   * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING  * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE  * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")  * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE  * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS  * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST   * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,   * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY   * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,   * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  *   * You acknowledge that this software is not designed, licensed or intended  * for use in the design, construction, operation or maintenance of any  * nuclear facility.  */ /*  * @(#)CodePointInputMethod.java  1.6 05/11/17  */ //package com.sun.inputmethods.internal.codepointim; import java.awt.AWTEvent; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.event.InputMethodEvent; import java.awt.event.KeyEvent; import java.awt.font.TextAttribute; import java.awt.font.TextHitInfo; import java.awt.im.InputMethodHighlight; import java.awt.im.spi.InputMethod; import java.awt.im.spi.InputMethodContext; import java.io.IOException; import java.text.AttributedString; import java.util.Locale; /**  * The Code Point Input Method is a simple input method that allows Unicode  * characters to be entered using their code point or code unit values. See the  * accompanying file README.txt for more information.  *  * @author Brian Beck  */ public class CodePointInputMethod implements InputMethod {     private static final int UNSET           = 0;     private static final int ESCAPE          = 1; // \u0000       - \uFFFF     private static final int SPECIAL_ESCAPE  = 2; // \U000000     - \U10FFFF     private static final int SURROGATE_PAIR  = 3; // \uD800\uDC00 - \uDBFF\uDFFF     private InputMethodContext context;     private Locale locale;     private StringBuffer buffer;     private int insertionPoint;     private int format = UNSET;     public CodePointInputMethod() throws IOException {     }     /**      * This is the input method's main routine.  The composed text is stored      * in buffer.      */     public void dispatchEvent(AWTEvent event) {         // This input method handles KeyEvent only.         if (!(event instanceof KeyEvent)) {             return;         }         KeyEvent e = (KeyEvent) event;         int eventID = event.getID();         boolean notInCompositionMode = buffer.length() == 0;         if (eventID == KeyEvent.KEY_PRESSED) {             // If we are not in composition mode, pass through             if (notInCompositionMode)  {                 return;             }             switch (e.getKeyCode()) {                 case KeyEvent.VK_LEFT:                     moveCaretLeft();                     break;                 case KeyEvent.VK_RIGHT:                     moveCaretRight();                     break;             }         } else if (eventID == KeyEvent.KEY_TYPED) {             char c = e.getKeyChar();             // If we are not in composition mode, wait a back slash             if (notInCompositionMode)  {                 // If the type character is not a back slash, pass through                 if (c != '\\') {                     return;                 }                 startComposition(); // Enter to composition mode             } else {                 switch (c) {                  case ' ': // Exit from composition mode                     finishComposition();                     break;                 case '\u007f':  // Delete                     deleteCharacter();                     break;                 case '\b':  // BackSpace                     deletePreviousCharacter();                     break;                 case '\u001b':  // Escape                     cancelComposition();                     break;                 case '\n':  // Return                 case '\t':  // Tab                     sendCommittedText();                     break;                 default:                     composeUnicodeEscape(c);                     break;                 }             }         } else {  // KeyEvent.KEY_RELEASED             // If we are not in composition mode, pass through             if (notInCompositionMode)  {                 return;             }         }         e.consume();     }     private void composeUnicodeEscape(char c) {         switch (buffer.length()) {             case  1:  // \\                 waitEscapeCharacter(c);                 break;             case 2:  // \\u or \\U             case 3:  // \\ux or \\Ux             case 4:  // \\uxx or \\Uxx                 waitDigit(c);                 break;             case 5:  // \\uxxx or \\Uxxx                 if (format == SPECIAL_ESCAPE) {                     waitDigit(c);                 } else {                     waitDigit2(c);                 }                 break;             case 6:  // \\uxxxx or \\Uxxxx                 if (format == SPECIAL_ESCAPE) {                     waitDigit(c);                 } else if (format == SURROGATE_PAIR) {                     waitBackSlashOrLowSurrogate(c);                 } else {                     beep();                 }                 break;             case 7:  // \\Uxxxxx                 // Only SPECIAL_ESCAPE format uses this state.                 // Since the second "\\u" of SURROGATE_PAIR format is inserted                 // automatically, users don't have to type these keys.                 waitDigit(c);                 break;             case 8:  // \\uxxxx\\u             case 9:  // \\uxxxx\\ux             case 10: // \\uxxxx\\uxx             case 11: // \\uxxxx\\uxxx                 if (format == SURROGATE_PAIR) {                     waitDigit(c);                 } else {                     beep();                 }                 break;             default:                 beep();                 break;         }     }     private void waitEscapeCharacter(char c) {         if (c == 'u' || c == 'U') {             buffer.append(c);             insertionPoint++;             sendComposedText();             format = (c == 'u') ? ESCAPE : SPECIAL_ESCAPE;         } else {             if (c != '\\') {                 buffer.append(c);                 insertionPoint++;             }             sendCommittedText();         }     }     private void waitDigit(char c) {         if (Character.digit(c, 16) != -1) {             buffer.insert(insertionPoint++, c);             sendComposedText();         } else {             beep();         }     }     private void waitDigit2(char c) {         if (Character.digit(c, 16) != -1) {             buffer.insert(insertionPoint++, c);             char codePoint = (char)getCodePoint(buffer, 2, 5);             if (Character.isHighSurrogate(codePoint)) {                 format = SURROGATE_PAIR;                 buffer.append("\\u");                 insertionPoint = 8;             } else {                 format = ESCAPE;             }             sendComposedText();         } else {             beep();         }     }     private void waitBackSlashOrLowSurrogate(char c) {         if (insertionPoint == 6) {             if (c == '\\') {                 buffer.append(c);                 buffer.append('u');                 insertionPoint = 8;                 sendComposedText();             } else if (Character.digit(c, 16) != -1) {                 buffer.append("\\u");                 buffer.append(c);                 insertionPoint = 9;                 sendComposedText();             } else {                 beep();             }         } else {             beep();         }     }     /**      * Send the composed text to the client.      */     private void sendComposedText() {         AttributedString as = new AttributedString(buffer.toString());         as.addAttribute(TextAttribute.INPUT_METHOD_HIGHLIGHT,                         InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT);         context.dispatchInputMethodEvent(                                   InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,                                   as.getIterator(), 0,                                   TextHitInfo.leading(insertionPoint), null);     }     /**      * Send the committed text to the client.      */     private void sendCommittedText() {         AttributedString as = new AttributedString(buffer.toString());         context.dispatchInputMethodEvent(                                   InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,                                   as.getIterator(), buffer.length(),                                   TextHitInfo.leading(insertionPoint), null);         buffer.setLength(0);         insertionPoint = 0;         format = UNSET;     }     /**      * Move the insertion point one position to the left in the composed text.      * Do not let the caret move to the left of the "\\u" or "\\U".      */     private void moveCaretLeft() {         int len = buffer.length();         if (--insertionPoint < 2) {             insertionPoint++;             beep();         } else if (format == SURROGATE_PAIR && insertionPoint == 7) {             insertionPoint = 8;             beep();         }         context.dispatchInputMethodEvent(                                   InputMethodEvent.CARET_POSITION_CHANGED,                                   null, 0,                                   TextHitInfo.leading(insertionPoint), null);     }     /**      * Move the insertion point one position to the right in the composed text.      */     private void moveCaretRight() {         int len = buffer.length();         if (++insertionPoint > len) {             insertionPoint = len;             beep();         }         context.dispatchInputMethodEvent(                                   InputMethodEvent.CARET_POSITION_CHANGED,                                   null, 0,                                   TextHitInfo.leading(insertionPoint), null);     }     /**      * Delete the character preceding the insertion point in the composed text.      * If the insertion point is not at the end of the composed text and the      * preceding text is "\\u" or "\\U", ring the bell.      */     private void deletePreviousCharacter() {         if (insertionPoint == 2) {             if (buffer.length() == 2) {                 cancelComposition();             } else {                 // Do not allow deletion of the leading "\\u" or "\\U" if there                 // are other digits in the composed text.                 beep();             }         } else if (insertionPoint == 8) {             if (buffer.length() == 8) {                 if (format == SURROGATE_PAIR) {                     buffer.deleteCharAt(--insertionPoint);                 }                 buffer.deleteCharAt(--insertionPoint);                 sendComposedText();             } else {                 // Do not allow deletion of the second "\\u" if there are other                 // digits in the composed text.                 beep();             }         } else {             buffer.deleteCharAt(--insertionPoint);             if (buffer.length() == 0) {                 sendCommittedText();             } else {                 sendComposedText();             }         }     }     /**      * Delete the character following the insertion point in the composed text.      * If the insertion point is at the end of the composed text, ring the bell.      */     private void deleteCharacter() {         if (insertionPoint < buffer.length()) {             buffer.deleteCharAt(insertionPoint);             sendComposedText();         } else {             beep();         }     }     private void startComposition() {         buffer.append('\\');         insertionPoint = 1;         sendComposedText();     }     private void cancelComposition() {         buffer.setLength(0);         insertionPoint = 0;         sendCommittedText();     }     private void finishComposition() {         int len = buffer.length();         if (len == 6 && format != SPECIAL_ESCAPE) {             char codePoint = (char)getCodePoint(buffer, 2, 5);             if (Character.isValidCodePoint(codePoint) && codePoint != 0xFFFF) {                 buffer.setLength(0);                 buffer.append(codePoint);           sendCommittedText();                 return;             }         } else if (len == 8 && format == SPECIAL_ESCAPE) {             int codePoint = getCodePoint(buffer, 2, 7);             if (Character.isValidCodePoint(codePoint) && codePoint != 0xFFFF) {                 buffer.setLength(0);                 buffer.appendCodePoint(codePoint);           sendCommittedText();                 return;             }         } else if (len == 12 && format == SURROGATE_PAIR) {       char[] codePoint = {                 (char)getCodePoint(buffer, 2, 5),           (char)getCodePoint(buffer, 8, 11)             };             if (Character.isHighSurrogate(codePoint[0]) &&                 Character.isLowSurrogate(codePoint[1])) {           buffer.setLength(0);           buffer.append(codePoint);           sendCommittedText();                 return;             }         }         beep();     }     private int getCodePoint(StringBuffer sb, int from, int to) {         int value = 0;         for (int i = from; i <= to; i++) {             value = (value<<4) + Character.digit(sb.charAt(i), 16);         }         return value;     }     private static void beep() {         Toolkit.getDefaultToolkit().beep();     }     public void activate() {         if (buffer == null) {             buffer = new StringBuffer(12);             insertionPoint = 0;         }     }     public void deactivate(boolean isTemporary) {         if (!isTemporary) {             buffer = null;         }     }     public void dispose() {     }     public Object getControlObject() {         return null;     }     public void endComposition() {         sendCommittedText();     }     public Locale getLocale() {         return locale;     }     public void hideWindows() {     }     public boolean isCompositionEnabled() {         // always enabled         return true;     }     public void notifyClientWindowChange(Rectangle location) {     }     public void reconvert() {         // not supported yet         throw new UnsupportedOperationException();     }     public void removeNotify() {     }     public void setCharacterSubsets(Character.Subset[] subsets) {     }     public void setCompositionEnabled(boolean enable) {         // not supported yet         throw new UnsupportedOperationException();     }     public void setInputMethodContext(InputMethodContext context) {         this.context = context;     }     /*      * The Code Point Input Method supports all locales.      */     public boolean setLocale(Locale locale) {         this.locale = locale;         return true;     } }