Subject: Re: Patch: Win32 IME support
From: Hilary Cheng (hilarycheng@usa.net)
Date: Sun Apr 15 2001 - 08:43:32 CDT
Hi Andrew,
    Is that possible to enable NT AIMME ? Since if we want to enable the users to input
non-english characeter, only AIMME is available.
Regards,
Hilary
Andrew Dunbar ¼g¹D¡G
> Here, finally is my Windows multilingual support including Input
> Methods.
>
> Tested & working:
> * 8 bit encodings:
>   * English: 98 & 2000
>   * Spanish: 98 & 2000
>   * German: 98 & 2000
>   * Czech: 98 & 2000
>   * Greek: 98 & 2000
>   * Russian: 2000
>   * Thai: 2000
> * Unicode encodings:
>   * Georgian: 2000
>   * Hindi: 2000
>   * Sanskrit: 2000
> * Multibyte IMEs
>   * Chinese Traditional: 2000
>   * Chinese Simplified: 2000
>   * Japanese: 2000
>
> Tested & not working:
> * Korean: 2000
>
> Needs testing:
> * Multibyte IMEs on Windows 95/98/ME
> * Unicode IMEs (if such a beast exists?)
> * Big endian NT/2000 8 bit, Multibyte, and Unicode.
>
> I believe there are big problems with the Korean support at least
> on Windows.  The IME returns garbage but so does importing a
> plain text KSC encoded file.  I can't test other Korean encodings
> on my setup.  I'm not sure if this is a problem just for Windows
> AbiWord, all AbiWord implementations, or a libiconv problem.
> Can somebody please look into this?
>
> Also regarding IME support, Chinese and Japanese IMEs only work
> correctly when I set the machine's default language to the language
> I want to check and reboot.  WM_IME_CHAR messages appear to arrive
> with only one byte of the MBCS character unless the IME matches the
> default language on the machine.
> Can somebody more knowlegeable on Windows IMEs please look into this?
> It seems to go against the MSDN documentation I have at my disposal.
>
> Andrew.
>
> --
> http://linguaphile.sourceforge.net
>
>   ------------------------------------------------------------------------
> ? src/af/xap/win/xap_Win32EncodingManager.cpp
> ? src/af/xap/win/xap_Win32EncodingManager.h
> Index: src/af/ev/win/ev_Win32Keyboard.cpp
> ===================================================================
> RCS file: /cvsroot/abi/src/af/ev/win/ev_Win32Keyboard.cpp,v
> retrieving revision 1.23
> diff -u -r1.23 ev_Win32Keyboard.cpp
> --- src/af/ev/win/ev_Win32Keyboard.cpp  2001/02/06 22:53:54     1.23
> +++ src/af/ev/win/ev_Win32Keyboard.cpp  2001/04/15 06:06:49
> @@ -168,6 +168,7 @@
>  {
>         m_hKeyboardLayout = 0;
>         m_iconv = (UT_iconv_t)-1;
> +       m_bIsUnicodeInput = false;
>         remapKeyboard(GetKeyboardLayout(0));
>  }
>
> @@ -179,7 +180,7 @@
>
>  void ev_Win32Keyboard::remapKeyboard(HKL hKeyboardLayout)
>  {
> -       char  szCodePage[10];
> +       char  szCodePage[16];
>
>         if( m_iconv != (UT_iconv_t)-1 )
>         {
> @@ -191,6 +192,17 @@
>                 strcpy( szCodePage, "CP" );
>                 if( GetLocaleInfo( LOWORD( hKeyboardLayout ), LOCALE_IDEFAULTANSICODEPAGE, &szCodePage[2], sizeof( szCodePage ) / sizeof( szCodePage[0] ) - 2 ) )
>                 {
> +                       // Unicode locale?
> +                       if( !strcmp( szCodePage, "CP0" ) )
> +                       {
> +                               m_bIsUnicodeInput = true;
> +                               strcpy( szCodePage, "UCS-2-INTERNAL" );
> +                       }
> +                       else
> +                               m_bIsUnicodeInput = false;
> +
> +                       UT_DEBUGMSG(("New keyboard codepage: %s\n",szCodePage));
> +
>                         m_iconv = UT_iconv_open( "UCS-2-INTERNAL", szCodePage );
>                 }
>
> @@ -371,13 +383,14 @@
>         // an unnamed-virtual-key -- a character key possibly with some sugar on it.
>
>         BYTE keyState[256];
> -       BYTE buffer[2];
> +       WCHAR buffer[2] = {0,0};
>         int count;
>
>         unsigned int scancode = (keyData & 0x00ff0000)>>16;
>         GetKeyboardState(keyState);
> -       count = ToAsciiEx(nVirtKey,scancode,keyState,(WORD *)buffer,0,m_hKeyboardLayout);
>
> +       count = _scanCodeToChars(nVirtKey,scancode,keyState,buffer,sizeof(buffer));
> +
>         if (count == -1)
>         {
>                 // a possible dead-char -- ignore it and wait for possible completed sequence.
> @@ -405,7 +418,7 @@
>                 keyState[VK_RCONTROL] &= ~0x80;
>                 keyState[VK_RMENU] &= ~0x80;
>
> -               count = ToAsciiEx(nVirtKey,scancode,keyState,(WORD *)buffer,0,m_hKeyboardLayout);
> +               count = _scanCodeToChars(nVirtKey,scancode,keyState,buffer,sizeof(buffer));
>
>                 if (count == 1)
>                 {
> @@ -477,7 +490,7 @@
>                 keyState[VK_RCONTROL] &= ~0x80;
>                 keyState[VK_RMENU] &= ~0x80;
>
> -               count = ToAsciiEx(nVirtKey,scancode,keyState,(WORD *)buffer,0,m_hKeyboardLayout);
> +               count = _scanCodeToChars(nVirtKey,scancode,keyState,buffer,sizeof(buffer));
>
>                 if (count == 1)
>                 {
> @@ -499,9 +512,22 @@
>         }
>  }
>
> +bool ev_Win32Keyboard::onIMEChar(AV_View * pView,
> +                                                                       HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
> +{
> +       WCHAR b = wParam;
> +
> +       // 2nd byte of MBCS is in high byte of word
> +       if (wParam & 0xff00)
> +               b = ((BYTE)(wParam >> 8)) | ((BYTE)wParam << 8);
> +
> +       _emitChar(pView,hWnd,iMsg,wParam,lParam,b,0);
> +       return true;
> +}
> +
>  void ev_Win32Keyboard::_emitChar(AV_View * pView,
>                                                                  HWND hWnd, UINT iMsg, WPARAM nVirtKey, LPARAM keyData,
> -                                                                BYTE b, EV_EditModifierState ems)
> +                                                                WCHAR b, EV_EditModifierState ems)
>  {
>         // do the dirty work of pumping this character thru the state machine.
>
> @@ -510,20 +536,24 @@
>         //                       (ems&EV_EMS_CONTROL)?"control":"",
>         //                       (ems&EV_EMS_ALT)?"alt":""));
>
> -       UT_uint16 charData;
> +       UT_uint16 charData[2];
>         if( m_iconv != (UT_iconv_t)-1 )
>         {
>                 // convert to 8bit string and null terminate
>                 size_t len_in, len_out;
>                 const char *In = (const char *)&b;
>                 char *Out = (char *)&charData;
> +
> +               len_in = 2;
> +               len_out = 4;
>
> -               len_in = 1;
> -               len_out = 2;
> -               UT_iconv( m_iconv, &In, &len_in, &Out, &len_out );
> +i              UT_iconv( m_iconv, &In, &len_in, &Out, &len_out );
>         }
>         else
> -               charData = b;
> +       {
> +               charData[0] = b;
> +               charData[1] = 0;
> +       }
>
>         EV_EditMethod * pEM;
>         EV_EditEventMapperResult result = m_pEEM->Keystroke(EV_EKP_PRESS|ems|b,&pEM);
> @@ -545,7 +575,7 @@
>
>         case EV_EEMR_COMPLETE:
>                 UT_ASSERT(pEM);
> -               invokeKeyboardMethod(pView,pEM,&charData,1);
> +               invokeKeyboardMethod(pView,pEM,charData,1);
>                 break;
>
>         case EV_EEMR_INCOMPLETE:
> @@ -608,6 +638,15 @@
>         new_msg.pt.y = 0;
>         TranslateMessage(&new_msg);
>  }
> +
> +int ev_Win32Keyboard::_scanCodeToChars(UINT nVirtKey, UINT wScanCode, CONST PBYTE lpKeyState,
> +                                                                          LPWSTR pwszBuff, int cchBuff)
> +{
> +       if (m_bIsUnicodeInput)
> +               return ToUnicodeEx(nVirtKey,wScanCode,lpKeyState,pwszBuff,cchBuff,0,m_hKeyboardLayout);
> +       else
> +               return ToAsciiEx(nVirtKey,wScanCode,lpKeyState,pwszBuff,0,m_hKeyboardLayout);
> +};
>
>  /*****************************************************************/
>  /*****************************************************************/
> Index: src/af/ev/win/ev_Win32Keyboard.h
> ===================================================================
> RCS file: /cvsroot/abi/src/af/ev/win/ev_Win32Keyboard.h,v
> retrieving revision 1.14
> diff -u -r1.14 ev_Win32Keyboard.h
> --- src/af/ev/win/ev_Win32Keyboard.h    2001/02/06 22:53:54     1.14
> +++ src/af/ev/win/ev_Win32Keyboard.h    2001/04/15 06:06:49
> @@ -37,17 +37,24 @@
>
>         bool onKeyDown(AV_View * pView,
>                                           HWND hWnd, UINT iMsg, WPARAM nVirtKey, LPARAM keyData);
> +
> +       bool onIMEChar(AV_View * pView,
> +                                         HWND hWnd, UINT iMsg, WPARAM nVirtKey, LPARAM keyData);
> +
>         bool onChar(AV_View * pView,
>                                    HWND hWnd, UINT iMsg, WPARAM nVirtKey, LPARAM keyData);
> -
> +
>  protected:
>         EV_EditBits                     _getModifierState(void);
>         void                            _translateMessage(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
>         void                            _emitChar(AV_View * pView,
>                                                                   HWND hWnd, UINT iMsg, WPARAM nVirtKey, LPARAM keyData,
> -                                                                 BYTE b, EV_EditModifierState ems);
> +                                                                 WCHAR b, EV_EditModifierState ems);
> +       int                                     _scanCodeToChars(UINT nVirtKey, UINT wScanCode,
> +                                                                                CONST PBYTE lpKeyState, LPWSTR pwszBuff, int cchBuff);
>         HKL                                     m_hKeyboardLayout;
>         UT_iconv_t                      m_iconv; /* Selected translation to Unicode */
> +       bool                            m_bIsUnicodeInput;
>  };
>
>  #endif /* EV_WIN32KEYBOARD_H */
> Index: src/af/xap/Makefile
> ===================================================================
> RCS file: /cvsroot/abi/src/af/xap/Makefile,v
> retrieving revision 1.60
> diff -u -r1.60 Makefile
> --- src/af/xap/Makefile 2001/04/11 21:40:15     1.60
> +++ src/af/xap/Makefile 2001/04/15 06:06:52
> @@ -80,7 +80,8 @@
>  ifeq ($(ABI_FE), Win32)
>  PLATFORM_OBJS +=       $(OBJDIR)/xap_$(ABI_FE)Slurp.$(OBJ_SUFFIX)              \
>                         $(OBJDIR)/xap_$(ABI_FE)PreviewWidget.$(OBJ_SUFFIX)              \
> -                       $(OBJDIR)/xap_$(ABI_FE)DialogHelper.$(OBJ_SUFFIX)
> +                       $(OBJDIR)/xap_$(ABI_FE)DialogHelper.$(OBJ_SUFFIX)       \
> +                       $(OBJDIR)/xap_$(ABI_FE)EncodingManager.$(OBJ_SUFFIX)
>  endif
>
>  ifdef ABI_OPT_GNOME
> Index: src/af/xap/win/Makefile
> ===================================================================
> RCS file: /cvsroot/abi/src/af/xap/win/Makefile,v
> retrieving revision 1.30
> diff -u -r1.30 Makefile
> --- src/af/xap/win/Makefile     2001/03/07 15:45:45     1.30
> +++ src/af/xap/win/Makefile     2001/04/15 06:06:54
> @@ -39,10 +39,27 @@
>                         xap_Win32Slurp.cpp                      \
>                         xap_Win32Toolbar_Icons.cpp      \
>                         xap_Win32DialogHelper.cpp               \
> -                       xap_Win32Module.cpp
> +                       xap_Win32Module.cpp                     \
> +                       xap_Win32EncodingManager.cpp
>
>  TARGETS=               $(OBJS)
>
>  include $(ABI_ROOT)/src/config/abi_rules.mk
> +
> +# Win32 must build libiconv as a peer, Unix should either
> +# have iconv.h available as part of its C library (GNU libc
> +# systems) or have it installed as part of the libiconv-1.0
> +# package.
> +
> +# Test for iconv in system locations
> +HAVE_ICONV_SYSTEM := $(shell if [ -r /usr/include/iconv.h -o -r /usr/local/include/iconv.h ] ; then echo 1 ; fi)
> +
> +ifeq ($(OS_NAME), WIN32)
> +INCLUDES=              -I$(ABI_XX_ROOT)/../libiconv/include
> +else
> +ifneq ($(HAVE_ICONV_SYSTEM),1)
> +INCLUDES=              -I$(ABI_ROOT)/../libiconv/include
> +endif
> +endif
>
>  build:: $(TARGETS)
> Index: src/af/xap/win/xap_Win32App.cpp
> ===================================================================
> RCS file: /cvsroot/abi/src/af/xap/win/xap_Win32App.cpp,v
> retrieving revision 1.40
> diff -u -r1.40 xap_Win32App.cpp
> --- src/af/xap/win/xap_Win32App.cpp     2001/03/19 04:01:31     1.40
> +++ src/af/xap/win/xap_Win32App.cpp     2001/04/15 06:06:56
> @@ -29,6 +29,7 @@
>  #include "xap_Win32_TB_CFactory.h"
>  #include "xap_Win32Slurp.h"
>  #include "xap_Win32Module.h"
> +#include "xap_Win32EncodingManager.h"
>
>  #ifdef _MSC_VER
>  #pragma warning(disable:4355)  // 'this' used in base member initializer list
> @@ -45,6 +46,9 @@
>         UT_ASSERT(hInstance);
>
>         _setAbiSuiteLibDir();
> +
> +       DELETEP(m_pEncMgr);
> +       m_pEncMgr = new XAP_Win32EncodingManager();
>  }
>
>  XAP_Win32App::~XAP_Win32App(void)
> Index: src/wp/ap/win/ap_Win32Frame.cpp
> ===================================================================
> RCS file: /cvsroot/abi/src/wp/ap/win/ap_Win32Frame.cpp,v
> retrieving revision 1.72
> diff -u -r1.72 ap_Win32Frame.cpp
> --- src/wp/ap/win/ap_Win32Frame.cpp     2001/03/25 07:46:35     1.72
> +++ src/wp/ap/win/ap_Win32Frame.cpp     2001/04/15 06:07:18
> @@ -697,6 +697,12 @@
>         return _showDocument();
>  }
>
> +UT_Error AP_Win32Frame::importDocument(const char * szFilename, int ieft, bool markClean)
> +{
> +  UT_ASSERT(UT_TODO);
> +  return UT_OK;
> +}
> +
>  void AP_Win32Frame::_scrollFuncY(void* pData, UT_sint32 yoff, UT_sint32 /*ylimit*/)
>  {
>         // this is a static callback function and doesn't have a 'this' pointer.
> @@ -1042,6 +1048,13 @@
>         {
>             ev_Win32Keyboard *pWin32Keyboard = static_cast<ev_Win32Keyboard *>(f->m_pKeyboard);
>                 if (pWin32Keyboard->onChar(pView,hwnd,iMsg,wParam,lParam))
> +                       return 0;
> +               return DefWindowProc(hwnd,iMsg,wParam,lParam);
> +       }
> +       case WM_IME_CHAR:
> +       {
> +               ev_Win32Keyboard *pWin32Keyboard = static_cast<ev_Win32Keyboard *>(f->m_pKeyboard);
> +               if (pWin32Keyboard->onIMEChar(pView,hwnd,iMsg,wParam,lParam))
>                         return 0;
>                 return DefWindowProc(hwnd,iMsg,wParam,lParam);
>         }
> Index: src/wp/ap/win/ap_Win32Frame.h
> ===================================================================
> RCS file: /cvsroot/abi/src/wp/ap/win/ap_Win32Frame.h,v
> retrieving revision 1.25
> diff -u -r1.25 ap_Win32Frame.h
> --- src/wp/ap/win/ap_Win32Frame.h       2001/03/17 16:48:57     1.25
> +++ src/wp/ap/win/ap_Win32Frame.h       2001/04/15 06:07:18
> @@ -36,6 +36,7 @@
>         virtual XAP_Frame *                     cloneFrame(void);
>         virtual UT_Error                        loadDocument(const char * szFilename, int ieft);
>         virtual UT_Error                        loadDocument(const char * szFilename, int ieft, bool createNew);
> +       virtual UT_Error                        importDocument(const char * szFilename, int ieft, bool markClean);
>         virtual bool                            initFrameData(void);
>         virtual void                            killFrameData(void);
>
>
>   ------------------------------------------------------------------------
>                                  Name: xap_Win32EncodingManager.h
>    xap_Win32EncodingManager.h    Type: application/x-unknown-content-type-hfile
>                              Encoding: base64
>
>  [Image]
This archive was generated by hypermail 2b25 : Sun Apr 15 2001 - 08:42:30 CDT