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