More migration.

This commit is contained in:
Pietro Gagliardi 2015-08-16 22:30:44 -04:00
parent 705f81d7e4
commit f95b9c1204
9 changed files with 471 additions and 0 deletions

View File

@ -0,0 +1,84 @@
// 4 december 2014
#import <stdlib.h>
#import "uipriv_darwin.h"
NSMutableArray *allocations;
void initAlloc(void)
{
allocations = [NSMutableArray new];
}
#define UINT8(p) ((uint8_t *) (p))
#define PVOID(p) ((void *) (p))
#define EXTRA (sizeof (size_t) + sizeof (const char **))
#define DATA(p) PVOID(UINT8(p) + EXTRA)
#define BASE(p) PVOID(UINT8(p) - EXTRA)
#define SIZE(p) ((size_t *) (p))
#define CCHAR(p) ((const char **) (p))
#define TYPE(p) CCHAR(UINT8(p) + sizeof (size_t))
void uninitAlloc(void)
{
if ([allocations count] == 0) {
[allocations release];
return;
}
fprintf(stderr, "[libui] leaked allocations:\n");
[allocations enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL *stop) {
NSValue *v;
void *ptr;
v = (NSValue *) obj;
ptr = [v pointerValue];
fprintf(stderr, "[libui] %p %s\n", ptr, *TYPE(ptr));
}];
complain("either you left something around or there's a bug in libui");
}
void *uiAlloc(size_t size, const char *type)
{
void *out;
out = malloc(EXTRA + size);
if (out == NULL) {
fprintf(stderr, "memory exhausted in uiAlloc()\n");
abort();
}
memset(DATA(out), 0, size);
*SIZE(out) = size;
*TYPE(out) = type;
[allocations addObject:[NSValue valueWithPointer:out]];
return DATA(out);
}
void *uiRealloc(void *p, size_t new, const char *type)
{
void *out;
size_t *s;
if (p == NULL)
return uiAlloc(new, type);
p = BASE(p);
out = realloc(p, EXTRA + new);
if (out == NULL) {
fprintf(stderr, "memory exhausted in uiRealloc()\n");
abort();
}
s = SIZE(out);
if (new <= *s)
memset(((uint8_t *) DATA(out)) + *s, 0, new - *s);
*s = new;
[allocations removeObject:[NSValue valueWithPointer:p]];
[allocations addObject:[NSValue valueWithPointer:out]];
return DATA(out);
}
void uiFree(void *p)
{
if (p == NULL)
complain("attempt to uiFree(NULL); there's a bug somewhere");
p = BASE(p);
free(p);
[allocations removeObject:[NSValue valueWithPointer:p]];
}

110
redo/reredo/darwin/main.m Normal file
View File

@ -0,0 +1,110 @@
// 6 april 2015
#import "uipriv_darwin.h"
static BOOL canQuit = NO;
@implementation applicationClass
// hey look! we're overriding terminate:!
// we're going to make sure we can go back to main() whether Cocoa likes it or not!
// and just how are we going to do that, hm?
// (note: this is called after applicationShouldTerminate:)
- (void)terminate:(id)sender
{
// yes that's right folks: DO ABSOLUTELY NOTHING.
// the magic is [NSApp run] will just... stop.
// well let's not do nothing; let's actually quit our graceful way
NSEvent *e;
// for debugging
NSLog(@"in terminate:");
if (!canQuit)
complain("call to [NSApp terminate:] when not ready to terminate");
[realNSApp() stop:realNSApp()];
// stop: won't register until another event has passed; let's synthesize one
e = [NSEvent otherEventWithType:NSApplicationDefined
location:NSZeroPoint
modifierFlags:0
timestamp:[[NSProcessInfo processInfo] systemUptime]
windowNumber:0
context:[NSGraphicsContext currentContext]
subtype:0
data1:0
data2:0];
[realNSApp() postEvent:e atStart:NO]; // let pending events take priority (this is what PostQuitMessage() on Windows does so we have to do it here too for parity; thanks to mikeash in irc.freenode.net/#macdev for confirming that this parameter should indeed be NO)
}
@end
@implementation appDelegate
- (void)dealloc
{
[self.menuManager release];
[super dealloc];
}
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)app
{
// for debugging
NSLog(@"in applicationShouldTerminate:");
if (shouldQuit()) {
canQuit = YES;
// this will call terminate:, which is the same as uiQuit()
return NSTerminateNow;
}
return NSTerminateCancel;
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app
{
return NO;
}
@end
uiInitOptions options;
const char *uiInit(uiInitOptions *o)
{
options = *o;
[applicationClass sharedApplication];
// don't check for a NO return; something (launch services?) causes running from application bundles to always return NO when asking to change activation policy, even if the change is to the same activation policy!
// see https://github.com/andlabs/ui/issues/6
[realNSApp() setActivationPolicy:NSApplicationActivationPolicyRegular];
[realNSApp() setDelegate:[appDelegate new]];
initAlloc();
// always do this so we always have an application menu
appDelegate().menuManager = [menuManager new];
[realNSApp() setMainMenu:[appDelegate().menuManager makeMenubar]];
return NULL;
}
void uiUninit(void)
{
uninitMenus();
// TODO free application delegate
// TODO free NSApplication resources (main menu, etc.)
uninitAlloc();
}
void uiFreeInitError(const char *err)
{
}
void uiMain(void)
{
[realNSApp() run];
}
void uiQuit(void)
{
canQuit = YES;
[realNSApp() terminate:realNSApp()];
}

View File

@ -0,0 +1,24 @@
// 26 june 2015
#import "uipriv_darwin.h"
char *uiOpenFile(void)
{
// TODO
return NULL;
}
char *uiSaveFile(void)
{
// TODO
return NULL;
}
void uiMsgBox(const char *title, const char *description)
{
// TODO
}
void uiMsgBoxError(const char *title, const char *description)
{
// TODO
}

19
redo/reredo/darwin/text.m Normal file
View File

@ -0,0 +1,19 @@
// 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);
}

56
redo/reredo/darwin/util.m Normal file
View File

@ -0,0 +1,56 @@
// 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, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "[libui] ");
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
abort();
}
// These are based on measurements from Interface Builder.
// These seem to be based on Auto Layout constants, but I don't see an API that exposes these...
// This one is 8 for most pairs of controls that I've tried; the only difference is between two pushbuttons, where it's 12...
#define macXPadding 8
// Likewise, this one appears to be 12 for pairs of push buttons...
#define macYPadding 8
uiSizing *uiDarwinNewSizing(void)
{
uiSizing *d;
d = uiNew(uiSizing);
d->XPadding = macXPadding;
d->YPadding = macYPadding;
d->Sys = uiNew(uiSizingSys);
return d;
}
void uiFreeSizing(uiSizing *d)
{
uiFree(d->Sys);
uiFree(d);
}

19
redo/reredo/menu.c Normal file
View File

@ -0,0 +1,19 @@
// 29 may 2015
#include "ui.h"
static uintmax_t type_uiMenu = 0;
static uintmax_t type_uiMenuItem = 0;
uintmax_t uiTypeMenu(void)
{
if (type_uiMenu == 0)
type_uiMenu = uiRegisterType("uiMenu", 0, 0);
return type_uiMenu;
}
uintmax_t uiTypeMenuItem(void)
{
if (type_uiMenuItem == 0)
type_uiMenuItem = uiRegisterType("uiMenuItem", 0, 0);
return type_uiMenuItem;
}

49
redo/reredo/ptrarray.c Normal file
View File

@ -0,0 +1,49 @@
// 5 may 2015
#include <string.h>
#include "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)
{
ptrArrayInsertAt(p, p->len, d);
}
void ptrArrayInsertAt(struct ptrArray *p, uintmax_t i, void *d)
{
if (i > p->len)
complain("index out of range in ptrArrayInsertAt()");
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--;
}

22
redo/reredo/shouldquit.c Normal file
View File

@ -0,0 +1,22 @@
// 9 may 2015
#include "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);
}

88
redo/reredo/types.c Normal file
View File

@ -0,0 +1,88 @@
// 17 may 2015
#include "ui.h"
#include "uipriv.h"
struct typeinfo {
const char *name;
uintmax_t parent;
size_t size;
};
static struct ptrArray *types = NULL;
uintmax_t uiRegisterType(const char *name, uintmax_t parent, size_t size)
{
struct typeinfo *ti;
if (types == NULL) {
types = newPtrArray();
// reserve ID 0
ptrArrayAppend(types, NULL);
}
// TODO prevent our size from being smaller than our parent's
ti = uiNew(struct typeinfo);
ti->name = name;
ti->parent = parent;
ti->size = size;
ptrArrayAppend(types, ti);
return types->len - 1;
}
void *uiIsA(void *p, uintmax_t id, int fail)
{
uiTyped *t;
struct typeinfo *ti, *ti2;
uintmax_t compareTo;
if (id == 0 || id >= types->len)
complain("invalid type ID given to uiIsA()");
t = (uiTyped *) p;
compareTo = t->Type;
if (compareTo == 0)
complain("object %p has no type in uiIsA()", t);
for (;;) {
if (compareTo >= types->len)
complain("invalid type ID in uiIsA()", t);
if (compareTo == id)
return t;
ti = ptrArrayIndex(types, struct typeinfo *, compareTo);
if (ti->parent == 0)
break;
compareTo = ti->parent;
}
if (fail) {
ti = ptrArrayIndex(types, struct typeinfo *, id);
ti2 = ptrArrayIndex(types, struct typeinfo *, t->Type);
complain("object %p not a %s in uiIsA() (is a %s)", t, ti->name, ti2->name);
}
return NULL;
}
void uninitTypes(void)
{
struct typeinfo *ti;
if (types == NULL) // never initialized; do nothing
return;
// the first entry is NULL; get rid of it directly
ptrArrayDelete(types, 0);
while (types->len != 0) {
ti = ptrArrayIndex(types, struct typeinfo *, 0);
ptrArrayDelete(types, 0);
uiFree(ti);
}
ptrArrayDestroy(types);
}
uiTyped *newTyped(uintmax_t type)
{
struct typeinfo *ti;
uiTyped *instance;
if (type == 0 || type >= types->len)
complain("invalid type ID given to newTyped()");
ti = ptrArrayIndex(types, struct typeinfo *, type);
instance = (uiTyped *) uiAlloc(ti->size, ti->name);
instance->Type = type;
return instance;
}