Implemented uiInit() on macOS. The tests work so far!

This commit is contained in:
Pietro Gagliardi 2019-04-20 21:38:26 -04:00
parent 74b1e2780d
commit 484989e925
8 changed files with 112 additions and 15 deletions

View File

@ -5,28 +5,54 @@
static int initialized = 0;
int uiprivInitCheckParams(void *options, uiInitError *err)
#define errAlreadyInitialized "libui already initialized"
#define errOptionsMustBeNULL "options parameter to uiInit() must be NULL"
static const char *commonInitErrors[] = {
errAlreadyInitialized,
errOptionsMustBeNULL,
NULL,
};
static int checkInitErrorLengths(uiInitError *err, const char *initErrors[])
{
const char **p;
for (p = initErrors; *p != NULL; p++)
if (strlen(*p) > 255) {
strcpy(err->Message, "[INTERNAL] uiInit() error too long: ");
strncat(err->Message, *p, 32);
strcat(err->Message, "...");
return 0;
}
return 1;
}
int uiprivInitCheckParams(void *options, uiInitError *err, const char *initErrors[])
{
if (err == NULL)
return 0;
if (err->Size != sizeof (uiInitError))
return 0;
if (!checkInitErrorLengths(err, commonInitErrors))
return 0;
if (!checkInitErrorLengths(err, initErrors))
return 0;
if (initialized)
return uiprivInitReturnError(err, "xxxxxxxxx");
return uiprivInitReturnError(err, errAlreadyInitialized);
if (options != NULL)
return uiprivInitReturnError(err, "xxxxxxxx");
return uiprivInitReturnError(err, errOptionsMustBeNULL);
return 1;
}
int uiprivInitReturnError(uiInitError *err, const char *msg)
{
// checkInitErrorLengths() above ensures that err->Message[255] will always be '\0'
strncpy(err->Message, msg, 256);
if (err->Message[255] != '\0')
// TODO there should be some check to make sure this doesn't happen
err->Message[255] = '\0';
return 0;
}

View File

@ -1,6 +1,6 @@
// 19 april 2019
// init.c
extern int uiprivInitCheckParams(void *options, uiInitError *err);
extern int uiprivInitCheckParams(void *options, uiInitError *err, const char *initErrors[]);
extern int uiprivInitReturnError(uiInitError *err, const char *msg);
extern void uiprivMarkInitialized(void);

34
darwin/main.m Normal file
View File

@ -0,0 +1,34 @@
// 20 april 2019
#import "uipriv_darwin.h"
@interface uiprivApplication : NSApplication
@end
@implementation uiprivApplication
@end
static NSApplication *uiprivApp;
#define errNSAppAlreadyInitialized "NSApp is not of type uiprivApplication; was likely already initialized beforehand"
static const char *initErrors[] = {
errNSAppAlreadyInitialized,
NULL,
};
int uiInit(void *options, uiInitError *err)
{
if (!uiprivInitCheckParams(options, err, initErrors))
return 0;
uiprivApp = [uiprivApplication sharedApplication];
if (![NSApp isKindOfClass:[uiprivApplication class]])
return uiprivInitReturnError(err, errNSAppAlreadyInitialized);
uiprivMarkInitialized();
return 1;
}
void uiUninit(void)
{
}

16
darwin/meson.build Normal file
View File

@ -0,0 +1,16 @@
# 23 march 2019
libui_sources += [
'darwin/main.m',
]
libui_deps += [
meson.get_compiler('objc').find_library('objc',
required: true),
dependency('appleframeworks',
modules: ['Foundation', 'AppKit'],
required: true),
]
libui_soversion = 'A'
# the / is required by some older versions of OS X
libui_rpath = '@executable_path/'

18
darwin/uipriv_darwin.h Normal file
View File

@ -0,0 +1,18 @@
// 6 january 2015
// note: as of OS X Sierra, the -mmacosx-version-min compiler options governs deprecation warnings; keep these around anyway just in case
#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_8
#define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_10_8
#import <Cocoa/Cocoa.h>
#import <dlfcn.h> // see future.m
#import "../ui.h"
#import "../ui_darwin.h"
#import "../common/uipriv.h"
#if __has_feature(objc_arc)
#error Sorry, libui cannot be compiled with ARC.
#endif
// TODO find a better place for this
#ifndef NSAppKitVersionNumber10_9
#define NSAppKitVersionNumber10_9 1265
#endif

View File

@ -145,7 +145,7 @@ if libui_OS == 'windows'
# subdir('windows')
install_headers('ui_windows.h')
elif libui_OS == 'darwin'
# subdir('darwin')
subdir('darwin')
install_headers('ui_darwin.h')
else
# subdir('unix')

View File

@ -3,11 +3,14 @@
#include "../ui.h"
#include "testing.h"
#define invalidOptionsError "TODOTODOTODO"
#define alreadyInitializedError "TODOTODOTODO"
// TODO fix up the formatting of testing.c so we can use newlines on the got/want stuff
#define errInvalidOptions "options parameter to uiInit() must be NULL"
#define errAlreadyInitialized "libui already initialized"
testingTestBefore(Init)
{
uiInitError err;
int ret;
ret = uiInit(NULL, NULL);
@ -26,8 +29,8 @@ testingTestBefore(Init)
ret = uiInit(&err, &err);
if (ret != 0)
testingTErrorf(t, "uiInit() with non-NULL options succeeded with return value %d; expected failure", err);
if (strcmp(err.Message, invalidOptionsError) != 0)
testingTErrorf(t, "uiInit() with non-NULL options returned bad error message: got %s, want %s", err.Message, invalidOptionsError);
if (strcmp(err.Message, errInvalidOptions) != 0)
testingTErrorf(t, "uiInit() with non-NULL options returned bad error message: got %s, want %s", err.Message, errInvalidOptions);
memset(&err, 0, sizeof (uiInitError));
err.Size = sizeof (uiInitError);
@ -40,8 +43,8 @@ testingTestBefore(Init)
ret = uiInit(NULL, &err);
if (ret != 0)
testingTErrorf(t, "uiInit() after a previous successful call succeeded with return value %d; expected failure", ret);
if (strcmp(err.Message, alreadyInitializedError) != 0)
testingTErrorf(t, "uiInit() after a previous successful call returned bad error message: got %s, want %s", err.Message, alreadyInitializedError);
if (strcmp(err.Message, errAlreadyInitialized) != 0)
testingTErrorf(t, "uiInit() after a previous successful call returned bad error message: got %s, want %s", err.Message, errAlreadyInitialized);
}
testingTestAfter(Uninit)

2
ui.h
View File

@ -13,7 +13,7 @@ extern "C" {
#ifdef uiprivBuildingLibui
#if defined(_WIN32) && !defined(uiStatic)
#define uiprivExtern __declspec(dllexport) extern
#elif deffined(_WIN32)
#elif defined(_WIN32)
#define uiprivExtern extern
#else
#define uiprivExtern __attribute__((visibility("default"))) extern