Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

clwinnls.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: clwinnls.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * This module contains all the code for the NT 3.x IMM API functions. 00007 * 00008 * History: 00009 * 11-Jan-1995 wkwok Created. 00010 * 07-May-1996 takaok Cleaned up. 00011 \***************************************************************************/ 00012 00013 #include "precomp.h" 00014 #pragma hdrstop 00015 00016 BOOL CheckCountry(); 00017 BOOL ImmEnableIME( HWND hwnd, BOOL fEnable ); 00018 BOOL IMPGetIMEWorker( HKL hkl, LPIMEPROW lpImeProW ); 00019 VOID ConvertImeProWtoA( LPIMEPROA lpImeProA, LPIMEPROW lpImeProW ); 00020 LRESULT SendIMEMessageAll( HWND hwndApp, HANDLE lParam, BOOL fAnsi ); 00021 00022 BOOL ImmWINNLSEnableIME( 00023 HWND hwndApp, 00024 BOOL bFlag) 00025 { 00026 if ( ! CheckCountry() ) { 00027 SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); 00028 return FALSE; 00029 } 00030 return ImmEnableIME( hwndApp, bFlag ); 00031 } 00032 00033 // 00034 // returns the "enable/disable" state of the 00035 // caller thread's default input context. 00036 // 00037 BOOL ImmWINNLSGetEnableStatus( 00038 HWND hwndApp) 00039 { 00040 if ( ! CheckCountry() ) { 00041 SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); 00042 return FALSE; 00043 } 00044 00045 return (ImmGetSaveContext(hwndApp, IGSC_WINNLSCHECK) != NULL_HIMC); 00046 } 00047 00048 00049 UINT WINAPI ImmWINNLSGetIMEHotkey( 00050 HWND hwndIme) 00051 { 00052 UNREFERENCED_PARAMETER(hwndIme); 00053 00054 // 00055 // Win95/NT3.51 behavior, i.e. always return 0. 00056 // 00057 return 0; 00058 } 00059 00060 00061 /***************************************************************************\ 00062 * 00063 * IME APIs 00064 * 00065 \***************************************************************************/ 00066 00067 LRESULT WINAPI ImmSendIMEMessageExW( 00068 HWND hwndApp, 00069 LPARAM lParam) 00070 { 00071 return SendIMEMessageAll( hwndApp, (HANDLE)lParam, FALSE ); 00072 } 00073 00074 LRESULT WINAPI ImmSendIMEMessageExA( 00075 HWND hwndApp, 00076 LPARAM lParam) 00077 { 00078 return SendIMEMessageAll( hwndApp, (HANDLE)lParam, TRUE ); 00079 } 00080 00081 LRESULT SendIMEMessageAll( 00082 HWND hwndApp, 00083 HANDLE hMemImeStruct, 00084 BOOL fAnsi ) 00085 { 00086 HWND hWnd; 00087 LPIMESTRUCT lpIme; 00088 LRESULT lResult; 00089 00090 #ifdef LATER 00091 // Need for MSTEST30a(32bit)... 00092 // If different process of hWnd in SendIMEMessageEx, then we should be inter-send messag 00093 on this. 00094 if (PtiCurrent() != pti) { 00095 HWND hDefIMEWnd = ImmGetDefaultIMEWnd(hWnd); 00096 if (hDefIMEWnd) 00097 return SendMessage(hDefIMEWnd,WM_CONVERTREQUESTEX,(WPARAM)hWnd,lParam); 00098 } 00099 #endif 00100 00101 // 00102 // the passed handle must be the handle of 00103 // global memory block. 00104 // 00105 lpIme = (LPIMESTRUCT)GlobalLock( hMemImeStruct ); 00106 if ( lpIme == NULL ) { 00107 return (FALSE); 00108 } 00109 00110 if ( ! CheckCountry( ) ) { 00111 00112 lpIme->wParam = IME_RS_INVALID; 00113 GlobalUnlock( hMemImeStruct ); 00114 return (FALSE); 00115 } 00116 00117 // 00118 // We don't need to handle if it's non-IME layout 00119 // 00120 if ( ! ImmIsIME( GetKeyboardLayout(0) ) ) { 00121 00122 lpIme->wParam = IME_RS_INVALID; 00123 GlobalUnlock( hMemImeStruct ); 00124 return (FALSE); 00125 } 00126 00127 // 00128 // check if the initialize of IMM has been done. 00129 // 00130 if ( !IsWindow(ImmGetDefaultIMEWnd(hwndApp)) ) { 00131 // 00132 // for Win3.1/Win95 compatibility 00133 // we need to return TRUE here. 00134 // 00135 // PPT4 calls SendImeMessage at the very 00136 // early stage of initialization. If we 00137 // return FALSE here, it thinks IME is 00138 // not available. 00139 // 00140 if ( lpIme->fnc == 0x07 ) // IME_GETVERSION 00141 // 00142 // Excel5.0J calls this function at the early stage 00143 // and we need to return version number. 00144 // 00145 lResult = IMEVER_31; 00146 else 00147 lResult = TRUE; 00148 00149 GlobalUnlock( hMemImeStruct ); 00150 return lResult; 00151 } 00152 00153 // 00154 // caller may give us NULL window handle... 00155 // 00156 if ( !IsWindow(hwndApp) ) { 00157 hWnd = GetFocus(); 00158 } else { 00159 hWnd = hwndApp; 00160 } 00161 00162 lResult = TranslateIMESubFunctions( hWnd, lpIme, fAnsi ); 00163 GlobalUnlock( hMemImeStruct ); 00164 00165 return lResult; 00166 } 00167 00168 00169 /***************************************************************************\ 00170 * 00171 * IMP APIs 00172 * 00173 \***************************************************************************/ 00174 00175 00176 BOOL WINAPI ImmIMPGetIMEW( 00177 HWND hwndApp, 00178 LPIMEPROW lpImeProW) 00179 { 00180 UNREFERENCED_PARAMETER(hwndApp); 00181 00182 if ( ! CheckCountry() ) { 00183 SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); 00184 return FALSE; 00185 } 00186 return IMPGetIMEWorker( GetKeyboardLayout(0), lpImeProW ); 00187 00188 } 00189 00190 BOOL WINAPI ImmIMPGetIMEA( 00191 HWND hwndApp, 00192 LPIMEPROA lpImeProA) 00193 { 00194 IMEPROW ImeProW; 00195 00196 UNREFERENCED_PARAMETER(hwndApp); 00197 00198 if ( ! CheckCountry() ) { 00199 SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); 00200 return FALSE; 00201 } 00202 if ( IMPGetIMEWorker( GetKeyboardLayout(0), &ImeProW ) ) { 00203 ConvertImeProWtoA( lpImeProA, &ImeProW ); 00204 return TRUE; 00205 } 00206 return FALSE; 00207 } 00208 00209 VOID ConvertImeProWtoA( LPIMEPROA lpImeProA, LPIMEPROW lpImeProW ) 00210 { 00211 lpImeProA->hWnd = lpImeProW->hWnd; 00212 lpImeProA->InstDate = lpImeProW->InstDate; 00213 lpImeProA->wVersion = lpImeProW->wVersion; 00214 00215 WideCharToMultiByte( CP_ACP, 0, 00216 lpImeProW->szDescription, -1, 00217 lpImeProA->szDescription, sizeof(lpImeProA->szName), 00218 NULL, NULL ); 00219 00220 WideCharToMultiByte( CP_ACP, 0, 00221 lpImeProW->szName, -1, 00222 lpImeProA->szName, sizeof(lpImeProA->szName), 00223 NULL, NULL ); 00224 00225 lpImeProA->szOptions[0] = '\0'; 00226 } 00227 00228 DATETIME CleanDate = {0}; 00229 00230 BOOL IMPGetIMEWorker( HKL hkl, LPIMEPROW lpImeProW ) 00231 { 00232 IMEINFOEX iiex; 00233 00234 if ( ImmGetImeInfoEx( &iiex, ImeInfoExKeyboardLayout, (PVOID)&hkl) ) { 00235 00236 lpImeProW->hWnd = NULL; 00237 lpImeProW->InstDate = CleanDate; 00238 lpImeProW->wVersion = iiex.dwImeWinVersion; 00239 lstrcpynW( lpImeProW->szDescription, iiex.wszImeDescription, 50 ); 00240 lstrcpynW( lpImeProW->szName, iiex.wszImeFile, 80 ); 00241 lstrcpynW( lpImeProW->szOptions, TEXT(""), 1 ); 00242 00243 return TRUE; 00244 } 00245 00246 return FALSE; 00247 } 00248 00249 00250 BOOL WINAPI ImmIMPQueryIMEW( 00251 LPIMEPROW lpImeProW) 00252 { 00253 BOOL fResult = FALSE; 00254 INT numLayouts = 0; 00255 HKL *phklRoot = NULL; 00256 HKL *phkl = NULL; 00257 00258 if ( ! CheckCountry() ) { 00259 SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); 00260 return FALSE; 00261 } 00262 00263 // 00264 // get the number of keyboard layouts available 00265 // 00266 numLayouts = GetKeyboardLayoutList( 0, NULL ); 00267 if ( numLayouts > 0 ) { 00268 // 00269 // allocate the buffer for the array of layouts. 00270 // +1 for a NULL sentinel 00271 // 00272 phklRoot = ImmLocalAlloc( 0, (numLayouts+1) * sizeof(HKL) ); 00273 if ( phklRoot != NULL ) { 00274 // 00275 // get the keyboard layouts 00276 // 00277 if ( GetKeyboardLayoutList( numLayouts, phklRoot ) == numLayouts ) { 00278 // 00279 // put a NULL sentinel at the end of the buffer 00280 // 00281 *(phklRoot+numLayouts) = (HKL)NULL; 00282 00283 if ( lpImeProW->szName[0] == L'\0' ) { 00284 // 00285 // This is the first call of IMPQueryIME 00286 // We will start at the first layout. 00287 // 00288 phkl = phklRoot; 00289 00290 } else { 00291 // 00292 // The caller specifies the name of IME. 00293 // We will start at the next layout. 00294 // Note this assumes that the order of keyboard layouts 00295 // returned by GetKeyboardLayoutList() is not changed 00296 // between calls. ( Though actually there is no such 00297 // guarantee, we ignore the chance of the changing 00298 // the list of keyboard layouts for now. ) 00299 // 00300 IMEINFOEX iiex; 00301 // 00302 // Let's retrieve the corresponding hkl 00303 // from the IME filename specified by the caller. 00304 // 00305 if ( ImmGetImeInfoEx( &iiex, 00306 ImeInfoExImeFileName, 00307 (PVOID)lpImeProW->szName ) ) { 00308 // 00309 // let phkl point to the next hkl 00310 // 00311 phkl = phklRoot; 00312 while ( *phkl != NULL ) { 00313 if ( *phkl++ == iiex.hkl ) { 00314 break; 00315 } 00316 } 00317 } 00318 } 00319 if ( phkl != NULL ) { 00320 while ( *phkl != NULL ) { 00321 // 00322 // IMPGetIMEWorker will return FALSE if 00323 // the hkl specified is a non-IME layout. 00324 // 00325 if ( fResult = IMPGetIMEWorker(*phkl++, lpImeProW) ) { 00326 break; 00327 } 00328 } 00329 } 00330 } 00331 ImmLocalFree( phklRoot ); 00332 } 00333 } 00334 return fResult; 00335 } 00336 00337 BOOL WINAPI ImmIMPQueryIMEA( 00338 LPIMEPROA lpImeProA) 00339 { 00340 00341 IMEPROW ImeProW; 00342 00343 if ( ! CheckCountry() ) { 00344 SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); 00345 return FALSE; 00346 } 00347 00348 if ( lpImeProA->szName[0] != '\0' ) { 00349 // 00350 // Convert MultiByteString(szName) to UnicodeString 00351 // 00352 INT i; 00353 00354 i = MultiByteToWideChar( CP_ACP, (DWORD)MB_PRECOMPOSED, 00355 lpImeProA->szName, 00356 -1, 00357 ImeProW.szName, 00358 (INT)sizeof(ImeProW.szName)/sizeof(WCHAR)); 00359 if ( i == 0 ) { 00360 return FALSE; 00361 } 00362 00363 } else { 00364 ImeProW.szName[0] = L'\0'; 00365 } 00366 00367 if ( ImmIMPQueryIMEW( &ImeProW ) ) { 00368 ConvertImeProWtoA( lpImeProA, &ImeProW ); 00369 return TRUE; 00370 } 00371 return FALSE; 00372 } 00373 00374 BOOL WINAPI ImmIMPSetIMEW( 00375 HWND hwndApp, 00376 LPIMEPROW lpImeProW) 00377 { 00378 IMEINFOEX iiex; 00379 HKL hkl = NULL; 00380 00381 UNREFERENCED_PARAMETER(hwndApp); 00382 00383 if ( ! CheckCountry() ) { 00384 SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); 00385 return FALSE; 00386 } 00387 00388 if ( lpImeProW->szName[0] != L'\0' ) { 00389 // 00390 // IME name is specified. Switch to the IME specified. 00391 // 00392 if ( ImmGetImeInfoEx(&iiex,ImeInfoExImeFileName,(PVOID)lpImeProW->szName) ) { 00393 hkl = iiex.hkl; 00394 } 00395 } else { 00396 // 00397 // IME name is not specified. Switch to a non-IME layout 00398 // 00399 INT numLayouts; 00400 HKL *phkl; 00401 HKL *phklRoot; 00402 00403 numLayouts = GetKeyboardLayoutList( 0, NULL ); 00404 if ( numLayouts > 0 ) { 00405 phkl = phklRoot = ImmLocalAlloc( 0, (numLayouts + 1) * sizeof(HKL) ); 00406 if ( phkl != NULL ) { 00407 if ( GetKeyboardLayoutList( numLayouts, phkl ) == numLayouts ) { 00408 *(phklRoot+numLayouts) = (HKL)NULL; 00409 while ( *phkl != NULL ) { 00410 if ( ! ImmIsIME( *phkl ) ) { 00411 hkl = *phkl; 00412 break; 00413 } 00414 phkl++; 00415 } 00416 ImmLocalFree( phklRoot ); 00417 } 00418 } 00419 } 00420 } 00421 00422 if ( hkl != NULL && GetKeyboardLayout(0) != hkl ) { 00423 HWND hwndFocus; 00424 00425 hwndFocus = GetFocus(); 00426 if ( hwndFocus != NULL ) { 00427 PostMessage( hwndFocus, 00428 WM_INPUTLANGCHANGEREQUEST, 00429 DEFAULT_CHARSET, 00430 (LPARAM)hkl); 00431 return TRUE; 00432 } 00433 } 00434 return FALSE; 00435 } 00436 00437 BOOL WINAPI ImmIMPSetIMEA( 00438 HWND hwndApp, 00439 LPIMEPROA lpImeProA) 00440 { 00441 IMEPROW ImeProW; 00442 00443 UNREFERENCED_PARAMETER(hwndApp); 00444 00445 if ( ! CheckCountry() ) { 00446 SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); 00447 return FALSE; 00448 } 00449 00450 if ( lpImeProA->szName[0] != '\0' ) { 00451 // 00452 // Convert MultiByteString(szName) to UnicodeString 00453 // 00454 INT i; 00455 00456 i = MultiByteToWideChar( CP_ACP, (DWORD)MB_PRECOMPOSED, 00457 lpImeProA->szName, 00458 -1, 00459 ImeProW.szName, 00460 (INT)sizeof(ImeProW.szName)/sizeof(WCHAR)); 00461 if ( i == 0 ) { 00462 return FALSE; 00463 } 00464 00465 } else { 00466 ImeProW.szName[0] = L'\0'; 00467 } 00468 return ImmIMPSetIMEW(hwndApp, &ImeProW); 00469 } 00470 00471 // 00472 // if the "enable/disable" state of the default input context 00473 // of the caller thread is same as the state specified by 00474 // fEnalble parameter, this function does nothing but returns 00475 // the current "enable/disable" state. 00476 // 00477 // if fEnable is FALSE, this function disables the default 00478 // input context of caller thread. 00479 // 00480 // if fEnable is TRUE, this function enables the default 00481 // input context of caller thread. 00482 // 00483 // 00484 BOOL ImmEnableIME( 00485 HWND hwnd, 00486 BOOL fEnable 00487 ) 00488 { 00489 HIMC hImc; 00490 PCLIENTIMC pClientImc; 00491 BOOL fCurrentState; 00492 HWND hwndFocus; 00493 BOOL fImeInitialized; 00494 00495 // 00496 // Get the caller thread's default input context 00497 // 00498 hImc = (HIMC)NtUserGetThreadState(UserThreadStateDefaultInputContext); 00499 if ( hImc == NULL_HIMC ) { 00500 return FALSE; 00501 } 00502 pClientImc = ImmLockClientImc( hImc ); 00503 if ( pClientImc == NULL ) { 00504 return FALSE; 00505 } 00506 00507 // 00508 // we will return the curren t"enable/disable" state of the input context 00509 // 00510 fCurrentState = TestICF(pClientImc, IMCF_WINNLSDISABLE) ? FALSE : TRUE; 00511 00512 // 00513 // if the current thread (caller thread) doesn't have the focus window, 00514 // UI windows will not be updated. When we're called later, we will end 00515 // up to just return the fCurrentState without calling ImmSetActiveContext. 00516 // To avoid that, the "same status" check below is disabled... 00517 00518 if ( (fCurrentState && fEnable) || (!fCurrentState && !fEnable) ) { 00519 ImmUnlockClientImc( pClientImc ); 00520 // 00521 // nothing has been changed. return the current state 00522 // 00523 return fCurrentState; 00524 } 00525 00526 00527 if ( ! IsWindow(hwnd) ) { 00528 hwndFocus = GetFocus(); 00529 } else { 00530 hwndFocus = hwnd; 00531 } 00532 00533 // 00534 // check if the initialize of IMM has been done. 00535 // 00536 if ( IsWindow(ImmGetDefaultIMEWnd(hwndFocus)) ) { 00537 fImeInitialized = TRUE; 00538 } else { 00539 fImeInitialized = FALSE; 00540 } 00541 00542 if ( fImeInitialized ) { 00543 if ( ! fEnable ) { 00544 // 00545 // we're going to disable the target IMC 00546 // 00547 // 00548 // make the target IMC non-active 00549 // 00550 ImmSetActiveContext( hwndFocus, hImc, FALSE ); 00551 00552 } else { 00553 // 00554 // we're going to enable the target IMC 00555 // 00556 // 00557 // make NULL context non-active 00558 // 00559 ImmSetActiveContext( hwndFocus, NULL_HIMC, FALSE ); 00560 } 00561 } 00562 00563 // 00564 // update the state of the input context 00565 // 00566 if ( fEnable ) 00567 ClrICF( pClientImc, IMCF_WINNLSDISABLE ); 00568 else 00569 SetICF( pClientImc, IMCF_WINNLSDISABLE ); 00570 ImmUnlockClientImc( pClientImc ); 00571 00572 00573 if ( fImeInitialized ) { 00574 if ( fEnable ) { 00575 // 00576 // we're going to enable the target IMC 00577 // 00578 // 00579 // make the target IMC active 00580 // 00581 ImmSetActiveContext( hwndFocus, hImc, TRUE ); 00582 } else { 00583 // 00584 // we're going to disable the target IMC 00585 // 00586 // 00587 // make NULL context active 00588 // 00589 ImmSetActiveContext( hwndFocus, NULL_HIMC, TRUE ); 00590 } 00591 } 00592 00593 // 00594 // the return value is previous state 00595 // 00596 return fCurrentState; 00597 } 00598 00599 BOOL CheckCountry() 00600 { 00601 WORD LangId; 00602 00603 LangId = PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())); 00604 if ( LangId == LANG_JAPANESE || LangId == LANG_KOREAN ) { 00605 return TRUE; 00606 } 00607 return FALSE; 00608 }

Generated on Sat May 15 19:39:26 2004 for test by doxygen 1.3.7