diff --git a/reactos/subsys/csrss/win32csr/guiconsole.c b/reactos/subsys/csrss/win32csr/guiconsole.c index 8a0c57088ea..17f72435c89 100644 --- a/reactos/subsys/csrss/win32csr/guiconsole.c +++ b/reactos/subsys/csrss/win32csr/guiconsole.c @@ -1,4 +1,4 @@ -/* $Id: guiconsole.c,v 1.10 2004/02/04 00:05:46 gvg Exp $ +/* $Id: guiconsole.c,v 1.11 2004/03/07 21:00:11 hbirr Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -29,6 +29,9 @@ typedef struct GUI_CONSOLE_DATA_TAG PWCHAR LineBuffer; BOOL CursorBlinkOn; BOOL ForceCursorOff; + CRITICAL_SECTION Lock; + HDC MemoryDC; + HBITMAP MemoryBitmap; } GUI_CONSOLE_DATA, *PGUI_CONSOLE_DATA; #ifndef WM_APP @@ -37,8 +40,6 @@ typedef struct GUI_CONSOLE_DATA_TAG #define PM_CREATE_CONSOLE (WM_APP + 1) #define PM_DESTROY_CONSOLE (WM_APP + 2) -#define PM_COPY_REGION (WM_APP + 100) - #define CURSOR_BLINK_TIME 500 static BOOL Initialized = FALSE; @@ -62,8 +63,9 @@ GuiConsoleHandleNcCreate(HWND hWnd, CREATESTRUCTW *Create) HDC Dc; HFONT OldFont; TEXTMETRICW Metrics; + NTSTATUS Status; - GuiData = HeapAlloc(Win32CsrApiHeap, 0, + GuiData = HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY, sizeof(GUI_CONSOLE_DATA) + (Console->Size.X + 1) * sizeof(WCHAR)); if (NULL == GuiData) @@ -71,6 +73,15 @@ GuiConsoleHandleNcCreate(HWND hWnd, CREATESTRUCTW *Create) DPRINT1("GuiConsoleNcCreate: HeapAlloc failed\n"); return FALSE; } + + Status = RtlInitializeCriticalSection(&GuiData->Lock); + if (!NT_SUCCESS(Status)) + { + DPRINT1("RtlInitializeCriticalSection failed, Status=%x\n", Status); + HeapFree(Win32CsrApiHeap, 0, GuiData); + return FALSE; + } + GuiData->LineBuffer = (PWCHAR)(GuiData + 1); GuiData->Font = CreateFontW(12, 0, 0, TA_BASELINE, FW_NORMAL, @@ -81,6 +92,7 @@ GuiConsoleHandleNcCreate(HWND hWnd, CREATESTRUCTW *Create) if (NULL == GuiData->Font) { DPRINT1("GuiConsoleNcCreate: CreateFont failed\n"); + RtlDeleteCriticalSection(&GuiData->Lock); HeapFree(Win32CsrApiHeap, 0, GuiData); return FALSE; } @@ -88,6 +100,8 @@ GuiConsoleHandleNcCreate(HWND hWnd, CREATESTRUCTW *Create) if (NULL == Dc) { DPRINT1("GuiConsoleNcCreate: GetDC failed\n"); + DeleteObject(GuiData->Font); + RtlDeleteCriticalSection(&GuiData->Lock); HeapFree(Win32CsrApiHeap, 0, GuiData); return FALSE; } @@ -96,6 +110,8 @@ GuiConsoleHandleNcCreate(HWND hWnd, CREATESTRUCTW *Create) { DPRINT1("GuiConsoleNcCreate: SelectObject failed\n"); ReleaseDC(hWnd, Dc); + DeleteObject(GuiData->Font); + RtlDeleteCriticalSection(&GuiData->Lock); HeapFree(Win32CsrApiHeap, 0, GuiData); return FALSE; } @@ -104,12 +120,23 @@ GuiConsoleHandleNcCreate(HWND hWnd, CREATESTRUCTW *Create) DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n"); SelectObject(Dc, OldFont); ReleaseDC(hWnd, Dc); + DeleteObject(GuiData->Font); + RtlDeleteCriticalSection(&GuiData->Lock); HeapFree(Win32CsrApiHeap, 0, GuiData); return FALSE; } GuiData->CharWidth = Metrics.tmMaxCharWidth; GuiData->CharHeight = Metrics.tmHeight + Metrics.tmExternalLeading; SelectObject(Dc, OldFont); + + GuiData->MemoryDC = CreateCompatibleDC(Dc); + GuiData->MemoryBitmap = CreateCompatibleBitmap(Dc, + Console->Size.X * GuiData->CharWidth, + Console->Size.Y * GuiData->CharHeight); + DeleteObject(SelectObject(GuiData->MemoryDC, GuiData->MemoryBitmap)); + DeleteObject(SelectObject(GuiData->MemoryDC, GuiData->Font)); + + ReleaseDC(hWnd, Dc); GuiData->CursorBlinkOn = TRUE; GuiData->ForceCursorOff = FALSE; @@ -161,17 +188,15 @@ GuiConsoleGetLogicalCursorPos(PCSRSS_SCREEN_BUFFER Buff, ULONG *CursorX, ULONG * } } -static VOID FASTCALL -GuiConsoleHandlePaint(HWND hWnd) +VOID FASTCALL +GuiConsoleUpdateBitmap(HWND hWnd, RECT rc) { - PAINTSTRUCT Ps; - HDC Dc; PCSRSS_CONSOLE Console; PGUI_CONSOLE_DATA GuiData; PCSRSS_SCREEN_BUFFER Buff; - unsigned TopLine, BottomLine, LeftChar, RightChar; - unsigned Line, Char, Start; - HFONT OldFont; + HDC Dc; + ULONG TopLine, BottomLine, LeftChar, RightChar; + ULONG Line, Char, Start; PBYTE From; PWCHAR To; BYTE LastAttribute, Attribute; @@ -182,23 +207,24 @@ GuiConsoleHandlePaint(HWND hWnd) if (NULL != Console && NULL != GuiData && NULL != Console->ActiveBuffer) { Buff = Console->ActiveBuffer; - EnterCriticalSection(&(Buff->Header.Lock)); - - Dc = BeginPaint(hWnd, &Ps); - if (Ps.rcPaint.right <= Ps.rcPaint.left || Ps.rcPaint.bottom <= Ps.rcPaint.top) + EnterCriticalSection(&Buff->Header.Lock); + Dc = GetDC(hWnd); + if (rc.right <= rc.left || rc.bottom <= rc.top) { - EndPaint(hWnd, &Ps); - LeaveCriticalSection(&(Buff->Header.Lock)); + ReleaseDC(hWnd, Dc); + LeaveCriticalSection(&Buff->Header.Lock); return; } - OldFont = SelectObject(Dc, GuiData->Font); - TopLine = Ps.rcPaint.top / GuiData->CharHeight; - BottomLine = (Ps.rcPaint.bottom + (GuiData->CharHeight - 1)) / GuiData->CharHeight - 1; - LeftChar = Ps.rcPaint.left / GuiData->CharWidth; - RightChar = (Ps.rcPaint.right + (GuiData->CharWidth - 1)) / GuiData->CharWidth - 1; + 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(Dc, LastAttribute); + GuiConsoleSetTextColors(GuiData->MemoryDC, LastAttribute); + for (Line = TopLine; Line <= BottomLine; Line++) { if (Line + Buff->ShowY < Buff->MaxY) @@ -217,14 +243,14 @@ GuiConsoleHandlePaint(HWND hWnd) { if (*(From + 1) != Attribute) { - TextOutW(Dc, Start * GuiData->CharWidth, Line * GuiData->CharHeight, + TextOutW(GuiData->MemoryDC, Start * GuiData->CharWidth, Line * GuiData->CharHeight, GuiData->LineBuffer, Char - Start); Start = Char; To = GuiData->LineBuffer; Attribute = *(From + 1); if (Attribute != LastAttribute) { - GuiConsoleSetTextColors(Dc, Attribute); + GuiConsoleSetTextColors(GuiData->MemoryDC, Attribute); LastAttribute = Attribute; } } @@ -233,12 +259,10 @@ GuiConsoleHandlePaint(HWND hWnd) To++; From += 2; } - TextOutW(Dc, Start * GuiData->CharWidth, Line * GuiData->CharHeight, + TextOutW(GuiData->MemoryDC, Start * GuiData->CharWidth, Line * GuiData->CharHeight, GuiData->LineBuffer, RightChar - Start + 1); } - SelectObject(Dc, OldFont); - if (Buff->CursorInfo.bVisible && GuiData->CursorBlinkOn &&! GuiData->ForceCursorOff) { @@ -253,22 +277,47 @@ GuiConsoleHandlePaint(HWND hWnd) } From = Buff->Buffer + (Buff->CurrentY * Buff->MaxX + Buff->CurrentX) * 2 + 1; CursorBrush = CreateSolidBrush(GuiConsoleRGBFromAttribute(*From)); - OldBrush = SelectObject(Dc, CursorBrush); - PatBlt(Dc, CursorX * GuiData->CharWidth, + OldBrush = SelectObject(GuiData->MemoryDC, CursorBrush); + PatBlt(GuiData->MemoryDC, CursorX * GuiData->CharWidth, CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight), GuiData->CharWidth, CursorHeight, PATCOPY); - SelectObject(Dc, OldBrush); + SelectObject(GuiData->MemoryDC, OldBrush); DeleteObject(CursorBrush); } } - EndPaint(hWnd, &Ps); - LeaveCriticalSection(&(Buff->Header.Lock)); + LeaveCriticalSection(&GuiData->Lock); + ReleaseDC(hWnd, Dc); + LeaveCriticalSection(&Buff->Header.Lock); + InvalidateRect(hWnd, &rc, FALSE); + } + +} + +VOID FASTCALL +GuiConsoleHandlePaint(HWND hWnd) +{ + PAINTSTRUCT Ps; + HDC Dc; + PCSRSS_CONSOLE Console; + PGUI_CONSOLE_DATA GuiData; + + GuiConsoleGetDataPointers(hWnd, &Console, &GuiData); + if (NULL != Console && NULL != GuiData) + { + EnterCriticalSection(&GuiData->Lock); + Dc = BeginPaint (hWnd, &Ps); + BitBlt(Dc, Ps.rcPaint.left, Ps.rcPaint.top, + Ps.rcPaint.right - Ps.rcPaint.left + 1, + Ps.rcPaint.bottom - Ps.rcPaint.top + 1, GuiData->MemoryDC, + Ps.rcPaint.left, Ps.rcPaint.top, SRCCOPY); + EndPaint (hWnd, &Ps); + LeaveCriticalSection(&GuiData->Lock); } else { - Dc = BeginPaint(hWnd, &Ps); - EndPaint(hWnd, &Ps); + Dc = BeginPaint (hWnd, &Ps); + EndPaint (hWnd, &Ps); } } @@ -288,25 +337,6 @@ GuiConsoleHandleKey(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) ConioProcessKey(&Message, Console, FALSE); } -static VOID FASTCALL -GuiConsoleHandleCopyRegion(HWND hWnd, PRECT Source, PRECT Dest) -{ - RECT ClientRect, ScrollRect; - PGUI_CONSOLE_DATA GuiData; - PCSRSS_CONSOLE Console; - - GetClientRect(hWnd, &ClientRect); - GuiConsoleGetDataPointers(hWnd, &Console, &GuiData); - ScrollRect.left = min(Source->left, Dest->left) * GuiData->CharWidth; - ScrollRect.top = min(Source->top, Dest->top) * GuiData->CharHeight; - ScrollRect.right = max(Source->right, Dest->right) * GuiData->CharWidth; - ScrollRect.bottom = max(Source->bottom, Dest->bottom) * GuiData->CharHeight; - ScrollWindow(hWnd, - (Dest->left - Source->left) * GuiData->CharWidth, - (Dest->top - Source->top) * GuiData->CharHeight, - &ScrollRect, &ClientRect); -} - static VOID FASTCALL GuiIntDrawRegion(PGUI_CONSOLE_DATA GuiData, HWND Wnd, RECT *Region) { @@ -317,7 +347,7 @@ GuiIntDrawRegion(PGUI_CONSOLE_DATA GuiData, HWND Wnd, RECT *Region) RegionRect.right = (Region->right + 1) * GuiData->CharWidth; RegionRect.bottom = (Region->bottom + 1) * GuiData->CharHeight; - InvalidateRect(Wnd, &RegionRect, FALSE); + GuiConsoleUpdateBitmap(Wnd, RegionRect); } static VOID STDCALL @@ -371,7 +401,7 @@ GuiWriteStream(PCSRSS_CONSOLE Console, RECT *Region, UINT CursorStartX, UINT Cur Dest.right = Console->Size.X - 1; Dest.bottom = Region->top - 1; - GuiConsoleCopyRegion(Console, &Source, &Dest); + GuiConsoleCopyRegion(Console->hWindow, &Source, &Dest); } GuiIntDrawRegion(GuiData, Console->hWindow, Region); @@ -467,6 +497,8 @@ GuiConsoleHandleNcDestroy(HWND hWnd) GuiConsoleGetDataPointers(hWnd, &Console, &GuiData); KillTimer(hWnd, 1); Console->PrivateData = NULL; + DeleteDC(GuiData->MemoryDC); + RtlDeleteCriticalSection(&GuiData->Lock); HeapFree(Win32CsrApiHeap, 0, GuiData); } @@ -496,9 +528,6 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) GuiConsoleHandleTimer(hWnd); Result = 0; break; - case PM_COPY_REGION: - GuiConsoleHandleCopyRegion(hWnd, (PRECT) wParam, (PRECT) lParam); - break; case WM_CLOSE: GuiConsoleHandleClose(hWnd); Result = 0; @@ -744,6 +773,7 @@ GuiInitConsole(PCSRSS_CONSOLE Console) DPRINT1("Win32Csr: Failed to create graphics console thread. Expect problems\n"); return STATUS_UNSUCCESSFUL; } + SetThreadPriority(ThreadHandle, THREAD_PRIORITY_HIGHEST); CloseHandle(ThreadHandle); WaitForSingleObject(GraphicsStartupEvent, INFINITE); @@ -762,13 +792,29 @@ GuiInitConsole(PCSRSS_CONSOLE Console) } VOID STDCALL -GuiConsoleCopyRegion(PCSRSS_CONSOLE Console, +GuiConsoleCopyRegion(HWND hWnd, RECT *Source, RECT *Dest) { - LeaveCriticalSection(&(Console->ActiveBuffer->Header.Lock)); - SendMessageW(Console->hWindow, PM_COPY_REGION, (WPARAM) Source, (LPARAM) Dest); - EnterCriticalSection(&(Console->ActiveBuffer->Header.Lock)); + 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 */ diff --git a/reactos/subsys/csrss/win32csr/guiconsole.h b/reactos/subsys/csrss/win32csr/guiconsole.h index 578ab6625a4..440a0b24e83 100644 --- a/reactos/subsys/csrss/win32csr/guiconsole.h +++ b/reactos/subsys/csrss/win32csr/guiconsole.h @@ -1,4 +1,4 @@ -/* $Id: guiconsole.h,v 1.2 2004/01/11 17:31:16 gvg Exp $ +/* $Id: guiconsole.h,v 1.3 2004/03/07 21:00:11 hbirr Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -10,7 +10,7 @@ extern NTSTATUS FASTCALL GuiInitConsole(PCSRSS_CONSOLE Console); extern VOID STDCALL GuiConsoleDrawRegion(PCSRSS_CONSOLE Console, SMALL_RECT Region); -extern VOID STDCALL GuiConsoleCopyRegion(PCSRSS_CONSOLE Console, +extern VOID STDCALL GuiConsoleCopyRegion(HWND hWnd, RECT *Source, RECT *Dest); extern VOID STDCALL GuiConsoleChangeTitle(PCSRSS_CONSOLE Console);