From b0b0e97aa5a06b22768bb9c9ea5e8caf383d78a4 Mon Sep 17 00:00:00 2001 From: Jonas Kümmerlin Date: Thu, 27 Dec 2018 20:50:39 +0100 Subject: split into multiple files --- Makefile.mingw | 19 ++- Makefile.vc6 | 21 ++- alf/alf.cpp | 376 +----------------------------------------------------- alf/alfbutton.cpp | 95 ++++++++++++++ alf/alfcompat.cpp | 23 ++++ alf/alfedit.cpp | 76 +++++++++++ alf/alflabel.cpp | 83 ++++++++++++ alf/alflist.h | 50 ++++++++ alf/alfpriv.h | 67 ++++++++++ makemakefile.sh | 57 +++++++++ 10 files changed, 489 insertions(+), 378 deletions(-) create mode 100644 alf/alfbutton.cpp create mode 100644 alf/alfcompat.cpp create mode 100644 alf/alfedit.cpp create mode 100644 alf/alflabel.cpp create mode 100644 alf/alflist.h create mode 100644 alf/alfpriv.h create mode 100755 makemakefile.sh diff --git a/Makefile.mingw b/Makefile.mingw index 3276c92..5da8fa5 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -1,11 +1,25 @@ +# automatically created by makemakefile.sh. DO NOT EDIT! + CXX = i686-w64-mingw32-c++ CFLAGS = -std=c++98 -Wall -Wextra -mwindows -municode -DUNICODE -D_UNICODE -fno-exceptions -fno-rtti -gstabs LDFLAGS = -luser32 -lcomctl32 -lshell32 -lversion -static -out/widgetfactory.exe: out/widgetfactory.o out/alf.o +out/widgetfactory.exe: out/widgetfactory.o out/alfbutton.o out/alfcompat.o out/alf.o out/alfedit.o out/alflabel.o $(CXX) $(CFLAGS) -o $@ $^ $(LDFLAGS) -out/alf.o: alf/alf.cpp alf/alf.h +out/alfbutton.o: alf/alfbutton.cpp alf/alf.h alf/alflist.h alf/alfpriv.h + $(CXX) $(CFLAGS) -c -o $@ $< + +out/alfcompat.o: alf/alfcompat.cpp alf/alf.h alf/alflist.h alf/alfpriv.h + $(CXX) $(CFLAGS) -c -o $@ $< + +out/alf.o: alf/alf.cpp alf/alf.h alf/alflist.h alf/alfpriv.h + $(CXX) $(CFLAGS) -c -o $@ $< + +out/alfedit.o: alf/alfedit.cpp alf/alf.h alf/alflist.h alf/alfpriv.h + $(CXX) $(CFLAGS) -c -o $@ $< + +out/alflabel.o: alf/alflabel.cpp alf/alf.h alf/alflist.h alf/alfpriv.h $(CXX) $(CFLAGS) -c -o $@ $< out/widgetfactory.o: widgetfactory.cpp alf/alf.h @@ -13,3 +27,4 @@ out/widgetfactory.o: widgetfactory.cpp alf/alf.h clean: rm -f out/*.o out/*.exe + diff --git a/Makefile.vc6 b/Makefile.vc6 index b5d8940..1a0ba43 100644 --- a/Makefile.vc6 +++ b/Makefile.vc6 @@ -1,13 +1,30 @@ +# automatically created by makemakefile.sh. DO NOT EDIT! + CXX = cl.exe CFLAGS = -O2 -GA -W3 -DUNICODE -D_UNICODE -D_WIN32=0x0500 -D_WIN32_WINNT=0x0500 -D_WIN32_IE=0x0500 -nologo LDFLAGS = /link kernel32.lib user32.lib comctl32.lib shell32.lib gdi32.lib version.lib -out/widgetfactory.exe: out/widgetfactory.obj out/alf.obj +out/widgetfactory.exe: out/widgetfactory.obj out/alfbutton.obj out/alfcompat.obj out/alf.obj out/alfedit.obj out/alflabel.obj $(CXX) $(CFLAGS) -Fe$@ $** $(LDFLAGS) -out/alf.obj: alf/alf.cpp alf/alf.h +out/alfbutton.obj: alf/alfbutton.cpp alf/alf.h alf/alflist.h alf/alfpriv.h + $(CXX) $(CFLAGS) -c -Fo$@ alf/alfbutton.cpp + +out/alfcompat.obj: alf/alfcompat.cpp alf/alf.h alf/alflist.h alf/alfpriv.h + $(CXX) $(CFLAGS) -c -Fo$@ alf/alfcompat.cpp + +out/alf.obj: alf/alf.cpp alf/alf.h alf/alflist.h alf/alfpriv.h $(CXX) $(CFLAGS) -c -Fo$@ alf/alf.cpp +out/alfedit.obj: alf/alfedit.cpp alf/alf.h alf/alflist.h alf/alfpriv.h + $(CXX) $(CFLAGS) -c -Fo$@ alf/alfedit.cpp + +out/alflabel.obj: alf/alflabel.cpp alf/alf.h alf/alflist.h alf/alfpriv.h + $(CXX) $(CFLAGS) -c -Fo$@ alf/alflabel.cpp + out/widgetfactory.obj: widgetfactory.cpp alf/alf.h $(CXX) $(CFLAGS) -c -Fo$@ widgetfactory.cpp +clean: + del /f out\*.obj out\*.exe + diff --git a/alf/alf.cpp b/alf/alf.cpp index f4117e7..3bcde5b 100644 --- a/alf/alf.cpp +++ b/alf/alf.cpp @@ -1,112 +1,4 @@ -#include "alf.h" - -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -// MSVC6 for scoping hack -# define for if(0){}else for -#endif - -typedef struct ALFListHeader { - struct ALFListHeader *prev; - struct ALFListHeader *next; -} ALFListHeader; - -#define ALF_LIST_CONTAINER(ContainerType, containermember, listp) \ - ((ContainerType *)((char *)(listp) - offsetof(ContainerType, containermember))) - -#define ALF_FOR_LIST(ContainerType, containermember, listp, iteratorvar) \ - for (ALFListHeader *alf_list_##iteratorvar##_curr = (listp)->next, \ - *alf_list_##iteratorvar##_next = alf_list_##iteratorvar##_curr->next; \ - alf_list_##iteratorvar##_curr != (listp); \ - alf_list_##iteratorvar##_curr = alf_list_##iteratorvar##_next, \ - alf_list_##iteratorvar##_next = alf_list_##iteratorvar##_next->next) \ - for (ContainerType *iteratorvar = (ContainerType *)((char *)alf_list_##iteratorvar##_curr - offsetof(ContainerType, containermember)); \ - iteratorvar; iteratorvar = NULL) \ - - -static inline BOOL -ALF_ListIsEmpty(ALFListHeader *list) -{ - return list->next == list; -} - -static inline void -ALF_ListInsert(ALFListHeader *list, ALFListHeader *newel) -{ - newel->prev = list; - newel->next = list->next; - newel->next->prev = newel; - list->next = newel; -} - -static inline void -ALF_ListRemove(ALFListHeader *member) -{ - member->prev->next = member->next; - member->next->prev = member->prev; - member->next = NULL; - member->prev = NULL; -} - -static inline void -ALF_ListInit(ALFListHeader *list) -{ - list->next = list->prev = list; -} - -typedef struct { - ALFListHeader list; - HWND hwnd; - UINT x; - UINT y; - UINT cptWidth; - UINT cptHeight; - UINT cptMarginTop; - UINT cptMarginRight; - UINT cptMarginBottom; - UINT cptMarginLeft; - DWORD flags; -} ALFWidgetPriv; - -typedef struct { - int minWidth; - int allocatedWidth; - int allocatedPosition; - int expand : 1; -} ALFRowOrColumn; - -typedef struct { - ALFRowOrColumn *columns; - ALFRowOrColumn *rows; - int nColumns; - int nRows; - int totalMinWidth; - int totalMinHeight; - int occupiedColumnCount; - int occupiedRowCount; -} ALFLayout; - -typedef struct { - ALFAPP app; - ALFWindowVTable *vtbl; - void *closure; - ALFWindowFonts fonts; - ALFListHeader widgets; - int modalResult; - ALFLayout layout; - WORD defid; - HWND hwndFocus; -} ALFWindowPriv; - -struct ALFAppPriv { - HINSTANCE hInstance; - ALFCompatFunctions *compatFn; -}; +#include "alfpriv.h" /* ALF App and Window */ @@ -600,23 +492,7 @@ ALF_CreateApplication(HINSTANCE hInstance) InitCommonControlsEx(&icc); - ALFCompatFunctions *compatfn = (ALFCompatFunctions*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY|HEAP_GENERATE_EXCEPTIONS, sizeof(ALFCompatFunctions)); - -#define COMPAT(dll, entrypoint, ordinal) \ - do { \ - FARPROC p = GetProcAddress(GetModuleHandleA(#dll), #entrypoint); \ - if (!p && ordinal) \ - p = GetProcAddress(GetModuleHandleA(#dll), (char*)ordinal); \ - CopyMemory(&compatfn->entrypoint, &p, sizeof(void*)); \ - } while (0) - - COMPAT(comctl32.dll, SetWindowSubclass, 410); - COMPAT(comctl32.dll, DefSubclassProc, 413); - COMPAT(comctl32.dll, RemoveWindowSubclass, 412); - -#undef COMPAT - - app->compatFn = compatfn; + app->compatFn = ALF_CreateCompatFuncTable(); return app; } @@ -767,251 +643,3 @@ ALF_WidgetHwndById(HWND win, WORD id) return closure.result; } -/* LABEL */ - -static LRESULT CALLBACK -ALF__LabelSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) -{ - (void)uIdSubclass; - (void)dwRefData; - - ALFAPP app = (ALFAPP)dwRefData; - - if (uMsg == ALF_WM_QUERYSIZE) { - HDC hdcLabel = GetDC(hwnd); - HFONT font = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0); - HFONT oldFont = 0; - if (font) - oldFont = SelectFont(hdcLabel, font); - - // calc drawtext style - DWORD style = GetWindowLong(hwnd, GWL_STYLE); - UINT format = DT_LEFT | DT_EXPANDTABS | DT_CALCRECT; - if (style & SS_NOPREFIX) - format |= DT_NOPREFIX; - if (style & SS_EDITCONTROL) - format |= DT_EDITCONTROL; - if (style & SS_ENDELLIPSIS || style & SS_PATHELLIPSIS || style & SS_WORDELLIPSIS) - format |= DT_SINGLELINE; - - RECT r = { 0, 0, 100, 100 }; - - int textlen = GetWindowTextLength(hwnd); - TCHAR *textbuf = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY|HEAP_GENERATE_EXCEPTIONS, (textlen + 1)*sizeof(TCHAR)); - GetWindowText(hwnd, textbuf, textlen+1); - - DrawText(hdcLabel, textbuf, -1, &r, format); - - HeapFree(GetProcessHeap(), 0, textbuf); - - SIZE *pSize = (SIZE*)(void*)lParam; - if (pSize->cx == 0) - pSize->cx = r.right - r.left; - if (pSize->cy == 0) - pSize->cy = r.bottom - r.top; - - if (font) - SelectFont(hdcLabel, oldFont); - - ReleaseDC(hwnd, hdcLabel); - } - - return app->compatFn->DefSubclassProc(hwnd, uMsg, wParam, lParam); -} - -HWND -ALF_AddLabel(HWND win, WORD id, UINT x, UINT y, const WCHAR *text) -{ - HWND hwndLabel = CreateWindow(L"STATIC", - text, - WS_CHILD | WS_VISIBLE | SS_LEFTNOWORDWRAP, - 0, 0, 100, 100, - win, - (HMENU)(int)id, - (HINSTANCE)GetWindowLongPtr(win, GWLP_HINSTANCE), - NULL); - - ALFAPP app = ALF_ApplicationFromWindow(win); - app->compatFn->SetWindowSubclass(hwndLabel, ALF__LabelSubclassProc, 0, (DWORD_PTR)app); - - ALFAddWidgetParams p; - ZeroMemory(&p, sizeof(p)); - p.hwnd = hwndLabel; - p.x = x; - p.y = y; - p.width = 0; - p.height = 0; - p.flags = ALF_QUERYSIZE | ALF_MESSAGEFONT; - p.margins[0] = 300; // TODO: pixel perfect margins from system metrics - - ALF_AddWidgetEx(win, &p); - - return hwndLabel; -} - -/* EDIT */ -static LRESULT CALLBACK -ALF__EditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) -{ - (void)uIdSubclass; - (void)dwRefData; - - ALFAPP app = (ALFAPP)dwRefData; - - if (uMsg == ALF_WM_QUERYSIZE) { - HDC hDc = GetDC(hwnd); - HFONT font = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0); - - if (font) { - HFONT oldfont = SelectFont(hDc, font); - - TEXTMETRIC tm; - ZeroMemory(&tm, sizeof(tm)); - - if (GetTextMetrics(hDc, &tm)) { - SIZE *ps = (SIZE*)lParam; - if (!ps->cx) { - ps->cx = ALF_CentipointsToPixels(GetParent(hwnd), 12000); - } - - if (!ps->cy) { - ps->cy = tm.tmHeight + 6; // FIXME! use system metrics - } - } - - SelectFont(hDc, oldfont); - } - - ReleaseDC(hwnd, hDc); - return 0; - } - - return app->compatFn->DefSubclassProc(hwnd, uMsg, wParam, lParam); -} - -HWND -ALF_AddEdit(HWND win, WORD id, UINT x, UINT y, const WCHAR *text) -{ - HWND hwndEdit = CreateWindowEx(WS_EX_CLIENTEDGE, - L"EDIT", - text, - WS_CHILD | WS_VISIBLE | WS_TABSTOP, - 0, 0, 100, 100, - win, - (HMENU)(int)id, - (HINSTANCE)GetWindowLongPtr(win, GWLP_HINSTANCE), - NULL); - - ALFAPP app = ALF_ApplicationFromWindow(win); - - app->compatFn->SetWindowSubclass(hwndEdit, ALF__EditSubclassProc, 0, (DWORD_PTR)app); - SetWindowPos(hwndEdit, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED); - - ALFAddWidgetParams p; - ZeroMemory(&p, sizeof(p)); - p.hwnd = hwndEdit; - p.x = x; - p.y = y; - p.width = 0; - p.height = 0; - p.flags = ALF_QUERYSIZE | ALF_MESSAGEFONT; - p.margins[0] = 75; // TODO: pixel-perfect margin from system metrics - p.margins[2] = 75; - - ALF_AddWidgetEx(win, &p); - - return hwndEdit; -} - -/* BUTTON */ -static LRESULT CALLBACK -ALF__ButtonSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) -{ - (void)uIdSubclass; - (void)dwRefData; - - ALFAPP app = (ALFAPP)dwRefData; - - if (uMsg == ALF_WM_QUERYSIZE) { - HDC hdc = GetDC(hwnd); - HFONT font = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0); - HFONT oldFont = 0; - if (font) - oldFont = SelectFont(hdc, font); - - // calc drawtext style - DWORD style = GetWindowLong(hwnd, GWL_STYLE); - UINT format = DT_LEFT | DT_EXPANDTABS | DT_CALCRECT; - if ((style & BS_MULTILINE) == 0) - format |= DT_SINGLELINE; - - RECT r = { 0, 0, 100, 100 }; - - int textlen = GetWindowTextLength(hwnd); - TCHAR *textbuf = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY|HEAP_GENERATE_EXCEPTIONS, (textlen + 1)*sizeof(TCHAR)); - GetWindowText(hwnd, textbuf, textlen+1); - - DrawText(hdc, textbuf, -1, &r, format); - - HeapFree(GetProcessHeap(), 0, textbuf); - - // TODO: calculate from system metrics - int padding = ALF_CentipointsToPixels(GetParent(hwnd), 525); - - SIZE *pSize = (SIZE*)(void*)lParam; - if (pSize->cx < r.right - r.left + padding) { - pSize->cx = r.right - r.left + padding; - } - if (pSize->cy < r.bottom - r.top + padding) { - pSize->cy = r.bottom - r.top + padding; - } - if (pSize->cx < pSize->cy) { - pSize->cx = pSize->cy; - } - - if (font) - SelectFont(hdc, oldFont); - - ReleaseDC(hwnd, hdc); - } - - return app->compatFn->DefSubclassProc(hwnd, uMsg, wParam, lParam); -} - -HWND -ALF_AddButton(HWND win, WORD id, UINT x, UINT y, const WCHAR *text) -{ - HWND hwndButton = CreateWindowEx(0, - L"BUTTON", - text, - WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_PUSHBUTTON | BS_MULTILINE, - 0, 0, 100, 100, - win, - (HMENU)(int)id, - (HINSTANCE)GetWindowLongPtr(win, GWLP_HINSTANCE), - NULL); - - ALFAPP app = ALF_ApplicationFromWindow(win); - - app->compatFn->SetWindowSubclass(hwndButton, ALF__ButtonSubclassProc, 0, (DWORD_PTR)app); - - ALFAddWidgetParams p; - ZeroMemory(&p, sizeof(p)); - p.hwnd = hwndButton; - p.x = x; - p.y = y; - p.width = 5625; - p.height = 0; - p.flags = ALF_QUERYSIZE | ALF_MESSAGEFONT; - - ALF_AddWidgetEx(win, &p); - - return hwndButton; -} - - -void -ALF_SetDefaultButton(HWND win, WORD id) -{ - SendMessage(win, DM_SETDEFID, (WPARAM)id, 0); -} diff --git a/alf/alfbutton.cpp b/alf/alfbutton.cpp new file mode 100644 index 0000000..079da75 --- /dev/null +++ b/alf/alfbutton.cpp @@ -0,0 +1,95 @@ +#include "alfpriv.h" + +/* BUTTON */ +static LRESULT CALLBACK +ALF__ButtonSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) +{ + (void)uIdSubclass; + (void)dwRefData; + + ALFAPP app = (ALFAPP)dwRefData; + + if (uMsg == ALF_WM_QUERYSIZE) { + HDC hdc = GetDC(hwnd); + HFONT font = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0); + HFONT oldFont = 0; + if (font) + oldFont = SelectFont(hdc, font); + + // calc drawtext style + DWORD style = GetWindowLong(hwnd, GWL_STYLE); + UINT format = DT_LEFT | DT_EXPANDTABS | DT_CALCRECT; + if ((style & BS_MULTILINE) == 0) + format |= DT_SINGLELINE; + + RECT r = { 0, 0, 100, 100 }; + + int textlen = GetWindowTextLength(hwnd); + TCHAR *textbuf = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY|HEAP_GENERATE_EXCEPTIONS, (textlen + 1)*sizeof(TCHAR)); + GetWindowText(hwnd, textbuf, textlen+1); + + DrawText(hdc, textbuf, -1, &r, format); + + HeapFree(GetProcessHeap(), 0, textbuf); + + // TODO: calculate from system metrics + int padding = ALF_CentipointsToPixels(GetParent(hwnd), 525); + + SIZE *pSize = (SIZE*)(void*)lParam; + if (pSize->cx < r.right - r.left + padding) { + pSize->cx = r.right - r.left + padding; + } + if (pSize->cy < r.bottom - r.top + padding) { + pSize->cy = r.bottom - r.top + padding; + } + if (pSize->cx < pSize->cy) { + pSize->cx = pSize->cy; + } + + if (font) + SelectFont(hdc, oldFont); + + ReleaseDC(hwnd, hdc); + } + + return app->compatFn->DefSubclassProc(hwnd, uMsg, wParam, lParam); +} + +HWND +ALF_AddButton(HWND win, WORD id, UINT x, UINT y, const WCHAR *text) +{ + HWND hwndButton = CreateWindowEx(0, + L"BUTTON", + text, + WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_PUSHBUTTON | BS_MULTILINE, + 0, 0, 100, 100, + win, + (HMENU)(int)id, + (HINSTANCE)GetWindowLongPtr(win, GWLP_HINSTANCE), + NULL); + + ALFAPP app = ALF_ApplicationFromWindow(win); + + app->compatFn->SetWindowSubclass(hwndButton, ALF__ButtonSubclassProc, 0, (DWORD_PTR)app); + + ALFAddWidgetParams p; + ZeroMemory(&p, sizeof(p)); + p.hwnd = hwndButton; + p.x = x; + p.y = y; + p.width = 5625; + p.height = 0; + p.flags = ALF_QUERYSIZE | ALF_MESSAGEFONT; + + ALF_AddWidgetEx(win, &p); + + return hwndButton; +} + + +void +ALF_SetDefaultButton(HWND win, WORD id) +{ + SendMessage(win, DM_SETDEFID, (WPARAM)id, 0); +} + diff --git a/alf/alfcompat.cpp b/alf/alfcompat.cpp new file mode 100644 index 0000000..452b9bc --- /dev/null +++ b/alf/alfcompat.cpp @@ -0,0 +1,23 @@ +#include "alfpriv.h" + +ALFCompatFunctions * +ALF_CreateCompatFuncTable(void) +{ + ALFCompatFunctions *compatfn = (ALFCompatFunctions*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY|HEAP_GENERATE_EXCEPTIONS, sizeof(ALFCompatFunctions)); + +#define COMPAT(dll, entrypoint, ordinal) \ + do { \ + FARPROC p = GetProcAddress(GetModuleHandleA(#dll), #entrypoint); \ + if (!p && ordinal) \ + p = GetProcAddress(GetModuleHandleA(#dll), (char*)ordinal); \ + CopyMemory(&compatfn->entrypoint, &p, sizeof(void*)); \ + } while (0) + + COMPAT(comctl32.dll, SetWindowSubclass, 410); + COMPAT(comctl32.dll, DefSubclassProc, 413); + COMPAT(comctl32.dll, RemoveWindowSubclass, 412); + +#undef COMPAT + + return compatfn; +} diff --git a/alf/alfedit.cpp b/alf/alfedit.cpp new file mode 100644 index 0000000..65f14c8 --- /dev/null +++ b/alf/alfedit.cpp @@ -0,0 +1,76 @@ +#include "alfpriv.h" + +/* EDIT */ +static LRESULT CALLBACK +ALF__EditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) +{ + (void)uIdSubclass; + (void)dwRefData; + + ALFAPP app = (ALFAPP)dwRefData; + + if (uMsg == ALF_WM_QUERYSIZE) { + HDC hDc = GetDC(hwnd); + HFONT font = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0); + + if (font) { + HFONT oldfont = SelectFont(hDc, font); + + TEXTMETRIC tm; + ZeroMemory(&tm, sizeof(tm)); + + if (GetTextMetrics(hDc, &tm)) { + SIZE *ps = (SIZE*)lParam; + if (!ps->cx) { + ps->cx = ALF_CentipointsToPixels(GetParent(hwnd), 12000); + } + + if (!ps->cy) { + ps->cy = tm.tmHeight + 6; // FIXME! use system metrics + } + } + + SelectFont(hDc, oldfont); + } + + ReleaseDC(hwnd, hDc); + return 0; + } + + return app->compatFn->DefSubclassProc(hwnd, uMsg, wParam, lParam); +} + +HWND +ALF_AddEdit(HWND win, WORD id, UINT x, UINT y, const WCHAR *text) +{ + HWND hwndEdit = CreateWindowEx(WS_EX_CLIENTEDGE, + L"EDIT", + text, + WS_CHILD | WS_VISIBLE | WS_TABSTOP, + 0, 0, 100, 100, + win, + (HMENU)(int)id, + (HINSTANCE)GetWindowLongPtr(win, GWLP_HINSTANCE), + NULL); + + ALFAPP app = ALF_ApplicationFromWindow(win); + + app->compatFn->SetWindowSubclass(hwndEdit, ALF__EditSubclassProc, 0, (DWORD_PTR)app); + SetWindowPos(hwndEdit, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED); + + ALFAddWidgetParams p; + ZeroMemory(&p, sizeof(p)); + p.hwnd = hwndEdit; + p.x = x; + p.y = y; + p.width = 0; + p.height = 0; + p.flags = ALF_QUERYSIZE | ALF_MESSAGEFONT; + p.margins[0] = 75; // TODO: pixel-perfect margin from system metrics + p.margins[2] = 75; + + ALF_AddWidgetEx(win, &p); + + return hwndEdit; +} + diff --git a/alf/alflabel.cpp b/alf/alflabel.cpp new file mode 100644 index 0000000..e9ae550 --- /dev/null +++ b/alf/alflabel.cpp @@ -0,0 +1,83 @@ +#include "alfpriv.h" + +/* LABEL */ + +static LRESULT CALLBACK +ALF__LabelSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) +{ + (void)uIdSubclass; + (void)dwRefData; + + ALFAPP app = (ALFAPP)dwRefData; + + if (uMsg == ALF_WM_QUERYSIZE) { + HDC hdcLabel = GetDC(hwnd); + HFONT font = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0); + HFONT oldFont = 0; + if (font) + oldFont = SelectFont(hdcLabel, font); + + // calc drawtext style + DWORD style = GetWindowLong(hwnd, GWL_STYLE); + UINT format = DT_LEFT | DT_EXPANDTABS | DT_CALCRECT; + if (style & SS_NOPREFIX) + format |= DT_NOPREFIX; + if (style & SS_EDITCONTROL) + format |= DT_EDITCONTROL; + if (style & SS_ENDELLIPSIS || style & SS_PATHELLIPSIS || style & SS_WORDELLIPSIS) + format |= DT_SINGLELINE; + + RECT r = { 0, 0, 100, 100 }; + + int textlen = GetWindowTextLength(hwnd); + TCHAR *textbuf = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY|HEAP_GENERATE_EXCEPTIONS, (textlen + 1)*sizeof(TCHAR)); + GetWindowText(hwnd, textbuf, textlen+1); + + DrawText(hdcLabel, textbuf, -1, &r, format); + + HeapFree(GetProcessHeap(), 0, textbuf); + + SIZE *pSize = (SIZE*)(void*)lParam; + if (pSize->cx == 0) + pSize->cx = r.right - r.left; + if (pSize->cy == 0) + pSize->cy = r.bottom - r.top; + + if (font) + SelectFont(hdcLabel, oldFont); + + ReleaseDC(hwnd, hdcLabel); + } + + return app->compatFn->DefSubclassProc(hwnd, uMsg, wParam, lParam); +} + +HWND +ALF_AddLabel(HWND win, WORD id, UINT x, UINT y, const WCHAR *text) +{ + HWND hwndLabel = CreateWindow(L"STATIC", + text, + WS_CHILD | WS_VISIBLE | SS_LEFTNOWORDWRAP, + 0, 0, 100, 100, + win, + (HMENU)(int)id, + (HINSTANCE)GetWindowLongPtr(win, GWLP_HINSTANCE), + NULL); + + ALFAPP app = ALF_ApplicationFromWindow(win); + app->compatFn->SetWindowSubclass(hwndLabel, ALF__LabelSubclassProc, 0, (DWORD_PTR)app); + + ALFAddWidgetParams p; + ZeroMemory(&p, sizeof(p)); + p.hwnd = hwndLabel; + p.x = x; + p.y = y; + p.width = 0; + p.height = 0; + p.flags = ALF_QUERYSIZE | ALF_MESSAGEFONT; + p.margins[0] = 300; // TODO: pixel perfect margins from system metrics + + ALF_AddWidgetEx(win, &p); + + return hwndLabel; +} diff --git a/alf/alflist.h b/alf/alflist.h new file mode 100644 index 0000000..e0de033 --- /dev/null +++ b/alf/alflist.h @@ -0,0 +1,50 @@ + +typedef struct ALFListHeader { + struct ALFListHeader *prev; + struct ALFListHeader *next; +} ALFListHeader; + +#define ALF_LIST_CONTAINER(ContainerType, containermember, listp) \ + ((ContainerType *)((char *)(listp) - offsetof(ContainerType, containermember))) + +#define ALF_FOR_LIST(ContainerType, containermember, listp, iteratorvar) \ + for (ALFListHeader *alf_list_##iteratorvar##_curr = (listp)->next, \ + *alf_list_##iteratorvar##_next = alf_list_##iteratorvar##_curr->next; \ + alf_list_##iteratorvar##_curr != (listp); \ + alf_list_##iteratorvar##_curr = alf_list_##iteratorvar##_next, \ + alf_list_##iteratorvar##_next = alf_list_##iteratorvar##_next->next) \ + for (ContainerType *iteratorvar = (ContainerType *)((char *)alf_list_##iteratorvar##_curr - offsetof(ContainerType, containermember)); \ + iteratorvar; iteratorvar = NULL) \ + + +static inline BOOL +ALF_ListIsEmpty(ALFListHeader *list) +{ + return list->next == list; +} + +static inline void +ALF_ListInsert(ALFListHeader *list, ALFListHeader *newel) +{ + newel->prev = list; + newel->next = list->next; + newel->next->prev = newel; + list->next = newel; +} + +static inline void +ALF_ListRemove(ALFListHeader *member) +{ + member->prev->next = member->next; + member->next->prev = member->prev; + member->next = NULL; + member->prev = NULL; +} + +static inline void +ALF_ListInit(ALFListHeader *list) +{ + list->next = list->prev = list; +} + + diff --git a/alf/alfpriv.h b/alf/alfpriv.h new file mode 100644 index 0000000..08f3832 --- /dev/null +++ b/alf/alfpriv.h @@ -0,0 +1,67 @@ +#include "alf.h" + +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +// MSVC6 for scoping hack +# define for if(0){}else for +#endif + +#include "alflist.h" + +typedef struct { + ALFListHeader list; + HWND hwnd; + UINT x; + UINT y; + UINT cptWidth; + UINT cptHeight; + UINT cptMarginTop; + UINT cptMarginRight; + UINT cptMarginBottom; + UINT cptMarginLeft; + DWORD flags; +} ALFWidgetPriv; + +typedef struct { + int minWidth; + int allocatedWidth; + int allocatedPosition; + int expand : 1; +} ALFRowOrColumn; + +typedef struct { + ALFRowOrColumn *columns; + ALFRowOrColumn *rows; + int nColumns; + int nRows; + int totalMinWidth; + int totalMinHeight; + int occupiedColumnCount; + int occupiedRowCount; +} ALFLayout; + +typedef struct { + ALFAPP app; + ALFWindowVTable *vtbl; + void *closure; + ALFWindowFonts fonts; + ALFListHeader widgets; + int modalResult; + ALFLayout layout; + WORD defid; + HWND hwndFocus; +} ALFWindowPriv; + +struct ALFAppPriv { + HINSTANCE hInstance; + ALFCompatFunctions *compatFn; +}; + +ALFCompatFunctions * +ALF_CreateCompatFuncTable(void); + diff --git a/makemakefile.sh b/makemakefile.sh new file mode 100755 index 0000000..0851a60 --- /dev/null +++ b/makemakefile.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +cd "$(dirname "$(readlink -f "$0")")" + +ALF_HEADERS=$(cd alf; ls *.h) +ALF_SOURCES=$(cd alf; ls *.cpp) +ALF_MINGW_OBJECTS=$(for i in $ALF_SOURCES; do printf ' out/%s.o' "$(basename "$i" .cpp)"; done) +ALF_VC6_OBJECTS=$(for i in $ALF_SOURCES; do printf ' out/%s.obj' "$(basename "$i" .cpp)"; done) + +# mingw makefile +( + printf '# automatically created by makemakefile.sh. DO NOT EDIT!\n' + printf '\n' + printf 'CXX = i686-w64-mingw32-c++\n' + printf 'CFLAGS = -std=c++98 -Wall -Wextra -mwindows -municode -DUNICODE -D_UNICODE -fno-exceptions -fno-rtti -gstabs\n' + printf 'LDFLAGS = -luser32 -lcomctl32 -lshell32 -lversion -static\n' + printf '\n' + printf 'out/widgetfactory.exe: out/widgetfactory.o %s\n' "$ALF_MINGW_OBJECTS" + printf '\t$(CXX) $(CFLAGS) -o $@ $^ $(LDFLAGS)\n' + printf '\n' + for i in $ALF_SOURCES; do + printf 'out/%s: %s %s\n' "$(basename "$i" .cpp).o" "alf/$i" "$(for k in $ALF_HEADERS; do printf ' alf/%s' "$k"; done)" + printf '\t$(CXX) $(CFLAGS) -c -o $@ $<\n\n' + done + + printf 'out/widgetfactory.o: widgetfactory.cpp alf/alf.h\n' + printf '\t$(CXX) $(CFLAGS) -c -o $@ $<\n\n' + + printf 'clean:\n' + printf '\trm -f out/*.o out/*.exe\n\n' +) > Makefile.mingw + + +# vc6 makefile +( + printf '# automatically created by makemakefile.sh. DO NOT EDIT!\n' + printf '\n' + printf 'CXX = cl.exe\n' + printf 'CFLAGS = -O2 -GA -W3 -DUNICODE -D_UNICODE -D_WIN32=0x0500 -D_WIN32_WINNT=0x0500 -D_WIN32_IE=0x0500 -nologo\n' + printf 'LDFLAGS = /link kernel32.lib user32.lib comctl32.lib shell32.lib gdi32.lib version.lib\n' + + printf '\n' + printf 'out/widgetfactory.exe: out/widgetfactory.obj %s\n' "$ALF_VC6_OBJECTS" + printf '\t$(CXX) $(CFLAGS) -Fe$@ $** $(LDFLAGS)\n' + printf '\n' + for i in $ALF_SOURCES; do + printf 'out/%s: %s %s\n' "$(basename "$i" .cpp).obj" "alf/$i" "$(for k in $ALF_HEADERS; do printf ' alf/%s' "$k"; done)" + printf '\t$(CXX) $(CFLAGS) -c -Fo$@ %s\n\n' "alf/$i" + done + + printf 'out/widgetfactory.obj: widgetfactory.cpp alf/alf.h\n' + printf '\t$(CXX) $(CFLAGS) -c -Fo$@ widgetfactory.cpp\n\n' + + + printf 'clean:\n' + printf '\tdel /f out\\*.obj out\\*.exe\n\n' +) > Makefile.vc6 -- cgit v1.2.3