Removed more files from the top level.
This commit is contained in:
parent
269e99aec3
commit
d98ca5dfd4
58
GNUbase.mk
58
GNUbase.mk
|
@ -1,58 +0,0 @@
|
||||||
# 22 april 2015
|
|
||||||
|
|
||||||
OUTBASE = new
|
|
||||||
OUTDIR = out
|
|
||||||
OBJDIR = .obj
|
|
||||||
|
|
||||||
xHFILES = \
|
|
||||||
ui.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
|
|
||||||
|
|
||||||
ui.h: ui.idl
|
|
||||||
@idl2h -extern _UI_EXTERN -guard __UI_UI_H__ < ui.idl > ui.h
|
|
||||||
@echo ====== Generated ui.h
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf $(OUTDIR) $(OBJDIR) ui.h
|
|
||||||
.PHONY: clean
|
|
45
GNUmakefile
45
GNUmakefile
|
@ -1,45 +0,0 @@
|
||||||
# 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
|
|
||||||
|
|
||||||
baseHFILES = \
|
|
||||||
ui.h \
|
|
||||||
uipriv.h \
|
|
||||||
ui_$(OS).h \
|
|
||||||
$(osHFILES)
|
|
||||||
|
|
||||||
baseCFILES = \
|
|
||||||
bin.c \
|
|
||||||
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
|
|
|
@ -1,16 +0,0 @@
|
||||||
# 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
|
|
132
bin.c
132
bin.c
|
@ -1,132 +0,0 @@
|
||||||
// 27 april 2015
|
|
||||||
#include "ui.h"
|
|
||||||
#include "uipriv.h"
|
|
||||||
|
|
||||||
struct bin {
|
|
||||||
uiBin b;
|
|
||||||
void (*baseDestroy)(uiControl *);
|
|
||||||
uiControl *mainControl;
|
|
||||||
intmax_t marginLeft;
|
|
||||||
intmax_t marginTop;
|
|
||||||
intmax_t marginRight;
|
|
||||||
intmax_t marginBottom;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void binDestroy(uiControl *c)
|
|
||||||
{
|
|
||||||
struct bin *b = (struct bin *) c;
|
|
||||||
|
|
||||||
// ensure clean removal by making sure the bin has no OS parent
|
|
||||||
if (uiBinHasOSParent(uiBin(b)))
|
|
||||||
complain("attempt to destroy bin %p while it has an OS parent", b);
|
|
||||||
// don't chain up to base here; we need to destroy children ourselves first
|
|
||||||
if (b->mainControl != NULL) {
|
|
||||||
uiControlSetParent(b->mainControl, NULL);
|
|
||||||
uiControlDestroy(b->mainControl);
|
|
||||||
}
|
|
||||||
// NOW we can chain up to base
|
|
||||||
(*(b->baseDestroy))(uiControl(b));
|
|
||||||
uiFree(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void binPreferredSize(uiControl *c, uiSizing *d, intmax_t *width, intmax_t *height)
|
|
||||||
{
|
|
||||||
struct bin *b = (struct bin *) c;
|
|
||||||
intmax_t left, top, right, bottom;
|
|
||||||
intmax_t cwid, cht;
|
|
||||||
|
|
||||||
if (b->mainControl == NULL) {
|
|
||||||
*width = 0;
|
|
||||||
*height = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// first do margins
|
|
||||||
left = b->marginLeft;
|
|
||||||
top = b->marginTop;
|
|
||||||
right = b->marginRight;
|
|
||||||
bottom = b->marginBottom;
|
|
||||||
uiBinTranslateMargins(uiBin(b), &left, &top, &right, &bottom, d);
|
|
||||||
*width = left + right;
|
|
||||||
*height = top + bottom;
|
|
||||||
|
|
||||||
// then do the control
|
|
||||||
uiControlPreferredSize(b->mainControl, d, &cwid, &cht);
|
|
||||||
*width += cwid;
|
|
||||||
*height += cht;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void binSysFunc(uiControl *c, uiControlSysFuncParams *p)
|
|
||||||
{
|
|
||||||
struct bin *b = (struct bin *) c;
|
|
||||||
|
|
||||||
if (b->mainControl != NULL)
|
|
||||||
uiControlSysFunc(b->mainControl, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void binResizeChildren(uiContainer *c, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d)
|
|
||||||
{
|
|
||||||
struct bin *b = (struct bin *) c;
|
|
||||||
intmax_t left, top, right, bottom;
|
|
||||||
|
|
||||||
if (b->mainControl == NULL)
|
|
||||||
return;
|
|
||||||
left = b->marginLeft;
|
|
||||||
top = b->marginTop;
|
|
||||||
right = b->marginRight;
|
|
||||||
bottom = b->marginBottom;
|
|
||||||
uiBinTranslateMargins(uiBin(b), &left, &top, &right, &bottom, d);
|
|
||||||
x += left;
|
|
||||||
y += top;
|
|
||||||
width -= left + right;
|
|
||||||
height -= top + bottom;
|
|
||||||
uiControlResize(b->mainControl, x, y, width, height, d);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void binSetMainControl(uiBin *bb, uiControl *mainControl)
|
|
||||||
{
|
|
||||||
struct bin *b = (struct bin *) bb;
|
|
||||||
|
|
||||||
if (b->mainControl != NULL)
|
|
||||||
uiControlSetParent(b->mainControl, NULL);
|
|
||||||
b->mainControl = mainControl;
|
|
||||||
if (b->mainControl != NULL)
|
|
||||||
uiControlSetParent(b->mainControl, uiContainer(b));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void binSetMargins(uiBin *bb, intmax_t left, intmax_t top, intmax_t right, intmax_t bottom)
|
|
||||||
{
|
|
||||||
struct bin *b = (struct bin *) bb;
|
|
||||||
|
|
||||||
b->marginLeft = left;
|
|
||||||
b->marginRight = right;
|
|
||||||
b->marginTop = top;
|
|
||||||
b->marginBottom = bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
uiBin *newBin(void)
|
|
||||||
{
|
|
||||||
struct bin *b;
|
|
||||||
|
|
||||||
b = uiNew(struct bin);
|
|
||||||
|
|
||||||
uiMakeContainer(uiContainer(b));
|
|
||||||
|
|
||||||
b->baseDestroy = uiControl(b)->Destroy;
|
|
||||||
uiControl(b)->Destroy = binDestroy;
|
|
||||||
uiControl(b)->PreferredSize = binPreferredSize;
|
|
||||||
uiControl(b)->SysFunc = binSysFunc;
|
|
||||||
|
|
||||||
uiContainer(b)->ResizeChildren = binResizeChildren;
|
|
||||||
|
|
||||||
uiBin(b)->SetMainControl = binSetMainControl;
|
|
||||||
uiBin(b)->SetMargins = binSetMargins;
|
|
||||||
// these are defined by each OS's bin.c
|
|
||||||
uiBin(b)->HasOSParent = binHasOSParent;
|
|
||||||
uiBin(b)->SetOSParent = binSetOSParent;
|
|
||||||
uiBin(b)->RemoveOSParent = binRemoveOSParent;
|
|
||||||
uiBin(b)->ResizeRootAndUpdate = binResizeRootAndUpdate;
|
|
||||||
uiBin(b)->TranslateMargins = binTranslateMargins;
|
|
||||||
|
|
||||||
return uiBin(b);
|
|
||||||
}
|
|
158
ui.idl
158
ui.idl
|
@ -1,158 +0,0 @@
|
||||||
// 6 april 2015
|
|
||||||
|
|
||||||
// This is not an IDL file for the conventional RPC or Microsoft IDLs.
|
|
||||||
// Instead, this is for a custom IDL of my own creation.
|
|
||||||
// You can find it at github.com/andlabs/pgidl
|
|
||||||
|
|
||||||
package ui {
|
|
||||||
|
|
||||||
raw "#include <stddef.h>";
|
|
||||||
raw "#include <stdint.h>";
|
|
||||||
|
|
||||||
raw "#ifndef _UI_EXTERN";
|
|
||||||
raw "#define _UI_EXTERN extern";
|
|
||||||
raw "#endif";
|
|
||||||
|
|
||||||
struct InitOptions {
|
|
||||||
field Size size_t;
|
|
||||||
};
|
|
||||||
|
|
||||||
func Init(options *InitOptions) *const char;
|
|
||||||
func Uninit(void);
|
|
||||||
func FreeInitError(err *const char);
|
|
||||||
|
|
||||||
func Main(void);
|
|
||||||
func Quit(void);
|
|
||||||
|
|
||||||
func OnShouldQuit(f *func(data *void) int, data *void);
|
|
||||||
|
|
||||||
func FreeText(text *char);
|
|
||||||
|
|
||||||
raw "typedef struct uiSizingSys uiSizingSys;";
|
|
||||||
|
|
||||||
struct Sizing {
|
|
||||||
field XPadding intmax_t;
|
|
||||||
field YPadding intmax_t;
|
|
||||||
field Sys *uiSizingSys;
|
|
||||||
};
|
|
||||||
|
|
||||||
raw "typedef struct uiControlSysFuncParams uiControlSysFuncParams;";
|
|
||||||
|
|
||||||
interface Control {
|
|
||||||
field Internal *void; // for use by ui only
|
|
||||||
func Destroy(void);
|
|
||||||
func Handle(void) uintptr_t;
|
|
||||||
func SetParent(c *Container);
|
|
||||||
func PreferredSize(d *Sizing, width *intmax_t, height *intmax_t);
|
|
||||||
func Resize(x intmax_t, y intmax_t, width intmax_t, height intmax_t, d *Sizing);
|
|
||||||
func Visible(void) int;
|
|
||||||
func Show(void);
|
|
||||||
func Hide(void);
|
|
||||||
func Enable(void);
|
|
||||||
func Disable(void);
|
|
||||||
func SysFunc(p *uiControlSysFuncParams);
|
|
||||||
};
|
|
||||||
|
|
||||||
interface Container from Control {
|
|
||||||
func ResizeChildren(x intmax_t, y intmax_t, width intmax_t, height intmax_t, d *Sizing);
|
|
||||||
func Update(void);
|
|
||||||
};
|
|
||||||
func MakeContainer(c *Container);
|
|
||||||
|
|
||||||
interface Bin from Container {
|
|
||||||
func SetMainControl(c *Control);
|
|
||||||
func SetMargins(left intmax_t, top intmax_t, right intmax_t, bottom intmax_t);
|
|
||||||
// defined by each OS
|
|
||||||
func HasOSParent(void) int;
|
|
||||||
func SetOSParent(parent uintptr_t);
|
|
||||||
func RemoveOSParent(void);
|
|
||||||
func ResizeRootAndUpdate(x intmax_t, y intmax_t, width intmax_t, height intmax_t);
|
|
||||||
func TranslateMargins(left *intmax_t, top *intmax_t, right *intmax_t, bottom *intmax_t, d *Sizing);
|
|
||||||
};
|
|
||||||
|
|
||||||
interface Window from Control {
|
|
||||||
func Title(void) *char;
|
|
||||||
func SetTitle(title *const char);
|
|
||||||
func OnClosing(f *func(w *Window, data *void) int, data *void);
|
|
||||||
func SetChild(c *Control);
|
|
||||||
func Margined(void) int;
|
|
||||||
func SetMargined(margined int);
|
|
||||||
};
|
|
||||||
func NewWindow(title *const char, width int, height int, hasMenubar int) *Window;
|
|
||||||
|
|
||||||
interface Button from Control {
|
|
||||||
func Text(void) *char;
|
|
||||||
func SetText(text *const char);
|
|
||||||
func OnClicked(f *func(b *Button, data *void), data *void);
|
|
||||||
};
|
|
||||||
func NewButton(text *const char) *Button;
|
|
||||||
|
|
||||||
interface Box from Container {
|
|
||||||
func Append(c *Control, stretchy int);
|
|
||||||
func Delete(index uintmax_t);
|
|
||||||
func Padded(void) int;
|
|
||||||
func SetPadded(padded int);
|
|
||||||
};
|
|
||||||
func NewHorizontalBox(void) *Box;
|
|
||||||
func NewVerticalBox(void) *Box;
|
|
||||||
|
|
||||||
interface Entry from Control {
|
|
||||||
func Text(void) *char;
|
|
||||||
func SetText(text *const char);
|
|
||||||
func OnChanged(f *func(e *Entry, data *void), data *void);
|
|
||||||
func ReadOnly(void) int;
|
|
||||||
func SetReadOnly(readonly int);
|
|
||||||
};
|
|
||||||
func NewEntry(void) *Entry;
|
|
||||||
|
|
||||||
interface Checkbox from Control {
|
|
||||||
func Text(void) *char;
|
|
||||||
func SetText(text *const char);
|
|
||||||
func OnToggled(f *func(c *Checkbox, data *void), data *void);
|
|
||||||
func Checked(void) int;
|
|
||||||
func SetChecked(checked int);
|
|
||||||
};
|
|
||||||
func NewCheckbox(text *const char) *Checkbox;
|
|
||||||
|
|
||||||
interface Label from Control {
|
|
||||||
func Text(void) *char;
|
|
||||||
func SetText(text *const char);
|
|
||||||
};
|
|
||||||
func NewLabel(text *const char) *Label;
|
|
||||||
|
|
||||||
interface Tab from Control {
|
|
||||||
func AppendPage(name *const char, c *Control);
|
|
||||||
func InsertPageBefore(name *const char, before uintmax_t, c *Control);
|
|
||||||
func DeletePage(index uintmax_t);
|
|
||||||
func NumPages(void) uintmax_t;
|
|
||||||
func Margined(page uintmax_t) int;
|
|
||||||
func SetMargined(page uintmax_t, margined int);
|
|
||||||
};
|
|
||||||
func NewTab(void) *Tab;
|
|
||||||
|
|
||||||
interface Group from Control {
|
|
||||||
// TODO text and settext
|
|
||||||
func SetChild(c *Control);
|
|
||||||
// TODO margined and setmargined
|
|
||||||
};
|
|
||||||
func NewGroup(text *const char) *Group;
|
|
||||||
|
|
||||||
interface Menu {
|
|
||||||
func AppendItem(name *const char) *MenuItem;
|
|
||||||
func AppendCheckItem(name *const char) *MenuItem;
|
|
||||||
func AppendQuitItem(void) *MenuItem;
|
|
||||||
func AppendPreferencesItem(void) *MenuItem;
|
|
||||||
func AppendAboutItem(void) *MenuItem;
|
|
||||||
func AppendSeparator(void);
|
|
||||||
};
|
|
||||||
func NewMenu(name *const char) *Menu;
|
|
||||||
|
|
||||||
interface MenuItem {
|
|
||||||
func Enable(void);
|
|
||||||
func Disable(void);
|
|
||||||
func OnClicked(f *func(sender *MenuItem, window *Window, data *void), data *void);
|
|
||||||
func Checked(void) int;
|
|
||||||
func SetChecked(checked int);
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
79
ui_windows.h
79
ui_windows.h
|
@ -1,79 +0,0 @@
|
||||||
// 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
|
|
34
uipriv.h
34
uipriv.h
|
@ -1,34 +0,0 @@
|
||||||
// 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);
|
|
38
unix/bin.c
38
unix/bin.c
|
@ -1,38 +0,0 @@
|
||||||
// 28 april 2015
|
|
||||||
#include "uipriv_unix.h"
|
|
||||||
|
|
||||||
int binHasOSParent(uiBin *b)
|
|
||||||
{
|
|
||||||
GtkWidget *binWidget;
|
|
||||||
|
|
||||||
binWidget = GTK_WIDGET(uiControlHandle(uiControl(b)));
|
|
||||||
return gtk_widget_get_parent(binWidget) != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void binSetOSParent(uiBin *b, uintptr_t osParent)
|
|
||||||
{
|
|
||||||
GtkWidget *binWidget;
|
|
||||||
|
|
||||||
binWidget = GTK_WIDGET(uiControlHandle(uiControl(b)));
|
|
||||||
gtk_container_add(GTK_CONTAINER(osParent), binWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
void binRemoveOSParent(uiBin *b)
|
|
||||||
{
|
|
||||||
GtkWidget *binWidget;
|
|
||||||
GtkWidget *oldparent;
|
|
||||||
|
|
||||||
binWidget = GTK_WIDGET(uiControlHandle(uiControl(b)));
|
|
||||||
oldparent = gtk_widget_get_parent(binWidget);
|
|
||||||
gtk_container_remove(GTK_CONTAINER(oldparent), binWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
void binResizeRootAndUpdate(uiBin *b, intmax_t x, intmax_t y, intmax_t width, intmax_t height)
|
|
||||||
{
|
|
||||||
// not used on GTK+
|
|
||||||
}
|
|
||||||
|
|
||||||
void binTranslateMargins(uiBin *b, intmax_t *left, intmax_t *top, intmax_t *right, intmax_t *bottom, uiSizing *d)
|
|
||||||
{
|
|
||||||
// not used on GTK+
|
|
||||||
}
|
|
|
@ -1,164 +0,0 @@
|
||||||
// 7 april 2015
|
|
||||||
#include "uipriv_unix.h"
|
|
||||||
|
|
||||||
struct singleWidget {
|
|
||||||
GtkWidget *widget;
|
|
||||||
GtkWidget *scrolledWindow;
|
|
||||||
GtkWidget *immediate; // the widget that is added to the parent container; either widget or scrolledWindow
|
|
||||||
uiContainer *parent;
|
|
||||||
int hidden;
|
|
||||||
void (*onDestroy)(void *);
|
|
||||||
void *onDestroyData;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void singleDestroy(uiControl *c)
|
|
||||||
{
|
|
||||||
struct singleWidget *s = (struct singleWidget *) (c->Internal);
|
|
||||||
|
|
||||||
if (s->parent != NULL)
|
|
||||||
complain("attempt to destroy a uiControl at %p while it still has a parent", c);
|
|
||||||
// first call the widget's own destruction code
|
|
||||||
(*(s->onDestroy))(s->onDestroyData);
|
|
||||||
// then actually destroy
|
|
||||||
g_object_unref(s->immediate);
|
|
||||||
// and free ourselves
|
|
||||||
uiFree(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uintptr_t singleHandle(uiControl *c)
|
|
||||||
{
|
|
||||||
struct singleWidget *s = (struct singleWidget *) (c->Internal);
|
|
||||||
|
|
||||||
return (uintptr_t) (s->widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void singleSetParent(uiControl *c, uiContainer *parent)
|
|
||||||
{
|
|
||||||
struct singleWidget *s = (struct singleWidget *) (c->Internal);
|
|
||||||
uiContainer *oldparent;
|
|
||||||
GtkContainer *oldcontainer;
|
|
||||||
GtkContainer *newcontainer;
|
|
||||||
|
|
||||||
oldparent = s->parent;
|
|
||||||
s->parent = parent;
|
|
||||||
if (oldparent != NULL) {
|
|
||||||
oldcontainer = GTK_CONTAINER(uiControlHandle(uiControl(oldparent)));
|
|
||||||
gtk_container_remove(oldcontainer, s->immediate);
|
|
||||||
}
|
|
||||||
if (s->parent != NULL) {
|
|
||||||
newcontainer = GTK_CONTAINER(uiControlHandle(uiControl(s->parent)));
|
|
||||||
gtk_container_add(newcontainer, s->immediate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void singlePreferredSize(uiControl *c, uiSizing *d, intmax_t *width, intmax_t *height)
|
|
||||||
{
|
|
||||||
struct singleWidget *s = (struct singleWidget *) (c->Internal);
|
|
||||||
GtkRequisition natural;
|
|
||||||
|
|
||||||
// use the natural size as the minimum size is an *absolute* minimum
|
|
||||||
// for example, if a label has ellipsizing on, it can be the width of the ellipses, not the text
|
|
||||||
// there is a warning about height-for-width sizing, but in my tests this isn't an issue
|
|
||||||
gtk_widget_get_preferred_size(s->widget, NULL, &natural);
|
|
||||||
*width = natural.width;
|
|
||||||
*height = natural.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void singleResize(uiControl *c, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d)
|
|
||||||
{
|
|
||||||
struct singleWidget *s = (struct singleWidget *) (c->Internal);
|
|
||||||
GtkAllocation a;
|
|
||||||
|
|
||||||
a.x = x;
|
|
||||||
a.y = y;
|
|
||||||
a.width = width;
|
|
||||||
a.height = height;
|
|
||||||
gtk_widget_size_allocate(s->immediate, &a);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int singleVisible(uiControl *c)
|
|
||||||
{
|
|
||||||
struct singleWidget *s = (struct singleWidget *) (c->Internal);
|
|
||||||
|
|
||||||
return !s->hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void singleShow(uiControl *c)
|
|
||||||
{
|
|
||||||
struct singleWidget *s = (struct singleWidget *) (c->Internal);
|
|
||||||
|
|
||||||
gtk_widget_show_all(s->immediate);
|
|
||||||
s->hidden = 0;
|
|
||||||
if (s->parent != NULL)
|
|
||||||
uiContainerUpdate(s->parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void singleHide(uiControl *c)
|
|
||||||
{
|
|
||||||
struct singleWidget *s = (struct singleWidget *) (c->Internal);
|
|
||||||
|
|
||||||
gtk_widget_hide(s->immediate);
|
|
||||||
s->hidden = 1;
|
|
||||||
if (s->parent != NULL)
|
|
||||||
uiContainerUpdate(s->parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void singleEnable(uiControl *c)
|
|
||||||
{
|
|
||||||
struct singleWidget *s = (struct singleWidget *) (c->Internal);
|
|
||||||
|
|
||||||
gtk_widget_set_sensitive(s->immediate, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void singleDisable(uiControl *c)
|
|
||||||
{
|
|
||||||
struct singleWidget *s = (struct singleWidget *) (c->Internal);
|
|
||||||
|
|
||||||
gtk_widget_set_sensitive(s->immediate, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void uiUnixMakeControl(uiControl *c, GType type, gboolean inScrolledWindow, gboolean scrolledWindowHasBorder, void (*onDestroy)(void *), void *onDestroyData, const char *firstProperty, ...)
|
|
||||||
{
|
|
||||||
struct singleWidget *s;
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
s = uiNew(struct singleWidget);
|
|
||||||
|
|
||||||
va_start(ap, firstProperty);
|
|
||||||
s->widget = GTK_WIDGET(g_object_new_valist(type, firstProperty, ap));
|
|
||||||
va_end(ap);
|
|
||||||
s->immediate = s->widget;
|
|
||||||
|
|
||||||
if (inScrolledWindow) {
|
|
||||||
s->scrolledWindow = gtk_scrolled_window_new(NULL, NULL);
|
|
||||||
if (!GTK_IS_SCROLLABLE(s->widget))
|
|
||||||
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(s->scrolledWindow), s->widget);
|
|
||||||
else
|
|
||||||
gtk_container_add(GTK_CONTAINER(s->scrolledWindow), s->widget);
|
|
||||||
if (scrolledWindowHasBorder)
|
|
||||||
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(s->scrolledWindow), GTK_SHADOW_IN);
|
|
||||||
s->immediate = s->scrolledWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we need to keep an extra reference on the immediate widget
|
|
||||||
// this is so we can reparent the control freely
|
|
||||||
g_object_ref_sink(s->immediate);
|
|
||||||
|
|
||||||
s->onDestroy = onDestroy;
|
|
||||||
s->onDestroyData = onDestroyData;
|
|
||||||
|
|
||||||
// finally, call gtk_widget_show_all() here to set the initial visibility of the widget
|
|
||||||
gtk_widget_show_all(s->immediate);
|
|
||||||
|
|
||||||
uiControl(c)->Internal = s;
|
|
||||||
uiControl(c)->Destroy = singleDestroy;
|
|
||||||
uiControl(c)->Handle = singleHandle;
|
|
||||||
uiControl(c)->SetParent = singleSetParent;
|
|
||||||
uiControl(c)->PreferredSize = singlePreferredSize;
|
|
||||||
uiControl(c)->Resize = singleResize;
|
|
||||||
uiControl(c)->Visible = singleVisible;
|
|
||||||
uiControl(c)->Show = singleShow;
|
|
||||||
uiControl(c)->Hide = singleHide;
|
|
||||||
uiControl(c)->Enable = singleEnable;
|
|
||||||
uiControl(c)->Disable = singleDisable;
|
|
||||||
}
|
|
231
unix/window.c
231
unix/window.c
|
@ -1,231 +0,0 @@
|
||||||
// 28 april 2015
|
|
||||||
#include "uipriv_unix.h"
|
|
||||||
|
|
||||||
struct window {
|
|
||||||
uiWindow w;
|
|
||||||
|
|
||||||
GtkWidget *widget;
|
|
||||||
GtkContainer *container;
|
|
||||||
GtkWindow *window;
|
|
||||||
|
|
||||||
GtkWidget *vboxWidget;
|
|
||||||
GtkContainer *vboxContainer;
|
|
||||||
GtkBox *vbox;
|
|
||||||
|
|
||||||
GtkWidget *menubar;
|
|
||||||
|
|
||||||
uiBin *bin;
|
|
||||||
|
|
||||||
int hidden;
|
|
||||||
|
|
||||||
int (*onClosing)(uiWindow *, void *);
|
|
||||||
void *onClosingData;
|
|
||||||
int margined;
|
|
||||||
};
|
|
||||||
|
|
||||||
static gboolean onClosing(GtkWidget *win, GdkEvent *e, gpointer data)
|
|
||||||
{
|
|
||||||
struct window *w = (struct window *) data;
|
|
||||||
|
|
||||||
// manually destroy the window ourselves; don't let the delete-event handler do it
|
|
||||||
if ((*(w->onClosing))(uiWindow(w), w->onClosingData))
|
|
||||||
uiControlDestroy(uiControl(w));
|
|
||||||
// don't continue to the default delete-event handler; we destroyed the window by now
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int defaultOnClosing(uiWindow *w, void *data)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void windowDestroy(uiControl *c)
|
|
||||||
{
|
|
||||||
struct window *w = (struct window *) c;
|
|
||||||
|
|
||||||
// first hide ourselves
|
|
||||||
gtk_widget_hide(w->widget);
|
|
||||||
// now destroy the bin
|
|
||||||
// we need to remove the bin from its parent first
|
|
||||||
uiBinRemoveOSParent(w->bin);
|
|
||||||
uiControlDestroy(uiControl(w->bin));
|
|
||||||
// now destroy the menus, if any
|
|
||||||
if (w->menubar != NULL)
|
|
||||||
freeMenubar(w->menubar);
|
|
||||||
// now destroy ourselves
|
|
||||||
// this will also free the vbox
|
|
||||||
gtk_widget_destroy(w->widget);
|
|
||||||
uiFree(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uintptr_t windowHandle(uiControl *c)
|
|
||||||
{
|
|
||||||
struct window *w = (struct window *) c;
|
|
||||||
|
|
||||||
return (uintptr_t) (w->window);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void windowSetParent(uiControl *c, uiContainer *parent)
|
|
||||||
{
|
|
||||||
complain("attempt to give the uiWindow at %p a parent", c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void windowPreferredSize(uiControl *c, uiSizing *d, intmax_t *width, intmax_t *height)
|
|
||||||
{
|
|
||||||
complain("attempt to get the preferred size of the uiWindow at %p", c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void windowResize(uiControl *c, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d)
|
|
||||||
{
|
|
||||||
complain("attempt to resize the uiWindow at %p", c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int windowVisible(uiControl *c)
|
|
||||||
{
|
|
||||||
struct window *w = (struct window *) c;
|
|
||||||
|
|
||||||
return !w->hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void windowShow(uiControl *c)
|
|
||||||
{
|
|
||||||
struct window *w = (struct window *) c;
|
|
||||||
|
|
||||||
// don't use gtk_widget_show_all() as that will show all children, regardless of user settings
|
|
||||||
// don't use gtk_widget_show(); that doesn't bring to front or give keyboard focus
|
|
||||||
// (gtk_window_present() does call gtk_widget_show() though)
|
|
||||||
gtk_window_present(w->window);
|
|
||||||
w->hidden = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void windowHide(uiControl *c)
|
|
||||||
{
|
|
||||||
struct window *w = (struct window *) c;
|
|
||||||
|
|
||||||
gtk_widget_hide(w->widget);
|
|
||||||
w->hidden = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void windowEnable(uiControl *c)
|
|
||||||
{
|
|
||||||
struct window *w = (struct window *) c;
|
|
||||||
|
|
||||||
gtk_widget_set_sensitive(w->widget, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void windowDisable(uiControl *c)
|
|
||||||
{
|
|
||||||
struct window *w = (struct window *) c;
|
|
||||||
|
|
||||||
gtk_widget_set_sensitive(w->widget, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *windowTitle(uiWindow *ww)
|
|
||||||
{
|
|
||||||
struct window *w = (struct window *) ww;
|
|
||||||
|
|
||||||
return uiUnixStrdupText(gtk_window_get_title(w->window));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void windowSetTitle(uiWindow *ww, const char *title)
|
|
||||||
{
|
|
||||||
struct window *w = (struct window *) ww;
|
|
||||||
|
|
||||||
gtk_window_set_title(w->window, title);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void windowOnClosing(uiWindow *ww, int (*f)(uiWindow *, void *), void *data)
|
|
||||||
{
|
|
||||||
struct window *w = (struct window *) ww;
|
|
||||||
|
|
||||||
w->onClosing = f;
|
|
||||||
w->onClosingData = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void windowSetChild(uiWindow *ww, uiControl *child)
|
|
||||||
{
|
|
||||||
struct window *w = (struct window *) ww;
|
|
||||||
|
|
||||||
uiBinSetMainControl(w->bin, child);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int windowMargined(uiWindow *ww)
|
|
||||||
{
|
|
||||||
struct window *w = (struct window *) ww;
|
|
||||||
|
|
||||||
return w->margined;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void windowSetMargined(uiWindow *ww, int margined)
|
|
||||||
{
|
|
||||||
struct window *w = (struct window *) ww;
|
|
||||||
|
|
||||||
w->margined = margined;
|
|
||||||
if (w->margined)
|
|
||||||
uiBinSetMargins(w->bin, gtkXMargin, gtkYMargin, gtkXMargin, gtkYMargin);
|
|
||||||
else
|
|
||||||
uiBinSetMargins(w->bin, 0, 0, 0, 0);
|
|
||||||
uiContainerUpdate(uiContainer(w->bin));
|
|
||||||
}
|
|
||||||
|
|
||||||
uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar)
|
|
||||||
{
|
|
||||||
struct window *w;
|
|
||||||
GtkWidget *binWidget;
|
|
||||||
|
|
||||||
w = uiNew(struct window);
|
|
||||||
|
|
||||||
w->widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
|
||||||
w->container = GTK_CONTAINER(w->widget);
|
|
||||||
w->window = GTK_WINDOW(w->widget);
|
|
||||||
|
|
||||||
gtk_window_set_title(w->window, title);
|
|
||||||
gtk_window_resize(w->window, width, height);
|
|
||||||
|
|
||||||
w->vboxWidget = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
|
||||||
w->vboxContainer = GTK_CONTAINER(w->vboxWidget);
|
|
||||||
w->vbox = GTK_BOX(w->vboxWidget);
|
|
||||||
|
|
||||||
// set the vbox as the GtkWindow child
|
|
||||||
gtk_container_add(w->container, w->vboxWidget);
|
|
||||||
|
|
||||||
if (hasMenubar) {
|
|
||||||
w->menubar = makeMenubar(uiWindow(w));
|
|
||||||
gtk_container_add(w->vboxContainer, w->menubar);
|
|
||||||
}
|
|
||||||
|
|
||||||
w->bin = newBin();
|
|
||||||
binWidget = GTK_WIDGET(uiControlHandle(uiControl(w->bin)));
|
|
||||||
gtk_widget_set_hexpand(binWidget, TRUE);
|
|
||||||
gtk_widget_set_halign(binWidget, GTK_ALIGN_FILL);
|
|
||||||
gtk_widget_set_vexpand(binWidget, TRUE);
|
|
||||||
gtk_widget_set_valign(binWidget, GTK_ALIGN_FILL);
|
|
||||||
uiBinSetOSParent(w->bin, (uintptr_t) (w->vboxContainer));
|
|
||||||
|
|
||||||
// show everything in the vbox, but not the GtkWindow itself
|
|
||||||
gtk_widget_show_all(w->vboxWidget);
|
|
||||||
|
|
||||||
// and connect our OnClosing() event
|
|
||||||
g_signal_connect(w->widget, "delete-event", G_CALLBACK(onClosing), w);
|
|
||||||
w->onClosing = defaultOnClosing;
|
|
||||||
|
|
||||||
uiControl(w)->Destroy = windowDestroy;
|
|
||||||
uiControl(w)->Handle = windowHandle;
|
|
||||||
uiControl(w)->SetParent = windowSetParent;
|
|
||||||
uiControl(w)->PreferredSize = windowPreferredSize;
|
|
||||||
uiControl(w)->Resize = windowResize;
|
|
||||||
uiControl(w)->Visible = windowVisible;
|
|
||||||
uiControl(w)->Show = windowShow;
|
|
||||||
uiControl(w)->Hide = windowHide;
|
|
||||||
uiControl(w)->Enable = windowEnable;
|
|
||||||
uiControl(w)->Disable = windowDisable;
|
|
||||||
|
|
||||||
uiWindow(w)->Title = windowTitle;
|
|
||||||
uiWindow(w)->SetTitle = windowSetTitle;
|
|
||||||
uiWindow(w)->OnClosing = windowOnClosing;
|
|
||||||
uiWindow(w)->SetChild = windowSetChild;
|
|
||||||
uiWindow(w)->Margined = windowMargined;
|
|
||||||
uiWindow(w)->SetMargined = windowSetMargined;
|
|
||||||
|
|
||||||
return uiWindow(w);
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
# 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
|
|
|
@ -1,196 +0,0 @@
|
||||||
// 26 april 2015
|
|
||||||
#include "uipriv_windows.h"
|
|
||||||
|
|
||||||
|
|
||||||
static LRESULT CALLBACK containerWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
uiContainer *cc;
|
|
||||||
struct container *c;
|
|
||||||
CREATESTRUCTW *cs = (CREATESTRUCTW *) lParam;
|
|
||||||
HWND control;
|
|
||||||
NMHDR *nm = (NMHDR *) lParam;
|
|
||||||
RECT r;
|
|
||||||
HDC dc;
|
|
||||||
PAINTSTRUCT ps;
|
|
||||||
|
|
||||||
cc = uiContainer(GetWindowLongPtrW(hwnd, GWLP_USERDATA));
|
|
||||||
if (cc == NULL)
|
|
||||||
if (uMsg == WM_NCCREATE)
|
|
||||||
SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) (cs->lpCreateParams));
|
|
||||||
// DO NOT RETURN DEFWINDOWPROC() HERE
|
|
||||||
// see the next block of comments as to why
|
|
||||||
// instead, we simply check if c == NULL again later
|
|
||||||
|
|
||||||
switch (uMsg) {
|
|
||||||
|
|
||||||
// these are only run if c is not NULL
|
|
||||||
|
|
||||||
case WM_PAINT:
|
|
||||||
if (cc == NULL)
|
|
||||||
break;
|
|
||||||
c = (struct container *) (uiControl(cc)->Internal);
|
|
||||||
dc = BeginPaint(c->hwnd, &ps);
|
|
||||||
if (dc == NULL)
|
|
||||||
logLastError("error beginning container paint in containerWndProc()");
|
|
||||||
r = ps.rcPaint;
|
|
||||||
paintContainerBackground(c->hwnd, dc, &r);
|
|
||||||
EndPaint(c->hwnd, &ps);
|
|
||||||
return 0;
|
|
||||||
// tab controls use this to draw the background of the tab area
|
|
||||||
case WM_PRINTCLIENT:
|
|
||||||
if (cc == NULL)
|
|
||||||
break;
|
|
||||||
c = (struct container *) (uiControl(cc)->Internal);
|
|
||||||
if (GetClientRect(c->hwnd, &r) == 0)
|
|
||||||
logLastError("error getting client rect in containerWndProc()");
|
|
||||||
paintContainerBackground(c->hwnd, (HDC) wParam, &r);
|
|
||||||
return 0;
|
|
||||||
case WM_ERASEBKGND:
|
|
||||||
// avoid some flicker
|
|
||||||
// we draw the whole update area anyway
|
|
||||||
return 1;
|
|
||||||
case msgUpdateChild:
|
|
||||||
if (cc == NULL)
|
|
||||||
break;
|
|
||||||
c = (struct container *) (uiControl(cc)->Internal);
|
|
||||||
if (GetClientRect(c->hwnd, &r) == 0)
|
|
||||||
logLastError("error getting client rect for resize in containerWndProc()");
|
|
||||||
resize(cc, &r);
|
|
||||||
// we used SWP_NOREDRAW for each resize so we can do this here
|
|
||||||
if (InvalidateRect(c->hwnd, NULL, TRUE) == 0)
|
|
||||||
logLastError("error queueing redraw after resize in containerWndProc()");
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
// subclasses override this and call back here when all children are destroyed
|
|
||||||
static void containerDestroy(uiControl *cc)
|
|
||||||
{
|
|
||||||
struct container *c = (struct container *) (cc->Internal);
|
|
||||||
|
|
||||||
if (c->parent != NULL)
|
|
||||||
complain("attempt to destroy uiContainer %p while it has a parent", cc);
|
|
||||||
if (DestroyWindow(c->hwnd) == 0)
|
|
||||||
logLastError("error destroying uiContainer window in containerDestroy()");
|
|
||||||
uiFree(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uintptr_t containerHandle(uiControl *cc)
|
|
||||||
{
|
|
||||||
struct container *c = (struct container *) (cc->Internal);
|
|
||||||
|
|
||||||
return (uintptr_t) (c->hwnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void containerSetParent(uiControl *cc, uiContainer *parent)
|
|
||||||
{
|
|
||||||
struct container *c = (struct container *) (cc->Internal);
|
|
||||||
uiContainer *oldparent;
|
|
||||||
HWND newparent;
|
|
||||||
|
|
||||||
oldparent = c->parent;
|
|
||||||
c->parent = parent;
|
|
||||||
newparent = initialParent;
|
|
||||||
if (c->parent != NULL)
|
|
||||||
newparent = (HWND) uiControlHandle(uiControl(c->parent));
|
|
||||||
if (SetParent(c->hwnd, newparent) == 0)
|
|
||||||
logLastError("error changing uiContainer parent in containerSetParent()");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void containerResize(uiControl *cc, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d)
|
|
||||||
{
|
|
||||||
struct container *c = (struct container *) (cc->Internal);
|
|
||||||
|
|
||||||
moveAndReorderWindow(c->hwnd, d->Sys->InsertAfter, x, y, width, height);
|
|
||||||
d->Sys->InsertAfter = c->hwnd;
|
|
||||||
SendMessageW(c->hwnd, msgUpdateChild, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int containerVisible(uiControl *cc)
|
|
||||||
{
|
|
||||||
struct container *c = (struct container *) (cc->Internal);
|
|
||||||
|
|
||||||
return !c->hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void containerShow(uiControl *cc)
|
|
||||||
{
|
|
||||||
struct container *c = (struct container *) (cc->Internal);
|
|
||||||
|
|
||||||
ShowWindow(c->hwnd, SW_SHOW);
|
|
||||||
// hidden controls don't count in boxes and grids
|
|
||||||
c->hidden = 0;
|
|
||||||
if (c->parent != NULL)
|
|
||||||
uiContainerUpdate(c->parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void containerHide(uiControl *cc)
|
|
||||||
{
|
|
||||||
struct container *c = (struct container *) (cc->Internal);
|
|
||||||
|
|
||||||
ShowWindow(c->hwnd, SW_HIDE);
|
|
||||||
c->hidden = 1;
|
|
||||||
if (c->parent != NULL)
|
|
||||||
uiContainerUpdate(c->parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void containerEnable(uiControl *cc)
|
|
||||||
{
|
|
||||||
struct container *c = (struct container *) (cc->Internal);
|
|
||||||
uiControlSysFuncParams p;
|
|
||||||
|
|
||||||
EnableWindow(c->hwnd, TRUE);
|
|
||||||
p.Func = uiWindowsSysFuncContainerEnable;
|
|
||||||
uiControlSysFunc(cc, &p);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void containerDisable(uiControl *cc)
|
|
||||||
{
|
|
||||||
struct container *c = (struct container *) (cc->Internal);
|
|
||||||
uiControlSysFuncParams p;
|
|
||||||
|
|
||||||
EnableWindow(c->hwnd, FALSE);
|
|
||||||
p.Func = uiWindowsSysFuncContainerDisable;
|
|
||||||
uiControlSysFunc(cc, &p);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void containerUpdate(uiContainer *cc)
|
|
||||||
{
|
|
||||||
struct container *c = (struct container *) (uiControl(cc)->Internal);
|
|
||||||
|
|
||||||
SendMessageW(c->hwnd, msgUpdateChild, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void uiMakeContainer(uiContainer *cc)
|
|
||||||
{
|
|
||||||
struct container *c;
|
|
||||||
|
|
||||||
c = uiNew(struct container);
|
|
||||||
|
|
||||||
c->hwnd = CreateWindowExW(WS_EX_CONTROLPARENT,
|
|
||||||
containerClass, L"",
|
|
||||||
WS_CHILD | WS_VISIBLE,
|
|
||||||
0, 0,
|
|
||||||
100, 100,
|
|
||||||
initialParent, NULL, hInstance, cc);
|
|
||||||
if (c->hwnd == NULL)
|
|
||||||
logLastError("error creating uiContainer window in uiMakeContainer()");
|
|
||||||
|
|
||||||
uiControl(cc)->Internal = c;
|
|
||||||
uiControl(cc)->Destroy = containerDestroy;
|
|
||||||
uiControl(cc)->Handle = containerHandle;
|
|
||||||
uiControl(cc)->SetParent = containerSetParent;
|
|
||||||
// PreferredSize() is provided by subclasses
|
|
||||||
uiControl(cc)->Resize = containerResize;
|
|
||||||
uiControl(cc)->Visible = containerVisible;
|
|
||||||
uiControl(cc)->Show = containerShow;
|
|
||||||
uiControl(cc)->Hide = containerHide;
|
|
||||||
uiControl(cc)->Enable = containerEnable;
|
|
||||||
uiControl(cc)->Disable = containerDisable;
|
|
||||||
|
|
||||||
// ResizeChildren() is provided by subclasses
|
|
||||||
uiContainer(cc)->Update = containerUpdate;
|
|
||||||
}
|
|
|
@ -1,96 +0,0 @@
|
||||||
// 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 "../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