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

1418 lines
42 KiB
C

// Copyright (c) 1985 - 1999, Microsoft Corporation
//
// MODULE: ConIme.c
//
// PURPOSE: Console IME control.
//
// PLATFORMS: Windows NT-J 3.51
//
// FUNCTIONS:
// WinMain() - calls initialization functions, processes message loop
// WndProc - Processes messages for the main window.
//
// History:
//
// 27.Jul.1995 v-HirShi (Hirotoshi Shimizu) created
//
// COMMENTS:
//
#include "precomp.h"
#pragma hdrstop
// Global Variables
HANDLE LastConsole;
HIMC ghDefaultIMC;
PCONSOLE_TABLE *ConsoleTable;
ULONG NumberOfConsoleTable;
CRITICAL_SECTION ConsoleTableLock; // serialize console table access
#define LockConsoleTable() RtlEnterCriticalSection(&ConsoleTableLock)
#define UnlockConsoleTable() RtlLeaveCriticalSection(&ConsoleTableLock)
BOOL gfDoNotKillFocus;
DWORD dwConsoleThreadId = 0;
#if DBG
ULONG InputExceptionFilter(
PEXCEPTION_POINTERS pexi)
{
if (pexi->ExceptionRecord->ExceptionCode != STATUS_PORT_DISCONNECTED) {
DbgPrint("CONIME: Unexpected exception - %x, pexi = %x\n",
pexi->ExceptionRecord->ExceptionCode, pexi);
DbgBreakPoint();
}
return EXCEPTION_EXECUTE_HANDLER;
}
#else
#define InputExceptionFilter(pexi) EXCEPTION_EXECUTE_HANDLER
#endif
int
APIENTRY
WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
MSG msg;
WCHAR systemPath[MAX_PATH];
if (GetSystemDirectory ( systemPath, MAX_PATH ) > 0 )
SetCurrentDirectory ( systemPath );
#ifdef CUAS_ENABLE
//
// Disable CUAS on the conime.exe process
//
ImmDisableTextFrameService( -1 );
#endif
if (!InitConsoleIME(hInstance) ) {
DBGPRINT(("CONIME: InitConsoleIME failure!\n"));
return FALSE;
}
else {
DBGPRINT(("CONIME: InitConsoleIME successful!\n"));
}
try {
while (TRUE) {
if (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
break;
}
}
} except (InputExceptionFilter(GetExceptionInformation())) {
if (dwConsoleThreadId)
{
DBGPRINT(("CONIME: Exception on WinMain!!\n"));
UnregisterConsoleIME();
dwConsoleThreadId = 0;
}
}
return (int)msg.wParam;
}
BOOL
InitConsoleIME(
HINSTANCE hInstance
)
{
HANDLE hEvent = NULL;
ATOM atom = 0;
HWND hWnd = NULL;
WNDCLASS ConsoleIMEClass;
int cxExecStart;
int cyExecStart;
WCHAR szMenuName[16]; // The name of Menu
WCHAR szClassName[16]; // The class name of this application
WCHAR szTitle[16]; // The title bar text
#ifdef DEBUG_MODE
WCHAR szAppName[16]; // The name of this application
LoadString(hInstance, IDS_TITLE, szTitle, sizeof(szTitle));
#else
szTitle[0] = L'\0';
#endif
DBGPRINT(("CONIME: Enter InitConsoleIMEl!\n"));
RtlInitializeCriticalSection(&ConsoleTableLock);
ConsoleTable = (PCONSOLE_TABLE *)LocalAlloc(LPTR, CONSOLE_INITIAL_TABLE * sizeof(PCONSOLE_TABLE));
if (ConsoleTable == NULL) {
return FALSE;
}
RtlZeroMemory(ConsoleTable, CONSOLE_INITIAL_TABLE * sizeof(PCONSOLE_TABLE));
NumberOfConsoleTable = CONSOLE_INITIAL_TABLE;
// Load the application name and description strings.
LoadString(hInstance, IDS_MENUNAME, szMenuName, sizeof(szMenuName)/sizeof(szMenuName[0]));
LoadString(hInstance, IDS_CLASSNAME, szClassName, sizeof(szClassName)/sizeof(szClassName[0]));
hEvent = OpenEvent(EVENT_MODIFY_STATE, // Access flag
FALSE, // Inherit
CONSOLEIME_EVENT); // Event object name
if (hEvent == NULL)
{
DBGPRINT(("CONIME: OpenEvent failure! %d\n",GetLastError()));
goto ErrorExit;
}
// Fill in window class structure with parameters that describe the
// main window.
ConsoleIMEClass.style = 0; // Class style(s).
ConsoleIMEClass.lpfnWndProc = WndProc; // Window Procedure
ConsoleIMEClass.cbClsExtra = 0; // No per-class extra data.
ConsoleIMEClass.cbWndExtra = 0; // No per-window extra data.
ConsoleIMEClass.hInstance = hInstance; // Owner of this class
ConsoleIMEClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(ID_CONSOLEIME_ICON));
ConsoleIMEClass.hCursor = LoadCursor(NULL, IDC_ARROW); // Cursor
ConsoleIMEClass.hbrBackground = GetStockObject(WHITE_BRUSH); // Default color
ConsoleIMEClass.lpszMenuName = szMenuName; // Menu name from .RC
ConsoleIMEClass.lpszClassName = szClassName; // Class Name
// Register the window class and return FALSE if unsuccesful.
atom = RegisterClass(&ConsoleIMEClass);
if (atom == 0)
{
DBGPRINT(("CONIME: RegisterClass failure! %d\n",GetLastError()));
goto ErrorExit;
}
else {
DBGPRINT(("CONIME: RegisterClass Successful!\n"));
}
// Guess size for now.
cxExecStart = GetSystemMetrics(SM_CXSCREEN);
cyExecStart = GetSystemMetrics(SM_CYMENU);
// Create a main window for this application instance.
hWnd = CreateWindow(szClassName, // See RegisterClass() call.
szTitle, // Text for window title bar.
WS_OVERLAPPEDWINDOW,
cxExecStart - (cxExecStart / 3) ,
cyExecStart ,
cxExecStart / 3 ,
cyExecStart * 10 ,
NULL, // Overlapped has no parent.
NULL, // Use the window class menu.
hInstance,
(LPVOID)NULL);
// If window could not be created, return "failure"
if (hWnd == NULL) {
DBGPRINT(("CONIME: CreateWindow failured! %d\n",GetLastError()));
goto ErrorExit;
}
else{
DBGPRINT(("CONIME: CreateWindow Successful!\n"));
}
if (! RegisterConsoleIME(hWnd, &dwConsoleThreadId))
{
DBGPRINT(("CONIME: RegisterConsoleIME failured! %d\n",GetLastError()));
goto ErrorExit;
}
if (! AttachThreadInput(GetCurrentThreadId(), dwConsoleThreadId, TRUE))
{
DBGPRINT(("CONIME: AttachThreadInput failured! %d\n",GetLastError()));
goto ErrorExit;
}
/*
* dwConsoleThreadId is locked until event sets of hEvent
*/
SetEvent(hEvent);
CloseHandle(hEvent);
#ifdef DEBUG_MODE
LoadString(hInstance, IDS_APPNAME, szAppName, sizeof(szAppName));
// Make the window visible; update its client area; and return "success"
ShowWindow(hWnd, SW_MINIMIZE); // Show the window
SetWindowText(hWnd, szAppName);
UpdateWindow(hWnd); // Sends WM_PAINT message
{
int i;
for (i = 0; i < CVMAX; i++) {
ConvertLine[i] = UNICODE_SPACE;
ConvertLineAtr[i] = 0;
}
xPos = 0;
xPosLast = 0;
}
#endif
return TRUE; // We succeeded...
ErrorExit:
if (dwConsoleThreadId)
UnregisterConsoleIME();
if (hWnd)
DestroyWindow(hWnd);
if (atom)
UnregisterClass(szClassName,hInstance);
if (hEvent)
{
SetEvent(hEvent);
CloseHandle(hEvent);
}
return FALSE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages
//
// PARAMETERS:
// hwnd - window handle
// uMessage - message number
// wparam - additional information (dependant of message number)
// lparam - additional information (dependant of message number)
//
// MESSAGES:
//
// WM_COMMAND - exit command
// WM_DESTROY - destroy window
//
// RETURN VALUE:
//
// Depends on the message number.
//
// COMMENTS:
//
//
LRESULT FAR PASCAL WndProc( HWND hWnd,
UINT Message,
WPARAM wParam,
LPARAM lParam)
{
DWORD dwImmRet = 0; // return value of ImmSrvProcessKey()
try {
switch (Message)
{
case CONIME_CREATE:
DBGPRINT(("CONIME: CONIME_CREATE: Console Handle=%08x\n", wParam));
return InsertNewConsole(hWnd,(HANDLE)wParam,(HWND)lParam);
case CONIME_DESTROY:
DBGPRINT(("CONIME: CONIME_DESTROY: Console Handle=%08x\n", wParam));
return RemoveConsole(hWnd, (HANDLE)wParam);
case CONIME_SETFOCUS:
DBGPRINT(("CONIME: CONIME_SETFOCUS: Console Handle=%08x\n", wParam));
return ConsoleSetFocus(hWnd, (HANDLE)wParam, (HKL)lParam);
case CONIME_KILLFOCUS:
DBGPRINT(("CONIME: CONIME_KILLFOCUS: Console Handle=%08x\n", wParam));
return ConsoleKillFocus(hWnd, (HANDLE)wParam);
case CONIME_GET_NLSMODE:
DBGPRINT(("CONIME: CONIME_GET_NLSMODE: Console Handle=%08x\n", wParam));
return GetNLSMode(hWnd, (HANDLE)wParam);
case CONIME_SET_NLSMODE:
DBGPRINT(("CONIME: CONIME_SET_NLSMODE: Console Handle=%08x\n", wParam));
return SetNLSMode(hWnd, (HANDLE)wParam, (DWORD)lParam);
case CONIME_HOTKEY:
DBGPRINT(("CONIME: CONIME_HOTKEY\n"));
return ConimeHotkey(hWnd, (HANDLE)wParam, (DWORD)lParam);
case CONIME_NOTIFY_VK_KANA:
DBGPRINT(("CONIME: CONIME_NOTIFY_VK_KANA\n"));
return ImeUISetConversionMode(hWnd);
case CONIME_NOTIFY_SCREENBUFFERSIZE: {
COORD ScreenBufferSize;
DBGPRINT(("CONIME: CONIME_NOTIFY_SCREENBUFFERSIZE: Console Handle=%08x\n", wParam));
ScreenBufferSize.X = LOWORD(lParam);
ScreenBufferSize.Y = HIWORD(lParam);
return ConsoleScreenBufferSize(hWnd, (HANDLE)wParam, ScreenBufferSize);
}
case CONIME_INPUTLANGCHANGE: {
DBGPRINT(("CONIME: CONIME_INPUTLANGCHANGE: Console Handle=%08x \n",wParam));
ConImeInputLangchange(hWnd, (HANDLE)wParam, (HKL)lParam );
return TRUE;
}
case CONIME_NOTIFY_CODEPAGE: {
BOOL Output;
WORD Codepage;
Codepage = HIWORD(lParam);
Output = LOWORD(lParam);
DBGPRINT(("CONIME: CONIME_NOTIFY_CODEPAGE: Console Handle=%08x %04x %04x\n",wParam, Output, Codepage));
return ConsoleCodepageChange(hWnd, (HANDLE)wParam, Output, Codepage);
}
case WM_KEYDOWN +CONIME_KEYDATA:
case WM_KEYUP +CONIME_KEYDATA:
case WM_SYSKEYDOWN +CONIME_KEYDATA:
case WM_SYSKEYUP +CONIME_KEYDATA:
case WM_DEADCHAR +CONIME_KEYDATA:
case WM_SYSDEADCHAR+CONIME_KEYDATA:
case WM_SYSCHAR +CONIME_KEYDATA:
case WM_CHAR +CONIME_KEYDATA:
CharHandlerFromConsole( hWnd, Message, (ULONG)wParam, (ULONG)lParam );
break;
case WM_KEYDOWN:
case WM_KEYUP:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_DEADCHAR:
case WM_SYSDEADCHAR:
case WM_SYSCHAR:
case WM_CHAR:
CharHandlerToConsole( hWnd, Message, (ULONG)wParam, (ULONG)lParam );
break;
case WM_INPUTLANGCHANGE:
DBGPRINT(("CONIME: CONIME_INPUTLANGCHANGE: Console Handle=%08x \n",wParam));
InputLangchange(hWnd, (DWORD)wParam, (HKL)lParam );
return TRUE;
case WM_INPUTLANGCHANGEREQUEST:
// Console IME never receive this message for this window is hidden
// and doesn't have focus.
//
// However, Hot key of IME_CHOTKEY_IME_NONIME_TOGGLE/IME_THOTKEY_IME_NONIME_TOGGLE
// are send this message by ImmSimulateHotKey API.
//
// If nothing processing by this message, then DefWindowProc calls
// ActivateKeyboardLayout on kernel side.
// And, ActivateKeyboardLayout send WM_INPUTLANGCHANGE message to focus window
// on this message queue.
// It window is console window procedure.
// Console window procedure can do send CONIME_INPUTLANGCHANGE message to
// console IME window.
// In console window is windowed case, this sequence as well.
// But, In console window is full screen case, message queue have not focus.
// WM_INPUTLANGCHANGE message can not send to console window procedure.
//
// This code avoid console full screen mode problem.
// Send message to console window procedure when this window receive it.
//
{
PCONSOLE_TABLE ConTbl;
ConTbl = SearchConsole(LastConsole);
if (ConTbl == NULL) {
return DefWindowProc(hWnd, Message, wParam, lParam);
}
PostMessage(ConTbl->hWndCon, Message, wParam, lParam);
}
return TRUE; // TRUE : process this message by application
case CONIME_INPUTLANGCHANGEREQUEST:
DBGPRINT(("CONIME: CONIME_INPUTLANGCHANGEREQUEST: Console Handle=%08x \n",wParam));
return ConImeInputLangchangeRequest(hWnd, (HANDLE)wParam, (HKL)lParam, CONIME_DIRECT);
case CONIME_INPUTLANGCHANGEREQUESTFORWARD:
DBGPRINT(("CONIME: CONIME_INPUTLANGCHANGEREQUEST: Console Handle=%08x \n",wParam));
return ConImeInputLangchangeRequest(hWnd, (HANDLE)wParam, (HKL)lParam, CONIME_FORWARD);
case CONIME_INPUTLANGCHANGEREQUESTBACKWARD:
DBGPRINT(("CONIME: CONIME_INPUTLANGCHANGEREQUEST: Console Handle=%08x \n",wParam));
return ConImeInputLangchangeRequest(hWnd, (HANDLE)wParam, (HKL)lParam, CONIME_BACKWARD);
#ifdef DEBUG_MODE
case WM_MOVE:
ImeUIMoveCandWin( hWnd );
break;
case WM_COMMAND: // message: command from application menu
// Message packing of wparam and lparam have changed for Win32,
// so use the GET_WM_COMMAND macro to unpack the commnad
switch (LOWORD(wParam)) {
case MM_EXIT:
PostMessage(hWnd,WM_CLOSE,0,0L);
break;
case MM_ACCESS_VIOLATION:
{
PBYTE p = 0;
*p = 0;
}
break;
}
break;
#endif
case WM_IME_STARTCOMPOSITION:
ImeUIStartComposition( hWnd );
break;
case WM_IME_ENDCOMPOSITION:
ImeUIEndComposition( hWnd );
break;
case WM_IME_COMPOSITION:
ImeUIComposition( hWnd, wParam, lParam );
break;
case WM_IME_COMPOSITIONFULL:
break;
case WM_IME_NOTIFY:
if ( !ImeUINotify( hWnd, wParam, lParam ) ) {
return DefWindowProc(hWnd, Message, wParam, lParam);
}
break;
case WM_IME_SETCONTEXT:
//
// The application have to pass WM_IME_SETCONTEXT to DefWindowProc.
// When the application want to handle the IME at the timing of
// focus changing, the application should use WM_GETFOCUS or
// WM_KILLFOCUS.
//
lParam &= ~ISC_SHOWUIALL;
return DefWindowProc( hWnd, Message, wParam, lParam );
case WM_IME_SYSTEM:
switch (wParam) {
case IMS_CLOSEPROPERTYWINDOW:
case IMS_OPENPROPERTYWINDOW:
ImeSysPropertyWindow(hWnd, wParam, lParam);
break;
default:
return DefWindowProc( hWnd, Message, wParam, lParam );
}
break;
case WM_CREATE:
return Create(hWnd);
break;
case WM_DESTROY:
DBGPRINT(("CONIME:Recieve WM_DESTROY\n"));
ExitList(hWnd);
PostQuitMessage(0);
return 0;
break;
case WM_CLOSE:
DBGPRINT(("CONIME:Recieve WM_CLOSE\n"));
DestroyWindow(hWnd);
return 0;
break;
case WM_ENABLE:{
PCONSOLE_TABLE FocusedConsole;
if (!wParam) {
FocusedConsole = SearchConsole(LastConsole);
if (FocusedConsole != NULL &&
FocusedConsole->hConsole != NULL) {
FocusedConsole->Enable = FALSE;
EnableWindow(FocusedConsole->hWndCon,FALSE);
gfDoNotKillFocus = TRUE;
}
}
else{
DWORD i;
LockConsoleTable();
for ( i = 1; i < NumberOfConsoleTable; i ++){
FocusedConsole = ConsoleTable[i];
if (FocusedConsole != NULL)
{
if ((FocusedConsole->hConsole != NULL)&&
(!FocusedConsole->Enable)&&
(!IsWindowEnabled(FocusedConsole->hWndCon))){
EnableWindow(FocusedConsole->hWndCon,TRUE);
FocusedConsole->Enable = TRUE;
if (!FocusedConsole->LateRemove)
SetForegroundWindow(FocusedConsole->hWndCon);
}
}
}
UnlockConsoleTable();
}
return DefWindowProc(hWnd, Message, wParam, lParam);
break;
}
#ifdef DEBUG_MODE
case WM_SETFOCUS:
CreateCaret( hWnd,
NULL,
IsUnicodeFullWidth( ConvertLine[xPos] ) ?
CaretWidth*2 : CaretWidth,
(UINT)cyMetrics );
SetCaretPos( xPos * cxMetrics, 0 );
ShowCaret( hWnd );
break;
case WM_KILLFOCUS:
HideCaret( hWnd );
DestroyCaret();
break;
case WM_PAINT:
{
PAINTSTRUCT pstruc;
HDC hDC;
hDC = BeginPaint(hWnd,&pstruc);
ReDraw(hWnd);
EndPaint(hWnd,&pstruc);
break;
}
#endif
case WM_QUERYENDSESSION:
#ifdef HIRSHI_DEBUG
/*
* If specified ntsd debugger on this process,
* then never catch WM_QUERYENDSESSION when logoff/shutdown because
* this process will terminate when ntsd process terminated.
*/
{
int i;
i = MessageBox(hWnd,TEXT("Could you approve exit session?"), TEXT("Console IME"),
MB_ICONSTOP | MB_YESNO);
return (i == IDYES ? TRUE : FALSE);
}
#endif
return TRUE; // Logoff or shutdown time.
case WM_ENDSESSION:
DBGPRINT(("CONIME:Recieve WM_ENDSESSION\n"));
ExitList(hWnd);
return 0;
default: // Passes it on if unproccessed
return DefWindowProc(hWnd, Message, wParam, lParam);
}
} except (InputExceptionFilter(GetExceptionInformation())) {
if (dwConsoleThreadId)
{
DBGPRINT(("CONIME: Exception on WndProc!!\n"));
UnregisterConsoleIME();
dwConsoleThreadId = 0;
DestroyWindow(hWnd);
return 0;
}
}
return TRUE;
}
VOID
ExitList(
HWND hWnd
)
{
ULONG i ,j;
PCONSOLE_TABLE FocusedConsole;
DBGPRINT(("CONIME:ExitList Processing\n"));
ImmAssociateContext(hWnd,ghDefaultIMC);
LockConsoleTable();
for (i = 1; i < NumberOfConsoleTable; i++) {
FocusedConsole = ConsoleTable[i];
if (FocusedConsole != NULL)
{
if (FocusedConsole->hConsole != NULL) {
if (FocusedConsole->Enable) {
ImmDestroyContext(FocusedConsole->hIMC_Original);
if ( FocusedConsole->lpCompStrMem != NULL) {
LocalFree( FocusedConsole->lpCompStrMem );
FocusedConsole->lpCompStrMem = NULL;
}
for (j = 0; j < MAX_LISTCAND; j++){
if (FocusedConsole->lpCandListMem[j] != NULL) {
LocalFree(FocusedConsole->lpCandListMem[j]);
FocusedConsole->lpCandListMem[j] = NULL;
FocusedConsole->CandListMemAllocSize[j] = 0;
}
}
if (FocusedConsole->CandSep != NULL) {
LocalFree(FocusedConsole->CandSep);
FocusedConsole->CandSepAllocSize = 0;
}
FocusedConsole->Enable = FALSE;
}
else
FocusedConsole->LateRemove = TRUE;
}
}
}
LocalFree( ConsoleTable );
ConsoleTable = NULL;
UnlockConsoleTable();
if (dwConsoleThreadId)
{
AttachThreadInput(GetCurrentThreadId(), dwConsoleThreadId, FALSE);
UnregisterConsoleIME();
dwConsoleThreadId = 0;
}
}
BOOL
InsertConsole(
HWND hWnd,
HANDLE hConsole,
HWND hWndConsole
)
{
ULONG i;
PCONSOLE_TABLE FocusedConsole;
i = 1;
do {
for (; i < NumberOfConsoleTable; i++) {
FocusedConsole = ConsoleTable[i];
if (FocusedConsole == NULL)
{
FocusedConsole = LocalAlloc(LPTR, sizeof(CONSOLE_TABLE));
if (FocusedConsole == NULL)
return FALSE;
ConsoleTable[i] = FocusedConsole;
}
if ((FocusedConsole->hConsole != NULL) &&
(FocusedConsole->LateRemove)&&
(FocusedConsole->Enable)) {
RemoveConsoleWorker(hWnd, FocusedConsole);
}
if (FocusedConsole->hConsole == NULL) {
RtlZeroMemory(FocusedConsole, sizeof(CONSOLE_TABLE));
FocusedConsole->lphklList = LocalAlloc(LPTR, sizeof(HKL_TABLE)*HKL_INITIAL_TABLE);
if (FocusedConsole->lphklList == NULL)
{
return FALSE;
}
RtlZeroMemory(FocusedConsole->lphklList, sizeof(HKL_TABLE)*HKL_INITIAL_TABLE);
FocusedConsole->hklListMax = HKL_INITIAL_TABLE ;
FocusedConsole->hIMC_Current = ImmCreateContext();
if (FocusedConsole->hIMC_Current == (HIMC)NULL) {
LocalFree(FocusedConsole);
FocusedConsole = NULL;
return FALSE;
}
FocusedConsole->hIMC_Original = FocusedConsole->hIMC_Current;
FocusedConsole->hConsole = hConsole;
FocusedConsole->hWndCon = hWndConsole;
// FocusedConsole->hklActive = NULL;
FocusedConsole->Enable = TRUE;
// FocusedConsole->LateRemove = FALSE;
// FocusedConsole->fNestCandidate = FALSE;
// FocusedConsole->fInComposition = FALSE;
// FocusedConsole->fInCandidate = FALSE;
FocusedConsole->ScreenBufferSize.X = DEFAULT_TEMP_WIDTH;
FocusedConsole->CompAttrColor[0] = DEFAULT_COMP_ENTERED;
FocusedConsole->CompAttrColor[1] = DEFAULT_COMP_ALREADY_CONVERTED;
FocusedConsole->CompAttrColor[2] = DEFAULT_COMP_CONVERSION;
FocusedConsole->CompAttrColor[3] = DEFAULT_COMP_YET_CONVERTED;
FocusedConsole->CompAttrColor[4] = DEFAULT_COMP_INPUT_ERROR;
FocusedConsole->CompAttrColor[5] = DEFAULT_COMP_INPUT_ERROR;
FocusedConsole->CompAttrColor[6] = DEFAULT_COMP_INPUT_ERROR;
FocusedConsole->CompAttrColor[7] = DEFAULT_COMP_INPUT_ERROR;
GetIMEName(FocusedConsole);
return TRUE;
}
}
} while (GrowConsoleTable());
DBGPRINT(("CONIME: Cannot grow Console Table\n"));
return FALSE;
}
BOOL
GrowConsoleTable(
VOID
)
{
PCONSOLE_TABLE *NewTable;
PCONSOLE_TABLE *OldTable;
ULONG MaxConsoleTable;
MaxConsoleTable = NumberOfConsoleTable + CONSOLE_CONSOLE_TABLE_INCREMENT;
NewTable = (PCONSOLE_TABLE *)LocalAlloc(LPTR, MaxConsoleTable * sizeof(PCONSOLE_TABLE));
if (NewTable == NULL) {
return FALSE;
}
CopyMemory(NewTable, ConsoleTable, NumberOfConsoleTable * sizeof(PCONSOLE_TABLE));
OldTable = ConsoleTable;
ConsoleTable = NewTable;
NumberOfConsoleTable = MaxConsoleTable;
LocalFree(OldTable);
return TRUE;
}
PCONSOLE_TABLE
SearchConsole(
HANDLE hConsole
)
{
ULONG i;
PCONSOLE_TABLE FocusedConsole;
LockConsoleTable();
// conime receive ime message from console before 1st console registered.
// this will happen after restart conime when conime dead by bogus ime's AV or
// other problem
// so this fail safe code is necessary to protect consrv.
if (LastConsole == 0) {
LastConsole = hConsole ;
}
for (i = 1; i < NumberOfConsoleTable; i++) {
FocusedConsole = ConsoleTable[i];
if (FocusedConsole != NULL)
{
if ((FocusedConsole->hConsole == hConsole)&&
(!FocusedConsole->LateRemove)) {
UnlockConsoleTable();
return FocusedConsole;
}
}
}
UnlockConsoleTable();
return NULL;
}
BOOL
RemoveConsole(
HWND hwnd,
HANDLE hConsole
)
{
PCONSOLE_TABLE ConTbl;
BOOL ret;
LockConsoleTable();
ConTbl = SearchConsole(hConsole);
if (ConTbl == NULL)
{
UnlockConsoleTable();
return FALSE;
}
ret = RemoveConsoleWorker(hwnd, ConTbl);
UnlockConsoleTable();
return ret;
}
BOOL
RemoveConsoleWorker(
HWND hwnd,
PCONSOLE_TABLE ConTbl
)
{
DWORD j;
if (ConTbl->Enable) {
ConTbl->hConsole = NULL;
ConTbl->ScreenBufferSize.X = 0;
ConTbl->ConsoleCP = 0;
ConTbl->ConsoleOutputCP = 0;
ConTbl->hklActive = 0;
ImmDestroyContext(ConTbl->hIMC_Original);
if (ConTbl->lpCompStrMem != NULL){
LocalFree(ConTbl->lpCompStrMem);
}
for (j = 0; j < MAX_LISTCAND; j++){
if (ConTbl->lpCandListMem[j] != NULL) {
LocalFree(ConTbl->lpCandListMem[j]);
}
}
if (ConTbl->CandSep != NULL) {
LocalFree(ConTbl->CandSep);
}
if (ConTbl->lphklList != NULL) {
LocalFree(ConTbl->lphklList) ;
}
ConTbl->Enable = FALSE;
ConTbl->LateRemove = FALSE;
}
else
ConTbl->LateRemove = TRUE;
#ifdef DEBUG_MODE
InvalidateRect(hwnd,NULL,TRUE);
#endif
return TRUE;
}
BOOL
InsertNewConsole(
HWND hWnd,
HANDLE hConsole,
HWND hWndConsole
)
{
// conime receive ime message from console before 1st console registered.
// this will happen after restart conime when conime dead by bogus ime's AV or
// other problem
// so this fail safe code is necessary to protect consrv.
if (SearchConsole(hConsole) != NULL) {
return TRUE;
}
LockConsoleTable();
if (!InsertConsole(hWnd, hConsole, hWndConsole)) {
UnlockConsoleTable();
return FALSE;
}
#ifdef DEBUG_MODE
DisplayInformation(hWnd, hConsole);
#endif
ImeUISetOpenStatus( hWndConsole );
UnlockConsoleTable();
return TRUE;
}
BOOL
ConsoleSetFocus(
HWND hWnd,
HANDLE hConsole,
HKL hKL
)
{
PCONSOLE_TABLE ConTbl;
HKL OldhKL;
ConTbl = SearchConsole(hConsole);
if (ConTbl == NULL) {
DBGPRINT(("CONIME: Error! Cannot found registed Console\n"));
return FALSE;
}
if ( gfDoNotKillFocus ){
gfDoNotKillFocus = FALSE;
}
OldhKL = ConTbl->hklActive ;
ConTbl->hklActive = hKL;
ActivateKeyboardLayout(ConTbl->hklActive, 0);
ImmAssociateContext(hWnd, ConTbl->hIMC_Current);
if (OldhKL == 0) {
GetIMEName( ConTbl );
ConTbl->ImmGetProperty = ImmGetProperty(ConTbl->hklActive , IGP_PROPERTY);
}
//v-hirshi Jun.13.1996 #if defined(LATER_DBCS) // kazum
ImmSetActiveContextConsoleIME(hWnd, TRUE);
//v-hirshi Jun.13.1996 #endif
LastConsole = hConsole;
#ifdef DEBUG_MODE
DisplayInformation(hWnd, hConsole);
#endif
ImeUISetOpenStatus( hWnd );
if (ConTbl->lpCompStrMem != NULL)
ReDisplayCompositionStr( hWnd );
return TRUE;
}
BOOL
ConsoleKillFocus(
HWND hWnd,
HANDLE hConsole
)
{
PCONSOLE_TABLE ConTbl;
ConTbl = SearchConsole(hConsole);
if (ConTbl == NULL) {
DBGPRINT(("CONIME: Error! Cannot found registed Console\n"));
return FALSE;
}
if ( gfDoNotKillFocus ){
gfDoNotKillFocus = FALSE;
}
else{
//v-hirshi Jun.13.1996 #if defined(LATER_DBCS) // kazum
ImmSetActiveContextConsoleIME(hWnd, FALSE);
//v-hirshi Jun.13.1996 #endif
ImmAssociateContext(hWnd, ghDefaultIMC);
}
#ifdef DEBUG_MODE
DisplayInformation(hWnd, hConsole);
#endif
return TRUE;
}
BOOL
ConsoleScreenBufferSize(
HWND hWnd,
HANDLE hConsole,
COORD ScreenBufferSize
)
{
PCONSOLE_TABLE ConTbl;
ConTbl = SearchConsole(hConsole);
if (ConTbl == NULL) {
DBGPRINT(("CONIME: Error! Cannot found registed Console\n"));
return FALSE;
}
ConTbl->ScreenBufferSize = ScreenBufferSize;
return TRUE;
}
BOOL
ConImeInputLangchangeRequest(
HWND hWnd,
HANDLE hConsole,
HKL hkl,
int Direction
)
{
PCONSOLE_TABLE ConTbl;
int nLayouts;
LPHKL lphkl;
DWORD RequiredLID = 0;
int StartPos;
int CurrentHklPos;
int i;
ConTbl = SearchConsole(hConsole);
if (ConTbl == NULL) {
DBGPRINT(("CONIME: cannot find registered Console\n"));
return FALSE;
}
switch (ConTbl->ConsoleOutputCP) {
case JAPAN_CODEPAGE:
RequiredLID = LANG_ID_JAPAN;
break;
case PRC_CODEPAGE:
RequiredLID = LANG_ID_PRC;
break;
case KOREA_CODEPAGE:
RequiredLID = LANG_ID_KOREA;
break;
case TAIWAN_CODEPAGE:
RequiredLID = LANG_ID_TAIWAN;
break;
default:
break;
}
if ( !IS_IME_KBDLAYOUT(hkl) ||
( HKL_TO_LANGID(hkl) == RequiredLID)) {
return TRUE;
}
if (Direction == CONIME_DIRECT) {
return FALSE;
}
nLayouts = GetKeyboardLayoutList(0, NULL);
if (nLayouts == 0) {
return FALSE;
}
lphkl = LocalAlloc(LPTR, nLayouts * sizeof(HKL));
if (lphkl == NULL) {
return FALSE;
}
GetKeyboardLayoutList(nLayouts, lphkl);
for (CurrentHklPos = 0; CurrentHklPos < nLayouts; CurrentHklPos++) {
if (ConTbl->hklActive == lphkl[CurrentHklPos] ) {
break;
}
}
if (CurrentHklPos >= nLayouts) {
LocalFree(lphkl);
return FALSE;
}
StartPos = CurrentHklPos;
for (i = 0; i < nLayouts; i++) {
StartPos+=Direction;
if (StartPos < 0) {
StartPos = nLayouts-1;
}
else if (StartPos >= nLayouts) {
StartPos = 0;
}
if ((( HandleToUlong(lphkl[StartPos]) & 0xf0000000) == 0x00000000) ||
(( HandleToUlong(lphkl[StartPos]) & 0x0000ffff) == RequiredLID)) {
PostMessage( ConTbl->hWndCon,
CM_CONIME_KL_ACTIVATE,
HandleToUlong(lphkl[StartPos]),
0);
LocalFree(lphkl);
return FALSE;
}
}
LocalFree(lphkl);
return FALSE;
}
BOOL
ConImeInputLangchange(
HWND hWnd,
HANDLE hConsole,
HKL hkl
)
{
PCONSOLE_TABLE ConTbl;
LPCONIME_UIMODEINFO lpModeInfo;
COPYDATASTRUCT CopyData;
INT counter ;
LPHKL_TABLE lphklListNew ;
ConTbl = SearchConsole(hConsole);
if (ConTbl == NULL) {
// cannot find specified console.
// It might be last console lost focus.
// try Last Console.
ConTbl = SearchConsole(LastConsole);
if (ConTbl == NULL) {
DBGPRINT(("CONIME: Error! Cannot found registed Console\n"));
return FALSE;
}
}
if (ConTbl->lphklList == NULL) {
return FALSE;
}
if (IS_IME_KBDLAYOUT(ConTbl->hklActive)) {
for (counter = 0 ; counter < ConTbl->hklListMax ;counter ++)
{
if (ConTbl->lphklList[counter].hkl == 0 || ConTbl->lphklList[counter].hkl == ConTbl->hklActive) {
break;
}
}
if (counter >= ConTbl->hklListMax)
{
ASSERT(counter == ConTbl->hklListMax);
// reallocation
lphklListNew = LocalAlloc(LPTR, sizeof(HKL_TABLE) * (ConTbl->hklListMax + HKL_TABLE_INCREMENT) ) ;
if (lphklListNew != NULL)
{
CopyMemory(lphklListNew , ConTbl->lphklList , sizeof(HKL_TABLE) * ConTbl->hklListMax) ;
ConTbl->hklListMax += HKL_TABLE_INCREMENT ;
LocalFree(ConTbl->lphklList);
ConTbl->lphklList = lphklListNew;
}
else {
return FALSE ;
}
}
ASSERT(ConTbl->lphklList != NULL);
ConTbl->lphklList[counter].hkl = ConTbl->hklActive;
ConTbl->lphklList[counter].dwConversion = ConTbl->dwConversion | (ConTbl->fOpen ? IME_CMODE_OPEN : 0) ;
}
ActivateKeyboardLayout(hkl, 0);
ConTbl->hklActive = hkl;
GetIMEName( ConTbl );
ImeUIOpenStatusWindow(hWnd);
ConTbl->ImmGetProperty = ImmGetProperty(ConTbl->hklActive , IGP_PROPERTY);
lpModeInfo = (LPCONIME_UIMODEINFO)LocalAlloc( LPTR, sizeof(CONIME_UIMODEINFO) ) ;
if ( lpModeInfo == NULL) {
return FALSE;
}
CopyData.dwData = CI_CONIMEMODEINFO ;
CopyData.cbData = sizeof(CONIME_UIMODEINFO) ;
CopyData.lpData = lpModeInfo ;
if (IS_IME_KBDLAYOUT(hkl)) {
for (counter=0; counter < ConTbl->hklListMax ; counter++)
{
if (ConTbl->lphklList[counter].hkl == hkl)
{
SetNLSMode(hWnd, hConsole,ConTbl->lphklList[counter].dwConversion ) ;
ImeUIOpenStatusWindow(hWnd) ;
if (ImeUIMakeInfoString(ConTbl,
lpModeInfo))
{
ConsoleImeSendMessage( ConTbl->hWndCon,
(WPARAM)hWnd,
(LPARAM)&CopyData
) ;
}
}
}
}
else
{
SetNLSMode(hWnd, hConsole,ConTbl->dwConversion & ~IME_CMODE_OPEN ) ;
lpModeInfo->ModeStringLen = 0 ;
lpModeInfo->Position = VIEW_RIGHT ;
ConsoleImeSendMessage( ConTbl->hWndCon,
(WPARAM)hWnd,
(LPARAM)&CopyData
) ;
}
LocalFree( lpModeInfo );
return TRUE;
}
BOOL
InputLangchange(
HWND hWnd,
DWORD CharSet,
HKL hkl
)
{
PCONSOLE_TABLE ConTbl;
ConTbl = SearchConsole(LastConsole);
if (ConTbl == NULL) {
DBGPRINT(("CONIME: Error! Cannot found registed Console\n"));
return FALSE;
}
ConTbl->hklActive = hkl;
ActivateKeyboardLayout(ConTbl->hklActive, 0);
GetIMEName( ConTbl );
ImeUIOpenStatusWindow(hWnd);
return TRUE;
}
/*
* Console IME message pump.
*/
LRESULT
ConsoleImeSendMessage(
HWND hWndConsoleIME,
WPARAM wParam,
LPARAM lParam
)
{
LRESULT lResult;
LRESULT fNoTimeout;
if (hWndConsoleIME == NULL)
{
return FALSE;
}
fNoTimeout = SendMessageTimeout(hWndConsoleIME,
WM_COPYDATA,
wParam,
lParam,
SMTO_ABORTIFHUNG | SMTO_NORMAL,
CONIME_SENDMSG_TIMEOUT,
&lResult);
if (fNoTimeout)
{
return TRUE;
}
/*
* ConsoleImeMessagePump give up SendMessage to conime.
* CONIME is hung up.
* probably, consrv also hung up.
*/
KdPrint(("ConsoleImeSendMessage: CONIME_SENDMSG_COUNT is hung up\n"));
return FALSE;
}
#ifdef DEBUG_MODE
int cxMetrics;
int cyMetrics;
int cxOverTypeCaret;
int xPos;
int xPosLast;
int CaretWidth; // insert/overtype mode caret width
WCHAR ConvertLine[CVMAX];
unsigned char ConvertLineAtr[CVMAX];
WCHAR DispTitle[] = TEXT(" Console Handle");
DWORD CompColor[ 8 ] = { RGB( 0, 0, 0 ), // ATTR_INPUT
RGB( 0, 0, 255 ), // ATTR_TARGET_CONVERTED
RGB( 0, 255, 0 ), // ATTR_CONVERTED
RGB( 255, 0, 0 ), // ATTR_TARGET_NOTCONVERTED
RGB( 255, 0, 255 ), // ATTR_INPUT_ERROR
RGB( 0, 255, 255 ), // ATTR_DEFAULT
RGB( 255, 255, 0 ), // ATTR_DEFAULT
RGB( 255, 255, 255 ) };// ATTR_DEFAULT
VOID
DisplayConvInformation(
HWND hWnd
)
{
RECT Rect;
HDC lhdc;
lhdc = GetDC(hWnd);
GetClientRect(hWnd, &Rect);
InvalidateRect(hWnd,NULL,FALSE);
UpdateWindow(hWnd);
ReleaseDC(hWnd, lhdc);
}
VOID
DisplayInformation(
HWND hWnd,
HANDLE hConsole
)
{
PCONSOLE_TABLE ConTbl;
RECT Rect;
HDC lhdc;
ConTbl = SearchConsole(hConsole);
if (ConTbl == NULL) {
DBGPRINT(("CONIME: Error! Cannot found registed Console\n"));
return;
}
lhdc = GetDC(hWnd);
GetClientRect(hWnd, &Rect);
wsprintf(ConTbl->DispBuf, TEXT("%08x"), (ULONG)hConsole);
InvalidateRect(hWnd,NULL,FALSE);
UpdateWindow(hWnd);
ReleaseDC(hWnd, lhdc);
}
VOID
RealReDraw(
HDC r_hdc
)
{
PCONSOLE_TABLE ConTbl;
INT ix, iy, i, rx, sx;
ULONG cnt;
int ColorIndex;
int PrevColorIndex;
DWORD dwColor;
iy = 0;
dwColor = GetTextColor( r_hdc );
ColorIndex = ( ((int)ConvertLineAtr[0]) < 0 ) ? 0 : (int)ConvertLineAtr[0];
ColorIndex = ( ColorIndex > 7 ) ? 0 : ColorIndex;
PrevColorIndex = ColorIndex;
SetTextColor( r_hdc, CompColor[ ColorIndex ] );
rx = 0;
sx = 0;
for (ix = 0; ix < MAXCOL; ) {
for (i = ix; i < MAXCOL; i++) {
if (PrevColorIndex != (int)ConvertLineAtr[i])
break;
rx += IsUnicodeFullWidth(ConvertLine[ix]) ? 2 : 1;
}
TextOut( r_hdc, sx * cxMetrics, iy, &ConvertLine[ix], i-ix );
sx = rx;
ColorIndex = ( ((int)ConvertLineAtr[i]) < 0 ) ? 0 : (int)ConvertLineAtr[i];
ColorIndex = ( ColorIndex > 7 ) ? 0 : ColorIndex;
PrevColorIndex = ColorIndex;
SetTextColor( r_hdc, CompColor[ ColorIndex ] );
ix = i;
}
ix = 0;
SetTextColor( r_hdc, dwColor );
iy += cyMetrics;
TextOut( r_hdc, ix, iy, DispTitle, lstrlenW(DispTitle));
iy += cyMetrics;
LockConsoleTable();
for (cnt = 1; cnt < NumberOfConsoleTable; cnt++, iy += cyMetrics){
ConTbl = ConsoleTable[cnt];
if (ConTbl != NULL)
{
if (ConTbl->hConsole)
{
TextOut( r_hdc, ix, iy, ConTbl->DispBuf, lstrlenW(ConTbl->DispBuf) );
}
}
}
UnlockConsoleTable();
return;
}
VOID
ReDraw(
HWND hWnd
)
{
HDC r_hdc;
RECT ClientRect;
GetClientRect(hWnd, &ClientRect);
r_hdc = GetDC(hWnd);
FillRect(r_hdc, &ClientRect, GetStockObject(WHITE_BRUSH));
RealReDraw(r_hdc);
ReleaseDC(hWnd, r_hdc);
return;
}
#endif