Removed a whole bunch of files from the old source tree.

This commit is contained in:
Pietro Gagliardi 2015-04-28 13:51:13 -04:00
parent ca487ad18d
commit bf401201f9
14 changed files with 0 additions and 1460 deletions

397
box.c
View File

@ -1,397 +0,0 @@
// 7 april 2015
#include "uipriv.h"
typedef struct box box;
typedef struct boxControl boxControl;
struct box {
uiBox s;
boxControl *controls;
uintmax_t len;
uintmax_t cap;
int vertical;
uiParent *parent;
int padded;
int userHid;
int containerHid;
int userDisabled;
int containerDisabled;
};
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)
{
box *b = (box *) c;
uintmax_t i;
if (b->parent != NULL)
complain("attempt to destroy a uiControl at %p while it still has a parent %p", c, b->parent);
for (i = 0; i < b->len; i++)
uiControlDestroy(b->controls[i].c);
uiFree(b->controls);
uiFree(b);
}
static uintptr_t boxHandle(uiControl *c)
{
return 0;
}
static void boxSetParent(uiControl *c, uiParent *parent)
{
box *b = (box *) c;
uintmax_t i;
uiParent *oldparent;
oldparent = b->parent;
b->parent = parent;
for (i = 0; i < b->len; i++)
uiControlSetParent(b->controls[i].c, b->parent);
if (oldparent != NULL)
uiParentUpdate(oldparent);
if (b->parent != NULL)
uiParentUpdate(b->parent);
}
static void boxPreferredSize(uiControl *c, uiSizing *d, intmax_t *width, intmax_t *height)
{
box *b = (box *) c;
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->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
if (b->vertical)
*height = (b->len - 1) * ypadding;
else
*width = (b->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->len; i++) {
if (!uiControlVisible(b->controls[i].c))
continue;
uiControlPreferredSize(b->controls[i].c, d, &preferredWidth, &preferredHeight);
if (b->controls[i].stretchy) {
nStretchy++;
if (maxStretchyWidth < preferredWidth)
maxStretchyWidth = preferredWidth;
if (maxStretchyHeight < preferredHeight)
maxStretchyHeight = preferredHeight;
}
if (b->vertical) {
if (*width < preferredWidth)
*width = preferredWidth;
if (!b->controls[i].stretchy)
*height += preferredHeight;
} else {
if (!b->controls[i].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 boxResize(uiControl *c, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d)
{
box *b = (box *) c;
int xpadding, ypadding;
uintmax_t nStretchy;
intmax_t stretchywid, stretchyht;
uintmax_t i;
intmax_t preferredWidth, preferredHeight;
if (b->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
if (b->vertical)
height -= (b->len - 1) * ypadding;
else
width -= (b->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->len; i++) {
if (!uiControlVisible(b->controls[i].c))
continue;
if (b->controls[i].stretchy) {
nStretchy++;
continue;
}
uiControlPreferredSize(b->controls[i].c, d, &preferredWidth, &preferredHeight);
if (b->vertical) { // all controls have same width
b->controls[i].width = width;
b->controls[i].height = preferredHeight;
stretchyht -= preferredHeight;
} else { // all controls have same height
b->controls[i].width = preferredWidth;
b->controls[i].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->len; i++) {
if (!uiControlVisible(b->controls[i].c))
continue;
if (b->controls[i].stretchy) {
b->controls[i].width = stretchywid;
b->controls[i].height = stretchyht;
}
}
// 3) now we can position controls
for (i = 0; i < b->len; i++) {
if (!uiControlVisible(b->controls[i].c))
continue;
uiControlResize(b->controls[i].c, x, y, b->controls[i].width, b->controls[i].height, d);
if (b->vertical)
y += b->controls[i].height + ypadding;
else
x += b->controls[i].width + xpadding;
}
}
static int boxVisible(uiControl *c)
{
box *b = (box *) c;
return !(b->userHid);
}
static void boxShow(uiControl *c)
{
box *b = (box *) c;
uintmax_t i;
b->userHid = 0;
if (!b->containerHid) {
for (i = 0; i < b->len; i++)
uiControlContainerShow(b->controls[i].c);
if (b->parent != NULL)
uiParentUpdate(b->parent);
}
}
static void boxHide(uiControl *c)
{
box *b = (box *) c;
uintmax_t i;
b->userHid = 1;
for (i = 0; i < b->len; i++)
uiControlContainerHide(b->controls[i].c);
if (b->parent != NULL)
uiParentUpdate(b->parent);
}
static void boxContainerShow(uiControl *c)
{
box *b = (box *) c;
uintmax_t i;
b->containerHid = 0;
if (!b->userHid) {
for (i = 0; i < b->len; i++)
uiControlContainerShow(b->controls[i].c);
if (b->parent != NULL)
uiParentUpdate(b->parent);
}
}
static void boxContainerHide(uiControl *c)
{
box *b = (box *) c;
uintmax_t i;
b->containerHid = 1;
for (i = 0; i < b->len; i++)
uiControlContainerHide(b->controls[i].c);
if (b->parent != NULL)
uiParentUpdate(b->parent);
}
static void boxEnable(uiControl *c)
{
box *b = (box *) c;
uintmax_t i;
b->userDisabled = 0;
if (!b->containerDisabled)
for (i = 0; i < b->len; i++)
uiControlContainerEnable(b->controls[i].c);
}
static void boxDisable(uiControl *c)
{
box *b = (box *) c;
uintmax_t i;
b->userDisabled = 1;
for (i = 0; i < b->len; i++)
uiControlContainerDisable(b->controls[i].c);
}
static void boxContainerEnable(uiControl *c)
{
box *b = (box *) c;
uintmax_t i;
b->containerDisabled = 0;
if (!b->userDisabled)
for (i = 0; i < b->len; i++)
uiControlContainerEnable(b->controls[i].c);
}
static void boxContainerDisable(uiControl *c)
{
box *b = (box *) c;
uintmax_t i;
b->containerDisabled = 1;
for (i = 0; i < b->len; i++)
uiControlContainerDisable(b->controls[i].c);
}
#define boxCapGrow 32
static void boxAppend(uiBox *ss, uiControl *c, int stretchy)
{
box *b = (box *) ss;
if (b->len >= b->cap) {
b->cap += boxCapGrow;
b->controls = (boxControl *) uiRealloc(b->controls, b->cap * sizeof (boxControl), "boxControl[]");
}
b->controls[b->len].c = c;
b->controls[b->len].stretchy = stretchy;
b->len++; // must be here for parent updates to work
if (b->parent != NULL) {
uiControlSetParent(b->controls[b->len - 1].c, b->parent);
uiParentUpdate(b->parent);
}
}
static void boxDelete(uiBox *ss, uintmax_t index)
{
box *b = (box *) ss;
uiControl *removed;
uintmax_t i;
removed = b->controls[index].c;
// TODO switch to memmove?
for (i = index; i < b->len - 1; i++)
b->controls[i] = b->controls[i + 1];
// TODO memset the last one to NULL
b->len--;
if (b->parent != NULL) {
uiControlSetParent(removed, NULL);
uiParentUpdate(b->parent);
}
}
static int boxPadded(uiBox *ss)
{
box *b = (box *) ss;
return b->padded;
}
static void boxSetPadded(uiBox *ss, int padded)
{
box *b = (box *) ss;
b->padded = padded;
if (b->parent != NULL)
uiParentUpdate(b->parent);
}
uiBox *uiNewHorizontalBox(void)
{
box *b;
b = uiNew(box);
uiControl(b)->Destroy = boxDestroy;
uiControl(b)->Handle = boxHandle;
uiControl(b)->SetParent = boxSetParent;
uiControl(b)->PreferredSize = boxPreferredSize;
uiControl(b)->Resize = boxResize;
uiControl(b)->Visible = boxVisible;
uiControl(b)->Show = boxShow;
uiControl(b)->Hide = boxHide;
uiControl(b)->ContainerShow = boxContainerShow;
uiControl(b)->ContainerHide = boxContainerHide;
uiControl(b)->Enable = boxEnable;
uiControl(b)->Disable = boxDisable;
uiControl(b)->ContainerEnable = boxContainerEnable;
uiControl(b)->ContainerDisable = boxContainerDisable;
uiBox(b)->Append = boxAppend;
uiBox(b)->Delete = boxDelete;
uiBox(b)->Padded = boxPadded;
uiBox(b)->SetPadded = boxSetPadded;
return uiBox(b);
}
uiBox *uiNewVerticalBox(void)
{
uiBox *ss;
box *b;
ss = uiNewHorizontalBox();
b = (box *) ss;
b->vertical = 1;
return ss;
}

View File

@ -1,44 +0,0 @@
// 4 december 2014
#import <stdio.h>
#import "uipriv_darwin.h"
void *uiAlloc(size_t size, const char *type)
{
void *out;
out = malloc(size);
if (out == NULL) {
fprintf(stderr, "memory exhausted in uiAlloc() allocating %s\n", type);
abort();
}
memset(out, 0, size);
if (options.debugLogAllocations)
fprintf(stderr, "%p alloc %s\n", out, type);
return out;
}
void *uiRealloc(void *p, size_t size, const char *type)
{
void *out;
if (p == NULL)
return uiAlloc(size, type);
out = realloc(p, size);
if (out == NULL) {
fprintf(stderr, "memory exhausted in uiRealloc() reallocating %s\n", type);
abort();
}
// TODO zero the extra memory
if (options.debugLogAllocations)
fprintf(stderr, "%p realloc %p\n", p, out);
return out;
}
void uiFree(void *p)
{
if (p == NULL)
return;
free(p);
if (options.debugLogAllocations)
fprintf(stderr, "%p free\n", p);
}

View File

@ -1,19 +0,0 @@
// 10 april 2015
#import "uipriv_darwin.h"
char *uiDarwinNSStringToText(NSString *s)
{
char *out;
out = strdup([s UTF8String]);
if (out == NULL) {
fprintf(stderr, "memory exhausted in uiDarwinNSStringToText()\n");
abort();
}
return out;
}
void uiFreeText(char *s)
{
free(s);
}

View File

@ -1,25 +0,0 @@
// 7 april 2015
#import "uipriv_darwin.h"
// also fine for NSCells and NSTexts (NSTextViews)
void setStandardControlFont(NSControl *control)
{
[control setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]];
}
void disableAutocorrect(NSTextView *tv)
{
[tv setEnabledTextCheckingTypes:0];
[tv setAutomaticDashSubstitutionEnabled:NO];
// don't worry about automatic data detection; it won't change stringValue (thanks pretty_function in irc.freenode.net/#macdev)
[tv setAutomaticSpellingCorrectionEnabled:NO];
[tv setAutomaticTextReplacementEnabled:NO];
[tv setAutomaticQuoteSubstitutionEnabled:NO];
[tv setAutomaticLinkDetectionEnabled:NO];
[tv setSmartInsertDeleteEnabled:NO];
}
void complain(const char *fmt, ...)
{
// TODO
}

View File

@ -1,163 +0,0 @@
// 6 april 2015
#import "uipriv_darwin.h"
// TODO
// - free chilld containers properly
@interface uiWindowDelegate : NSObject <NSWindowDelegate>
@property (assign) NSWindow *w;
@property uiParent *content;
@property int (*onClosing)(uiWindow *, void *);
@property void *onClosingData;
@property struct window *uiw;
@end
@implementation uiWindowDelegate
uiLogObjCClassAllocations
- (BOOL)windowShouldClose:(id)win
{
// return exact constants to be safe
if ((*(self.onClosing))(uiWindow(self.uiw), self.onClosingData))
return YES;
return NO;
}
// after this method returns we assume the window will be released (see below), so we can go too
- (void)windowWillClose:(NSNotification *)note
{
[self.w setDelegate:nil]; // see http://stackoverflow.com/a/29523141/3408572
// just to be safe
[self.w setContentView:[[NSView alloc] initWithFrame:NSZeroRect]];
uiParentDestroy(self.content);
// now we need to release the window too
[self.w release];
// and clean up
uiFree(self.uiw);
[self release];
}
@end
struct window {
uiWindow w;
uiWindowDelegate *d;
int margined;
};
static int defaultOnClosing(uiWindow *w, void *data)
{
return 1;
}
#define D (((struct window *) w)->d)
static void windowDestroy(uiWindow *w)
{
[D.w close];
}
static uintptr_t windowHandle(uiWindow *w)
{
return (uintptr_t) (D.w);
}
static char *windowTitle(uiWindow *w)
{
return uiDarwinNSStringToText([D.w title]);
}
static void windowSetTitle(uiWindow *w, const char *title)
{
[D.w setTitle:toNSString(title)];
}
static void windowShow(uiWindow *w)
{
[D.w makeKeyAndOrderFront:D.w];
}
static void windowHide(uiWindow *w)
{
[D.w orderOut:D.w];
}
static void windowOnClosing(uiWindow *w, int (*f)(uiWindow *, void *), void *data)
{
D.onClosing = f;
D.onClosingData = data;
}
static void windowSetChild(uiWindow *w, uiControl *c)
{
uiParentSetMainControl(D.content, c);
}
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)
uiParentSetMargins(D.content, macXMargin, macYMargin, macXMargin, macYMargin);
else
uiParentSetMargins(D.content, 0, 0, 0, 0);
uiParentUpdate(D.content);
}
uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar)
{
uiWindowDelegate *d;
d = [uiWindowDelegate new];
d.w = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, (CGFloat) width, (CGFloat) height)
styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)
backing:NSBackingStoreBuffered
defer:YES];
[d.w setTitle:toNSString(title)];
// we do not want substitutions
// text fields, labels, etc. take their smart quotes and other autocorrect settings from their parent window, which provides a shared "field editor"
// so we have to turn them off here
// thanks akempgen in irc.freenode.net/#macdev
// for some reason, this selector returns NSText but is documented to return NSTextView...
// NOTE: if you disagree with me about disabling substitutions, start a github issue with why and I'll be happy to consider it
disableAutocorrect((NSTextView *) [d.w fieldEditor:YES forObject:nil]);
// don't release on close; we'll do it ourselves (see above)
[d.w setReleasedWhenClosed:NO];
d.content = uiNewParent(0);
[d.w setContentView:((NSView *) uiParentHandle(d.content))];
d.onClosing = defaultOnClosing;
[d.w setDelegate:d];
d.uiw = uiNew(struct window);
d.uiw->d = d;
uiWindow(d.uiw)->Destroy = windowDestroy;
uiWindow(d.uiw)->Handle = windowHandle;
uiWindow(d.uiw)->Title = windowTitle;
uiWindow(d.uiw)->SetTitle = windowSetTitle;
uiWindow(d.uiw)->Show = windowShow;
uiWindow(d.uiw)->Hide = windowHide;
uiWindow(d.uiw)->OnClosing = windowOnClosing;
uiWindow(d.uiw)->SetChild = windowSetChild;
uiWindow(d.uiw)->Margined = windowMargined;
uiWindow(d.uiw)->SetMargined = windowSetMargined;
return uiWindow(d.uiw);
}

149
ui.idl
View File

@ -1,149 +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 {
// TODO autogenerate this somehow
// TODO alternatively, move AFTER typedefs
raw "#ifndef __UI_UI_H__";
raw "#define __UI_UI_H__";
raw "#include <stdint.h>";
// TODO note that should be initialized to zero
struct InitOptions {
// TODO cbSize
// If nonzero, allocations will be logged to stderr.
// See leaks.awk.
field debugLogAllocations int;
};
func Init(options *InitOptions) *const char;
func FreeInitError(err *const char);
func Main(void);
func Quit(void);
func FreeText(text *char);
raw "typedef struct uiSizingSys uiSizingSys;";
struct Sizing {
field xPadding intmax_t;
field yPadding intmax_t;
field sys *uiSizingSys;
};
interface Control {
field Internal *void; // for use by ui only
func Destroy(void);
func Handle(void) uintptr_t;
func SetHasParent(hasParent int);
func SetOSContainer(c *OSContainer);
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 ContainerShow(void);
func ContainerHide(void);
func Enable(void);
func Disable(void);
func ContainerEnable(void);
func ContainerDisable(void);
};
interface OSContainer {
field Internal *void;
func Destroy(void);
func Handle(void) uintptr_t;
func SetMainControl(c *Control);
func SetMargins(left intmax_t, top intmax_t, right intmax_t, bottom intmax_t);
func Update(void);
};
func NewOSContainer(osParent uintptr_t) *OSContainer;
interface Window {
field Internal *void;
func Destroy(void);
func Handle(void) uintptr_t;
func Title(void) *char;
func SetTitle(title *const char);
func Show(void);
func Hide(void);
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 Control {
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 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 {
// TODO rename to AppendPage()
func AddPage(name *const char, c *Control);
func DeletePage(index uintmax_t);
};
func NewTab(void) *Tab;
interface Menu {
func AddItem(name string) *MenuItem;
func AddCheckItem(name string) *MenuItem;
func AddQuitItem(void) *MenuItem;
func AddPreferencesItem(void) *MenuItem;
func AddAboutItem(void) *MenuItem;
func AddSeparator(void);
};
func NewMenu(name string) *Menu;
interface MenuItem {
func Enable(void);
func Disable(void);
func OnClicked(f *func(sender *void, data *void), data *void);
func Checked(void) int;
func SetChecked(checked int);
};
raw "#endif";
};

View File

@ -1,33 +0,0 @@
// 7 april 2015
#include <stdio.h>
#include "uipriv_unix.h"
void *uiAlloc(size_t size, const char *type)
{
void *out;
out = g_malloc0(size);
if (options.debugLogAllocations)
fprintf(stderr, "%p alloc %s\n", out, type);
return out;
}
void *uiRealloc(void *p, size_t size, const char *type)
{
void *out;
if (p == NULL)
return uiAlloc(size, type);
// TODO fill with 0s
out = g_realloc(p, size);
if (options.debugLogAllocations)
fprintf(stderr, "%p realloc %p\n", p, out);
return out;
}
void uiFree(void *p)
{
g_free(p);
if (options.debugLogAllocations)
fprintf(stderr, "%p free\n", p);
}

View File

@ -1,7 +0,0 @@
// 9 april 2015
#include "uipriv_unix.h"
void uiFreeText(char *t)
{
g_free(t);
}

View File

@ -1,13 +0,0 @@
// 18 april 2015
#include "uipriv_unix.h"
void complain(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
// there's no g_errorv() in glib 2.32, so do it manually instead
g_logv(G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, fmt, ap);
va_end(ap);
abort(); // just in case
}

View File

@ -1,172 +0,0 @@
// 6 april 2015
#include "uipriv_unix.h"
struct window {
uiWindow w;
GtkWidget *widget;
GtkContainer *container;
GtkWindow *window;
uiParent *content;
int (*onClosing)(uiWindow *, void *);
void *onClosingData;
int margined;
gulong destroyBlocker;
};
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))
uiWindowDestroy(uiWindow(w));
return TRUE; // don't continue to the default delete-event handler; we destroyed the window by now
}
static int defaultOnClosing(uiWindow *w, void *data)
{
return 1;
}
static void destroyBlocker(GtkWidget *widget, gpointer data)
{
complain("attempt to dispose uiWindow at %p before uiWindowDestroy()", data);
}
// TODO should we change the GtkWindow's child first?
static void windowDestroy(uiWindow *ww)
{
struct window *w = (struct window *) ww;
// first, hide the window to prevent our cleanup from being noticed
gtk_widget_hide(w->widget);
// next, destroy the content uiParent
uiParentDestroy(w->content);
// now that we cleaned up properly, we can mark our window as ready to be destroyed
g_signal_handler_disconnect(w->widget, w->destroyBlocker);
// finally, destroy the window
gtk_widget_destroy(w->widget);
// and free ourselves
uiFree(w);
}
static uintptr_t windowHandle(uiWindow *ww)
{
struct window *w = (struct window *) ww;
return (uintptr_t) (w->widget);
}
static char *windowTitle(uiWindow *ww)
{
struct window *w = (struct window *) ww;
return g_strdup(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 windowShow(uiWindow *ww)
{
struct window *w = (struct window *) ww;
// don't use gtk_widget_show_all(); that will override user hidden settings
gtk_widget_show(w->widget);
}
static void windowHide(uiWindow *ww)
{
struct window *w = (struct window *) ww;
gtk_widget_hide(w->widget);
}
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 *c)
{
struct window *w = (struct window *) ww;
uiParentSetMainControl(w->content, c);
uiParentUpdate(w->content);
}
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)
uiParentSetMargins(w->content, gtkXMargin, gtkYMargin, gtkXMargin, gtkYMargin);
else
uiParentSetMargins(w->content, 0, 0, 0, 0);
uiParentUpdate(w->content);
}
uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar)
{
struct window *w;
GtkWidget *vbox;
GtkWidget *contentWidget;
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);
// TODO this does not take menus or CSD into account
gtk_window_resize(w->window, width, height);
g_signal_connect(w->widget, "delete-event", G_CALLBACK(onClosing), w);
w->destroyBlocker = g_signal_connect(w->widget, "destroy", G_CALLBACK(destroyBlocker), w);
if (hasMenubar) {
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_show_all(vbox);
gtk_container_add(w->container, vbox);
gtk_container_add(GTK_CONTAINER(vbox), makeMenubar());
w->content = uiNewParent((uintptr_t) GTK_CONTAINER(vbox));
contentWidget = GTK_WIDGET(uiParentHandle(w->content));
gtk_widget_set_hexpand(contentWidget, TRUE);
gtk_widget_set_halign(contentWidget, GTK_ALIGN_FILL);
gtk_widget_set_vexpand(contentWidget, TRUE);
gtk_widget_set_valign(contentWidget, GTK_ALIGN_FILL);
} else
w->content = uiNewParent((uintptr_t) (w->container));
w->onClosing = defaultOnClosing;
uiWindow(w)->Destroy = windowDestroy;
uiWindow(w)->Handle = windowHandle;
uiWindow(w)->Title = windowTitle;
uiWindow(w)->SetTitle = windowSetTitle;
uiWindow(w)->Show = windowShow;
uiWindow(w)->Hide = windowHide;
uiWindow(w)->OnClosing = windowOnClosing;
uiWindow(w)->SetChild = windowSetChild;
uiWindow(w)->Margined = windowMargined;
uiWindow(w)->SetMargined = windowSetMargined;
return uiWindow(w);
}

View File

@ -1,49 +0,0 @@
// 4 december 2014
#include "uipriv_windows.h"
// wrappers for allocator of choice
// panics on memory exhausted, undefined on heap corruption or other unreliably-detected malady (see http://stackoverflow.com/questions/28761680/is-there-a-windows-api-memory-allocator-deallocator-i-can-use-that-will-just-giv)
// new memory is set to zero
// passing NULL to tableRealloc() acts like tableAlloc()
// passing NULL to tableFree() is a no-op
void *uiAlloc(size_t size, const char *type)
{
void *out;
out = malloc(size);
if (out == NULL) {
fprintf(stderr, "memory exhausted in uiAlloc() allocating %s\n", type);
abort();
}
ZeroMemory(out, size);
if (options.debugLogAllocations)
fprintf(stderr, "%p alloc %s\n", out, type);
return out;
}
void *uiRealloc(void *p, size_t size, const char *type)
{
void *out;
if (p == NULL)
return uiAlloc(size, type);
out = realloc(p, size);
if (out == NULL) {
fprintf(stderr, "memory exhausted in uiRealloc() reallocating %s\n", type);
abort();
}
// TODO zero the extra memory
if (options.debugLogAllocations)
fprintf(stderr, "%p realloc %p\n", p, out);
return out;
}
void uiFree(void *p)
{
if (p == NULL)
return;
free(p);
if (options.debugLogAllocations)
fprintf(stderr, "%p free\n", p);
}

View File

@ -1,55 +0,0 @@
// 9 april 2015
#include "uipriv_windows.h"
// see http://stackoverflow.com/a/29556509/3408572
#define MBTWC(str, wstr, bufsiz) MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, bufsiz)
WCHAR *toUTF16(const char *str)
{
WCHAR *wstr;
int n;
n = MBTWC(str, NULL, 0);
if (n == 0)
logLastError("error figuring out number of characters to convert to in toUTF16()");
wstr = (WCHAR *) uiAlloc(n * sizeof (WCHAR), "WCHAR[]");
if (MBTWC(str, wstr, n) != n)
logLastError("error converting from UTF-8 to UTF-16 in toUTF16()");
return wstr;
}
#define WCTMB(wstr, str, bufsiz) WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, bufsiz, NULL, NULL)
char *toUTF8(const WCHAR *wstr)
{
char *str;
int n;
n = WCTMB(wstr, NULL, 0);
if (n == 0)
logLastError("error figuring out number of characters to convert to in toUTF8()");
str = (char *) uiAlloc(n * sizeof (char), "char[]");
if (WCTMB(wstr, str, n) != n)
logLastError("error converting from UTF-16 to UTF-8 in toUTFF8()");
return str;
}
WCHAR *windowText(HWND hwnd)
{
LRESULT n;
WCHAR *text;
n = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
// WM_GETTEXTLENGTH does not include the null terminator
text = (WCHAR *) uiAlloc((n + 1) * sizeof (WCHAR), "WCHAR[]");
// note the comparison: the size includes the null terminator, but the return does not
if (GetWindowTextW(hwnd, text, n + 1) != n)
logLastError("error getting window text in windowText()");
return text;
}
void uiFreeText(char *text)
{
uiFree(text);
}

View File

@ -1,83 +0,0 @@
// 6 april 2015
#include "uipriv_windows.h"
intmax_t uiWindowsWindowTextWidth(HWND hwnd)
{
LRESULT len;
WCHAR *text;
HDC dc;
HFONT prevfont;
SIZE size;
size.cx = 0;
size.cy = 0;
// first we need the window text
len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
if (len == 0) // no text; nothing to do
return 0;
text = (WCHAR *) uiAlloc((len + 1) * sizeof (WCHAR), "WCHAR[]");
// note the comparison: the size includes the null terminator, but the return does not
if (GetWindowText(hwnd, text, len + 1) != len)
logLastError("error getting window text in uiWindowsWindowTextWidth()");
// now we can do the calculations
dc = GetDC(hwnd);
if (dc == NULL)
logLastError("error getting DC in uiWindowsWindowTextWidth()");
prevfont = (HFONT) SelectObject(dc, hMessageFont);
if (prevfont == NULL)
logLastError("error loading control font into device context in uiWindowsWindowTextWidth()");
if (GetTextExtentPoint32W(dc, text, len, &size) == 0)
logLastError("error getting text extent point in uiWindowsWindowTextWidth()");
if (SelectObject(dc, prevfont) != hMessageFont)
logLastError("error restoring previous font into device context in uiWindowsWindowTextWidth()");
if (ReleaseDC(hwnd, dc) == 0)
logLastError("error releasing DC in uiWindowsWindowTextWidth()");
uiFree(text);
return size.cx;
}
// this is a helper function that takes the logic of determining window classes and puts it all in one place
// there are a number of places where we need to know what window class an arbitrary handle has
// theoretically we could use the class atom to avoid a _wcsicmp()
// however, raymond chen advises against this - http://blogs.msdn.com/b/oldnewthing/archive/2004/10/11/240744.aspx (and we're not in control of the Tab class, before you say anything)
// usage: windowClassOf(hwnd, L"class 1", L"class 2", ..., NULL)
int windowClassOf(HWND hwnd, ...)
{
// MSDN says 256 is the maximum length of a class name; add a few characters just to be safe (because it doesn't say whether this includes the terminating null character)
#define maxClassName 260
WCHAR classname[maxClassName + 1];
va_list ap;
WCHAR *curname;
int i;
if (GetClassNameW(hwnd, classname, maxClassName) == 0)
logLastError("error getting name of window class in windowClassOf()");
va_start(ap, hwnd);
i = 0;
for (;;) {
curname = va_arg(ap, WCHAR *);
if (curname == NULL)
break;
if (_wcsicmp(classname, curname) == 0) {
va_end(ap);
return i;
}
i++;
}
// no match
va_end(ap);
return -1;
}
void complain(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
abort();
}

View File

@ -1,251 +0,0 @@
// 6 april 2015
#include "uipriv_windows.h"
struct window {
uiWindow w;
HWND hwnd;
uiParent *content;
BOOL shownOnce;
int (*onClosing)(uiWindow *, void *);
void *onClosingData;
int margined;
BOOL canDestroy;
};
#define uiWindowClass L"uiWindowClass"
static LRESULT CALLBACK uiWindowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
struct window *w;
CREATESTRUCTW *cs = (CREATESTRUCTW *) lParam;
WINDOWPOS *wp = (WINDOWPOS *) lParam;
RECT r;
HWND contenthwnd;
const uiMenuItem *item;
w = (struct window *) GetWindowLongPtrW(hwnd, GWLP_USERDATA);
if (w == NULL) {
if (uMsg == WM_CREATE)
SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) (cs->lpCreateParams));
// fall through to DefWindowProc() anyway
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
switch (uMsg) {
case WM_COMMAND:
// not a menu
if (lParam != 0)
break;
if (HIWORD(wParam) != 0)
break;
item = menuIDToItem(LOWORD(wParam));
printf("%d", item->Type);
if (item->Type == uiMenuItemTypeCommand)
printf(" %s", item->Name);
printf("\n");
return 0;
case WM_WINDOWPOSCHANGED:
if ((wp->flags & SWP_NOSIZE) != 0)
break;
// fall through
case msgUpdateChild:
if (GetClientRect(w->hwnd, &r) == 0)
logLastError("error getting window client rect for resize in uiWindowWndProc()");
contenthwnd = uiParentHWND(w->content);
if (MoveWindow(contenthwnd, r.left, r.top, r.right - r.left, r.bottom - r.top, TRUE) == 0)
logLastError("error resizing window content parent in uiWindowWndProc()");
return 0;
case WM_CLOSE:
if (!(*(w->onClosing))(uiWindow(w), w->onClosingData))
uiWindowDestroy(uiWindow(w));
return 0; // we destroyed it already
case WM_DESTROY:
if (!w->canDestroy)
complain("attempt to destroy uiWindow at %p before uiWindowDestroy()", w);
uiFree(w);
break; // fall through to DefWindowProcW()
}
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
ATOM registerWindowClass(HICON hDefaultIcon, HCURSOR hDefaultCursor)
{
WNDCLASSW wc;
ZeroMemory(&wc, sizeof (WNDCLASSW));
wc.lpszClassName = uiWindowClass;
wc.lpfnWndProc = uiWindowWndProc;
wc.hInstance = hInstance;
wc.hIcon = hDefaultIcon;
wc.hCursor = hDefaultCursor;
wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
return RegisterClassW(&wc);
}
#define exstyle 0
#define style WS_OVERLAPPEDWINDOW
static int defaultOnClosing(uiWindow *w, void *data)
{
return 1;
}
static void windowDestroy(uiWindow *ww)
{
struct window *w = (struct window *) ww;
// first destroy the content
uiParentDestroy(w->content);
// then mark that we're ready to destroy
w->canDestroy = TRUE;
// and finally destroy
// TODO check for errors
DestroyWindow(w->hwnd);
// no need to explicitly destroy the menubar, if any; that's done automatically during window destruction
}
static uintptr_t windowHandle(uiWindow *ww)
{
struct window *w = (struct window *) ww;
return (uintptr_t) (w->hwnd);
}
static char *windowTitle(uiWindow *ww)
{
struct window *w = (struct window *) ww;
WCHAR *wtext;
char *text;
wtext = windowText(w->hwnd);
text = toUTF8(wtext);
uiFree(wtext);
return text;
}
static void windowSetTitle(uiWindow *ww, const char *text)
{
struct window *w = (struct window *) ww;
WCHAR *wtext;
wtext = toUTF16(text);
if (SetWindowTextW(w->hwnd, wtext) == 0)
logLastError("error setting window title in uiWindowSetTitle()");
uiFree(wtext);
}
static void windowShow(uiWindow *ww)
{
struct window *w = (struct window *) ww;
if (w->shownOnce) {
ShowWindow(w->hwnd, SW_SHOW);
return;
}
w->shownOnce = TRUE;
ShowWindow(w->hwnd, nCmdShow);
if (UpdateWindow(w->hwnd) == 0)
logLastError("error calling UpdateWindow() after showing uiWindow for the first time");
}
static void windowHide(uiWindow *ww)
{
struct window *w = (struct window *) ww;
ShowWindow(w->hwnd, SW_HIDE);
}
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 *c)
{
struct window *w = (struct window *) ww;
uiParentSetMainControl(w->content, c);
// don't call uiParentUpdate(); instead, synthesize a resize
// otherwise, we'll have a 0x0 content area at first
SendMessageW(w->hwnd, msgUpdateChild, 0, 0);
}
static int windowMargined(uiWindow *ww)
{
struct window *w = (struct window *) ww;
return w->margined;
}
// from https://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
#define windowMargin 7
static void windowSetMargined(uiWindow *ww, int margined)
{
struct window *w = (struct window *) ww;
w->margined = margined;
if (w->margined)
uiParentSetMargins(w->content, windowMargin, windowMargin, windowMargin, windowMargin);
else
uiParentSetMargins(w->content, 0, 0, 0, 0);
uiParentUpdate(w->content);
}
uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar)
{
struct window *w;
RECT adjust;
WCHAR *wtitle;
BOOL hasMenubarBOOL;
HMENU hmenu;
w = uiNew(struct window);
w->onClosing = defaultOnClosing;
hasMenubarBOOL = FALSE;
if (hasMenubar)
hasMenubarBOOL = TRUE;
adjust.left = 0;
adjust.top = 0;
adjust.right = width;
adjust.bottom = height;
// TODO does not handle menu wrapping; see http://blogs.msdn.com/b/oldnewthing/archive/2003/09/11/54885.aspx
if (AdjustWindowRectEx(&adjust, style, hasMenubarBOOL, exstyle) == 0)
logLastError("error getting real window coordinates in uiWindow()");
wtitle = toUTF16(title);
w->hwnd = CreateWindowExW(exstyle,
uiWindowClass, wtitle,
style,
CW_USEDEFAULT, CW_USEDEFAULT,
adjust.right - adjust.left, adjust.bottom - adjust.top,
NULL, NULL, hInstance, w);
if (w->hwnd == NULL)
logLastError("error creating window in uiWindow()");
uiFree(wtitle);
w->content = uiNewParent((uintptr_t) (w->hwnd));
if (hasMenubar) {
hmenu = makeMenubar();
if (SetMenu(w->hwnd, hmenu) == 0)
logLastError("error giving menu to window in uiNewWindow()");
}
uiWindow(w)->Destroy = windowDestroy;
uiWindow(w)->Handle = windowHandle;
uiWindow(w)->Title = windowTitle;
uiWindow(w)->SetTitle = windowSetTitle;
uiWindow(w)->Show = windowShow;
uiWindow(w)->Hide = windowHide;
uiWindow(w)->OnClosing = windowOnClosing;
uiWindow(w)->SetChild = windowSetChild;
uiWindow(w)->Margined = windowMargined;
uiWindow(w)->SetMargined = windowSetMargined;
return uiWindow(w);
}