|
|
/*++
Copyright (c) 2001, Microsoft Corporation
Module Name:
candpos.cpp
Abstract:
This file implements the CCandidatePosition Class.
Author:
Revision History:
Notes:
--*/
#include "private.h"
#include "candpos.h"
#include "ctxtcomp.h"
#include "uicomp.h"
HRESULT CCandidatePosition::GetCandidatePosition( IN IMCLock& imc, IN CicInputContext& CicContext, IN IME_UIWND_STATE uists, IN LANGID langid, OUT RECT* out_rcArea ) { HRESULT hr; ::SetRect(out_rcArea, 0, 0, 0, 0);
#if 0
//
// Simplified Chinese TIP's Candidate window create ic and Push it.
// AIMM can know candidate window status.
// If it opened, we returns position of imc->cfCandForm.
// Not use QueryCharPos() because it returns position of Reading window.
//
if (langid == MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)) { CAImeContext* _pAImeContext = imc->m_pAImeContext; if (_pAImeContext == NULL) return E_FAIL;
if (_pAImeContext->m_fOpenCandidateWindow) { if (imc->cfCandForm[0].dwStyle != CFS_DEFAULT && imc->cfCandForm[0].dwStyle != CFS_EXCLUDE) {
#if 0
//
// Chinese TIP needs rectangle
//
IMECHARPOSITION ip = {0}; ip.dwSize = sizeof(IMECHARPOSITION);
if (QueryCharPos(ptls, imc, &ip)) { //
// Sure. Support "query positioning".
//
RECT rect; hr = GetRectFromApp(imc, &rect); // rect = screen coordinate.
if (SUCCEEDED(hr)) { MapWindowPoints(HWND_DESKTOP, imc->hWnd, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT)); hr = GetRectFromHIMC(imc, CFS_EXCLUDE, &imc->cfCandForm[0].ptCurrentPos, &rect, out_rcArea); if (SUCCEEDED(hr)) return hr; } } #endif
//
// Chinese TIP needs rectangle
//
hr = GetRectFromCompFont(imc, &imc->cfCandForm[0].ptCurrentPos, out_rcArea); if (SUCCEEDED(hr)) return hr;
}
hr = GetRectFromHIMC(imc, imc->cfCandForm[0].dwStyle, &imc->cfCandForm[0].ptCurrentPos, &imc->cfCandForm[0].rcArea, out_rcArea);
return hr; } } #endif
//
// Is apps support "query positioning" ?
//
CicInputContext::IME_QUERY_POS qpos = CicInputContext::IME_QUERY_POS_UNKNOWN;
if (SUCCEEDED(CicContext.InquireIMECharPosition(langid, imc, &qpos)) && qpos == CicInputContext::IME_QUERY_POS_YES) { //
// Sure. Support "query positioning".
//
hr = GetRectFromApp(imc, CicContext, langid, out_rcArea); if (SUCCEEDED(hr)) return hr; else CicContext.ResetIMECharPosition(); }
#if 0
//
// Is apps composition window Level 1 or 2 ?
//
// For Level 1 and 2, there are handled in CInputContextOwnerCallBack::IcoTextExt()
//
IME_UIWND_STATE uists; uists = UIComposition::InquireImeUIWndState(imc); if (uists == IME_UIWND_LEVEL1 || uists == IME_UIWND_LEVEL2) { //
// Get candidate window rectangle from composition
//
DWORD dwCharPos = GetCharPos(imc, langid); hr = UIComposition::GetCandRectFromComposition(imc, langid, dwCharPos, out_rcArea); return hr; } #endif
//
// This apps is Level 3 or unknown, and do not support "query position".
//
if ( (PRIMARYLANGID(langid) == LANG_CHINESE) && (imc->cfCandForm[0].dwIndex == -1 || (uists != IME_UIWND_LEVEL3 && CicContext.m_fOpenCandidateWindow.IsResetFlag()) ) ) { //
// Assume CHT/CHS's Reading Window Position.
//
hr = GetRectFromHIMC(imc, FALSE, imc->cfCompForm.dwStyle, &imc->cfCompForm.ptCurrentPos, &imc->cfCompForm.rcArea, out_rcArea); return hr; }
//
// This apps is Level 3 or unknown, and do not support "query position".
//
if (PRIMARYLANGID(langid) == LANG_KOREAN) { hr = GetRectFromHIMC(imc, TRUE, imc->cfCandForm[0].dwStyle, &imc->cfCandForm[0].ptCurrentPos, &imc->cfCandForm[0].rcArea, out_rcArea); return hr; }
//
// This is workaround for IME_UIWND_UNKNOWN case.
// If WM_IME_STARTCOMPOSITION is not comes in, uists set IME_UIWND_UNKNOWN.
//
if ( (uists == IME_UIWND_UNKNOWN) && // #513458
// If apps specified any cfCandForm, then ctfime should use it.
(imc->cfCandForm[0].dwIndex == -1)) { hr = GetRectFromHIMC(imc, FALSE, imc->cfCompForm.dwStyle, &imc->cfCompForm.ptCurrentPos, &imc->cfCompForm.rcArea, out_rcArea); } else { hr = GetRectFromHIMC(imc, TRUE, imc->cfCandForm[0].dwStyle, &imc->cfCandForm[0].ptCurrentPos, &imc->cfCandForm[0].rcArea, out_rcArea); }
return hr; }
HRESULT CCandidatePosition::GetRectFromApp( IN IMCLock& imc, IN CicInputContext& CicContext, IN LANGID langid, OUT RECT* out_rcArea ) { IMECHARPOSITION ip = {0}; ip.dwSize = sizeof(IMECHARPOSITION); ip.dwCharPos = GetCharPos(imc, langid);
HRESULT hr;
if (SUCCEEDED(hr = CicContext.RetrieveIMECharPosition(imc, &ip))) { switch (imc.GetDirection()) { case DIR_TOP_BOTTOM: ::SetRect(out_rcArea, ip.pt.x - ip.cLineHeight, // left
ip.pt.y, // top
ip.pt.x, // right
max(ip.pt.y, ip.rcDocument.bottom)); // bottom
break; case DIR_BOTTOM_TOP: ::SetRect(out_rcArea, ip.pt.x - ip.cLineHeight, // left
min(ip.pt.y, ip.rcDocument.top), // top
ip.pt.x, // right
ip.pt.y); // bottom
break; case DIR_RIGHT_LEFT: ::SetRect(out_rcArea, min(ip.pt.x, ip.rcDocument.left), // left
ip.pt.y, // top
ip.pt.x, // right
ip.pt.y + ip.cLineHeight); // bottom
break; case DIR_LEFT_RIGHT: ::SetRect(out_rcArea, ip.pt.x, // left
ip.pt.y, // top
max(ip.pt.x, ip.rcDocument.right), // right
ip.pt.y + ip.cLineHeight); // bottom
break; } }
return hr; }
HRESULT CCandidatePosition::GetRectFromHIMC( IN IMCLock& imc, IN BOOL fCandForm, IN DWORD dwStyle, IN POINT* ptCurrentPos, IN RECT* rcArea, OUT RECT* out_rcArea ) { HWND hWnd = imc->hWnd;
POINT pt;
if (dwStyle == CFS_DEFAULT) { ::SystemParametersInfo(SPI_GETWORKAREA, 0, out_rcArea, 0); out_rcArea->left = out_rcArea->right; out_rcArea->top = out_rcArea->bottom; return S_OK; } else if (dwStyle & (CFS_RECT | CFS_POINT | CFS_FORCE_POSITION)) { if (! fCandForm) { return GetRectFromCompFont(imc, ptCurrentPos, out_rcArea); } else { out_rcArea->left = ptCurrentPos->x; out_rcArea->right = ptCurrentPos->x; out_rcArea->top = ptCurrentPos->y; out_rcArea->bottom = ptCurrentPos->y; } } else if (dwStyle == CFS_CANDIDATEPOS) { //
// We needs rectangle
//
return GetRectFromCompFont(imc, ptCurrentPos, out_rcArea); } else if (dwStyle == CFS_EXCLUDE) { GetCandidateArea(imc, dwStyle, ptCurrentPos, rcArea, out_rcArea); }
pt.x = pt.y = 0; ClientToScreen(hWnd, &pt); out_rcArea->left += pt.x; out_rcArea->right += pt.x; out_rcArea->top += pt.y; out_rcArea->bottom += pt.y;
return S_OK; }
HRESULT CCandidatePosition::GetRectFromCompFont( IN IMCLock& imc, IN POINT* ptCurrentPos, OUT RECT* out_rcArea ) { HRESULT hr = E_FAIL;
HDC dc = ::GetDC(imc->hWnd); if (dc != NULL) {
LOGFONT logfont; if (ImmGetCompositionFont((HIMC)imc, &logfont)) {
HFONT font = ::CreateFontIndirect( &logfont ); if (font != NULL) {
HFONT prev_font; prev_font = (HFONT)::SelectObject(dc, font);
TEXTMETRIC metric; if (::GetTextMetrics(dc, &metric)) {
int font_cx = metric.tmMaxCharWidth; int font_cy = metric.tmHeight;
switch (imc.GetDirection()) { case DIR_TOP_BOTTOM: ::SetRect(out_rcArea, ptCurrentPos->x - font_cx, // left
ptCurrentPos->y, // top
ptCurrentPos->x, // right
ptCurrentPos->y + font_cy); // bottom
break; case DIR_BOTTOM_TOP: ::SetRect(out_rcArea, ptCurrentPos->x, // left
ptCurrentPos->y - font_cy, // top
ptCurrentPos->x + font_cx, // right
ptCurrentPos->y); // bottom
break; case DIR_RIGHT_LEFT: ::SetRect(out_rcArea, ptCurrentPos->x - font_cx, // left
ptCurrentPos->y - font_cy, // top
ptCurrentPos->x, // right
ptCurrentPos->y); // bottom
break; case DIR_LEFT_RIGHT: ::SetRect(out_rcArea, ptCurrentPos->x, // left
ptCurrentPos->y, // top
ptCurrentPos->x + font_cx, // right
ptCurrentPos->y + font_cy); // bottom
break; }
POINT pt; pt.x = pt.y = 0; ClientToScreen(imc->hWnd, &pt); out_rcArea->left += pt.x; out_rcArea->right += pt.x; out_rcArea->top += pt.y; out_rcArea->bottom += pt.y;
hr = S_OK; }
::SelectObject(dc, prev_font); ::DeleteObject(font); } }
::ReleaseDC(imc->hWnd, dc); }
return hr; }
/*
* * dwStyle == CFS_EXCLUDE * */
HRESULT CCandidatePosition::GetCandidateArea( IN IMCLock& imc, IN DWORD dwStyle, IN POINT* ptCurrentPos, IN RECT* rcArea, OUT RECT* out_rcArea ) { POINT pt = *ptCurrentPos; RECT rc = *rcArea;
switch (imc.GetDirection()) { case DIR_TOP_BOTTOM: ::SetRect(out_rcArea, min(pt.x, rcArea->left), // left
max(pt.y, rcArea->top), // top
max(pt.x, rcArea->right), // right
rcArea->bottom); // bottom
break; case DIR_BOTTOM_TOP: ::SetRect(out_rcArea, min(pt.x, rcArea->left), // left
rcArea->top, // top
max(pt.x, rcArea->right), // right
min(pt.y, rcArea->bottom)); // bottom
break; case DIR_RIGHT_LEFT: ::SetRect(out_rcArea, rcArea->left, // left
min(pt.y, rcArea->top), // top
min(pt.x, rcArea->right), // right
max(pt.y, rcArea->bottom)); // bottom
break; case DIR_LEFT_RIGHT: ::SetRect(out_rcArea, max(pt.x, rcArea->left), // left
min(pt.y, rcArea->top), // top
rcArea->right, // right
max(pt.y, rcArea->bottom)); // bottom
break; }
return S_OK; }
HRESULT CCandidatePosition::FindAttributeInCompositionString( IN IMCLock& imc, IN BYTE target_attribute, OUT CWCompCursorPos& wCursorPosition ) { HRESULT hr = E_FAIL;
CWCompString wCompString; CWCompAttribute wCompAttribute;
if (SUCCEEDED(hr = EscbGetTextAndAttribute(imc, &wCompString, &wCompAttribute))) {
LONG num_of_written = (LONG)wCompAttribute.ReadCompData(); if (num_of_written == 0) return E_FAIL;
BYTE* attribute = new BYTE[ num_of_written ]; if (attribute != NULL) { //
// Get attribute data.
//
wCompAttribute.ReadCompData(attribute, num_of_written);
LONG start_position = 0;
LONG ich = 0; LONG attr_size = num_of_written; while (ich < attr_size && attribute[ich] != target_attribute) ich++;
if (ich < attr_size) { start_position = ich; } else { //
// If not hit with target_attribute, then returns S_FALSE.
//
hr = S_FALSE; }
wCursorPosition.Set(start_position);
delete [] attribute; } }
return hr; }
DWORD CCandidatePosition::GetCharPos( IMCLock& imc, LANGID langid) { CWCompCursorPos wCursorPosition; HRESULT hr; DWORD dwCharPos = 0;
if (PRIMARYLANGID(langid) == LANG_JAPANESE && (hr = FindAttributeInCompositionString(imc, ATTR_TARGET_CONVERTED, wCursorPosition)) == S_OK) { dwCharPos = wCursorPosition.GetAt(0); } else if (PRIMARYLANGID(langid) == LANG_JAPANESE && (hr = FindAttributeInCompositionString(imc, ATTR_INPUT, wCursorPosition)) == S_OK) { dwCharPos = wCursorPosition.GetAt(0); } else { if (SUCCEEDED(hr = EscbGetCursorPosition(imc, &wCursorPosition))) { CWCompCursorPos wStartSelection; CWCompCursorPos wEndSelection; if (SUCCEEDED(hr = EscbGetStartEndSelection(imc, wStartSelection, wEndSelection))) { dwCharPos = min(wCursorPosition.GetAt(0), wStartSelection.GetAt(0)); } else { dwCharPos = wCursorPosition.GetAt(0); } } else { dwCharPos = 0; } } return dwCharPos; }
|