From 05976711fa026d436bbba02d616c589e8465934c Mon Sep 17 00:00:00 2001 From: George Watson Date: Wed, 29 Nov 2023 14:38:41 +0000 Subject: [PATCH] clean up --- .gitignore | 1 + README.md | 56 +++- build.bat | 6 - docs.sh | 3 - examples/live.c | 75 ----- live/dlfcn_win32.c | 414 ---------------------------- live/dlfcn_win32.h | 59 ---- live/getopt_win32.h | 653 -------------------------------------------- live/ppLive.c | 352 ------------------------ live/ppLive.h | 104 ------- live/ppUtils.c | 79 ------ rebuild.bat | 4 - 12 files changed, 56 insertions(+), 1750 deletions(-) delete mode 100644 build.bat delete mode 100644 docs.sh delete mode 100644 examples/live.c delete mode 100644 live/dlfcn_win32.c delete mode 100644 live/dlfcn_win32.h delete mode 100644 live/getopt_win32.h delete mode 100644 live/ppLive.c delete mode 100644 live/ppLive.h delete mode 100644 live/ppUtils.c delete mode 100644 rebuild.bat diff --git a/.gitignore b/.gitignore index 1ecb6b7..e2a2ae3 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ build/ .DS_Store *.plist *.obj +docs.sh diff --git a/README.md b/README.md index 2fa206a..1a05514 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,60 @@ # pp -This is an original version of `pp` but slimmed down to basically just the window handling functions and a few functions for image handling. +_pp_ **[ˈpiːpiː]** or "_Pixel Playground_" is a small minimal cross-platform software-rendering window + context. Click [here](https://takeiteasy.github.io/pp/) for documentation. + +Platforms: +* Windows +* MacOS +* Linux +* WebAssembly (via [emscripten](https://github.com/emscripten-core/emscripten)) + +## Example +```c +#include "pp" + +// Window event callbacks +void onKeyboard(void *userdata, int key, int modifier, int isDown); +void onMouseButton(void *userdata, int button, int modifier, int isDown); +void onMouseMove(void *userdata, int x, int y, float dx, float dy); +void onMouseScroll(void *userdata, float dx, float dy, int modifier); +void onFocus(void *userdata, int isFocused); +void onResized(void *userdata, int w, int h); +void onClosed(void *userdata); + +// Buffer to store image data +static int test[640 * 480]; + +int main(int argc, const char *argv[]) { + // Initialize pp and create 640x480 window titled "pp" + ppBegin(640, 480, "pp", ppResizable); + // Set window event callbacks ... + // ppKeyboardCallback(onKeyboard); + + // Create a simple xor pattern in the image buffer + for (int x = 0; x < 640; x++) + for (int y = 0; y < 480; y++) + test[y * 640 + x] = x ^ y; + + // Keep window open and poll events (must poll every frame) + while (ppPoll()) { + // do something here ... + + // Flush the buffer to the window + ppFlush(test, 640, 480); + } + + // Always clean your pp + ppEnd(); + return 0; +} + +``` + +## Building + +The Makefile has three options; ```default``` will build example/basic.c, ```library``` will build a dynamic library and ```web``` will also build example/basic.c, except compiled to wasm. + +It's also very easy to use in your own project. Simply copy (or fork) ```pp.c``` and ```pp.h``` from the ```src``` directory. If you are on windows you will need to link ```-lgdi32```. If you're on Linux you must link ```-lX11 -lm``` and on MacOS ```-framework Cocoa```. ## License ``` diff --git a/build.bat b/build.bat deleted file mode 100644 index b5d7e77..0000000 --- a/build.bat +++ /dev/null @@ -1,6 +0,0 @@ -@echo off -if exist .\build\ppLive.dll move .\build\ppLive.dll .\build\ppLive.%random%.dll -cl .\live\ppUtils.c .\examples\live.c /I.\src /I.\live /MD /link /DLL /SUBSYSTEM:CONSOLE /out:.\build\ppLive.dll -if exist .\build\pp.exe move .\build\pp.exe .\build\pp.%random%.exe -cl .\src\ppWindows.c .\live\*.c /I.\src /I.\live Psapi.lib /link /SUBSYSTEM:CONSOLE /out:.\build\pp.exe -del *.obj \ No newline at end of file diff --git a/docs.sh b/docs.sh deleted file mode 100644 index 95a1c3a..0000000 --- a/docs.sh +++ /dev/null @@ -1,3 +0,0 @@ -headerdoc2html -udpb src/pp.h -o docs/ -gatherheaderdoc docs -mv docs/masterTOC.html docs/index.html diff --git a/examples/live.c b/examples/live.c deleted file mode 100644 index d3771fb..0000000 --- a/examples/live.c +++ /dev/null @@ -1,75 +0,0 @@ -#include "ppLive.h" -#include -#include - -struct ppState { - ppColor clearColor; -}; - -// Called once at the beginning of runtime -static ppState* init(void) { - ppState *state = malloc(sizeof(ppState)); - if (!state) - return NULL; - state->clearColor = (ppColor){.r = 255, .g = 0, .b = 0}; - return state; -} - -// Called once at the end of runtime -static void deinit(ppState *state) { - if (!state) - return; - free(state); -} - -// Called whenever the app is modified and reloaded -static void reload(ppState *state) { -} - -// Called just before the app is reloaded -static void unload(ppState *state) { -} - -static int event(ppState *state, ppEvent *e) { - switch (e->type) { - case ppKeyboardEvent: - printf("Keyboard key %d is now %s\n", e->Keyboard.key, e->Keyboard.isdown ? "pressed" : "released"); - break; - case ppMouseButtonEvent: - printf("Mouse button %d is now %s\n", e->Mouse.button, e->Mouse.isdown ? "pressed" : "released"); - break; - case ppMouseMoveEvent: - printf("Mouse moved by %fx%f to %dx%d\n", e->Mouse.Position.dx, e->Mouse.Position.dy, e->Mouse.Position.x, e->Mouse.Position.y); - break; - case ppMouseScrollEvent: - printf("Mouse scrolled by %fx%f\n", e->Mouse.Scroll.dx, e->Mouse.Scroll.dy); - break; - case ppResizedEvent: - printf("Window has resized to %dx%d\n", e->Window.Size.width, e->Window.Size.height); - break; - case ppFocusEvent: - printf("Window is now %s\n", e->Window.focused ? "focused" : "blured"); - break; - case ppClosedEvent: - printf("Window closed\n"); - return 0; - } - return 1; -} - -// Called every frame -static int tick(ppState *state, ppSurface *frame, double delta) { - ppClearSurface(frame, state->clearColor); - return 1; -} - -// App descriptor to direct callbacks -// Must be called "pp" as that is the symbol that is looked up -EXPORT const ppApp pp = { - .init = init, - .deinit = deinit, - .reload = reload, - .unload = unload, - .event = event, - .tick = tick -}; diff --git a/live/dlfcn_win32.c b/live/dlfcn_win32.c deleted file mode 100644 index 1925132..0000000 --- a/live/dlfcn_win32.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * dlfcn-win32 - * Copyright (c) 2007 Ramiro Polla - * Copyright (c) 2015 Tiancheng "Timothy" Gu - * - * dlfcn-win32 is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * dlfcn-win32 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with dlfcn-win32; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifdef _DEBUG -#define _CRTDBG_MAP_ALLOC -#include -#include -#endif -#define PSAPI_VERSION 1 -#include -#include -#include - -#ifdef SHARED -#define DLFCN_WIN32_EXPORTS -#endif -#include "dlfcn.h" - -/* Note: - * MSDN says these functions are not thread-safe. We make no efforts to have - * any kind of thread safety. - */ - -typedef struct global_object { - HMODULE hModule; - struct global_object *previous; - struct global_object *next; -} global_object; - -static global_object first_object; -static global_object first_automatic_object; -static int auto_ref_count = 0; - -/* These functions implement a double linked list for the global objects. */ -static global_object *global_search( global_object *start, HMODULE hModule ) -{ - global_object *pobject; - - if( hModule == NULL ) - return NULL; - - for( pobject = start; pobject; pobject = pobject->next ) - if( pobject->hModule == hModule ) - return pobject; - - return NULL; -} - -static void global_add( global_object *start, HMODULE hModule ) -{ - global_object *pobject; - global_object *nobject; - - if( hModule == NULL ) - return; - - pobject = global_search( start, hModule ); - - /* Do not add object again if it's already on the list */ - if( pobject ) - return; - - if( start == &first_automatic_object ) - { - pobject = global_search( &first_object, hModule ); - if( pobject ) - return; - } - - for( pobject = start; pobject->next; pobject = pobject->next ); - - nobject = malloc( sizeof( global_object ) ); - - /* Should this be enough to fail global_add, and therefore also fail - * dlopen? - */ - if( !nobject ) - return; - - pobject->next = nobject; - nobject->next = NULL; - nobject->previous = pobject; - nobject->hModule = hModule; -} - -static void global_rem( global_object *start, HMODULE hModule ) -{ - global_object *pobject; - - if( hModule == NULL ) - return; - - pobject = global_search( start, hModule ); - - if( !pobject ) - return; - - if( pobject->next ) - pobject->next->previous = pobject->previous; - if( pobject->previous ) - pobject->previous->next = pobject->next; - - free( pobject ); -} - -/* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one - * static buffer. - * MSDN says the buffer cannot be larger than 64K bytes, so we set it to - * the limit. - */ -static char error_buffer[65535]; -static char *current_error; - -static int copy_string( char *dest, int dest_size, const char *src ) -{ - int i = 0; - - /* gcc should optimize this out */ - if( !src || !dest ) - return 0; - - for( i = 0 ; i < dest_size-1 ; i++ ) - { - if( !src[i] ) - break; - else - dest[i] = src[i]; - } - dest[i] = '\0'; - - return i; -} - -static void save_err_str( const char *str ) -{ - DWORD dwMessageId; - DWORD pos; - - dwMessageId = GetLastError( ); - - if( dwMessageId == 0 ) - return; - - /* Format error message to: - * "": - */ - pos = copy_string( error_buffer, sizeof(error_buffer), "\"" ); - pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, str ); - pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, "\": " ); - pos += FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMessageId, - MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), - error_buffer+pos, sizeof(error_buffer)-pos, NULL ); - - if( pos > 1 ) - { - /* POSIX says the string must not have trailing */ - if( error_buffer[pos-2] == '\r' && error_buffer[pos-1] == '\n' ) - error_buffer[pos-2] = '\0'; - } - - current_error = error_buffer; -} - -static void save_err_ptr_str( const void *ptr ) -{ - char ptr_buf[19]; /* 0x up to 64 bits. */ - - sprintf_s( ptr_buf, 19, "0x%p", ptr ); - - save_err_str( ptr_buf ); -} - -void *dlopen( const char *file, int mode ) -{ - HMODULE hModule; - UINT uMode; - - current_error = NULL; - - /* Do not let Windows display the critical-error-handler message box */ - uMode = SetErrorMode( SEM_FAILCRITICALERRORS ); - - if( file == 0 ) - { - HMODULE hAddtnlMods[1024]; // Already loaded modules - HANDLE hCurrentProc = GetCurrentProcess( ); - DWORD cbNeeded; - - /* POSIX says that if the value of file is 0, a handle on a global - * symbol object must be provided. That object must be able to access - * all symbols from the original program file, and any objects loaded - * with the RTLD_GLOBAL flag. - * The return value from GetModuleHandle( ) allows us to retrieve - * symbols only from the original program file. For objects loaded with - * the RTLD_GLOBAL flag, we create our own list later on. For objects - * outside of the program file but already loaded (e.g. linked DLLs) - * they are added below. - */ - hModule = GetModuleHandle( NULL ); - - if( !hModule ) - save_err_ptr_str( file ); - - - /* GetModuleHandle( NULL ) only returns the current program file. So - * if we want to get ALL loaded module including those in linked DLLs, - * we have to use EnumProcessModules( ). - */ - if( EnumProcessModules( hCurrentProc, hAddtnlMods, - sizeof( hAddtnlMods ), &cbNeeded ) != 0 ) - { - DWORD i; - for( i = 0; i < cbNeeded / sizeof( HMODULE ); i++ ) - { - global_add( &first_automatic_object, hAddtnlMods[i] ); - } - } - auto_ref_count++; - } - else - { - char lpFileName[MAX_PATH]; - int i; - - /* MSDN says backslashes *must* be used instead of forward slashes. */ - for( i = 0 ; i < sizeof(lpFileName)-1 ; i++ ) - { - if( !file[i] ) - break; - else if( file[i] == '/' ) - lpFileName[i] = '\\'; - else - lpFileName[i] = file[i]; - } - lpFileName[i] = '\0'; - - /* POSIX says the search path is implementation-defined. - * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely - * to UNIX's search paths (start with system folders instead of current - * folder). - */ - hModule = LoadLibraryEx( (LPSTR) lpFileName, NULL, - LOAD_WITH_ALTERED_SEARCH_PATH ); - - /* If the object was loaded with RTLD_GLOBAL, add it to list of global - * objects, so that its symbols may be retrieved even if the handle for - * the original program file is passed. POSIX says that if the same - * file is specified in multiple invocations, and any of them are - * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the - * symbols will remain global. - */ - if( !hModule ) - save_err_str( lpFileName ); - else if( (mode & RTLD_GLOBAL) ) - global_add( &first_object, hModule ); - } - - /* Return to previous state of the error-mode bit flags. */ - SetErrorMode( uMode ); - - return (void *) hModule; -} - -static void free_auto( ) -{ - global_object *pobject = first_automatic_object.next; - if( pobject ) - { - global_object *next; - for ( ; pobject; pobject = next ) - { - next = pobject->next; - free( pobject ); - } - first_automatic_object.next = NULL; - } -} - -int dlclose( void *handle ) -{ - HMODULE hModule = (HMODULE) handle; - BOOL ret; - - current_error = NULL; - - ret = FreeLibrary( hModule ); - - /* If the object was loaded with RTLD_GLOBAL, remove it from list of global - * objects. - */ - if( ret ) - { - HMODULE cur = GetModuleHandle( NULL ); - global_rem( &first_object, hModule ); - if( hModule == cur ) - { - auto_ref_count--; - if( auto_ref_count < 0 ) - auto_ref_count = 0; - if( !auto_ref_count ) - free_auto( ); - } - } - else - save_err_ptr_str( handle ); - - /* dlclose's return value in inverted in relation to FreeLibrary's. */ - ret = !ret; - - return (int) ret; -} - -void *dlsym( void *handle, const char *name ) -{ - FARPROC symbol; - HMODULE hModule; - - current_error = NULL; - - symbol = GetProcAddress( handle, name ); - - if( symbol != NULL ) - goto end; - - /* If the handle for the original program file is passed, also search - * in all globally loaded objects. - */ - - hModule = GetModuleHandle( NULL ); - - if( hModule == handle ) - { - global_object *pobject; - - for( pobject = &first_object; pobject; pobject = pobject->next ) - { - if( pobject->hModule ) - { - symbol = GetProcAddress( pobject->hModule, name ); - if( symbol != NULL ) - goto end; - } - } - - for( pobject = &first_automatic_object; pobject; pobject = pobject->next ) - { - if( pobject->hModule ) - { - symbol = GetProcAddress( pobject->hModule, name ); - if( symbol != NULL ) - goto end; - } - } - } - -end: - if( symbol == NULL ) - save_err_str( name ); - -// warning C4054: 'type cast' : from function pointer 'FARPROC' to data pointer 'void *' -#ifdef _MSC_VER -#pragma warning( suppress: 4054 ) -#endif - return (void*) symbol; -} - -char *dlerror( void ) -{ - char *error_pointer = current_error; - - /* POSIX says that invoking dlerror( ) a second time, immediately following - * a prior invocation, shall result in NULL being returned. - */ - current_error = NULL; - - return error_pointer; -} - -#ifdef SHARED -BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) -{ - (void) hinstDLL; - /* - * https://msdn.microsoft.com/en-us/library/windows/desktop/ms682583(v=vs.85).aspx - * - * When handling DLL_PROCESS_DETACH, a DLL should free resources such as heap - * memory only if the DLL is being unloaded dynamically (the lpReserved - * parameter is NULL). - */ - if( fdwReason == DLL_PROCESS_DETACH && !lpvReserved ) - { - auto_ref_count = 0; - free_auto( ); - } - return TRUE; -} -#endif \ No newline at end of file diff --git a/live/dlfcn_win32.h b/live/dlfcn_win32.h deleted file mode 100644 index 1eefd83..0000000 --- a/live/dlfcn_win32.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * dlfcn-win32 - * Copyright (c) 2007 Ramiro Polla - * - * dlfcn-win32 is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * dlfcn-win32 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with dlfcn-win32; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef DLFCN_H -#define DLFCN_H - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(DLFCN_WIN32_EXPORTS) -# define DLFCN_EXPORT __declspec(dllexport) -#else -# define DLFCN_EXPORT -#endif - -/* POSIX says these are implementation-defined. - * To simplify use with Windows API, we treat them the same way. - */ - -#define RTLD_LAZY 0 -#define RTLD_NOW 0 - -#define RTLD_GLOBAL (1 << 1) -#define RTLD_LOCAL (1 << 2) - -/* These two were added in The Open Group Base Specifications Issue 6. - * Note: All other RTLD_* flags in any dlfcn.h are not standard compliant. - */ - -#define RTLD_DEFAULT 0 -#define RTLD_NEXT 0 - -DLFCN_EXPORT void *dlopen ( const char *file, int mode ); -DLFCN_EXPORT int dlclose(void *handle); -DLFCN_EXPORT void *dlsym(void *handle, const char *name); -DLFCN_EXPORT char *dlerror(void); - -#ifdef __cplusplus -} -#endif - -#endif /* DLFCN_H */ diff --git a/live/getopt_win32.h b/live/getopt_win32.h deleted file mode 100644 index a9c6b32..0000000 --- a/live/getopt_win32.h +++ /dev/null @@ -1,653 +0,0 @@ -#ifndef __GETOPT_H__ -/** - * DISCLAIMER - * This file is part of the mingw-w64 runtime package. - * - * The mingw-w64 runtime package and its code is distributed in the hope that it - * will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR - * IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to - * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - /* - * Copyright (c) 2002 Todd C. Miller - * - * Permission to use, copy, modify, and 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. - * - * THE 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. - * - * Sponsored in part by the Defense Advanced Research Projects - * Agency (DARPA) and Air Force Research Laboratory, Air Force - * Materiel Command, USAF, under agreement number F39502-99-1-0512. - */ -/*- - * Copyright (c) 2000 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Dieter Baron and Thomas Klausner. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma warning(disable:4996); - -#define __GETOPT_H__ - -/* All the headers include this file. */ -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ - -#ifdef REPLACE_GETOPT -int opterr = 1; /* if error message should be printed */ -int optind = 1; /* index into parent argv vector */ -int optopt = '?'; /* character checked for validity */ -#undef optreset /* see getopt.h */ -#define optreset __mingw_optreset -int optreset; /* reset getopt */ -char *optarg; /* argument associated with option */ -#endif - -//extern int optind; /* index of first non-option in argv */ -//extern int optopt; /* single option character, as parsed */ -//extern int opterr; /* flag to enable built-in diagnostics... */ -// /* (user may set to zero, to suppress) */ -// -//extern char *optarg; /* pointer to argument of current option */ - -#define PRINT_ERROR ((opterr) && (*options != ':')) - -#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ -#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ -#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ - -/* return values */ -#define BADCH (int)'?' -#define BADARG ((*options == ':') ? (int)':' : (int)'?') -#define INORDER (int)1 - -#ifndef __CYGWIN__ -#define __progname __argv[0] -#else -extern char __declspec(dllimport) *__progname; -#endif - -#ifdef __CYGWIN__ -static char EMSG[] = ""; -#else -#define EMSG "" -#endif - -static int getopt_internal(int, char * const *, const char *, - const struct option *, int *, int); -static int parse_long_options(char * const *, const char *, - const struct option *, int *, int); -static int gcd(int, int); -static void permute_args(int, int, int, char * const *); - -static char *place = EMSG; /* option letter processing */ - -/* XXX: set optreset to 1 rather than these two */ -static int nonopt_start = -1; /* first non option argument (for permute) */ -static int nonopt_end = -1; /* first option after non options (for permute) */ - -/* Error messages */ -static const char recargchar[] = "option requires an argument -- %c"; -static const char recargstring[] = "option requires an argument -- %s"; -static const char ambig[] = "ambiguous option -- %.*s"; -static const char noarg[] = "option doesn't take an argument -- %.*s"; -static const char illoptchar[] = "unknown option -- %c"; -static const char illoptstring[] = "unknown option -- %s"; - -static void -_vwarnx(const char *fmt,va_list ap) -{ - (void)fprintf(stderr,"%s: ",__progname); - if (fmt != NULL) - (void)vfprintf(stderr,fmt,ap); - (void)fprintf(stderr,"\n"); -} - -static void -warnx(const char *fmt,...) -{ - va_list ap; - va_start(ap,fmt); - _vwarnx(fmt,ap); - va_end(ap); -} - -/* - * Compute the greatest common divisor of a and b. - */ -static int -gcd(int a, int b) -{ - int c; - - c = a % b; - while (c != 0) { - a = b; - b = c; - c = a % b; - } - - return (b); -} - -/* - * Exchange the block from nonopt_start to nonopt_end with the block - * from nonopt_end to opt_end (keeping the same order of arguments - * in each block). - */ -static void -permute_args(int panonopt_start, int panonopt_end, int opt_end, - char * const *nargv) -{ - int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; - char *swap; - - /* - * compute lengths of blocks and number and size of cycles - */ - nnonopts = panonopt_end - panonopt_start; - nopts = opt_end - panonopt_end; - ncycle = gcd(nnonopts, nopts); - cyclelen = (opt_end - panonopt_start) / ncycle; - - for (i = 0; i < ncycle; i++) { - cstart = panonopt_end+i; - pos = cstart; - for (j = 0; j < cyclelen; j++) { - if (pos >= panonopt_end) - pos -= nnonopts; - else - pos += nopts; - swap = nargv[pos]; - /* LINTED const cast */ - ((char **) nargv)[pos] = nargv[cstart]; - /* LINTED const cast */ - ((char **)nargv)[cstart] = swap; - } - } -} - -#ifdef REPLACE_GETOPT -/* - * getopt -- - * Parse argc/argv argument vector. - * - * [eventually this will replace the BSD getopt] - */ -int -getopt(int nargc, char * const *nargv, const char *options) -{ - - /* - * We don't pass FLAG_PERMUTE to getopt_internal() since - * the BSD getopt(3) (unlike GNU) has never done this. - * - * Furthermore, since many privileged programs call getopt() - * before dropping privileges it makes sense to keep things - * as simple (and bug-free) as possible. - */ - return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); -} -#endif /* REPLACE_GETOPT */ - -//extern int getopt(int nargc, char * const *nargv, const char *options); - -#ifdef _BSD_SOURCE -/* - * BSD adds the non-standard `optreset' feature, for reinitialisation - * of `getopt' parsing. We support this feature, for applications which - * proclaim their BSD heritage, before including this header; however, - * to maintain portability, developers are advised to avoid it. - */ -# define optreset __mingw_optreset -extern int optreset; -#endif -#ifdef __cplusplus -} -#endif -/* - * POSIX requires the `getopt' API to be specified in `unistd.h'; - * thus, `unistd.h' includes this header. However, we do not want - * to expose the `getopt_long' or `getopt_long_only' APIs, when - * included in this manner. Thus, close the standard __GETOPT_H__ - * declarations block, and open an additional __GETOPT_LONG_H__ - * specific block, only when *not* __UNISTD_H_SOURCED__, in which - * to declare the extended API. - */ -#endif /* !defined(__GETOPT_H__) */ - -#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) -#define __GETOPT_LONG_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -struct option /* specification for a long form option... */ -{ - const char *name; /* option name, without leading hyphens */ - int has_arg; /* does it take an argument? */ - int *flag; /* where to save its status, or NULL */ - int val; /* its associated status value */ -}; - -enum /* permitted values for its `has_arg' field... */ -{ - no_argument = 0, /* option never takes an argument */ - required_argument, /* option always requires an argument */ - optional_argument /* option may take an argument */ -}; - -/* - * parse_long_options -- - * Parse long options in argc/argv argument vector. - * Returns -1 if short_too is set and the option does not match long_options. - */ -static int -parse_long_options(char * const *nargv, const char *options, - const struct option *long_options, int *idx, int short_too) -{ - char *current_argv, *has_equal; - size_t current_argv_len; - int i, ambiguous, match; - -#define IDENTICAL_INTERPRETATION(_x, _y) \ - (long_options[(_x)].has_arg == long_options[(_y)].has_arg && \ - long_options[(_x)].flag == long_options[(_y)].flag && \ - long_options[(_x)].val == long_options[(_y)].val) - - current_argv = place; - match = -1; - ambiguous = 0; - - optind++; - - if ((has_equal = strchr(current_argv, '=')) != NULL) { - /* argument found (--option=arg) */ - current_argv_len = has_equal - current_argv; - has_equal++; - } else - current_argv_len = strlen(current_argv); - - for (i = 0; long_options[i].name; i++) { - /* find matching long option */ - if (strncmp(current_argv, long_options[i].name, - current_argv_len)) - continue; - - if (strlen(long_options[i].name) == current_argv_len) { - /* exact match */ - match = i; - ambiguous = 0; - break; - } - /* - * If this is a known short option, don't allow - * a partial match of a single character. - */ - if (short_too && current_argv_len == 1) - continue; - - if (match == -1) /* partial match */ - match = i; - else if (!IDENTICAL_INTERPRETATION(i, match)) - ambiguous = 1; - } - if (ambiguous) { - /* ambiguous abbreviation */ - if (PRINT_ERROR) - warnx(ambig, (int)current_argv_len, - current_argv); - optopt = 0; - return (BADCH); - } - if (match != -1) { /* option found */ - if (long_options[match].has_arg == no_argument - && has_equal) { - if (PRINT_ERROR) - warnx(noarg, (int)current_argv_len, - current_argv); - /* - * XXX: GNU sets optopt to val regardless of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - return (BADARG); - } - if (long_options[match].has_arg == required_argument || - long_options[match].has_arg == optional_argument) { - if (has_equal) - optarg = has_equal; - else if (long_options[match].has_arg == - required_argument) { - /* - * optional argument doesn't use next nargv - */ - optarg = nargv[optind++]; - } - } - if ((long_options[match].has_arg == required_argument) - && (optarg == NULL)) { - /* - * Missing argument; leading ':' indicates no error - * should be generated. - */ - if (PRINT_ERROR) - warnx(recargstring, - current_argv); - /* - * XXX: GNU sets optopt to val regardless of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - --optind; - return (BADARG); - } - } else { /* unknown option */ - if (short_too) { - --optind; - return (-1); - } - if (PRINT_ERROR) - warnx(illoptstring, current_argv); - optopt = 0; - return (BADCH); - } - if (idx) - *idx = match; - if (long_options[match].flag) { - *long_options[match].flag = long_options[match].val; - return (0); - } else - return (long_options[match].val); -#undef IDENTICAL_INTERPRETATION -} - -/* - * getopt_internal -- - * Parse argc/argv argument vector. Called by user level routines. - */ -static int -getopt_internal(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx, int flags) -{ - char *oli; /* option letter list index */ - int optchar, short_too; - static int posixly_correct = -1; - - if (options == NULL) - return (-1); - - /* - * XXX Some GNU programs (like cvs) set optind to 0 instead of - * XXX using optreset. Work around this braindamage. - */ - if (optind == 0) - optind = optreset = 1; - - /* - * Disable GNU extensions if POSIXLY_CORRECT is set or options - * string begins with a '+'. - * - * CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or - * optreset != 0 for GNU compatibility. - */ - if (posixly_correct == -1 || optreset != 0) - posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); - if (*options == '-') - flags |= FLAG_ALLARGS; - else if (posixly_correct || *options == '+') - flags &= ~FLAG_PERMUTE; - if (*options == '+' || *options == '-') - options++; - - optarg = NULL; - if (optreset) - nonopt_start = nonopt_end = -1; -start: - if (optreset || !*place) { /* update scanning pointer */ - optreset = 0; - if (optind >= nargc) { /* end of argument vector */ - place = EMSG; - if (nonopt_end != -1) { - /* do permutation, if we have to */ - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - else if (nonopt_start != -1) { - /* - * If we skipped non-options, set optind - * to the first of them. - */ - optind = nonopt_start; - } - nonopt_start = nonopt_end = -1; - return (-1); - } - if (*(place = nargv[optind]) != '-' || - (place[1] == '\0' && strchr(options, '-') == NULL)) { - place = EMSG; /* found non-option */ - if (flags & FLAG_ALLARGS) { - /* - * GNU extension: - * return non-option as argument to option 1 - */ - optarg = nargv[optind++]; - return (INORDER); - } - if (!(flags & FLAG_PERMUTE)) { - /* - * If no permutation wanted, stop parsing - * at first non-option. - */ - return (-1); - } - /* do permutation */ - if (nonopt_start == -1) - nonopt_start = optind; - else if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - nonopt_start = optind - - (nonopt_end - nonopt_start); - nonopt_end = -1; - } - optind++; - /* process next argument */ - goto start; - } - if (nonopt_start != -1 && nonopt_end == -1) - nonopt_end = optind; - - /* - * If we have "-" do nothing, if "--" we are done. - */ - if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { - optind++; - place = EMSG; - /* - * We found an option (--), so if we skipped - * non-options, we have to permute. - */ - if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - nonopt_start = nonopt_end = -1; - return (-1); - } - } - - /* - * Check long options if: - * 1) we were passed some - * 2) the arg is not just "-" - * 3) either the arg starts with -- we are getopt_long_only() - */ - if (long_options != NULL && place != nargv[optind] && - (*place == '-' || (flags & FLAG_LONGONLY))) { - short_too = 0; - if (*place == '-') - place++; /* --foo long option */ - else if (*place != ':' && strchr(options, *place) != NULL) - short_too = 1; /* could be short option too */ - - optchar = parse_long_options(nargv, options, long_options, - idx, short_too); - if (optchar != -1) { - place = EMSG; - return (optchar); - } - } - - if ((optchar = (int)*place++) == (int)':' || - (optchar == (int)'-' && *place != '\0') || - (oli = (char*)strchr(options, optchar)) == NULL) { - /* - * If the user specified "-" and '-' isn't listed in - * options, return -1 (non-option) as per POSIX. - * Otherwise, it is an unknown option character (or ':'). - */ - if (optchar == (int)'-' && *place == '\0') - return (-1); - if (!*place) - ++optind; - if (PRINT_ERROR) - warnx(illoptchar, optchar); - optopt = optchar; - return (BADCH); - } - if (long_options != NULL && optchar == 'W' && oli[1] == ';') { - /* -W long-option */ - if (*place) /* no space */ - /* NOTHING */; - else if (++optind >= nargc) { /* no arg */ - place = EMSG; - if (PRINT_ERROR) - warnx(recargchar, optchar); - optopt = optchar; - return (BADARG); - } else /* white space */ - place = nargv[optind]; - optchar = parse_long_options(nargv, options, long_options, - idx, 0); - place = EMSG; - return (optchar); - } - if (*++oli != ':') { /* doesn't take argument */ - if (!*place) - ++optind; - } else { /* takes (optional) argument */ - optarg = NULL; - if (*place) /* no white space */ - optarg = place; - else if (oli[1] != ':') { /* arg not optional */ - if (++optind >= nargc) { /* no arg */ - place = EMSG; - if (PRINT_ERROR) - warnx(recargchar, optchar); - optopt = optchar; - return (BADARG); - } else - optarg = nargv[optind]; - } - place = EMSG; - ++optind; - } - /* dump back option letter */ - return (optchar); -} - -/* - * getopt_long -- - * Parse argc/argv argument vector. - */ -int -getopt_long(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx) -{ - - return (getopt_internal(nargc, nargv, options, long_options, idx, - FLAG_PERMUTE)); -} - -/* - * getopt_long_only -- - * Parse argc/argv argument vector. - */ -int -getopt_long_only(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx) -{ - - return (getopt_internal(nargc, nargv, options, long_options, idx, - FLAG_PERMUTE|FLAG_LONGONLY)); -} - -//extern int getopt_long(int nargc, char * const *nargv, const char *options, -// const struct option *long_options, int *idx); -//extern int getopt_long_only(int nargc, char * const *nargv, const char *options, -// const struct option *long_options, int *idx); -/* - * Previous MinGW implementation had... - */ -#ifndef HAVE_DECL_GETOPT -/* - * ...for the long form API only; keep this for compatibility. - */ -# define HAVE_DECL_GETOPT 1 -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */ \ No newline at end of file diff --git a/live/ppLive.c b/live/ppLive.c deleted file mode 100644 index cc7d68d..0000000 --- a/live/ppLive.c +++ /dev/null @@ -1,352 +0,0 @@ -/* ppLive.c -- https://github.com/takeiteasy/pp - - The MIT License (MIT) - - Copyright (c) 2022 George Watson - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#define PP_IMPLEMENTATION -#include "ppLive.h" -#if defined(PP_WINDOWS) -#include -#include -#define F_OK 0 -#define access _access -#include "getopt_win32.h" -#ifndef _MSC_VER -#pragma comment(lib, "Psapi.lib") -#endif -#include "dlfcn_win32.h" -static FILETIME writeTime; -#else -#include -#define _BSD_SOURCE // usleep() -#include -#include -#include -#include -static ino_t handleID; -#endif - -static void *handle = NULL; -static ppState *state = NULL; -static ppApp *app = NULL; -static ppSurface *surface = NULL; -static struct { - int width; - int height; - const char *title; - ppFlags flags; - char *path; -} Args = {0}; - -static struct option long_options[] = { - {"width", required_argument, NULL, 'w'}, - {"height", required_argument, NULL, 'h'}, - {"title", required_argument, NULL, 't'}, - {"resizable", no_argument, NULL, 'r'}, - {"top", no_argument, NULL, 'a'}, - {"usage", no_argument, NULL, 'u'}, - {"path", required_argument, NULL, 'p'}, - {NULL, 0, NULL, 0} -}; - -static void usage(void) { - puts(" usage: ppLive -p [path to dylib] [options]\n"); - puts(" -w/--width -- Window width [default: 640]"); - puts(" -h/--height -- Window height [default: 480]"); - puts(" -t/--title -- Window title [default: \"pp\"]"); - puts(" -r/--resizable -- Enable resizable window"); - puts(" -a/--top -- Enable window always on top"); - puts(" -p/--path -- Path the dynamic library [required]"); - puts(" -u/--usage -- Display this message"); -} - -#if defined(PP_WINDOWS) -static FILETIME Win32GetLastWriteTime(char* path) { - FILETIME time; - WIN32_FILE_ATTRIBUTE_DATA data; - - if (GetFileAttributesEx(path, GetFileExInfoStandard, &data)) - time = data.ftLastWriteTime; - - return time; -} -#endif - -static int ShouldReloadLibrary(void) { -#if defined(PP_WINDOWS) - FILETIME newTime = Win32GetLastWriteTime(Args.path); - bool result = CompareFileTime(&newTime, &writeTime); - if (result) - writeTime = newTime; - return result; -#else - struct stat attr; - int result = !stat(Args.path, &attr) && handleID != attr.st_ino; - if (result) - handleID = attr.st_ino; - return result; -#endif -} - -#if defined(PP_WINDOWS) -char* RemoveExt(char* path) { - char *ret = malloc(strlen(path) + 1); - if (!ret) - return NULL; - strcpy(ret, path); - char *ext = strrchr(ret, '.'); - if (ext) - *ext = '\0'; - return ret; -} -#endif - -static int ReloadLibrary(const char *path) { - if (!ShouldReloadLibrary()) - return 1; - - if (handle) { - if (app->unload) - app->unload(state); - dlclose(handle); - } - -#if defined(PP_WINDOWS) - size_t newPathSize = strlen(path) + 4; - char *newPath = malloc(sizeof(char) * newPathSize); - char *noExt = RemoveExt(path); - sprintf(newPath, "%s.tmp.dll", noExt); - CopyFile(path, newPath, 0); - handle = dlopen(newPath, RTLD_NOW); - free(newPath); - free(noExt); - if (!handle) -#else - if (!(handle = dlopen(path, RTLD_NOW))) -#endif - goto BAIL; - if (!(app = dlsym(handle, "pp"))) - goto BAIL; - if (!state) { - if (!(state = app->init())) - goto BAIL; - } else { - if (app->reload) - app->reload(state); - } - return 1; - -BAIL: - if (handle) - dlclose(handle); - handle = NULL; -#if defined(PP_WINDOWS) - memset(&writeTime, 0, sizeof(FILETIME)); -#else - handleID = 0; -#endif - return 0; -} - -#define ppInputCallback(E) \ - if (app->event) \ - app->event(state, &(E)) - -static void ppInputKeyboard(void *userdata, int key, int modifier, int isDown) { - ppEvent e = { - .type = ppKeyboardEvent, - .Keyboard = { - .key = key, - .isdown = isDown - }, - .modifier = modifier - }; - ppInputCallback(e); -} - -static void ppInputMouseButton(void *userdata, int button, int modifier, int isDown) { - ppEvent e = { - .type = ppMouseButtonEvent, - .Mouse = { - .button = button, - .isdown = isDown - }, - .modifier = modifier - }; - ppInputCallback(e); -} - -static void ppInputMouseMove(void *userdata, int x, int y, float dx, float dy) { - ppEvent e = { - .type = ppMouseMoveEvent, - .Mouse = { - .Position = { - .x = x, - .y = y, - .dx = dx, - .dy = dy - } - } - }; - ppInputCallback(e); -} - -static void ppInputMouseScroll(void *userdata, float dx, float dy, int modifier) { - ppEvent e = { - .type = ppMouseScrollEvent, - .Mouse = { - .Scroll = { - .dx = dx, - .dy = dy - } - } - }; - ppInputCallback(e); -} - -static void ppInputFocus(void *userdata, int isFocused) { - ppEvent e = { - .type = ppFocusEvent, - .Window = { - .focused = isFocused - } - }; - ppInputCallback(e); -} - -static void ppInputResized(void *userdata, int w, int h) { - ppEvent e = { - .type = ppResizedEvent, - .Window = { - .Size = { - .width = w, - .height = h - } - } - }; - ppInputCallback(e); -} - -static void ppInputClosed(void *userdata) { - ppEvent e = { - .type = ppClosedEvent, - .Window = { - .closed = true - } - }; - ppInputCallback(e); -} - -int main(int argc, char *argv[]) { - extern char* optarg; - extern int optopt; - int opt; - while ((opt = getopt_long(argc, argv, ":w:h:t:p:uar", long_options, NULL)) != -1) { - switch (opt) { - case 'w': - Args.width = atoi(optarg); - break; - case 'h': - Args.height = atoi(optarg); - break; - case 't': - Args.title = optarg; - break; - case 'r': - Args.flags |= ppResizable; - break; - case 'a': - Args.flags |= ppAlwaysOnTop; - break; - case 'p': - Args.path = optarg; - break; - case ':': - printf("ERROR: \"-%c\" requires an value!\n", optopt); - usage(); - return 1; - case '?': - printf("ERROR: Unknown argument \"-%c\"\n", optopt); - usage(); - return 1; - case 'u': - usage(); - return 0; - default: - usage(); - return 1; - } - } - - if (!Args.path) { - puts("ERROR: No path to dynamic library provided (-p/--path)"); - usage(); - return 1; - } else { -#if !defined(PP_WINDOWS) - if (Args.path[0] != '.' || Args.path[1] != '/') { - char *tmp = malloc(strlen(Args.path) + 2 * sizeof(char)); - sprintf(tmp, "./%s", Args.path); - Args.path = tmp; - } else - Args.path = strdup(Args.path); -#endif - } - - if (access(Args.path, F_OK)) { - printf("ERROR: No file found at path \"%s\"\n", Args.path); - return 1; - } - - if (!Args.width) - Args.width = 640; - if (!Args.height) - Args.height = 480; - ppBegin(Args.width, Args.height, Args.title ? Args.title : "pp", Args.flags); - surface = ppNewSurface(Args.width, Args.height); - - if (!ReloadLibrary(Args.path)) - return 1; - -#define X(NAME, _) ppInput##NAME, - ppCallbacks(PP_CALLBACKS NULL); -#undef X - - while (ppPoll()) { - if (!ReloadLibrary(Args.path)) - break; - if (!app->tick(state, surface, ppTime())) - break; - ppFlush(surface->buf, surface->w, surface->h); - } - - app->deinit(state); - if (handle) - dlclose(handle); - ppFreeSurface(surface); -#if !defined(PP_WINDOWS) - free(Args.path); -#endif - ppEnd(); - return 0; -} diff --git a/live/ppLive.h b/live/ppLive.h deleted file mode 100644 index a8248b6..0000000 --- a/live/ppLive.h +++ /dev/null @@ -1,104 +0,0 @@ -/* ppLive.h -- https://github.com/takeiteasy/pp - - The MIT License (MIT) - - Copyright (c) 2022 George Watson - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef ppLive_h -#define ppLive_h -#if defined(__cplusplus) -extern "C" { -#endif - -#include "pp.h" - -typedef union ppColor { - struct { - unsigned char a; - unsigned char r; - unsigned char g; - unsigned char b; - }; - int value; -} ppColor; - -typedef struct ppSurface { - int *buf, w, h; -} ppSurface; - -EXPORT ppSurface* ppNewSurface(int w, int h); -EXPORT void ppFreeSurface(ppSurface *surface); -EXPORT void ppClearSurface(ppSurface *surface, ppColor color); -EXPORT void ppSurfacePSet(ppSurface *surface, int x, int y, ppColor color); -EXPORT ppColor ppSurfacePGet(ppSurface *surface, int x, int y); - -typedef struct ppState ppState; - -typedef enum { -#define X(NAME, ARGS) pp##NAME##Event, - PP_CALLBACKS -#undef X -} ppEventType; - -typedef struct { - struct { - int button; - int isdown; - struct { - int x, y; - float dx, dy; - } Position; - struct { - float dx, dy; - } Scroll; - } Mouse; - struct { - ppKey key; - int isdown; - } Keyboard; - ppMod modifier; - struct { - int focused, closed; - struct { - int width, height; - } Size; - } Window; - ppEventType type; -} ppEvent; - -typedef struct { - ppState*(*init)(void); - void(*deinit)(ppState*); - void(*reload)(ppState*); - void(*unload)(ppState*); - int(*event)(ppState*, ppEvent*); - int(*tick)(ppState*, ppSurface*, double); -} ppApp; - -#ifndef _MSC_VER -extern const ppApp pp; -#endif - -#if defined(__cplusplus) -} -#endif -#endif // ppLive_h diff --git a/live/ppUtils.c b/live/ppUtils.c deleted file mode 100644 index 98f39f3..0000000 --- a/live/ppUtils.c +++ /dev/null @@ -1,79 +0,0 @@ -/* ppUtils.h -- https://github.com/takeiteasy/pp - - The MIT License (MIT) - - Copyright (c) 2022 George Watson - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "ppLive.h" -#include -#include - -ppSurface* ppNewSurface(int w, int h) { - assert(w && h); - ppSurface *result = (ppSurface*)malloc(sizeof(ppSurface)); - result->w = w; - result->h = h; - result->buf = (int*)malloc(w * h * sizeof(int)); - return result; -} - -void ppFreeSurface(ppSurface *surface) { - assert(surface && surface->buf); - free(surface->buf); - free(surface); -} - -void ppClearSurface(ppSurface *surface, ppColor color) { - assert(surface && surface->buf); - for (int i = 0; i < surface->w * surface->h; i++) - surface->buf[i] = color.value; -} - -#if defined(PP_ENABLE_BLENDING) -#define BLEND(c0, c1, a0, a1) (c0 * a0 / 255) + (c1 * a1 * (255 - a0) / 65025) - -static ppColor ppBlendColor(ppColor _a, ppColor _b) { - return !_a.a ? (ppColor){.value = 0xFF000000} : a >= 255 ? a : (ppColor) { - .r = BLEND(_a.r, _b.r, _a.a, _b.a), - .g = BLEND(_a.g, _b.g, _a.a, _b.a), - .b = BLEND(_a.b, _b.b, _a.a, _b.a), - .a = _a.a + (_b.a * (255 - _a.a) >> 8) - }; -} -#endif - -void ppSurfacePSet(ppSurface *surface, int x, int y, ppColor color) { - assert(surface && surface->buf); - assert(x >= 0 && y >= 0 && x < surface->w && y < surface->h); - surface->buf[y * surface->w + x] = -#if defined(PP_ENABLE_BLENDING) - ppBlendColor(ppPGet(surface, x, y), color); -#else - color.value; -#endif -} - -ppColor ppSurfacePGet(ppSurface *surface, int x, int y) { - assert(surface && surface->buf); - assert(x >= 0 && y >= 0 && x < surface->w && y < surface->h); - return (ppColor){.value = surface->buf[y * surface->w + x]}; -} diff --git a/rebuild.bat b/rebuild.bat deleted file mode 100644 index aff4e1d..0000000 --- a/rebuild.bat +++ /dev/null @@ -1,4 +0,0 @@ -@echo off -if exist .\build\ppLive.dll move .\build\ppLive.dll .\build\ppLive.%random%.dll -cl .\live\ppUtils.c .\examples\live.c /I.\src /I.\live /MD /link /DLL /SUBSYSTEM:CONSOLE /out:.\build\ppLive.dll -del *.obj \ No newline at end of file