More rewriting imports. Also moved ui.h to out/.
This commit is contained in:
parent
b98de32786
commit
06cad86f55
|
@ -0,0 +1,63 @@
|
|||
# 22 april 2015
|
||||
|
||||
OUTBASE = new
|
||||
OUTDIR = out
|
||||
OBJDIR = .obj
|
||||
|
||||
IDLFILES = \
|
||||
ui.idl \
|
||||
$(baseIDLFILES)
|
||||
|
||||
xHFILES = \
|
||||
uipriv.h \
|
||||
$(IDLFILES:%.idl=$(OUTDIR)/%.h) \
|
||||
$(baseHFILES)
|
||||
|
||||
OFILES = \
|
||||
$(baseCFILES:%.c=$(OBJDIR)/%.o) \
|
||||
$(baseMFILES:%.m=$(OBJDIR)/%.o)
|
||||
|
||||
xCFLAGS = \
|
||||
-g \
|
||||
-Wall -Wextra \
|
||||
-Wno-unused-parameter \
|
||||
-Wno-switch \
|
||||
--std=c99 \
|
||||
$(CFLAGS) \
|
||||
$(archmflag) \
|
||||
$(baseCFLAGS)
|
||||
|
||||
xLDFLAGS = \
|
||||
-g \
|
||||
$(LDFLAGS) \
|
||||
$(archmflag) \
|
||||
$(baseLDFLAGS)
|
||||
|
||||
OUT = $(OUTDIR)/$(OUTBASE)$(baseSUFFIX)
|
||||
|
||||
$(OUT): $(OFILES) | $(OUTDIR)/.phony
|
||||
@$(CC) -o $(OUT) $(OFILES) $(xLDFLAGS)
|
||||
@echo ====== Linked $(OUT)
|
||||
|
||||
.SECONDEXPANSION:
|
||||
$(OBJDIR)/%.o: %.c $(xHFILES) | $$(dir $$@).phony
|
||||
@$(CC) -o $@ -c $< $(xCFLAGS)
|
||||
@echo ====== Compiled $<
|
||||
|
||||
$(OBJDIR)/%.o: %.m $(xHFILES) | $$(dir $$@).phony
|
||||
@$(CC) -o $@ -c $< $(xCFLAGS)
|
||||
@echo ====== Compiled $<
|
||||
|
||||
# see http://www.cmcrossroads.com/article/making-directories-gnu-make
|
||||
%/.phony:
|
||||
@mkdir -p $(dir $@)
|
||||
@touch $@
|
||||
.PRECIOUS: %/.phony
|
||||
|
||||
$(OUTDIR)/%.h: %.idl tools/idl2h.go | $(OUTDIR)/.phony
|
||||
@go run tools/idl2h.go -extern _UI_EXTERN -guard __UI_UI_H__ < $< > $@
|
||||
@echo ====== Generated `basename $@`
|
||||
|
||||
clean:
|
||||
rm -rf $(OUTDIR) $(OBJDIR) ui.h
|
||||
.PHONY: clean
|
|
@ -0,0 +1,46 @@
|
|||
# 22 april 2015
|
||||
|
||||
# MAME does this so :/
|
||||
ifeq ($(OS),Windows_NT)
|
||||
OS = windows
|
||||
endif
|
||||
|
||||
ifndef OS
|
||||
UNAME = $(shell uname -s)
|
||||
ifeq ($(UNAME),Darwin)
|
||||
OS = darwin
|
||||
else
|
||||
OS = unix
|
||||
endif
|
||||
endif
|
||||
|
||||
include $(OS)/GNUmakeinc.mk
|
||||
|
||||
#baseIDLFILES = \
|
||||
# ui_$(OS).idl
|
||||
|
||||
baseHFILES = \
|
||||
uipriv.h \
|
||||
ui_$(OS).h \
|
||||
$(osHFILES)
|
||||
|
||||
baseCFILES = \
|
||||
box.c \
|
||||
ptrarray.c \
|
||||
shouldquit.c \
|
||||
$(osCFILES)
|
||||
|
||||
baseMFILES = $(osMFILES)
|
||||
|
||||
baseCFLAGS = $(osCFLAGS)
|
||||
baseLDFLAGS = \
|
||||
-shared \
|
||||
$(osLDWarnUndefinedFlags) \
|
||||
$(osLDFLAGS)
|
||||
baseSUFFIX = $(osLIBSUFFIX)
|
||||
|
||||
include GNUbase.mk
|
||||
|
||||
test: $(OUT)
|
||||
@$(MAKE) -f GNUmaketest.mk osLIB=$(OUT) osEXESUFFIX=$(osEXESUFFIX) CC=$(CC) archmflag=$(archmflag)
|
||||
.PHONY: test
|
|
@ -0,0 +1,16 @@
|
|||
# 22 april 2015
|
||||
# should never be invoked directly, only ever from the main makefile
|
||||
|
||||
include test/GNUmakeinc.mk
|
||||
|
||||
baseHFILES = \
|
||||
ui.h \
|
||||
$(testHFILES)
|
||||
|
||||
baseCFILES = $(testCFILES)
|
||||
|
||||
baseCFLAGS = $(testCFLAGS)
|
||||
baseLDFLAGS = $(osLIB) $(testLDFLAGS)
|
||||
baseSUFFIX = $(osEXESUFFIX)
|
||||
|
||||
include GNUbase.mk
|
|
@ -0,0 +1,296 @@
|
|||
// 7 april 2015
|
||||
#include "out/ui.h"
|
||||
#include "uipriv.h"
|
||||
|
||||
struct box {
|
||||
uiBox b;
|
||||
void (*baseDestroy)(uiControl *);
|
||||
struct ptrArray *controls;
|
||||
int vertical;
|
||||
void (*baseSetParent)(uiControl *, uiContainer *);
|
||||
uiContainer *parent;
|
||||
int padded;
|
||||
};
|
||||
|
||||
struct boxControl {
|
||||
uiControl *c;
|
||||
int stretchy;
|
||||
intmax_t width; // both used by resize(); preallocated to save time and reduce risk of failure
|
||||
intmax_t height;
|
||||
};
|
||||
|
||||
static void boxDestroy(uiControl *c)
|
||||
{
|
||||
struct box *b = (struct box *) c;
|
||||
struct boxControl *bc;
|
||||
|
||||
if (b->parent != NULL)
|
||||
complain("attempt to destroy uiBox %p while it has a parent", b);
|
||||
// don't chain up to base here; we need to destroy children ourselves first
|
||||
while (b->controls->len != 0) {
|
||||
bc = ptrArrayIndex(b->controls, struct boxControl *, 0);
|
||||
uiControlSetParent(bc->c, NULL);
|
||||
uiControlDestroy(bc->c);
|
||||
ptrArrayDelete(b->controls, 0);
|
||||
uiFree(bc);
|
||||
}
|
||||
ptrArrayDestroy(b->controls);
|
||||
// NOW we can chain up to base
|
||||
(*(b->baseDestroy))(uiControl(b));
|
||||
uiFree(b);
|
||||
}
|
||||
|
||||
static void boxSetParent(uiControl *c, uiContainer *parent)
|
||||
{
|
||||
struct box *b = (struct box *) c;
|
||||
|
||||
// this does all the actual work
|
||||
(*(b->baseSetParent))(uiControl(b), parent);
|
||||
// we just need to have a copy of the parent ourselves for boxSetPadded()
|
||||
b->parent = parent;
|
||||
}
|
||||
|
||||
static void boxPreferredSize(uiControl *c, uiSizing *d, intmax_t *width, intmax_t *height)
|
||||
{
|
||||
struct box *b = (struct box *) c;
|
||||
struct boxControl *bc;
|
||||
int xpadding, ypadding;
|
||||
uintmax_t nStretchy;
|
||||
// these two contain the largest preferred width and height of all stretchy controls in the box
|
||||
// all stretchy controls will use this value to determine the final preferred size
|
||||
intmax_t maxStretchyWidth, maxStretchyHeight;
|
||||
uintmax_t i;
|
||||
intmax_t preferredWidth, preferredHeight;
|
||||
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
if (b->controls->len == 0)
|
||||
return;
|
||||
|
||||
// 0) get this Box's padding
|
||||
xpadding = 0;
|
||||
ypadding = 0;
|
||||
if (b->padded) {
|
||||
xpadding = d->XPadding;
|
||||
ypadding = d->YPadding;
|
||||
}
|
||||
|
||||
// 1) initialize the desired rect with the needed padding
|
||||
// TODO this is wrong if any controls are hidden
|
||||
if (b->vertical)
|
||||
*height = (b->controls->len - 1) * ypadding;
|
||||
else
|
||||
*width = (b->controls->len - 1) * xpadding;
|
||||
|
||||
// 2) add in the size of non-stretchy controls and get (but not add in) the largest widths and heights of stretchy controls
|
||||
// we still add in like direction of stretchy controls
|
||||
nStretchy = 0;
|
||||
maxStretchyWidth = 0;
|
||||
maxStretchyHeight = 0;
|
||||
for (i = 0; i < b->controls->len; i++) {
|
||||
bc = ptrArrayIndex(b->controls, struct boxControl *, i);
|
||||
if (!uiControlVisible(bc->c))
|
||||
continue;
|
||||
uiControlPreferredSize(bc->c, d, &preferredWidth, &preferredHeight);
|
||||
if (bc->stretchy) {
|
||||
nStretchy++;
|
||||
if (maxStretchyWidth < preferredWidth)
|
||||
maxStretchyWidth = preferredWidth;
|
||||
if (maxStretchyHeight < preferredHeight)
|
||||
maxStretchyHeight = preferredHeight;
|
||||
}
|
||||
if (b->vertical) {
|
||||
if (*width < preferredWidth)
|
||||
*width = preferredWidth;
|
||||
if (!bc->stretchy)
|
||||
*height += preferredHeight;
|
||||
} else {
|
||||
if (!bc->stretchy)
|
||||
*width += preferredWidth;
|
||||
if (*height < preferredHeight)
|
||||
*height = preferredHeight;
|
||||
}
|
||||
}
|
||||
|
||||
// 3) and now we can add in stretchy controls
|
||||
if (b->vertical)
|
||||
*height += nStretchy * maxStretchyHeight;
|
||||
else
|
||||
*width += nStretchy * maxStretchyWidth;
|
||||
}
|
||||
|
||||
static void boxSysFunc(uiControl *c, uiControlSysFuncParams *p)
|
||||
{
|
||||
struct box *b = (struct box *) c;
|
||||
struct boxControl *bc;
|
||||
uintmax_t i;
|
||||
|
||||
for (i = 0; i < b->controls->len; i++) {
|
||||
bc = ptrArrayIndex(b->controls, struct boxControl *, i);
|
||||
uiControlSysFunc(bc->c, p);
|
||||
}
|
||||
}
|
||||
|
||||
static void boxResizeChildren(uiContainer *c, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d)
|
||||
{
|
||||
struct box *b = (struct box *) c;
|
||||
struct boxControl *bc;
|
||||
int xpadding, ypadding;
|
||||
uintmax_t nStretchy;
|
||||
intmax_t stretchywid, stretchyht;
|
||||
uintmax_t i;
|
||||
intmax_t preferredWidth, preferredHeight;
|
||||
|
||||
if (b->controls->len == 0)
|
||||
return;
|
||||
|
||||
// -1) get this Box's padding
|
||||
xpadding = 0;
|
||||
ypadding = 0;
|
||||
if (b->padded) {
|
||||
xpadding = d->XPadding;
|
||||
ypadding = d->YPadding;
|
||||
}
|
||||
|
||||
// 0) inset the available rect by the needed padding
|
||||
// TODO this is incorrect if any controls are hidden
|
||||
if (b->vertical)
|
||||
height -= (b->controls->len - 1) * ypadding;
|
||||
else
|
||||
width -= (b->controls->len - 1) * xpadding;
|
||||
|
||||
// 1) get width and height of non-stretchy controls
|
||||
// this will tell us how much space will be left for stretchy controls
|
||||
stretchywid = width;
|
||||
stretchyht = height;
|
||||
nStretchy = 0;
|
||||
for (i = 0; i < b->controls->len; i++) {
|
||||
bc = ptrArrayIndex(b->controls, struct boxControl *, i);
|
||||
if (!uiControlVisible(bc->c))
|
||||
continue;
|
||||
if (bc->stretchy) {
|
||||
nStretchy++;
|
||||
continue;
|
||||
}
|
||||
uiControlPreferredSize(bc->c, d, &preferredWidth, &preferredHeight);
|
||||
if (b->vertical) { // all controls have same width
|
||||
bc->width = width;
|
||||
bc->height = preferredHeight;
|
||||
stretchyht -= preferredHeight;
|
||||
} else { // all controls have same height
|
||||
bc->width = preferredWidth;
|
||||
bc->height = height;
|
||||
stretchywid -= preferredWidth;
|
||||
}
|
||||
}
|
||||
|
||||
// 2) now get the size of stretchy controls
|
||||
if (nStretchy != 0)
|
||||
if (b->vertical)
|
||||
stretchyht /= nStretchy;
|
||||
else
|
||||
stretchywid /= nStretchy;
|
||||
for (i = 0; i < b->controls->len; i++) {
|
||||
bc = ptrArrayIndex(b->controls, struct boxControl *, i);
|
||||
if (!uiControlVisible(bc->c))
|
||||
continue;
|
||||
if (bc->stretchy) {
|
||||
bc->width = stretchywid;
|
||||
bc->height = stretchyht;
|
||||
}
|
||||
}
|
||||
|
||||
// 3) now we can position controls
|
||||
for (i = 0; i < b->controls->len; i++) {
|
||||
bc = ptrArrayIndex(b->controls, struct boxControl *, i);
|
||||
if (!uiControlVisible(bc->c))
|
||||
continue;
|
||||
uiControlResize(bc->c, x, y, bc->width, bc->height, d);
|
||||
if (b->vertical)
|
||||
y += bc->height + ypadding;
|
||||
else
|
||||
x += bc->width + xpadding;
|
||||
}
|
||||
}
|
||||
|
||||
static void boxAppend(uiBox *ss, uiControl *c, int stretchy)
|
||||
{
|
||||
struct box *b = (struct box *) ss;
|
||||
struct boxControl *bc;
|
||||
|
||||
bc = uiNew(struct boxControl);
|
||||
bc->c = c;
|
||||
bc->stretchy = stretchy;
|
||||
uiControlSetParent(bc->c, uiContainer(b));
|
||||
ptrArrayAppend(b->controls, bc);
|
||||
uiContainerUpdate(uiContainer(b));
|
||||
}
|
||||
|
||||
static void boxDelete(uiBox *ss, uintmax_t index)
|
||||
{
|
||||
struct box *b = (struct box *) ss;
|
||||
struct boxControl *bc;
|
||||
uiControl *removed;
|
||||
|
||||
// TODO rearrange this
|
||||
// TODO sync call order with that of Destroy()
|
||||
bc = ptrArrayIndex(b->controls, struct boxControl *, index);
|
||||
removed = bc->c;
|
||||
ptrArrayDelete(b->controls, index);
|
||||
uiControlSetParent(removed, NULL);
|
||||
uiFree(bc);
|
||||
uiContainerUpdate(uiContainer(b));
|
||||
}
|
||||
|
||||
static int boxPadded(uiBox *ss)
|
||||
{
|
||||
struct box *b = (struct box *) ss;
|
||||
|
||||
return b->padded;
|
||||
}
|
||||
|
||||
static void boxSetPadded(uiBox *ss, int padded)
|
||||
{
|
||||
struct box *b = (struct box *) ss;
|
||||
|
||||
b->padded = padded;
|
||||
uiContainerUpdate(uiContainer(b));
|
||||
}
|
||||
|
||||
uiBox *uiNewHorizontalBox(void)
|
||||
{
|
||||
struct box *b;
|
||||
|
||||
b = uiNew(struct box);
|
||||
|
||||
uiMakeContainer(uiContainer(b));
|
||||
|
||||
b->controls = newPtrArray();
|
||||
|
||||
b->baseDestroy = uiControl(b)->Destroy;
|
||||
uiControl(b)->Destroy = boxDestroy;
|
||||
b->baseSetParent = uiControl(b)->SetParent;
|
||||
uiControl(b)->SetParent = boxSetParent;
|
||||
uiControl(b)->PreferredSize = boxPreferredSize;
|
||||
uiControl(b)->SysFunc = boxSysFunc;
|
||||
|
||||
uiContainer(b)->ResizeChildren = boxResizeChildren;
|
||||
|
||||
uiBox(b)->Append = boxAppend;
|
||||
uiBox(b)->Delete = boxDelete;
|
||||
uiBox(b)->Padded = boxPadded;
|
||||
uiBox(b)->SetPadded = boxSetPadded;
|
||||
|
||||
return uiBox(b);
|
||||
}
|
||||
|
||||
uiBox *uiNewVerticalBox(void)
|
||||
{
|
||||
uiBox *bb;
|
||||
struct box *b;
|
||||
|
||||
bb = uiNewHorizontalBox();
|
||||
b = (struct box *) bb;
|
||||
b->vertical = 1;
|
||||
return bb;
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
// 5 may 2015
|
||||
#include <string.h>
|
||||
#include "out/ui.h"
|
||||
#include "uipriv.h"
|
||||
|
||||
struct ptrArray *newPtrArray(void)
|
||||
{
|
||||
return uiNew(struct ptrArray);
|
||||
}
|
||||
|
||||
void ptrArrayDestroy(struct ptrArray *p)
|
||||
{
|
||||
if (p->len != 0)
|
||||
complain("attempt to destroy ptrarray %p while it still has pointers inside", p);
|
||||
if (p->ptrs != NULL) // array was created but nothing was ever put inside
|
||||
uiFree(p->ptrs);
|
||||
uiFree(p);
|
||||
}
|
||||
|
||||
#define grow 32
|
||||
|
||||
void ptrArrayAppend(struct ptrArray *p, void *d)
|
||||
{
|
||||
if (p->len >= p->cap) {
|
||||
p->cap += grow;
|
||||
p->ptrs = (void **) uiRealloc(p->ptrs, p->cap * sizeof (void *), "void *[]");
|
||||
}
|
||||
p->ptrs[p->len] = d;
|
||||
p->len++;
|
||||
}
|
||||
|
||||
void ptrArrayInsertBefore(struct ptrArray *p, uintmax_t i, void *d)
|
||||
{
|
||||
if (i >= p->len)
|
||||
complain("index out of range in ptrArrayInsertBefore()");
|
||||
if (p->len >= p->cap) {
|
||||
p->cap += grow;
|
||||
p->ptrs = (void **) uiRealloc(p->ptrs, p->cap * sizeof (void *), "void *[]");
|
||||
}
|
||||
// thanks to ValleyBell
|
||||
memmove(&(p->ptrs[i + 1]), &(p->ptrs[i]), (p->len - i) * sizeof (void *));
|
||||
p->ptrs[i] = d;
|
||||
p->len++;
|
||||
}
|
||||
|
||||
void ptrArrayDelete(struct ptrArray *p, uintmax_t i)
|
||||
{
|
||||
if (i >= p->len)
|
||||
complain("index out of range in ptrArrayRemove()");
|
||||
// thanks to ValleyBell
|
||||
memmove(&(p->ptrs[i]), &(p->ptrs[i + 1]), (p->len - i - 1) * sizeof (void *));
|
||||
p->ptrs[p->len - 1] = NULL;
|
||||
p->len--;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// 9 may 2015
|
||||
#include "out/ui.h"
|
||||
#include "uipriv.h"
|
||||
|
||||
static int defaultOnShouldQuit(void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int (*onShouldQuit)(void *) = defaultOnShouldQuit;
|
||||
static void *onShouldQuitData;
|
||||
|
||||
void uiOnShouldQuit(int (*f)(void *), void *data)
|
||||
{
|
||||
onShouldQuit = f;
|
||||
onShouldQuitData = data;
|
||||
}
|
||||
|
||||
int shouldQuit(void)
|
||||
{
|
||||
return (*onShouldQuit)(onShouldQuitData);
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
// 15 april 2015
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"flag"
|
||||
"github.com/andlabs/pgidl"
|
||||
)
|
||||
|
||||
var extern = flag.String("extern", "extern", "name for extern")
|
||||
var guard = flag.String("guard", "", "#define name for include guards")
|
||||
|
||||
var pkgtypes = map[string]string{}
|
||||
|
||||
func typedecl(t *pgidl.Type, name string) string {
|
||||
if t == nil {
|
||||
return "void " + name
|
||||
}
|
||||
if t.IsFuncPtr {
|
||||
return cfuncptrdecl(t.FuncType, name)
|
||||
}
|
||||
s := t.Name + " "
|
||||
if pkgtypes[t.Name] != "" {
|
||||
s = pkgtypes[t.Name] + " "
|
||||
}
|
||||
for i := uint(0); i < t.NumPtrs; i++ {
|
||||
s += "*"
|
||||
}
|
||||
return s + name
|
||||
}
|
||||
|
||||
func arglist(a []*pgidl.Arg) string {
|
||||
if len(a) == 0 {
|
||||
return "void"
|
||||
}
|
||||
s := typedecl(a[0].Type, a[0].Name)
|
||||
for i := 1; i < len(a); i++ {
|
||||
s += ", " + typedecl(a[i].Type, a[i].Name)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func cfuncdecl(f *pgidl.Func, name string) string {
|
||||
fd := name + "(" + arglist(f.Args) + ")"
|
||||
return *extern + " " + typedecl(f.Ret, fd) + ";"
|
||||
}
|
||||
|
||||
func cfuncptrdecl(f *pgidl.Func, name string) string {
|
||||
name = "(*" + name + ")"
|
||||
fd := name + "(" + arglist(f.Args) + ")"
|
||||
return typedecl(f.Ret, fd)
|
||||
}
|
||||
|
||||
func cmethodmacro(f *pgidl.Func, typename string) string {
|
||||
s := "#define " + typename + f.Name + "("
|
||||
first := true
|
||||
for _, a := range f.Args {
|
||||
if !first {
|
||||
s += ", "
|
||||
}
|
||||
s += a.Name
|
||||
first = false
|
||||
}
|
||||
s += ") ("
|
||||
s += "(*((this)->" + f.Name + "))"
|
||||
s += "("
|
||||
first = true
|
||||
for _, a := range f.Args {
|
||||
if !first {
|
||||
s += ", "
|
||||
}
|
||||
s += "(" + a.Name + ")"
|
||||
first = false
|
||||
}
|
||||
s += ")"
|
||||
s += ")"
|
||||
return s
|
||||
}
|
||||
|
||||
func genpkgfunc(f *pgidl.Func, prefix string) {
|
||||
fmt.Printf("%s\n", cfuncdecl(f, prefix + f.Name))
|
||||
}
|
||||
|
||||
func genstruct(s *pgidl.Struct, prefix string) {
|
||||
fmt.Printf("struct %s%s {\n", prefix, s.Name)
|
||||
for _, f := range s.Fields {
|
||||
fmt.Printf("\t%s;\n", typedecl(f.Type, f.Name))
|
||||
}
|
||||
fmt.Printf("};\n")
|
||||
}
|
||||
|
||||
func geniface(i *pgidl.Interface, prefix string) {
|
||||
fmt.Printf("struct %s%s {\n", prefix, i.Name)
|
||||
if i.From != "" {
|
||||
fmt.Printf("\t%s%s base;\n", prefix, i.From)
|
||||
}
|
||||
for _, f := range i.Fields {
|
||||
fmt.Printf("\t%s;\n", typedecl(f.Type, f.Name))
|
||||
}
|
||||
for _, m := range i.Methods {
|
||||
// hack our this pointer in
|
||||
m.Args = append([]*pgidl.Arg{
|
||||
&pgidl.Arg{
|
||||
Name: "this",
|
||||
Type: &pgidl.Type{
|
||||
Name: prefix + i.Name,
|
||||
NumPtrs: 1,
|
||||
},
|
||||
},
|
||||
}, m.Args...)
|
||||
fmt.Printf("\t%s;\n", cfuncptrdecl(m, m.Name))
|
||||
fmt.Printf("%s\n", cmethodmacro(m, prefix + i.Name))
|
||||
}
|
||||
fmt.Printf("};\n")
|
||||
fmt.Printf("#define %s%s(this) ((%s%s *) (this))\n",
|
||||
prefix, i.Name,
|
||||
prefix, i.Name)
|
||||
}
|
||||
|
||||
func genenum(e *pgidl.Enum, prefix string) {
|
||||
fmt.Printf("enum %s%s {\n", prefix, e.Name)
|
||||
for _, m := range e.Members {
|
||||
fmt.Printf("\t%s%s%s,\n", prefix, e.Name, m)
|
||||
}
|
||||
fmt.Printf("};\n")
|
||||
}
|
||||
|
||||
func genpkg(p *pgidl.Package) {
|
||||
for _, s := range p.Structs {
|
||||
fmt.Printf("typedef struct %s%s %s%s;\n",
|
||||
p.Name, s.Name,
|
||||
p.Name, s.Name)
|
||||
pkgtypes[s.Name] = p.Name + s.Name
|
||||
}
|
||||
for _, i := range p.Interfaces {
|
||||
fmt.Printf("typedef struct %s%s %s%s;\n",
|
||||
p.Name, i.Name,
|
||||
p.Name, i.Name)
|
||||
pkgtypes[i.Name] = p.Name + i.Name
|
||||
}
|
||||
for _, e := range p.Enums {
|
||||
fmt.Printf("typedef enum %s%s %s%s;\n",
|
||||
p.Name, e.Name,
|
||||
p.Name, e.Name)
|
||||
pkgtypes[e.Name] = p.Name + e.Name
|
||||
}
|
||||
// apparently we have to fully define C enumerations before we can use them...
|
||||
for _, e := range p.Enums {
|
||||
genenum(e, p.Name)
|
||||
}
|
||||
for _, o := range p.Order {
|
||||
switch o.Which {
|
||||
case pgidl.Funcs:
|
||||
genpkgfunc(p.Funcs[o.Index], p.Name)
|
||||
case pgidl.Structs:
|
||||
genstruct(p.Structs[o.Index], p.Name)
|
||||
case pgidl.Interfaces:
|
||||
geniface(p.Interfaces[o.Index], p.Name)
|
||||
case pgidl.Raws:
|
||||
fmt.Printf("%s\n", p.Raws[o.Index])
|
||||
case pgidl.Enums:
|
||||
// we did them already; see above
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
idl, errs := pgidl.Parse(os.Stdin, "<stdin>")
|
||||
if len(errs) != 0 {
|
||||
for _, e := range errs {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", e)
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("// generated by idl2h; do not edit\n")
|
||||
if *guard != "" {
|
||||
fmt.Printf("#ifndef %s\n", *guard)
|
||||
fmt.Printf("#define %s\n", *guard)
|
||||
}
|
||||
for _, p := range idl {
|
||||
genpkg(p)
|
||||
}
|
||||
if *guard != "" {
|
||||
fmt.Printf("#endif\n")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
// 7 april 2015
|
||||
|
||||
/*
|
||||
This file assumes that you have included <windows.h> and "ui.h" beforehand. It provides API-specific functions for interfacing with foreign controls in Windows.
|
||||
*/
|
||||
|
||||
#ifndef __UI_UI_WINDOWS_H__
|
||||
#define __UI_UI_WINDOWS_H__
|
||||
|
||||
// uiWindowsMakeControl() initializes the given uiControl with the given Windows API control inside.
|
||||
// You will need to provide the preferredSize() method yourself.
|
||||
typedef struct uiWindowsMakeControlParams uiWindowsMakeControlParams;
|
||||
struct uiWindowsMakeControlParams {
|
||||
// These match the CreateWindowExW() function.
|
||||
DWORD dwExStyle;
|
||||
LPCWSTR lpClassName;
|
||||
LPCWSTR lpWindowName;
|
||||
DWORD dwStyle; // WS_CHILD and WS_VISIBLE are automatically applied.
|
||||
HINSTANCE hInstance;
|
||||
|
||||
// Set this to non-FALSE to use the standard control font used by other ui controls.
|
||||
BOOL useStandardControlFont;
|
||||
|
||||
// These are called when the control sends a WM_COMMAND or WM_NOTIFY (respectively) to its parent.
|
||||
// ui redirects the message back and calls these functions.
|
||||
// Store the result in *lResult and return any non-FALSE value (such as TRUE) to return the given result; return FALSE to pass the notification up to your window procedure.
|
||||
// Note that these are only issued if they come from the uiControl itself; notifications from children of the uiControl (such as a header control) will be received normally.
|
||||
BOOL (*onWM_COMMAND)(uiControl *c, WORD code, LRESULT *lResult);
|
||||
BOOL (*onWM_NOTIFY)(uiControl *c, NMHDR *nm, LRESULT *lResult);
|
||||
|
||||
// This is called when the widget is ready to be destroyed.
|
||||
void (*onDestroy)(void *data);
|
||||
void *onDestroyData;
|
||||
};
|
||||
_UI_EXTERN void uiWindowsMakeControl(uiControl *c, uiWindowsMakeControlParams *p);
|
||||
|
||||
// This contains the Windows-specific parts of the uiSizing structure.
|
||||
// BaseX and BaseY are the dialog base units.
|
||||
// InternalLeading is the standard control font's internal leading; labels in uiForms use this for correct Y positioning.
|
||||
struct uiSizingSys {
|
||||
int BaseX;
|
||||
int BaseY;
|
||||
LONG InternalLeading;
|
||||
|
||||
// This is the window handle to pass to the hWndInsertAfter parameter of SetWindowPos().
|
||||
// You should set this to your own window handle when done.
|
||||
// Controls made with uiWindowsMakeControl() do this for you; you only need to do this if you are implementing uiControlResize() yourself.
|
||||
HWND InsertAfter;
|
||||
};
|
||||
// Use these in your preferredSize() implementation with baseX and baseY.
|
||||
#define uiWindowsDlgUnitsToX(dlg, baseX) MulDiv((dlg), baseX, 4)
|
||||
#define uiWindowsDlgUnitsToY(dlg, baseY) MulDiv((dlg), baseY, 8)
|
||||
|
||||
// and use this if you need the text of the window width
|
||||
_UI_EXTERN intmax_t uiWindowsWindowTextWidth(HWND hwnd);
|
||||
|
||||
// these functions get and set the window text for such a uiControl
|
||||
// the value returned should be freed with uiFreeText()
|
||||
_UI_EXTERN char *uiWindowsControlText(uiControl *);
|
||||
_UI_EXTERN void uiWindowsControlSetText(uiControl *, const char *);
|
||||
|
||||
struct uiControlSysFuncParams {
|
||||
int Func;
|
||||
BOOL HasTabStops;
|
||||
};
|
||||
|
||||
enum {
|
||||
// These should enable and disable the uiControl while preserving the user enable/disable setting.
|
||||
// These are needed because while disabling a parent window does cause children to stop receiving events, they are not shown as disabled, which is not what we want.
|
||||
uiWindowsSysFuncContainerEnable,
|
||||
uiWindowsSysFuncContainerDisable,
|
||||
// This is interpreted by controls that are tab stops; the control should set HasTabStops to TRUE if so, and *LEAVE IT ALONE* if not.
|
||||
// You only need this if implementing your own uiControl.
|
||||
// Controls created with uiWindowsMakeControl() check for the window being enabled and the presence of WS_TABSTOP.
|
||||
// The name is "has tab stops" because it is used by uiTabs to say "does the current tab page have tab stops?".
|
||||
uiWindowsSysFuncHasTabStops,
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,34 @@
|
|||
// 6 april 2015
|
||||
#include <stdlib.h>
|
||||
|
||||
extern uiInitOptions options;
|
||||
|
||||
extern void *uiAlloc(size_t, const char *);
|
||||
#define uiNew(T) ((T *) uiAlloc(sizeof (T), #T))
|
||||
extern void *uiRealloc(void *, size_t, const char *);
|
||||
extern void uiFree(void *);
|
||||
|
||||
extern void complain(const char *, ...);
|
||||
|
||||
extern uiBin *newBin(void);
|
||||
extern int binHasOSParent(uiBin *);
|
||||
extern void binSetOSParent(uiBin *, uintptr_t);
|
||||
extern void binRemoveOSParent(uiBin *);
|
||||
extern void binResizeRootAndUpdate(uiBin *, intmax_t, intmax_t, intmax_t, intmax_t);
|
||||
extern void binTranslateMargins(uiBin *, intmax_t *, intmax_t *, intmax_t *, intmax_t *, uiSizing *);
|
||||
|
||||
// array.c
|
||||
struct ptrArray {
|
||||
void **ptrs;
|
||||
uintmax_t len;
|
||||
uintmax_t cap;
|
||||
};
|
||||
struct ptrArray *newPtrArray(void);
|
||||
void ptrArrayDestroy(struct ptrArray *);
|
||||
void ptrArrayAppend(struct ptrArray *, void *);
|
||||
void ptrArrayInsertBefore(struct ptrArray *, uintmax_t, void *);
|
||||
void ptrArrayDelete(struct ptrArray *, uintmax_t);
|
||||
#define ptrArrayIndex(p, T, i) ((T) ((p)->ptrs[(i)]))
|
||||
|
||||
// shouldquit.c
|
||||
int shouldQuit(void);
|
|
@ -0,0 +1,53 @@
|
|||
# 22 april 2015
|
||||
|
||||
osCFILES = \
|
||||
windows/alloc.c \
|
||||
windows/bin.c \
|
||||
windows/button.c \
|
||||
windows/checkbox.c \
|
||||
windows/comctl32.c \
|
||||
windows/container.c \
|
||||
windows/debug.c \
|
||||
windows/entry.c \
|
||||
windows/group.c \
|
||||
windows/init.c \
|
||||
windows/label.c \
|
||||
windows/main.c \
|
||||
windows/menu.c \
|
||||
windows/newcontrol.c \
|
||||
windows/tab.c \
|
||||
windows/text.c \
|
||||
windows/util.c \
|
||||
windows/window.c
|
||||
|
||||
osHFILES = \
|
||||
windows/uipriv_windows.h
|
||||
|
||||
# thanks ebassi in irc.gimp.net/#gtk+
|
||||
osCFLAGS = \
|
||||
-D_UI_EXTERN='__declspec(dllexport) extern'
|
||||
|
||||
osLDFLAGS = \
|
||||
-static-libgcc \
|
||||
-luser32 -lkernel32 -lgdi32 -luxtheme -lmsimg32 -lcomdlg32 -lole32 -loleaut32 -loleacc -luuid
|
||||
|
||||
osLDWarnUndefinedFlags = -Wl,--no-undefined -Wl,--no-allow-shlib-undefined
|
||||
|
||||
osLIBSUFFIX = .dll
|
||||
osEXESUFFIX = .exe
|
||||
|
||||
ifeq ($(ARCH),amd64)
|
||||
CC = x86_64-w64-mingw32-gcc
|
||||
RC = x86_64-w64-mingw32-windres
|
||||
archmflag = -m64
|
||||
else
|
||||
CC = i686-w64-mingw32-gcc
|
||||
RC = i686-w64-mingw32-windres
|
||||
archmflag = -m32
|
||||
endif
|
||||
|
||||
ifeq ($(PROFILE),1)
|
||||
osCFILES += windows/profiler.c
|
||||
osCFLAGS += -finstrument-functions
|
||||
osLDFLAGS += -finstrument-functions
|
||||
endif
|
|
@ -0,0 +1,2 @@
|
|||
// 14 may 2015
|
||||
#include "uipriv_windows.h"
|
|
@ -0,0 +1,96 @@
|
|||
// 6 january 2015
|
||||
#define UNICODE
|
||||
#define _UNICODE
|
||||
#define STRICT
|
||||
#define STRICT_TYPED_ITEMIDS
|
||||
#define CINTERFACE
|
||||
#define COBJMACROS
|
||||
// see https://github.com/golang/go/issues/9916#issuecomment-74812211
|
||||
#define INITGUID
|
||||
// get Windows version right; right now Windows XP
|
||||
#define WINVER 0x0501
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#define _WIN32_WINDOWS 0x0501 /* according to Microsoft's winperf.h */
|
||||
#define _WIN32_IE 0x0600 /* according to Microsoft's sdkddkver.h */
|
||||
#define NTDDI_VERSION 0x05010000 /* according to Microsoft's sdkddkver.h */
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <stdint.h>
|
||||
#include <uxtheme.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <windowsx.h>
|
||||
#include <vsstyle.h>
|
||||
#include <vssym32.h>
|
||||
#include <stdarg.h>
|
||||
#include <oleacc.h>
|
||||
#include <stdio.h>
|
||||
#include "../out/ui.h"
|
||||
#include "../ui_windows.h"
|
||||
#include "../uipriv.h"
|
||||
|
||||
// ui internal window messages
|
||||
enum {
|
||||
// redirected WM_COMMAND and WM_NOTIFY
|
||||
msgCOMMAND = WM_APP + 0x40, // start offset just to be safe
|
||||
msgNOTIFY,
|
||||
msgUpdateChild, // fake because Windows seems to SWP_NOSIZE MoveWindow()s and SetWindowPos()s that don't change the window size (even if SWP_NOSIZE isn't specified)
|
||||
msgHasTabStops,
|
||||
msgConsoleEndSession,
|
||||
};
|
||||
|
||||
// debug.c
|
||||
extern HRESULT logLastError(const char *);
|
||||
extern HRESULT logHRESULT(const char *, HRESULT);
|
||||
extern HRESULT logMemoryExhausted(const char *);
|
||||
|
||||
// init.c
|
||||
extern HINSTANCE hInstance;
|
||||
extern int nCmdShow;
|
||||
extern HFONT hMessageFont;
|
||||
extern HBRUSH hollowBrush;
|
||||
|
||||
// util.c
|
||||
extern int windowClassOf(HWND, ...);
|
||||
extern void mapWindowRect(HWND, HWND, RECT *);
|
||||
extern DWORD getStyle(HWND);
|
||||
extern void setStyle(HWND, DWORD);
|
||||
extern DWORD getExStyle(HWND);
|
||||
extern void setExStyle(HWND, DWORD);
|
||||
extern void moveWindow(HWND, intmax_t, intmax_t, intmax_t, intmax_t);
|
||||
extern void moveAndReorderWindow(HWND, HWND, intmax_t, intmax_t, intmax_t, intmax_t);
|
||||
|
||||
// text.c
|
||||
extern WCHAR *toUTF16(const char *);
|
||||
extern char *toUTF8(const WCHAR *);
|
||||
extern WCHAR *windowText(HWND);
|
||||
|
||||
// comctl32.c
|
||||
extern BOOL (*WINAPI fv_SetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
|
||||
extern BOOL (*WINAPI fv_RemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
|
||||
extern LRESULT (*WINAPI fv_DefSubclassProc)(HWND, UINT, WPARAM, LPARAM);
|
||||
extern const char *initCommonControls(void);
|
||||
|
||||
// window.c
|
||||
extern ATOM registerWindowClass(HICON, HCURSOR);
|
||||
extern void unregisterWindowClass(void);
|
||||
|
||||
// container.c
|
||||
extern HWND initialParent;
|
||||
extern const char *initContainer(HICON, HCURSOR);
|
||||
extern void uninitContainer(void);
|
||||
|
||||
// menu.c
|
||||
extern HMENU makeMenubar(void);
|
||||
extern const uiMenuItem *menuIDToItem(UINT_PTR);
|
||||
extern void runMenuEvent(WORD, uiWindow *);
|
||||
extern void freeMenubar(HMENU);
|
||||
extern void uninitMenus(void);
|
||||
|
||||
// alloc.c
|
||||
extern int initAlloc(void);
|
||||
extern void uninitAlloc(void);
|
||||
|
||||
// tab.c
|
||||
extern void tabEnterTabNavigation(HWND);
|
||||
extern void tabLeaveTabNavigation(HWND);
|
Loading…
Reference in New Issue