inline void handleCandidatesClosed(HWND hwnd) { if(!hwnd||hwnd!=candidateIMEWindow) return; /* Obtain IME context */ HIMC imc = ImmGetContext(hwnd); if (!imc) { candidateIMEWindow=0; nvdaControllerInternal_inputCandidateListUpdate(L"",-1,L""); return; } DWORD count = 0; DWORD len = ImmGetCandidateListCountW(imc, &count); ImmReleaseContext(hwnd, imc); if (!count) { candidateIMEWindow=0; nvdaControllerInternal_inputCandidateListUpdate(L"",-1,L""); } }
static bool handleCandidates(HWND hwnd) { /* Obtain IME context */ HIMC imc = ImmGetContext(hwnd); if (!imc) return false; /* Make sure there is at least one candidate list */ DWORD count = 0; DWORD len = ImmGetCandidateListCountW(imc, &count); if (!count) { ImmReleaseContext(hwnd, imc); return false; } candidateIMEWindow=hwnd; /* Read first candidate list */ CANDIDATELIST* list = (CANDIDATELIST*)malloc(len); ImmGetCandidateList(imc, 0, list, len); ImmReleaseContext(hwnd, imc); /* Determine candidates currently being shown */ DWORD pageEnd = list->dwPageStart + list->dwPageSize; DWORD selection=list->dwSelection-list->dwPageStart; if (list->dwPageSize == 0) { pageEnd = list->dwCount; } else if (pageEnd > list->dwCount) { pageEnd = list->dwCount; } /* Concatenate currently shown candidates into a string */ WCHAR* cand_str = (WCHAR*)malloc(len); WCHAR* ptr = cand_str; for (DWORD n = list->dwPageStart, count = 0; n < pageEnd; ++n) { DWORD offset = list->dwOffset[n]; WCHAR* cand = (WCHAR*)(((char*)list) + offset); size_t clen = wcslen(cand); if (!clen) continue; CopyMemory(ptr, cand, (clen + 1) * sizeof(WCHAR)); if ((n + 1) < pageEnd) ptr[clen] = '\n'; ptr += (clen + 1); ++count; } HKL kbd_layout = GetKeyboardLayout(0); WCHAR filename[MAX_PATH + 1]={0}; ImmGetIMEFileNameW(kbd_layout, filename, MAX_PATH); if(cand_str&&wcslen(cand_str)>0) { nvdaControllerInternal_inputCandidateListUpdate(cand_str,selection,filename); } /* Clean up */ free(cand_str); free(list); return (count > 0); }
static LRESULT handleIMEWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_IME_NOTIFY: if(!hasValidIMEContext(hwnd)) return 0; switch (wParam) { case IMN_SETOPENSTATUS: handleOpenStatus(hwnd); break; case IMN_OPENCANDIDATE: case IMN_CHANGECANDIDATE: PostMessage(hwnd,wm_candidateChange,0,0); break; case IMN_CLOSECANDIDATE: nvdaControllerInternal_inputCandidateListUpdate(L"",-1,L""); break; case IMN_SETCONVERSIONMODE: PostMessage(hwnd,wm_handleIMEConversionModeUpdate,0,0); break; case IMN_PRIVATE: // Needed in XP to support EasyDots IME if (!isUIElementMgrSafe || !isTSFThread(true)) handleReadingStringUpdate(hwnd); break; } break; case WM_IME_COMPOSITION: if(!hasValidIMEContext(hwnd)) return 0; curIMEWindow=hwnd; if(!isTSFThread(true)) {\ if(lParam&GCS_COMPSTR||lParam&GCS_CURSORPOS) { handleComposition(hwnd, wParam, lParam); } } break; case WM_IME_ENDCOMPOSITION: if(!hasValidIMEContext(hwnd)) return 0; if(curIMEWindow==hwnd) { if(handleEndComposition(hwnd, wParam, lParam)) { //Disable further typed character notifications produced by TSF typedCharacter_window=NULL; } curIMEWindow=NULL; } break; case WM_ACTIVATE: case WM_SETFOCUS: if(!hasValidIMEContext(hwnd)) return 0; handleIMEConversionModeUpdate(hwnd,false); if(!isTSFThread(true)) { if (hwnd != GetFocus()) break; handleComposition(hwnd, wParam, lParam); handleCandidates(hwnd); } break; default: break; } return 0; }