JDK-7201151 : Fix Contribution : Java cannot get Windows's IME name correctly
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt:i18n
  • Affected Version: 8
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2012-09-26
  • Updated: 2014-02-05
  • Resolved: 2012-10-04
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7 JDK 8
7u40Fixed 8 b61Fixed
Description
SYNOPSIS
--------
Java cannot get Windows's IME name correctly


OPERATING SYSTEM(S)
-------------------
Not sure whether it is a platform independent issue.


FULL JDK VERSION(S)
-------------------
Java 6 onwards.


PROBLEM DESCRIPTION from LICENSEE
---------------------------------
Java cannot get Windows's IME name correctly - its last character is missing. Users may see this bug when any program acquires the IME name.

The root cause is an insufficiently sized buffer. Note the information in this URL:

        http://msdn.microsoft.com/en-us/library/windows/desktop/dd318562%28v=vs.85%29.aspx

The terminating null character is *not* included in the size of the output buffer returned by ImmGetDescription(). This fact is not taken into account when the AWT code constructs the buffer, so the buffer is created one character too short.


REPRODUCTION INSTRUCTIONS
-------------------------
1. Compile and run the attached testcase
2. Enable Microsoft IME
3. Press some key(eg. press shift), IME name is displayed on bottom of window.

PROBLEM: The IME name is "Microsoft IME Standar", but it should be "Microsoft IME Standard".


TESTCASE
--------
The testcase does demonstrate the issue, but may not be ready for regression-type testing.

import java.awt.*;
import java.awt.event.*;
import java.awt.im.*;
import javax.swing.*;

public class InputMethodInfoTest extends JFrame implements KeyListener {
    JTextArea text = null;
    JLabel label = null;
    InputMethodInfoTest() {
        setTitle("InputMethodInfoTest");
        Container c = getContentPane();
        text = new JTextArea();
        text.addKeyListener(this);
        label = new JLabel();
        c.setLayout(new BorderLayout());
        c.add(text, BorderLayout.CENTER);
        c.add(label, BorderLayout.SOUTH);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(500, 400);
        setVisible(true);
    }

    public void keyTyped(KeyEvent e) {}
    public void keyPressed(KeyEvent e) {
        InputContext ic = text.getInputContext();
        if (ic instanceof sun.awt.im.InputContext) {
            sun.awt.im.InputContext s_ic = (sun.awt.im.InputContext)ic;
            label.setText("IM name: "+s_ic.getInputMethodInfo());
        }
    }
    public void keyReleased(KeyEvent e) {}

    public static void main(String[] args) {
        new InputMethodInfoTest();
        if (false) {
            Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
                                                                public void eventDispatched(AWTEvent e) {
                                                                    System.out.println(e.toString());
                                                                }
                                                            }, /*AWTEvent.KEY_EVENT_MASK*/ 0xFFFFFFFF);
        }
    }
}


SUGGESTED FIX from LICENSEE
---------------------------
Based on JDK 8.

Index: src/windows/native/sun/windows/awt_InputMethod.cpp
===================================================================
--- src/windows/native/sun/windows/awt_InputMethod.cpp        (revision 11359)
+++ src/windows/native/sun/windows/awt_InputMethod.cpp        (revision 11360)
@@ -546,10 +546,10 @@
     jstring infojStr = NULL;
 
     if ((buffSize = ::ImmGetDescription(hkl, szImmDescription, 0)) > 0) {
-        szImmDescription = (LPTSTR) safe_Malloc(buffSize * sizeof(TCHAR));
+        szImmDescription = (LPTSTR) safe_Malloc((buffSize+1) * sizeof(TCHAR));
 
         if (szImmDescription != NULL) {
-            ImmGetDescription(hkl, szImmDescription, buffSize);
+            ImmGetDescription(hkl, szImmDescription, buffSize+1);
 
             infojStr = JNU_NewStringPlatform(env, szImmDescription);