static LRESULT CALLBACK TuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { /* PTUI_CONSOLE_DATA TuiData = NULL; PCONSOLE Console = NULL; TuiData = TuiGetGuiData(hWnd); if (TuiData == NULL) return 0; */ switch (msg) { case WM_CHAR: case WM_SYSCHAR: case WM_KEYDOWN: case WM_SYSKEYDOWN: case WM_KEYUP: case WM_SYSKEYUP: { if (ConDrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE)) { MSG Message; Message.hwnd = hWnd; Message.message = msg; Message.wParam = wParam; Message.lParam = lParam; ConioProcessKey(ActiveConsole->Console, &Message); LeaveCriticalSection(&ActiveConsole->Console->Lock); } break; } case WM_ACTIVATE: { if (ConDrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE)) { if (LOWORD(wParam) != WA_INACTIVE) { SetFocus(hWnd); ConioDrawConsole(ActiveConsole->Console); } LeaveCriticalSection(&ActiveConsole->Console->Lock); } break; } default: break; } return DefWindowProcW(hWnd, msg, wParam, lParam); }
static VOID WINAPI TuiDeinitFrontEnd(IN OUT PFRONTEND This) { // PCONSOLE Console = This->Console; PTUI_CONSOLE_DATA TuiData = This->Data; // Console->TermIFace.Data; /* Close the notification window */ DestroyWindow(TuiData->hWindow); /* * Set the active console to the next one * and remove the console from the list. */ EnterCriticalSection(&ActiveVirtConsLock); ActiveConsole = GetNextConsole(TuiData); RemoveEntryList(&TuiData->Entry); // /* Switch to next console */ // if (ActiveConsole == TuiData) // if (ActiveConsole->Console == Console) // { // ActiveConsole = (TuiData->Entry.Flink != TuiData->Entry ? GetNextConsole(TuiData) : NULL); // } // if (GetNextConsole(TuiData) != TuiData) // { // TuiData->Entry.Blink->Flink = TuiData->Entry.Flink; // TuiData->Entry.Flink->Blink = TuiData->Entry.Blink; // } LeaveCriticalSection(&ActiveVirtConsLock); /* Switch to the next console */ if (NULL != ActiveConsole) ConioDrawConsole(ActiveConsole->Console); // Console->TermIFace.Data = NULL; This->Data = NULL; DeleteCriticalSection(&TuiData->Lock); ConsoleFreeHeap(TuiData); }
VOID NTAPI ConioProcessKey(PCONSRV_CONSOLE Console, MSG* msg) { static BYTE KeyState[256] = { 0 }; /* MSDN mentions that you should use the last virtual key code received * when putting a virtual key identity to a WM_CHAR message since multiple * or translated keys may be involved. */ static UINT LastVirtualKey = 0; DWORD ShiftState; WCHAR UnicodeChar; UINT VirtualKeyCode; UINT VirtualScanCode; BOOL Down = FALSE; BOOLEAN Fake; // Synthesized, not a real event BOOLEAN NotChar; // Message should not be used to return a character INPUT_RECORD er; if (Console == NULL) { DPRINT1("No Active Console!\n"); return; } VirtualScanCode = HIWORD(msg->lParam) & 0xFF; Down = msg->message == WM_KEYDOWN || msg->message == WM_CHAR || msg->message == WM_SYSKEYDOWN || msg->message == WM_SYSCHAR; GetKeyboardState(KeyState); ShiftState = ConioGetShiftState(KeyState, msg->lParam); if (msg->message == WM_CHAR || msg->message == WM_SYSCHAR) { VirtualKeyCode = LastVirtualKey; UnicodeChar = msg->wParam; } else { WCHAR Chars[2]; INT RetChars = 0; VirtualKeyCode = msg->wParam; RetChars = ToUnicodeEx(VirtualKeyCode, VirtualScanCode, KeyState, Chars, 2, 0, NULL); UnicodeChar = (RetChars == 1 ? Chars[0] : 0); } Fake = UnicodeChar && (msg->message != WM_CHAR && msg->message != WM_SYSCHAR && msg->message != WM_KEYUP && msg->message != WM_SYSKEYUP); NotChar = (msg->message != WM_CHAR && msg->message != WM_SYSCHAR); if (NotChar) LastVirtualKey = msg->wParam; DPRINT("CONSRV: %s %s %s %s %02x %02x '%lc' %04x\n", Down ? "down" : "up ", (msg->message == WM_CHAR || msg->message == WM_SYSCHAR) ? "char" : "key ", Fake ? "fake" : "real", NotChar ? "notc" : "char", VirtualScanCode, VirtualKeyCode, (UnicodeChar >= L' ') ? UnicodeChar : L'.', ShiftState); if (Fake) return; /* Process Ctrl-C and Ctrl-Break */ if ( Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT && Down && (VirtualKeyCode == VK_PAUSE || VirtualKeyCode == 'C') && (ShiftState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) || KeyState[VK_CONTROL] & 0x80) ) { DPRINT1("Console_Api Ctrl-C\n"); ConSrvConsoleProcessCtrlEvent(Console, 0, CTRL_C_EVENT); if (Console->LineBuffer && !Console->LineComplete) { /* Line input is in progress; end it */ Console->LinePos = Console->LineSize = 0; Console->LineComplete = TRUE; } return; } if ( (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) != 0 && (VirtualKeyCode == VK_UP || VirtualKeyCode == VK_DOWN) ) { if (!Down) return; /* Scroll up or down */ if (VirtualKeyCode == VK_UP) { /* Only scroll up if there is room to scroll up into */ if (Console->ActiveBuffer->CursorPosition.Y != Console->ActiveBuffer->ScreenBufferSize.Y - 1) { Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + Console->ActiveBuffer->ScreenBufferSize.Y - 1) % Console->ActiveBuffer->ScreenBufferSize.Y; Console->ActiveBuffer->CursorPosition.Y++; } } else { /* Only scroll down if there is room to scroll down into */ if (Console->ActiveBuffer->CursorPosition.Y != 0) { Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + 1) % Console->ActiveBuffer->ScreenBufferSize.Y; Console->ActiveBuffer->CursorPosition.Y--; } } ConioDrawConsole(Console); return; } /* Send the key press to the console driver */ er.EventType = KEY_EVENT; er.Event.KeyEvent.bKeyDown = Down; er.Event.KeyEvent.wRepeatCount = 1; er.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode; er.Event.KeyEvent.wVirtualScanCode = VirtualScanCode; er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar; er.Event.KeyEvent.dwControlKeyState = ShiftState; ConioProcessInputEvent(Console, &er); }
static BOOL FASTCALL TuiSwapConsole(INT Next) { static PTUI_CONSOLE_DATA SwapConsole = NULL; /* Console we are thinking about swapping with */ DWORD BytesReturned; ANSI_STRING Title; PVOID Buffer; PCOORD pos; if (0 != Next) { /* * Alt-Tab, swap consoles. * move SwapConsole to next console, and print its title. */ EnterCriticalSection(&ActiveVirtConsLock); if (!SwapConsole) SwapConsole = ActiveConsole; SwapConsole = (0 < Next ? GetNextConsole(SwapConsole) : GetPrevConsole(SwapConsole)); Title.MaximumLength = RtlUnicodeStringToAnsiSize(&SwapConsole->Console->Title); Title.Length = 0; Buffer = ConsoleAllocHeap(0, sizeof(COORD) + Title.MaximumLength); pos = (PCOORD)Buffer; Title.Buffer = (PVOID)((ULONG_PTR)Buffer + sizeof(COORD)); RtlUnicodeStringToAnsiString(&Title, &SwapConsole->Console->Title, FALSE); pos->X = (PhysicalConsoleSize.X - Title.Length) / 2; pos->Y = PhysicalConsoleSize.Y / 2; /* Redraw the console to clear off old title */ ConioDrawConsole(ActiveConsole->Console); if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER, NULL, 0, Buffer, sizeof(COORD) + Title.Length, &BytesReturned, NULL)) { DPRINT1( "Error writing to console\n" ); } ConsoleFreeHeap(Buffer); LeaveCriticalSection(&ActiveVirtConsLock); return TRUE; } else if (NULL != SwapConsole) { EnterCriticalSection(&ActiveVirtConsLock); if (SwapConsole != ActiveConsole) { /* First remove swapconsole from the list */ SwapConsole->Entry.Blink->Flink = SwapConsole->Entry.Flink; SwapConsole->Entry.Flink->Blink = SwapConsole->Entry.Blink; /* Now insert before activeconsole */ SwapConsole->Entry.Flink = &ActiveConsole->Entry; SwapConsole->Entry.Blink = ActiveConsole->Entry.Blink; ActiveConsole->Entry.Blink->Flink = &SwapConsole->Entry; ActiveConsole->Entry.Blink = &SwapConsole->Entry; } ActiveConsole = SwapConsole; SwapConsole = NULL; ConioDrawConsole(ActiveConsole->Console); LeaveCriticalSection(&ActiveVirtConsLock); return TRUE; } else { return FALSE; } }
/* * This function explicitely references Console->ActiveBuffer * (and also makes use of keyboard functions...). * It is possible that it will move into frontends... */ VOID NTAPI ConDrvProcessKey(IN PCONSOLE Console, IN BOOLEAN Down, IN UINT VirtualKeyCode, IN UINT VirtualScanCode, IN WCHAR UnicodeChar, IN ULONG ShiftState, IN BYTE KeyStateCtrl) { INPUT_RECORD er; /* process Ctrl-C and Ctrl-Break */ if ( Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT && Down && (VirtualKeyCode == VK_PAUSE || VirtualKeyCode == 'C') && (ShiftState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) || KeyStateCtrl & 0x80) ) { DPRINT1("Console_Api Ctrl-C\n"); ConDrvConsoleProcessCtrlEvent(Console, 0, CTRL_C_EVENT); if (Console->LineBuffer && !Console->LineComplete) { /* Line input is in progress; end it */ Console->LinePos = Console->LineSize = 0; Console->LineComplete = TRUE; } return; } if ( (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) != 0 && (VK_UP == VirtualKeyCode || VK_DOWN == VirtualKeyCode) ) { if (!Down) return; /* scroll up or down */ if (VK_UP == VirtualKeyCode) { /* only scroll up if there is room to scroll up into */ if (Console->ActiveBuffer->CursorPosition.Y != Console->ActiveBuffer->ScreenBufferSize.Y - 1) { Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + Console->ActiveBuffer->ScreenBufferSize.Y - 1) % Console->ActiveBuffer->ScreenBufferSize.Y; Console->ActiveBuffer->CursorPosition.Y++; } } else { /* only scroll down if there is room to scroll down into */ if (Console->ActiveBuffer->CursorPosition.Y != 0) { Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + 1) % Console->ActiveBuffer->ScreenBufferSize.Y; Console->ActiveBuffer->CursorPosition.Y--; } } ConioDrawConsole(Console); return; } er.EventType = KEY_EVENT; er.Event.KeyEvent.bKeyDown = Down; er.Event.KeyEvent.wRepeatCount = 1; er.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode; er.Event.KeyEvent.wVirtualScanCode = VirtualScanCode; er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar; er.Event.KeyEvent.dwControlKeyState = ShiftState; ConioProcessInputEvent(Console, &er); }