Windows2003-3790/windows/core/ntcon/conime/consubs.c
2020-09-30 16:53:55 +02:00

773 lines
20 KiB
C

// Copyright (c) 1985 - 1999, Microsoft Corporation
//
// MODULE: ConSubs.c
//
// PURPOSE: Console IME control.
//
// PLATFORMS: Windows NT-FE 3.51
//
// FUNCTIONS:
//
// History:
//
// 27.Jul.1995 v-HirShi (Hirotoshi Shimizu) created
// 10.Jul.1996 v-HirShi (Hirotoshi Shimizu) adupt FE edition
//
// COMMENTS:
//
#include "precomp.h"
#pragma hdrstop
INT
Create( HWND hWnd )
{
ghDefaultIMC = ImmGetContext(hWnd) ;
#ifdef DEBUG_MODE
{
//
// Select fixed pitch system font and get its text metrics
//
HDC hdc;
TEXTMETRIC tm;
WORD patern = 0xA4A4;
SIZE size;
HFONT hfntFixed; // fixed-pitch font
HFONT hfntOld; // default font holder
hdc = GetDC( hWnd );
hfntFixed = GetStockObject( SYSTEM_FIXED_FONT );
hfntOld = SelectObject( hdc, hfntFixed );
GetTextMetrics( hdc, &tm );
GetTextExtentPoint32( hdc, (LPWSTR)&patern, sizeof(WORD), (LPSIZE) &size );
cxMetrics = (UINT) size.cx / 2;
cyMetrics = (UINT) size.cy;
ReleaseDC( hWnd, hdc );
xPos = 0 ;
CaretWidth = GetSystemMetrics( SM_CXBORDER );
}
#endif
return 0;
}
//**********************************************************************
//
// void ImeUIStartComposition()
//
// This handles WM_IME_STARTCOMPOSITION message.
//
//**********************************************************************
void ImeUIStartComposition( HWND hwnd )
{
PCONSOLE_TABLE ConTbl;
ConTbl = SearchConsole(LastConsole);
if (ConTbl == NULL) {
DBGPRINT(("CONIME: Error! Cannot found registed Console\n"));
return;
}
//
// Set fInComposition variables.
//
ConTbl->fInComposition = TRUE;
#ifdef DEBUG_MODE
{
int i ;
for (i = FIRSTCOL ; i < MAXCOL ; i++) {
ConvertLine[i] = UNICODE_SPACE ;
ConvertLineAtr[i] = 0 ;
}
}
#endif
#ifdef DEBUG_INFO
xPos = FIRSTCOL;
xPosLast = FIRSTCOL;
HideCaret( hwnd );
DisplayConvInformation( hwnd ) ;
ResetCaret( hwnd );
#endif
}
//**********************************************************************
//
// void ImeUIEndComposition
//
// This handles WM_IME_ENDCOMPOSITION message.
//
//**********************************************************************
void ImeUIEndComposition( HWND hwnd )
{
PCONSOLE_TABLE ConTbl;
ConTbl = SearchConsole(LastConsole);
if (ConTbl == NULL) {
DBGPRINT(("CONIME: Error! Cannot found registed Console\n"));
return;
}
//
// Reset fInComposition variables.
//
ConTbl->fInComposition = FALSE;
if (ConTbl->lpCompStrMem)
LocalFree( ConTbl->lpCompStrMem );
ConTbl->lpCompStrMem = NULL ;
#ifdef DEBUG_MODE
{
int i ;
//
// Reset the length of composition string to zero.
//
for (i = FIRSTCOL ; i < MAXCOL ; i++) {
ConvertLine[i] = UNICODE_SPACE ;
ConvertLineAtr[i] = 0 ;
}
}
#endif
#ifdef DEBUG_INFO
xPos = FIRSTCOL;
xPosLast = FIRSTCOL;
HideCaret( hwnd );
DisplayConvInformation( hwnd ) ;
ResetCaret( hwnd );
#endif
}
//**********************************************************************
//
// void ImeUIComposition()
//
// This handles WM_IME_COMPOSITION message. It here just handles
// composition string and result string. For normal case, it should
// examine all posibile flags indicated by CompFlag, then do some
// actitions to reflect what kinds of composition info. IME conversion
// engine informs.
//
//**********************************************************************
void ImeUIComposition( HWND hwnd, WPARAM CompChar, LPARAM CompFlag )
{
DBGPRINT(("CONIME: WM_IME_COMPOSITION %08x %08x\n",CompChar,CompFlag));
#ifdef DEBUG_MODE
{
int i ;
for (i = FIRSTCOL ; i < MAXCOL ; i++) {
ConvertLine[i] = UNICODE_SPACE ;
ConvertLineAtr[i] = 0 ;
}
xPos = FIRSTCOL;
xPosLast = FIRSTCOL;
}
#endif
if ( CompFlag == 0 ) {
DBGPRINT((" None\n"));
GetCompositionStr( hwnd, CompFlag, CompChar);
}
if ( CompFlag & GCS_RESULTSTR ) {
DBGPRINT((" GCS_RESULTSTR\n"));
GetCompositionStr( hwnd, ( CompFlag & GCS_RESULTSTR ), CompChar );
}
if ( CompFlag & GCS_COMPSTR ) {
DBGPRINT((" GCS_COMPSTR\n"));
GetCompositionStr( hwnd, ( CompFlag & (GCS_COMPSTR|GCS_COMPATTR)), CompChar);
}
if ( CompFlag & CS_INSERTCHAR ) {
DBGPRINT((" CS_INSERTCHAR\n"));
GetCompositionStr( hwnd, ( CompFlag & (CS_INSERTCHAR|GCS_COMPATTR)), CompChar);
}
if ( CompFlag & CS_NOMOVECARET ) {
DBGPRINT((" CS_NOMOVECARET\n"));
GetCompositionStr( hwnd, ( CompFlag & (CS_NOMOVECARET|GCS_COMPATTR)), CompChar);
}
}
#ifdef DEBUG_INFO
//*********************************************************************
//
// void DisplayCompString()
//
// This displays composition string.
//
// This function send string to Console.
//
//*********************************************************************
void DisplayCompString( HWND hwnd, int Length, PWCHAR CharBuf, PUCHAR AttrBuf )
{
int i;
CopyMemory(ConvertLine, CharBuf, Length * sizeof(WCHAR) ) ;
if ( AttrBuf == NULL ) {
for ( i = 0 ; i < Length ; i++ )
ConvertLineAtr[i] = 0 ;
}
else {
CopyMemory(ConvertLineAtr, AttrBuf, Length) ;
}
HideCaret( hwnd );
DisplayConvInformation( hwnd ) ;
ResetCaret( hwnd );
}
//*********************************************************************
//
// void DisplayResultString()
//
// This displays result string.
//
// This function supports only fixed pitch font.
//
//*********************************************************************
void DisplayResultString( HWND hwnd, LPWSTR lpwStr )
{
int StrLen = lstrlenW( lpwStr );
CopyMemory(ConvertLine, lpwStr, StrLen*sizeof(WCHAR)) ;
HideCaret( hwnd );
DisplayConvInformation( hwnd ) ;
ResetCaret( hwnd );
// gImeUIData.uCompLen = 0;
}
#endif
//**********************************************************************
//
// BOOL ImeUINotify()
//
// This handles WM_IME_NOTIFY message.
//
//**********************************************************************
BOOL ImeUINotify( HWND hwnd, WPARAM wParam, LPARAM lParam )
{
switch (wParam )
{
case IMN_OPENSTATUSWINDOW:
ImeUIOpenStatusWindow(hwnd) ;
break;
case IMN_CHANGECANDIDATE:
ImeUIChangeCandidate( hwnd, (DWORD)lParam );
break;
case IMN_CLOSECANDIDATE:
ImeUICloseCandidate( hwnd, (DWORD)lParam );
break;
case IMN_OPENCANDIDATE:
ImeUIOpenCandidate( hwnd, (DWORD)lParam, TRUE);
break;
case IMN_SETCONVERSIONMODE:
ImeUISetConversionMode(hwnd) ;
// IMN_SETCONVERSIONMODE should be pass to DefWindowProc
// becuase ImeNotifyHandler in User32 does notify to shell and keyboard.
return FALSE;
case IMN_SETOPENSTATUS:
ImeUISetOpenStatus( hwnd );
// IMN_SETOPENSTATUS should be pass to DefWindowProc
// becuase ImeNotifyHandler in User32 does notify to shell and keyboard.
return FALSE;
case IMN_GUIDELINE:
ImeUIGuideLine(hwnd) ;
break;
default:
return FALSE;
}
return TRUE;
}
/***************************************************************************\
* BOOL IsConsoleFullWidth(DWORD CodePage,WCHAR wch)
*
* Determine if the given Unicode char is fullwidth or not.
*
* History:
* 04-08-92 ShunK Created.
* Jul-27-1992 KazuM Added Screen Information and Code Page Information.
* Jan-29-1992 V-Hirots Substruct Screen Information.
* Oct-06-1996 KazuM Not use RtlUnicodeToMultiByteSize and WideCharToMultiByte
* Because 950 only defined 13500 chars,
* and unicode defined almost 18000 chars.
* So there are almost 4000 chars can not be mapped to big5 code.
\***************************************************************************/
BOOL IsUnicodeFullWidth(
IN WCHAR wch
)
{
if (0x20 <= wch && wch <= 0x7e)
/* ASCII */
return FALSE;
else if (0x3041 <= wch && wch <= 0x3094)
/* Hiragana */
return TRUE;
else if (0x30a1 <= wch && wch <= 0x30f6)
/* Katakana */
return TRUE;
else if (0x3105 <= wch && wch <= 0x312c)
/* Bopomofo */
return TRUE;
else if (0x3131 <= wch && wch <= 0x318e)
/* Hangul Elements */
return TRUE;
else if (0xac00 <= wch && wch <= 0xd7a3)
/* Korean Hangul Syllables */
return TRUE;
else if (0xff01 <= wch && wch <= 0xff5e)
/* Fullwidth ASCII variants */
return TRUE;
else if (0xff61 <= wch && wch <= 0xff9f)
/* Halfwidth Katakana variants */
return FALSE;
else if ( (0xffa0 <= wch && wch <= 0xffbe) ||
(0xffc2 <= wch && wch <= 0xffc7) ||
(0xffca <= wch && wch <= 0xffcf) ||
(0xffd2 <= wch && wch <= 0xffd7) ||
(0xffda <= wch && wch <= 0xffdc) )
/* Halfwidth Hangule variants */
return FALSE;
else if (0xffe0 <= wch && wch <= 0xffe6)
/* Fullwidth symbol variants */
return TRUE;
else if (0x4e00 <= wch && wch <= 0x9fa5)
/* Han Ideographic */
return TRUE;
else if (0xf900 <= wch && wch <= 0xfa2d)
/* Han Ideographic Compatibility */
return TRUE;
else
{
#if 0
/*
* Hack this block for I don't know FONT of Console Window.
*
* If you would like perfect result from IsUnicodeFullWidth routine,
* then you should enable this block and
* you should know FONT of Console Window.
*/
INT Width;
TEXTMETRIC tmi;
/* Unknown character */
GetTextMetricsW(hDC, &tmi);
if (IS_ANY_DBCS_CHARSET(tmi.tmCharSet))
tmi.tmMaxCharWidth /= 2;
GetCharWidth32(hDC, wch, wch, &Width);
if (Width == tmi.tmMaxCharWidth)
return FALSE;
else if (Width == tmi.tmMaxCharWidth*2)
return TRUE;
#else
ULONG MultiByteSize;
RtlUnicodeToMultiByteSize(&MultiByteSize, &wch, sizeof(WCHAR));
if (MultiByteSize == 2)
return TRUE ;
else
return FALSE ;
#endif
}
ASSERT(FALSE);
return FALSE;
#if 0
ULONG MultiByteSize;
RtlUnicodeToMultiByteSize(&MultiByteSize, &wch, sizeof(WCHAR));
if (MultiByteSize == 2)
return TRUE ;
else
return FALSE ;
#endif
}
BOOL
ImeUIOpenStatusWindow(
HWND hwnd
)
{
PCONSOLE_TABLE ConTbl;
HIMC hIMC; // Input context handle.
LPCONIME_UIMODEINFO lpModeInfo ;
COPYDATASTRUCT CopyData ;
DBGPRINT(("CONIME: Get IMN_OPENSTATUSWINDOW Message\n"));
ConTbl = SearchConsole(LastConsole);
if (ConTbl == NULL) {
DBGPRINT(("CONIME: Error! Cannot found registed Console\n"));
return FALSE;
}
hIMC = ImmGetContext( hwnd ) ;
if ( hIMC == 0 )
return FALSE;
lpModeInfo = (LPCONIME_UIMODEINFO)LocalAlloc( LPTR, sizeof(CONIME_UIMODEINFO) ) ;
if ( lpModeInfo == NULL) {
ImmReleaseContext( hwnd, hIMC );
return FALSE;
}
ImmGetConversionStatus(hIMC,
(LPDWORD)&ConTbl->dwConversion,
(LPDWORD)&ConTbl->dwSentence) ;
CopyData.dwData = CI_CONIMEMODEINFO ;
CopyData.cbData = sizeof(CONIME_UIMODEINFO) ;
CopyData.lpData = lpModeInfo ;
if (ImeUIMakeInfoString(ConTbl,
lpModeInfo))
{
ConsoleImeSendMessage( ConTbl->hWndCon,
(WPARAM)hwnd,
(LPARAM)&CopyData
) ;
}
LocalFree( lpModeInfo );
ImmReleaseContext( hwnd, hIMC );
return TRUE ;
}
BOOL
ImeUIChangeCandidate(
HWND hwnd,
DWORD lParam
)
{
return ImeUIOpenCandidate( hwnd, lParam, FALSE) ;
}
BOOL
ImeUISetOpenStatus(
HWND hwnd
)
{
PCONSOLE_TABLE ConTbl;
HIMC hIMC; // Input context handle.
LPCONIME_UIMODEINFO lpModeInfo ;
COPYDATASTRUCT CopyData ;
DBGPRINT(("CONIME: Get IMN_SETOPENSTATUS Message\n"));
ConTbl = SearchConsole(LastConsole);
if (ConTbl == NULL) {
DBGPRINT(("CONIME: Error! Cannot found registed Console\n"));
return FALSE;
}
hIMC = ImmGetContext( hwnd ) ;
if ( hIMC == 0 )
return FALSE;
ConTbl->fOpen = GetOpenStatusByCodepage( hIMC, ConTbl ) ;
ImmGetConversionStatus(hIMC,
(LPDWORD)&ConTbl->dwConversion,
(LPDWORD)&ConTbl->dwSentence) ;
if (ConTbl->ScreenBufferSize.X != 0) {
lpModeInfo = (LPCONIME_UIMODEINFO)LocalAlloc( LPTR, sizeof(CONIME_UIMODEINFO)) ;
if ( lpModeInfo == NULL) {
ImmReleaseContext( hwnd, hIMC );
return FALSE;
}
CopyData.dwData = CI_CONIMEMODEINFO ;
CopyData.cbData = sizeof(CONIME_UIMODEINFO) ;
CopyData.lpData = lpModeInfo ;
if (ImeUIMakeInfoString(ConTbl,
lpModeInfo))
{
ConsoleImeSendMessage( ConTbl->hWndCon,
(WPARAM)hwnd,
(LPARAM)&CopyData
) ;
}
LocalFree( lpModeInfo );
}
ImmReleaseContext( hwnd, hIMC );
return TRUE ;
}
BOOL
ImeUISetConversionMode(
HWND hwnd
)
{
PCONSOLE_TABLE ConTbl;
HIMC hIMC; // Input context handle.
LPCONIME_UIMODEINFO lpModeInfo ;
COPYDATASTRUCT CopyData ;
DWORD OldConversion ;
DBGPRINT(("CONIME: Get IMN_SETCONVERSIONMODE Message\n"));
ConTbl = SearchConsole(LastConsole);
if (ConTbl == NULL) {
DBGPRINT(("CONIME: Error! Cannot found registed Console\n"));
return FALSE;
}
hIMC = ImmGetContext( hwnd ) ;
if ( hIMC == 0 )
return FALSE;
lpModeInfo = (LPCONIME_UIMODEINFO)LocalAlloc(LPTR, sizeof(CONIME_UIMODEINFO) ) ;
if ( lpModeInfo == NULL) {
ImmReleaseContext( hwnd, hIMC );
return FALSE;
}
OldConversion = ConTbl->dwConversion ;
ImmGetConversionStatus(hIMC,
(LPDWORD)&ConTbl->dwConversion,
(LPDWORD)&ConTbl->dwSentence) ;
CopyData.dwData = CI_CONIMEMODEINFO ;
CopyData.cbData = sizeof(CONIME_UIMODEINFO) ;
CopyData.lpData = lpModeInfo ;
if (ImeUIMakeInfoString(ConTbl,
lpModeInfo))
{
ConsoleImeSendMessage( ConTbl->hWndCon,
(WPARAM)hwnd,
(LPARAM)&CopyData
) ;
}
LocalFree( lpModeInfo );
ImmReleaseContext( hwnd, hIMC );
return TRUE ;
}
BOOL
ImeUIGuideLine(
HWND hwnd
)
{
PCONSOLE_TABLE ConTbl;
HIMC hIMC ; // Input context handle.
DWORD Level ;
DWORD Index ;
DWORD Length ;
LPCONIME_UIMESSAGE GuideLine ;
COPYDATASTRUCT CopyData ;
DBGPRINT(("CONIME: Get IMN_GUIDELINE Message "));
ConTbl = SearchConsole(LastConsole);
if (ConTbl == NULL) {
DBGPRINT(("CONIME: Error! Cannot found registed Console\n"));
return FALSE;
}
hIMC = ImmGetContext( hwnd ) ;
if ( hIMC == 0 )
return FALSE;
Level = ImmGetGuideLine(hIMC, GGL_LEVEL, NULL, 0) ;
Index = ImmGetGuideLine(hIMC, GGL_INDEX, NULL, 0) ;
Length = ImmGetGuideLine(hIMC, GGL_STRING, NULL, 0) ;
DBGPRINT(("Level=%d Index=%d Length=%d",Level,Index,Length));
if (Length == 0) {
CopyData.dwData = CI_CONIMESYSINFO ;
CopyData.cbData = Length ;
CopyData.lpData = NULL ;
ConsoleImeSendMessage( ConTbl->hWndCon,
(WPARAM)hwnd,
(LPARAM)&CopyData
) ;
}
else{
GuideLine = (LPCONIME_UIMESSAGE)LocalAlloc(LPTR, Length + sizeof(WCHAR)) ;
if (GuideLine == NULL) {
ImmReleaseContext( hwnd, hIMC );
return FALSE;
}
CopyData.dwData = CI_CONIMESYSINFO ;
CopyData.cbData = Length + sizeof(WCHAR) ;
CopyData.lpData = GuideLine ;
Length = ImmGetGuideLine(hIMC, GGL_STRING, GuideLine->String, Length) ;
ConsoleImeSendMessage( ConTbl->hWndCon,
(WPARAM)hwnd,
(LPARAM)&CopyData
) ;
LocalFree( GuideLine ) ;
}
ImmReleaseContext( hwnd, hIMC );
DBGPRINT(("\n"));
return TRUE ;
}
DWORD
GetNLSMode(
HWND hWnd,
HANDLE hConsole
)
{
PCONSOLE_TABLE ConTbl;
HIMC hIMC;
ConTbl = SearchConsole(hConsole);
if (ConTbl == NULL) {
DBGPRINT(("CONIME: Error! Cannot found registed Console\n"));
return 0;
}
hIMC = ImmGetContext( hWnd ) ;
if ( hIMC == (HIMC)NULL )
return IME_CMODE_DISABLE;
ImmGetConversionStatus(hIMC,
&ConTbl->dwConversion,
&ConTbl->dwSentence);
ConTbl->fOpen = GetOpenStatusByCodepage( hIMC, ConTbl ) ;
ImmReleaseContext( hWnd, hIMC );
return ((ConTbl->fOpen ? IME_CMODE_OPEN : 0) + ConTbl->dwConversion);
}
BOOL
SetNLSMode(
HWND hWnd,
HANDLE hConsole,
DWORD fdwConversion
)
{
PCONSOLE_TABLE ConTbl;
HIMC hIMC;
ConTbl = SearchConsole(hConsole);
if (ConTbl == NULL) {
DBGPRINT(("CONIME: Error! Cannot found registed Console\n"));
return FALSE;
}
if (fdwConversion & IME_CMODE_DISABLE)
{
ImmSetActiveContextConsoleIME(hWnd, FALSE) ;
ImmAssociateContext(hWnd, (HIMC)NULL);
ConTbl->hIMC_Current = (HIMC)NULL;
}
else
{
ImmAssociateContext(hWnd, ConTbl->hIMC_Original);
ImmSetActiveContextConsoleIME(hWnd, TRUE) ;
ConTbl->hIMC_Current = ConTbl->hIMC_Original;
}
hIMC = ImmGetContext( hWnd ) ;
if ( hIMC == (HIMC)NULL )
return TRUE;
ConTbl->fOpen =(fdwConversion & IME_CMODE_OPEN) ? TRUE : FALSE ;
ImmSetOpenStatus(hIMC, ConTbl->fOpen);
fdwConversion &= ~(IME_CMODE_DISABLE | IME_CMODE_OPEN);
if (ConTbl->dwConversion != fdwConversion)
{
ConTbl->dwConversion = fdwConversion;
ImmSetConversionStatus(hIMC,
ConTbl->dwConversion,
ConTbl->dwSentence );
}
ImmReleaseContext( hWnd, hIMC );
return TRUE;
}
BOOL
ConsoleCodepageChange(
HWND hWnd,
HANDLE hConsole,
BOOL Output,
WORD CodePage
)
{
PCONSOLE_TABLE ConTbl;
ConTbl = SearchConsole(hConsole);
if (ConTbl == NULL) {
DBGPRINT(("CONIME: Error! Cannot found registed Console\n"));
return FALSE;
}
if (Output)
{
ConTbl->ConsoleOutputCP = CodePage ;
}
else
{
ConTbl->ConsoleCP = CodePage ;
}
return (TRUE) ;
}
BOOL
ImeSysPropertyWindow(
HWND hWnd,
WPARAM wParam,
LPARAM lParam
)
{
PCONSOLE_TABLE ConTbl;
COPYDATASTRUCT CopyData;
ConTbl = SearchConsole(LastConsole);
if (ConTbl == NULL) {
DBGPRINT(("CONIME: Error! Cannot found registed Console\n"));
return FALSE;
}
CopyData.dwData = CI_CONIMEPROPERTYINFO;
CopyData.cbData = sizeof(WPARAM);
CopyData.lpData = &wParam;
ConsoleImeSendMessage( ConTbl->hWndCon,
(WPARAM)hWnd,
(LPARAM)&CopyData
);
return TRUE;
}