Wrote a Win32 Font Editor for our VGA Fonts used in blue.sys.

It has a MDI user interface, imports binary fonts (.bin) and PC Screen Fonts (.psf) and exports .bin fonts.
Compiles without any warnings with GCC and MSVC (at /W3).

The "misc.c" file was taken from devmgmt (thanks Ged!) and modified.
The used bitmaps and icons were all done myself, but partly consist of characters of the cp737 font we have in media/vgafont.

svn path=/trunk/; revision=32079
This commit is contained in:
Colin Finck 2008-02-01 21:40:18 +00:00
parent 817d837921
commit 7901978873
20 changed files with 2261 additions and 0 deletions

View file

@ -20,6 +20,10 @@
<xi:include href="syscalldump/syscalldump.rbuild" />
</directory>
<directory name="vgafontedit">
<xi:include href="vgafontedit/vgafontedit.rbuild" />
</directory>
<directory name="zoomin">
<xi:include href="zoomin/zoomin.rbuild" />
</directory>

View file

@ -0,0 +1,31 @@
/*
* PROJECT: ReactOS VGA Font Editor
* LICENSE: GNU General Public License Version 2.0 or any later version
* FILE: devutils/vgafontedit/aboutdlg.c
* PURPOSE: About dialog
* COPYRIGHT: Copyright 2008 Colin Finck <mail@colinfinck.de>
*/
#include "precomp.h"
INT_PTR CALLBACK
AboutDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch(uMsg)
{
case WM_COMMAND:
if( LOWORD(wParam) == IDCANCEL )
{
EndDialog(hwnd, 0);
return TRUE;
}
break;
case WM_INITDIALOG:
return TRUE;
}
return FALSE;
}

View file

@ -0,0 +1,15 @@
/*
* PROJECT: ReactOS VGA Font Editor
* LICENSE: GNU General Public License Version 2.0 or any later version
* FILE: devutils/vgafontedit/customwndclasses.h
* PURPOSE: Header for custom defined window classes (needed by "precomp.h" and the resource files)
* COPYRIGHT: Copyright 2008 Colin Finck <mail@colinfinck.de>
*/
#ifndef __CUSTOMWNDCLASSES_H
#define __CUSTOMWNDCLASSES_H
#define EDIT_GLYPH_EDIT_CLASSW L"VGAFontEditEditGlyphEditClass"
#define EDIT_GLYPH_PREVIEW_CLASSW L"VGAFontEditEditGlyphPreviewClass"
#endif

View file

@ -0,0 +1,297 @@
/*
* PROJECT: ReactOS VGA Font Editor
* LICENSE: GNU General Public License Version 2.0 or any later version
* FILE: devutils/vgafontedit/editglyphdlg.c
* PURPOSE: Dialog for editing a glyph
* COPYRIGHT: Copyright 2008 Colin Finck <mail@colinfinck.de>
*/
#include "precomp.h"
static VOID
AddToolboxButton(IN HWND hToolbar, IN INT iBitmap, IN INT idCommand, IN BYTE fsState)
{
TBBUTTON tbb = {0,};
tbb.fsState = fsState;
tbb.fsStyle = BTNS_CHECKGROUP;
tbb.iBitmap = iBitmap;
tbb.idCommand = idCommand;
SendMessageW( hToolbar, TB_ADDBUTTONSW, 1, (LPARAM)&tbb );
}
static VOID
InitToolbox(IN PEDIT_GLYPH_INFO Info)
{
HWND hToolbar;
INT iBitmap;
TBADDBITMAP tbab;
hToolbar = GetDlgItem(Info->hSelf, IDC_EDIT_GLYPH_TOOLBOX);
// Identify the used Common Controls version
SendMessageW(hToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
// Set the button size to 24x24
SendMessageW( hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(24, 24) );
SendMessageW( hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(24, 24) );
// Add the Toolbox bitmaps
tbab.hInst = hInstance;
tbab.nID = IDB_EDIT_GLYPH_TOOLBOX;
iBitmap = SendMessageW(hToolbar, TB_ADDBITMAP, 0, (LPARAM)&tbab);
AddToolboxButton(hToolbar, iBitmap + TOOLBOX_PEN, ID_TOOLBOX_PEN, TBSTATE_ENABLED | TBSTATE_CHECKED);
}
static VOID
GetBitRect(IN PEDIT_GLYPH_INFO Info, IN UINT uRow, IN UINT uColumn, OUT LPRECT BitRect)
{
BitRect->left = uColumn * Info->lEditSpacing + 1;
BitRect->top = uRow * Info->lEditSpacing + 1;
BitRect->right = BitRect->left + Info->lEditSpacing - 1;
BitRect->bottom = BitRect->top + Info->lEditSpacing - 1;
}
static VOID
SetPixelBit(IN PEDIT_GLYPH_INFO Info, IN UINT uRow, IN UINT uColumn, IN BOOL uBit)
{
// Set the bit in the bitfield
if(uBit)
Info->CharacterBits[uRow] |= 1 << (7 - uColumn);
else
Info->CharacterBits[uRow] &= ~( 1 << (7 - uColumn) );
// Redraw everything
InvalidateRect(Info->hEdit, NULL, FALSE);
InvalidateRect(Info->hPreview, NULL, FALSE);
}
static BOOL
EditGlyphCommand(IN INT idCommand, IN PEDIT_GLYPH_INFO Info)
{
switch(idCommand)
{
case IDOK:
{
RECT rect;
UINT uColumn;
UINT uRow;
RtlCopyMemory( Info->FontWndInfo->Font->Bits + Info->uCharacter * 8, Info->CharacterBits, sizeof(Info->CharacterBits) );
GetCharacterPosition(Info->uCharacter, &uRow, &uColumn);
GetCharacterRect(uRow, uColumn, &rect);
InvalidateRect(Info->FontWndInfo->hFontBoxesWnd, &rect, FALSE);
Info->FontWndInfo->OpenInfo->bModified = TRUE;
// Fall through
}
case IDCANCEL:
EndDialog(Info->hSelf, 0);
return TRUE;
}
return FALSE;
}
INT_PTR CALLBACK
EditGlyphDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PEDIT_GLYPH_INFO Info;
Info = (PEDIT_GLYPH_INFO) GetWindowLongW(hwnd, GWLP_USERDATA);
if(Info || uMsg == WM_INITDIALOG)
{
switch(uMsg)
{
case WM_COMMAND:
return EditGlyphCommand( LOWORD(wParam), Info );
case WM_DESTROY:
SetWindowLongW(hwnd, GWLP_USERDATA, 0);
SetWindowLongW(Info->hEdit, GWLP_USERDATA, 0);
SetWindowLongW(Info->hPreview, GWLP_USERDATA, 0 );
HeapFree(hProcessHeap, 0, Info);
return TRUE;
case WM_INITDIALOG:
Info = (PEDIT_GLYPH_INFO) lParam;
Info->hSelf = hwnd;
Info->hEdit = GetDlgItem(hwnd, IDC_EDIT_GLYPH_EDIT);
Info->hPreview = GetDlgItem(hwnd, IDC_EDIT_GLYPH_PREVIEW);
SetWindowLongW(hwnd, GWLP_USERDATA, (LONG)Info);
SetWindowLongW(Info->hEdit, GWLP_USERDATA, (LONG)Info);
SetWindowLongW(Info->hPreview, GWLP_USERDATA, (LONG)Info);
InitToolbox(Info);
return TRUE;
}
}
return FALSE;
}
static LRESULT CALLBACK
EditGlyphEditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PEDIT_GLYPH_INFO Info;
Info = (PEDIT_GLYPH_INFO) GetWindowLongW(hwnd, GWLP_USERDATA);
if(Info)
{
switch(uMsg)
{
case WM_CREATE:
return 0;
case WM_LBUTTONDOWN:
SetPixelBit(Info, GET_Y_LPARAM(lParam) / Info->lEditSpacing, GET_X_LPARAM(lParam) / Info->lEditSpacing, 1);
return 0;
case WM_RBUTTONDOWN:
SetPixelBit(Info, GET_Y_LPARAM(lParam) / Info->lEditSpacing, GET_X_LPARAM(lParam) / Info->lEditSpacing, 0);
return 0;
case WM_PAINT:
{
BOOL bBit;
HPEN hOldPen;
HPEN hPen;
PAINTSTRUCT ps;
RECT rect;
UINT i;
UINT j;
BeginPaint(hwnd, &ps);
// Draw the grid
GetClientRect(hwnd, &rect);
Info->lEditSpacing = rect.right / 8;
hPen = CreatePen( PS_SOLID, 1, RGB(128, 128, 128) );
hOldPen = SelectObject(ps.hdc, hPen);
for(i = 1; i < 8; i++)
{
MoveToEx(ps.hdc, i * Info->lEditSpacing, 0, NULL);
LineTo (ps.hdc, i * Info->lEditSpacing, rect.right);
MoveToEx(ps.hdc, 0, i * Info->lEditSpacing, NULL);
LineTo (ps.hdc, rect.right, i * Info->lEditSpacing);
}
SelectObject(ps.hdc, hOldPen);
DeleteObject(hPen);
// Draw all bits
for(i = 0; i < 8; i++)
{
for(j = 0; j < 8; j++)
{
bBit = (BOOL) (Info->CharacterBits[i] << j & 0x80);
GetBitRect(Info, i, j, &rect);
FillRect( ps.hdc, &rect, (HBRUSH) GetStockObject(bBit ? BLACK_BRUSH : WHITE_BRUSH) );
}
}
// Draw the bounding rectangle
SelectObject( ps.hdc, GetStockObject(NULL_BRUSH) );
Rectangle(ps.hdc, 0, 0, rect.right, rect.right);
EndPaint(hwnd, &ps);
return 0;
}
}
}
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
static LRESULT CALLBACK
EditGlyphPreviewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PEDIT_GLYPH_INFO Info;
Info = (PEDIT_GLYPH_INFO) GetWindowLongW(hwnd, GWLP_USERDATA);
if(Info)
{
switch(uMsg)
{
case WM_CREATE:
return 0;
case WM_PAINT:
{
BOOL bBit;
INT iLeft;
INT iTop;
PAINTSTRUCT ps;
RECT rect;
UINT i;
UINT j;
BeginPaint(hwnd, &ps);
// Draw the bounding rectangle
GetClientRect(hwnd, &rect);
Rectangle(ps.hdc, 0, 0, rect.right, rect.bottom);
// Draw all bits
iLeft = rect.right / 2 - 8 / 2;
iTop = rect.bottom / 2 - 8 / 2;
for(i = 0; i < 8; i++)
{
for(j = 0; j < 8; j++)
{
bBit = (BOOL) (Info->CharacterBits[i] << j & 0x80);
SetPixel( ps.hdc, j + iLeft, i + iTop, (bBit ? 0 : 0xFFFFFF) );
}
}
EndPaint(hwnd, &ps);
return 0;
}
}
}
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
BOOL
InitEditGlyphWndClasses(VOID)
{
WNDCLASSW wc = {0,};
wc.lpfnWndProc = EditGlyphEditWndProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.lpszClassName = EDIT_GLYPH_EDIT_CLASSW;
if( !RegisterClassW(&wc) )
return FALSE;
wc.lpfnWndProc = EditGlyphPreviewWndProc;
wc.lpszClassName = EDIT_GLYPH_PREVIEW_CLASSW;
return RegisterClassW(&wc) != 0;
}
VOID
UnInitEditGlyphWndClasses(VOID)
{
UnregisterClassW(EDIT_GLYPH_EDIT_CLASSW, hInstance);
UnregisterClassW(EDIT_GLYPH_PREVIEW_CLASSW, hInstance);
}

View file

@ -0,0 +1,55 @@
VGA Font File Formats
=====================
We only deal with 8x8 fonts with 256 characters, so different formats aren't described here.
1. The binary format (*.bin)
----------------------------
A binary font file is always 2048 bytes in size.
These bytes are divided into 256 characters, so every character is 8 bytes large.
Each byte represents a character row. Consequently, each column is represented by one bit. The most-significant bit contains the pixel of the first column from the left.
Example:
We want to get the pixel in the third column of the second row of the seventh character.
We assume you loaded the binary font file completely into a byte array called FontBits.
// All indexes need to be zero-based
UINT uCharacter = 6;
UINT uRow = 1;
UINT uColumn = 2;
UCHAR uBit;
// uBit will either contain 0 (0-bit is set) or 128 dec, 0x80 hex (1-bit is set) now
uBit = FontBits[uCharacter * 8 + uRow] << uColumn & 0x80;
2. The PC Screen Font Version 1 format (*.psf)
----------------------------------------------
A PC Screen Font Version 1 file is always 2052 bytes in size.
It has the following structure:
struct PSF1_FILE
{
UCHAR uMagic[2];
UCHAR uMode;
UCHAR uCharSize;
UCHAR FontBits[2048];
};
* uMagic contains two magic bytes, which identify a PSFv1 file. These are:
uMagic[0] = 0x36
uMagic[1] = 0x04
* uMode specifies special modes of the font.
We only deal with fonts here, which don't have any special modes, so this value should be 0.
* uCharSize specifies the size of a character.
In our case, this needs to be 8.
* Finally the FontBits array contains the font bits in the same format as described above.
This way, it is very easy to convert a PSFv1 file to a binary *.bin file.
- Colin Finck, 2008/02/01

View file

@ -0,0 +1,325 @@
/*
* 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);
}

View file

@ -0,0 +1,438 @@
/*
* PROJECT: ReactOS VGA Font Editor
* LICENSE: GNU General Public License Version 2.0 or any later version
* FILE: devutils/vgafontedit/fontwnd.c
* PURPOSE: Implements the MDI child window for a font
* COPYRIGHT: Copyright 2008 Colin Finck <mail@colinfinck.de>
*/
#include "precomp.h"
static const WCHAR szFontWndClass[] = L"VGAFontEditFontWndClass";
static BOOL
InitFont(IN PFONT_WND_INFO Info)
{
Info->Font = (PBITMAP_FONT) HeapAlloc( hProcessHeap, 0, sizeof(BITMAP_FONT) );
if(Info->OpenInfo->bCreateNew)
{
ZeroMemory( Info->Font, sizeof(BITMAP_FONT) );
return TRUE;
}
else
{
// Load a font
BOOL bRet = FALSE;
DWORD dwTemp;
HANDLE hFile;
hFile = CreateFileW(Info->OpenInfo->pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
LocalizedError( IDS_OPENERROR, GetLastError() );
return FALSE;
}
// Let's first check the file size to determine the file type
dwTemp = GetFileSize(hFile, NULL);
switch(dwTemp)
{
case 2048:
// It should be a binary font file
Info->OpenInfo->bBinaryFileOpened = TRUE;
if( ReadFile(hFile, Info->Font, sizeof(BITMAP_FONT), &dwTemp, NULL) )
bRet = TRUE;
else
LocalizedError( IDS_READERROR, GetLastError() );
break;
case 2052:
{
PSF1_HEADER Header;
// Probably it's a PSFv1 file, check the header to make sure
if( !ReadFile(hFile, &Header, sizeof(PSF1_HEADER) , &dwTemp, NULL) )
{
LocalizedError( IDS_READERROR, GetLastError() );
break;
}
else
{
if(Header.uMagic[0] == PSF1_MAGIC0 && Header.uMagic[1] == PSF1_MAGIC1)
{
// Yes, it is a PSFv1 file.
// Check the mode and character size. We only support 8x8 fonts with no special mode.
if(Header.uCharSize == 8 && Header.uMode == 0)
{
// Perfect! The file pointer is already set correctly, so we can just read the font bitmap now.
if( ReadFile(hFile, Info->Font, sizeof(BITMAP_FONT), &dwTemp, NULL) )
bRet = TRUE;
else
LocalizedError( IDS_READERROR, GetLastError() );
}
else
LocalizedError(IDS_UNSUPPORTEDPSF);
break;
}
// Fall through if the magic numbers aren't there
}
}
default:
LocalizedError(IDS_UNSUPPORTEDFORMAT);
}
CloseHandle(hFile);
return bRet;
}
}
static LRESULT CALLBACK
FontWndProc(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_CHILDACTIVATE:
Info->MainWndInfo->CurrentFontWnd = Info;
SetToolbarFileButtonState(Info->MainWndInfo, TRUE);
break;
case WM_CREATE:
Info = (PFONT_WND_INFO)( ( (LPMDICREATESTRUCT) ( (LPCREATESTRUCT)lParam )->lpCreateParams )->lParam );
Info->hSelf = hwnd;
SetWindowLongW(hwnd, GWLP_USERDATA, (LONG)Info);
CreateFontBoxesWindow(Info);
return 0;
case WM_USER_APPCLOSE:
case WM_CLOSE:
if(Info->OpenInfo->bModified)
{
INT nMsgBoxResult;
PWSTR pszPrompt;
WCHAR szFile[MAX_PATH];
GetWindowTextW(hwnd, szFile, MAX_PATH);
LoadAndFormatString(IDS_SAVEPROMPT, &pszPrompt, szFile);
nMsgBoxResult = MessageBoxW(hwnd, pszPrompt, szAppName, MB_YESNOCANCEL | MB_ICONQUESTION);
HeapFree(hProcessHeap, 0, pszPrompt);
switch(nMsgBoxResult)
{
case IDYES:
DoFileSave(Info->MainWndInfo, FALSE);
break;
case IDCANCEL:
// 0 = Stop the process of closing the windows (same value for both WM_CLOSE and WM_USER_APPCLOSE)
return 0;
// IDNO is handled automatically
}
}
// If there is another child, it will undo the following actions through its WM_CHILDACTIVATE handler.
// Otherwise CurrentFontWnd will stay NULL, so the main window knows that no more childs are opened.
Info->MainWndInfo->CurrentFontWnd = NULL;
SetToolbarFileButtonState(Info->MainWndInfo, FALSE);
if(uMsg == WM_USER_APPCLOSE)
{
// First do the tasks we would do for a normal WM_CLOSE message, then return the value for WM_USER_APPCLOSE
// Anything other than 0 indicates that the application shall continue closing the windows
DefMDIChildProcW(hwnd, WM_CLOSE, 0, 0);
return 1;
}
break;
case WM_DESTROY:
// Remove the window from the linked list
if(Info->MainWndInfo->FirstFontWnd == Info)
{
Info->MainWndInfo->FirstFontWnd = Info->NextFontWnd;
if(Info->NextFontWnd)
Info->NextFontWnd->PrevFontWnd = NULL;
}
else
Info->PrevFontWnd->NextFontWnd = Info->NextFontWnd;
if(Info->MainWndInfo->LastFontWnd == Info)
{
Info->MainWndInfo->LastFontWnd = Info->PrevFontWnd;
if(Info->PrevFontWnd)
Info->PrevFontWnd->NextFontWnd = NULL;
}
else
Info->NextFontWnd->PrevFontWnd = Info->PrevFontWnd;
// Free memory
if(Info->Font)
HeapFree(hProcessHeap, 0, Info->Font);
if(Info->OpenInfo->pszFileName)
HeapFree(hProcessHeap, 0, Info->OpenInfo->pszFileName);
HeapFree(hProcessHeap, 0, Info->OpenInfo);
HeapFree(hProcessHeap, 0, Info);
SetWindowLongW(hwnd, GWLP_USERDATA, 0);
return 0;
case WM_SETFOCUS:
// Set the keyboard focus to the FontBoxes window every time the Font window gets the focus
SetFocus(Info->hFontBoxesWnd);
break;
case WM_SIZE:
{
INT nHeight = HIWORD(lParam);
INT nWidth = LOWORD(lParam);
POINT pt;
RECT WndRect;
// This ugly workaround is necessary for not setting either the Height or the Width of the window with SetWindowPos
GetWindowRect(Info->hFontBoxesWnd, &WndRect);
pt.x = WndRect.left;
pt.y = WndRect.top;
ScreenToClient(hwnd, &pt);
if(nHeight < FONT_BOXES_WND_HEIGHT)
{
SCROLLINFO si;
// Set the vertical scroll bar
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE;
si.nMin = 0;
si.nMax = FONT_BOXES_WND_HEIGHT;
si.nPage = nHeight;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
}
else
{
ShowScrollBar(hwnd, SB_VERT, FALSE);
// Store the new y coordinate in pt.y as well (needed for the SetWindowPos call for setting a new x coordinate)
pt.y = nHeight / 2 - FONT_BOXES_WND_HEIGHT / 2;
SetWindowPos(Info->hFontBoxesWnd,
NULL,
pt.x,
pt.y,
0,
0,
SWP_NOSIZE | SWP_NOZORDER);
}
if(nWidth < FONT_BOXES_WND_WIDTH)
{
SCROLLINFO si;
// Set the horizontal scroll bar
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE;
si.nMin = 0;
si.nMax = FONT_BOXES_WND_WIDTH;
si.nPage = nWidth;
SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
}
else
{
ShowScrollBar(hwnd, SB_HORZ, FALSE);
SetWindowPos(Info->hFontBoxesWnd,
NULL,
nWidth / 2 - FONT_BOXES_WND_WIDTH / 2,
pt.y,
0,
0,
SWP_NOSIZE | SWP_NOZORDER);
}
// We have to call DefMDIChildProcW here as well, otherwise we won't get the Minimize/Maximize/Close buttons for a maximized MDI child.
break;
}
case WM_HSCROLL:
case WM_VSCROLL:
{
INT nBar;
INT nOrgPos;
SCROLLINFO si;
if(uMsg == WM_HSCROLL)
nBar = SB_HORZ;
else
nBar = SB_VERT;
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
GetScrollInfo(hwnd, nBar, &si);
nOrgPos = si.nPos;
switch( LOWORD(wParam) )
{
// Constant is the same as SB_LEFT for WM_HSCROLL
case SB_TOP:
si.nPos = si.nMin;
break;
// Constant is the same as SB_RIGHT for WM_HSCROLL
case SB_BOTTOM:
si.nPos = si.nMax;
break;
// Constant is the same as SB_LINELEFT for WM_HSCROLL
case SB_LINEUP:
si.nPos -= 20;
break;
// Constant is the same as SB_LINERIGHT for WM_HSCROLL
case SB_LINEDOWN:
si.nPos += 20;
break;
// Constant is the same as SB_PAGELEFT for WM_HSCROLL
case SB_PAGEUP:
si.nPos -= si.nPage;
break;
// Constant is the same as SB_PAGERIGHT for WM_HSCROLL
case SB_PAGEDOWN:
si.nPos += si.nPage;
break;
case SB_THUMBTRACK:
si.nPos = si.nTrackPos;
break;
}
si.fMask = SIF_POS;
SetScrollInfo(hwnd, nBar, &si, TRUE);
GetScrollInfo(hwnd, nBar, &si);
if(si.nPos != nOrgPos)
{
// This ugly workaround is necessary for not setting the x coordinate
POINT pt;
RECT WndRect;
GetWindowRect(Info->hFontBoxesWnd, &WndRect);
pt.x = WndRect.left;
pt.y = WndRect.top;
ScreenToClient(hwnd, &pt);
if(uMsg == WM_HSCROLL)
SetWindowPos(Info->hFontBoxesWnd, NULL, -si.nPos, pt.y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
else
SetWindowPos(Info->hFontBoxesWnd, NULL, pt.x, -si.nPos, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
return 0;
}
}
}
return DefMDIChildProcW(hwnd, uMsg, wParam, lParam);
}
BOOL
CreateFontWindow(IN PMAIN_WND_INFO MainWndInfo, IN PFONT_OPEN_INFO OpenInfo)
{
HWND hFontWnd;
PFONT_WND_INFO Info;
Info = (PFONT_WND_INFO) HeapAlloc( hProcessHeap, HEAP_ZERO_MEMORY, sizeof(FONT_WND_INFO) );
if(Info)
{
Info->MainWndInfo = MainWndInfo;
Info->OpenInfo = OpenInfo;
if( InitFont(Info) )
{
PWSTR pszWindowTitle;
if(OpenInfo->pszFileName)
pszWindowTitle = wcsrchr(OpenInfo->pszFileName, '\\') + 1;
else
LoadAndFormatString(IDS_DOCNAME, &pszWindowTitle, ++MainWndInfo->uDocumentCounter);
hFontWnd = CreateMDIWindowW( szFontWndClass,
pszWindowTitle,
0,
CW_USEDEFAULT,
CW_USEDEFAULT,
FONT_WND_MIN_WIDTH,
FONT_WND_MIN_HEIGHT,
MainWndInfo->hMdiClient,
hInstance,
(LPARAM)Info );
if(!OpenInfo->pszFileName)
HeapFree(hProcessHeap, 0, pszWindowTitle);
if(hFontWnd)
{
// Add the new window to the linked list
if(Info->MainWndInfo->LastFontWnd)
{
Info->PrevFontWnd = Info->MainWndInfo->LastFontWnd;
Info->PrevFontWnd->NextFontWnd = Info;
Info->MainWndInfo->LastFontWnd = Info;
}
else
{
Info->MainWndInfo->FirstFontWnd = Info;
Info->MainWndInfo->LastFontWnd = Info;
}
return TRUE;
}
}
HeapFree(hProcessHeap, 0, Info);
}
return FALSE;
}
BOOL
InitFontWndClass(VOID)
{
WNDCLASSW wc = {0,};
wc.lpfnWndProc = FontWndProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hIcon = LoadIconW( hInstance, MAKEINTRESOURCEW(IDI_DOC) );
wc.hbrBackground = (HBRUSH)( COLOR_BTNFACE + 1 );
wc.lpszClassName = szFontWndClass;
return RegisterClassW(&wc) != 0;
}
VOID
UnInitFontWndClass(VOID)
{
UnregisterClassW(szFontWndClass, hInstance);
}

View file

@ -0,0 +1,82 @@
/*
* PROJECT: ReactOS VGA Font Editor
* LICENSE: GNU General Public License Version 2.0 or any later version
* FILE: devutils/vgafontedit/lang/en-US.rc
* PURPOSE: English resource file
* COPYRIGHT: Copyright 2008 Colin Finck <mail@colinfinck.de>
* TRANSLATOR: Colin Finck
*/
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
IDD_ABOUT DIALOGEX 10, 10, 130, 62
STYLE DS_SHELLFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "About"
FONT 8, "MS Shell Dlg"
BEGIN
ICON IDI_MAIN, IDC_STATIC, 10, 10, 20, 20
LTEXT "ReactOS VGA Font Editor", IDC_STATIC, 37, 10, 93, 10
LTEXT "Copyright 2008 Colin Finck", IDC_STATIC, 37, 20, 93, 10
DEFPUSHBUTTON "OK", IDCANCEL, 40, 44, 55, 15
END
IDD_EDITGLYPH DIALOGEX 10, 10, 246, 197
STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Edit Glyph"
FONT 8, "MS Shell Dlg"
BEGIN
CONTROL "", IDC_EDIT_GLYPH_TOOLBOX, TOOLBARCLASSNAMEA, CCS_NODIVIDER | CCS_NORESIZE, 5, 5, 24, 82
CONTROL "", IDC_EDIT_GLYPH_EDIT, EDIT_GLYPH_EDIT_CLASSW, 0, 39, 5, 160, 160
CONTROL "", IDC_EDIT_GLYPH_PREVIEW, EDIT_GLYPH_PREVIEW_CLASSW, 0, 209, 5, 32, 32
DEFPUSHBUTTON "OK", IDOK, 48, 177, 70, 14
PUSHBUTTON "Cancel", IDCANCEL, 125, 177, 70, 14
END
IDM_MAINMENU MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&New\tCtrl+N", ID_FILE_NEW
MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
MENUITEM "Close", ID_FILE_CLOSE
MENUITEM SEPARATOR
MENUITEM "Save\tCtrl+S", ID_FILE_SAVE
MENUITEM "Save As...", ID_FILE_SAVE_AS
MENUITEM SEPARATOR
MENUITEM "Exit\tAlt+F4", ID_FILE_EXIT
END
POPUP "&Window"
BEGIN
MENUITEM "&Cascade", ID_WINDOW_CASCADE
MENUITEM "Tile &Horizontally", ID_WINDOW_TILE_HORZ
MENUITEM "Tile &Vertically", ID_WINDOW_TILE_VERT
MENUITEM "&Arrange Icons", ID_WINDOW_ARRANGE
MENUITEM SEPARATOR
MENUITEM "Nex&t\tCtrl+F6", ID_WINDOW_NEXT
END
POPUP "&Help"
BEGIN
MENUITEM "&About...", ID_HELP_ABOUT
END
END
STRINGTABLE
BEGIN
IDS_OPENFILTER, "All supported formats (*.bin,*.psf)|*.bin;*.psf|Binary Font Files (*.bin)|*.bin|PC Screen Fonts Version 1 (*.psf)|*.psf|"
IDS_SAVEFILTER, "Binary Font Files (*.bin)|*.bin|"
IDS_OPENERROR, "Error while opening the file! (Error number %1!u!)"
IDS_READERROR, "Error while reading the file! (Error number %1!u!)"
IDS_WRITEERROR, "Error while writing the file! (Error number %1!u!)"
IDS_UNSUPPORTEDFORMAT, "Unsupported file format!"
IDS_UNSUPPORTEDPSF, "Unsupported PSF font format! The editor only supports 8x8 fonts with no special modes."
IDS_DOCNAME, "Font %1!u!"
IDS_SAVEPROMPT, "The file ""%1"" was modified, but not saved.\n\nDo you want to save it?"
IDS_TOOLTIP_NEW, "New"
IDS_TOOLTIP_OPEN, "Open"
IDS_TOOLTIP_SAVE, "Save"
IDS_TOOLTIP_EDIT_GLYPH, "Edit Glyph"
END

View file

@ -0,0 +1,57 @@
/*
* PROJECT: ReactOS VGA Font Editor
* LICENSE: GNU General Public License Version 2.0 or any later version
* FILE: devutils/vgafontedit/main.c
* PURPOSE: Main entry point of the application
* COPYRIGHT: Copyright 2008 Colin Finck <mail@colinfinck.de>
*/
#include "precomp.h"
const WCHAR szAppName[] = L"ReactOS VGA Font Editor";
HINSTANCE hInstance;
HANDLE hProcessHeap;
INT WINAPI
wWinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
HACCEL hAccel;
INT nRet = 1;
MSG msg;
PMAIN_WND_INFO Info = 0;
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
hInstance = hInst;
hProcessHeap = GetProcessHeap();
hAccel = LoadAcceleratorsW( hInstance, MAKEINTRESOURCEW(IDA_MAINACCELERATORS) );
if( InitMainWndClass() && InitFontWndClass() && InitFontBoxesWndClass() && InitEditGlyphWndClasses() )
{
if( CreateMainWindow(nCmdShow, &Info) )
{
while( GetMessageW(&msg, NULL, 0, 0) )
{
if( !TranslateMDISysAccel(Info->hMdiClient, &msg) &&
!TranslateAccelerator(Info->hMainWnd, hAccel, &msg) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
nRet = 0;
}
}
// Just unregister our window classes, don't care whether they were created or not
UnInitEditGlyphWndClasses();
UnInitFontBoxesWndClass();
UnInitFontWndClass();
UnInitMainWndClass();
return nRet;
}

View file

@ -0,0 +1,32 @@
/*
* PROJECT: ReactOS VGA Font Editor
* LICENSE: GNU General Public License Version 2.0 or any later version
* FILE: devutils/vgafontedit/main.rc
* PURPOSE: Main resource file
* COPYRIGHT: Copyright 2008 Colin Finck <mail@colinfinck.de>
*/
#include <windows.h>
#include <commctrl.h>
#include "resource.h"
#include "customwndclasses.h"
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS VGA Font Editor"
#define REACTOS_STR_INTERNAL_NAME "vgafontedit"
#define REACTOS_STR_ORIGINAL_FILENAME "vgafontedit.exe"
#include <reactos/version.rc>
IDA_MAINACCELERATORS ACCELERATORS
BEGIN
"N", ID_FILE_NEW, VIRTKEY, CONTROL
"O", ID_FILE_OPEN, VIRTKEY, CONTROL
"S", ID_FILE_SAVE, VIRTKEY, CONTROL
END
IDB_MAIN_TOOLBAR BITMAP "res/toolbar.bmp"
IDB_EDIT_GLYPH_TOOLBOX BITMAP "res/toolbox.bmp"
IDI_MAIN ICON "res/main.ico"
IDI_DOC ICON "res/doc.ico"
// Languages
#include "lang/en-US.rc"

View file

@ -0,0 +1,477 @@
/*
* PROJECT: ReactOS VGA Font Editor
* LICENSE: GNU General Public License Version 2.0 or any later version
* FILE: devutils/vgafontedit/mainwnd.c
* PURPOSE: Implements the main window of the application
* COPYRIGHT: Copyright 2008 Colin Finck <mail@colinfinck.de>
*/
#include "precomp.h"
static const WCHAR szMainWndClass[] = L"VGAFontEditMainWndClass";
static VOID
InitResources(IN PMAIN_WND_INFO Info)
{
HDC hMemDC;
HDC hMainDC;
HPEN hPen;
RECT rect;
hMemDC = CreateCompatibleDC(NULL);
hMainDC = GetDC(Info->hMainWnd);
// Create the "Box" bitmap
Info->hBoxBmp = CreateCompatibleBitmap(hMainDC, CHARACTER_BOX_WIDTH, CHARACTER_BOX_HEIGHT);
SelectObject(hMemDC, Info->hBoxBmp);
rect.left = 0;
rect.top = 0;
rect.right = CHARACTER_INFO_BOX_WIDTH;
rect.bottom = CHARACTER_INFO_BOX_HEIGHT;
FillRect( hMemDC, &rect, (HBRUSH)(COLOR_BTNFACE + 1) );
SelectObject( hMemDC, GetStockObject(WHITE_PEN) );
Rectangle(hMemDC, 0, 0, CHARACTER_INFO_BOX_WIDTH - 1, 2);
Rectangle(hMemDC, 0, 2, 2, CHARACTER_INFO_BOX_HEIGHT - 1);
hPen = CreatePen( PS_SOLID, 1, RGB(128, 128, 128) );
SelectObject(hMemDC, hPen);
Rectangle(hMemDC, 1, CHARACTER_INFO_BOX_HEIGHT - 2, CHARACTER_INFO_BOX_WIDTH, CHARACTER_INFO_BOX_HEIGHT);
Rectangle(hMemDC, CHARACTER_INFO_BOX_WIDTH - 2, 1, CHARACTER_INFO_BOX_WIDTH, CHARACTER_INFO_BOX_HEIGHT - 2);
SetPixel( hMemDC, CHARACTER_INFO_BOX_WIDTH - 1, 0, RGB(128, 128, 128) );
SetPixel( hMemDC, 0, CHARACTER_INFO_BOX_HEIGHT - 1, RGB(128, 128, 128) );
DeleteObject(hPen);
DeleteDC(hMemDC);
}
static VOID
UnInitResources(IN PMAIN_WND_INFO Info)
{
DeleteObject(Info->hBoxBmp);
}
static VOID
AddToolbarButton(IN PMAIN_WND_INFO Info, IN INT iBitmap, IN INT idCommand, IN UINT uID)
{
PWSTR pszTooltip;
TBBUTTON tbb = {0,};
if( AllocAndLoadString(&pszTooltip, uID) )
{
tbb.fsState = TBSTATE_ENABLED;
tbb.iBitmap = iBitmap;
tbb.idCommand = idCommand;
tbb.iString = (INT_PTR)pszTooltip;
SendMessageW( Info->hToolbar, TB_ADDBUTTONSW, 1, (LPARAM)&tbb );
HeapFree(hProcessHeap, 0, pszTooltip);
}
}
static VOID
SetToolbarButtonState(IN PMAIN_WND_INFO Info, INT idCommand, BOOL bEnabled)
{
TBBUTTONINFOW tbbi = {0,};
tbbi.cbSize = sizeof(tbbi);
tbbi.dwMask = TBIF_STATE;
tbbi.fsState = (bEnabled ? TBSTATE_ENABLED : 0);
SendMessageW(Info->hToolbar, TB_SETBUTTONINFOW, idCommand, (LPARAM)&tbbi);
}
VOID
SetToolbarFileButtonState(IN PMAIN_WND_INFO Info, BOOL bEnabled)
{
SetToolbarButtonState(Info, ID_FILE_SAVE, bEnabled);
SetToolbarButtonState(Info, ID_EDIT_GLYPH, bEnabled);
}
static VOID
AddToolbarSeparator(IN PMAIN_WND_INFO Info)
{
TBBUTTON tbb = {0,};
tbb.fsStyle = BTNS_SEP;
SendMessageW( Info->hToolbar, TB_ADDBUTTONSW, 1, (LPARAM)&tbb );
}
static VOID
InitMainWnd(IN PMAIN_WND_INFO Info)
{
CLIENTCREATESTRUCT ccs;
INT iCustomBitmaps;
INT iStandardBitmaps;
TBADDBITMAP tbab;
// Add the toolbar
Info->hToolbar = CreateWindowExW(0,
TOOLBARCLASSNAMEW,
NULL,
WS_VISIBLE | WS_CHILD | TBSTYLE_TOOLTIPS,
0,
0,
0,
0,
Info->hMainWnd,
NULL,
hInstance,
NULL);
// Identify the used Common Controls version
SendMessageW(Info->hToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
// Enable Tooltips
SendMessageW(Info->hToolbar, TB_SETMAXTEXTROWS, 0, 0);
// Add the toolbar bitmaps
tbab.hInst = HINST_COMMCTRL;
tbab.nID = IDB_STD_SMALL_COLOR;
iStandardBitmaps = SendMessageW(Info->hToolbar, TB_ADDBITMAP, 0, (LPARAM)&tbab);
tbab.hInst = hInstance;
tbab.nID = IDB_MAIN_TOOLBAR;
iCustomBitmaps = SendMessageW(Info->hToolbar, TB_ADDBITMAP, 0, (LPARAM)&tbab);
// Add the toolbar buttons
AddToolbarButton(Info, iStandardBitmaps + STD_FILENEW, ID_FILE_NEW, IDS_TOOLTIP_NEW);
AddToolbarButton(Info, iStandardBitmaps + STD_FILEOPEN, ID_FILE_OPEN, IDS_TOOLTIP_OPEN);
AddToolbarButton(Info, iStandardBitmaps + STD_FILESAVE, ID_FILE_SAVE, IDS_TOOLTIP_SAVE);
AddToolbarSeparator(Info);
AddToolbarButton(Info, iCustomBitmaps + TOOLBAR_EDIT_GLYPH, ID_EDIT_GLYPH, IDS_TOOLTIP_EDIT_GLYPH);
SetToolbarFileButtonState(Info, FALSE);
// Add the MDI client area
ccs.hWindowMenu = GetSubMenu(Info->hMenu, 1);
ccs.idFirstChild = ID_MDI_FIRSTCHILD;
Info->hMdiClient = CreateWindowExW(WS_EX_CLIENTEDGE,
L"MDICLIENT",
NULL,
WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VSCROLL | WS_HSCROLL,
0,
0,
0,
0,
Info->hMainWnd,
NULL,
hInstance,
&ccs);
// Initialize the file handling
FileInitialize(Info->hMainWnd);
}
static VOID
InitMenuPopup(IN PMAIN_WND_INFO Info)
{
UINT uState;
uState = MF_BYCOMMAND | (Info->CurrentFontWnd == NULL);
EnableMenuItem(Info->hMenu, ID_FILE_CLOSE, uState);
EnableMenuItem(Info->hMenu, ID_FILE_SAVE, uState);
EnableMenuItem(Info->hMenu, ID_FILE_SAVE_AS, uState);
}
static VOID
DoFileNew(IN PMAIN_WND_INFO Info)
{
PFONT_OPEN_INFO OpenInfo;
OpenInfo = (PFONT_OPEN_INFO) HeapAlloc( hProcessHeap, HEAP_ZERO_MEMORY, sizeof(FONT_OPEN_INFO) );
OpenInfo->bCreateNew = TRUE;
CreateFontWindow(Info, OpenInfo);
}
static VOID
DoFileOpen(IN PMAIN_WND_INFO Info)
{
PFONT_OPEN_INFO OpenInfo;
OpenInfo = (PFONT_OPEN_INFO) HeapAlloc( hProcessHeap, HEAP_ZERO_MEMORY, sizeof(FONT_OPEN_INFO) );
OpenInfo->pszFileName = HeapAlloc(hProcessHeap, 0, MAX_PATH);
OpenInfo->pszFileName[0] = 0;
if( DoOpenFile(OpenInfo->pszFileName) )
{
OpenInfo->bCreateNew = FALSE;
CreateFontWindow(Info, OpenInfo);
}
}
VOID
DoFileSave(IN PMAIN_WND_INFO Info, IN BOOL bSaveAs)
{
DWORD dwBytesWritten;
HANDLE hFile;
// Show the "Save" dialog
// - if "Save As" was clicked
// - if the file was not yet saved
// - if another format than the binary format was opened
if(bSaveAs || !Info->CurrentFontWnd->OpenInfo->bBinaryFileOpened)
{
if(!Info->CurrentFontWnd->OpenInfo->pszFileName)
{
Info->CurrentFontWnd->OpenInfo->pszFileName = (PWSTR) HeapAlloc(hProcessHeap, 0, MAX_PATH);
Info->CurrentFontWnd->OpenInfo->pszFileName[0] = 0;
}
else if(!Info->CurrentFontWnd->OpenInfo->bBinaryFileOpened)
{
// For a file in another format, the user has to enter a new file name as well
Info->CurrentFontWnd->OpenInfo->pszFileName[0] = 0;
}
if( !DoSaveFile(Info->CurrentFontWnd->OpenInfo->pszFileName) )
return;
}
// Save the binary font
hFile = CreateFileW(Info->CurrentFontWnd->OpenInfo->pszFileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
LocalizedError( IDS_OPENERROR, GetLastError() );
return;
}
if( !WriteFile(hFile, Info->CurrentFontWnd->Font, sizeof(BITMAP_FONT), &dwBytesWritten, NULL) )
LocalizedError( IDS_WRITEERROR, GetLastError() );
CloseHandle(hFile);
}
static BOOL
MenuCommand(IN INT nMenuItemID, IN PMAIN_WND_INFO Info)
{
switch(nMenuItemID)
{
// File Menu
case ID_FILE_NEW:
DoFileNew(Info);
return TRUE;
case ID_FILE_OPEN:
DoFileOpen(Info);
return TRUE;
case ID_FILE_CLOSE:
SendMessageW(Info->CurrentFontWnd->hSelf, WM_CLOSE, 0, 0);
return TRUE;
case ID_FILE_SAVE:
DoFileSave(Info, FALSE);
return TRUE;
case ID_FILE_SAVE_AS:
DoFileSave(Info, TRUE);
return TRUE;
case ID_FILE_EXIT:
PostMessage(Info->hMainWnd, WM_CLOSE, 0, 0);
return TRUE;
// "Edit Glyph" toolbar button
case ID_EDIT_GLYPH:
EditCurrentGlyph(Info->CurrentFontWnd);
return TRUE;
// Window Menu
case ID_WINDOW_TILE_HORZ:
SendMessageW(Info->hMdiClient, WM_MDITILE, MDITILE_HORIZONTAL, 0);
return TRUE;
case ID_WINDOW_TILE_VERT:
SendMessageW(Info->hMdiClient, WM_MDITILE, MDITILE_VERTICAL, 0);
return TRUE;
case ID_WINDOW_CASCADE:
SendMessageW(Info->hMdiClient, WM_MDICASCADE, 0, 0);
return TRUE;
case ID_WINDOW_ARRANGE:
SendMessageW(Info->hMdiClient, WM_MDIICONARRANGE, 0, 0);
return TRUE;
case ID_WINDOW_NEXT:
SendMessageW(Info->hMdiClient, WM_MDINEXT, 0, 0);
return TRUE;
// Help Menu
case ID_HELP_ABOUT:
DialogBoxW( hInstance, MAKEINTRESOURCEW(IDD_ABOUT), Info->hMainWnd, AboutDlgProc );
return TRUE;
}
return FALSE;
}
static VOID
MainWndSize(PMAIN_WND_INFO Info, INT cx, INT cy)
{
HDWP dwp;
INT iMdiTop;
RECT ToolbarRect;
iMdiTop = 0;
dwp = BeginDeferWindowPos(2);
if(!dwp)
return;
if(Info->hToolbar)
{
GetWindowRect(Info->hToolbar, &ToolbarRect);
iMdiTop += ToolbarRect.bottom - ToolbarRect.top;
dwp = DeferWindowPos(dwp, Info->hToolbar, NULL, 0, 0, cx, ToolbarRect.bottom - ToolbarRect.top, SWP_NOZORDER);
if(!dwp)
return;
}
if(Info->hMdiClient)
{
dwp = DeferWindowPos(dwp, Info->hMdiClient, NULL, 0, iMdiTop, cx, cy - iMdiTop, SWP_NOZORDER);
if(!dwp)
return;
}
EndDeferWindowPos(dwp);
}
static LRESULT CALLBACK
MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PMAIN_WND_INFO Info;
Info = (PMAIN_WND_INFO) GetWindowLongW(hwnd, GWLP_USERDATA);
if(Info || uMsg == WM_CREATE)
{
switch(uMsg)
{
case WM_COMMAND:
if( MenuCommand( LOWORD(wParam), Info ) )
return 0;
break;
case WM_CLOSE:
if(Info->FirstFontWnd)
{
// Send WM_CLOSE to all subwindows, so they can prompt for saving unsaved files
PFONT_WND_INFO pNextWnd;
PFONT_WND_INFO pWnd;
pWnd = Info->FirstFontWnd;
do
{
// The pWnd structure might already be destroyed after the WM_CLOSE, so we have to preserve the address of the next window here
pNextWnd = pWnd->NextFontWnd;
// Send WM_USER_APPCLOSE, so we can check for a custom return value
// In this case, we check if the user clicked the "Cancel" button in one of the prompts and if so, we don't close the app
if( !SendMessage(pWnd->hSelf, WM_USER_APPCLOSE, 0, 0) )
return 0;
}
while( (pWnd = pNextWnd) );
}
break;
case WM_CREATE:
Info = (PMAIN_WND_INFO)( ( (LPCREATESTRUCT)lParam )->lpCreateParams );
Info->hMainWnd = hwnd;
Info->hMenu = GetMenu(hwnd);
SetWindowLongW(hwnd, GWLP_USERDATA, (LONG)Info);
InitMainWnd(Info);
InitResources(Info);
ShowWindow(hwnd, Info->nCmdShow);
return 0;
case WM_DESTROY:
UnInitResources(Info);
HeapFree(hProcessHeap, 0, Info);
SetWindowLongW(hwnd, GWLP_USERDATA, 0);
PostQuitMessage(0);
return 0;
case WM_INITMENUPOPUP:
InitMenuPopup(Info);
break;
case WM_SIZE:
MainWndSize( Info, LOWORD(lParam), HIWORD(lParam) );
return 0;
}
}
if(Info && Info->hMdiClient)
return DefFrameProcW(hwnd, Info->hMdiClient, uMsg, wParam, lParam);
else
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
BOOL
CreateMainWindow(IN INT nCmdShow, OUT PMAIN_WND_INFO* Info)
{
HWND hMainWnd;
*Info = (PMAIN_WND_INFO) HeapAlloc( hProcessHeap, HEAP_ZERO_MEMORY, sizeof(MAIN_WND_INFO) );
if(*Info)
{
(*Info)->nCmdShow = nCmdShow;
hMainWnd = CreateWindowExW(0,
szMainWndClass,
szAppName,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
LoadMenuW(hInstance, MAKEINTRESOURCEW(IDM_MAINMENU)),
hInstance,
*Info);
if(hMainWnd)
return TRUE;
else
HeapFree(hProcessHeap, 0, *Info);
}
return FALSE;
}
BOOL
InitMainWndClass(VOID)
{
WNDCLASSW wc = {0,};
wc.lpfnWndProc = MainWndProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hIcon = LoadIconW( hInstance, MAKEINTRESOURCEW(IDI_MAIN) );
wc.hbrBackground = (HBRUSH)( COLOR_BTNFACE + 1 );
wc.lpszClassName = szMainWndClass;
return RegisterClassW(&wc) != 0;
}
VOID
UnInitMainWndClass(VOID)
{
UnregisterClassW(szMainWndClass, hInstance);
}

View file

@ -0,0 +1,118 @@
/*
* PROJECT: ReactOS VGA Font Editor
* LICENSE: GNU General Public License Version 2.0 only
* FILE: devutils/vgafontedit/misc.c
* PURPOSE: Some miscellaneous resource functions (copied from "devmgmt") and modified
* COPYRIGHT: Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
* Copyright 2008 Colin Finck <mail@colinfinck.de>
*/
#include "precomp.h"
static INT
LengthOfStrResource(IN UINT uID)
{
HRSRC hrSrc;
HGLOBAL hRes;
PWSTR lpName, lpStr;
/* There are always blocks of 16 strings */
lpName = (PWSTR) MAKEINTRESOURCEW((uID >> 4) + 1);
/* Find the string table block */
if ((hrSrc = FindResourceW(hInstance, lpName, (PWSTR)RT_STRING)) != 0 &&
(hRes = LoadResource(hInstance, hrSrc)) != 0 &&
(lpStr = (PWSTR)LockResource(hRes)) != 0)
{
UINT x;
/* Find the string we're looking for */
uID &= 0xF; /* position in the block, same as % 16 */
for (x = 0; x < uID; x++)
lpStr += (*lpStr) + 1;
/* Found the string */
return (int)(*lpStr);
}
return -1;
}
INT
AllocAndLoadString(OUT PWSTR *lpTarget, IN UINT uID)
{
INT ln;
ln = LengthOfStrResource(uID);
if (ln++ > 0)
{
(*lpTarget) = (PWSTR) HeapAlloc( hProcessHeap, 0, ln * sizeof(WCHAR) );
if (*lpTarget)
{
INT nRet;
nRet = LoadStringW(hInstance, uID, *lpTarget, ln);
if (!nRet)
HeapFree(hProcessHeap, 0, *lpTarget);
return nRet;
}
}
return 0;
}
static DWORD
VarListLoadAndFormatString(IN UINT uID, OUT PWSTR *lpTarget, IN va_list* Args)
{
DWORD Ret = 0;
PWSTR lpFormat;
if (AllocAndLoadString(&lpFormat, uID) > 0)
{
/* let's use FormatMessage to format it because it has the ability to allocate
memory automatically */
Ret = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
lpFormat,
0,
0,
(LPWSTR)lpTarget,
0,
Args);
HeapFree(hProcessHeap, 0, lpFormat);
}
return Ret;
}
DWORD
LoadAndFormatString(IN UINT uID, OUT PWSTR *lpTarget, ...)
{
DWORD Ret;
va_list Args;
va_start(Args, lpTarget);
Ret = VarListLoadAndFormatString(uID, lpTarget, &Args);
va_end(Args);
return Ret;
}
VOID
LocalizedError(IN UINT uID, ...)
{
PWSTR pszError;
va_list Args;
va_start(Args, uID);
VarListLoadAndFormatString(uID, &pszError, &Args);
va_end(Args);
MessageBoxW(NULL, pszError, szAppName, MB_ICONERROR);
HeapFree(hProcessHeap, 0, pszError);
}

View file

@ -0,0 +1,77 @@
/*
* PROJECT: ReactOS VGA Font Editor
* LICENSE: GNU General Public License Version 2.0 or any later version
* FILE: devutils/vgafontedit/opensave.c
* PURPOSE: Functions for opening and saving files
* COPYRIGHT: Copyright 2008 Colin Finck <mail@colinfinck.de>
*/
#include "precomp.h"
static OPENFILENAMEW ofn;
VOID
FileInitialize(IN HWND hwnd)
{
ZeroMemory( &ofn, sizeof(ofn) );
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrDefExt = L"bin";
}
static __inline VOID
PrepareFilter(IN PWSTR pszFilter)
{
// RC strings can't be double-null terminated, so we use | instead to separate the entries.
// Convert them back to null characters here.
do
{
if(*pszFilter == '|')
*pszFilter = 0;
}
while(*++pszFilter);
}
BOOL
DoOpenFile(OUT PWSTR pszFileName)
{
BOOL bRet;
PWSTR pszFilter;
if( AllocAndLoadString(&pszFilter, IDS_OPENFILTER) )
{
PrepareFilter(pszFilter);
ofn.lpstrFilter = pszFilter;
ofn.lpstrFile = pszFileName;
ofn.Flags = OFN_FILEMUSTEXIST;
bRet = GetOpenFileNameW(&ofn);
HeapFree(hProcessHeap, 0, pszFilter);
return bRet;
}
return FALSE;
}
BOOL
DoSaveFile(IN OUT PWSTR pszFileName)
{
BOOL bRet;
PWSTR pszFilter;
if( AllocAndLoadString(&pszFilter, IDS_SAVEFILTER) )
{
PrepareFilter(pszFilter);
ofn.lpstrFilter = pszFilter;
ofn.lpstrFile = pszFileName;
bRet = GetSaveFileNameW(&ofn);
HeapFree(hProcessHeap, 0, pszFilter);
return bRet;
}
return FALSE;
}

View file

@ -0,0 +1,161 @@
/*
* PROJECT: ReactOS VGA Font Editor
* LICENSE: GNU General Public License Version 2.0 or any later version
* FILE: devutils/vgafontedit/precomp.h
* PURPOSE: Main header
* COPYRIGHT: Copyright 2008 Colin Finck <mail@colinfinck.de>
*/
#ifndef __PRECOMP_H
#define __PRECOMP_H
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include "resource.h"
#include "customwndclasses.h"
// Forward declarations
typedef struct _FONT_WND_INFO FONT_WND_INFO, *PFONT_WND_INFO;
// Structure declarations
typedef struct _BITMAP_FONT
{
UCHAR Bits[2048];
} BITMAP_FONT, *PBITMAP_FONT;
typedef struct _MAIN_WND_INFO
{
HWND hMainWnd;
HWND hMdiClient;
HMENU hMenu;
HWND hToolbar;
INT nCmdShow;
HBITMAP hBoxBmp;
PFONT_WND_INFO CurrentFontWnd;
ULONG uDocumentCounter;
PFONT_WND_INFO FirstFontWnd;
PFONT_WND_INFO LastFontWnd;
} MAIN_WND_INFO, *PMAIN_WND_INFO;
typedef struct _FONT_OPEN_INFO
{
BOOL bCreateNew;
BOOL bBinaryFileOpened;
BOOL bModified;
PWSTR pszFileName;
} FONT_OPEN_INFO, *PFONT_OPEN_INFO;
struct _FONT_WND_INFO
{
PMAIN_WND_INFO MainWndInfo;
PFONT_OPEN_INFO OpenInfo;
PBITMAP_FONT Font;
HWND hSelf;
HWND hFontBoxesWnd;
UINT uSelectedCharacter;
PFONT_WND_INFO PrevFontWnd;
PFONT_WND_INFO NextFontWnd;
};
typedef struct _EDIT_GLYPH_INFO
{
PFONT_WND_INFO FontWndInfo;
UINT uCharacter;
UCHAR CharacterBits[8];
HWND hSelf;
HWND hEdit;
HWND hPreview;
LONG lEditSpacing;
} EDIT_GLYPH_INFO, *PEDIT_GLYPH_INFO;
#define ID_MDI_FIRSTCHILD 50000
// Dimensions of the visual elements
#define CHARACTER_INFO_BOX_WIDTH 55
#define CHARACTER_INFO_BOX_HEIGHT 16
#define CHARACTER_BITMAP_BOX_HEIGHT 14
#define CHARACTER_BOX_WIDTH (CHARACTER_INFO_BOX_WIDTH)
#define CHARACTER_BOX_HEIGHT (CHARACTER_INFO_BOX_HEIGHT + CHARACTER_BITMAP_BOX_HEIGHT)
#define CHARACTER_BOX_PADDING 5
#define FONT_BOXES_WND_WIDTH (CHARACTER_BOX_WIDTH * 16 + CHARACTER_BOX_PADDING * 15)
#define FONT_BOXES_WND_HEIGHT (CHARACTER_BOX_HEIGHT * 16 + CHARACTER_BOX_PADDING * 15)
#define FONT_WND_MIN_WIDTH (FONT_BOXES_WND_WIDTH + 25)
#define FONT_WND_MIN_HEIGHT (FONT_BOXES_WND_HEIGHT + GetSystemMetrics(SM_CYCAPTION) + 25)
// Custom return values
#define HITTEST_SEPARATOR -1
// Custom window messages
#define WM_USER_APPCLOSE (WM_USER + 1)
// Bitmap numbers
#define TOOLBAR_EDIT_GLYPH 0
#define TOOLBOX_PEN 0
// PSFv1 file handling
#define PSF1_MAGIC0 0x36
#define PSF1_MAGIC1 0x04
typedef struct _PSF1_HEADER
{
UCHAR uMagic[2];
UCHAR uMode;
UCHAR uCharSize;
} PSF1_HEADER, *PPSF1_HEADER;
//
// Function prototypes
//
// aboutdlg.c
INT_PTR CALLBACK AboutDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
// editglyphdlg.c
INT_PTR CALLBACK EditGlyphDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
BOOL InitEditGlyphWndClasses(VOID);
VOID UnInitEditGlyphWndClasses(VOID);
// fontboxeswnd.c
VOID CreateFontBoxesWindow(PFONT_WND_INFO FontWndInfo);
BOOL InitFontBoxesWndClass(VOID);
VOID UnInitFontBoxesWndClass(VOID);
VOID GetCharacterRect(IN UINT uFontRow, IN UINT uFontColumn, OUT LPRECT CharacterRect);
__inline VOID GetCharacterPosition(IN UINT uCharacter, OUT PUINT uFontRow, OUT PUINT uFontColumn);
VOID EditCurrentGlyph(PFONT_WND_INFO FontWndInfo);
// fontwnd.c
BOOL CreateFontWindow(PMAIN_WND_INFO MainWndInfo, PFONT_OPEN_INFO OpenInfo);
BOOL InitFontWndClass(VOID);
VOID UnInitFontWndClass(VOID);
// main.c
extern const WCHAR szAppName[];
extern HINSTANCE hInstance;
extern HANDLE hProcessHeap;
// mainwnd.c
BOOL CreateMainWindow(IN INT nCmdShow, OUT PMAIN_WND_INFO* Info);
BOOL InitMainWndClass(VOID);
VOID UnInitMainWndClass(VOID);
VOID DoFileSave(IN PMAIN_WND_INFO Info, IN BOOL bSaveAs);
VOID SetToolbarFileButtonState(IN PMAIN_WND_INFO Info, BOOL bEnabled);
// misc.c
INT AllocAndLoadString(OUT PWSTR *lpTarget, IN UINT uID);
DWORD LoadAndFormatString(IN UINT uID, OUT PWSTR *lpTarget, ...);
VOID LocalizedError(IN UINT uID, ...);
// opensave.c
VOID FileInitialize(HWND hwnd);
BOOL DoOpenFile(OUT PWSTR pszFileName);
BOOL DoSaveFile(IN PWSTR pszFileName);
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

View file

@ -0,0 +1,73 @@
/*
* PROJECT: ReactOS VGA Font Editor
* LICENSE: GNU General Public License Version 2.0 or any later version
* FILE: devutils/vgafontedit/resource.h
* PURPOSE: Header containing resource IDs
* COPYRIGHT: Copyright 2008 Colin Finck <mail@colinfinck.de>
*/
#ifndef __RESOURCE_H
#define __RESOURCE_H
#define IDC_STATIC -1
// Icons
#define IDI_MAIN 100
#define IDI_DOC 101
// Accelerator Tables
#define IDA_MAINACCELERATORS 201
// Menus
#define IDM_MAINMENU 301
// Bitmaps
#define IDB_MAIN_TOOLBAR 401
#define IDB_EDIT_GLYPH_TOOLBOX 402
// Dialogs
#define IDD_ABOUT 501
#define IDD_EDITGLYPH 502
// Dialog Controls
#define IDC_EDIT_GLYPH_TOOLBOX 601
#define IDC_EDIT_GLYPH_EDIT 602
#define IDC_EDIT_GLYPH_PREVIEW 603
// Command IDs
#define ID_FILE_NEW 1001
#define ID_FILE_OPEN 1002
#define ID_FILE_CLOSE 1003
#define ID_FILE_SAVE 1004
#define ID_FILE_SAVE_AS 1005
#define ID_FILE_EXIT 1006
#define ID_EDIT_GLYPH 2001
#define ID_WINDOW_TILE_HORZ 3001
#define ID_WINDOW_TILE_VERT 3002
#define ID_WINDOW_CASCADE 3003
#define ID_WINDOW_NEXT 3004
#define ID_WINDOW_ARRANGE 3005
#define ID_HELP_ABOUT 4001
#define ID_TOOLBOX_PEN 5001
// Strings
#define IDS_OPENFILTER 10001
#define IDS_SAVEFILTER 10002
#define IDS_OPENERROR 10003
#define IDS_READERROR 10004
#define IDS_WRITEERROR 10005
#define IDS_UNSUPPORTEDFORMAT 10006
#define IDS_UNSUPPORTEDPSF 10007
#define IDS_DOCNAME 10008
#define IDS_SAVEPROMPT 10009
#define IDS_TOOLTIP_NEW 11001
#define IDS_TOOLTIP_OPEN 11002
#define IDS_TOOLTIP_SAVE 11003
#define IDS_TOOLTIP_EDIT_GLYPH 11004
#endif

View file

@ -0,0 +1,19 @@
<module name="vgafontedit" type="win32gui" installname="vgafontedit.exe" unicode="yes">
<include base="vgafontedit">.</include>
<library>kernel32</library>
<library>user32</library>
<library>gdi32</library>
<library>comdlg32</library>
<file>aboutdlg.c</file>
<file>editglyphdlg.c</file>
<file>fontboxeswnd.c</file>
<file>fontwnd.c</file>
<file>main.c</file>
<file>main.rc</file>
<file>mainwnd.c</file>
<file>misc.c</file>
<file>opensave.c</file>
<pch>precomp.h</pch>
</module>