SDL_hints.c
Go to the documentation of this file.
/*
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: */
SDL_HintWatch::userdata
void * userdata
Definition: SDL_hints.c:32
SDL_GetHint
const char * SDL_GetHint(const char *name)
Get a hint.
Definition: SDL_hints.c:104
SDL_DelHintCallback
void SDL_DelHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
Remove a function watching a particular hint.
Definition: SDL_hints.c:178
SDL_Hint::next
struct SDL_Hint * next
Definition: SDL_hints.c:41
SDL_AddHintCallback
void SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
Definition: SDL_hints.c:122
SDL_SetHintWithPriority
SDL_bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPriority priority)
Set a hint with a specific priority.
Definition: SDL_hints.c:47
SDL_internal.h
SDL_HINT_OVERRIDE
Definition: SDL_hints.h:640
SDL_HintCallback
void(* SDL_HintCallback)(void *userdata, const char *name, const char *oldValue, const char *newValue)
Add a function to watch a particular hint.
Definition: SDL_hints.h:679
SDL_HintPriority
SDL_HintPriority
An enumeration of hint priorities.
Definition: SDL_hints.h:636
name
GLuint const GLchar * name
Definition: SDL_opengl_glext.h:660
SDL_InvalidParamError
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
SDL_HINT_DEFAULT
Definition: SDL_hints.h:638
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:126
value
GLsizei const GLfloat * value
Definition: SDL_opengl_glext.h:698
SDL_free
void SDL_free(void *mem)
SDL_hints.h
SDL_SetHint
SDL_bool SDL_SetHint(const char *name, const char *value)
Set a hint with normal priority.
Definition: SDL_hints.c:98
SDL_TRUE
Definition: SDL_stdinc.h:129
SDL_Hint::callbacks
SDL_HintWatch * callbacks
Definition: SDL_hints.c:40
SDL_getenv
#define SDL_getenv
Definition: SDL_dynapi_overrides.h:384
NULL
#define NULL
Definition: begin_code.h:143
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_Hint::priority
SDL_HintPriority priority
Definition: SDL_hints.c:39
SDL_HintWatch
Definition: SDL_hints.c:30
SDL_strdup
#define SDL_strdup
Definition: SDL_dynapi_overrides.h:403
SDL_FALSE
Definition: SDL_stdinc.h:128
SDL_ClearHints
void SDL_ClearHints(void)
Clear all hints.
Definition: SDL_hints.c:203
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:380
SDL_strcmp
#define SDL_strcmp
Definition: SDL_dynapi_overrides.h:423
SDL_Hint::value
char * value
Definition: SDL_hints.c:38
SDL_error.h
SDL_HintWatch::callback
SDL_HintCallback callback
Definition: SDL_hints.c:31
SDL_HintWatch::next
struct SDL_HintWatch * next
Definition: SDL_hints.c:33
SDL_Hint
Definition: SDL_hints.c:36
SDL_HINT_NORMAL
Definition: SDL_hints.h:639
SDL_Hint::name
char * name
Definition: SDL_hints.c:37
SDL_hints
static SDL_Hint * SDL_hints
Definition: SDL_hints.c:44