To: vim-dev@vim.org Subject: Patch 6.0.262 (extra) Fcc: outbox From: Bram Moolenaar MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit ------------ Patch 6.0.262 (extra) Problem: Win32: IME doesn't work properly. OnImeComposition() isn't used at all. Solution: Adjust various things for IME. Files: src/globals.h, src/gui_w32.c, src/mbyte.c, src/proto/ui.pro, src/structs.h, src/ui.c *** ../vim60.261/src/globals.h Thu Feb 21 17:14:51 2002 --- src/globals.h Fri Feb 22 16:07:45 2002 *************** *** 576,581 **** --- 577,586 ---- EXTERN vimconv_T input_conv; /* type of input conversion */ EXTERN vimconv_T output_conv; /* type of output conversion */ + #ifdef FEAT_MBYTE_IME + EXTERN vimconv_T ime_conv; /* ucs-2 -> encoding */ + EXTERN vimconv_T ime_conv_cp; /* codepage -> ucs-2 */ + #endif /* * Function pointers, used to quickly get to the right function. Each has * three possible values: latin_ (8-bit), utfc_ or utf_ (utf-8) and dbcs_ *** ../vim60.261/src/gui_w32.c Mon Feb 4 22:35:33 2002 --- src/gui_w32.c Fri Feb 22 16:16:05 2002 *************** *** 210,215 **** --- 210,219 ---- static int get_toolbar_bitmap(vimmenu_T *menu); #endif + #ifdef FEAT_MBYTE_IME + static LRESULT _OnImeComposition(HWND hwnd, WPARAM dbcs, LPARAM param); + static char_u *GetResultStr(HWND hwnd, int GCS); + #endif #if defined(FEAT_MBYTE_IME) && defined(DYNAMIC_IME) # ifdef NOIME typedef struct tagCOMPOSITIONFORM { *************** *** 221,227 **** # endif HINSTANCE hLibImm = NULL; ! LONG (WINAPI *pImmGetCompositionString)(HIMC, DWORD, LPVOID, DWORD); HIMC (WINAPI *pImmGetContext)(HWND); BOOL (WINAPI *pImmReleaseContext)(HWND, HIMC); BOOL (WINAPI *pImmGetOpenStatus)(HIMC); --- 225,232 ---- # endif HINSTANCE hLibImm = NULL; ! LONG (WINAPI *pImmGetCompositionStringA)(HIMC, DWORD, LPVOID, DWORD); ! LONG (WINAPI *pImmGetCompositionStringW)(HIMC, DWORD, LPVOID, DWORD); HIMC (WINAPI *pImmGetContext)(HWND); BOOL (WINAPI *pImmReleaseContext)(HWND, HIMC); BOOL (WINAPI *pImmGetOpenStatus)(HIMC); *************** *** 232,238 **** BOOL (WINAPI *pImmGetConversionStatus)(HIMC, LPDWORD, LPDWORD); static void dyn_imm_load(void); #else ! # define pImmGetCompositionString ImmGetCompositionStringA # define pImmGetContext ImmGetContext # define pImmReleaseContext ImmReleaseContext # define pImmGetOpenStatus ImmGetOpenStatus --- 237,244 ---- BOOL (WINAPI *pImmGetConversionStatus)(HIMC, LPDWORD, LPDWORD); static void dyn_imm_load(void); #else ! # define pImmGetCompositionStringA ImmGetCompositionStringA ! # define pImmGetCompositionStringW ImmGetCompositionStringW # define pImmGetContext ImmGetContext # define pImmReleaseContext ImmReleaseContext # define pImmGetOpenStatus ImmGetOpenStatus *************** *** 792,797 **** --- 798,808 ---- case WM_IME_NOTIFY: if (!_OnImeNotify(hwnd, (DWORD)wParam, (DWORD)lParam)) return DefWindowProc(hwnd, uMsg, wParam, lParam); + break; + case WM_IME_COMPOSITION: + if (!_OnImeComposition(hwnd, wParam, lParam)) + return DefWindowProc(hwnd, uMsg, wParam, lParam); + break; #endif default: *************** *** 1294,1300 **** #include #include - static char lpCompStr[100]; // Pointer to composition str. static BOOL bInComposition=FALSE; /* --- 1305,1310 ---- *************** *** 1333,1455 **** State &= ~LANGMAP; if (State & INSERT) { ! int old_row, old_col; ! ! /* Save cursor position */ ! old_row = gui.row; ! old_col = gui.col; curbuf->b_p_iminsert = B_IMODE_IM; - // This must be called here before status_redraw_curbuf(), - // otherwise the mode message may appear in the wrong - // position. - showmode(); - #if defined(FEAT_WINDOWS) && defined(FEAT_KEYMAP) ! /* Show/unshow value of 'keymap' in status lines. */ ! status_redraw_curbuf(); #endif - update_screen(0); - - /* Restore cursor position */ - gui.row = old_row; - gui.col = old_col; } } gui_update_cursor(TRUE, FALSE); ! lResult = 1; break; } pImmReleaseContext(hWnd, hImc); return lResult; } ! /* get composition string from WIN_IME */ ! static void ! GetCompositionStr(HWND hwnd, LPARAM CompFlag) { ! DWORD dwBufLen; // Stogare for len. of composition str ! HIMC hIMC; // Input context handle. ! // If fail to get input context handle then do nothing. ! // Applications should call ImmGetContext API to get ! // input context handle. ! if (!pImmGetContext || !(hIMC = pImmGetContext(hwnd))) ! return; ! // Determines how much memory space to store the composition string. ! // Applications should call ImmGetCompositionString with ! // GCS_COMPSTR flag on, buffer length zero, to get the bullfer ! // length. ! if ((dwBufLen = pImmGetCompositionString(hIMC, GCS_COMPSTR, ! (void FAR*)NULL, 0l)) < 0) ! goto exit2; ! if (dwBufLen > 99) ! goto exit2; ! // Reads in the composition string. ! if ( dwBufLen != 0 ) { ! pImmGetCompositionString(hIMC, GCS_COMPSTR, lpCompStr, dwBufLen); ! lpCompStr[dwBufLen] = 0; } else { ! strcpy(lpCompStr, " "); ! dwBufLen = 2; ! } ! // Display new composition chars. ! DisplayCompStringOpaque(lpCompStr, dwBufLen); ! ! exit2: ! pImmReleaseContext(hwnd, hIMC); } ! ! // void GetResultStr() ! // ! // This handles WM_IME_COMPOSITION with GCS_RESULTSTR flag on. ! // ! // get complete composition string ! ! static void ! GetResultStr(HWND hwnd) { ! DWORD dwBufLen; // Storage for length of result str. ! HIMC hIMC; // Input context handle. - // If fail to get input context handle then do nothing. if (!pImmGetContext || !(hIMC = pImmGetContext(hwnd))) ! return; ! ! // Determines how much memory space to store the result string. ! // Applications should call ImmGetCompositionString with ! // GCS_RESULTSTR flag on, buffer length zero, to get the bullfer ! // length. ! if ((dwBufLen = pImmGetCompositionString(hIMC, GCS_RESULTSTR, ! (void FAR *)NULL, (DWORD) 0)) <= 0) ! goto exit2; ! ! if (dwBufLen > 99) ! goto exit2; ! ! // Reads in the result string. ! pImmGetCompositionString(hIMC, GCS_RESULTSTR, lpCompStr, dwBufLen); ! // Displays the result string. ! DisplayCompStringOpaque(lpCompStr, dwBufLen); ! exit2: pImmReleaseContext(hwnd, hIMC); } ! static char * ImeGetTempComposition(void) { if (bInComposition == TRUE) --- 1343,1477 ---- State &= ~LANGMAP; if (State & INSERT) { ! long old_imi = curbuf->b_p_iminsert; curbuf->b_p_iminsert = B_IMODE_IM; #if defined(FEAT_WINDOWS) && defined(FEAT_KEYMAP) ! /* Unshown 'keymap' in status lines */ ! if (old_imi == B_IMODE_LMAP) ! { ! /* Save cursor position */ ! int old_row = gui.row; ! int old_col = gui.col; ! ! // This must be called here before ! // status_redraw_curbuf(), otherwise the mode ! // message may appear in the wrong position. ! showmode(); ! status_redraw_curbuf(); ! update_screen(0); ! /* Restore cursor position */ ! gui.row = old_row; ! gui.col = old_col; ! } #endif } } gui_update_cursor(TRUE, FALSE); ! lResult = 0; break; } pImmReleaseContext(hWnd, hImc); return lResult; } ! static LRESULT ! _OnImeComposition(HWND hwnd, WPARAM dbcs, LPARAM param) { ! char_u *ret; ! if ((param & GCS_RESULTSTR) == 0) /* Composition unfinished. */ ! return 0; ! if (ret = GetResultStr(hwnd, GCS_RESULTSTR)) ! { ! add_to_input_buf_csi(ret, strlen(ret)); ! vim_free(ret); ! return 1; ! } ! else ! return 0; ! } ! /* ! * get the currnet composition string, in UCS-2; len is the number of ! * Unicode characters ! */ ! unsigned short * ! GetCompositionString_inUCS2(HIMC hIMC, DWORD GCS, int *len) ! { ! LONG ret; ! unsigned short *wbuf = NULL; ! if (!pImmGetContext) ! return NULL; /* no imm32.dll */ ! /* Try Unicode; this'll always work on NT regardless of codepage. */ ! ret = pImmGetCompositionStringW(hIMC, GCS, NULL, 0); ! if (ret == 0) ! return NULL; /* empty */ ! if (ret > 0) { ! wbuf = (unsigned short *) alloc(ret * sizeof(unsigned short)); ! if(!wbuf) return NULL; ! pImmGetCompositionStringW(hIMC, GCS, wbuf, ret); ! *len = ret / sizeof(unsigned short); /* char -> wchar */ ! return wbuf; } + /* ret < 0; we got an error, so try the ANSI version. This'll work + * on 9x/ME, but only if the codepage happens to be set to whatever + * we're inputting. */ + ret = pImmGetCompositionStringA(hIMC, GCS, NULL, 0); + if (ret <= 0) + return NULL; /* empty or error */ else { ! char_u *buf; ! buf = alloc(ret); ! if (buf == NULL) ! return NULL; ! pImmGetCompositionStringA(hIMC, GCS, buf, ret); ! /* convert from codepage to UCS-2 */ ! wbuf = (unsigned short *)string_convert(&ime_conv_cp, buf, &ret); ! vim_free(buf); ! *len = ret / sizeof(unsigned short); /* char_u -> wchar */ ! } ! return wbuf; } ! /* ! * void GetResultStr() ! * ! * This handles WM_IME_COMPOSITION with GCS_RESULTSTR flag on. ! * get complete composition string ! */ ! static char_u * ! GetResultStr(HWND hwnd, int GCS) { ! DWORD dwBufLen; /* Stogare for len. of composition str. */ ! HIMC hIMC; /* Input context handle. */ ! unsigned short *buf = NULL; ! char *convbuf = NULL; if (!pImmGetContext || !(hIMC = pImmGetContext(hwnd))) ! return NULL; ! /* Reads in the composition string. */ ! buf = GetCompositionString_inUCS2(hIMC, GCS, &dwBufLen); ! if (buf == NULL) ! return NULL; ! convbuf = string_convert(&ime_conv, (unsigned char *) buf, &dwBufLen); pImmReleaseContext(hwnd, hIMC); + vim_free(buf); + return convbuf; } ! static char_u * ImeGetTempComposition(void) { if (bInComposition == TRUE) *************** *** 1461,1468 **** { pImmGetConversionStatus(hImc, &dwConvMode, &dwSentMode); pImmReleaseContext(s_hwnd, hImc); ! if ((dwConvMode & IME_CMODE_NATIVE)) ! return lpCompStr; } } return NULL; --- 1483,1492 ---- { pImmGetConversionStatus(hImc, &dwConvMode, &dwSentMode); pImmReleaseContext(s_hwnd, hImc); ! if (dwConvMode & IME_CMODE_NATIVE) ! { ! return GetResultStr(s_hwnd, GCS_COMPSTR); ! } } } return NULL; *************** *** 1670,1676 **** HBRUSH hbr; RECT rc; #ifdef FEAT_MBYTE_IME ! char *szComp; #endif if (!(flags & DRAW_TRANSP)) --- 1694,1700 ---- HBRUSH hbr; RECT rc; #ifdef FEAT_MBYTE_IME ! char_u *szComp; #endif if (!(flags & DRAW_TRANSP)) *************** *** 1766,1773 **** --- 1790,1800 ---- /* draw an incomplete composition character (korean) */ if (len == 1 && blink_state == BLINK_ON && (szComp = ImeGetTempComposition()) != NULL) // hangul + { HanExtTextOut(s_hdc, TEXT_X(col), TEXT_Y(row), foptions, pcliprect, szComp, 2, padding, TRUE); + vim_free(szComp); + } else HanExtTextOut(s_hdc, TEXT_X(col), TEXT_Y(row), foptions, pcliprect, (char *)text, len, padding, FALSE); *************** *** 1957,1967 **** POINT p; /* Find the position of the current cursor */ ! GetDCOrgEx(s_hdc,&p); if (curwin != NULL) { ! p.x+= TEXT_X(W_WINCOL(curwin) + curwin->w_wcol +1); ! p.y+= TEXT_Y(W_WINROW(curwin) + curwin->w_wrow +1); } msg_scroll = FALSE; gui_mch_show_popupmenu_at(menu, (int)p.x, (int)p.y); --- 1984,1994 ---- POINT p; /* Find the position of the current cursor */ ! GetDCOrgEx(s_hdc, &p); if (curwin != NULL) { ! p.x += TEXT_X(W_WINCOL(curwin) + curwin->w_wcol + 1); ! p.y += TEXT_Y(W_WINROW(curwin) + curwin->w_wrow + 1); } msg_scroll = FALSE; gui_mch_show_popupmenu_at(menu, (int)p.x, (int)p.y); *************** *** 3336,3344 **** hLibImm = LoadLibrary("imm32.dll"); if (hLibImm == NULL) return; ! if ((*((FARPROC*)&pImmGetCompositionString) = GetProcAddress(hLibImm, "ImmGetCompositionStringA"))) nImmFunc++; if ((*((FARPROC*)&pImmGetContext) = GetProcAddress(hLibImm, "ImmGetContext"))) nImmFunc++; --- 3363,3374 ---- hLibImm = LoadLibrary("imm32.dll"); if (hLibImm == NULL) return; ! if ((*((FARPROC*)&pImmGetCompositionStringA) = GetProcAddress(hLibImm, "ImmGetCompositionStringA"))) nImmFunc++; + if ((*((FARPROC*)&pImmGetCompositionStringW) + = GetProcAddress(hLibImm, "ImmGetCompositionStringW"))) + nImmFunc++; if ((*((FARPROC*)&pImmGetContext) = GetProcAddress(hLibImm, "ImmGetContext"))) nImmFunc++; *************** *** 3364,3370 **** = GetProcAddress(hLibImm, "ImmGetConversionStatus"))) nImmFunc++; ! if (nImmFunc != 9) { FreeLibrary(hLibImm); hLibImm = NULL; --- 3394,3400 ---- = GetProcAddress(hLibImm, "ImmGetConversionStatus"))) nImmFunc++; ! if (nImmFunc != 10) { FreeLibrary(hLibImm); hLibImm = NULL; *** ../vim60.261/src/mbyte.c Thu Feb 7 16:50:47 2002 --- src/mbyte.c Fri Feb 22 16:58:36 2002 *************** *** 572,577 **** --- 572,586 ---- if (enc_utf8 && !option_was_set((char_u *)"fencs")) set_string_option_direct((char_u *)"fencs", -1, (char_u *)"ucs-bom,utf-8,latin1", OPT_FREE); + #ifdef FEAT_MBYTE_IME + # ifdef USE_ICONV + ime_conv.vc_fd = (iconv_t)-1; + ime_conv_cp.vc_fd = (iconv_t)-1; + # endif + convert_setup(&ime_conv, "ucs-2", p_enc); + ime_conv_cp.vc_type = CONV_CODEPAGE; + ime_conv_cp.vc_factor = 2; /* we don't really know anything about the codepage */ + #endif #ifdef HAVE_BIND_TEXTDOMAIN_CODESET /* GNU gettext 0.10.37 supports this feature: set the codeset used for *************** *** 3595,3622 **** add_to_input_buf(str, 3); } - /* - * Add "str[len]" to the input buffer while escaping CSI bytes. - */ - static void - add_to_input_buf_csi(char_u *str, int len) - { - int i; - char_u buf[2]; - - for (i = 0; i < len; ++i) - { - add_to_input_buf(str + i, 1); - if (str[i] == CSI) - { - /* Turn CSI into K_CSI. */ - buf[0] = KS_EXTRA; - buf[1] = (int)KE_CSI; - add_to_input_buf(buf, 2); - } - } - } - static GSList *key_press_event_queue = NULL; static int preedit_buf_len = 0; static gboolean processing_queued_event = FALSE; --- 3611,3616 ---- *************** *** 3953,3958 **** --- 3947,3970 ---- /* Internal utf-8 -> latin1 conversion. */ vcp->vc_type = CONV_TO_LATIN1; } + #ifdef WIN32 + /* Win32-specific UTF-16 -> DBCS conversion, for the IME, + * so we don't need iconv ... */ + else if ((from_prop & ENC_UNICODE) + && (from_prop & ENC_2BYTE) && (to_prop & ENC_DBCS)) + { + vcp->vc_type = CONV_DBCS; + vcp->vc_factor = 2; /* up to twice as long */ + vcp->vc_dbcs = atoi(to + 2); + } + else if ((from_prop & ENC_UNICODE) + && (from_prop & ENC_2BYTE) && (to_prop & ENC_UNICODE)) + { + vcp->vc_type = CONV_DBCS; + vcp->vc_factor = 2; /* up to twice as long */ + vcp->vc_dbcs = CP_UTF8; + } + #endif # ifdef USE_ICONV else { *************** *** 4079,4084 **** --- 4091,4130 ---- retval = iconv_string(vcp->vc_fd, ptr, len); if (retval != NULL && lenp != NULL) *lenp = (int)STRLEN(retval); + break; + # endif + # ifdef WIN32 + case CONV_DBCS: /* UTF-16 -> dbcs or UTF8 */ + { + int retlen; + + if (!lenp) + len /= sizeof(unsigned short); + retlen = WideCharToMultiByte(vcp->vc_dbcs, 0, + (const unsigned short *)ptr, len, 0, 0, 0, 0); + retval = alloc(retlen + 1); + if (retval == NULL) + break; + WideCharToMultiByte(vcp->vc_dbcs, 0, + (const unsigned short *) ptr, len, retval, retlen, 0, 0); + retval[retlen] = NUL; + if (lenp != NULL) + *lenp = retlen; + break; + } + case CONV_CODEPAGE: /* current codepage -> ucs-2 */ + { + int retlen; + + retlen = MultiByteToWideChar(GetACP(), 0, ptr, len, 0, 0); + retval = alloc(sizeof(unsigned short) * retlen); + if (retval == NULL) + break; + MultiByteToWideChar(GetACP(), 0, ptr, len, + (unsigned short *) retval, retlen); + if (lenp != NULL) + *lenp = retlen * sizeof(unsigned short); /* number of shorts -> buffer size */ + } # endif } *** ../vim60.261/src/proto/ui.pro Tue Sep 25 21:49:26 2001 --- src/proto/ui.pro Fri Feb 22 16:28:18 2002 *************** *** 34,39 **** --- 34,40 ---- int vim_free_in_input_buf __ARGS((void)); int vim_used_in_input_buf __ARGS((void)); void add_to_input_buf __ARGS((char_u *s, int len)); + void add_to_input_buf_csi __ARGS((char_u *str, int len)); void push_raw_key __ARGS((char_u *s, int len)); void trash_input_buf __ARGS((void)); int read_from_input_buf __ARGS((char_u *buf, long maxlen)); *** ../vim60.261/src/structs.h Sun Feb 17 23:22:34 2002 --- src/structs.h Fri Feb 22 16:58:41 2002 *************** *** 669,678 **** */ typedef struct { ! int vc_type; /* zero or one of the CONV_ values */ ! int vc_factor; /* max. expansion factor */ # ifdef USE_ICONV ! iconv_t vc_fd; /* for CONV_ICONV */ # endif } vimconv_T; --- 669,681 ---- */ typedef struct { ! int vc_type; /* zero or one of the CONV_ values */ ! int vc_factor; /* max. expansion factor */ ! # ifdef FEAT_WINDOWS ! int vc_dbcs; /* codepage to convert to (CONV_CODEPAGE) */ ! # endif # ifdef USE_ICONV ! iconv_t vc_fd; /* for CONV_ICONV */ # endif } vimconv_T; *************** *** 692,697 **** --- 695,704 ---- #define CONV_TO_UTF8 1 #define CONV_TO_LATIN1 2 #define CONV_ICONV 3 + #ifdef FEAT_WINDOWS + # define CONV_DBCS 4 /* ucs-2 -> dbcs */ + # define CONV_CODEPAGE 5 /* current codepage -> ucs-2 */ + #endif /* * Structure used for mappings and abbreviations. *** ../vim60.261/src/ui.c Fri Feb 22 12:33:04 2002 --- src/ui.c Fri Feb 22 16:28:16 2002 *************** *** 1533,1538 **** --- 1533,1564 ---- } #endif + #if (defined(FEAT_XIM) && defined(FEAT_GUI_GTK)) \ + || (defined(FEAT_MBYTE) && defined(FEAT_MBYTE_IME)) \ + || defined(PROTO) + /* + * Add "str[len]" to the input buffer while escaping CSI bytes. + */ + void + add_to_input_buf_csi(char_u *str, int len) + { + int i; + char_u buf[2]; + + for (i = 0; i < len; ++i) + { + add_to_input_buf(str + i, 1); + if (str[i] == CSI) + { + /* Turn CSI into K_CSI. */ + buf[0] = KS_EXTRA; + buf[1] = (int)KE_CSI; + add_to_input_buf(buf, 2); + } + } + } + #endif + #if defined(FEAT_HANGULIN) || defined(PROTO) void push_raw_key (s, len) *** ../vim60.261/src/version.c Fri Feb 22 14:32:58 2002 --- src/version.c Fri Feb 22 16:54:25 2002 *************** *** 608,609 **** --- 608,611 ---- { /* Add new patch number below this line */ + /**/ + 262, /**/ -- A)bort, R)etry, D)o it right this time /// Bram Moolenaar -- Bram@moolenaar.net -- http://www.moolenaar.net \\\ /// Creator of Vim -- http://vim.sf.net -- ftp://ftp.vim.org/pub/vim \\\ \\\ Project leader for A-A-P -- http://www.a-a-p.org /// \\\ Help me helping AIDS orphans in Uganda - http://iccf-holland.org ///