mirror of
https://github.com/reactos/reactos.git
synced 2024-10-15 05:37:44 +00:00
326 lines
11 KiB
C
326 lines
11 KiB
C
|
/*
|
||
|
* PROJECT: ReactOS VGA Font Editor
|
||
|
* LICENSE: GNU General Public License Version 2.0 or any later version
|
||
|
* FILE: devutils/vgafontedit/fontboxeswnd.c
|
||
|
* PURPOSE: Implements the window showing the character boxes for a font
|
||
|
* COPYRIGHT: Copyright 2008 Colin Finck <mail@colinfinck.de>
|
||
|
*/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
|
||
|
static const WCHAR szFontBoxesWndClass[] = L"VGAFontEditFontBoxesWndClass";
|
||
|
|
||
|
static VOID
|
||
|
DrawCharacterPixel(IN PAINTSTRUCT *ps, IN UINT uCharacter, IN UCHAR uRow, IN UCHAR uColumn, IN UCHAR uBit, IN COLORREF clBackground)
|
||
|
{
|
||
|
INT x;
|
||
|
INT y;
|
||
|
|
||
|
x = (uCharacter % 16) * (CHARACTER_BOX_WIDTH + CHARACTER_BOX_PADDING) + 24 + uColumn;
|
||
|
y = (uCharacter / 16) * (CHARACTER_BOX_HEIGHT + CHARACTER_BOX_PADDING)+ 1 + CHARACTER_INFO_BOX_HEIGHT + 2 + uRow;
|
||
|
|
||
|
SetPixel( ps->hdc, x, y, (uBit ? 0 : clBackground) );
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
GetCharacterRect(IN UINT uFontRow, IN UINT uFontColumn, OUT LPRECT CharacterRect)
|
||
|
{
|
||
|
CharacterRect->left = uFontColumn * (CHARACTER_BOX_WIDTH + CHARACTER_BOX_PADDING);
|
||
|
CharacterRect->top = uFontRow * (CHARACTER_BOX_HEIGHT + CHARACTER_BOX_PADDING);
|
||
|
CharacterRect->right = CharacterRect->left + CHARACTER_BOX_WIDTH;
|
||
|
CharacterRect->bottom = CharacterRect->top + CHARACTER_BOX_HEIGHT;
|
||
|
}
|
||
|
|
||
|
__inline VOID
|
||
|
GetCharacterPosition(IN UINT uCharacter, OUT PUINT uFontRow, OUT PUINT uFontColumn)
|
||
|
{
|
||
|
*uFontRow = uCharacter / 16;
|
||
|
*uFontColumn = uCharacter % 16;
|
||
|
}
|
||
|
|
||
|
static INT
|
||
|
FontBoxesHitTest(IN UINT xPos, IN UINT yPos, OUT LPRECT CharacterRect)
|
||
|
{
|
||
|
UINT uFontColumn;
|
||
|
UINT uFontRow;
|
||
|
|
||
|
uFontColumn = xPos / (CHARACTER_BOX_WIDTH + CHARACTER_BOX_PADDING);
|
||
|
uFontRow = yPos / (CHARACTER_BOX_HEIGHT + CHARACTER_BOX_PADDING);
|
||
|
GetCharacterRect(uFontRow, uFontColumn, CharacterRect);
|
||
|
|
||
|
if(xPos > (UINT)CharacterRect->right || yPos > (UINT)CharacterRect->bottom)
|
||
|
// The user clicked on separator space, so return HITTEST_SEPARATOR
|
||
|
return HITTEST_SEPARATOR;
|
||
|
else
|
||
|
// Return the character number
|
||
|
return (uFontRow * 16 + uFontColumn);
|
||
|
}
|
||
|
|
||
|
static VOID
|
||
|
SetSelectedCharacter(IN PFONT_WND_INFO Info, IN UINT uNewCharacter, OPTIONAL IN LPRECT NewCharacterRect)
|
||
|
{
|
||
|
LPRECT pCharacterRect;
|
||
|
RECT OldCharacterRect;
|
||
|
UINT uFontColumn;
|
||
|
UINT uFontRow;
|
||
|
|
||
|
// Remove the selection of the old character
|
||
|
GetCharacterPosition(Info->uSelectedCharacter, &uFontRow, &uFontColumn);
|
||
|
GetCharacterRect(uFontRow, uFontColumn, &OldCharacterRect);
|
||
|
InvalidateRect(Info->hFontBoxesWnd, &OldCharacterRect, FALSE);
|
||
|
|
||
|
// You may pass the RECT of the new character, otherwise we'll allocate memory for one and get it ourselves
|
||
|
if(NewCharacterRect)
|
||
|
pCharacterRect = NewCharacterRect;
|
||
|
else
|
||
|
{
|
||
|
GetCharacterPosition(uNewCharacter, &uFontRow, &uFontColumn);
|
||
|
pCharacterRect = (LPRECT) HeapAlloc( hProcessHeap, 0, sizeof(RECT) );
|
||
|
GetCharacterRect(uFontRow, uFontColumn, pCharacterRect);
|
||
|
}
|
||
|
|
||
|
// Select the new character
|
||
|
Info->uSelectedCharacter = uNewCharacter;
|
||
|
InvalidateRect(Info->hFontBoxesWnd, pCharacterRect, FALSE);
|
||
|
|
||
|
if(!NewCharacterRect)
|
||
|
HeapFree(hProcessHeap, 0, pCharacterRect);
|
||
|
}
|
||
|
|
||
|
static VOID
|
||
|
DrawProc(IN PFONT_WND_INFO Info, IN PAINTSTRUCT* ps)
|
||
|
{
|
||
|
COLORREF clBackground;
|
||
|
HBRUSH hBrush = 0;
|
||
|
HBRUSH hOldBrush = 0;
|
||
|
HDC hBoxDC;
|
||
|
HFONT hFont;
|
||
|
HFONT hOldFont;
|
||
|
RECT CharacterRect;
|
||
|
UINT uFontColumn;
|
||
|
UINT uStartColumn;
|
||
|
UINT uEndColumn;
|
||
|
UINT uFontRow;
|
||
|
UINT uStartRow;
|
||
|
UINT uEndRow;
|
||
|
UINT uCharacter;
|
||
|
UCHAR uCharacterColumn;
|
||
|
UCHAR uCharacterRow;
|
||
|
UCHAR uBit;
|
||
|
WCHAR szInfoText[9];
|
||
|
|
||
|
// Preparations
|
||
|
hBoxDC = CreateCompatibleDC(NULL);
|
||
|
SelectObject(hBoxDC, Info->MainWndInfo->hBoxBmp);
|
||
|
|
||
|
hFont = CreateFontW(13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, L"Tahoma");
|
||
|
hOldFont = SelectObject(ps->hdc, hFont);
|
||
|
|
||
|
SetBkMode( ps->hdc, TRANSPARENT );
|
||
|
|
||
|
// What ranges do we have to draw?
|
||
|
uStartRow = ps->rcPaint.top / (CHARACTER_BOX_HEIGHT + CHARACTER_BOX_PADDING);
|
||
|
uEndRow = ps->rcPaint.bottom / (CHARACTER_BOX_HEIGHT + CHARACTER_BOX_PADDING);
|
||
|
uStartColumn = ps->rcPaint.left / (CHARACTER_BOX_WIDTH + CHARACTER_BOX_PADDING);
|
||
|
uEndColumn = ps->rcPaint.right / (CHARACTER_BOX_WIDTH + CHARACTER_BOX_PADDING);
|
||
|
|
||
|
for(uFontRow = uStartRow; uFontRow <= uEndRow; uFontRow++)
|
||
|
{
|
||
|
for(uFontColumn = uStartColumn; uFontColumn <= uEndColumn; uFontColumn++)
|
||
|
{
|
||
|
GetCharacterRect(uFontRow, uFontColumn, &CharacterRect);
|
||
|
uCharacter = uFontRow * 16 + uFontColumn;
|
||
|
|
||
|
// Draw the Character Info Box (header)
|
||
|
BitBlt(ps->hdc,
|
||
|
CharacterRect.left,
|
||
|
CharacterRect.top,
|
||
|
CHARACTER_BOX_WIDTH,
|
||
|
CHARACTER_INFO_BOX_HEIGHT,
|
||
|
hBoxDC,
|
||
|
0,
|
||
|
0,
|
||
|
SRCCOPY);
|
||
|
|
||
|
// Draw the header text
|
||
|
wsprintfW(szInfoText, L"%02u = %02X", uCharacter, uCharacter);
|
||
|
DrawTextW( ps->hdc, szInfoText, -1, &CharacterRect, DT_CENTER );
|
||
|
|
||
|
// Draw the Character Bitmap Box (rectangle with the actual character)
|
||
|
if(Info->uSelectedCharacter == uCharacter)
|
||
|
{
|
||
|
clBackground = RGB(255, 255, 0);
|
||
|
hBrush = CreateSolidBrush(clBackground);
|
||
|
hOldBrush = SelectObject(ps->hdc, hBrush);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
clBackground = RGB(255, 255, 255);
|
||
|
SelectObject( ps->hdc, GetStockObject(WHITE_BRUSH) );
|
||
|
}
|
||
|
|
||
|
Rectangle(ps->hdc,
|
||
|
CharacterRect.left,
|
||
|
CharacterRect.top + CHARACTER_INFO_BOX_HEIGHT,
|
||
|
CharacterRect.right,
|
||
|
CharacterRect.bottom);
|
||
|
|
||
|
// Draw the actual character into the box
|
||
|
for(uCharacterRow = 0; uCharacterRow < 8; uCharacterRow++)
|
||
|
{
|
||
|
for(uCharacterColumn = 0; uCharacterColumn < 8; uCharacterColumn++)
|
||
|
{
|
||
|
uBit = Info->Font->Bits[uCharacter * 8 + uCharacterRow] << uCharacterColumn & 0x80;
|
||
|
DrawCharacterPixel(ps, uCharacter, uCharacterRow, uCharacterColumn, uBit, clBackground);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SelectObject(ps->hdc, hOldFont);
|
||
|
DeleteObject(hFont);
|
||
|
SelectObject(ps->hdc, hOldBrush);
|
||
|
DeleteObject(hBrush);
|
||
|
DeleteDC(hBoxDC);
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
EditCurrentGlyph(PFONT_WND_INFO FontWndInfo)
|
||
|
{
|
||
|
PEDIT_GLYPH_INFO EditGlyphInfo;
|
||
|
|
||
|
EditGlyphInfo = (PEDIT_GLYPH_INFO) HeapAlloc( hProcessHeap, 0, sizeof(EDIT_GLYPH_INFO) );
|
||
|
EditGlyphInfo->FontWndInfo = FontWndInfo;
|
||
|
EditGlyphInfo->uCharacter = FontWndInfo->uSelectedCharacter;
|
||
|
RtlCopyMemory( EditGlyphInfo->CharacterBits, FontWndInfo->Font->Bits + FontWndInfo->uSelectedCharacter * 8, sizeof(EditGlyphInfo->CharacterBits) );
|
||
|
|
||
|
DialogBoxParamW(hInstance, MAKEINTRESOURCEW(IDD_EDITGLYPH), FontWndInfo->hSelf, EditGlyphDlgProc, (LPARAM)EditGlyphInfo);
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
CreateFontBoxesWindow(IN PFONT_WND_INFO FontWndInfo)
|
||
|
{
|
||
|
FontWndInfo->hFontBoxesWnd = CreateWindowExW(0,
|
||
|
szFontBoxesWndClass,
|
||
|
0,
|
||
|
WS_CHILD | WS_VISIBLE,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
FontWndInfo->hSelf,
|
||
|
NULL,
|
||
|
hInstance,
|
||
|
FontWndInfo);
|
||
|
}
|
||
|
|
||
|
static LRESULT CALLBACK
|
||
|
FontBoxesWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
PFONT_WND_INFO Info;
|
||
|
|
||
|
Info = (PFONT_WND_INFO) GetWindowLongW(hwnd, GWLP_USERDATA);
|
||
|
|
||
|
if(Info || uMsg == WM_CREATE)
|
||
|
{
|
||
|
switch(uMsg)
|
||
|
{
|
||
|
case WM_CREATE:
|
||
|
Info = (PFONT_WND_INFO)( ( (LPCREATESTRUCT)lParam )->lpCreateParams );
|
||
|
SetWindowLongW(hwnd, GWLP_USERDATA, (LONG)Info);
|
||
|
|
||
|
// Set a fixed window size
|
||
|
SetWindowPos(hwnd, NULL, 0, 0, FONT_BOXES_WND_WIDTH, FONT_BOXES_WND_HEIGHT, SWP_NOZORDER | SWP_NOMOVE);
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
case WM_DESTROY:
|
||
|
SetWindowLongW(hwnd, GWLP_USERDATA, 0);
|
||
|
return 0;
|
||
|
|
||
|
case WM_KEYDOWN:
|
||
|
switch(wParam)
|
||
|
{
|
||
|
case VK_DOWN:
|
||
|
if(Info->uSelectedCharacter < 239)
|
||
|
SetSelectedCharacter(Info, Info->uSelectedCharacter + 16, NULL);
|
||
|
return 0;
|
||
|
|
||
|
case VK_LEFT:
|
||
|
if(Info->uSelectedCharacter)
|
||
|
SetSelectedCharacter(Info, Info->uSelectedCharacter - 1, NULL);
|
||
|
return 0;
|
||
|
|
||
|
case VK_RETURN:
|
||
|
EditCurrentGlyph(Info);
|
||
|
return 0;
|
||
|
|
||
|
case VK_RIGHT:
|
||
|
if(Info->uSelectedCharacter < 255)
|
||
|
SetSelectedCharacter(Info, Info->uSelectedCharacter + 1, NULL);
|
||
|
return 0;
|
||
|
|
||
|
case VK_UP:
|
||
|
if(Info->uSelectedCharacter > 15)
|
||
|
SetSelectedCharacter(Info, Info->uSelectedCharacter - 16, NULL);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case WM_LBUTTONDBLCLK:
|
||
|
{
|
||
|
EditCurrentGlyph(Info);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
case WM_LBUTTONDOWN:
|
||
|
{
|
||
|
RECT CharacterRect;
|
||
|
INT iRet;
|
||
|
|
||
|
iRet = FontBoxesHitTest( GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), &CharacterRect );
|
||
|
|
||
|
if(iRet >= 0)
|
||
|
SetSelectedCharacter( Info, (UINT)iRet, &CharacterRect );
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
case WM_PAINT:
|
||
|
{
|
||
|
PAINTSTRUCT ps;
|
||
|
|
||
|
BeginPaint(hwnd, &ps);
|
||
|
DrawProc(Info, &ps);
|
||
|
EndPaint(hwnd, &ps);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
InitFontBoxesWndClass(VOID)
|
||
|
{
|
||
|
WNDCLASSW wc = {0,};
|
||
|
|
||
|
wc.lpfnWndProc = FontBoxesWndProc;
|
||
|
wc.hInstance = hInstance;
|
||
|
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
|
||
|
wc.hbrBackground = (HBRUSH)( COLOR_BTNFACE + 1 );
|
||
|
wc.lpszClassName = szFontBoxesWndClass;
|
||
|
wc.style = CS_DBLCLKS;
|
||
|
|
||
|
return RegisterClassW(&wc) != 0;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
UnInitFontBoxesWndClass(VOID)
|
||
|
{
|
||
|
UnregisterClassW(szFontBoxesWndClass, hInstance);
|
||
|
}
|