diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h index ec435e3b480..0afdf86f4bb 100644 --- a/win32ss/include/ntuser.h +++ b/win32ss/include/ntuser.h @@ -1566,7 +1566,7 @@ NtUserCloseWindowStation( typedef enum _CONSOLECONTROL { GuiConsoleWndClassAtom, - TuiConsoleWndClassAtom, + ConsoleAcquireDisplayOwnership, } CONSOLECONTROL, *PCONSOLECONTROL; NTSTATUS diff --git a/win32ss/user/consrv/alias.c b/win32ss/user/consrv/alias.c index 6a410c6a834..c7589b743c0 100644 --- a/win32ss/user/consrv/alias.c +++ b/win32ss/user/consrv/alias.c @@ -40,7 +40,7 @@ static PALIAS_HEADER IntFindAliasHeader(PALIAS_HEADER RootHeader, LPCWSTR lpExeName) { - while(RootHeader) + while (RootHeader) { INT diff = _wcsicmp(RootHeader->lpExeName, lpExeName); if (!diff) return RootHeader; @@ -93,7 +93,7 @@ IntGetAliasEntry(PALIAS_HEADER Header, LPCWSTR lpSrcName) if (Header == NULL) return NULL; RootHeader = Header->Data; - while(RootHeader) + while (RootHeader) { INT diff; DPRINT("IntGetAliasEntry->lpSource %S\n", RootHeader->lpSource); @@ -151,7 +151,7 @@ IntGetConsoleAliasesExesLength(PALIAS_HEADER RootHeader) { UINT length = 0; - while(RootHeader) + while (RootHeader) { length += (wcslen(RootHeader->lpExeName) + 1) * sizeof(WCHAR); RootHeader = RootHeader->Next; @@ -169,7 +169,7 @@ IntGetConsoleAliasesExes(PALIAS_HEADER RootHeader, LPWSTR TargetBuffer, UINT Tar UINT Length; TargetBufferSize /= sizeof(WCHAR); - while(RootHeader) + while (RootHeader) { Length = wcslen(RootHeader->lpExeName) + 1; if (TargetBufferSize > Offset + Length) @@ -194,7 +194,7 @@ IntGetAllConsoleAliasesLength(PALIAS_HEADER Header) UINT Length = 0; PALIAS_ENTRY CurEntry = Header->Data; - while(CurEntry) + while (CurEntry) { Length += wcslen(CurEntry->lpSource); Length += wcslen(CurEntry->lpTarget); @@ -217,7 +217,7 @@ IntGetAllConsoleAliases(PALIAS_HEADER Header, LPWSTR TargetBuffer, UINT TargetBu UINT SrcLength, TargetLength; TargetBufferLength /= sizeof(WCHAR); - while(CurEntry) + while (CurEntry) { SrcLength = wcslen(CurEntry->lpSource) + 1; TargetLength = wcslen(CurEntry->lpTarget) + 1; diff --git a/win32ss/user/consrv/coninput.c b/win32ss/user/consrv/coninput.c index ef13030056d..48bc9b3bc39 100644 --- a/win32ss/user/consrv/coninput.c +++ b/win32ss/user/consrv/coninput.c @@ -772,7 +772,7 @@ CSR_API(SrvGetConsoleInput) GetInputRequest->InputsRead = 0; Status = ConSrvGetInputBufferAndHandleEntry(ProcessData, GetInputRequest->InputHandle, &InputBuffer, &HandleEntry, GENERIC_READ, TRUE); - if(!NT_SUCCESS(Status)) return Status; + if (!NT_SUCCESS(Status)) return Status; InputInfo.CallingThread = CsrGetClientThread(); InputInfo.HandleEntry = HandleEntry; @@ -855,7 +855,7 @@ CSR_API(SrvFlushConsoleInputBuffer) &InputBuffer, GENERIC_WRITE, TRUE); - if(!NT_SUCCESS(Status)) return Status; + if (!NT_SUCCESS(Status)) return Status; /* Discard all entries in the input event queue */ while (!IsListEmpty(&InputBuffer->InputEvents)) diff --git a/win32ss/user/consrv/conio.h b/win32ss/user/consrv/conio.h index ecef65c0741..7235ac21422 100644 --- a/win32ss/user/consrv/conio.h +++ b/win32ss/user/consrv/conio.h @@ -10,27 +10,35 @@ /* Macros used to call functions in the FRONTEND_VTBL virtual table */ -#define ConioDrawRegion(Console, Region) (Console)->TermIFace.Vtbl->DrawRegion((Console), (Region)) +#define ConioDrawRegion(Console, Region) \ + (Console)->TermIFace.Vtbl->DrawRegion((Console), (Region)) #define ConioWriteStream(Console, Block, CurStartX, CurStartY, ScrolledLines, Buffer, Length) \ - (Console)->TermIFace.Vtbl->WriteStream((Console), (Block), (CurStartX), (CurStartY), \ - (ScrolledLines), (Buffer), (Length)) -#define ConioSetCursorInfo(Console, Buff) (Console)->TermIFace.Vtbl->SetCursorInfo((Console), (Buff)) + (Console)->TermIFace.Vtbl->WriteStream((Console), (Block), (CurStartX), (CurStartY), \ + (ScrolledLines), (Buffer), (Length)) +#define ConioSetCursorInfo(Console, Buff) \ + (Console)->TermIFace.Vtbl->SetCursorInfo((Console), (Buff)) #define ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY) \ - (Console)->TermIFace.Vtbl->SetScreenInfo((Console), (Buff), (OldCursorX), (OldCursorY)) + (Console)->TermIFace.Vtbl->SetScreenInfo((Console), (Buff), (OldCursorX), (OldCursorY)) #define ConioUpdateScreenInfo(Console, Buff) \ - (Console)->TermIFace.Vtbl->UpdateScreenInfo((Console), (Buff)) -#define ConioChangeTitle(Console) (Console)->TermIFace.Vtbl->ChangeTitle(Console) -#define ConioCleanupConsole(Console) (Console)->TermIFace.Vtbl->CleanupConsole(Console) -#define ConioChangeIcon(Console, hWindowIcon) (Console)->TermIFace.Vtbl->ChangeIcon((Console), (hWindowIcon)) -#define ConioResizeBuffer(Console, Buff, Size) (Console)->TermIFace.Vtbl->ResizeBuffer((Console), (Buff), (Size)) -#define ConioResizeTerminal(Console) (Console)->TermIFace.Vtbl->ResizeTerminal((Console)) + (Console)->TermIFace.Vtbl->UpdateScreenInfo((Console), (Buff)) +#define ConioIsBufferResizeSupported(Console) \ + (Console)->TermIFace.Vtbl->IsBufferResizeSupported(Console) +#define ConioChangeTitle(Console) \ + (Console)->TermIFace.Vtbl->ChangeTitle(Console) +#define ConioCleanupConsole(Console) \ + (Console)->TermIFace.Vtbl->CleanupConsole(Console) +#define ConioChangeIcon(Console, hWindowIcon) \ + (Console)->TermIFace.Vtbl->ChangeIcon((Console), (hWindowIcon)) +// #define ConioResizeBuffer(Console, Buff, Size) (Console)->TermIFace.Vtbl->ResizeBuffer((Console), (Buff), (Size)) +#define ConioResizeTerminal(Console) \ + (Console)->TermIFace.Vtbl->ResizeTerminal(Console) #define ConioProcessKeyCallback(Console, Msg, KeyStateMenu, ShiftState, VirtualKeyCode, Down) \ - (Console)->TermIFace.Vtbl->ProcessKeyCallback((Console), (Msg), (KeyStateMenu), (ShiftState), (VirtualKeyCode), (Down)) + (Console)->TermIFace.Vtbl->ProcessKeyCallback((Console), (Msg), (KeyStateMenu), (ShiftState), (VirtualKeyCode), (Down)) #define ConioGetLargestConsoleWindowSize(Console, pSize) \ - (Console)->TermIFace.Vtbl->GetLargestConsoleWindowSize((Console), (pSize)) + (Console)->TermIFace.Vtbl->GetLargestConsoleWindowSize((Console), (pSize)) #define ConioGetConsoleWindowHandle(Console) \ - (Console)->TermIFace.Vtbl->GetConsoleWindowHandle((Console)) + (Console)->TermIFace.Vtbl->GetConsoleWindowHandle(Console) #define ConioRefreshInternalInfo(Console) \ - (Console)->TermIFace.Vtbl->RefreshInternalInfo((Console)) + (Console)->TermIFace.Vtbl->RefreshInternalInfo(Console) /* EOF */ diff --git a/win32ss/user/consrv/conoutput.c b/win32ss/user/consrv/conoutput.c index 088d9af6c36..7bd67946712 100644 --- a/win32ss/user/consrv/conoutput.c +++ b/win32ss/user/consrv/conoutput.c @@ -30,7 +30,7 @@ do { \ ((Rect)->Left) = left; \ ((Rect)->Bottom) = bottom; \ ((Rect)->Right) = right; \ -} while(0) +} while (0) #define ConioIsRectEmpty(Rect) \ (((Rect)->Left > (Rect)->Right) || ((Rect)->Top > (Rect)->Bottom)) @@ -401,6 +401,119 @@ ConioMoveRegion(PCONSOLE_SCREEN_BUFFER ScreenBuffer, } } +NTSTATUS FASTCALL +ConioResizeBuffer(PCONSOLE Console, + PCONSOLE_SCREEN_BUFFER ScreenBuffer, + COORD Size) +{ + BYTE * Buffer; + DWORD Offset = 0; + BYTE * OldPtr; + USHORT CurrentY; + BYTE * OldBuffer; +#ifdef HAVE_WMEMSET + USHORT value = MAKEWORD(' ', ScreenBuffer->ScreenDefaultAttrib); +#else + DWORD i; +#endif + DWORD diff; + + /* Buffer size is not allowed to be smaller than window size */ + if (Size.X < Console->ConsoleSize.X || Size.Y < Console->ConsoleSize.Y) + return STATUS_INVALID_PARAMETER; + + if (Size.X == ScreenBuffer->ScreenBufferSize.X && Size.Y == ScreenBuffer->ScreenBufferSize.Y) + { + // FIXME: Trigger a buffer resize event ?? + return STATUS_SUCCESS; + } + + if (!ConioIsBufferResizeSupported(Console)) return STATUS_NOT_SUPPORTED; + + Buffer = RtlAllocateHeap(ConSrvHeap, 0, Size.X * Size.Y * 2); + if (!Buffer) return STATUS_NO_MEMORY; + + DPRINT1("Resizing (%d,%d) to (%d,%d)\n", ScreenBuffer->ScreenBufferSize.X, ScreenBuffer->ScreenBufferSize.Y, Size.X, Size.Y); + OldBuffer = ScreenBuffer->Buffer; + + for (CurrentY = 0; CurrentY < ScreenBuffer->ScreenBufferSize.Y && CurrentY < Size.Y; CurrentY++) + { + OldPtr = ConioCoordToPointer(ScreenBuffer, 0, CurrentY); + if (Size.X <= ScreenBuffer->ScreenBufferSize.X) + { + /* reduce size */ + RtlCopyMemory(&Buffer[Offset], OldPtr, Size.X * 2); + Offset += (Size.X * 2); + } + else + { + /* enlarge size */ + RtlCopyMemory(&Buffer[Offset], OldPtr, ScreenBuffer->ScreenBufferSize.X * 2); + Offset += (ScreenBuffer->ScreenBufferSize.X * 2); + + diff = Size.X - ScreenBuffer->ScreenBufferSize.X; + /* zero new part of it */ +#ifdef HAVE_WMEMSET + wmemset((PWCHAR)&Buffer[Offset], value, diff); +#else + for (i = 0; i < diff; i++) + { + Buffer[Offset++] = ' '; + Buffer[Offset++] = ScreenBuffer->ScreenDefaultAttrib; + } +#endif + } + } + + if (Size.Y > ScreenBuffer->ScreenBufferSize.Y) + { + diff = Size.X * (Size.Y - ScreenBuffer->ScreenBufferSize.Y); +#ifdef HAVE_WMEMSET + wmemset((PWCHAR)&Buffer[Offset], value, diff); +#else + for (i = 0; i < diff; i++) + { + Buffer[Offset++] = ' '; + Buffer[Offset++] = ScreenBuffer->ScreenDefaultAttrib; + } +#endif + } + + (void)InterlockedExchangePointer((PVOID volatile*)&ScreenBuffer->Buffer, Buffer); + RtlFreeHeap(ConSrvHeap, 0, OldBuffer); + ScreenBuffer->ScreenBufferSize = Size; + ScreenBuffer->VirtualY = 0; + + /* Ensure cursor and window are within buffer */ + if (ScreenBuffer->CursorPosition.X >= Size.X) + ScreenBuffer->CursorPosition.X = Size.X - 1; + if (ScreenBuffer->CursorPosition.Y >= Size.Y) + ScreenBuffer->CursorPosition.Y = Size.Y - 1; + if (ScreenBuffer->ShowX > Size.X - Console->ConsoleSize.X) + ScreenBuffer->ShowX = Size.X - Console->ConsoleSize.X; + if (ScreenBuffer->ShowY > Size.Y - Console->ConsoleSize.Y) + ScreenBuffer->ShowY = Size.Y - Console->ConsoleSize.Y; + + /* + * Trigger a buffer resize event + */ + if (Console->InputBuffer.Mode & ENABLE_WINDOW_INPUT) + { + INPUT_RECORD er; + + er.EventType = WINDOW_BUFFER_SIZE_EVENT; + er.Event.WindowBufferSizeEvent.dwSize = ScreenBuffer->ScreenBufferSize; + + ConioProcessInputEvent(Console, &er); + } + + /* TODO: Should update scrollbar, but can't use anything that + * calls SendMessage or it could cause deadlock --> Use PostMessage */ + // TODO: Tell the terminal to resize its scrollbars. + + return STATUS_SUCCESS; +} + VOID WINAPI ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer) { @@ -1148,8 +1261,8 @@ CSR_API(SrvGetConsoleCursorInfo) CursorInfoRequest->Info.bVisible = Buff->CursorInfo.bVisible; CursorInfoRequest->Info.dwSize = Buff->CursorInfo.dwSize; - ConSrvReleaseScreenBuffer(Buff, TRUE); + ConSrvReleaseScreenBuffer(Buff, TRUE); return STATUS_SUCCESS; } @@ -1195,7 +1308,6 @@ CSR_API(SrvSetConsoleCursorInfo) } ConSrvReleaseScreenBuffer(Buff, TRUE); - return STATUS_SUCCESS; } @@ -1237,7 +1349,6 @@ CSR_API(SrvSetConsoleCursorPosition) } ConSrvReleaseScreenBuffer(Buff, TRUE); - return STATUS_SUCCESS; } @@ -1266,7 +1377,6 @@ CSR_API(SrvSetConsoleTextAttribute) } ConSrvReleaseScreenBuffer(Buff, TRUE); - return STATUS_SUCCESS; } @@ -1374,7 +1484,6 @@ CSR_API(SrvGetConsoleScreenBufferInfo) pInfo->dwMaximumWindowSize = Buff->ScreenBufferSize; ConSrvReleaseScreenBuffer(Buff, TRUE); - return STATUS_SUCCESS; } @@ -1411,7 +1520,6 @@ CSR_API(SrvSetConsoleActiveScreenBuffer) ConioDrawConsole(Console); ConSrvReleaseScreenBuffer(Buff, TRUE); - return STATUS_SUCCESS; } @@ -1503,7 +1611,6 @@ CSR_API(SrvScrollConsoleScreenBuffer) } ConSrvReleaseScreenBuffer(Buff, TRUE); - return STATUS_SUCCESS; } @@ -1517,8 +1624,8 @@ CSR_API(SrvSetConsoleScreenBufferSize) if (!NT_SUCCESS(Status)) return Status; Status = ConioResizeBuffer(Buff->Header.Console, Buff, SetScreenBufferSizeRequest->Size); - ConSrvReleaseScreenBuffer(Buff, TRUE); + ConSrvReleaseScreenBuffer(Buff, TRUE); return Status; } diff --git a/win32ss/user/consrv/console.c b/win32ss/user/consrv/console.c index 33f3a1dcf8d..c112751ede4 100644 --- a/win32ss/user/consrv/console.c +++ b/win32ss/user/consrv/console.c @@ -25,10 +25,7 @@ #include "include/settings.h" #include "frontends/gui/guiterm.h" - -#ifdef TUI_CONSOLE - #include "frontends/tui/tuiterm.h" -#endif +#include "frontends/tui/tuiterm.h" #include "include/console.h" #include "console.h" @@ -57,13 +54,11 @@ static RTL_RESOURCE ListLock; /* PRIVATE FUNCTIONS **********************************************************/ -#ifdef TUI_CONSOLE static BOOL DtbgIsDesktopVisible(VOID) { return !((BOOL)NtUserCallNoParam(NOPARAM_ROUTINE_ISCONSOLEMODE)); } -#endif static ULONG ConSrvConsoleCtrlEventTimeout(DWORD Event, @@ -640,13 +635,8 @@ ConSrvInitConsole(OUT PCONSOLE* NewConsole, * If we are not in GUI-mode, start the text-mode terminal emulator. * If we fail, try to start the GUI-mode terminal emulator. */ -#ifdef TUI_CONSOLE GuiMode = DtbgIsDesktopVisible(); -#else - GuiMode = TRUE; -#endif -#ifdef TUI_CONSOLE if (!GuiMode) { DPRINT1("CONSRV: Opening text-mode terminal emulator\n"); @@ -660,7 +650,6 @@ ConSrvInitConsole(OUT PCONSOLE* NewConsole, GuiMode = TRUE; } } -#endif /* * Try to open the GUI-mode terminal emulator. Two cases are possible: diff --git a/win32ss/user/consrv/frontends/gui/guiterm.c b/win32ss/user/consrv/frontends/gui/guiterm.c index f1eea6372a3..7bbd681a315 100644 --- a/win32ss/user/consrv/frontends/gui/guiterm.c +++ b/win32ss/user/consrv/frontends/gui/guiterm.c @@ -70,7 +70,7 @@ do { \ ConsoleLeaderCID = ProcessData->Process->ClientId; \ SetWindowLongPtrW((GuiData)->hWindow, GWLP_CONSOLE_LEADER_PID, (LONG_PTR)(ConsoleLeaderCID.UniqueProcess)); \ SetWindowLongPtrW((GuiData)->hWindow, GWLP_CONSOLE_LEADER_TID, (LONG_PTR)(ConsoleLeaderCID.UniqueThread )); \ -} while(0) +} while (0) /**************************************************************/ static BOOL ConsInitialized = FALSE; @@ -185,7 +185,7 @@ GuiConsoleAppendMenuItems(HMENU hMenu, NULL); } i++; - } while(!(Items[i].uID == 0 && Items[i].SubMenu == NULL && Items[i].wCmdID == 0)); + } while (!(Items[i].uID == 0 && Items[i].SubMenu == NULL && Items[i].wCmdID == 0)); } static VOID @@ -209,8 +209,6 @@ static VOID GuiConsoleUpdateSelection(PCONSOLE Console, PCOORD coord); static VOID WINAPI GuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region); -static NTSTATUS WINAPI -GuiResizeBuffer(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER ScreenBuffer, COORD Size); static VOID GuiConsoleResizeWindow(PGUI_CONSOLE_DATA GuiData); @@ -510,7 +508,7 @@ GuiConsoleUpdateSelection(PCONSOLE Console, PCOORD coord) { if ((rgn2 = CreateRectRgnIndirect(&newRect))) { - if(CombineRgn(rgn1, rgn2, rgn1, RGN_XOR) != ERROR) + if (CombineRgn(rgn1, rgn2, rgn1, RGN_XOR) != ERROR) { InvalidateRgn(GuiData->hWindow, rgn1, FALSE); } @@ -861,7 +859,7 @@ GuiConsoleHandleTimer(PGUI_CONSOLE_DATA GuiData) GuiInvalidateCell(Console, Buff->CursorPosition.X, Buff->CursorPosition.Y); Buff->CursorBlinkOn = !Buff->CursorBlinkOn; - if((GuiData->OldCursor.x != Buff->CursorPosition.X) || (GuiData->OldCursor.y != Buff->CursorPosition.Y)) + if ((GuiData->OldCursor.x != Buff->CursorPosition.X) || (GuiData->OldCursor.y != Buff->CursorPosition.Y)) { SCROLLINFO xScroll; int OldScrollX = -1, OldScrollY = -1; @@ -870,16 +868,16 @@ GuiConsoleHandleTimer(PGUI_CONSOLE_DATA GuiData) xScroll.cbSize = sizeof(SCROLLINFO); xScroll.fMask = SIF_POS; // Capture the original position of the scroll bars and save them. - if(GetScrollInfo(GuiData->hWindow, SB_HORZ, &xScroll))OldScrollX = xScroll.nPos; - if(GetScrollInfo(GuiData->hWindow, SB_VERT, &xScroll))OldScrollY = xScroll.nPos; + if (GetScrollInfo(GuiData->hWindow, SB_HORZ, &xScroll))OldScrollX = xScroll.nPos; + if (GetScrollInfo(GuiData->hWindow, SB_VERT, &xScroll))OldScrollY = xScroll.nPos; // If we successfully got the info for the horizontal scrollbar - if(OldScrollX >= 0) + if (OldScrollX >= 0) { - if((Buff->CursorPosition.X < Buff->ShowX)||(Buff->CursorPosition.X >= (Buff->ShowX + Console->ConsoleSize.X))) + if ((Buff->CursorPosition.X < Buff->ShowX)||(Buff->CursorPosition.X >= (Buff->ShowX + Console->ConsoleSize.X))) { // Handle the horizontal scroll bar - if(Buff->CursorPosition.X >= Console->ConsoleSize.X) NewScrollX = Buff->CursorPosition.X - Console->ConsoleSize.X + 1; + if (Buff->CursorPosition.X >= Console->ConsoleSize.X) NewScrollX = Buff->CursorPosition.X - Console->ConsoleSize.X + 1; else NewScrollX = 0; } else @@ -888,12 +886,12 @@ GuiConsoleHandleTimer(PGUI_CONSOLE_DATA GuiData) } } // If we successfully got the info for the vertical scrollbar - if(OldScrollY >= 0) + if (OldScrollY >= 0) { - if((Buff->CursorPosition.Y < Buff->ShowY) || (Buff->CursorPosition.Y >= (Buff->ShowY + Console->ConsoleSize.Y))) + if ((Buff->CursorPosition.Y < Buff->ShowY) || (Buff->CursorPosition.Y >= (Buff->ShowY + Console->ConsoleSize.Y))) { // Handle the vertical scroll bar - if(Buff->CursorPosition.Y >= Console->ConsoleSize.Y) NewScrollY = Buff->CursorPosition.Y - Console->ConsoleSize.Y + 1; + if (Buff->CursorPosition.Y >= Console->ConsoleSize.Y) NewScrollY = Buff->CursorPosition.Y - Console->ConsoleSize.Y + 1; else NewScrollY = 0; } else @@ -906,7 +904,7 @@ GuiConsoleHandleTimer(PGUI_CONSOLE_DATA GuiData) // NOTE: OldScroll# and NewScroll# will both be -1 (initial value) if the info for the respective scrollbar // was not obtained successfully in the previous steps. This means their difference is 0 (no scrolling) // and their associated scrollbar is left alone. - if((OldScrollX != NewScrollX) || (OldScrollY != NewScrollY)) + if ((OldScrollX != NewScrollX) || (OldScrollY != NewScrollY)) { Buff->ShowX = NewScrollX; Buff->ShowY = NewScrollY; @@ -918,12 +916,12 @@ GuiConsoleHandleTimer(PGUI_CONSOLE_DATA GuiData) NULL, NULL, SW_INVALIDATE); - if(NewScrollX >= 0) + if (NewScrollX >= 0) { xScroll.nPos = NewScrollX; SetScrollInfo(GuiData->hWindow, SB_HORZ, &xScroll, TRUE); } - if(NewScrollY >= 0) + if (NewScrollY >= 0) { xScroll.nPos = NewScrollY; SetScrollInfo(GuiData->hWindow, SB_VERT, &xScroll, TRUE); @@ -1338,8 +1336,8 @@ GuiConsoleGetMinMaxInfo(PGUI_CONSOLE_DATA GuiData, PMINMAXINFO minMaxInfo) windx = (Console->ActiveBuffer->ScreenBufferSize.X) * GuiData->CharWidth + 2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE)); windy = (Console->ActiveBuffer->ScreenBufferSize.Y) * GuiData->CharHeight + 2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION); - if(Console->ConsoleSize.X < Console->ActiveBuffer->ScreenBufferSize.X) windy += GetSystemMetrics(SM_CYHSCROLL); // window currently has a horizontal scrollbar - if(Console->ConsoleSize.Y < Console->ActiveBuffer->ScreenBufferSize.Y) windx += GetSystemMetrics(SM_CXVSCROLL); // window currently has a vertical scrollbar + if (Console->ConsoleSize.X < Console->ActiveBuffer->ScreenBufferSize.X) windy += GetSystemMetrics(SM_CYHSCROLL); // window currently has a horizontal scrollbar + if (Console->ConsoleSize.Y < Console->ActiveBuffer->ScreenBufferSize.Y) windx += GetSystemMetrics(SM_CXVSCROLL); // window currently has a vertical scrollbar minMaxInfo->ptMaxTrackSize.x = windx; minMaxInfo->ptMaxTrackSize.y = windy; @@ -1366,29 +1364,29 @@ GuiConsoleResize(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM lParam) windy = HIWORD(lParam); // Compensate for existing scroll bars (because lParam values do not accommodate scroll bar) - if(Console->ConsoleSize.X < Buff->ScreenBufferSize.X) windy += GetSystemMetrics(SM_CYHSCROLL); // window currently has a horizontal scrollbar - if(Console->ConsoleSize.Y < Buff->ScreenBufferSize.Y) windx += GetSystemMetrics(SM_CXVSCROLL); // window currently has a vertical scrollbar + if (Console->ConsoleSize.X < Buff->ScreenBufferSize.X) windy += GetSystemMetrics(SM_CYHSCROLL); // window currently has a horizontal scrollbar + if (Console->ConsoleSize.Y < Buff->ScreenBufferSize.Y) windx += GetSystemMetrics(SM_CXVSCROLL); // window currently has a vertical scrollbar charx = windx / GuiData->CharWidth; chary = windy / GuiData->CharHeight; // Character alignment (round size up or down) - if((windx % GuiData->CharWidth) >= (GuiData->CharWidth / 2)) ++charx; - if((windy % GuiData->CharHeight) >= (GuiData->CharHeight / 2)) ++chary; + if ((windx % GuiData->CharWidth) >= (GuiData->CharWidth / 2)) ++charx; + if ((windy % GuiData->CharHeight) >= (GuiData->CharHeight / 2)) ++chary; // Compensate for added scroll bars in new window - if(charx < Buff->ScreenBufferSize.X)windy -= GetSystemMetrics(SM_CYHSCROLL); // new window will have a horizontal scroll bar - if(chary < Buff->ScreenBufferSize.Y)windx -= GetSystemMetrics(SM_CXVSCROLL); // new window will have a vertical scroll bar + if (charx < Buff->ScreenBufferSize.X)windy -= GetSystemMetrics(SM_CYHSCROLL); // new window will have a horizontal scroll bar + if (chary < Buff->ScreenBufferSize.Y)windx -= GetSystemMetrics(SM_CXVSCROLL); // new window will have a vertical scroll bar charx = windx / GuiData->CharWidth; chary = windy / GuiData->CharHeight; // Character alignment (round size up or down) - if((windx % GuiData->CharWidth) >= (GuiData->CharWidth / 2)) ++charx; - if((windy % GuiData->CharHeight) >= (GuiData->CharHeight / 2)) ++chary; + if ((windx % GuiData->CharWidth) >= (GuiData->CharWidth / 2)) ++charx; + if ((windy % GuiData->CharHeight) >= (GuiData->CharHeight / 2)) ++chary; // Resize window - if((charx != Console->ConsoleSize.X) || (chary != Console->ConsoleSize.Y)) + if ((charx != Console->ConsoleSize.X) || (chary != Console->ConsoleSize.Y)) { Console->ConsoleSize.X = (charx <= Buff->ScreenBufferSize.X) ? charx : Buff->ScreenBufferSize.X; Console->ConsoleSize.Y = (chary <= Buff->ScreenBufferSize.Y) ? chary : Buff->ScreenBufferSize.Y; @@ -1397,8 +1395,8 @@ GuiConsoleResize(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM lParam) GuiConsoleResizeWindow(GuiData); // Adjust the start of the visible area if we are attempting to show nonexistent areas - if((Buff->ScreenBufferSize.X - Buff->ShowX) < Console->ConsoleSize.X) Buff->ShowX = Buff->ScreenBufferSize.X - Console->ConsoleSize.X; - if((Buff->ScreenBufferSize.Y - Buff->ShowY) < Console->ConsoleSize.Y) Buff->ShowY = Buff->ScreenBufferSize.Y - Console->ConsoleSize.Y; + if ((Buff->ScreenBufferSize.X - Buff->ShowX) < Console->ConsoleSize.X) Buff->ShowX = Buff->ScreenBufferSize.X - Console->ConsoleSize.X; + if ((Buff->ScreenBufferSize.Y - Buff->ShowY) < Console->ConsoleSize.Y) Buff->ShowY = Buff->ScreenBufferSize.Y - Console->ConsoleSize.Y; InvalidateRect(GuiData->hWindow, NULL, TRUE); GuiData->WindowSizeLock = FALSE; @@ -1809,7 +1807,7 @@ GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) * So first empty the message queue. */ /* - while(PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE)) + while (PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&Msg); DispatchMessageW(&Msg); @@ -1873,7 +1871,7 @@ GuiConsoleGuiThread(PVOID Data) SetEvent(*GraphicsStartupEvent); - while(GetMessageW(&msg, NULL, 0, 0)) + while (GetMessageW(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessageW(&msg); @@ -2122,114 +2120,10 @@ GuiUpdateScreenInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff) return TRUE; } -static NTSTATUS WINAPI -GuiResizeBuffer(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER ScreenBuffer, COORD Size) +static BOOL WINAPI +GuiIsBufferResizeSupported(PCONSOLE Console) { - BYTE * Buffer; - DWORD Offset = 0; - BYTE * OldPtr; - USHORT CurrentY; - BYTE * OldBuffer; -#ifdef HAVE_WMEMSET - USHORT value = MAKEWORD(' ', ScreenBuffer->ScreenDefaultAttrib); -#else - DWORD i; -#endif - DWORD diff; - - /* Buffer size is not allowed to be smaller than window size */ - if (Size.X < Console->ConsoleSize.X || Size.Y < Console->ConsoleSize.Y) - return STATUS_INVALID_PARAMETER; - - if (Size.X == ScreenBuffer->ScreenBufferSize.X && Size.Y == ScreenBuffer->ScreenBufferSize.Y) - { - // FIXME: Trigger a buffer resize event ?? - return STATUS_SUCCESS; - } - - Buffer = RtlAllocateHeap(ConSrvHeap, 0, Size.X * Size.Y * 2); - if (!Buffer) - return STATUS_NO_MEMORY; - - DPRINT1("Resizing (%d,%d) to (%d,%d)\n", ScreenBuffer->ScreenBufferSize.X, ScreenBuffer->ScreenBufferSize.Y, Size.X, Size.Y); - OldBuffer = ScreenBuffer->Buffer; - - for (CurrentY = 0; CurrentY < ScreenBuffer->ScreenBufferSize.Y && CurrentY < Size.Y; CurrentY++) - { - OldPtr = ConioCoordToPointer(ScreenBuffer, 0, CurrentY); - if (Size.X <= ScreenBuffer->ScreenBufferSize.X) - { - /* reduce size */ - RtlCopyMemory(&Buffer[Offset], OldPtr, Size.X * 2); - Offset += (Size.X * 2); - } - else - { - /* enlarge size */ - RtlCopyMemory(&Buffer[Offset], OldPtr, ScreenBuffer->ScreenBufferSize.X * 2); - Offset += (ScreenBuffer->ScreenBufferSize.X * 2); - - diff = Size.X - ScreenBuffer->ScreenBufferSize.X; - /* zero new part of it */ -#ifdef HAVE_WMEMSET - wmemset((PWCHAR)&Buffer[Offset], value, diff); -#else - for (i = 0; i < diff; i++) - { - Buffer[Offset++] = ' '; - Buffer[Offset++] = ScreenBuffer->ScreenDefaultAttrib; - } -#endif - } - } - - if (Size.Y > ScreenBuffer->ScreenBufferSize.Y) - { - diff = Size.X * (Size.Y - ScreenBuffer->ScreenBufferSize.Y); -#ifdef HAVE_WMEMSET - wmemset((PWCHAR)&Buffer[Offset], value, diff); -#else - for (i = 0; i < diff; i++) - { - Buffer[Offset++] = ' '; - Buffer[Offset++] = ScreenBuffer->ScreenDefaultAttrib; - } -#endif - } - - (void)InterlockedExchangePointer((PVOID volatile*)&ScreenBuffer->Buffer, Buffer); - RtlFreeHeap(ConSrvHeap, 0, OldBuffer); - ScreenBuffer->ScreenBufferSize = Size; - ScreenBuffer->VirtualY = 0; - - /* Ensure cursor and window are within buffer */ - if (ScreenBuffer->CursorPosition.X >= Size.X) - ScreenBuffer->CursorPosition.X = Size.X - 1; - if (ScreenBuffer->CursorPosition.Y >= Size.Y) - ScreenBuffer->CursorPosition.Y = Size.Y - 1; - if (ScreenBuffer->ShowX > Size.X - Console->ConsoleSize.X) - ScreenBuffer->ShowX = Size.X - Console->ConsoleSize.X; - if (ScreenBuffer->ShowY > Size.Y - Console->ConsoleSize.Y) - ScreenBuffer->ShowY = Size.Y - Console->ConsoleSize.Y; - - /* - * Trigger a buffer resize event - */ - if (Console->InputBuffer.Mode & ENABLE_WINDOW_INPUT) - { - INPUT_RECORD er; - - er.EventType = WINDOW_BUFFER_SIZE_EVENT; - er.Event.WindowBufferSizeEvent.dwSize = ScreenBuffer->ScreenBufferSize; - - ConioProcessInputEvent(Console, &er); - } - - /* TODO: Should update scrollbar, but can't use anything that - * calls SendMessage or it could cause deadlock --> Use PostMessage */ - // TODO: Tell the terminal to resize its scrollbars. - - return STATUS_SUCCESS; + return TRUE; } static VOID WINAPI @@ -2365,7 +2259,7 @@ static FRONTEND_VTBL GuiVtbl = GuiSetCursorInfo, GuiSetScreenInfo, GuiUpdateScreenInfo, - GuiResizeBuffer, + GuiIsBufferResizeSupported, GuiResizeTerminal, GuiProcessKeyCallback, GuiRefreshInternalInfo, diff --git a/win32ss/user/consrv/frontends/tui/tuiterm.c b/win32ss/user/consrv/frontends/tui/tuiterm.c index c1d870ccc6d..2ff25475133 100644 --- a/win32ss/user/consrv/frontends/tui/tuiterm.c +++ b/win32ss/user/consrv/frontends/tui/tuiterm.c @@ -2,18 +2,18 @@ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Console Server DLL * FILE: win32ss/user/consrv/frontends/tui/tuiterm.c - * PURPOSE: TUI Terminal Front-End + * PURPOSE: TUI Terminal Front-End - Virtual Consoles... * PROGRAMMERS: David Welch * Gé van Geldorp * Jeffrey Morlan * Hermes Belusca-Maito (hermes.belusca@sfr.fr) */ -#ifdef TUI_CONSOLE - #include "consrv.h" -#include "settings.h" -#include "tuiconsole.h" +#include "include/conio.h" +// #include "include/console.h" +#include "include/settings.h" +#include "tuiterm.h" #include #define NDEBUG @@ -22,24 +22,35 @@ /* GLOBALS ********************************************************************/ +#define GetNextConsole(Console) \ + CONTAINING_RECORD(Console->Entry.Flink, TUI_CONSOLE_DATA, Entry) + +#define GetPrevConsole(Console) \ + CONTAINING_RECORD(Console->Entry.Blink, TUI_CONSOLE_DATA, Entry) + + /* TUI Console Window Class name */ #define TUI_CONSOLE_WINDOW_CLASS L"TuiConsoleWindowClass" typedef struct _TUI_CONSOLE_DATA { CRITICAL_SECTION Lock; + LIST_ENTRY Entry; /* Entry in the list of virtual consoles */ // HANDLE hTuiInitEvent; - HWND hWindow; + HWND hWindow; /* Handle to the console's window (used for the window's procedure */ - PCONSOLE Console; - // TUI_CONSOLE_INFO TuiInfo; + PCONSOLE Console; /* Pointer to the owned console */ + // TUI_CONSOLE_INFO TuiInfo; /* TUI terminal settings */ } TUI_CONSOLE_DATA, *PTUI_CONSOLE_DATA; -CRITICAL_SECTION ActiveConsoleLock; +/* List of the maintained virtual consoles and its lock */ +static LIST_ENTRY VirtConsList; +static PTUI_CONSOLE_DATA ActiveConsole; /* The active console on screen */ +static CRITICAL_SECTION ActiveVirtConsLock; + static COORD PhysicalConsoleSize; static HANDLE ConsoleDeviceHandle; -static PCONSOLE ActiveConsole; static BOOL ConsInitialized = FALSE; @@ -153,24 +164,10 @@ done: /**\ \******************************************************************************/ -static LRESULT CALLBACK -TuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (msg == WM_ACTIVATE) - { - if (LOWORD(wParam) != WA_INACTIVE) - { - SetFocus(hWnd); - ConioDrawConsole(ActiveConsole); - } - } - return DefWindowProcW(hWnd, msg, wParam, lParam); -} - static BOOL FASTCALL TuiSwapConsole(INT Next) { - static PCONSOLE SwapConsole = NULL; /* console we are thinking about swapping with */ + static PTUI_CONSOLE_DATA SwapConsole = NULL; /* Console we are thinking about swapping with */ DWORD BytesReturned; ANSI_STRING Title; PVOID Buffer; @@ -178,28 +175,26 @@ TuiSwapConsole(INT Next) if (0 != Next) { - /* alt-tab, swap consoles */ - /* move SwapConsole to next console, and print its title */ - EnterCriticalSection(&ActiveConsoleLock); - if (!SwapConsole) - { - SwapConsole = ActiveConsole; - } + /* + * Alt-Tab, swap consoles. + * move SwapConsole to next console, and print its title. + */ + EnterCriticalSection(&ActiveVirtConsLock); + if (!SwapConsole) SwapConsole = ActiveConsole; - SwapConsole = (0 < Next ? SwapConsole->Next : SwapConsole->Prev); - Title.MaximumLength = RtlUnicodeStringToAnsiSize(&SwapConsole->Title); + SwapConsole = (0 < Next ? GetNextConsole(SwapConsole) : GetPrevConsole(SwapConsole)); + Title.MaximumLength = RtlUnicodeStringToAnsiSize(&SwapConsole->Console->Title); Title.Length = 0; - Buffer = RtlAllocateHeap(ConSrvHeap, - 0, - sizeof(COORD) + Title.MaximumLength); - pos = (PCOORD )Buffer; - Title.Buffer = (PVOID)((ULONG_PTR)Buffer + sizeof( COORD )); + Buffer = RtlAllocateHeap(ConSrvHeap, 0, + sizeof(COORD) + Title.MaximumLength); + pos = (PCOORD)Buffer; + Title.Buffer = (PVOID)((ULONG_PTR)Buffer + sizeof(COORD)); - RtlUnicodeStringToAnsiString(&Title, &SwapConsole->Title, FALSE); - pos->Y = PhysicalConsoleSize.Y / 2; + RtlUnicodeStringToAnsiString(&Title, &SwapConsole->Console->Title, FALSE); pos->X = (PhysicalConsoleSize.X - Title.Length) / 2; - /* redraw the console to clear off old title */ - ConioDrawConsole(ActiveConsole); + 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)) @@ -207,28 +202,28 @@ TuiSwapConsole(INT Next) DPRINT1( "Error writing to console\n" ); } RtlFreeHeap(ConSrvHeap, 0, Buffer); - LeaveCriticalSection(&ActiveConsoleLock); + LeaveCriticalSection(&ActiveVirtConsLock); return TRUE; } else if (NULL != SwapConsole) { - EnterCriticalSection(&ActiveConsoleLock); + EnterCriticalSection(&ActiveVirtConsLock); if (SwapConsole != ActiveConsole) { - /* first remove swapconsole from the list */ - SwapConsole->Prev->Next = SwapConsole->Next; - SwapConsole->Next->Prev = SwapConsole->Prev; - /* now insert before activeconsole */ - SwapConsole->Next = ActiveConsole; - SwapConsole->Prev = ActiveConsole->Prev; - ActiveConsole->Prev->Next = SwapConsole; - ActiveConsole->Prev = SwapConsole; + /* 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); - LeaveCriticalSection(&ActiveConsoleLock); + ConioDrawConsole(ActiveConsole->Console); + LeaveCriticalSection(&ActiveVirtConsLock); return TRUE; } else @@ -237,92 +232,6 @@ TuiSwapConsole(INT Next) } } -static BOOL WINAPI -TuiProcessKeyCallback(PCONSOLE Console, MSG* msg, BYTE KeyStateMenu, DWORD ShiftState, UINT VirtualKeyCode, BOOL Down) -{ - if (0 != (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) && - VK_TAB == VirtualKeyCode) - { - if (Down) - { - TuiSwapConsole(ShiftState & SHIFT_PRESSED ? -1 : 1); - } - - return TRUE; - } - else if (VK_MENU == VirtualKeyCode && !Down) - { - return TuiSwapConsole(0); - } - - return FALSE; -} - -static BOOL FASTCALL -TuiInit(DWORD OemCP) -{ - CONSOLE_SCREEN_BUFFER_INFO ScrInfo; - DWORD BytesReturned; - WNDCLASSEXW wc; - ATOM ConsoleClassAtom; - USHORT TextAttribute = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; - - ScmLoadDriver(L"Blue"); - - ConsoleDeviceHandle = CreateFileW(L"\\\\.\\BlueScreen", FILE_ALL_ACCESS, 0, NULL, - OPEN_EXISTING, 0, NULL); - if (INVALID_HANDLE_VALUE == ConsoleDeviceHandle) - { - DPRINT1("Failed to open BlueScreen.\n"); - return FALSE; - } - - if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_LOADFONT, - &OemCP, sizeof(OemCP), NULL, 0, - &BytesReturned, NULL)) - { - DPRINT1("Failed to load the font for codepage %d\n", OemCP); - /* Let's suppose the font is good enough to continue */ - } - - if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE, - &TextAttribute, sizeof(TextAttribute), NULL, 0, - &BytesReturned, NULL)) - { - DPRINT1("Failed to set text attribute\n"); - } - - ActiveConsole = NULL; - InitializeCriticalSection(&ActiveConsoleLock); - if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO, - NULL, 0, &ScrInfo, sizeof(ScrInfo), &BytesReturned, NULL)) - { - DPRINT1("Failed to get console info\n"); - return FALSE; - } - PhysicalConsoleSize = ScrInfo.dwSize; - - RtlZeroMemory(&wc, sizeof(WNDCLASSEXW)); - wc.cbSize = sizeof(WNDCLASSEXW); - wc.lpszClassName = TUI_CONSOLE_WINDOW_CLASS; - wc.lpfnWndProc = TuiConsoleWndProc; - wc.cbWndExtra = GWLP_CONSOLEWND_ALLOC; - wc.hInstance = ConSrvDllInstance; - - ConsoleClassAtom = RegisterClassExW(&wc); - if (ConsoleClassAtom == 0) - { - DPRINT1("Failed to register TUI console wndproc\n"); - return FALSE; - } - else - { - NtUserConsoleControl(TuiConsoleWndClassAtom, &ConsoleClassAtom, sizeof(ATOM)); - } - - return TRUE; -} - static VOID FASTCALL TuiCopyRect(char *Dest, PCONSOLE_SCREEN_BUFFER Buff, SMALL_RECT* Region) { @@ -346,6 +255,211 @@ TuiCopyRect(char *Dest, PCONSOLE_SCREEN_BUFFER Buff, SMALL_RECT* Region) } } +static LRESULT CALLBACK +TuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (msg == WM_ACTIVATE) + { + if (LOWORD(wParam) != WA_INACTIVE) + { + SetFocus(hWnd); + ConioDrawConsole(ActiveConsole->Console); + } + } + return DefWindowProcW(hWnd, msg, wParam, lParam); +} + +static DWORD WINAPI +TuiConsoleThread(PVOID Data) +{ + PTUI_CONSOLE_DATA TuiData = (PTUI_CONSOLE_DATA)Data; + PCONSOLE Console = TuiData->Console; + HWND NewWindow; + MSG msg; + + NewWindow = CreateWindowW(TUI_CONSOLE_WINDOW_CLASS, + Console->Title.Buffer, + 0, + -32000, -32000, 0, 0, + NULL, NULL, + ConSrvDllInstance, + (PVOID)Console); + if (NULL == NewWindow) + { + DPRINT1("CONSRV: Unable to create console window\n"); + return 1; + } + TuiData->hWindow = NewWindow; + + SetForegroundWindow(TuiData->hWindow); + NtUserConsoleControl(ConsoleAcquireDisplayOwnership, NULL, 0); + + while (GetMessageW(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessageW(&msg); + + if (msg.message == WM_CHAR || msg.message == WM_SYSCHAR || + msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN || + msg.message == WM_KEYUP || msg.message == WM_SYSKEYUP) + { + ConioProcessKey(Console, &msg); + } + } + + return 0; +} + +static BOOL +TuiInit(DWORD OemCP) +{ + BOOL Ret = FALSE; + CONSOLE_SCREEN_BUFFER_INFO ScrInfo; + DWORD BytesReturned; + WNDCLASSEXW wc; + ATOM ConsoleClassAtom; + USHORT TextAttribute = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; + + /* Exit if we were already initialized */ + if (ConsInitialized) return TRUE; + + /* + * Initialize the TUI front-end: + * - load the console driver, + * - set default screen attributes, + * - grab the console size. + */ + ScmLoadDriver(L"Blue"); + + ConsoleDeviceHandle = CreateFileW(L"\\\\.\\BlueScreen", + FILE_ALL_ACCESS, + 0, NULL, + OPEN_EXISTING, + 0, NULL); + if (INVALID_HANDLE_VALUE == ConsoleDeviceHandle) + { + DPRINT1("Failed to open BlueScreen.\n"); + return FALSE; + } + + if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_LOADFONT, + &OemCP, sizeof(OemCP), NULL, 0, + &BytesReturned, NULL)) + { + DPRINT1("Failed to load the font for codepage %d\n", OemCP); + /* Let's suppose the font is good enough to continue */ + } + + if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE, + &TextAttribute, sizeof(TextAttribute), NULL, 0, + &BytesReturned, NULL)) + { + DPRINT1("Failed to set text attribute\n"); + } + + ActiveConsole = NULL; + InitializeListHead(&VirtConsList); + InitializeCriticalSection(&ActiveVirtConsLock); + + if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO, + NULL, 0, &ScrInfo, sizeof(ScrInfo), &BytesReturned, NULL)) + { + DPRINT1("Failed to get console info\n"); + Ret = FALSE; + goto Quit; + } + PhysicalConsoleSize = ScrInfo.dwSize; + + /* Register the TUI notification window class */ + RtlZeroMemory(&wc, sizeof(WNDCLASSEXW)); + wc.cbSize = sizeof(WNDCLASSEXW); + wc.lpszClassName = TUI_CONSOLE_WINDOW_CLASS; + wc.lpfnWndProc = TuiConsoleWndProc; + wc.cbWndExtra = 0; + wc.hInstance = ConSrvDllInstance; + + ConsoleClassAtom = RegisterClassExW(&wc); + if (ConsoleClassAtom == 0) + { + DPRINT1("Failed to register TUI console wndproc\n"); + Ret = FALSE; + } + else + { + Ret = TRUE; + } + +Quit: + if (Ret == FALSE) + { + DeleteCriticalSection(&ActiveVirtConsLock); + CloseHandle(ConsoleDeviceHandle); + } + + ConsInitialized = Ret; + return Ret; +} + + + +/****************************************************************************** + * TUI Console Driver * + ******************************************************************************/ + +static VOID WINAPI +TuiCleanupConsole(PCONSOLE Console) +{ + PTUI_CONSOLE_DATA TuiData = 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; + DeleteCriticalSection(&TuiData->Lock); + RtlFreeHeap(ConSrvHeap, 0, TuiData); +} + +static VOID WINAPI +TuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, LONG CursorStartX, LONG CursorStartY, + UINT ScrolledLines, CHAR *Buffer, UINT Length) +{ + DWORD BytesWritten; + PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer; + + if (ActiveConsole->Console->ActiveBuffer != Buff) return; + + if (!WriteFile(ConsoleDeviceHandle, Buffer, Length, &BytesWritten, NULL)) + { + DPRINT1("Error writing to BlueScreen\n"); + } +} + static VOID WINAPI TuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region) { @@ -354,10 +468,7 @@ TuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region) PCONSOLE_DRAW ConsoleDraw; UINT ConsoleDrawSize; - if (ActiveConsole != Console) - { - return; - } + if (ActiveConsole->Console != Console) return; ConsoleDrawSize = sizeof(CONSOLE_DRAW) + (ConioRectWidth(Region) * ConioRectHeight(Region)) * 2; @@ -387,34 +498,13 @@ TuiDrawRegion(PCONSOLE Console, SMALL_RECT* Region) RtlFreeHeap(ConSrvHeap, 0, ConsoleDraw); } -static VOID WINAPI -TuiWriteStream(PCONSOLE Console, SMALL_RECT* Region, LONG CursorStartX, LONG CursorStartY, - UINT ScrolledLines, CHAR *Buffer, UINT Length) -{ - DWORD BytesWritten; - PCONSOLE_SCREEN_BUFFER Buff = Console->ActiveBuffer; - - if (ActiveConsole->ActiveBuffer != Buff) - { - return; - } - - if (!WriteFile(ConsoleDeviceHandle, Buffer, Length, &BytesWritten, NULL)) - { - DPRINT1("Error writing to BlueScreen\n"); - } -} - static BOOL WINAPI TuiSetCursorInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff) { CONSOLE_CURSOR_INFO Info; DWORD BytesReturned; - if (ActiveConsole->ActiveBuffer != Buff) - { - return TRUE; - } + if (ActiveConsole->Console->ActiveBuffer != Buff) return TRUE; Info.dwSize = ConioEffectiveCursorSize(Console, 100); Info.bVisible = Buff->CursorInfo.bVisible; @@ -435,10 +525,7 @@ TuiSetScreenInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff, UINT OldCursorX, CONSOLE_SCREEN_BUFFER_INFO Info; DWORD BytesReturned; - if (ActiveConsole->ActiveBuffer != Buff) - { - return TRUE; - } + if (ActiveConsole->Console->ActiveBuffer != Buff) return TRUE; Info.dwCursorPosition = Buff->CursorPosition; Info.wAttributes = Buff->ScreenDefaultAttrib; @@ -460,35 +547,46 @@ TuiUpdateScreenInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff) return TRUE; } +static BOOL WINAPI +TuiIsBufferResizeSupported(PCONSOLE Console) +{ + return (Console && Console->State == CONSOLE_INITIALIZING ? TRUE : FALSE); +} + static VOID WINAPI -TuiChangeTitle(PCONSOLE Console) +TuiResizeTerminal(PCONSOLE Console) +{ +} + +static BOOL WINAPI +TuiProcessKeyCallback(PCONSOLE Console, MSG* msg, BYTE KeyStateMenu, DWORD ShiftState, UINT VirtualKeyCode, BOOL Down) +{ + if (0 != (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) && + VK_TAB == VirtualKeyCode) + { + if (Down) + { + TuiSwapConsole(ShiftState & SHIFT_PRESSED ? -1 : 1); + } + + return TRUE; + } + else if (VK_MENU == VirtualKeyCode && !Down) + { + return TuiSwapConsole(0); + } + + return FALSE; +} + +static VOID WINAPI +TuiRefreshInternalInfo(PCONSOLE Console) { } static VOID WINAPI -TuiCleanupConsole(PCONSOLE Console) +TuiChangeTitle(PCONSOLE Console) { - DestroyWindow(Console->hWindow); - - EnterCriticalSection(&ActiveConsoleLock); - - /* Switch to next console */ - if (ActiveConsole == Console) - { - ActiveConsole = Console->Next != Console ? Console->Next : NULL; - } - - if (Console->Next != Console) - { - Console->Prev->Next = Console->Next; - Console->Next->Prev = Console->Prev; - } - LeaveCriticalSection(&ActiveConsoleLock); - - if (NULL != ActiveConsole) - { - ConioDrawConsole(ActiveConsole); - } } static BOOL WINAPI @@ -500,57 +598,18 @@ TuiChangeIcon(PCONSOLE Console, HICON hWindowIcon) static HWND WINAPI TuiGetConsoleWindowHandle(PCONSOLE Console) { - return Console->hWindow; + PTUI_CONSOLE_DATA TuiData = Console->TermIFace.Data; + return TuiData->hWindow; } -static NTSTATUS WINAPI -TuiResizeBuffer(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER ScreenBuffer, COORD Size) +static VOID WINAPI +TuiGetLargestConsoleWindowSize(PCONSOLE Console, PCOORD pSize) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + if (!pSize) return; + *pSize = PhysicalConsoleSize; } -static DWORD WINAPI -TuiConsoleThread(PVOID Data) -{ - PCONSOLE Console = (PCONSOLE) Data; - HWND NewWindow; - MSG msg; - - NewWindow = CreateWindowW(TUI_CONSOLE_WINDOW_CLASS, - Console->Title.Buffer, - 0, - -32000, -32000, 0, 0, - NULL, NULL, - ConSrvDllInstance, - (PVOID)Console); - if (NULL == NewWindow) - { - DPRINT1("CONSRV: Unable to create console window\n"); - return 1; - } - Console->hWindow = NewWindow; - - SetForegroundWindow(Console->hWindow); - - while (TRUE) - { - GetMessageW(&msg, 0, 0, 0); - DispatchMessage(&msg); - TranslateMessage(&msg); - - if (msg.message == WM_CHAR || msg.message == WM_SYSCHAR || - msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN || - msg.message == WM_KEYUP || msg.message == WM_SYSKEYUP) - { - ConioProcessKey(Console, &msg); - } - } - - return 0; -} - -static TERMINAL_VTBL TuiVtbl = +static FRONTEND_VTBL TuiVtbl = { TuiCleanupConsole, TuiWriteStream, @@ -558,72 +617,86 @@ static TERMINAL_VTBL TuiVtbl = TuiSetCursorInfo, TuiSetScreenInfo, TuiUpdateScreenInfo, + TuiIsBufferResizeSupported, + TuiResizeTerminal, + TuiProcessKeyCallback, + TuiRefreshInternalInfo, TuiChangeTitle, TuiChangeIcon, TuiGetConsoleWindowHandle, - TuiResizeBuffer, - TuiProcessKeyCallback + TuiGetLargestConsoleWindowSize }; NTSTATUS FASTCALL TuiInitConsole(PCONSOLE Console, - PCONSOLE_INFO ConsoleInfo) + /*IN*/ PCONSOLE_START_INFO ConsoleStartInfo, + PCONSOLE_INFO ConsoleInfo, + DWORD ProcessId) { + PTUI_CONSOLE_DATA TuiData; HANDLE ThreadHandle; - if (!ConsInitialized) - { - ConsInitialized = TRUE; - if (!TuiInit(Console->CodePage)) - { - ConsInitialized = FALSE; - return STATUS_UNSUCCESSFUL; - } - } + if (Console == NULL || ConsoleInfo == NULL) + return STATUS_INVALID_PARAMETER; + /* Initialize the TUI terminal emulator */ + if (!TuiInit(Console->CodePage)) return STATUS_UNSUCCESSFUL; + + /* Initialize the console */ Console->TermIFace.Vtbl = &TuiVtbl; - Console->hWindow = NULL; - Console->Size = PhysicalConsoleSize; - Console->ActiveBuffer->ScreenBufferSize = PhysicalConsoleSize; + TuiData = RtlAllocateHeap(ConSrvHeap, HEAP_ZERO_MEMORY, + sizeof(TUI_CONSOLE_DATA)); + if (!TuiData) + { + DPRINT1("CONSRV: Failed to create TUI_CONSOLE_DATA\n"); + return STATUS_UNSUCCESSFUL; + } + Console->TermIFace.Data = (PVOID)TuiData; + TuiData->Console = Console; + TuiData->hWindow = NULL; + + InitializeCriticalSection(&TuiData->Lock); + + /* + * HACK: Resize the console since we don't support for now changing + * the console size when we display it with the hardware. + */ + Console->ConsoleSize = PhysicalConsoleSize; + ConioResizeBuffer(Console, Console->ActiveBuffer, PhysicalConsoleSize); + Console->ActiveBuffer->DisplayMode |= CONSOLE_FULLSCREEN_MODE; + // ConioResizeTerminal(Console); + + /* + * Contrary to what we do in the GUI front-end, here we create + * an input thread for each console. It will dispatch all the + * input messages to the proper console (on the GUI it is done + * via the default GUI dispatch thread). + */ ThreadHandle = CreateThread(NULL, 0, TuiConsoleThread, - (PVOID)Console, + (PVOID)TuiData, 0, NULL); if (NULL == ThreadHandle) { DPRINT1("CONSRV: Unable to create console thread\n"); + TuiCleanupConsole(Console); return STATUS_UNSUCCESSFUL; } CloseHandle(ThreadHandle); - EnterCriticalSection(&ActiveConsoleLock); - if (NULL != ActiveConsole) - { - Console->Prev = ActiveConsole; - Console->Next = ActiveConsole->Next; - ActiveConsole->Next->Prev = Console; - ActiveConsole->Next = Console; - } - else - { - Console->Prev = Console; - Console->Next = Console; - } - ActiveConsole = Console; - LeaveCriticalSection(&ActiveConsoleLock); + /* + * Insert the newly created console in the list of virtual consoles + * and activate it (give it the focus). + */ + EnterCriticalSection(&ActiveVirtConsLock); + InsertTailList(&VirtConsList, &TuiData->Entry); + ActiveConsole = TuiData; + LeaveCriticalSection(&ActiveVirtConsLock); return STATUS_SUCCESS; } -PCONSOLE FASTCALL -TuiGetFocusConsole(VOID) -{ - return ActiveConsole; -} - -#endif - /* EOF */ diff --git a/win32ss/user/consrv/frontends/tui/tuiterm.h b/win32ss/user/consrv/frontends/tui/tuiterm.h index 8a4efa91b8a..4e349e20bfc 100644 --- a/win32ss/user/consrv/frontends/tui/tuiterm.h +++ b/win32ss/user/consrv/frontends/tui/tuiterm.h @@ -9,10 +9,11 @@ * Hermes Belusca-Maito (hermes.belusca@sfr.fr) */ -#include "conio.h" +#pragma once NTSTATUS FASTCALL TuiInitConsole(PCONSOLE Console, - PCONSOLE_INFO ConsoleInfo); -PCONSOLE FASTCALL TuiGetFocusConsole(VOID); + /*IN*/ PCONSOLE_START_INFO ConsoleStartInfo, + PCONSOLE_INFO ConsoleInfo, + DWORD ProcessId); /* EOF */ diff --git a/win32ss/user/consrv/include/conio.h b/win32ss/user/consrv/include/conio.h index fc41d94002e..c7960f3afb2 100644 --- a/win32ss/user/consrv/include/conio.h +++ b/win32ss/user/consrv/include/conio.h @@ -108,9 +108,7 @@ typedef struct _FRONTEND_VTBL UINT OldCursorY); BOOL (WINAPI *UpdateScreenInfo)(struct _CONSOLE* Console, PCONSOLE_SCREEN_BUFFER ScreenBuffer); - NTSTATUS (WINAPI *ResizeBuffer)(struct _CONSOLE* Console, - PCONSOLE_SCREEN_BUFFER ScreenBuffer, - COORD Size); + BOOL (WINAPI *IsBufferResizeSupported)(struct _CONSOLE* Console); VOID (WINAPI *ResizeTerminal)(struct _CONSOLE* Console); BOOL (WINAPI *ProcessKeyCallback)(struct _CONSOLE* Console, MSG* msg, @@ -156,7 +154,6 @@ typedef struct _CONSOLE CRITICAL_SECTION Lock; CONSOLE_STATE State; /* State of the console */ - // struct _CONSOLE *Prev, *Next; /* Next and Prev consoles in console wheel */ LIST_ENTRY Entry; /* Entry in the list of consoles */ LIST_ENTRY ProcessList; /* List of processes owning the console. The first one is the so-called "Console Leader Process" */ @@ -230,10 +227,19 @@ NTSTATUS FASTCALL ConioProcessInputEvent(PCONSOLE Console, #define ConioRectWidth(Rect) \ (((Rect)->Left) > ((Rect)->Right) ? 0 : ((Rect)->Right) - ((Rect)->Left) + 1) -PBYTE FASTCALL ConioCoordToPointer(PCONSOLE_SCREEN_BUFFER Buf, ULONG X, ULONG Y); +PBYTE FASTCALL ConioCoordToPointer(PCONSOLE_SCREEN_BUFFER Buf, + ULONG X, + ULONG Y); VOID FASTCALL ConioDrawConsole(PCONSOLE Console); -NTSTATUS FASTCALL ConioWriteConsole(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff, - CHAR *Buffer, DWORD Length, BOOL Attrib); -DWORD FASTCALL ConioEffectiveCursorSize(PCONSOLE Console, DWORD Scale); +NTSTATUS FASTCALL ConioResizeBuffer(PCONSOLE Console, + PCONSOLE_SCREEN_BUFFER ScreenBuffer, + COORD Size); +NTSTATUS FASTCALL ConioWriteConsole(PCONSOLE Console, + PCONSOLE_SCREEN_BUFFER Buff, + CHAR *Buffer, + DWORD Length, + BOOL Attrib); +DWORD FASTCALL ConioEffectiveCursorSize(PCONSOLE Console, + DWORD Scale); /* EOF */ diff --git a/win32ss/user/ntuser/ntstubs.c b/win32ss/user/ntuser/ntstubs.c index fc41f80d3ed..adbc4b85903 100644 --- a/win32ss/user/ntuser/ntstubs.c +++ b/win32ss/user/ntuser/ntstubs.c @@ -584,20 +584,8 @@ NtUserConsoleControl( break; } - case TuiConsoleWndClassAtom: + case ConsoleAcquireDisplayOwnership: { - _SEH2_TRY - { - ProbeForRead(ConsoleCtrlInfo, ConsoleCtrlInfoLength, 1); - ASSERT(ConsoleCtrlInfoLength == sizeof(ATOM)); - gaTuiConsoleWndClass = *(ATOM*)ConsoleCtrlInfo; - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - Status = _SEH2_GetExceptionCode(); - } - _SEH2_END; - break; } diff --git a/win32ss/user/ntuser/ntuser.c b/win32ss/user/ntuser/ntuser.c index 5e0499e6b73..f496e420a15 100644 --- a/win32ss/user/ntuser/ntuser.c +++ b/win32ss/user/ntuser/ntuser.c @@ -22,7 +22,6 @@ HINSTANCE hModClient = NULL; BOOL ClientPfnInit = FALSE; PEPROCESS gpepCSRSS = NULL; ATOM gaGuiConsoleWndClass; -ATOM gaTuiConsoleWndClass; /* PRIVATE FUNCTIONS *********************************************************/ diff --git a/win32ss/user/ntuser/ntuser.h b/win32ss/user/ntuser/ntuser.h index a3ad0216785..2206f30daba 100644 --- a/win32ss/user/ntuser/ntuser.h +++ b/win32ss/user/ntuser/ntuser.h @@ -17,7 +17,6 @@ extern PPROCESSINFO ppiScrnSaver; extern PPROCESSINFO gppiInputProvider; extern PEPROCESS gpepCSRSS; extern ATOM gaGuiConsoleWndClass; -extern ATOM gaTuiConsoleWndClass; INIT_FUNCTION NTSTATUS NTAPI InitUserImpl(VOID); VOID FASTCALL CleanupUserImpl(VOID); diff --git a/win32ss/user/ntuser/window.c b/win32ss/user/ntuser/window.c index 8f4be712175..5a32227a3fc 100644 --- a/win32ss/user/ntuser/window.c +++ b/win32ss/user/ntuser/window.c @@ -3741,8 +3741,7 @@ NtUserQueryWindow(HWND hWnd, DWORD Index) case QUERY_WINDOW_UNIQUE_PROCESS_ID: { if ( (pWnd->head.pti->TIF_flags & TIF_CSRSSTHREAD) && - ( (pWnd->pcls->atomClassName == gaGuiConsoleWndClass) || - (pWnd->pcls->atomClassName == gaTuiConsoleWndClass) ) ) + (pWnd->pcls->atomClassName == gaGuiConsoleWndClass) ) { // IntGetWindowLong(offset == GWLP_CONSOLE_LEADER_PID) Result = (DWORD)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_PID))); @@ -3757,8 +3756,7 @@ NtUserQueryWindow(HWND hWnd, DWORD Index) case QUERY_WINDOW_UNIQUE_THREAD_ID: { if ( (pWnd->head.pti->TIF_flags & TIF_CSRSSTHREAD) && - ( (pWnd->pcls->atomClassName == gaGuiConsoleWndClass) || - (pWnd->pcls->atomClassName == gaTuiConsoleWndClass) ) ) + (pWnd->pcls->atomClassName == gaGuiConsoleWndClass) ) { // IntGetWindowLong(offset == GWLP_CONSOLE_LEADER_TID) Result = (DWORD)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_TID)));