guiconsole.c
来自「一个类似windows」· C语言 代码 · 共 1,107 行 · 第 1/3 页
C
1,107 行
/* $Id: guiconsole.c 21263 2006-03-08 23:32:01Z audit $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/csrss/win32csr/guiconsole.c
* PURPOSE: Implementation of gui-mode consoles
*/
/* INCLUDES ******************************************************************/
#include "w32csr.h"
#define NDEBUG
#include <debug.h>
/* Not defined in any header file */
extern VOID STDCALL PrivateCsrssManualGuiCheck(LONG Check);
/* GLOBALS *******************************************************************/
typedef struct GUI_CONSOLE_DATA_TAG
{
HFONT Font;
unsigned CharWidth;
unsigned CharHeight;
PWCHAR LineBuffer;
BOOL CursorBlinkOn;
BOOL ForceCursorOff;
CRITICAL_SECTION Lock;
RECT Selection;
POINT SelectionStart;
BOOL MouseDown;
} GUI_CONSOLE_DATA, *PGUI_CONSOLE_DATA;
#ifndef WM_APP
#define WM_APP 0x8000
#endif
#define PM_CREATE_CONSOLE (WM_APP + 1)
#define PM_DESTROY_CONSOLE (WM_APP + 2)
#define CURSOR_BLINK_TIME 500
static BOOL ConsInitialized = FALSE;
static HWND NotifyWnd;
/* FUNCTIONS *****************************************************************/
static VOID FASTCALL
GuiConsoleGetDataPointers(HWND hWnd, PCSRSS_CONSOLE *Console, PGUI_CONSOLE_DATA *GuiData)
{
*Console = (PCSRSS_CONSOLE) GetWindowLongPtrW(hWnd, GWL_USERDATA);
*GuiData = (NULL == *Console ? NULL : (*Console)->PrivateData);
}
static BOOL FASTCALL
GuiConsoleHandleNcCreate(HWND hWnd, CREATESTRUCTW *Create)
{
RECT Rect;
PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) Create->lpCreateParams;
PGUI_CONSOLE_DATA GuiData;
HDC Dc;
HFONT OldFont;
TEXTMETRICW Metrics;
GuiData = HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY,
sizeof(GUI_CONSOLE_DATA) +
(Console->Size.X + 1) * sizeof(WCHAR));
if (NULL == GuiData)
{
DPRINT1("GuiConsoleNcCreate: HeapAlloc failed\n");
return FALSE;
}
InitializeCriticalSection(&GuiData->Lock);
GuiData->LineBuffer = (PWCHAR)(GuiData + 1);
GuiData->Font = CreateFontW(12, 0, 0, TA_BASELINE, FW_NORMAL,
FALSE, FALSE, FALSE, OEM_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
NONANTIALIASED_QUALITY, FIXED_PITCH | FF_DONTCARE,
L"Bitstream Vera Sans Mono");
if (NULL == GuiData->Font)
{
DPRINT1("GuiConsoleNcCreate: CreateFont failed\n");
DeleteCriticalSection(&GuiData->Lock);
HeapFree(Win32CsrApiHeap, 0, GuiData);
return FALSE;
}
Dc = GetDC(hWnd);
if (NULL == Dc)
{
DPRINT1("GuiConsoleNcCreate: GetDC failed\n");
DeleteObject(GuiData->Font);
DeleteCriticalSection(&GuiData->Lock);
HeapFree(Win32CsrApiHeap, 0, GuiData);
return FALSE;
}
OldFont = SelectObject(Dc, GuiData->Font);
if (NULL == OldFont)
{
DPRINT1("GuiConsoleNcCreate: SelectObject failed\n");
ReleaseDC(hWnd, Dc);
DeleteObject(GuiData->Font);
DeleteCriticalSection(&GuiData->Lock);
HeapFree(Win32CsrApiHeap, 0, GuiData);
return FALSE;
}
if (! GetTextMetricsW(Dc, &Metrics))
{
DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n");
SelectObject(Dc, OldFont);
ReleaseDC(hWnd, Dc);
DeleteObject(GuiData->Font);
DeleteCriticalSection(&GuiData->Lock);
HeapFree(Win32CsrApiHeap, 0, GuiData);
return FALSE;
}
GuiData->CharWidth = Metrics.tmMaxCharWidth;
GuiData->CharHeight = Metrics.tmHeight + Metrics.tmExternalLeading;
SelectObject(Dc, OldFont);
ReleaseDC(hWnd, Dc);
GuiData->CursorBlinkOn = TRUE;
GuiData->ForceCursorOff = FALSE;
GuiData->Selection.left = -1;
Console->PrivateData = GuiData;
SetWindowLongPtrW(hWnd, GWL_USERDATA, (DWORD_PTR) Console);
GetWindowRect(hWnd, &Rect);
Rect.right = Rect.left + Console->Size.X * GuiData->CharWidth +
2 * GetSystemMetrics(SM_CXFIXEDFRAME);
Rect.bottom = Rect.top + Console->Size.Y * GuiData->CharHeight +
2 * GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYCAPTION);
MoveWindow(hWnd, Rect.left, Rect.top, Rect.right - Rect.left,
Rect.bottom - Rect.top, FALSE);
SetTimer(hWnd, 1, CURSOR_BLINK_TIME, NULL);
return (BOOL) DefWindowProcW(hWnd, WM_NCCREATE, 0, (LPARAM) Create);
}
static COLORREF FASTCALL
GuiConsoleRGBFromAttribute(BYTE Attribute)
{
int Red = (Attribute & 0x04 ? (Attribute & 0x08 ? 0xff : 0x80) : 0x00);
int Green = (Attribute & 0x02 ? (Attribute & 0x08 ? 0xff : 0x80) : 0x00);
int Blue = (Attribute & 0x01 ? (Attribute & 0x08 ? 0xff : 0x80) : 0x00);
return RGB(Red, Green, Blue);
}
static VOID FASTCALL
GuiConsoleSetTextColors(HDC Dc, BYTE Attribute)
{
SetTextColor(Dc, GuiConsoleRGBFromAttribute(Attribute & 0x0f));
SetBkColor(Dc, GuiConsoleRGBFromAttribute((Attribute & 0xf0) >> 4));
}
static VOID FASTCALL
GuiConsoleGetLogicalCursorPos(PCSRSS_SCREEN_BUFFER Buff, ULONG *CursorX, ULONG *CursorY)
{
*CursorX = Buff->CurrentX;
if (Buff->CurrentY < Buff->ShowY)
{
*CursorY = Buff->MaxY - Buff->ShowY + Buff->CurrentY;
}
else
{
*CursorY = Buff->CurrentY - Buff->ShowY;
}
}
static VOID FASTCALL
GuiConsoleUpdateSelection(HWND hWnd, PRECT rc, PGUI_CONSOLE_DATA GuiData)
{
RECT oldRect = GuiData->Selection;
if(rc != NULL)
{
RECT changeRect = *rc;
GuiData->Selection = *rc;
changeRect.left *= GuiData->CharWidth;
changeRect.top *= GuiData->CharHeight;
changeRect.right *= GuiData->CharWidth;
changeRect.bottom *= GuiData->CharHeight;
if(rc->left != oldRect.left ||
rc->top != oldRect.top ||
rc->right != oldRect.right ||
rc->bottom != oldRect.bottom)
{
if(oldRect.left != -1)
{
HRGN rgn1, rgn2;
oldRect.left *= GuiData->CharWidth;
oldRect.top *= GuiData->CharHeight;
oldRect.right *= GuiData->CharWidth;
oldRect.bottom *= GuiData->CharHeight;
/* calculate the region that needs to be updated */
if((rgn1 = CreateRectRgnIndirect(&oldRect)))
{
if((rgn2 = CreateRectRgnIndirect(&changeRect)))
{
if(CombineRgn(rgn1, rgn2, rgn1, RGN_XOR) != ERROR)
{
InvalidateRgn(hWnd, rgn1, FALSE);
}
DeleteObject(rgn2);
}
DeleteObject(rgn1);
}
}
else
{
InvalidateRect(hWnd, &changeRect, FALSE);
}
}
}
else if(oldRect.left != -1)
{
/* clear the selection */
GuiData->Selection.left = -1;
oldRect.left *= GuiData->CharWidth;
oldRect.top *= GuiData->CharHeight;
oldRect.right *= GuiData->CharWidth;
oldRect.bottom *= GuiData->CharHeight;
InvalidateRect(hWnd, &oldRect, FALSE);
}
}
static VOID FASTCALL
GuiConsolePaint(PCSRSS_CONSOLE Console,
PGUI_CONSOLE_DATA GuiData,
HDC hDC,
PRECT rc)
{
PCSRSS_SCREEN_BUFFER Buff;
ULONG TopLine, BottomLine, LeftChar, RightChar;
ULONG Line, Char, Start;
PBYTE From;
PWCHAR To;
BYTE LastAttribute, Attribute;
ULONG CursorX, CursorY, CursorHeight;
HBRUSH CursorBrush, OldBrush;
HFONT OldFont;
Buff = 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++)
{
if (Line + Buff->ShowY < Buff->MaxY)
{
From = Buff->Buffer + ((Line + Buff->ShowY) * Buff->MaxX + LeftChar) * 2;
}
else
{
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)
{
TextOutW(hDC,
Start * GuiData->CharWidth,
Line * GuiData->CharHeight,
GuiData->LineBuffer,
Char - Start);
Start = Char;
To = GuiData->LineBuffer;
Attribute = *(From + 1);
if (Attribute != LastAttribute)
{
GuiConsoleSetTextColors(hDC,
Attribute);
LastAttribute = Attribute;
}
}
MultiByteToWideChar(Console->OutputCodePage,
0,
(PCHAR)From,
1,
To,
1);
To++;
From += 2;
}
TextOutW(hDC,
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)
{
CursorHeight = (GuiData->CharHeight * Buff->CursorInfo.dwSize) / 100;
if (CursorHeight < 1)
{
CursorHeight = 1;
}
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(&Buff->Header.Lock);
SelectObject(hDC,
OldFont);
}
static VOID FASTCALL
GuiConsoleHandlePaint(HWND hWnd, HDC hDCPaint)
{
HDC hDC;
PAINTSTRUCT ps;
PCSRSS_CONSOLE Console;
PGUI_CONSOLE_DATA GuiData;
hDC = BeginPaint(hWnd, &ps);
if (hDC != NULL &&
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?