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