diff options
author | 2016-02-27 16:28:05 +0100 | |
---|---|---|
committer | 2016-02-27 16:53:49 +0100 | |
commit | cf6dc7d370407914020f3e623719f09c8668c692 (patch) | |
tree | 46b3416d091b4c09b50fba7ffcbd310aed032cc8 /3rdparty/SDL2/src/SDL_hints.c | |
parent | 64135e73f973d9b95beb0c60b65feb34fbfec64a (diff) |
Placed SDL2 source since we need it on some platforms (nw)
Diffstat (limited to '3rdparty/SDL2/src/SDL_hints.c')
-rw-r--r-- | 3rdparty/SDL2/src/SDL_hints.c | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/3rdparty/SDL2/src/SDL_hints.c b/3rdparty/SDL2/src/SDL_hints.c new file mode 100644 index 00000000000..04523327ade --- /dev/null +++ b/3rdparty/SDL2/src/SDL_hints.c @@ -0,0 +1,223 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "./SDL_internal.h" + +#include "SDL_hints.h" +#include "SDL_error.h" + + +/* Assuming there aren't many hints set and they aren't being queried in + critical performance paths, we'll just use linked lists here. + */ +typedef struct SDL_HintWatch { + SDL_HintCallback callback; + void *userdata; + struct SDL_HintWatch *next; +} SDL_HintWatch; + +typedef struct SDL_Hint { + char *name; + char *value; + SDL_HintPriority priority; + SDL_HintWatch *callbacks; + struct SDL_Hint *next; +} SDL_Hint; + +static SDL_Hint *SDL_hints; + +SDL_bool +SDL_SetHintWithPriority(const char *name, const char *value, + SDL_HintPriority priority) +{ + const char *env; + SDL_Hint *hint; + SDL_HintWatch *entry; + + if (!name || !value) { + return SDL_FALSE; + } + + env = SDL_getenv(name); + if (env && priority < SDL_HINT_OVERRIDE) { + return SDL_FALSE; + } + + for (hint = SDL_hints; hint; hint = hint->next) { + if (SDL_strcmp(name, hint->name) == 0) { + if (priority < hint->priority) { + return SDL_FALSE; + } + if (!hint->value || !value || SDL_strcmp(hint->value, value) != 0) { + for (entry = hint->callbacks; entry; ) { + /* Save the next entry in case this one is deleted */ + SDL_HintWatch *next = entry->next; + entry->callback(entry->userdata, name, hint->value, value); + entry = next; + } + SDL_free(hint->value); + hint->value = value ? SDL_strdup(value) : NULL; + } + hint->priority = priority; + return SDL_TRUE; + } + } + + /* Couldn't find the hint, add a new one */ + hint = (SDL_Hint *)SDL_malloc(sizeof(*hint)); + if (!hint) { + return SDL_FALSE; + } + hint->name = SDL_strdup(name); + hint->value = value ? SDL_strdup(value) : NULL; + hint->priority = priority; + hint->callbacks = NULL; + hint->next = SDL_hints; + SDL_hints = hint; + return SDL_TRUE; +} + +SDL_bool +SDL_SetHint(const char *name, const char *value) +{ + return SDL_SetHintWithPriority(name, value, SDL_HINT_NORMAL); +} + +const char * +SDL_GetHint(const char *name) +{ + const char *env; + SDL_Hint *hint; + + env = SDL_getenv(name); + for (hint = SDL_hints; hint; hint = hint->next) { + if (SDL_strcmp(name, hint->name) == 0) { + if (!env || hint->priority == SDL_HINT_OVERRIDE) { + return hint->value; + } + break; + } + } + return env; +} + +void +SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata) +{ + SDL_Hint *hint; + SDL_HintWatch *entry; + const char *value; + + if (!name || !*name) { + SDL_InvalidParamError("name"); + return; + } + if (!callback) { + SDL_InvalidParamError("callback"); + return; + } + + SDL_DelHintCallback(name, callback, userdata); + + entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry)); + if (!entry) { + SDL_OutOfMemory(); + return; + } + entry->callback = callback; + entry->userdata = userdata; + + for (hint = SDL_hints; hint; hint = hint->next) { + if (SDL_strcmp(name, hint->name) == 0) { + break; + } + } + if (!hint) { + /* Need to add a hint entry for this watcher */ + hint = (SDL_Hint *)SDL_malloc(sizeof(*hint)); + if (!hint) { + SDL_OutOfMemory(); + SDL_free(entry); + return; + } + hint->name = SDL_strdup(name); + hint->value = NULL; + hint->priority = SDL_HINT_DEFAULT; + hint->callbacks = NULL; + hint->next = SDL_hints; + SDL_hints = hint; + } + + /* Add it to the callbacks for this hint */ + entry->next = hint->callbacks; + hint->callbacks = entry; + + /* Now call it with the current value */ + value = SDL_GetHint(name); + callback(userdata, name, value, value); +} + +void +SDL_DelHintCallback(const char *name, SDL_HintCallback callback, void *userdata) +{ + SDL_Hint *hint; + SDL_HintWatch *entry, *prev; + + for (hint = SDL_hints; hint; hint = hint->next) { + if (SDL_strcmp(name, hint->name) == 0) { + prev = NULL; + for (entry = hint->callbacks; entry; entry = entry->next) { + if (callback == entry->callback && userdata == entry->userdata) { + if (prev) { + prev->next = entry->next; + } else { + hint->callbacks = entry->next; + } + SDL_free(entry); + break; + } + prev = entry; + } + return; + } + } +} + +void SDL_ClearHints(void) +{ + SDL_Hint *hint; + SDL_HintWatch *entry; + + while (SDL_hints) { + hint = SDL_hints; + SDL_hints = hint->next; + + SDL_free(hint->name); + SDL_free(hint->value); + for (entry = hint->callbacks; entry; ) { + SDL_HintWatch *freeable = entry; + entry = entry->next; + SDL_free(freeable); + } + SDL_free(hint); + } +} + +/* vi: set ts=4 sw=4 expandtab: */ |