COMP.C

/**********************************************************************/ 
/* */
/* COMP.C */
/* */
/* Copyright (c) 1995-1997 Microsoft Corporation */
/* */
/**********************************************************************/

#include "windows.h"
#include "imm.h"
#include "resource.h"
#include "imeapps.h"

#define DEBUG 1

LRESULT HandleStartComposition(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
COMPOSITIONFORM cpf;
HIMC hIMC;

#ifdef DEBUG
OutputDebugString("WM_STARTCOMPOSITIONSTRING!!!\r\n");
#endif

if (fdwProperty & IME_PROP_SPECIAL_UI)
{
// Normally, we need to set the composition window
// position to caret position for a special UI IME
}
else if (fdwProperty & IME_PROP_AT_CARET)
{
// If an application show composition string by itself, we do not
// need to set the position of composition window for an at caret
// IME.

return 1;
}
else
{
// Normally, we need to set the composition window
// position to caret position for a near caret IME
}

hIMC = ImmGetContext(hWnd);

if (!hIMC)
{
return 1;
}

cpf.dwStyle = CFS_POINT;
cpf.ptCurrentPos.x = ptImeUIPos.x;
cpf.ptCurrentPos.y = ptImeUIPos.y;

ImmSetCompositionWindow(hIMC,&cpf);

ImmReleaseContext(hWnd,hIMC);

return 1;
}

LRESULT HandleEndComposition(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
#ifdef DEBUG
OutputDebugString("WM_ENDCOMPOSITIONSTRING!!!\r\n");
#endif
dwCompStrLen = 0;
dwCompAttrLen = 0;
dwCompClsLen = 0;
dwCompReadStrLen = 0;
dwCompReadAttrLen = 0;
dwCompReadClsLen = 0;
dwResultStrLen = 0;
dwResultClsLen = 0;
dwResultReadStrLen = 0;
dwResultReadClsLen = 0;
InvalidateRect(hWnd,NULL,TRUE);

return 1;
}

void MakePaintString(HWND hWnd, LPMYSTR lpStr,DWORD dwStrLen,LPDWORD lpCls,DWORD dwClsLen,LPMYSTR lpPaintStr)
{
LPMYSTR lpPaintStart = lpPaintStr;

lpPaintStr += Mylstrlen(lpPaintStr);

if (dwStrLen)
{
if (dwClsLen)
{
lpCls[127] = 0;

while (*(lpCls+1) && *lpCls < dwStrLen)
{
DWORD dwTextLen = *(lpCls+1) - *lpCls;
LPMYSTR lpT = lpStr + *lpCls;

memcpy(lpPaintStr,lpT,dwTextLen * sizeof(MYCHAR));
lpPaintStr += dwTextLen;
*lpPaintStr = MYTEXT(',');
lpPaintStr++;
lpCls++;
}
*lpPaintStr = MYTEXT('\0');
}
else
{
Mylstrcpy(lpPaintStr,lpStr);
Mylstrcat(lpPaintStr,MYTEXT(","));
}
}

}

LRESULT HandleComposition(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
HIMC hIMC;
BOOL fRedraw = FALSE;

hIMC = ImmGetContext(hWnd);

if (lParam & GCS_COMPSTR)
{
dwCompStrLen = MyImmGetCompositionString(hIMC,GCS_COMPSTR,szCompStr,sizeof(szCompStr));
dwCompStrLen /= sizeof(MYCHAR);
szCompStr[dwCompStrLen] = MYTEXT('\0');
fRedraw = TRUE;
}
else
{
dwCompStrLen = 0;
szCompStr[0] = MYTEXT('\0');
}

if (lParam & GCS_COMPATTR)
{
dwCompAttrLen = MyImmGetCompositionString(hIMC,GCS_COMPATTR,bCompAttr,sizeof(bCompAttr));
fRedraw = TRUE;
}
else
{
dwCompAttrLen = 0;
bCompAttr[0] = 0;
}

if (lParam & GCS_COMPCLAUSE)
{
dwCompClsLen = MyImmGetCompositionString(hIMC,GCS_COMPCLAUSE,dwCompCls,sizeof(dwCompCls));
fRedraw = TRUE;
}
else
{
dwCompClsLen = 0;
dwCompCls[0] = 0;
dwCompCls[1] = 0;
}


if (lParam & GCS_COMPREADSTR)
{
dwCompReadStrLen = MyImmGetCompositionString(hIMC,GCS_COMPREADSTR,szCompReadStr,sizeof(szCompReadStr));
dwCompReadStrLen /= sizeof(MYCHAR);
szCompReadStr[dwCompReadStrLen] = MYTEXT('\0');
fRedraw = TRUE;
}
else
{
dwCompReadStrLen = 0;
szCompReadStr[0] = MYTEXT('\0');
}

if (lParam & GCS_COMPREADATTR)
{
dwCompReadAttrLen = MyImmGetCompositionString(hIMC,GCS_COMPREADATTR,bCompReadAttr,sizeof(bCompReadAttr));
fRedraw = TRUE;
}
else
{
dwCompReadAttrLen = 0;
bCompReadAttr[0] = 0;
}

if (lParam & GCS_COMPREADCLAUSE)
{
dwCompReadClsLen = MyImmGetCompositionString(hIMC,GCS_COMPREADCLAUSE,dwCompReadCls,sizeof(dwCompReadCls));
fRedraw = TRUE;
}
else
{
dwCompReadClsLen = 0;
dwCompReadCls[0] = 0;
dwCompReadCls[1] = 0;
}


if (lParam & GCS_RESULTSTR)
{
RECT rc;
HDC hIC;
SIZE sz0,sz1;
HFONT hOldFont;

if (lParam & GCS_RESULTCLAUSE)
{
dwResultClsLen = MyImmGetCompositionString(hIMC,GCS_RESULTCLAUSE,dwResultCls,sizeof(dwResultCls));
}
else
{
dwResultClsLen = 0;
dwResultCls[0] = 0;
dwResultCls[1] = 0;
}

dwResultStrLen = MyImmGetCompositionString(hIMC,GCS_RESULTSTR,szResultStr,sizeof(szResultStr));
dwResultStrLen /= sizeof(MYCHAR);
szResultStr[dwResultStrLen] = MYTEXT('\0');


// szPaintResult may overflow..
GetClientRect(hWnd,&rc);
hIC = CreateIC("DISPLAY", NULL, NULL, NULL);
hOldFont = SelectObject(hIC,hFont);
#ifdef USEWAPI
GetTextExtentPointW(hIC,szPaintResult,Mylstrlen(szPaintResult),&sz0);
GetTextExtentPointW(hIC,szResultStr,Mylstrlen(szResultStr),&sz1);
#else
GetTextExtentPoint(hIC,szPaintResult,Mylstrlen(szPaintResult),&sz0);
GetTextExtentPoint(hIC,szResultStr,Mylstrlen(szResultStr),&sz1);
#endif
if (sz0.cx + sz1.cx >= rc.right)
{
szPaintResult[0] = MYTEXT('\0');
szPaintResultRead[0] = MYTEXT('\0');
}
SelectObject(hIC,hOldFont);
DeleteDC(hIC);

MakePaintString(hWnd,szResultStr,dwResultStrLen,dwResultCls,dwResultClsLen,szPaintResult);

fRedraw = TRUE;
}
else
{
dwResultStrLen = 0;
szResultStr[0] = MYTEXT('\0');
dwResultClsLen = 0;
dwResultCls[0] = 0;
dwResultCls[1] = 0;
}



if (lParam & GCS_RESULTREADSTR)
{
if (lParam & GCS_RESULTREADCLAUSE)
{
dwResultReadClsLen = MyImmGetCompositionString(hIMC,GCS_RESULTREADCLAUSE,dwResultReadCls,sizeof(dwResultReadCls));
fRedraw = TRUE;
}
else
{
dwResultReadClsLen = 0;
dwResultReadCls[0] = 0;
dwResultReadCls[1] = 0;
}
dwResultReadStrLen = MyImmGetCompositionString(hIMC,GCS_RESULTREADSTR,szResultReadStr,sizeof(szResultReadStr));
dwResultReadStrLen /= sizeof(MYCHAR);
szResultReadStr[dwResultReadStrLen] = MYTEXT('\0');
MakePaintString(hWnd,szResultReadStr,dwResultReadStrLen,dwResultReadCls,dwResultReadClsLen,szPaintResultRead);
fRedraw = TRUE;
}
else
{
dwResultReadStrLen = 0;
szResultReadStr[0] = MYTEXT('\0');
dwResultReadClsLen = 0;
dwResultReadCls[0] = 0;
dwResultReadCls[1] = 0;
}



if (fRedraw)
{
InvalidateRect(hWnd,NULL,TRUE);
UpdateWindow(hWnd);
}
return 1;
}


LRESULT HandleChar(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
RECT rc;
HDC hIC;
SIZE sz0,sz1;
HFONT hOldFont;
LPMYSTR lp;
// is the previous received char is a DBCS lead byte char ?
static BOOL fIsPrevLeadByte = FALSE;

GetClientRect(hWnd,&rc);
hIC = CreateIC("DISPLAY", NULL, NULL, NULL);
hOldFont = SelectObject(hIC,hFont);
#ifdef USEWAPI
GetTextExtentPointW(hIC,szPaintResult,Mylstrlen(szPaintResult),&sz0);
GetTextExtentPointW(hIC,szResultStr,Mylstrlen(szResultStr),&sz1);
#else
GetTextExtentPoint(hIC,szPaintResult,Mylstrlen(szPaintResult),&sz0);
GetTextExtentPoint(hIC,szResultStr,Mylstrlen(szResultStr),&sz1);
#endif
if (sz0.cx + sz1.cx >= rc.right)
{
szPaintResult[0] = MYTEXT('\0');
szPaintResultRead[0] = MYTEXT('\0');
}
SelectObject(hIC,hOldFont);
DeleteDC(hIC);

lp = szPaintResult + Mylstrlen(szPaintResult);

#ifndef USEWAPI
if (fIsPrevLeadByte) {
// remove , and append second byte for showing DBCS char
if (*(lp - 1) == ',') {
lp--;
}
}
#endif

// append second byte
*lp++ = (MYCHAR)(BYTE)wParam;
*lp++ = MYTEXT(',');
*lp++ = MYTEXT('\0');

lp = szPaintResultRead + Mylstrlen(szPaintResultRead);

#ifndef USEWAPI
if (fIsPrevLeadByte) {
// remove , and append second byte for showing DBCS char
if (*(lp - 1) == ',') {
lp--;
}

fIsPrevLeadByte = FALSE;
} else {
fIsPrevLeadByte = IsDBCSLeadByte((BYTE)wParam);
}
#endif

*lp++ = (BYTE)wParam;
*lp++ = MYTEXT(',');
*lp++ = MYTEXT('\0');

InvalidateRect(hWnd,NULL,TRUE);
UpdateWindow(hWnd);

return 1;
}


LRESULT HandleNotify(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
HIMC hIMC;
BOOL fOpen;
DWORD dwConvMode,dwSentMode;


switch (wParam)
{
case IMN_OPENSTATUSWINDOW:
case IMN_CLOSESTATUSWINDOW:
break;

case IMN_SETOPENSTATUS:
SetStatusItems(hWnd);

hIMC = ImmGetContext(hWnd);
fOpen = ImmGetOpenStatus(hIMC);
UpdateShowOpenStatusButton(fOpen);

ImmReleaseContext(hWnd,hIMC);
break;

case IMN_SETCONVERSIONMODE:
hIMC = ImmGetContext(hWnd);
fOpen = ImmGetOpenStatus(hIMC);
ImmGetConversionStatus(hIMC,&dwConvMode,&dwSentMode);
if (fOpen)
{
SetConvModeParts(dwConvMode);
UpdateModeButton(dwConvMode);
}
else
ClearConvModeParts();
ImmReleaseContext(hWnd,hIMC);
break;

case IMN_OPENCANDIDATE:
if (!fShowCand || (lParam != 0x01))
{
if (fdwProperty & IME_PROP_SPECIAL_UI)
{
// Normally, we only need to set the composition window
// position for a special UI IME
}
else if (fdwProperty & IME_PROP_AT_CARET)
{
CANDIDATEFORM cdf;
HIMC hIMC;

hIMC = ImmGetContext(hWnd);

cdf.dwIndex = 0;
cdf.dwStyle = CFS_CANDIDATEPOS;
cdf.ptCurrentPos.x = ptImeUIPos.x;
cdf.ptCurrentPos.y = ptImeUIPos.y;
ImmSetCandidateWindow(hIMC,&cdf);

ImmReleaseContext(hWnd,hIMC);
}
else
{
// Normally, we only need to set the composition window
// position for a near caret IME
}

return (DefWindowProc(hWnd, message, wParam, lParam));
}

case IMN_CHANGECANDIDATE:

#ifdef _DEBUG
{
char szDev[80];
DWORD dwSize;
LPCANDIDATELIST lpC;

hIMC = ImmGetContext(hWnd);
if (dwSize = ImmGetCandidateList(hIMC,0x0,NULL,0))
{
lpC = (LPCANDIDATELIST)GlobalAlloc(GPTR,dwSize);

ImmGetCandidateList(hIMC,0x0,lpC,dwSize);

OutputDebugString("DumpCandList!!!\r\n");
wsprintf((LPSTR)szDev,"dwCount %d\r\n",lpC->dwCount);
OutputDebugString((LPSTR)szDev);
wsprintf((LPSTR)szDev,"dwSelection %d\r\n",lpC->dwSelection);
OutputDebugString((LPSTR)szDev);
wsprintf((LPSTR)szDev,"dwPageStart %d\r\n",lpC->dwPageStart);
OutputDebugString((LPSTR)szDev);
wsprintf((LPSTR)szDev,"dwPageSize %d\r\n",lpC->dwPageSize);
OutputDebugString((LPSTR)szDev);
GlobalFree((HANDLE)lpC);
}
}
#endif
if (fShowCand && (lParam == 0x01))
{
DWORD dwSize;

if (!lpCandList)
lpCandList = (LPCANDIDATELIST)GlobalAlloc(GPTR,sizeof(CANDIDATELIST));

hIMC = ImmGetContext(hWnd);
if (dwSize = ImmGetCandidateList(hIMC,0x0,NULL,0))
{
GlobalFree((HANDLE)lpCandList);
lpCandList = (LPCANDIDATELIST)GlobalAlloc(GPTR,dwSize);

ImmGetCandidateList(hIMC,0x0,lpCandList,dwSize);

}
else
{
memset(lpCandList, 0, sizeof(CANDIDATELIST));
}

InvalidateRect(hWndCandList,NULL,TRUE);
UpdateWindow(hWndCandList);


ImmReleaseContext(hWnd,hIMC);
}
else
{
return (DefWindowProc(hWnd, message, wParam, lParam));
}
break;

case IMN_CLOSECANDIDATE:
if (fShowCand && (lParam == 0x01))
{
if (!lpCandList)
lpCandList = (LPCANDIDATELIST)GlobalAlloc(GPTR,sizeof(CANDIDATELIST));

memset(lpCandList, 0, sizeof(CANDIDATELIST));
InvalidateRect(hWndCandList,NULL,TRUE);
UpdateWindow(hWndCandList);
}
else
{
return (DefWindowProc(hWnd, message, wParam, lParam));
}
break;


default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}

return 0;
}