more light-weight gui consoles that don't double-buffer the console screen

svn path=/trunk/; revision=19710
This commit is contained in:
Thomas Bluemel 2005-11-27 23:18:12 +00:00
parent 731c8ee507
commit 08d15d11e3
2 changed files with 168 additions and 176 deletions

View file

@ -27,8 +27,6 @@ typedef struct GUI_CONSOLE_DATA_TAG
BOOL CursorBlinkOn; BOOL CursorBlinkOn;
BOOL ForceCursorOff; BOOL ForceCursorOff;
CRITICAL_SECTION Lock; CRITICAL_SECTION Lock;
HDC MemoryDC;
HBITMAP MemoryBitmap;
RECT Selection; RECT Selection;
POINT SelectionStart; POINT SelectionStart;
BOOL MouseDown; BOOL MouseDown;
@ -122,15 +120,6 @@ GuiConsoleHandleNcCreate(HWND hWnd, CREATESTRUCTW *Create)
GuiData->CharHeight = Metrics.tmHeight + Metrics.tmExternalLeading; GuiData->CharHeight = Metrics.tmHeight + Metrics.tmExternalLeading;
SelectObject(Dc, OldFont); SelectObject(Dc, OldFont);
GuiData->MemoryDC = CreateCompatibleDC(Dc);
GuiData->MemoryBitmap = CreateCompatibleBitmap(Dc,
Console->Size.X * GuiData->CharWidth,
Console->Size.Y * GuiData->CharHeight);
/* NOTE: Don't delete the "first bitmap", it's done in DeleteDC. */
SelectObject(GuiData->MemoryDC, GuiData->MemoryBitmap);
/* NOTE: Don't delete stock font. */
SelectObject(GuiData->MemoryDC, GuiData->Font);
ReleaseDC(hWnd, Dc); ReleaseDC(hWnd, Dc);
GuiData->CursorBlinkOn = TRUE; GuiData->CursorBlinkOn = TRUE;
GuiData->ForceCursorOff = FALSE; GuiData->ForceCursorOff = FALSE;
@ -249,149 +238,187 @@ GuiConsoleUpdateSelection(HWND hWnd, PRECT rc, PGUI_CONSOLE_DATA GuiData)
} }
VOID FASTCALL static VOID FASTCALL
GuiConsoleUpdateBitmap(HWND hWnd, RECT rc) GuiConsolePaint(PCSRSS_CONSOLE Console,
PGUI_CONSOLE_DATA GuiData,
HDC hDC,
PRECT rc)
{ {
PCSRSS_CONSOLE Console; PCSRSS_SCREEN_BUFFER Buff;
PGUI_CONSOLE_DATA GuiData; ULONG TopLine, BottomLine, LeftChar, RightChar;
PCSRSS_SCREEN_BUFFER Buff; ULONG Line, Char, Start;
HDC Dc; PBYTE From;
ULONG TopLine, BottomLine, LeftChar, RightChar; PWCHAR To;
ULONG Line, Char, Start; BYTE LastAttribute, Attribute;
PBYTE From; ULONG CursorX, CursorY, CursorHeight;
PWCHAR To; HBRUSH CursorBrush, OldBrush;
BYTE LastAttribute, Attribute; HFONT OldFont;
ULONG CursorX, CursorY, CursorHeight;
HBRUSH CursorBrush, OldBrush;
GuiConsoleGetDataPointers(hWnd, &Console, &GuiData); Buff = Console->ActiveBuffer;
if (NULL != Console && NULL != GuiData && NULL != Console->ActiveBuffer)
TopLine = rc->top / GuiData->CharHeight;
BottomLine = (rc->bottom + (GuiData->CharHeight - 1)) / GuiData->CharHeight - 1;
LeftChar = rc->left / GuiData->CharWidth;
RightChar = (rc->right + (GuiData->CharWidth - 1)) / GuiData->CharWidth - 1;
LastAttribute = Buff->Buffer[(TopLine * Buff->MaxX + LeftChar) * 2 + 1];
GuiConsoleSetTextColors(hDC,
LastAttribute);
EnterCriticalSection(&Buff->Header.Lock);
OldFont = SelectObject(hDC,
GuiData->Font);
for (Line = TopLine; Line <= BottomLine; Line++)
{ {
Buff = Console->ActiveBuffer; if (Line + Buff->ShowY < Buff->MaxY)
EnterCriticalSection(&Buff->Header.Lock);
Dc = GetDC(hWnd);
if (rc.right <= rc.left || rc.bottom <= rc.top)
{ {
ReleaseDC(hWnd, Dc); From = Buff->Buffer + ((Line + Buff->ShowY) * Buff->MaxX + LeftChar) * 2;
LeaveCriticalSection(&Buff->Header.Lock);
return;
} }
else
EnterCriticalSection(&GuiData->Lock);
TopLine = rc.top / GuiData->CharHeight;
BottomLine = (rc.bottom + (GuiData->CharHeight - 1)) / GuiData->CharHeight - 1;
LeftChar = rc.left / GuiData->CharWidth;
RightChar = (rc.right + (GuiData->CharWidth - 1)) / GuiData->CharWidth - 1;
LastAttribute = Buff->Buffer[(TopLine * Buff->MaxX + LeftChar) * 2 + 1];
GuiConsoleSetTextColors(GuiData->MemoryDC, LastAttribute);
for (Line = TopLine; Line <= BottomLine; Line++)
{ {
if (Line + Buff->ShowY < Buff->MaxY) From = Buff->Buffer +
((Line - (Buff->MaxY - Buff->ShowY)) * Buff->MaxX + LeftChar) * 2;
}
Start = LeftChar;
To = GuiData->LineBuffer;
for (Char = LeftChar; Char <= RightChar; Char++)
{
if (*(From + 1) != LastAttribute)
{ {
From = Buff->Buffer + ((Line + Buff->ShowY) * Buff->MaxX + LeftChar) * 2; TextOutW(hDC,
} Start * GuiData->CharWidth,
else Line * GuiData->CharHeight,
{ GuiData->LineBuffer,
From = Buff->Buffer + Char - Start);
((Line - (Buff->MaxY - Buff->ShowY)) * Buff->MaxX + LeftChar) * 2; Start = Char;
} To = GuiData->LineBuffer;
Start = LeftChar; Attribute = *(From + 1);
To = GuiData->LineBuffer; if (Attribute != LastAttribute)
for (Char = LeftChar; Char <= RightChar; Char++)
{
if (*(From + 1) != LastAttribute)
{ {
TextOutW(GuiData->MemoryDC, Start * GuiData->CharWidth, Line * GuiData->CharHeight, GuiConsoleSetTextColors(hDC,
GuiData->LineBuffer, Char - Start); Attribute);
Start = Char; LastAttribute = Attribute;
To = GuiData->LineBuffer;
Attribute = *(From + 1);
if (Attribute != LastAttribute)
{
GuiConsoleSetTextColors(GuiData->MemoryDC, Attribute);
LastAttribute = Attribute;
}
} }
MultiByteToWideChar(Console->OutputCodePage, 0, (PCHAR)From, 1, To, 1);
To++;
From += 2;
} }
TextOutW(GuiData->MemoryDC, Start * GuiData->CharWidth, Line * GuiData->CharHeight,
GuiData->LineBuffer, RightChar - Start + 1); MultiByteToWideChar(Console->OutputCodePage,
0,
(PCHAR)From,
1,
To,
1);
To++;
From += 2;
} }
if (Buff->CursorInfo.bVisible && GuiData->CursorBlinkOn TextOutW(hDC,
&&! GuiData->ForceCursorOff) Start * GuiData->CharWidth,
Line * GuiData->CharHeight,
GuiData->LineBuffer,
RightChar - Start + 1);
}
if (Buff->CursorInfo.bVisible && GuiData->CursorBlinkOn &&
!GuiData->ForceCursorOff)
{
GuiConsoleGetLogicalCursorPos(Buff,
&CursorX,
&CursorY);
if (LeftChar <= CursorX && CursorX <= RightChar &&
TopLine <= CursorY && CursorY <= BottomLine)
{ {
GuiConsoleGetLogicalCursorPos(Buff, &CursorX, &CursorY); CursorHeight = (GuiData->CharHeight * Buff->CursorInfo.dwSize) / 100;
if (LeftChar <= CursorX && CursorX <= RightChar && if (CursorHeight < 1)
TopLine <= CursorY && CursorY <= BottomLine)
{ {
CursorHeight = (GuiData->CharHeight * Buff->CursorInfo.dwSize) / 100; CursorHeight = 1;
if (CursorHeight < 1)
{
CursorHeight = 1;
}
From = Buff->Buffer + (Buff->CurrentY * Buff->MaxX + Buff->CurrentX) * 2 + 1;
CursorBrush = CreateSolidBrush(GuiConsoleRGBFromAttribute(*From));
OldBrush = SelectObject(GuiData->MemoryDC, CursorBrush);
PatBlt(GuiData->MemoryDC, CursorX * GuiData->CharWidth,
CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
GuiData->CharWidth, CursorHeight, PATCOPY);
SelectObject(GuiData->MemoryDC, OldBrush);
DeleteObject(CursorBrush);
} }
From = Buff->Buffer + (Buff->CurrentY * Buff->MaxX + Buff->CurrentX) * 2 + 1;
CursorBrush = CreateSolidBrush(GuiConsoleRGBFromAttribute(*From));
OldBrush = SelectObject(hDC,
CursorBrush);
PatBlt(hDC,
CursorX * GuiData->CharWidth,
CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
GuiData->CharWidth,
CursorHeight,
PATCOPY);
SelectObject(hDC,
OldBrush);
DeleteObject(CursorBrush);
} }
}
LeaveCriticalSection(&GuiData->Lock); LeaveCriticalSection(&Buff->Header.Lock);
ReleaseDC(hWnd, Dc);
LeaveCriticalSection(&Buff->Header.Lock); SelectObject(hDC,
InvalidateRect(hWnd, &rc, FALSE); OldFont);
}
} }
VOID FASTCALL static VOID FASTCALL
GuiConsoleHandlePaint(HWND hWnd) GuiConsoleHandlePaint(HWND hWnd, HDC hDCPaint)
{ {
PAINTSTRUCT Ps; RECT rcUpdate;
HDC Dc; HDC hDC;
PCSRSS_CONSOLE Console; PAINTSTRUCT ps;
PGUI_CONSOLE_DATA GuiData; PCSRSS_CONSOLE Console;
PGUI_CONSOLE_DATA GuiData;
GuiConsoleGetDataPointers(hWnd, &Console, &GuiData); if (GetUpdateRect(hWnd,
if (NULL != Console && NULL != GuiData) &rcUpdate,
FALSE))
{ {
EnterCriticalSection(&GuiData->Lock); hDC = (hDCPaint != NULL ? hDCPaint : BeginPaint(hWnd,
Dc = BeginPaint (hWnd, &Ps); &ps));
BitBlt(Dc, Ps.rcPaint.left, Ps.rcPaint.top, if (hDC != NULL)
Ps.rcPaint.right - Ps.rcPaint.left + 1,
Ps.rcPaint.bottom - Ps.rcPaint.top + 1, GuiData->MemoryDC,
Ps.rcPaint.left, Ps.rcPaint.top, SRCCOPY);
if (GuiData->Selection.left != -1)
{
RECT rc = GuiData->Selection;
rc.left *= GuiData->CharWidth;
rc.top *= GuiData->CharHeight;
rc.right *= GuiData->CharWidth;
rc.bottom *= GuiData->CharHeight;
if (IntersectRect(&rc, &Ps.rcPaint, &rc))
{ {
PatBlt(Dc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, DSTINVERT); GuiConsoleGetDataPointers(hWnd,
} &Console,
} &GuiData);
if (Console != NULL && GuiData != NULL &&
Console->ActiveBuffer != NULL)
{
EnterCriticalSection(&GuiData->Lock);
EndPaint (hWnd, &Ps); GuiConsolePaint(Console,
LeaveCriticalSection(&GuiData->Lock); GuiData,
} hDC,
else &rcUpdate);
{
Dc = BeginPaint (hWnd, &Ps); if (GuiData->Selection.left != -1)
EndPaint (hWnd, &Ps); {
RECT rc = GuiData->Selection;
rc.left *= GuiData->CharWidth;
rc.top *= GuiData->CharHeight;
rc.right *= GuiData->CharWidth;
rc.bottom *= GuiData->CharHeight;
/* invert the selection */
if (IntersectRect(&rc,
&rcUpdate,
&rc))
{
PatBlt(hDC,
rc.left,
rc.top,
rc.right - rc.left,
rc.bottom - rc.top,
DSTINVERT);
}
}
LeaveCriticalSection(&GuiData->Lock);
}
if (hDCPaint == NULL)
{
EndPaint(hWnd,
&ps);
}
}
} }
} }
@ -427,7 +454,7 @@ GuiIntDrawRegion(PGUI_CONSOLE_DATA GuiData, HWND Wnd, RECT *Region)
RegionRect.right = (Region->right + 1) * GuiData->CharWidth; RegionRect.right = (Region->right + 1) * GuiData->CharWidth;
RegionRect.bottom = (Region->bottom + 1) * GuiData->CharHeight; RegionRect.bottom = (Region->bottom + 1) * GuiData->CharHeight;
GuiConsoleUpdateBitmap(Wnd, RegionRect); InvalidateRect(Wnd, &RegionRect, FALSE);
} }
static VOID STDCALL static VOID STDCALL
@ -435,12 +462,10 @@ GuiDrawRegion(PCSRSS_CONSOLE Console, RECT *Region)
{ {
PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA) Console->PrivateData; PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA) Console->PrivateData;
if (NULL == Console->hWindow || NULL == GuiData) if (NULL != Console->hWindow && NULL != GuiData)
{ {
return; GuiIntDrawRegion(GuiData, Console->hWindow, Region);
} }
GuiIntDrawRegion(GuiData, Console->hWindow, Region);
} }
static VOID FASTCALL static VOID FASTCALL
@ -463,7 +488,7 @@ GuiWriteStream(PCSRSS_CONSOLE Console, RECT *Region, LONG CursorStartX, LONG Cur
PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA) Console->PrivateData; PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA) Console->PrivateData;
PCSRSS_SCREEN_BUFFER Buff = Console->ActiveBuffer; PCSRSS_SCREEN_BUFFER Buff = Console->ActiveBuffer;
LONG CursorEndX, CursorEndY; LONG CursorEndX, CursorEndY;
RECT Source, Dest; RECT Source, ScrollRect;
if (NULL == Console->hWindow || NULL == GuiData) if (NULL == Console->hWindow || NULL == GuiData)
{ {
@ -476,12 +501,12 @@ GuiWriteStream(PCSRSS_CONSOLE Console, RECT *Region, LONG CursorStartX, LONG Cur
Source.top = ScrolledLines; Source.top = ScrolledLines;
Source.right = Console->Size.X - 1; Source.right = Console->Size.X - 1;
Source.bottom = ScrolledLines + Region->top - 1; Source.bottom = ScrolledLines + Region->top - 1;
Dest.left = 0; ScrollRect.left = 0;
Dest.top = 0; ScrollRect.top = 0;
Dest.right = Console->Size.X - 1; ScrollRect.right = Console->Size.X * GuiData->CharWidth;
Dest.bottom = Region->top - 1; ScrollRect.bottom = Region->top * GuiData->CharHeight;
GuiConsoleCopyRegion(Console->hWindow, &Source, &Dest); InvalidateRect(Console->hWindow, &ScrollRect, FALSE);
} }
GuiIntDrawRegion(GuiData, Console->hWindow, Region); GuiIntDrawRegion(GuiData, Console->hWindow, Region);
@ -595,7 +620,6 @@ GuiConsoleHandleNcDestroy(HWND hWnd)
GuiConsoleGetDataPointers(hWnd, &Console, &GuiData); GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
KillTimer(hWnd, 1); KillTimer(hWnd, 1);
Console->PrivateData = NULL; Console->PrivateData = NULL;
DeleteDC(GuiData->MemoryDC);
DeleteCriticalSection(&GuiData->Lock); DeleteCriticalSection(&GuiData->Lock);
HeapFree(Win32CsrApiHeap, 0, GuiData); HeapFree(Win32CsrApiHeap, 0, GuiData);
} }
@ -742,7 +766,7 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
Result = (LRESULT) GuiConsoleHandleNcCreate(hWnd, (CREATESTRUCTW *) lParam); Result = (LRESULT) GuiConsoleHandleNcCreate(hWnd, (CREATESTRUCTW *) lParam);
break; break;
case WM_PAINT: case WM_PAINT:
GuiConsoleHandlePaint(hWnd); GuiConsoleHandlePaint(hWnd, (HDC)wParam);
break; break;
case WM_KEYDOWN: case WM_KEYDOWN:
case WM_KEYUP: case WM_KEYUP:
@ -1058,30 +1082,4 @@ GuiInitConsole(PCSRSS_CONSOLE Console)
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
VOID STDCALL
GuiConsoleCopyRegion(HWND hWnd,
RECT *Source,
RECT *Dest)
{
RECT ScrollRect;
PGUI_CONSOLE_DATA GuiData;
PCSRSS_CONSOLE Console;
GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
ScrollRect.left = Dest->left * GuiData->CharWidth;
ScrollRect.right = (Dest->right + 1) * GuiData->CharWidth;
ScrollRect.top = Dest->top * GuiData->CharHeight;
ScrollRect.bottom = (Dest->bottom + 1) * GuiData->CharHeight;
EnterCriticalSection(&GuiData->Lock);
BitBlt(GuiData->MemoryDC, ScrollRect.left, ScrollRect.top,
ScrollRect.right - ScrollRect.left, ScrollRect.bottom - ScrollRect.top,
GuiData->MemoryDC, Source->left * GuiData->CharWidth, Source->top * GuiData->CharHeight, SRCCOPY);
LeaveCriticalSection(&GuiData->Lock);
InvalidateRect(hWnd, &ScrollRect, FALSE);
}
/* EOF */ /* EOF */

View file

@ -8,12 +8,6 @@
#include "api.h" #include "api.h"
extern NTSTATUS FASTCALL GuiInitConsole(PCSRSS_CONSOLE Console); NTSTATUS FASTCALL GuiInitConsole(PCSRSS_CONSOLE Console);
extern VOID STDCALL GuiConsoleDrawRegion(PCSRSS_CONSOLE Console, SMALL_RECT Region);
extern VOID STDCALL GuiConsoleCopyRegion(HWND hWnd,
RECT *Source,
RECT *Dest);
extern VOID STDCALL GuiConsoleChangeTitle(PCSRSS_CONSOLE Console);
extern VOID STDCALL GuiConsoleDeleteConsole(PCSRSS_CONSOLE Console);
/*EOF*/ /*EOF*/