diff options
Diffstat (limited to 'include/pugl/detail/implementation.c')
-rw-r--r-- | include/pugl/detail/implementation.c | 488 |
1 files changed, 0 insertions, 488 deletions
diff --git a/include/pugl/detail/implementation.c b/include/pugl/detail/implementation.c deleted file mode 100644 index 4f0776a..0000000 --- a/include/pugl/detail/implementation.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - Copyright 2012-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/** - @file implementation.c - @brief Platform-independent implementation. -*/ - -#include "pugl/detail/implementation.h" -#include "pugl/pugl.h" - -#include <assert.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -static const char* -puglLogLevelPrefix(const PuglLogLevel level) -{ - switch (level) { - case PUGL_LOG_LEVEL_ERR: - return "error: "; - case PUGL_LOG_LEVEL_WARNING: - return "warning: "; - case PUGL_LOG_LEVEL_INFO: - case PUGL_LOG_LEVEL_DEBUG: - return ""; - } - - return ""; -} - -static void -puglDefaultLogFunc(PuglWorld* PUGL_UNUSED(world), - PuglLogLevel level, - const char* msg) -{ - fprintf(stderr, "%s%s", puglLogLevelPrefix(level), msg); -} - -const char* -puglStrerror(const PuglStatus status) -{ - // clang-format off - switch (status) { - case PUGL_SUCCESS: return "Success"; - case PUGL_FAILURE: return "Non-fatal failure"; - case PUGL_UNKNOWN_ERROR: return "Unknown system error"; - case PUGL_BAD_BACKEND: return "Invalid or missing backend"; - case PUGL_BAD_CONFIGURATION: return "Invalid view configuration"; - case PUGL_BAD_PARAMETER: return "Invalid parameter"; - case PUGL_BACKEND_FAILED: return "Backend initialisation failed"; - case PUGL_REGISTRATION_FAILED: return "Class registration failed"; - case PUGL_REALIZE_FAILED: return "View creation failed"; - case PUGL_SET_FORMAT_FAILED: return "Failed to set pixel format"; - case PUGL_CREATE_CONTEXT_FAILED: return "Failed to create drawing context"; - case PUGL_UNSUPPORTED_TYPE: return "Unsupported data type"; - } - // clang-format on - - return "Unknown error"; -} - -void -puglSetString(char** dest, const char* string) -{ - if (*dest != string) { - const size_t len = strlen(string); - - *dest = (char*)realloc(*dest, len + 1); - strncpy(*dest, string, len + 1); - } -} - -void -puglSetBlob(PuglBlob* const dest, const void* const data, const size_t len) -{ - if (data) { - dest->len = len; - dest->data = realloc(dest->data, len + 1); - memcpy(dest->data, data, len); - ((char*)dest->data)[len] = 0; - } else { - dest->len = 0; - dest->data = NULL; - } -} - -static void -puglSetDefaultHints(PuglHints hints) -{ - hints[PUGL_USE_COMPAT_PROFILE] = PUGL_TRUE; - hints[PUGL_CONTEXT_VERSION_MAJOR] = 2; - hints[PUGL_CONTEXT_VERSION_MINOR] = 0; - hints[PUGL_RED_BITS] = 8; - hints[PUGL_GREEN_BITS] = 8; - hints[PUGL_BLUE_BITS] = 8; - hints[PUGL_ALPHA_BITS] = 8; - hints[PUGL_DEPTH_BITS] = 0; - hints[PUGL_STENCIL_BITS] = 0; - hints[PUGL_SAMPLES] = 0; - hints[PUGL_DOUBLE_BUFFER] = PUGL_TRUE; - hints[PUGL_SWAP_INTERVAL] = PUGL_DONT_CARE; - hints[PUGL_RESIZABLE] = PUGL_FALSE; - hints[PUGL_IGNORE_KEY_REPEAT] = PUGL_FALSE; - hints[PUGL_REFRESH_RATE] = PUGL_DONT_CARE; -} - -PuglWorld* -puglNewWorld(PuglWorldType type, PuglWorldFlags flags) -{ - PuglWorld* world = (PuglWorld*)calloc(1, sizeof(PuglWorld)); - if (!world || !(world->impl = puglInitWorldInternals(type, flags))) { - free(world); - return NULL; - } - - world->startTime = puglGetTime(world); - world->logFunc = puglDefaultLogFunc; - world->logLevel = PUGL_LOG_LEVEL_INFO; - - puglSetString(&world->className, "Pugl"); - - return world; -} - -void -puglFreeWorld(PuglWorld* const world) -{ - puglFreeWorldInternals(world); - free(world->className); - free(world->views); - free(world); -} - -void -puglSetWorldHandle(PuglWorld* world, PuglWorldHandle handle) -{ - world->handle = handle; -} - -PuglWorldHandle -puglGetWorldHandle(PuglWorld* world) -{ - return world->handle; -} - -PuglStatus -puglSetLogFunc(PuglWorld* world, PuglLogFunc logFunc) -{ - world->logFunc = logFunc; - - return PUGL_SUCCESS; -} - -PuglStatus -puglSetLogLevel(PuglWorld* world, PuglLogLevel level) -{ - world->logLevel = level; - - return PUGL_SUCCESS; -} - -PuglStatus -puglSetClassName(PuglWorld* const world, const char* const name) -{ - puglSetString(&world->className, name); - return PUGL_SUCCESS; -} - -PuglView* -puglNewView(PuglWorld* const world) -{ - PuglView* view = (PuglView*)calloc(1, sizeof(PuglView)); - if (!view || !(view->impl = puglInitViewInternals())) { - free(view); - return NULL; - } - - view->world = world; - view->minWidth = 1; - view->minHeight = 1; - - puglSetDefaultHints(view->hints); - - // Add to world view list - ++world->numViews; - world->views = (PuglView**)realloc(world->views, - world->numViews * sizeof(PuglView*)); - - world->views[world->numViews - 1] = view; - - return view; -} - -void -puglFreeView(PuglView* view) -{ - puglDispatchSimpleEvent(view, PUGL_DESTROY); - - // Remove from world view list - PuglWorld* world = view->world; - for (size_t i = 0; i < world->numViews; ++i) { - if (world->views[i] == view) { - if (i == world->numViews - 1) { - world->views[i] = NULL; - } else { - memmove(world->views + i, world->views + i + 1, - sizeof(PuglView*) * (world->numViews - i - 1)); - world->views[world->numViews - 1] = NULL; - } - --world->numViews; - } - } - - free(view->title); - free(view->clipboard.data); - puglFreeViewInternals(view); - free(view); -} - -PuglWorld* -puglGetWorld(PuglView* view) -{ - return view->world; -} - -PuglStatus -puglSetViewHint(PuglView* view, PuglViewHint hint, int value) -{ - if (value == PUGL_DONT_CARE) { - switch (hint) { - case PUGL_USE_COMPAT_PROFILE: - case PUGL_USE_DEBUG_CONTEXT: - case PUGL_CONTEXT_VERSION_MAJOR: - case PUGL_CONTEXT_VERSION_MINOR: - case PUGL_SWAP_INTERVAL: - return PUGL_BAD_PARAMETER; - default: - break; - } - } - - if (hint < PUGL_NUM_VIEW_HINTS) { - view->hints[hint] = value; - return PUGL_SUCCESS; - } - - return PUGL_BAD_PARAMETER; -} - -int -puglGetViewHint(const PuglView* view, PuglViewHint hint) -{ - if (hint < PUGL_NUM_VIEW_HINTS) { - return view->hints[hint]; - } - - return PUGL_DONT_CARE; -} - -PuglStatus -puglSetParentWindow(PuglView* view, PuglNativeView parent) -{ - view->parent = parent; - return PUGL_SUCCESS; -} - -PuglStatus -puglSetBackend(PuglView* view, const PuglBackend* backend) -{ - view->backend = backend; - return PUGL_SUCCESS; -} - -void -puglSetHandle(PuglView* view, PuglHandle handle) -{ - view->handle = handle; -} - -PuglHandle -puglGetHandle(PuglView* view) -{ - return view->handle; -} - -bool -puglGetVisible(const PuglView* view) -{ - return view->visible; -} - -PuglRect -puglGetFrame(const PuglView* view) -{ - return view->frame; -} - -void* -puglGetContext(PuglView* view) -{ - return view->backend->getContext(view); -} - -#ifndef PUGL_DISABLE_DEPRECATED - -PuglStatus -puglPollEvents(PuglWorld* world, double timeout) -{ - return puglUpdate(world, timeout); -} - -PuglStatus -puglDispatchEvents(PuglWorld* world) -{ - return puglUpdate(world, 0.0); -} - -#endif - -PuglStatus -puglEnterContext(PuglView* view) -{ - return view->backend->enter(view, NULL); -} - -PuglStatus -puglLeaveContext(PuglView* view) -{ - return view->backend->leave(view, NULL); -} - -PuglStatus -puglSetEventFunc(PuglView* view, PuglEventFunc eventFunc) -{ - view->eventFunc = eventFunc; - return PUGL_SUCCESS; -} - -/// Return the code point for buf, or the replacement character on error -uint32_t -puglDecodeUTF8(const uint8_t* buf) -{ -#define FAIL_IF(cond) do { if (cond) return 0xFFFD; } while (0) - - // http://en.wikipedia.org/wiki/UTF-8 - - if (buf[0] < 0x80) { - return buf[0]; - } else if (buf[0] < 0xC2) { - return 0xFFFD; - } else if (buf[0] < 0xE0) { - FAIL_IF((buf[1] & 0xC0u) != 0x80); - return ((uint32_t)buf[0] << 6u) + buf[1] - 0x3080u; - } else if (buf[0] < 0xF0) { - FAIL_IF((buf[1] & 0xC0u) != 0x80); - FAIL_IF(buf[0] == 0xE0 && buf[1] < 0xA0); - FAIL_IF((buf[2] & 0xC0u) != 0x80); - return ((uint32_t)buf[0] << 12u) + // - ((uint32_t)buf[1] << 6u) + // - ((uint32_t)buf[2] - 0xE2080u); - } else if (buf[0] < 0xF5) { - FAIL_IF((buf[1] & 0xC0u) != 0x80); - FAIL_IF(buf[0] == 0xF0 && buf[1] < 0x90); - FAIL_IF(buf[0] == 0xF4 && buf[1] >= 0x90); - FAIL_IF((buf[2] & 0xC0u) != 0x80u); - FAIL_IF((buf[3] & 0xC0u) != 0x80u); - return (((uint32_t)buf[0] << 18u) + // - ((uint32_t)buf[1] << 12u) + // - ((uint32_t)buf[2] << 6u) + // - ((uint32_t)buf[3] - 0x3C82080u)); - } - return 0xFFFD; -} - -static inline bool -puglMustConfigure(PuglView* view, const PuglEventConfigure* configure) -{ - return memcmp(configure, &view->lastConfigure, sizeof(PuglEventConfigure)); -} - -void -puglDispatchSimpleEvent(PuglView* view, const PuglEventType type) -{ - assert(type == PUGL_CREATE || type == PUGL_DESTROY || type == PUGL_MAP || - type == PUGL_UNMAP || type == PUGL_UPDATE || type == PUGL_CLOSE || - type == PUGL_LOOP_ENTER || type == PUGL_LOOP_LEAVE); - - const PuglEvent event = {{type, 0}}; - puglDispatchEvent(view, &event); -} - -void -puglDispatchEventInContext(PuglView* view, const PuglEvent* event) -{ - if (event->type == PUGL_CONFIGURE) { - view->frame.x = event->configure.x; - view->frame.y = event->configure.y; - view->frame.width = event->configure.width; - view->frame.height = event->configure.height; - - if (puglMustConfigure(view, &event->configure)) { - view->eventFunc(view, event); - view->lastConfigure = event->configure; - } - } else if (event->type == PUGL_EXPOSE) { - if (event->expose.width > 0 && event->expose.height > 0) { - view->eventFunc(view, event); - } - } else { - view->eventFunc(view, event); - } -} - -void -puglDispatchEvent(PuglView* view, const PuglEvent* event) -{ - switch (event->type) { - case PUGL_NOTHING: - break; - case PUGL_CREATE: - case PUGL_DESTROY: - view->backend->enter(view, NULL); - view->eventFunc(view, event); - view->backend->leave(view, NULL); - break; - case PUGL_CONFIGURE: - if (puglMustConfigure(view, &event->configure)) { - view->backend->enter(view, NULL); - puglDispatchEventInContext(view, event); - view->backend->leave(view, NULL); - } - break; - case PUGL_EXPOSE: - view->backend->enter(view, &event->expose); - puglDispatchEventInContext(view, event); - view->backend->leave(view, &event->expose); - break; - default: - view->eventFunc(view, event); - } -} - -const void* -puglGetInternalClipboard(const PuglView* const view, - const char** const type, - size_t* const len) -{ - if (len) { - *len = view->clipboard.len; - } - - if (type) { - *type = "text/plain"; - } - - return view->clipboard.data; -} - -PuglStatus -puglSetInternalClipboard(PuglView* const view, - const char* const type, - const void* const data, - const size_t len) -{ - if (type && strcmp(type, "text/plain")) { - return PUGL_UNSUPPORTED_TYPE; - } - - puglSetBlob(&view->clipboard, data, len); - return PUGL_SUCCESS; -} - |