- Reintegrate the text-only frontend, deactivated in revision r58447.
- Use a (temporary) helper ConioIsBufferResizeSupported to know whether or not the frontend supports screenbuffer resizing. In a near future, all the frontends will support that so this function will be removed.
- Promote ConioResizeBuffer to be a function of the console server (not only reserved for the GUI frontend).

[WIN32K]
- Remove the support of registrating TUI notification window class (feature such as knowing at which console app the notification window belongs to is unneeded when using the TUI).
- Start to introduce ConsoleAcquireDisplayOwnership, a win32k console control to let win32k release the display so that we can own it (it is step 0.0.1 on a scale of 0.0.0 to 1.0.0).

Note that, as in trunk, getting a text-only interface when booting with the /CONSOLE switch still doesn't work (clash between text-mode and video-mode enabled by win32k).

svn path=/branches/ros-csrss/; revision=58732
This commit is contained in:
Hermès Bélusca-Maïto 2013-04-11 23:37:09 +00:00
parent 2b02f27941
commit 0777ed55e5
14 changed files with 556 additions and 494 deletions

View file

@ -1566,7 +1566,7 @@ NtUserCloseWindowStation(
typedef enum _CONSOLECONTROL
{
GuiConsoleWndClassAtom,
TuiConsoleWndClassAtom,
ConsoleAcquireDisplayOwnership,
} CONSOLECONTROL, *PCONSOLECONTROL;
NTSTATUS

View file

@ -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;

View file

@ -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))

View file

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

View file

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

View file

@ -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:

View file

@ -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,

View file

@ -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
* 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 <drivers/blue/ntddblue.h>
#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 */

View file

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

View file

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

View file

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

View file

@ -22,7 +22,6 @@ HINSTANCE hModClient = NULL;
BOOL ClientPfnInit = FALSE;
PEPROCESS gpepCSRSS = NULL;
ATOM gaGuiConsoleWndClass;
ATOM gaTuiConsoleWndClass;
/* PRIVATE FUNCTIONS *********************************************************/

View file

@ -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);

View file

@ -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)));