-#include <precomp.h>\r
-\r
-static const TCHAR szMapWndClass[] = TEXT("FontMapWnd");\r
-static const TCHAR szLrgCellWndClass[] = TEXT("LrgCellWnd");\r
-\r
-static VOID\r
-TagFontToCell(PCELL pCell,\r
- TCHAR ch)\r
-{\r
- pCell->ch = ch;\r
-}\r
-\r
-\r
-static VOID\r
-SetGrid(PMAP infoPtr)\r
-{\r
- INT x, y;\r
-\r
- for (y = 0; y < YCELLS; y++)\r
- for (x = 0; x < XCELLS; x++)\r
- {\r
- infoPtr->Cells[y][x].CellExt.left = x * infoPtr->CellSize.cx + 1;\r
- infoPtr->Cells[y][x].CellExt.top = y * infoPtr->CellSize.cy + 1;\r
- infoPtr->Cells[y][x].CellExt.right = (x + 1) * infoPtr->CellSize.cx + 2;\r
- infoPtr->Cells[y][x].CellExt.bottom = (y + 1) * infoPtr->CellSize.cy + 2;\r
-\r
- CopyRect(&infoPtr->Cells[y][x].CellInt,\r
- &infoPtr->Cells[y][x].CellExt);\r
-\r
- InflateRect(&infoPtr->Cells[y][x].CellInt,\r
- -1,\r
- -1);\r
- }\r
-}\r
-\r
-static VOID\r
-DrawActiveCell(PMAP infoPtr,\r
- HDC hdc)\r
-{\r
- Rectangle(hdc,\r
- infoPtr->pActiveCell->CellInt.left,\r
- infoPtr->pActiveCell->CellInt.top,\r
- infoPtr->pActiveCell->CellInt.right,\r
- infoPtr->pActiveCell->CellInt.bottom);\r
-\r
-}\r
-\r
-\r
-static VOID\r
-DrawGrid(PMAP infoPtr,\r
- HDC hdc)\r
-{\r
- INT x, y;\r
-\r
- for (y = 0; y < YCELLS; y++)\r
- for (x = 0; x < XCELLS; x++)\r
- {\r
- Rectangle(hdc,\r
- infoPtr->Cells[y][x].CellExt.left,\r
- infoPtr->Cells[y][x].CellExt.top,\r
- infoPtr->Cells[y][x].CellExt.right,\r
- infoPtr->Cells[y][x].CellExt.bottom);\r
- }\r
-\r
- if (infoPtr->pActiveCell)\r
- DrawActiveCell(infoPtr,\r
- hdc);\r
-}\r
-\r
-\r
-static VOID\r
-FillGrid(PMAP infoPtr,\r
- HDC hdc)\r
-{\r
- HFONT hOldFont;\r
- TCHAR ch;\r
- INT x, y;\r
-\r
- hOldFont = SelectObject(hdc,\r
- infoPtr->hFont);\r
-\r
- for (y = 0; y < YCELLS; y++)\r
- for (x = 0; x < XCELLS; x++)\r
- {\r
- ch = (TCHAR)((256 * infoPtr->iPage) + (XCELLS * y) + x);\r
-\r
- TagFontToCell(&infoPtr->Cells[y][x], ch);\r
-\r
- DrawText(hdc,\r
- &ch,\r
- 1,\r
- &infoPtr->Cells[y][x].CellInt,\r
- DT_CENTER | DT_VCENTER | DT_SINGLELINE);\r
- }\r
-\r
- SelectObject(hdc,\r
- hOldFont);\r
-}\r
-\r
-\r
-static BOOL\r
-CreateLargeCell(PMAP infoPtr)\r
-{\r
- RECT rLarge;\r
-\r
- CopyRect(&rLarge,\r
- &infoPtr->pActiveCell->CellExt);\r
-\r
- MapWindowPoints(infoPtr->hMapWnd,\r
- infoPtr->hParent,\r
- (LPPOINT)&rLarge,\r
- 2);\r
-\r
- InflateRect(&rLarge,\r
- XLARGE - XCELLS,\r
- YLARGE - YCELLS);\r
-\r
- infoPtr->hLrgWnd = CreateWindowEx(0,\r
- szLrgCellWndClass,\r
- NULL,\r
- WS_CHILDWINDOW | WS_VISIBLE,\r
- rLarge.left,\r
- rLarge.top,\r
- rLarge.right - rLarge.left,\r
- rLarge.bottom - rLarge.top,\r
- infoPtr->hParent,\r
- NULL,\r
- hInstance,\r
- infoPtr);\r
- if (!infoPtr->hLrgWnd)\r
- return FALSE;\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-static VOID\r
-MoveLargeCell(PMAP infoPtr)\r
-{\r
- RECT rLarge;\r
-\r
- CopyRect(&rLarge,\r
- &infoPtr->pActiveCell->CellExt);\r
-\r
- MapWindowPoints(infoPtr->hMapWnd,\r
- infoPtr->hParent,\r
- (LPPOINT)&rLarge,\r
- 2);\r
-\r
- InflateRect(&rLarge,\r
- XLARGE - XCELLS,\r
- YLARGE - YCELLS);\r
-\r
- MoveWindow(infoPtr->hLrgWnd,\r
- rLarge.left,\r
- rLarge.top,\r
- rLarge.right - rLarge.left,\r
- rLarge.bottom - rLarge.top,\r
- TRUE);\r
-\r
- InvalidateRect(infoPtr->hLrgWnd,\r
- NULL,\r
- TRUE);\r
-}\r
-\r
-\r
-static VOID\r
-SetFont(PMAP infoPtr,\r
- LPTSTR lpFontName)\r
-{\r
- HDC hdc;\r
-\r
- if (infoPtr->hFont)\r
- DeleteObject(infoPtr->hFont);\r
-\r
- ZeroMemory(&infoPtr->CurrentFont,\r
- sizeof(LOGFONT));\r
-\r
- hdc = GetDC(infoPtr->hMapWnd);\r
- infoPtr->CurrentFont.lfHeight = GetDeviceCaps(hdc,\r
- LOGPIXELSY) / 5;\r
- ReleaseDC(infoPtr->hMapWnd, hdc);\r
-\r
- infoPtr->CurrentFont.lfCharSet = DEFAULT_CHARSET;\r
- lstrcpy(infoPtr->CurrentFont.lfFaceName,\r
- lpFontName);\r
-\r
- infoPtr->hFont = CreateFontIndirect(&infoPtr->CurrentFont);\r
-\r
- InvalidateRect(infoPtr->hMapWnd,\r
- NULL,\r
- TRUE);\r
-}\r
-\r
-\r
-static LRESULT\r
-NotifyParentOfSelection(PMAP infoPtr,\r
- UINT code,\r
- TCHAR ch)\r
-{\r
- LRESULT Ret = 0;\r
-\r
- if (infoPtr->hParent != NULL)\r
- {\r
- MAPNOTIFY mnmh;\r
-\r
- mnmh.hdr.hwndFrom = infoPtr->hMapWnd;\r
- mnmh.hdr.idFrom = GetWindowLongPtr(infoPtr->hMapWnd,\r
- GWLP_ID);\r
- mnmh.hdr.code = code;\r
-\r
- mnmh.ch = ch;\r
-\r
- Ret = SendMessage(infoPtr->hParent,\r
- WM_NOTIFY,\r
- (WPARAM)mnmh.hdr.idFrom,\r
- (LPARAM)&mnmh);\r
- }\r
-\r
- return Ret;\r
-}\r
-\r
-\r
-static VOID\r
-OnClick(PMAP infoPtr,\r
- WORD ptx,\r
- WORD pty)\r
-{\r
- POINT pt;\r
- INT x, y;\r
-\r
- pt.x = ptx;\r
- pt.y = pty;\r
-\r
- for (x = 0; x < XCELLS; x++)\r
- for (y = 0; y < YCELLS; y++)\r
- {\r
- if (PtInRect(&infoPtr->Cells[y][x].CellInt,\r
- pt))\r
- {\r
- /* if the cell is not already active */\r
- if (!infoPtr->Cells[y][x].bActive)\r
- {\r
- /* set previous active cell to inactive */\r
- if (infoPtr->pActiveCell)\r
- {\r
- /* invalidate normal cells, required when\r
- * moving a small active cell via keyboard */\r
- if (!infoPtr->pActiveCell->bLarge)\r
- {\r
- InvalidateRect(infoPtr->hMapWnd,\r
- &infoPtr->pActiveCell->CellInt,\r
- TRUE);\r
- }\r
-\r
- infoPtr->pActiveCell->bActive = FALSE;\r
- infoPtr->pActiveCell->bLarge = FALSE;\r
- }\r
-\r
- /* set new cell to active */\r
- infoPtr->pActiveCell = &infoPtr->Cells[y][x];\r
- infoPtr->pActiveCell->bActive = TRUE;\r
- infoPtr->pActiveCell->bLarge = TRUE;\r
- if (infoPtr->hLrgWnd)\r
- MoveLargeCell(infoPtr);\r
- else\r
- CreateLargeCell(infoPtr);\r
- }\r
- else\r
- {\r
- /* flick between large and small */\r
- if (infoPtr->pActiveCell->bLarge)\r
- {\r
- DestroyWindow(infoPtr->hLrgWnd);\r
- infoPtr->hLrgWnd = NULL;\r
- }\r
- else\r
- {\r
- CreateLargeCell(infoPtr);\r
- }\r
-\r
- infoPtr->pActiveCell->bLarge = (infoPtr->pActiveCell->bLarge) ? FALSE : TRUE;\r
- }\r
-\r
- break;\r
- }\r
- }\r
-}\r
-\r
-\r
-static BOOL\r
-OnCreate(PMAP infoPtr,\r
- HWND hwnd,\r
- HWND hParent)\r
-{\r
- RECT rc;\r
- BOOL Ret = FALSE;\r
-\r
- infoPtr = HeapAlloc(GetProcessHeap(),\r
- 0,\r
- sizeof(MAP));\r
- if (infoPtr)\r
- {\r
- SetLastError(0);\r
- SetWindowLongPtr(hwnd,\r
- 0,\r
- (DWORD_PTR)infoPtr);\r
- if (GetLastError() == 0)\r
- {\r
- ZeroMemory(infoPtr,\r
- sizeof(MAP));\r
-\r
- infoPtr->hMapWnd = hwnd;\r
- infoPtr->hParent = hParent;\r
-\r
- GetClientRect(hwnd, &rc);\r
- infoPtr->ClientSize.cx = rc.right;\r
- infoPtr->ClientSize.cy = rc.bottom;\r
- infoPtr->CellSize.cx = infoPtr->ClientSize.cx / XCELLS;\r
- infoPtr->CellSize.cy = infoPtr->ClientSize.cy / YCELLS;\r
-\r
- infoPtr->pActiveCell = NULL;\r
-\r
- SetGrid(infoPtr);\r
-\r
- SetScrollRange(hwnd, SB_VERT, 0, 255, FALSE);\r
- SetScrollPos(hwnd, SB_VERT, 0, TRUE);\r
-\r
- Ret = TRUE;\r
- }\r
- }\r
-\r
- return Ret;\r
-}\r
-\r
-\r
-static VOID\r
-OnVScroll(PMAP infoPtr,\r
- INT Value,\r
- INT Pos)\r
-{\r
- switch (Value)\r
- {\r
- case SB_LINEUP:\r
- infoPtr->iPage -= 1;\r
- break;\r
-\r
- case SB_LINEDOWN:\r
- infoPtr->iPage += 1;\r
- break;\r
-\r
- case SB_PAGEUP:\r
- infoPtr->iPage -= 16;\r
- break;\r
-\r
- case SB_PAGEDOWN:\r
- infoPtr->iPage += 16;\r
- break;\r
-\r
- case SB_THUMBPOSITION:\r
- infoPtr->iPage = Pos;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
-\r
- infoPtr->iPage = max(0,\r
- min(infoPtr->iPage,\r
- 255));\r
-\r
- SetScrollPos(infoPtr->hMapWnd,\r
- SB_VERT,\r
- infoPtr->iPage,\r
- TRUE);\r
-\r
- InvalidateRect(infoPtr->hMapWnd,\r
- NULL,\r
- TRUE);\r
-}\r
-\r
-\r
-static VOID\r
-OnPaint(PMAP infoPtr,\r
- WPARAM wParam)\r
-{\r
- PAINTSTRUCT ps;\r
- HDC hdc;\r
-\r
-\r
- if (wParam != 0)\r
- {\r
- if (!GetUpdateRect(infoPtr->hMapWnd,\r
- &ps.rcPaint,\r
- TRUE))\r
- {\r
- return;\r
- }\r
- hdc = (HDC)wParam;\r
- }\r
- else\r
- {\r
- hdc = BeginPaint(infoPtr->hMapWnd,\r
- &ps);\r
- if (hdc == NULL)\r
- {\r
- return;\r
- }\r
- }\r
-\r
- DrawGrid(infoPtr,\r
- hdc);\r
-\r
- FillGrid(infoPtr,\r
- hdc);\r
-\r
- if (wParam == 0)\r
- {\r
- EndPaint(infoPtr->hMapWnd,\r
- &ps);\r
- }\r
-}\r
-\r
-\r
-LRESULT CALLBACK\r
-MapWndProc(HWND hwnd,\r
- UINT uMsg,\r
- WPARAM wParam,\r
- LPARAM lParam)\r
-{\r
- PMAP infoPtr;\r
- LRESULT Ret = 0;\r
-\r
- infoPtr = (PMAP)GetWindowLongPtr(hwnd,\r
- 0);\r
-\r
- switch (uMsg)\r
- {\r
- case WM_CREATE:\r
- {\r
- if (!OnCreate(infoPtr,\r
- hwnd,\r
- ((LPCREATESTRUCTW)lParam)->hwndParent))\r
- {\r
- return (LRESULT)-1;\r
- }\r
-\r
- break;\r
- }\r
-\r
- case WM_LBUTTONDOWN:\r
- {\r
- OnClick(infoPtr,\r
- LOWORD(lParam),\r
- HIWORD(lParam));\r
-\r
- break;\r
- }\r
-\r
- case WM_LBUTTONDBLCLK:\r
- {\r
- NotifyParentOfSelection(infoPtr,\r
- FM_SETCHAR,\r
- infoPtr->pActiveCell->ch);\r
-\r
-\r
- break;\r
- }\r
-\r
- case WM_VSCROLL:\r
- {\r
- OnVScroll(infoPtr,\r
- LOWORD(wParam),\r
- HIWORD(wParam));\r
-\r
- break;\r
- }\r
-\r
- case FM_SETFONT:\r
- {\r
- LPTSTR lpFontName = (LPTSTR)lParam;\r
-\r
- SetFont(infoPtr,\r
- lpFontName);\r
-\r
- HeapFree(GetProcessHeap(),\r
- 0,\r
- lpFontName);\r
-\r
- break;\r
- }\r
-\r
- case FM_GETCHAR:\r
- {\r
- return infoPtr->pActiveCell->ch;\r
- }\r
-\r
- case WM_PAINT:\r
- {\r
- OnPaint(infoPtr,\r
- wParam);\r
- break;\r
- }\r
-\r
- case WM_DESTROY:\r
- {\r
- DeleteObject(infoPtr->hFont);\r
- HeapFree(GetProcessHeap(),\r
- 0,\r
- infoPtr);\r
- SetWindowLongPtr(hwnd,\r
- 0,\r
- (DWORD_PTR)NULL);\r
- break;\r
- }\r
-\r
- default:\r
- {\r
- Ret = DefWindowProc(hwnd,\r
- uMsg,\r
- wParam,\r
- lParam);\r
- break;\r
- }\r
- }\r
-\r
- return Ret;\r
-}\r
-\r
-\r
-BOOL\r
-RegisterMapClasses(HINSTANCE hInstance)\r
-{\r
- WNDCLASS wc = {0};\r
-\r
- wc.style = CS_DBLCLKS;\r
- wc.lpfnWndProc = MapWndProc;\r
- wc.cbWndExtra = sizeof(PMAP);\r
- wc.hInstance = hInstance;\r
- wc.hCursor = LoadCursor(NULL,\r
- (LPTSTR)IDC_ARROW);\r
- wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);\r
- wc.lpszClassName = szMapWndClass;\r
-\r
- if (RegisterClass(&wc))\r
- {\r
- wc.lpfnWndProc = LrgCellWndProc;\r
- wc.cbWndExtra = 0;\r
- wc.lpszClassName = szLrgCellWndClass;\r
-\r
- return RegisterClass(&wc) != 0;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-VOID\r
-UnregisterMapClasses(HINSTANCE hInstance)\r
-{\r
- UnregisterClass(szMapWndClass,\r
- hInstance);\r
-\r
- UnregisterClass(szLrgCellWndClass,\r
- hInstance);\r
-}\r
+/*
+ * PROJECT: ReactOS Character Map
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: base/applications/charmap/map.c
+ * PURPOSE: class implementation for painting glyph region
+ * COPYRIGHT: Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
+ *
+ */
+
+#include <precomp.h>
+
+static const WCHAR szMapWndClass[] = L"FontMapWnd";
+static const WCHAR szLrgCellWndClass[] = L"LrgCellWnd";
+
+static
+VOID
+TagFontToCell(PCELL pCell,
+ WCHAR ch)
+{
+ pCell->ch = ch;
+}
+
+
+static
+VOID
+SetGrid(PMAP infoPtr)
+{
+ INT x, y;
+
+ for (y = 0; y < YCELLS; y++)
+ for (x = 0; x < XCELLS; x++)
+ {
+ infoPtr->Cells[y][x].CellExt.left = x * infoPtr->CellSize.cx + 1;
+ infoPtr->Cells[y][x].CellExt.top = y * infoPtr->CellSize.cy + 1;
+ infoPtr->Cells[y][x].CellExt.right = (x + 1) * infoPtr->CellSize.cx + 2;
+ infoPtr->Cells[y][x].CellExt.bottom = (y + 1) * infoPtr->CellSize.cy + 2;
+
+ CopyRect(&infoPtr->Cells[y][x].CellInt,
+ &infoPtr->Cells[y][x].CellExt);
+
+ InflateRect(&infoPtr->Cells[y][x].CellInt,
+ -1,
+ -1);
+ }
+}
+
+static
+VOID
+DrawActiveCell(PMAP infoPtr,
+ HDC hdc)
+{
+ Rectangle(hdc,
+ infoPtr->pActiveCell->CellInt.left,
+ infoPtr->pActiveCell->CellInt.top,
+ infoPtr->pActiveCell->CellInt.right,
+ infoPtr->pActiveCell->CellInt.bottom);
+
+}
+
+
+static
+VOID
+DrawGrid(PMAP infoPtr,
+ HDC hdc)
+{
+ INT x, y;
+
+ for (y = 0; y < YCELLS; y++)
+ for (x = 0; x < XCELLS; x++)
+ {
+ Rectangle(hdc,
+ infoPtr->Cells[y][x].CellExt.left,
+ infoPtr->Cells[y][x].CellExt.top,
+ infoPtr->Cells[y][x].CellExt.right,
+ infoPtr->Cells[y][x].CellExt.bottom);
+ }
+
+ if (infoPtr->pActiveCell)
+ DrawActiveCell(infoPtr,
+ hdc);
+}
+
+
+static
+VOID
+FillGrid(PMAP infoPtr,
+ HDC hdc)
+{
+ HFONT hOldFont;
+ WCHAR ch;
+ INT x, y;
+
+ hOldFont = SelectObject(hdc,
+ infoPtr->hFont);
+
+ for (y = 0; y < YCELLS; y++)
+ for (x = 0; x < XCELLS; x++)
+ {
+ ch = (WCHAR)((XCELLS * (y + infoPtr->iYStart)) + x);
+
+ TagFontToCell(&infoPtr->Cells[y][x], ch);
+
+ DrawTextW(hdc,
+ &ch,
+ 1,
+ &infoPtr->Cells[y][x].CellInt,
+ DT_CENTER | DT_VCENTER | DT_SINGLELINE);
+ }
+
+ SelectObject(hdc,
+ hOldFont);
+}
+
+
+static
+BOOL
+CreateLargeCell(PMAP infoPtr)
+{
+ RECT rLarge;
+
+ CopyRect(&rLarge,
+ &infoPtr->pActiveCell->CellExt);
+
+ MapWindowPoints(infoPtr->hMapWnd,
+ infoPtr->hParent,
+ (VOID*)&rLarge,
+ 2);
+
+ InflateRect(&rLarge,
+ XLARGE - XCELLS,
+ YLARGE - YCELLS);
+
+ infoPtr->hLrgWnd = CreateWindowExW(0,
+ szLrgCellWndClass,
+ NULL,
+ WS_CHILDWINDOW | WS_VISIBLE,
+ rLarge.left,
+ rLarge.top,
+ rLarge.right - rLarge.left,
+ rLarge.bottom - rLarge.top,
+ infoPtr->hParent,
+ NULL,
+ hInstance,
+ infoPtr);
+ if (!infoPtr->hLrgWnd)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+static
+VOID
+MoveLargeCell(PMAP infoPtr)
+{
+ RECT rLarge;
+
+ CopyRect(&rLarge,
+ &infoPtr->pActiveCell->CellExt);
+
+ MapWindowPoints(infoPtr->hMapWnd,
+ infoPtr->hParent,
+ (VOID*)&rLarge,
+ 2);
+
+ InflateRect(&rLarge,
+ XLARGE - XCELLS,
+ YLARGE - YCELLS);
+
+ MoveWindow(infoPtr->hLrgWnd,
+ rLarge.left,
+ rLarge.top,
+ rLarge.right - rLarge.left,
+ rLarge.bottom - rLarge.top,
+ TRUE);
+
+ InvalidateRect(infoPtr->hLrgWnd,
+ NULL,
+ TRUE);
+}
+
+
+static
+VOID
+SetFont(PMAP infoPtr,
+ LPWSTR lpFontName)
+{
+ HDC hdc;
+
+ if (infoPtr->hFont)
+ DeleteObject(infoPtr->hFont);
+
+ ZeroMemory(&infoPtr->CurrentFont,
+ sizeof(LOGFONTW));
+
+ hdc = GetDC(infoPtr->hMapWnd);
+ infoPtr->CurrentFont.lfHeight = GetDeviceCaps(hdc,
+ LOGPIXELSY) / 5;
+ ReleaseDC(infoPtr->hMapWnd, hdc);
+
+ infoPtr->CurrentFont.lfCharSet = DEFAULT_CHARSET;
+ wcscpy(infoPtr->CurrentFont.lfFaceName,
+ lpFontName);
+
+ infoPtr->hFont = CreateFontIndirectW(&infoPtr->CurrentFont);
+
+ InvalidateRect(infoPtr->hMapWnd,
+ NULL,
+ TRUE);
+}
+
+
+static
+LRESULT
+NotifyParentOfSelection(PMAP infoPtr,
+ UINT code,
+ WCHAR ch)
+{
+ LRESULT Ret = 0;
+
+ if (infoPtr->hParent != NULL)
+ {
+ DWORD dwIdc = GetWindowLongPtr(infoPtr->hMapWnd, GWLP_ID);
+ /*
+ * Push directly into the event queue instead of waiting
+ * the parent to be unlocked.
+ * High word of LPARAM is still available for future needs...
+ */
+ Ret = PostMessage(infoPtr->hParent,
+ WM_COMMAND,
+ MAKELPARAM((WORD)dwIdc, (WORD)code),
+ (LPARAM)LOWORD(ch));
+ }
+
+ return Ret;
+}
+
+
+static
+VOID
+OnClick(PMAP infoPtr,
+ WORD ptx,
+ WORD pty)
+{
+ POINT pt;
+ INT x, y;
+
+ pt.x = ptx;
+ pt.y = pty;
+
+ for (x = 0; x < XCELLS; x++)
+ for (y = 0; y < YCELLS; y++)
+ {
+ if (PtInRect(&infoPtr->Cells[y][x].CellInt,
+ pt))
+ {
+ /* if the cell is not already active */
+ if (!infoPtr->Cells[y][x].bActive)
+ {
+ /* set previous active cell to inactive */
+ if (infoPtr->pActiveCell)
+ {
+ /* invalidate normal cells, required when
+ * moving a small active cell via keyboard */
+ if (!infoPtr->pActiveCell->bLarge)
+ {
+ InvalidateRect(infoPtr->hMapWnd,
+ &infoPtr->pActiveCell->CellInt,
+ TRUE);
+ }
+
+ infoPtr->pActiveCell->bActive = FALSE;
+ infoPtr->pActiveCell->bLarge = FALSE;
+ }
+
+ /* set new cell to active */
+ infoPtr->pActiveCell = &infoPtr->Cells[y][x];
+ infoPtr->pActiveCell->bActive = TRUE;
+ infoPtr->pActiveCell->bLarge = TRUE;
+ if (infoPtr->hLrgWnd)
+ MoveLargeCell(infoPtr);
+ else
+ CreateLargeCell(infoPtr);
+ }
+ else
+ {
+ /* flick between large and small */
+ if (infoPtr->pActiveCell->bLarge)
+ {
+ DestroyWindow(infoPtr->hLrgWnd);
+ infoPtr->hLrgWnd = NULL;
+ }
+ else
+ {
+ CreateLargeCell(infoPtr);
+ }
+
+ infoPtr->pActiveCell->bLarge = (infoPtr->pActiveCell->bLarge) ? FALSE : TRUE;
+ }
+
+ break;
+ }
+ }
+}
+
+
+static
+BOOL
+OnCreate(PMAP infoPtr,
+ HWND hwnd,
+ HWND hParent)
+{
+ RECT rc;
+ BOOL Ret = FALSE;
+
+ infoPtr = HeapAlloc(GetProcessHeap(),
+ 0,
+ sizeof(MAP));
+ if (infoPtr)
+ {
+ SetLastError(0);
+ SetWindowLongPtrW(hwnd,
+ 0,
+ (DWORD_PTR)infoPtr);
+ if (GetLastError() == 0)
+ {
+ ZeroMemory(infoPtr,
+ sizeof(MAP));
+
+ infoPtr->hMapWnd = hwnd;
+ infoPtr->hParent = hParent;
+
+ GetClientRect(hwnd, &rc);
+ infoPtr->ClientSize.cx = rc.right;
+ infoPtr->ClientSize.cy = rc.bottom;
+ infoPtr->CellSize.cx = infoPtr->ClientSize.cx / XCELLS;
+ infoPtr->CellSize.cy = infoPtr->ClientSize.cy / YCELLS;
+
+ infoPtr->pActiveCell = NULL;
+
+ SetGrid(infoPtr);
+
+ SetScrollRange(hwnd, SB_VERT, 0, 255, FALSE);
+ SetScrollPos(hwnd, SB_VERT, 0, TRUE);
+
+ Ret = TRUE;
+ }
+ }
+
+ return Ret;
+}
+
+
+static
+VOID
+OnVScroll(PMAP infoPtr,
+ INT Value,
+ INT Pos)
+{
+ INT iYDiff, iOldYStart = infoPtr->iYStart;
+
+ switch (Value)
+ {
+ case SB_LINEUP:
+ infoPtr->iYStart -= 1;
+ break;
+
+ case SB_LINEDOWN:
+ infoPtr->iYStart += 1;
+ break;
+
+ case SB_PAGEUP:
+ infoPtr->iYStart -= YCELLS;
+ break;
+
+ case SB_PAGEDOWN:
+ infoPtr->iYStart += YCELLS;
+ break;
+
+ case SB_THUMBTRACK:
+ infoPtr->iYStart = Pos;
+ break;
+
+ default:
+ break;
+ }
+
+ infoPtr->iYStart = max(0,
+ min(infoPtr->iYStart, 255*16));
+
+ iYDiff = iOldYStart - infoPtr->iYStart;
+ if (iYDiff)
+ {
+ SetScrollPos(infoPtr->hMapWnd,
+ SB_VERT,
+ infoPtr->iYStart,
+ TRUE);
+
+ if (abs(iYDiff) < YCELLS)
+ {
+ RECT rect;
+ GetClientRect(infoPtr->hMapWnd, &rect);
+ rect.top += 2;
+ rect.bottom -= 2;
+ ScrollWindowEx(infoPtr->hMapWnd,
+ 0,
+ iYDiff * infoPtr->CellSize.cy,
+ &rect,
+ &rect,
+ NULL,
+ NULL,
+ SW_INVALIDATE);
+ }
+ else
+ {
+ InvalidateRect(infoPtr->hMapWnd,
+ NULL,
+ TRUE);
+ }
+ }
+}
+
+
+static
+VOID
+OnPaint(PMAP infoPtr,
+ WPARAM wParam)
+{
+ PAINTSTRUCT ps;
+ HDC hdc;
+
+
+ if (wParam != 0)
+ {
+ if (!GetUpdateRect(infoPtr->hMapWnd,
+ &ps.rcPaint,
+ TRUE))
+ {
+ return;
+ }
+ hdc = (HDC)wParam;
+ }
+ else
+ {
+ hdc = BeginPaint(infoPtr->hMapWnd,
+ &ps);
+ if (hdc == NULL)
+ {
+ return;
+ }
+ }
+
+ DrawGrid(infoPtr,
+ hdc);
+
+ FillGrid(infoPtr,
+ hdc);
+
+ if (wParam == 0)
+ {
+ EndPaint(infoPtr->hMapWnd,
+ &ps);
+ }
+}
+
+
+LRESULT
+CALLBACK
+MapWndProc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ PMAP infoPtr;
+ LRESULT Ret = 0;
+
+ infoPtr = (PMAP)GetWindowLongPtrW(hwnd,
+ 0);
+
+ switch (uMsg)
+ {
+ case WM_CREATE:
+ {
+ if (!OnCreate(infoPtr,
+ hwnd,
+ ((LPCREATESTRUCTW)lParam)->hwndParent))
+ {
+ return (LRESULT)-1;
+ }
+
+ break;
+ }
+
+ case WM_LBUTTONDOWN:
+ {
+ OnClick(infoPtr,
+ LOWORD(lParam),
+ HIWORD(lParam));
+
+ break;
+ }
+
+ case WM_LBUTTONDBLCLK:
+ {
+ NotifyParentOfSelection(infoPtr,
+ FM_SETCHAR,
+ infoPtr->pActiveCell->ch);
+
+
+ break;
+ }
+
+ case WM_VSCROLL:
+ {
+ OnVScroll(infoPtr,
+ LOWORD(wParam),
+ HIWORD(wParam));
+
+ break;
+ }
+
+ case FM_SETFONT:
+ SetFont(infoPtr, (LPWSTR)lParam);
+ break;
+
+ case FM_GETCHAR:
+ {
+ if (!infoPtr->pActiveCell) return 0;
+ return infoPtr->pActiveCell->ch;
+ }
+
+ case FM_GETHFONT:
+ return (LRESULT)infoPtr->hFont;
+
+ case WM_PAINT:
+ {
+ OnPaint(infoPtr,
+ wParam);
+ break;
+ }
+
+ case WM_DESTROY:
+ {
+ DeleteObject(infoPtr->hFont);
+ HeapFree(GetProcessHeap(),
+ 0,
+ infoPtr);
+ SetWindowLongPtrW(hwnd,
+ 0,
+ (DWORD_PTR)NULL);
+ break;
+ }
+
+ default:
+ {
+ Ret = DefWindowProcW(hwnd,
+ uMsg,
+ wParam,
+ lParam);
+ break;
+ }
+ }
+
+ return Ret;
+}
+
+
+BOOL
+RegisterMapClasses(HINSTANCE hInstance)
+{
+ WNDCLASSW wc = {0};
+
+ wc.style = CS_DBLCLKS;
+ wc.lpfnWndProc = MapWndProc;
+ wc.cbWndExtra = sizeof(PMAP);
+ wc.hInstance = hInstance;
+ wc.hCursor = LoadCursorW(NULL,
+ (LPWSTR)IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+ wc.lpszClassName = szMapWndClass;
+
+ if (RegisterClassW(&wc))
+ {
+ wc.lpfnWndProc = LrgCellWndProc;
+ wc.cbWndExtra = 0;
+ wc.lpszClassName = szLrgCellWndClass;
+
+ return RegisterClassW(&wc) != 0;
+ }
+
+ return FALSE;
+}
+
+VOID
+UnregisterMapClasses(HINSTANCE hInstance)
+{
+ UnregisterClassW(szMapWndClass,
+ hInstance);
+
+ UnregisterClassW(szLrgCellWndClass,
+ hInstance);
+}