|
|
/*++
Copyright (c) 1985 - 1999, Microsoft Corporation
Module Name:
candpos.cpp
Abstract:
This file implements the CCandidatePosition Class.
Author:
Revision History:
Notes:
--*/
#include "private.h"
#include "candpos.h"
#include "a_context.h"
#include "ctxtcomp.h"
HRESULT CCandidatePosition::GetCandidatePosition( OUT RECT* out_rcArea ) { IMTLS *ptls;
ptls = IMTLS_GetOrAlloc(); if (ptls == NULL) return E_FAIL;
HRESULT hr; IMCLock imc(ptls->hIMC); if (FAILED(hr = imc.GetResult())) return hr;
::SetRect(out_rcArea, 0, 0, 0, 0);
LANGID langid; ptls->pAImeProfile->GetLangId(&langid); #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(ptls, 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(ptls, 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
CAImeContext* _pAImeContext = imc->m_pAImeContext; if (_pAImeContext == NULL) return E_FAIL;
//
// Is apps support "query positioning" ?
//
CAImeContext::IME_QUERY_POS qpos; if (SUCCEEDED(_pAImeContext->InquireIMECharPosition(imc, &qpos)) && qpos == CAImeContext::IME_QUERY_POS_YES) { //
// Sure. Support "query positioning".
//
hr = GetRectFromApp(ptls, imc, langid, out_rcArea); if (SUCCEEDED(hr)) return hr; else _pAImeContext->ResetIMECharPosition(imc); }
if ( (PRIMARYLANGID(langid) == LANG_CHINESE) && (imc->cfCandForm[0].dwIndex == -1)) { //
// Assume CHT/CHS's Reading Window Position.
//
hr = GetRectFromHIMC(imc, imc->cfCompForm.dwStyle, &imc->cfCompForm.ptCurrentPos, &imc->cfCompForm.rcArea, out_rcArea); return hr; }
hr = GetRectFromHIMC(imc, imc->cfCandForm[0].dwStyle, &imc->cfCandForm[0].ptCurrentPos, &imc->cfCandForm[0].rcArea, out_rcArea);
return hr; }
HRESULT CCandidatePosition::GetRectFromApp( IN IMTLS* ptls, IN IMCLock& imc, IN LANGID langid, OUT RECT* out_rcArea ) { CAImeContext* _pAImeContext = imc->m_pAImeContext; if (_pAImeContext == NULL) return E_FAIL;
IMECHARPOSITION ip = {0}; ip.dwSize = sizeof(IMECHARPOSITION);
CWCompCursorPos wCursorPosition; HRESULT hr;
if (PRIMARYLANGID(langid) == LANG_JAPANESE && (hr = FindAttributeInCompositionString(imc, ATTR_TARGET_CONVERTED, wCursorPosition)) == S_OK) { ip.dwCharPos = wCursorPosition.GetAt(0); } else { if (SUCCEEDED(hr = GetCursorPosition(imc, wCursorPosition))) { CWCompCursorPos wStartSelection; CWCompCursorPos wEndSelection; if (SUCCEEDED(hr = GetSelection(imc, wStartSelection, wEndSelection))) { ip.dwCharPos = min(wCursorPosition.GetAt(0), wStartSelection.GetAt(0)); } else { ip.dwCharPos = wCursorPosition.GetAt(0); } } else { ip.dwCharPos = 0; } }
if (SUCCEEDED(hr = _pAImeContext->RetrieveIMECharPosition(imc, &ip))) { switch (DocumentDirection(imc)) { 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 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; } else if (dwStyle == CFS_RECT) { 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) { IMTLS *ptls;
ptls = IMTLS_GetOrAlloc(); if (ptls == NULL) return E_FAIL;
//
// We needs rectangle
//
return GetRectFromCompFont(ptls, 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 IMTLS* ptls, IN IMCLock& imc, IN POINT* ptCurrentPos, OUT RECT* out_rcArea ) { HRESULT hr = E_FAIL;
HDC dc = ::GetDC(imc->hWnd); if (dc != NULL) {
LOGFONTA logfont; if (SUCCEEDED(ptls->pAImm->GetCompositionFontA((HIMC)imc, &logfont))) {
HFONT font = ::CreateFontIndirectA( &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 (DocumentDirection(imc)) { 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 (DocumentDirection(imc)) { 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;
CAImeContext* _pAImeContext = imc->m_pAImeContext; if (_pAImeContext != NULL) {
CWCompString wCompString; CWCompAttribute wCompAttribute;
if (SUCCEEDED(hr = _pAImeContext->GetTextAndAttribute((HIMC)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; }
HRESULT CCandidatePosition::GetCursorPosition( IN IMCLock& imc, OUT CWCompCursorPos& wCursorPosition ) { HRESULT hr = E_FAIL;
CAImeContext* _pAImeContext = imc->m_pAImeContext; if (_pAImeContext != NULL) { hr = _pAImeContext->GetCursorPosition((HIMC)imc, &wCursorPosition); }
return hr; }
HRESULT CCandidatePosition::GetSelection( IN IMCLock& imc, OUT CWCompCursorPos& wStartSelection, OUT CWCompCursorPos& wEndSelection ) { HRESULT hr = E_FAIL;
CAImeContext* _pAImeContext = imc->m_pAImeContext; if (_pAImeContext != NULL) { hr = _pAImeContext->GetSelection((HIMC)imc, wStartSelection, wEndSelection); }
return hr; }
|