diff --git a/cpp.hint b/cpp.hint
new file mode 100644
index 0000000..bf3e441
--- /dev/null
+++ b/cpp.hint
@@ -0,0 +1,4 @@
+// Hint files help the Visual Studio IDE interpret Visual C++ identifiers
+// such as names of functions and macros.
+// For more information see https://go.microsoft.com/fwlink/?linkid=865984
+#define DECLARE_$NEW(T, __VA_ARGS__) T* T##_$new(E) { void* pObject = malloc(sizeof(T)); if (pObject) { memset(pObject, 0, sizeof(T)); T##_$init((T*)pObject, __VA_ARGS__); } return (T*)pObject; }
diff --git a/panitent.sln b/panitent.sln
index 64768e5..f083482 100644
--- a/panitent.sln
+++ b/panitent.sln
@@ -15,42 +15,78 @@ Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
+ MinSizeRel|x64 = MinSizeRel|x64
+ MinSizeRel|x86 = MinSizeRel|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
+ RelWithDebInfo|x64 = RelWithDebInfo|x64
+ RelWithDebInfo|x86 = RelWithDebInfo|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F95C4EF5-0539-455C-B247-96029C28E36D}.Debug|x64.ActiveCfg = Debug|x64
{F95C4EF5-0539-455C-B247-96029C28E36D}.Debug|x64.Build.0 = Debug|x64
{F95C4EF5-0539-455C-B247-96029C28E36D}.Debug|x86.ActiveCfg = Debug|Win32
{F95C4EF5-0539-455C-B247-96029C28E36D}.Debug|x86.Build.0 = Debug|Win32
+ {F95C4EF5-0539-455C-B247-96029C28E36D}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {F95C4EF5-0539-455C-B247-96029C28E36D}.MinSizeRel|x64.Build.0 = Release|x64
+ {F95C4EF5-0539-455C-B247-96029C28E36D}.MinSizeRel|x86.ActiveCfg = Release|Win32
+ {F95C4EF5-0539-455C-B247-96029C28E36D}.MinSizeRel|x86.Build.0 = Release|Win32
{F95C4EF5-0539-455C-B247-96029C28E36D}.Release|x64.ActiveCfg = Release|x64
{F95C4EF5-0539-455C-B247-96029C28E36D}.Release|x64.Build.0 = Release|x64
{F95C4EF5-0539-455C-B247-96029C28E36D}.Release|x86.ActiveCfg = Release|Win32
{F95C4EF5-0539-455C-B247-96029C28E36D}.Release|x86.Build.0 = Release|Win32
+ {F95C4EF5-0539-455C-B247-96029C28E36D}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {F95C4EF5-0539-455C-B247-96029C28E36D}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {F95C4EF5-0539-455C-B247-96029C28E36D}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
+ {F95C4EF5-0539-455C-B247-96029C28E36D}.RelWithDebInfo|x86.Build.0 = Release|Win32
{290557A9-3D88-4047-AE9C-F84118A13ADE}.Debug|x64.ActiveCfg = Debug|x64
{290557A9-3D88-4047-AE9C-F84118A13ADE}.Debug|x64.Build.0 = Debug|x64
{290557A9-3D88-4047-AE9C-F84118A13ADE}.Debug|x86.ActiveCfg = Debug|Win32
{290557A9-3D88-4047-AE9C-F84118A13ADE}.Debug|x86.Build.0 = Debug|Win32
+ {290557A9-3D88-4047-AE9C-F84118A13ADE}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {290557A9-3D88-4047-AE9C-F84118A13ADE}.MinSizeRel|x64.Build.0 = Release|x64
+ {290557A9-3D88-4047-AE9C-F84118A13ADE}.MinSizeRel|x86.ActiveCfg = Release|Win32
+ {290557A9-3D88-4047-AE9C-F84118A13ADE}.MinSizeRel|x86.Build.0 = Release|Win32
{290557A9-3D88-4047-AE9C-F84118A13ADE}.Release|x64.ActiveCfg = Release|x64
{290557A9-3D88-4047-AE9C-F84118A13ADE}.Release|x64.Build.0 = Release|x64
{290557A9-3D88-4047-AE9C-F84118A13ADE}.Release|x86.ActiveCfg = Release|Win32
{290557A9-3D88-4047-AE9C-F84118A13ADE}.Release|x86.Build.0 = Release|Win32
+ {290557A9-3D88-4047-AE9C-F84118A13ADE}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {290557A9-3D88-4047-AE9C-F84118A13ADE}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {290557A9-3D88-4047-AE9C-F84118A13ADE}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
+ {290557A9-3D88-4047-AE9C-F84118A13ADE}.RelWithDebInfo|x86.Build.0 = Release|Win32
{DC50FB1F-44E3-478C-9CE3-C82F809309AD}.Debug|x64.ActiveCfg = Debug|x64
{DC50FB1F-44E3-478C-9CE3-C82F809309AD}.Debug|x64.Build.0 = Debug|x64
{DC50FB1F-44E3-478C-9CE3-C82F809309AD}.Debug|x86.ActiveCfg = Debug|Win32
{DC50FB1F-44E3-478C-9CE3-C82F809309AD}.Debug|x86.Build.0 = Debug|Win32
+ {DC50FB1F-44E3-478C-9CE3-C82F809309AD}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {DC50FB1F-44E3-478C-9CE3-C82F809309AD}.MinSizeRel|x64.Build.0 = Release|x64
+ {DC50FB1F-44E3-478C-9CE3-C82F809309AD}.MinSizeRel|x86.ActiveCfg = Release|Win32
+ {DC50FB1F-44E3-478C-9CE3-C82F809309AD}.MinSizeRel|x86.Build.0 = Release|Win32
{DC50FB1F-44E3-478C-9CE3-C82F809309AD}.Release|x64.ActiveCfg = Release|x64
{DC50FB1F-44E3-478C-9CE3-C82F809309AD}.Release|x64.Build.0 = Release|x64
{DC50FB1F-44E3-478C-9CE3-C82F809309AD}.Release|x86.ActiveCfg = Release|Win32
{DC50FB1F-44E3-478C-9CE3-C82F809309AD}.Release|x86.Build.0 = Release|Win32
+ {DC50FB1F-44E3-478C-9CE3-C82F809309AD}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {DC50FB1F-44E3-478C-9CE3-C82F809309AD}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {DC50FB1F-44E3-478C-9CE3-C82F809309AD}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
+ {DC50FB1F-44E3-478C-9CE3-C82F809309AD}.RelWithDebInfo|x86.Build.0 = Release|Win32
{5427E0AA-9701-4AD6-B223-7404B614BA04}.Debug|x64.ActiveCfg = Debug|x64
{5427E0AA-9701-4AD6-B223-7404B614BA04}.Debug|x64.Build.0 = Debug|x64
{5427E0AA-9701-4AD6-B223-7404B614BA04}.Debug|x86.ActiveCfg = Debug|Win32
{5427E0AA-9701-4AD6-B223-7404B614BA04}.Debug|x86.Build.0 = Debug|Win32
+ {5427E0AA-9701-4AD6-B223-7404B614BA04}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {5427E0AA-9701-4AD6-B223-7404B614BA04}.MinSizeRel|x64.Build.0 = Release|x64
+ {5427E0AA-9701-4AD6-B223-7404B614BA04}.MinSizeRel|x86.ActiveCfg = Release|Win32
+ {5427E0AA-9701-4AD6-B223-7404B614BA04}.MinSizeRel|x86.Build.0 = Release|Win32
{5427E0AA-9701-4AD6-B223-7404B614BA04}.Release|x64.ActiveCfg = Release|x64
{5427E0AA-9701-4AD6-B223-7404B614BA04}.Release|x64.Build.0 = Release|x64
{5427E0AA-9701-4AD6-B223-7404B614BA04}.Release|x86.ActiveCfg = Release|Win32
{5427E0AA-9701-4AD6-B223-7404B614BA04}.Release|x86.Build.0 = Release|Win32
+ {5427E0AA-9701-4AD6-B223-7404B614BA04}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {5427E0AA-9701-4AD6-B223-7404B614BA04}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {5427E0AA-9701-4AD6-B223-7404B614BA04}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
+ {5427E0AA-9701-4AD6-B223-7404B614BA04}.RelWithDebInfo|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/panitent.vcxproj b/panitent.vcxproj
index 76ff314..39e6d0f 100644
--- a/panitent.vcxproj
+++ b/panitent.vcxproj
@@ -1,4 +1,4 @@
-
+
@@ -20,6 +20,7 @@
+
@@ -46,6 +47,8 @@
+
+
@@ -72,6 +75,10 @@
+
+
+
+
@@ -116,6 +123,7 @@
+
@@ -142,7 +150,11 @@
+
+
+
+
@@ -173,7 +185,13 @@
+
+
+
+
+
+
@@ -188,6 +206,8 @@
+
+
@@ -213,7 +233,11 @@
+
+
+
+
diff --git a/panitent.vcxproj.user b/panitent.vcxproj.user
index 966b4ff..3b6182a 100644
--- a/panitent.vcxproj.user
+++ b/panitent.vcxproj.user
@@ -3,4 +3,20 @@
true
+
+ --enable-experimental-dock
+ WindowsLocalDebugger
+
+
+ --enable-experimental-dock
+ WindowsLocalDebugger
+
+
+ --enable-experimental-dock
+ WindowsLocalDebugger
+
+
+ --enable-experimental-dock
+ WindowsLocalDebugger
+
\ No newline at end of file
diff --git a/panitent_test.vcxproj b/panitent_test.vcxproj
index 4d82686..52a17e0 100644
--- a/panitent_test.vcxproj
+++ b/panitent_test.vcxproj
@@ -47,6 +47,9 @@
{f95c4ef5-0539-455c-b247-96029c28e36d}
+
+
+
16.0
Win32Proj
diff --git a/panitent_test/test_window.c b/panitent_test/test_window.c
index 57991b5..9a0bf14 100644
--- a/panitent_test/test_window.c
+++ b/panitent_test/test_window.c
@@ -3,11 +3,13 @@
#include "test_application.h"
#include "../src/palette_window.h"
+#include "../src/util/tentobj.h"
static const WCHAR szClassName[] = L"TestWindowClass";
-TestWindow* TestWindow_Create(struct Application* app);
-void TestWindow_Init(TestWindow*, Application*);
+/* Forward declarations */
+DECLARE_$NEW(TestWindow)
+void TestWindow_$init(TestWindow*, Application*);
void TestWindow_PreRegister(LPWNDCLASSEX);
void TestWindow_PreCreate(LPCREATESTRUCT);
@@ -17,7 +19,7 @@ void TestWindow_OnSize(TestWindow*, UINT, int, int);
void TestWindow_OnPaint(TestWindow*);
LRESULT CALLBACK TestWindow_UserProc(struct Window*, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
-TestWindow* TestWindow_Create(struct Application* app)
+TestWindow* TestWindow_$new()
{
TestWindow* pTestWindow = (TestWindow*)malloc(sizeof(TestWindow));
if (pTestWindow)
@@ -29,7 +31,7 @@ TestWindow* TestWindow_Create(struct Application* app)
return pTestWindow;
}
-void TestWindow_Init(TestWindow* window, struct Application* app)
+void TestWindow_$init(TestWindow* window)
{
Window_Init(&window->base, app);
@@ -41,7 +43,7 @@ void TestWindow_Init(TestWindow* window, struct Application* app)
window->base.OnPaint = TestWindow_OnPaint;
window->base.UserProc = TestWindow_UserProc;
- window->paletteWindow = PaletteWindow_Create(window->base.app, ((struct TestApplication*)app)->palette);
+ window->paletteWindow = PaletteWindow_Create(((struct TestApplication*)app)->palette);
}
LRESULT CALLBACK TestWindow_UserProc(struct Window* window, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
diff --git a/panitent_test/test_window.h b/panitent_test/test_window.h
index 497d9c3..6bfa0e8 100644
--- a/panitent_test/test_window.h
+++ b/panitent_test/test_window.h
@@ -11,6 +11,6 @@ struct TestWindow {
PaletteWindow* paletteWindow;
};
-TestWindow* TestWindow_Create(Application*);
+TestWindow* TestWindow_$new(Application*);
#endif /* _TEST_WINDOW_H_INLUCDED */
diff --git a/res/panitent.rc b/res/panitent.rc
index baf077e..c11e1b3 100644
--- a/res/panitent.rc
+++ b/res/panitent.rc
@@ -249,6 +249,53 @@ END
+//
+// Menu resources
+//
+IDC_MAINMENU MENU
+ BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&New\tCtrl+N", IDM_FILE_NEW
+ MENUITEM "&Open\tCtrl+O", IDM_FILE_OPEN
+ MENUITEM "&Save\tCtrl+S", IDM_FILE_SAVE
+ MENUITEM "Export image to clipboard", IDM_FILE_CLIPBOARD_EXPORT
+ MENUITEM "BinView", IDM_FILE_BINVIEW
+ MENUITEM "&Close", IDM_FILE_CLOSE
+ END
+ POPUP "&Edit"
+ BEGIN
+ MENUITEM "&Undo", IDM_EDIT_UNDO
+ MENUITEM "&Redo", IDM_EDIT_REDO
+ MENUITEM "&Clear canvas", IDM_EDIT_CLRCANVAS
+ END
+ POPUP "&Scripting"
+ BEGIN
+ MENUITEM "Run last script", IDM_FILE_RUN_SCRIPT
+ MENUITEM "Run script...", IDM_FILE_RUN_SCRIPT
+ END
+ POPUP "&Window"
+ BEGIN
+ MENUITEM "&Tools", IDM_WINDOW_TOOLS
+ MENUITEM "&Activity...", IDM_WINDOW_ACTIVITY_DIALOG
+ MENUITEM "&Property Grid...", IDM_WINDOW_PROPERTY_GRID
+ END
+ POPUP "&Settings"
+ BEGIN
+ MENUITEM "&Options", IDM_OPTIONS_SETTINGS
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "Help &Topics", IDM_HELP_TOPICS
+ MENUITEM "&Log", IDM_HELP_LOG
+ MENUITEM "&RBTreeViz", IDM_HELP_RBTREEVIZ
+ MENUITEM "&About", IDM_HELP_ABOUT
+ MENUITEM "&Display pixel buffer", IDM_HELP_DISPLAYPIXELBUFFER
+ END
+END
+
+
+
//
// Cursor resources
//
diff --git a/src/appcmd.c b/src/appcmd.c
new file mode 100644
index 0000000..24b4d27
--- /dev/null
+++ b/src/appcmd.c
@@ -0,0 +1,44 @@
+#include "precomp.h"
+
+#include "appcmd.h"
+#include "util/assert.h"
+#include "panitentapp.h"
+
+int AppCmd_KeyCompare(void* pKey1, void* pKey2) {
+ if ((UINT)pKey1 == (UINT)pKey2) {
+ return 0;
+ }
+ else if ((UINT)pKey1 > (UINT)pKey2) {
+ return 1;
+ }
+
+ return -1;
+}
+
+void AppCmd_Init(AppCmd* pAppCmd) {
+ ASSERT(pAppCmd);
+ memset(pAppCmd, 0, sizeof(AppCmd));
+
+ HashMap* pHashMap = HashMap_Create(16, &AppCmd_KeyCompare);
+ ASSERT(pHashMap);
+ pAppCmd->pCmdMap = pHashMap;
+}
+
+void AppCmd_AddCommand(AppCmd* pAppCmd, UINT cmdId, PFNAppCmdCallback* pfnCallback) {
+ ASSERT(pAppCmd);
+ ASSERT(pfnCallback);
+ HashMap_Put(pAppCmd->pCmdMap, (void*)cmdId, (void*)pfnCallback);
+}
+
+void AppCmd_Execute(AppCmd* pAppCmd, UINT cmdId, PanitentApp* pPanitentApp) {
+ ASSERT(pAppCmd);
+ PFNAppCmdCallback *pfnCallback = (PFNAppCmdCallback*)HashMap_Get(pAppCmd->pCmdMap, (void*)cmdId);
+ ASSERT(pfnCallback);
+ pfnCallback(pPanitentApp);
+}
+
+void AppCmd_Destroy(AppCmd* pAppCmd) {
+ ASSERT(pAppCmd);
+ HashMap_Destroy(pAppCmd->pCmdMap);
+ pAppCmd->pCmdMap = NULL;
+}
diff --git a/src/appcmd.h b/src/appcmd.h
new file mode 100644
index 0000000..ec2392a
--- /dev/null
+++ b/src/appcmd.h
@@ -0,0 +1,21 @@
+#ifndef PANITENT_APPCMD_H
+#define PANITENT_APPCMD_H
+
+#include "util/hashmap.h"
+
+typedef struct PanitentApp PanitentApp;
+
+typedef void (PFNAppCmdCallback)(PanitentApp*);
+
+typedef struct AppCmd AppCmd;
+typedef struct AppCmd {
+ HashMap* pCmdMap;
+};
+
+/* Public Interface */
+void AppCmd_Init(AppCmd* pAppCmd);
+void AppCmd_AddCommand(AppCmd* pAppCmd, UINT cmdId, PFNAppCmdCallback* pfnCallback);
+void AppCmd_Execute(AppCmd* pAppCmd, UINT cmdId, PanitentApp* pPanitentApp);
+void AppCmd_Destroy(AppCmd* pAppCmd);
+
+#endif /* PANITENT_APPCMD_H */
diff --git a/src/canvas.c b/src/canvas.c
index de0aa7f..0c99eff 100644
--- a/src/canvas.c
+++ b/src/canvas.c
@@ -27,33 +27,30 @@ uint32_t color_opacity(uint32_t color, float opacity)
uint32_t mix(uint32_t base, uint32_t overlay)
{
- float baseA = (base >> 24 & 0xFF) / 255.f;
- float baseR = (base >> 16 & 0xFF) / 255.f;
- float baseG = (base >> 8 & 0xFF) / 255.f;
- float baseB = (base & 0xFF) / 255.f;
-
- float overlayA = (overlay >> 24 & 0xFF) / 255.f;
- float overlayR = (overlay >> 16 & 0xFF) / 255.f;
- float overlayG = (overlay >> 8 & 0xFF) / 255.f;
- float overlayB = (overlay & 0xFF) / 255.f;
-
- /*
- float blendR = baseR * overlayA + overlayR * (1.f - overlayA);
- float blendG = baseG * overlayA + overlayG * (1.f - overlayA);
- float blendB = baseB * overlayA + overlayB * (1.f - overlayA);
- */
-
- float resultR = (1.f - overlayA) * baseR + overlayA * overlayR;
- float resultG = (1.f - overlayA) * baseG + overlayA * overlayG;
- float resultB = (1.f - overlayA) * baseB + overlayA * overlayB;
- float resultA = 1.f - (1.f - baseA) * (1.f - overlayA);
-
- uint8_t a = (uint8_t)roundf(resultA * 255.f);
- uint8_t r = (uint8_t)roundf(resultR * 255.f);
- uint8_t g = (uint8_t)roundf(resultG * 255.f);
- uint8_t b = (uint8_t)roundf(resultB * 255.f);
-
- return ARGB(a, r, g, b);
+ /* extract base color components */
+ uint8_t baseA = (base >> 24) & 0xFF;
+ uint8_t baseR = (base >> 16) & 0xFF;
+ uint8_t baseG = (base >> 8) & 0xFF;
+ uint8_t baseB = base & 0xFF;
+
+ /* Extract overlay color components */
+ uint8_t overlayA = (overlay >> 24) & 0xFF;
+ uint8_t overlayR = (overlay >> 16) & 0xFF;
+ uint8_t overlayG = (overlay >> 8) & 0xFF;
+ uint8_t overlayB = overlay & 0xFF;
+
+ /* Precompute scaled alpha for base and overlay */
+ uint16_t invOverlayA = 255 - overlayA;
+
+ /* Blend the RGB channels directly using integer math */
+ uint8_t resultR = (uint8_t)((baseR * invOverlayA + overlayR * overlayA) / 255);
+ uint8_t resultG = (uint8_t)((baseG * invOverlayA + overlayG * overlayA) / 255);
+ uint8_t resultB = (uint8_t)((baseB * invOverlayA + overlayB * overlayA) / 255);
+
+ /* Blend alpha channel (premultiply the inverse alpha blend) */
+ uint8_t resultA = (uint8_t)(255 - ((255 - baseA) * invOverlayA / 255));
+
+ return (resultA << 24) | (resultR << 16) | (resultG << 8) | resultB;
}
void* Canvas_BufferAlloc(Canvas* canvas)
diff --git a/src/dockhost.c b/src/dockhost.c
index 45ea03a..0fcc97d 100644
--- a/src/dockhost.c
+++ b/src/dockhost.c
@@ -588,9 +588,7 @@ void DockHostWindow_UndockToFloating(DockHostWindow* pDockHostWindow, TreeNode*
FloatingWindowContainer* pFloatingWindowContainer = FloatingWindowContainer_Create();
Window_CreateWindow((Window*)pFloatingWindowContainer, NULL);
FloatingWindowContainer_PinWindow(pFloatingWindowContainer, ((DockData*)pNode->data)->hWnd);
-
- DockHostWindow_Rearrange(pDockHostWindow, pNode);
-
+ DockHostWindow_Rearrange(pDockHostWindow);
DestroyWindow(g_hWndDragOverlay);
}
@@ -820,6 +818,174 @@ void DockHostWindow_StartDrag(DockHostWindow* pDockHostWindow, int x, int y)
ReleaseDC(NULL, hdcScreen);
}
+void DockHostWindow_StartDrag(DockHostWindow* pDockHostWindow, int x, int y)
+{
+ WNDCLASSEX wcex = { 0 };
+ if (!GetClassInfoEx(GetModuleHandle(NULL), L"__DragOverlayClass", &wcex))
+ {
+ wcex.cbSize = sizeof(wcex);
+ wcex.lpfnWndProc = (WNDPROC)DragOverlayWndProc;
+ wcex.hInstance = GetModuleHandle(NULL);
+ wcex.lpszClassName = L"__DragOverlayClass";
+ RegisterClassEx(&wcex);
+ }
+
+ HWND g_hWndDragOverlay = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST, L"__DragOverlayClass", L"DragOverlay", WS_VISIBLE | WS_POPUP, x - 64, y - 64, 128, 128, NULL, NULL, GetModuleHandle(NULL), NULL);
+
+ HDC hdcScreen = GetDC(NULL);
+ HDC hdcMem = CreateCompatibleDC(hdcScreen);
+
+ BLENDFUNCTION blendFunction = { 0 };
+ blendFunction.BlendOp = AC_SRC_OVER;
+ blendFunction.SourceConstantAlpha = 255;
+ blendFunction.AlphaFormat = AC_SRC_ALPHA;
+
+ BITMAPINFO bmi = { 0 };
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.bmiHeader.biWidth = 128;
+ bmi.bmiHeader.biHeight = -128;
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 32;
+ bmi.bmiHeader.biCompression = BI_RGB;
+
+ unsigned int* pBits;
+
+ // Create a compatible bitmap with the desired format
+ HBITMAP hBitmap = CreateDIBSection(hdcScreen, &bmi, DIB_RGB_COLORS, (void**)&pBits, NULL, 0);
+ HGDIOBJ hOldObj = SelectObject(hdcMem, hBitmap);
+
+ // Draw
+ {
+ int centerX = 32;
+ int centerY = 32;
+ int radius = 32;
+
+ unsigned char* pCircle = malloc(64 * 64 * sizeof(unsigned char));
+
+ for (int y = 0; y < 64; ++y)
+ {
+ for (int x = 0; x < 64; ++x)
+ {
+ int dx = x - centerX;
+ int dy = y - centerY;
+ float distance = sqrtf((float)(dx * dx + dy * dy));
+
+ float dist = distance / (float)radius;
+
+ // Calculate alpha based on the distance
+
+ float uStripeWidth = 0.1f;
+ float stripeEdge = 0.5 * (1.0 / uStripeWidth);
+ BYTE alpha1 = (BYTE)(255.0f * smoothstepf(1.0f, 0.95f, dist));
+ BYTE alpha2 = (BYTE)(255.0f * (sinf(dist * 24.0f) * 0.5f + 0.5f));
+ BYTE alpha = min(alpha1, alpha2);
+ if (alpha > 255)
+ {
+ alpha = 255;
+ }
+ if (alpha < 0)
+ {
+ alpha = 0;
+ }
+
+ pCircle[y * 64 + x] = alpha;
+ }
+ }
+
+ unsigned int* pData = pBits;
+ pData += 128 * ((128 - 64) / 2) + ((128 - 64) / 2);
+ for (int y = 0; y < 64; ++y)
+ {
+ for (int x = 0; x < 64; ++x)
+ {
+ BYTE alpha = pCircle[y * 64 + x];
+ unsigned int color = (alpha << 24) | (alpha << 16);
+ *pData = color;
+ pData++;
+ }
+
+ pData += 64;
+ }
+
+ free(pCircle);
+
+ /*
+ for (int y = 0; y < 128; ++y)
+ {
+ for (int x = 0; x < 128; ++x)
+ {
+ unsigned int color = pBits[y * 128 + x];
+
+ // Extract RGBA components
+ BYTE alpha = (color >> 24) & 0xFF;
+ BYTE red = (color >> 16) & 0xFF;
+ BYTE green = (color >> 8) & 0xFF;
+ BYTE blue = (color) & 0xFF;
+
+ // Premultiply RGB values by alpha
+ BYTE premultRed = (BYTE)((red * alpha) / 255);
+ BYTE premultGreen = (BYTE)((green * alpha) / 255);
+ BYTE premultBlue = (BYTE)((blue * alpha) / 255);
+
+ // Store the premultiplied color back into the bitmap
+ pBits[y * 128 + x] = (premultRed << 16) | (premultGreen << 8) | premultBlue | (alpha << 24);
+ }
+ }
+ */
+
+ /*
+ for (int y = 0; y < 128; ++y)
+ {
+ pBits[y * 128] = 0xFFFF0000;
+ pBits[y * 128 + 127] = 0xFFFF0000;
+ pBits[y] = 0xFFFF0000;
+ pBits[y + 127 * 128] = 0xFFFF0000;
+ }
+ */
+
+ /*
+ for (int y = 0; y < 128; ++y)
+ {
+ for (int x = 0; x < 128; ++x)
+ {
+ int dx = x - centerX;
+ int dy = y - centerY;
+ float distance = sqrtf((float)(dx * dx + dy * dy));
+
+ // Calculate alpha based on the distance
+ BYTE alpha = (BYTE)(255 * (1.0f - (distance / radius)));
+ if (alpha > 255)
+ {
+ alpha = 255;
+ }
+ if (alpha < 0 || distance > radius)
+ {
+ alpha = 0;
+ }
+
+ // Set the pixel color (white with varying alpha)
+ DWORD color = (alpha << 24) | (alpha << 16) | (alpha << 8) | alpha;
+ pBits[y * 128 + x] = color;
+ }
+ }
+ */
+ }
+
+ POINT ptPos = { x, y };
+ SIZE sizeWnd = { 128, 128 };
+ POINT ptSrc = { 0, 0 };
+
+ ClientToScreen(pDockHostWindow->base.hWnd, &ptPos);
+ ptPos.x -= 64;
+ ptPos.y -= 64;
+
+ UpdateLayeredWindow(g_hWndDragOverlay, hdcScreen, &ptPos, &sizeWnd, hdcMem, &ptSrc, RGB(0, 0, 0), &blendFunction, ULW_ALPHA);
+
+ SelectObject(hdcMem, hOldObj);
+ DeleteDC(hdcMem);
+ ReleaseDC(NULL, hdcScreen);
+}
+
void DockHostWindow_OnLButtonDown(DockHostWindow* pDockHostWindow, BOOL fDoubleClick, int x, int y, UINT keyFlags)
{
UNREFERENCED_PARAMETER(fDoubleClick);
@@ -996,7 +1162,7 @@ void DockHostWindow_PreCreate(LPCREATESTRUCT lpcs)
void DockHostWindow_Init(DockHostWindow* pDockHostWindow, PanitentApp* pPanitentApp)
{
- Window_Init(&pDockHostWindow->base, pPanitentApp);
+ Window_Init(&pDockHostWindow->base);
pDockHostWindow->base.szClassName = szClassName;
diff --git a/src/experimental/dockwindow.c b/src/experimental/dockwindow.c
index 0780770..611f43c 100644
--- a/src/experimental/dockwindow.c
+++ b/src/experimental/dockwindow.c
@@ -42,7 +42,7 @@ void DockHostWindow2_Init(DockHostWindow2* pDockHostWindow2, Application* pAppli
{
memset(pDockHostWindow2, 0, sizeof(DockHostWindow2));
- Window_Init(&pDockHostWindow2->base, pApplication);
+ Window_Init(&pDockHostWindow2->base);
_WindowInitHelper_SetPreCreateRoutine(pDockHostWindow2, (FnWindowPreCreate)DockHostWindow2_PreCreate);
_WindowInitHelper_SetPreRegisterRoutine(pDockHostWindow2, (FnWindowPreRegister)DockHostWindow2_PreRegister);
diff --git a/src/floatingwindowcontainer.c b/src/floatingwindowcontainer.c
index 08fc0f2..8c11932 100644
--- a/src/floatingwindowcontainer.c
+++ b/src/floatingwindowcontainer.c
@@ -272,7 +272,7 @@ FloatingWindowContainer* FloatingWindowContainer_Create(struct Application* app)
void FloatingWindowContainer_Init(FloatingWindowContainer* window, struct Application* app)
{
- Window_Init(&window->base, app);
+ Window_Init(&window->base);
window->base.szClassName = szClassName;
diff --git a/src/grimstroke/basic_plotter.h b/src/grimstroke/basic_plotter.h
new file mode 100644
index 0000000..3b8e2d0
--- /dev/null
+++ b/src/grimstroke/basic_plotter.h
@@ -0,0 +1,35 @@
+#ifndef PANITENT_GRIMSTROKE_BASICPLOTTER_H
+#define PANITENT_GRIMSTROKE_BASICPLOTTER_H
+
+typedef struct BasicPlotter BasicPlotter;
+
+struct BasicPlotter_vtbl {
+ void (*DrawPixel)(BasicPlotter* plotterContext, float xPos, float yPos);
+};
+
+struct BasicPlotter {
+ struct BasicPlotter_vtbl* pVtbl;
+};
+
+void __impl_BasicPlotter_DrawPixel(BasicPlotter* plotterContext, float xPos, float yPos);
+
+struct BasicPlotter_vtbl __g_BasicPlotter_vtbl = {
+ .DrawPixel = __impl_BasicPlotter_DrawPixel
+};
+
+void BasicPlotter_Init(BasicPlotter* plotterContext)
+{
+ plotterContext->pVtbl = &__g_BasicPlotter_vtbl;
+}
+
+inline BasicPlotter_DrawPixel(BasicPlotter* plotterContext, float xPos, float yPos)
+{
+ plotterContext->pVtbl->DrawPixel(plotterContext, xPos, yPos);
+}
+
+void __impl_BasicPlotter_DrawPixel(BasicPlotter* plotterContext, float xPos, float yPos)
+{
+
+}
+
+#endif // PANITENT_GRIMSTROKE_BASICPLOTTER
diff --git a/src/grimstroke/msaa.c b/src/grimstroke/msaa.c
new file mode 100644
index 0000000..06fb92f
--- /dev/null
+++ b/src/grimstroke/msaa.c
@@ -0,0 +1,27 @@
+#include "../precomp.h"
+
+#include "msaa.h"
+
+void GrimstrokeMSAA_CreateSampler(GrimstrokeMSAA* msaaCtx)
+{
+ memset(msaaCtx, 0, sizeof(msaaCtx));
+
+ msaaCtx->wSamples = 4;
+ msaaCtx->hSamples = 4;
+}
+
+void GrimstrokeMSAA_AllocateBitMask(GrimstrokeMSAA* msaaCtx)
+{
+ size_t nCells = msaaCtx->wSamples * msaaCtx->hSamples;
+ size_t nBytes = nCells / sizeof(unsigned long long) * 8 + 1;
+ msaaCtx->bitMask = (char*)malloc(nBytes * sizeof(unsigned long long));
+ msaaCtx->bitMask[0] = 1ULL;
+}
+
+void GrimstrokeMSAA_FromMSAACords(GrimstrokeMSAA* msaaCtx, TENTPosf pos)
+{
+}
+
+void GrimstrokeMSAA_ToMSAACords(GrimstrokeMSAA* msaaCtx, int x, int y)
+{
+}
diff --git a/src/grimstroke/msaa.h b/src/grimstroke/msaa.h
new file mode 100644
index 0000000..8efaeae
--- /dev/null
+++ b/src/grimstroke/msaa.h
@@ -0,0 +1,13 @@
+#ifndef PANITENT_GRIMSTROKE_MSAA_H
+#define PANITENT_GRIMSTROKE_MSAA_H
+
+#include "../util/tenttypes.h"
+
+typedef struct GrimstrokeMSAA GrimstrokeMSAA;
+struct GrimstrokeMSAA {
+ unsigned int wSamples;
+ unsigned int hSamples;
+ unsigned long long* bitMask;
+};
+
+#endif /* PANITENT_GRIMSTROKE_MSAA_H */
diff --git a/src/grimstroke/msaaplotterproxy.c b/src/grimstroke/msaaplotterproxy.c
new file mode 100644
index 0000000..e69de29
diff --git a/src/grimstroke/msaaplotterproxy.h b/src/grimstroke/msaaplotterproxy.h
new file mode 100644
index 0000000..9d68569
--- /dev/null
+++ b/src/grimstroke/msaaplotterproxy.h
@@ -0,0 +1,6 @@
+#pragma once
+
+typedef struct GrimstrokeMSAAPlotterProxy GrimstrokeMSAAPlotterProxy;
+
+struct __g_GrimpstrokeMSAAPlotterProxy_vtbl {
+};
\ No newline at end of file
diff --git a/src/grimstroke/path.h b/src/grimstroke/path.h
new file mode 100644
index 0000000..8f8c300
--- /dev/null
+++ b/src/grimstroke/path.h
@@ -0,0 +1,111 @@
+#ifndef PANITENT_GRIMSTROKE_PATH_H
+#define PANITENT_GRIMSTROKE_PATH_H
+
+#include "../util/tenttypes.h"
+
+typedef struct PathCommand PathCommand;
+typedef struct Path Path;
+
+typedef enum {
+ PATHCOMMAND_MOVETO,
+ PATHCOMMAND_LINETO,
+ PATHCOMMAND_CURVETO,
+ PATHCOMMAND_ARCTO
+} PathCommandType;
+
+struct PathCommand {
+ PathCommandType type;
+ TENTPointf p1;
+ TENTPointf p2;
+ TENTPointf control;
+ float radius;
+ struct PathCommand* next;
+};
+
+struct Path {
+ PathCommand* head;
+ PathCommand* tail;
+};
+
+Path* Path_Create()
+{
+ Path* pPath = (Path*)malloc(sizeof(Path));
+ pPath->head = NULL;
+ pPath->tail = NULL;
+ return pPath;
+}
+
+void Path_MoveTo(Path* path, float x, float y)
+{
+ PathCommand* cmd = (PathCommand*)malloc(sizeof(PathCommand));
+ cmd->type = PATHCOMMAND_MOVETO;
+ cmd->p1.x = x;
+ cmd->p2.y = y;
+ cmd->next = NULL;
+
+ if (!path->head) {
+ path->head = cmd;
+ }
+ else {
+ path->tail->next = cmd;
+ }
+ path->tail = cmd;
+}
+
+void Path_LineTo(Path* path, float x, float y)
+{
+ PathCommand* cmd = (PathCommand*)malloc(sizeof(PathCommand));
+ cmd->type = PATHCOMMAND_LINETO;
+ cmd->p1.x = x;
+ cmd->p2.y = y;
+ cmd->next = NULL;
+
+ if (!path->head) {
+ path->head = cmd;
+ }
+ else {
+ path->tail->next = cmd;
+ }
+ path->tail = cmd;
+}
+
+void Path_CurveTo(Path* path, float cx, float cy, float x, float y)
+{
+ PathCommand* cmd = (PathCommand*)malloc(sizeof(PathCommand));
+ cmd->type = PATHCOMMAND_ARCTO;
+ cmd->control.x = cx;
+ cmd->control.y = cy;
+ cmd->p1.x = x;
+ cmd->p1.y = y;
+ cmd->next = NULL;
+
+ if (!path->head) {
+ path->head = cmd;
+ }
+ else {
+ path->tail->next = cmd;
+ }
+ path->tail = cmd;
+}
+
+void Path_ArcTo(Path* path, float cx, float cy, float radius, float startAngle, float endAngle)
+{
+ PathCommand* cmd = (PathCommand*)malloc(sizeof(PathCommand));
+ cmd->type = PATHCOMMAND_ARCTO;
+ cmd->p1.x = cx;
+ cmd->p1.y = cy;
+ cmd->radius = radius;
+ cmd->p2.x = startAngle;
+ cmd->p2.y = endAngle;
+ cmd->next = NULL;
+
+ if (!path->head) {
+ path->head = cmd;
+ }
+ else {
+ path->tail->next = cmd;
+ }
+ path->tail = cmd;
+}
+
+#endif /* PANITENT_GRIMSTROKE_PATH_H */
diff --git a/src/grimstroke/polygon.h b/src/grimstroke/polygon.h
index 0054bc2..bb4879f 100644
--- a/src/grimstroke/polygon.h
+++ b/src/grimstroke/polygon.h
@@ -1,6 +1,7 @@
#pragma once
#include "../util/vector.h"
+#include "pixelbuffer.h"
typedef struct Point {
int x;
@@ -16,4 +17,4 @@ typedef struct PixelBuffer PixelBuffer;
PolygonPath* PolygonPath_Create();
void PolygonPath_AddPoint(PolygonPath* pPolygonPath, int x, int y);
void PolygonPath_Enclose(PolygonPath* pPolygonPath);
-void Polygon_DrawOnPixelBuffer(PolygonPath* pPolygonPath, PixelBuffer* pPixelBuffer);
+void Polygon_DrawOnPixelBuffer(PolygonPath* pPolygonPath, PixelBuffer* pPixelBuffer, Color color);
diff --git a/src/grimstroke/wushapestrategy.c b/src/grimstroke/wushapestrategy.c
index 9dbd423..f8a6420 100644
--- a/src/grimstroke/wushapestrategy.c
+++ b/src/grimstroke/wushapestrategy.c
@@ -51,9 +51,9 @@ void WuShapeStrategy_DrawLine(WuShapeStrategy* pWuShapeStrategy, int x1, int y1,
ASSERT(pWuShapeStrategy && pWuShapeStrategy->base.m_pShapeContext);
Plotter* pPlotter = ShapeContext_GetPlotter(pWuShapeStrategy->base.m_pShapeContext);
- int strokeWidth = 32;
+ int strokeWidth = 2;
- BOOL steep = fabsf((float)(y2 - y1)) > fabsf((float)(x2 - x1)) != 0.0f;
+ BOOL steep = fabsf((float)(y2 - y1)) > fabsf((float)(x2 - x1));
if (steep) {
ffswapT_(int, x1, y1);
diff --git a/src/msthemeloader.c b/src/msthemeloader.c
index 628b89b..f7ad7cb 100644
--- a/src/msthemeloader.c
+++ b/src/msthemeloader.c
@@ -61,10 +61,7 @@ int PntINI_Callback(void* user, PCTSTR section, PCTSTR name, PCTSTR value, int l
SelectObject(hdcMem, hOldBitmap);
DeleteBitmap(hBitmap);
DeleteDC(hdcMem);
-
- // MessageBox(NULL, szValue, section, NULL);
}
-
}
}
@@ -157,11 +154,7 @@ void MSTheme_Init(MSTheme* pMSTheme, PTSTR pszPath)
PTSTR pszKey = (PTSTR)malloc((len + 1) * sizeof(TCHAR));
_stprintf_s(pszKey, len + 1, szFormat, pPntINIContext->szSection, pPntINIContext->szName);
- // MessageBox(NULL, pszValue, pszKey, MB_OK);
-
RBHashMap_Insert(map, pszKey, pszValue);
-
-
}
void* val = RBHashMap_Lookup(map, _T("Window.Caption//ImageFile"));
diff --git a/src/panitentapp.c b/src/panitentapp.c
index 74cbc45..b0eb86d 100644
--- a/src/panitentapp.c
+++ b/src/panitentapp.c
@@ -32,12 +32,20 @@
#include "util/assert.h"
#include "win32/util.h"
#include "lua_scripting.h"
+#include "history.h"
+#include "viewport.h"
+#include "aboutbox.h"
#include "verifycheck.h"
+void PanitentApp_RegisterCommands(PanitentApp* pPanitentApp);
+
void PanitentApp_Init(PanitentApp* pPanitentApp)
{
Application_Init(&pPanitentApp->base);
+
+ AppCmd_Init(&pPanitentApp->m_appCmd);
+ PanitentApp_RegisterCommands(pPanitentApp);
pPanitentApp->pPanitentWindow = PanitentWindow_Create(pPanitentApp);
pPanitentApp->palette = Palette_Create();
@@ -93,7 +101,7 @@ int PanitentApp_Run(PanitentApp* pPanitentApp)
Window_CreateWindow((Window*)pPanitentApp->pPanitentWindow, NULL);
PanitentApp* pPanitentApp2 = PanitentApp_Instance();
- HANDLE hVerifyCheckThread = CreateThread(NULL, 0, VerifyCheckThreadProc, NULL, 0, NULL);
+ // HANDLE hVerifyCheckThread = CreateThread(NULL, 0, VerifyCheckThreadProc, NULL, 0, NULL);
return Application_Run(pPanitentApp);
}
@@ -159,7 +167,7 @@ TreeNode* CreatePaletteWindowNode(PanitentApp* pPanitentApp, DockHostWindow* pDo
memset(pDockDataPalette, 0, sizeof(DockData));
pNodePalette->data = (void*)pDockDataPalette;
wcscpy_s(pDockDataPalette->lpszName, MAX_PATH, L"Palette");
- PaletteWindow* pPaletteWindow = PaletteWindow_Create((Application*)pPanitentApp, pPanitentApp->palette);
+ PaletteWindow* pPaletteWindow = PaletteWindow_Create(pPanitentApp->palette);
HWND hwndPalette = Window_CreateWindow((Window*)pPaletteWindow, NULL);
DockData_PinWindow(pDockHostWindow, pDockDataPalette, (Window*)pPaletteWindow);
}
@@ -311,8 +319,8 @@ ViewportWindow* PanitentApp_GetActiveViewport(PanitentApp* pPanitentApp)
Document* PanitentApp_GetActiveDocument(PanitentApp* pPanitentApp)
{
- /* TODO: Not implemented */
- return NULL;
+ ViewportWindow *pViewportWindow = PanitentApp_GetActiveViewport(pPanitentApp);
+ return ViewportWindow_GetDocument(pViewportWindow);
}
ActivitySharingManager* PanitentApp_GetActivitySharingManager(PanitentApp* pPanitentApp)
@@ -552,3 +560,48 @@ void PanitentApp_CmdDisplayPixelBuffer(PanitentApp* pPanitentApp)
fclose(fp);
}
}
+
+void PanitentApp_CmdClose(PanitentApp* pPanitentApp)
+{
+ PostQuitMessage(0);
+}
+
+void PanitentApp_CmdUndo(PanitentApp* pPanitentApp)
+{
+ History_Undo(PanitentApp_GetActiveDocument(pPanitentApp));
+}
+
+void PanitentApp_CmdRedo(PanitentApp* pPanitentApp)
+{
+ History_Redo(PanitentApp_GetActiveDocument(pPanitentApp));
+}
+
+void PanitentApp_CmdAbout(PanitentApp* pPanitentApp)
+{
+ PanitentWindow* pPanitentWindow = PanitentApp_GetWindow(pPanitentApp);
+ HWND hMainWnd = Window_GetHWND((Window*)pPanitentWindow);
+ AboutBox_Run(hMainWnd);
+}
+
+void PanitentApp_RegisterCommands(PanitentApp* pPanitentApp)
+{
+ AppCmd* pAppCmd = &pPanitentApp->m_appCmd;
+
+ AppCmd_AddCommand(pAppCmd, IDM_FILE_NEW, &PanitentApp_CmdNewFile);
+ AppCmd_AddCommand(pAppCmd, IDM_FILE_OPEN, &PanitentApp_CmdOpenFile);
+ AppCmd_AddCommand(pAppCmd, IDM_FILE_SAVE, &PanitentApp_CmdSaveFile);
+ AppCmd_AddCommand(pAppCmd, IDM_FILE_CLIPBOARD_EXPORT, &PanitentApp_CmdClipboardExport);
+ AppCmd_AddCommand(pAppCmd, IDM_FILE_BINVIEW, &PanitentApp_CmdBinView);
+ AppCmd_AddCommand(pAppCmd, IDM_FILE_RUN_SCRIPT, &PanitentApp_CmdRunScript);
+ AppCmd_AddCommand(pAppCmd, IDM_FILE_CLOSE, &PanitentApp_CmdClose);
+ AppCmd_AddCommand(pAppCmd, IDM_EDIT_UNDO, &PanitentApp_CmdUndo);
+ AppCmd_AddCommand(pAppCmd, IDM_EDIT_REDO, &PanitentApp_CmdRedo);
+ AppCmd_AddCommand(pAppCmd, IDM_EDIT_CLRCANVAS, &PanitentApp_CmdClearCanvas);
+ AppCmd_AddCommand(pAppCmd, IDM_WINDOW_ACTIVITY_DIALOG, &PanitentApp_CmdShowActivityDialog);
+ AppCmd_AddCommand(pAppCmd, IDM_WINDOW_PROPERTY_GRID, &PanitentApp_CmdShowPropertyGridDialog);
+ AppCmd_AddCommand(pAppCmd, IDM_OPTIONS_SETTINGS, &PanitentApp_CmdShowSettings);
+ AppCmd_AddCommand(pAppCmd, IDM_HELP_LOG, &PanitentApp_CmdShowLog);
+ AppCmd_AddCommand(pAppCmd, IDM_HELP_RBTREEVIZ, &PanitentApp_CmdShowRbTreeViz);
+ AppCmd_AddCommand(pAppCmd, IDM_HELP_ABOUT, &PanitentApp_CmdAbout);
+ AppCmd_AddCommand(pAppCmd, IDM_HELP_DISPLAYPIXELBUFFER, &PanitentApp_CmdDisplayPixelBuffer);
+}
diff --git a/src/panitentapp.h b/src/panitentapp.h
index 768762a..a2d0c0f 100644
--- a/src/panitentapp.h
+++ b/src/panitentapp.h
@@ -4,6 +4,7 @@
#include "win32/application.h"
#include "palette.h"
#include "settings.h"
+#include "appcmd.h"
typedef struct PanitentWindow PanitentWindow;
typedef struct Tool Tool;
@@ -30,6 +31,7 @@ struct PanitentApp {
ViewportWindow* m_pViewportWindow;
PNTSETTINGS m_settings;
ShapeContext* m_pShapeContext;
+ AppCmd m_appCmd;
};
void PanitentApp_Init(PanitentApp* pPanitentApp);
diff --git a/src/panitentwindow.c b/src/panitentwindow.c
index bc12734..67cb0da 100644
--- a/src/panitentwindow.c
+++ b/src/panitentwindow.c
@@ -91,6 +91,7 @@ void PanitentWindow_PreRegister(LPWNDCLASSEX lpwcex)
lpwcex->hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON));
lpwcex->hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
lpwcex->lpszClassName = szClassName;
+ lpwcex->lpszMenuName = MAKEINTRESOURCE(IDC_MAINMENU);
}
void PanitentWindow_OnPaint(PanitentWindow* window)
@@ -337,155 +338,10 @@ LRESULT PanitentWindow_OnNCPaint(PanitentWindow* pPanitentWindow, HRGN hrgn)
return 0;
}
-/* Menu ID values */
-enum {
- IDM_FILE_NEW = 1001,
- IDM_FILE_OPEN,
- IDM_FILE_SAVE,
- IDM_FILE_CLIPBOARD_EXPORT,
- IDM_FILE_BINVIEW,
- IDM_FILE_RUN_SCRIPT,
- IDM_FILE_CLOSE,
-
- IDM_EDIT_UNDO,
- IDM_EDIT_REDO,
- IDM_EDIT_CLRCANVAS,
-
- IDM_WINDOW_TOOLS,
- IDM_WINDOW_ACTIVITY_DIALOG,
- IDM_WINDOW_PROPERTY_GRID,
-
- IDM_OPTIONS_SETTINGS,
-
- IDM_HELP_TOPICS,
- IDM_HELP_LOG,
- IDM_HELP_RBTREEVIZ,
- IDM_HELP_ABOUT,
- IDM_HELP_DISPLAYPIXELBUFFER
-};
-
-HMENU PanitentWindow_CreateMenu()
-{
- HMENU hMenu;
- HMENU hSubMenu;
-
- hMenu = CreateMenu();
-
- hSubMenu = CreatePopupMenu();
- AppendMenu(hSubMenu, MF_STRING, IDM_FILE_NEW, L"&New\tCtrl+N");
- AppendMenu(hSubMenu, MF_STRING, IDM_FILE_OPEN, L"&Open\tCtrl+O");
- AppendMenu(hSubMenu, MF_STRING, IDM_FILE_SAVE, L"&Save\tCtrl+S");
- AppendMenu(hSubMenu, MF_STRING, IDM_FILE_CLIPBOARD_EXPORT, L"Export image to clipboard");
- AppendMenu(hSubMenu, MF_STRING, IDM_FILE_BINVIEW, L"BinView");
- AppendMenu(hSubMenu, MF_STRING, IDM_FILE_CLOSE, L"&Close");
- AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT_PTR)hSubMenu, L"&File");
-
- hSubMenu = CreatePopupMenu();
- AppendMenu(hSubMenu, MF_STRING, IDM_EDIT_UNDO, L"&Undo");
- AppendMenu(hSubMenu, MF_STRING, IDM_EDIT_REDO, L"&Redo");
- AppendMenu(hSubMenu, MF_STRING, IDM_EDIT_CLRCANVAS, L"&Clear canvas");
- AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT_PTR)hSubMenu, L"&Edit");
-
- hSubMenu = CreatePopupMenu();
- AppendMenu(hSubMenu, MF_STRING, IDM_FILE_RUN_SCRIPT, L"Run last script");
- AppendMenu(hSubMenu, MF_STRING, IDM_FILE_RUN_SCRIPT, L"Run script...");
- AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT_PTR)hSubMenu, L"&Scripting");
-
- hSubMenu = CreatePopupMenu();
- AppendMenu(hSubMenu, MF_STRING, IDM_WINDOW_TOOLS, L"&Tools");
- AppendMenu(hSubMenu, MF_STRING, IDM_WINDOW_ACTIVITY_DIALOG, L"&Activity...");
- AppendMenu(hSubMenu, MF_STRING, IDM_WINDOW_PROPERTY_GRID, L"&Property Grid...");
- AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT_PTR)hSubMenu, L"&Window");
- CheckMenuItem(hSubMenu, IDM_WINDOW_TOOLS, MF_BYCOMMAND | MF_CHECKED);
-
- hSubMenu = CreatePopupMenu();
- AppendMenu(hSubMenu, MF_STRING, IDM_OPTIONS_SETTINGS, L"&Settings");
- AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT_PTR)hSubMenu, L"&Options");
-
- hSubMenu = CreatePopupMenu();
- AppendMenu(hSubMenu, MF_STRING, IDM_HELP_TOPICS, L"Help &Topics");
- AppendMenu(hSubMenu, MF_STRING, IDM_HELP_LOG, L"&Log");
- AppendMenu(hSubMenu, MF_STRING, IDM_HELP_RBTREEVIZ, L"&RBTreeViz");
- AppendMenu(hSubMenu, MF_STRING, IDM_HELP_ABOUT, L"&About");
- AppendMenu(hSubMenu, MF_STRING, IDM_HELP_DISPLAYPIXELBUFFER, L"&Display pixel buffer");
- AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT_PTR)hSubMenu, L"&Help");
-
- return hMenu;
-}
-
LRESULT PanitentWindow_OnCommand(PanitentWindow* pPanitentWindow, WPARAM wParam, LPARAM lParam)
{
- /* Handle menu commands */
- switch (LOWORD(wParam))
- {
- case IDM_FILE_NEW:
- PanitentApp_CmdNewFile(PanitentApp_Instance());
- break;
-
- case IDM_FILE_OPEN:
- PanitentApp_CmdOpenFile(PanitentApp_Instance());
- break;
-
- case IDM_FILE_SAVE:
- PanitentApp_CmdSaveFile(PanitentApp_Instance());
- break;
-
- case IDM_FILE_CLIPBOARD_EXPORT:
- PanitentApp_CmdClipboardExport(PanitentApp_Instance());
- break;
-
- case IDM_FILE_BINVIEW:
- PanitentApp_CmdBinView(PanitentApp_Instance());
- break;
-
- case IDM_FILE_RUN_SCRIPT:
- PanitentApp_CmdRunScript(PanitentApp_Instance());
- break;
-
- case IDM_FILE_CLOSE:
- PostQuitMessage(0);
- break;
-
- case IDM_EDIT_UNDO:
- History_Undo(PanitentApp_GetActiveDocument(PanitentApp_Instance()));
- break;
-
- case IDM_EDIT_REDO:
- History_Redo(PanitentApp_GetActiveDocument(PanitentApp_Instance()));
- break;
-
- case IDM_EDIT_CLRCANVAS:
- PanitentApp_CmdClearCanvas(PanitentApp_Instance());
- break;
-
- case IDM_WINDOW_ACTIVITY_DIALOG:
- PanitentApp_CmdShowActivityDialog(PanitentApp_Instance());
- break;
-
- case IDM_WINDOW_PROPERTY_GRID:
- PanitentApp_CmdShowPropertyGridDialog(PanitentApp_Instance());
- break;
-
- case IDM_OPTIONS_SETTINGS:
- PanitentApp_CmdShowSettings(PanitentApp_Instance());
- break;
-
- case IDM_HELP_LOG:
- PanitentApp_CmdShowLog(PanitentApp_Instance());
- break;
-
- case IDM_HELP_RBTREEVIZ:
- PanitentApp_CmdShowRbTreeViz(PanitentApp_Instance());
- break;
-
- case IDM_HELP_ABOUT:
- AboutBox_Run(Window_GetHWND((Window *)pPanitentWindow));
- break;
-
- case IDM_HELP_DISPLAYPIXELBUFFER:
- PanitentApp_CmdDisplayPixelBuffer(PanitentApp_Instance());
- }
-
+ PanitentApp* pPanitentApp = PanitentApp_Instance();
+ AppCmd_Execute(&pPanitentApp->m_appCmd, LOWORD(wParam), pPanitentApp);
return 0;
}
@@ -572,9 +428,7 @@ BOOL PanitentWindow_OnCreate(PanitentWindow* pPanitentWindow, LPCREATESTRUCT lpc
void PanitentWindow_PostCreate(PanitentWindow* pPanitentWindow)
{
- /* Set menu */
HWND hWnd = Window_GetHWND((Window *)pPanitentWindow);
- SetMenu(hWnd, PanitentWindow_CreateMenu());
/* Allocate dockhost window data structure */
DockHostWindow* pDockHostWindow = DockHostWindow_Create(PanitentApp_Instance());
diff --git a/src/resource.h b/src/resource.h
index 284c866..35d7a58 100644
--- a/src/resource.h
+++ b/src/resource.h
@@ -10,6 +10,32 @@
#define IDI_ICON 1101
#define IDI_LOG 1102
+#define IDC_MAINMENU 100
+
+#define IDM_FILE_NEW 1001
+#define IDM_FILE_OPEN 1002
+#define IDM_FILE_SAVE 1003
+#define IDM_FILE_CLIPBOARD_EXPORT 1004
+#define IDM_FILE_BINVIEW 1005
+#define IDM_FILE_RUN_SCRIPT 1006
+#define IDM_FILE_CLOSE 1007
+
+#define IDM_EDIT_UNDO 1008
+#define IDM_EDIT_REDO 1009
+#define IDM_EDIT_CLRCANVAS 1010
+
+#define IDM_WINDOW_TOOLS 1011
+#define IDM_WINDOW_ACTIVITY_DIALOG 1012
+#define IDM_WINDOW_PROPERTY_GRID 1013
+
+#define IDM_OPTIONS_SETTINGS 1014
+
+#define IDM_HELP_TOPICS 1015
+#define IDM_HELP_LOG 1016
+#define IDM_HELP_RBTREEVIZ 1017
+#define IDM_HELP_ABOUT 1018
+#define IDM_HELP_DISPLAYPIXELBUFFER 1019
+
#define IDB_TOOLS 1201
#define IDB_TOOLS24 1202
#define IDB_CLOSEBTN 1203
diff --git a/src/s11n/bsonserializer.c b/src/s11n/bsonserializer.c
new file mode 100644
index 0000000..e69de29
diff --git a/src/s11n/bsonserializer.h b/src/s11n/bsonserializer.h
new file mode 100644
index 0000000..f9407e3
--- /dev/null
+++ b/src/s11n/bsonserializer.h
@@ -0,0 +1,6 @@
+#ifndef PANITENT_S11N_BSON_SERIALIZER_H
+#define PANITENT_S11N_BSON_SERIALIZER_H
+
+
+
+#endif /* PANITENT_S11N_BSON_SERIALIZER_H */
diff --git a/src/s11n/jsonserializer.c b/src/s11n/jsonserializer.c
new file mode 100644
index 0000000..dc9179e
--- /dev/null
+++ b/src/s11n/jsonserializer.c
@@ -0,0 +1,27 @@
+#include "../precomp.h"
+
+#include "jsonserializer.h"
+
+/* Implementation */
+void __impl_JSONSerializer_Serialize(JSONSerializer* pSerializer, PropertyTreeNode* pPropTree)
+{
+ printf("Key: %s\n", pPropTree->key);
+
+ switch (pPropTree->value.type) {
+ case TENTANY_TYPE_INT:
+ printf("Value: %d\n", pPropTree->value.data.intVal);
+ break;
+ case TENTANY_TYPE_STRING:
+ printf("Value: %s\n", pPropTree->value.data.strVal);
+ break;
+ }
+}
+
+JSONSerializer_vtbl __vtbl_JSONSerializer = {
+ .Serialize = __impl_JSONSerializer_Serialize
+};
+
+void JSONSerializer_Init(JSONSerializer* pSerializer)
+{
+ pSerializer->pVtbl = &__vtbl_JSONSerializer;
+}
diff --git a/src/s11n/jsonserializer.h b/src/s11n/jsonserializer.h
new file mode 100644
index 0000000..d39146e
--- /dev/null
+++ b/src/s11n/jsonserializer.h
@@ -0,0 +1,30 @@
+#ifndef PANITENT_S11N_JSONSERIALIZER_H
+#define PANITENT_S11N_JSONSERIALIZER_H
+
+#include "propertytree.h"
+#include "serializer.h"
+
+/*
+ * class JSONSerializer implements ISerializer
+ */
+
+typedef struct JSONSerializer JSONSerializer;
+typedef struct JSONSerializer_vtbl JSONSerializer_vtbl;
+
+struct JSONSerializer_vtbl {
+ void (*Serialize)(JSONSerializer* pSerializer, PropertyTreeNode* pPropTree);
+};
+
+struct JSONSerializer {
+ JSONSerializer_vtbl* pVtbl;
+};
+
+void JSONSerializer_Init(JSONSerializer* pSerializer);
+
+/* Interface wrappers */
+inline void JSONSerializer_Serialize(JSONSerializer* pSerializer, PropertyTreeNode* pPropTree)
+{
+ pSerializer->pVtbl->Serialize(pSerializer, pPropTree);
+}
+
+#endif /* PANITENT_S11N_JSONSERIALIZER_H */
diff --git a/src/s11n/propertytree.h b/src/s11n/propertytree.h
new file mode 100644
index 0000000..9cda4a6
--- /dev/null
+++ b/src/s11n/propertytree.h
@@ -0,0 +1,46 @@
+#ifndef PANITENT_S11N_PROPERTYTREE_H
+#define PANITENT_S11N_PROPERTYTREE_H
+
+#ifndef PANITENT_PRECOMP_H
+#error "Include precomp.h first"
+#endif /* PANITENT_PRECOMP_H */
+
+#include "tentany.h"
+
+typedef struct PropertyTreeNode PropertyTreeNode;
+struct PropertyTreeNode {
+ char* key;
+ TENTAny value;
+ PropertyTreeNode* child;
+ PropertyTreeNode* sibling;
+};
+
+/* Function to create a new tree node */
+inline PropertyTreeNode* PropertyTreeNode_CreateNode(const char* key, TENTAny* value)
+{
+ PropertyTreeNode* pNode = (PropertyTreeNode*)malloc(sizeof(PropertyTreeNode));
+ pNode->key = _strdup(key);
+ pNode->value = *value;
+ pNode->child = NULL;
+ pNode->sibling = NULL;
+ return pNode;
+}
+
+/* Function to add a child node to a parent node */
+inline void PropertyTreeNode_AddChildNode(PropertyTreeNode* parent, PropertyTreeNode* child)
+{
+ if (parent->child == NULL)
+ {
+ parent->child = child;
+ }
+ else {
+ PropertyTreeNode* sibling = parent->child;
+ while (sibling->sibling != NULL)
+ {
+ sibling = sibling->sibling;
+ }
+ sibling->sibling = child;
+ }
+}
+
+#endif /* PANITENT_S11N_PROPERTYTREE_H */
diff --git a/src/s11n/serializable.h b/src/s11n/serializable.h
new file mode 100644
index 0000000..cad9dce
--- /dev/null
+++ b/src/s11n/serializable.h
@@ -0,0 +1,17 @@
+#ifndef PANITENT_SERIALIZATION_SERIALIZABLE_H
+#define PANITENT_SERIALIZATION_SERIALIZABLE_H
+
+#include "serializer.h"
+
+typedef struct ISerializable ISerializable;
+
+struct ISerializable {
+ void (*Serialize)(ISerializable *pSerializable, ISerializer* pSerializer);
+};
+
+inline void ISerializable_Serialize(ISerializable* pSerializable, ISerializer* pSerializer)
+{
+ pSerializable->Serialize(pSerializable, pSerializer);
+}
+
+#endif /* PANITENT_SERIALIZATION_SERIALIZABLE_H */
diff --git a/src/s11n/serializable_example.c b/src/s11n/serializable_example.c
new file mode 100644
index 0000000..f2c7fb4
--- /dev/null
+++ b/src/s11n/serializable_example.c
@@ -0,0 +1,36 @@
+#include "../precomp.h"
+
+#include "tentany.h"
+#include "serializable_example.h"
+#include "serializer.h"
+
+void __impl_SerializableExample_Serialize(SerializableExample* pSerializableExample, ISerializer* pSerializer);
+
+SerializableExample_vtbl __vtbl_SerializableExample = {
+ .Serialize = __impl_SerializableExample_Serialize
+};
+
+void __impl_SerializableExample_Serialize(SerializableExample* pSerializableExample, ISerializer* pSerializer)
+{
+ TENTAny nameTA = { 0 };
+ TENTAny_SetString(&nameTA, pSerializableExample->name);
+ PropertyTreeNode* pNameNode = PropertyTreeNode_CreateNode("name", &nameTA);
+
+ TENTAny ageTA = { 0 };
+ TENTAny_SetInt(&ageTA, pSerializableExample->age);
+ PropertyTreeNode* pAgeNode = PropertyTreeNode_CreateNode("age", &ageTA);
+
+ TENTAny flatTA = { 0 };
+ TENTAny_SetInt(&flatTA, pSerializableExample->flat);
+ PropertyTreeNode* pFlatNode = PropertyTreeNode_CreateNode("flat", &flatTA);
+
+ // PropertyTreeNode_AddChildNode(&nameTA, &ageTA);
+ // PropertyTreeNode_AddChildNode(&nameTA, &flatTA);
+
+ ISerializer_Serialize((ISerializer*)pSerializer, &nameTA);
+}
+
+void SerializableExample_Init(SerializableExample* pSerializableExample)
+{
+ pSerializableExample->pVtbl = &__vtbl_SerializableExample;
+}
diff --git a/src/s11n/serializable_example.h b/src/s11n/serializable_example.h
new file mode 100644
index 0000000..737b3cc
--- /dev/null
+++ b/src/s11n/serializable_example.h
@@ -0,0 +1,30 @@
+#ifndef PANITENT_S11N_SERIALIZABLE_EXAMPLE_H
+#define PANITENT_S11N_SERIALIZABLE_EXAMPLE_H
+
+#include "serializable.h"
+#include "serializer.h"
+#include "propertytree.h"
+
+typedef struct SerializableExample SerializableExample;
+typedef struct SerializableExample_vtbl SerializableExample_vtbl;
+
+struct SerializableExample_vtbl {
+ void (*Serialize)(SerializableExample* pSerializableExample, ISerializer* pSerializer);
+};
+
+struct SerializableExample {
+ SerializableExample_vtbl* pVtbl;
+ char* name;
+ int age;
+ int flat;
+};
+
+void SerializableExample_Init(SerializableExample* pSerializableExample);
+
+/* Interface wrappers */
+inline void SerializableExample_Serialize(SerializableExample* pSerializableExample, ISerializer* pSerializer)
+{
+ pSerializableExample->pVtbl->Serialize(pSerializableExample, pSerializer);
+}
+
+#endif /* PANITENT_S11N_SERIALIZABLE_EXAMPLE_H */
diff --git a/src/s11n/serializer.h b/src/s11n/serializer.h
new file mode 100644
index 0000000..5069dd8
--- /dev/null
+++ b/src/s11n/serializer.h
@@ -0,0 +1,22 @@
+#ifndef PANITENT_SERIALIZATION_SERIALIZER_H
+#define PANITENT_SERIALIZATION_SERIALIZER_H
+
+#include "propertytree.h"
+
+typedef struct ISerializer ISerializer;
+typedef struct ISerializer_vtbl ISerializer_vtbl;
+
+struct ISerializer_vtbl {
+ void (*Serialize)(ISerializer* pSerializer, PropertyTreeNode* pPropTree);
+};
+
+struct ISerializer {
+ ISerializer_vtbl* pVtbl;
+};
+
+inline void ISerializer_Serialize(ISerializer* pSerializer, PropertyTreeNode* pPropTree)
+{
+ pSerializer->pVtbl->Serialize(pSerializer, pPropTree);
+}
+
+#endif /* PANITENT_UTIL_SERIALIZER_H */
diff --git a/src/s11n/tentany.h b/src/s11n/tentany.h
new file mode 100644
index 0000000..6328333
--- /dev/null
+++ b/src/s11n/tentany.h
@@ -0,0 +1,78 @@
+#ifndef PANITENT_S11N_ANY_H
+#define PANITENT_S11N_ANY_H
+
+typedef enum {
+ TENTANY_TYPE_EMPTY,
+ TENTANY_TYPE_INT,
+ TENTANY_TYPE_FLOAT,
+ TENTANY_TYPE_DOUBLE,
+ TENTANY_TYPE_STRING,
+ TENTANY_TYPE_CUSTOM
+} ETENTAnyType;
+
+typedef struct TENTAny TENTAny;
+typedef union TENTAnyUnion TENTAnyUnion;
+
+struct TENTAny {
+ ETENTAnyType type;
+ union TENTAnyUnion {
+ int intVal;
+ float floatVal;
+ double doubleVal;
+ char* strVal;
+ void* customVal;
+ } data;
+};
+
+inline void TENTAny_Clear(TENTAny* pAny)
+{
+ switch (pAny->type)
+ {
+ case TENTANY_TYPE_STRING:
+ case TENTANY_TYPE_CUSTOM:
+ free(pAny->data.customVal);
+ break;
+ }
+
+ memset(&pAny->data, 0, sizeof(TENTAnyUnion));
+ pAny->type = TENTANY_TYPE_EMPTY;
+}
+
+inline void TENTAny_SetInt(TENTAny* pAny, int val)
+{
+ TENTAny_Clear(pAny);
+ pAny->type = TENTANY_TYPE_INT;
+ pAny->data.intVal = val;
+}
+
+inline void TENTAny_SetFloat(TENTAny* pAny, float val)
+{
+ TENTAny_Clear(pAny);
+ pAny->type = TENTANY_TYPE_FLOAT;
+ pAny->data.floatVal = val;
+}
+
+inline void TENTAny_SetDouble(TENTAny* pAny, double val)
+{
+ TENTAny_Clear(pAny);
+ pAny->type = TENTANY_TYPE_DOUBLE;
+ pAny->data.doubleVal = val;
+}
+
+inline void TENTAny_SetString(TENTAny* pAny, char* string)
+{
+ TENTAny_Clear(pAny);
+ pAny->type = TENTANY_TYPE_STRING;
+ pAny->data.strVal = _strdup(string);
+}
+
+inline void TENTAny_SetCustom(TENTAny* pAny, void* data, size_t size)
+{
+ TENTAny_Clear(pAny);
+ pAny->type = TENTANY_TYPE_CUSTOM;
+ void* pCustom = malloc(size);
+ memcpy(pCustom, data, size);
+ pAny->data.customVal = pCustom;
+}
+
+#endif /* PANITENT_S11N_ANY_H */
diff --git a/src/s11n/xmlserializer.c b/src/s11n/xmlserializer.c
new file mode 100644
index 0000000..663178b
--- /dev/null
+++ b/src/s11n/xmlserializer.c
@@ -0,0 +1,4 @@
+#include "../precomp.h"
+
+#include "xmlserializer.h"
+
diff --git a/src/s11n/xmlserializer.h b/src/s11n/xmlserializer.h
new file mode 100644
index 0000000..6392486
--- /dev/null
+++ b/src/s11n/xmlserializer.h
@@ -0,0 +1,41 @@
+#ifndef PANITENT_S11N_XMLSERIALIZER_H
+#define PANITENT_S11N_XMLSERIALIZER_H
+
+#include "propertytree.h"
+#include "serializer.h"
+
+/*
+ * class XMLSerializer implements ISerializer
+ */
+
+typedef struct XMLSerializer XMLSerializer;
+typedef struct XMLSerializer_vtbl XMLSerializer_vtbl;
+
+struct XMLSerializer_vtbl {
+ void (*Serialize)(XMLSerializer* pSerializer, PropertyTreeNode* pPropTree);
+};
+
+void __impl_XMLSerializer_Serialize(XMLSerializer* pSerializer, PropertyTreeNode* pPropTree)
+{
+
+}
+
+XMLSerializer_vtbl __vtbl_XMLSerializer = {
+ .Serialize = __impl_XMLSerializer_Serialize
+};
+
+struct XMLSerializer {
+ XMLSerializer_vtbl* pVtbl;
+};
+
+void XMLSerializer_Init(XMLSerializer* pSerializer)
+{
+ pSerializer->pVtbl = &__vtbl_XMLSerializer;
+}
+
+inline void XMLSerializer_Serialize(XMLSerializer* pSerializer, PropertyTreeNode* pPropTree)
+{
+ pSerializer->pVtbl->Serialize(pSerializer, pPropTree);
+}
+
+#endif /* PANITENT_S11N_XMLSERIALIZER_H */
diff --git a/src/shell/pathutil.c b/src/shell/pathutil.c
index ff6c063..28f61c3 100644
--- a/src/shell/pathutil.c
+++ b/src/shell/pathutil.c
@@ -115,7 +115,7 @@ void GetWorkDir()
PWSTR pszWorkDir = (PWSTR)malloc((dwLen + 1) * sizeof(WCHAR));
if (pszWorkDir)
{
- GetCurrentDirectory(pszWorkDir, pszWorkDir, dwLen + 1);
+ GetCurrentDirectoryW(dwLen + 1, pszWorkDir);
}
}
}
diff --git a/src/swatchstorage.h b/src/swatchstorage.h
new file mode 100644
index 0000000..c62f977
--- /dev/null
+++ b/src/swatchstorage.h
@@ -0,0 +1,49 @@
+#ifndef PANITENT_SWATCHSTORAGE_H
+#define PATENINT_SWATCHSTORAGE_H
+
+#include "swatchstoragebase.h"
+
+// FIXME remove
+#include
+#include "util/vector.h"
+
+typedef struct SwatchStorage SwatchStorage;
+typedef struct SwatchStorage_vtbl SwatchStorage_vtbl;
+
+struct SwatchStorage_vtbl {
+ void (*Add)(SwatchStorage* pSwatchStorage, uint32_t color);
+ void (*Clear)(SwatchStorage* pSwatchStorage);
+};
+
+struct SwatchStorage {
+ SwatchStorage_vtbl* pVtbl;
+ Vector colors;
+};
+
+void __impl_SwatchStorage_Add(SwatchStorage* pSwatchStorage, uint32_t color);
+void __impl_SwatchStorage_Clear(SwatchStorage* pSwatchStorage);
+
+SwatchStorage_vtbl __vtbl_SwatchStorage = {
+ .Add = __impl_SwatchStorage_Add,
+ .Clear = __impl_SwatchStorage_Clear
+};
+
+void SwatchStorage_Init(SwatchStorage* pSwatchStorage)
+{
+ pSwatchStorage->pVtbl = &__vtbl_SwatchStorage;
+
+ Vector_Init(&pSwatchStorage->colors, sizeof(uint32_t));
+}
+
+void __impl_SwatchStorage_Add(SwatchStorage* pSwatchStorage, uint32_t color)
+{
+ Vector* pColors = &pSwatchStorage->colors;
+ Vector_PushBack(pColors, (void*)&color);
+}
+
+void __impl_SwatchStorage_Clear(SwatchStorage* pSwatchStorage)
+{
+ Vector* pColors = &pSwatchStorage->colors;
+}
+
+#endif /* PANITENT_SWATCHSTORAGE */
diff --git a/src/swatchstoragebase.h b/src/swatchstoragebase.h
new file mode 100644
index 0000000..6be0f4e
--- /dev/null
+++ b/src/swatchstoragebase.h
@@ -0,0 +1,16 @@
+#ifndef PANITENT_SWATCHSTORAGEBASE_H
+#define PANITENT_SWATCHSTORAGEBASE_H
+
+typedef struct ISwatchStorage ISwatchStorage;
+typedef struct ISwatchStorage_vtbl ISwatchStorage_vtbl;
+
+struct ISwatchStorage_vtbl {
+ void (*Add)(ISwatchStorage* pISwatchStorage, uint32_t color);
+ void (*Clear)(ISwatchStorage* pISwatchStorage);
+};
+
+struct ISwatchStorage {
+ ISwatchStorage_vtbl* pVtbl;
+};
+
+#endif /* PANITENT_SWATCHSTORAGEBASE_H */
diff --git a/src/toolwndframe.h b/src/toolwndframe.h
index 946e5fc..a17aaac 100644
--- a/src/toolwndframe.h
+++ b/src/toolwndframe.h
@@ -18,5 +18,5 @@ struct CaptionButton {
int htCommand;
};
-void DrawCaptionGlyph(HDC hdc, int x, int y, int iGlyph);
-void DrawCaptionButton(CaptionButton* pCaptionButton, HDC hdc, int x, int y);
+void DrawCaptionGlyph(HDC hdc, PRECT prc, int iGlyph);
+void DrawCaptionButton(CaptionButton* pCaptionButton, HDC hdc, int x, int y, int width, int height);
diff --git a/src/util/list.c b/src/util/list.c
index d4fc374..c739689 100644
--- a/src/util/list.c
+++ b/src/util/list.c
@@ -10,7 +10,7 @@ struct List {
size_t nElementSize;
};
-void List_Init(List* pList);
+void List_Init(List* pList, size_t nElementSize);
List* List_Create(size_t nElementSize)
{
diff --git a/src/util/pntstring.c b/src/util/pntstring.c
index a79562e..72e2f87 100644
--- a/src/util/pntstring.c
+++ b/src/util/pntstring.c
@@ -86,7 +86,7 @@ void PntString_SetFromUTF16(PntString* pPntString, const uint16_t* pStr)
pData = realloc(pPntString->data, len);
}
else {
- pData = malloc(pPntString->data, len);
+ pData = malloc(len);
}
if (!pData)
diff --git a/src/util/tentobj.h b/src/util/tentobj.h
new file mode 100644
index 0000000..9079006
--- /dev/null
+++ b/src/util/tentobj.h
@@ -0,0 +1,24 @@
+#ifndef TENTCORE_TENTOBJ_H
+#define TENTCORE_TENTOBJ_H
+
+#define DECLARE_$NEW_ARGS(T, ...) \
+T* T##_$new(__VA_ARGS__) { \
+ void* pObject = malloc(sizeof(T)); \
+ if (pObject) { \
+ memset(pObject, 0, sizeof(T)); \
+ T##_$init((T*)pObject, __VA_ARGS__); \
+ } \
+ return (T*)pObject; \
+}
+
+#define DECLARE_$NEW(T) \
+T* T##_$new() { \
+ void* pObject = malloc(sizeof(T)); \
+ if (pObject) { \
+ memset(pObject, 0, sizeof(T)); \
+ T##_$init((T*)pObject); \
+ } \
+ return (T*)pObject; \
+}
+
+#endif /* TENTCORE_TENTOBJ_H */
diff --git a/src/util/tenttypes.h b/src/util/tenttypes.h
new file mode 100644
index 0000000..a004de1
--- /dev/null
+++ b/src/util/tenttypes.h
@@ -0,0 +1,51 @@
+#ifndef PANITENT_UTIL_TENTTYPES_H
+#define PANITENT_UTIL_TENTTYPES_H
+
+#define __TENT_DECLARE_VEC2T(T, TN) \
+typedef struct TENTVec2##TN { \
+ union { \
+ T x; \
+ T w; \
+ T width; \
+ }; \
+ union { \
+ T y; \
+ T h; \
+ T height; \
+ }; \
+} TENTVec2##TN;
+
+#define __TENT_DECLARE_VEC3T(T, TN) \
+typedef struct TENTVec3##TN { \
+ union { \
+ T x; \
+ T w; \
+ T width; \
+ }; \
+ union { \
+ T y; \
+ T h; \
+ T height; \
+ }; \
+ union { \
+ T z; \
+ T d; \
+ T depth; \
+ }; \
+} TENTVec3##TN;
+
+__TENT_DECLARE_VEC2T(int, i)
+__TENT_DECLARE_VEC2T(unsigned, u)
+__TENT_DECLARE_VEC2T(float, f)
+__TENT_DECLARE_VEC2T(double, d)
+
+__TENT_DECLARE_VEC3T(int, i)
+__TENT_DECLARE_VEC3T(unsigned, u)
+__TENT_DECLARE_VEC3T(float, f)
+__TENT_DECLARE_VEC3T(double, d)
+
+typedef TENTVec2i TENTSizei, TENTPointi, TENTPosi;
+typedef TENTVec2u TENTSizeu, TENTPointu, TENTPosu;
+typedef TENTVec2f TENTSizef, TENTPointf, TENTPosf;
+
+#endif /* PANITENT_UTIL_TENTTYPES_H */
diff --git a/src/util/vector.c b/src/util/vector.c
index 7619d18..5fec75a 100644
--- a/src/util/vector.c
+++ b/src/util/vector.c
@@ -112,3 +112,9 @@ void Vector_Free(Vector* pVector)
pVector->nSize = 0;
pVector->nCapacity = 0;
}
+
+/* Clear the vector. (Remove all elements) */
+void Vector_Clear(Vector* pVector)
+{
+ pVector->nSize = 0;
+}
diff --git a/src/util/vector.h b/src/util/vector.h
index fb07d87..0a72d19 100644
--- a/src/util/vector.h
+++ b/src/util/vector.h
@@ -9,10 +9,22 @@ struct Vector {
};
void Vector_Init(Vector* pVector, size_t nElementSize);
+
+/* Capacity */
+void Vector_IsEmpty(Vector* pVector);
+size_t Vector_GetSize(Vector* pVector);
void Vector_Reserve(Vector* pVector, size_t nNewCapacity);
-void Vector_Resize(Vector* pVector, size_t nNewSize, void* pDefaultValue);
+size_t Vector_GetCapacity(Vector* pVector);
+
+/* Modifiers */
+void Vector_Clear(Vector* pVector);
+// void Vector_Insert(Vector* pVector);
+// void Vector_Erase(Vector* pVector);
void Vector_PushBack(Vector* pVector, void* pValue);
-void* Vector_At(Vector* pVector, size_t nIndex);
+// void Vector_PopBack(Vector* pVector, void* pValue);
+void Vector_Resize(Vector* pVector, size_t nNewSize, void* pDefaultValue);
void Vector_Remove(Vector* pVector, size_t nIndex);
-size_t Vector_GetSize(Vector* pVector);
+
+void* Vector_At(Vector* pVector, size_t nIndex);
void Vector_Free(Vector* pVector);
+
diff --git a/win32fw_test/test_application.c b/win32fw_test/test_application.c
index b06ccf8..09b0831 100644
--- a/win32fw_test/test_application.c
+++ b/win32fw_test/test_application.c
@@ -8,7 +8,7 @@ void TestApplication_Init(TestApplication* app)
{
Application_Init(&app->application);
- app->mainWindow = TestWindow_Create(app);
+ app->mainWindow = TestWindow_$new(app);
}
TestApplication* TestApplication_Create()
diff --git a/win32fw_test/test_window.c b/win32fw_test/test_window.c
index 992a27c..866cdad 100644
--- a/win32fw_test/test_window.c
+++ b/win32fw_test/test_window.c
@@ -5,8 +5,8 @@
static const WCHAR szClassName[] = L"TestWindowClass";
-TestWindow* TestWindow_Create(Application*);
-void TestWindow_Init(TestWindow* window, Application*);
+TestWindow* TestWindow_$new(Application*);
+void TestWindow_$init(TestWindow* window, Application*);
void TestWindow_PreRegister(LPWNDCLASSEX);
void TestWindow_PreCreate(LPCREATESTRUCT);
@@ -16,22 +16,22 @@ void TestWindow_OnSize(TestWindow*, UINT, int, int);
void TestWindow_OnPaint(TestWindow*);
LRESULT CALLBACK TestWindow_UserProc(struct Window*, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
-TestWindow* TestWindow_Create(Application* app)
+TestWindow* TestWindow_$new(Application* app)
{
TestWindow* pTestWindow = (TestWindow*)malloc(sizeof(TestWindow));
memset(pTestWindow, 0, sizeof(TestWindow));
if (pTestWindow)
{
- TestWindow_Init(pTestWindow, app);
+ TestWindow_$init(pTestWindow, app);
}
return pTestWindow;
}
-void TestWindow_Init(TestWindow* window, Application* app)
+void TestWindow_$init(TestWindow* window, Application* app)
{
- Window_Init(&window->base, app);
+ Window_$init(&window->base, app);
window->base.szClassName = szClassName;
diff --git a/win32fw_test/test_window.h b/win32fw_test/test_window.h
index e2be079..b1a8721 100644
--- a/win32fw_test/test_window.h
+++ b/win32fw_test/test_window.h
@@ -11,6 +11,6 @@ struct TestWindow {
TreeViewCtl treeView;
};
-TestWindow* TestWindow_Create(Application*);
+TestWindow* TestWindow_$new(Application*);
#endif /* _TEST_WINDOW_H_INLUCDED */