Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

518 lines
16 KiB

/*++
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;
}