From c0cd20683af9e330e222bf2227a3a26eb6329527 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Fri, 29 May 2015 14:43:44 -0400 Subject: [PATCH] Changed the type system so that memory is allocated as-is. This means that uiControls are destroyed by controlBaseDestroy(). There's a system for specifying uiControl subclasses directly in the source code too. --- redo/objimpl/control.c | 9 +++-- redo/objimpl/types.c | 73 ++++++++++++++++++++++++++++++++++ redo/objimpl/ui.idl | 13 +++++- redo/objimpl/ui_windows.h | 2 +- redo/objimpl/uipriv.h | 5 ++- redo/objimpl/windows/control.c | 7 +++- 6 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 redo/objimpl/types.c diff --git a/redo/objimpl/control.c b/redo/objimpl/control.c index a7fdd9a6..4d71c0e5 100644 --- a/redo/objimpl/control.c +++ b/redo/objimpl/control.c @@ -18,7 +18,7 @@ static void controlBaseDestroy(uiControl *c) complain("attempt to destroy uiControl %p while it has a parent", c); uiControlCommitDestroy(c); uiFree(cb); - // TODO free c? + uiFree(c); } static uiControl *controlBaseParent(uiControl *c) @@ -119,9 +119,11 @@ static void controlBaseContainerUpdateState(uiControl *c) // by default not a container; do nothing } -void uiMakeControl(uiControl *c, uintmax_t type) +uiControl *uiNewControl(uintmax_t type) { - uiTyped(c)->Type = type; + uiControl *c; + + c = uiControl(newTyped(type)); uiControl(c)->Internal = uiNew(struct controlBase); uiControl(c)->Destroy = controlBaseDestroy; uiControl(c)->Parent = controlBaseParent; @@ -135,4 +137,5 @@ void uiMakeControl(uiControl *c, uintmax_t type) uiControl(c)->Disable = controlBaseDisable; uiControl(c)->UpdateState = controlBaseUpdateState; uiControl(c)->ContainerUpdateState = controlBaseContainerUpdateState; + return uiControl(c); } diff --git a/redo/objimpl/types.c b/redo/objimpl/types.c new file mode 100644 index 00000000..d7942fb8 --- /dev/null +++ b/redo/objimpl/types.c @@ -0,0 +1,73 @@ +// 17 may 2015 +#include "out/ui.h" +#include "uipriv.h" + +struct typeinfo { + const char *name; + uintmax_t parent; + size_t size; +}; + +static struct ptrArray *types = NULL; + +uintmax_t uiRegisterType(const char *name, uintmax_t parent, size_t size) +{ + struct typeinfo *ti; + + if (types == NULL) { + types = newPtrArray(); + // reserve ID 0 + ptrArrayAppend(types, NULL); + } + ti = uiNew(struct typeinfo); + ti->name = name; + ti->parent = parent; + ti->size = size; + ptrArrayAppend(types, ti); + return types->len - 1; +} + +void *uiIsA(void *p, uintmax_t id, int fail) +{ + uiTyped *t; + struct typeinfo *ti, *ti2; + uintmax_t compareTo; + + if (id == 0 || id >= types->len) + complain("invalid type ID given to uiIsA()"); + t = (uiTyped *) p; + compareTo = t->Type; + if (compareTo == 0) + complain("object %p has no type in uiIsA()", t); + for (;;) { + if (compareTo >= types->len) + complain("invalid type ID in uiIsA()", t); + if (compareTo == id) + return t; + ti = ptrArrayIndex(types, struct typeinfo *, compareTo); + if (ti->parent == 0) + break; + compareTo = ti->parent; + } + if (fail) { + ti = ptrArrayIndex(types, struct typeinfo *, id); + ti2 = ptrArrayIndex(types, struct typeinfo *, t->Type); + complain("object %p not a %s in uiIsA() (is a %s)", t, ti->name, ti2->name); + } + return NULL; +} + +// TODO free type info + +uiTyped *newTyped(uintmax_t type) +{ + struct typeinfo *ti; + uiTyped *instance; + + if (type == 0 || id >= types->len) + complain("invalid type ID given to newTyped()"); + ti = ptrArrayIndex(types, struct typeinfo *, type); + instance = (uiTyped *) uiAlloc(ti->size, ti->name); + instance->Type = type; + return instance; +} diff --git a/redo/objimpl/ui.idl b/redo/objimpl/ui.idl index e9e6ff0e..944ba400 100644 --- a/redo/objimpl/ui.idl +++ b/redo/objimpl/ui.idl @@ -28,7 +28,7 @@ func OnShouldQuit(f *func(data *void) int, data *void); func FreeText(text *char); -func RegisterType(name *const char, parent uintmax_t) uintmax_t; +func RegisterType(name *const char, parent uintmax_t, size size_t) uintmax_t; func IsA(p *void, type uintmax_t, fail int) *void; struct Typed { field Type uintmax_t; @@ -74,6 +74,17 @@ interface Control { func ContainerUpdateState(void); }; +func NewControl(type uintmax_t) *Control; + +raw "#define uiDefineControlType(typename, funcname, realtype) \"; +raw " static uintmax_t type_ ## typename = 0; \"; +raw " uintmax_t funcname(void) \"; +raw " { \"; +raw " if (type_ ## typename == 0) \"; +raw " type_ ## typename = uiRegisterType(#typename, uiTypeControl(), sizeof (realtype)); \"; +raw " return type_ ## typename; \"; +raw " }"; + func FreeSizing(d *Sizing); func MakeContainer(c *Control); diff --git a/redo/objimpl/ui_windows.h b/redo/objimpl/ui_windows.h index 3d1c14a7..309d1b68 100644 --- a/redo/objimpl/ui_windows.h +++ b/redo/objimpl/ui_windows.h @@ -18,7 +18,7 @@ _UI_EXTERN void uiWIndowsUtilEnable(HWND hwnd); _UI_EXTERN void uiWindowsUtilDisable(HWND hwnd); _UI_EXTERN void uiWindowsUtilSysFunc(HWND hwnd, uiControlSysFuncParams *p); _UI_EXTERN void uiWindowsUtilStartZOrder(HWND hwnd, uiControlSysFuncParams *p); -_UI_EXTERN void uiWindowsMakeSingleHWNDControl(uiControl *c, uintmax_t type); +_UI_EXTERN uiControl *uiWindowsNewSingleHWNDControl(uintmax_t type); // This contains the Windows-specific parts of the uiSizing structure. // BaseX and BaseY are the dialog base units. diff --git a/redo/objimpl/uipriv.h b/redo/objimpl/uipriv.h index 3601d611..0eddbec0 100644 --- a/redo/objimpl/uipriv.h +++ b/redo/objimpl/uipriv.h @@ -31,4 +31,7 @@ void ptrArrayDelete(struct ptrArray *, uintmax_t); #define ptrArrayIndex(p, T, i) ((T) ((p)->ptrs[(i)])) // shouldquit.c -int shouldQuit(void); +extern int shouldQuit(void); + +// types.c +extern uiTyped *newTyped(uintmax_t type); diff --git a/redo/objimpl/windows/control.c b/redo/objimpl/windows/control.c index 7b45d0ee..118cf1db 100644 --- a/redo/objimpl/windows/control.c +++ b/redo/objimpl/windows/control.c @@ -144,9 +144,11 @@ static void singleHWNDStartZOrder(uiControl *c, uiControlSysFuncParams *p) uiWindowsUtilStartZOrder(HWND(c), p); } -void uiWindowsMakeSingleHWNDControl(uiControl *c, uintmax_t type) +uiControl *uiWindowsNewSingleHWNDControl(uintmax_t type) { - uiMakeControl(c, type); + uiControl *c; + + c = uiNewControl(type); uiControl(c)->CommitDestroy = singleHWNDCommitDestroy; uiControl(c)->CommitSetParent = singleHWNDCommitSetParent; uiControl(c)->Resize = singleHWNDResize; @@ -157,4 +159,5 @@ void uiWindowsMakeSingleHWNDControl(uiControl *c, uintmax_t type) uiControl(c)->CommitDisable = singleHWNDCommitDisable; uiControl(c)->SysFunc = singleHWNDSysFunc; uiControl(c)->StartZOrder = singleHWNDStartZOrder; + return c; }