21
#include "SDL_internal.h"
23
#include "SDL_hints_c.h"
25
typedef struct SDL_HintWatch
27
SDL_HintCallback callback;
29
struct SDL_HintWatch *next;
32
typedef struct SDL_Hint
35
SDL_HintPriority priority;
36
SDL_HintWatch *callbacks;
39
static SDL_PropertiesID SDL_hint_props = 0;
41
static SDL_PropertiesID GetHintProperties(bool create)
43
if (!SDL_hint_props && create) {
44
SDL_hint_props = SDL_CreateProperties();
46
return SDL_hint_props;
49
void SDL_InitHints(void)
52
(void)GetHintProperties(true);
55
static void SDLCALL CleanupHintProperty(void *userdata, void *value)
57
SDL_Hint *hint = (SDL_Hint *) value;
58
SDL_free(hint->value);
60
SDL_HintWatch *entry = hint->callbacks;
62
SDL_HintWatch *freeable = entry;
69
SDL_bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPriority priority)
71
if (!name || !*name) {
72
return SDL_InvalidParamError("name");
75
const char *env = SDL_getenv(name);
76
if (env && (priority < SDL_HINT_OVERRIDE)) {
77
return SDL_SetError("An environment variable is taking priority");
80
const SDL_PropertiesID hints = GetHintProperties(true);
87
SDL_LockProperties(hints);
89
SDL_Hint *hint = (SDL_Hint *)SDL_GetPointerProperty(hints, name, NULL);
91
if (priority >= hint->priority) {
92
if (hint->value != value && (!value || !hint->value || SDL_strcmp(hint->value, value) != 0)) {
93
char *old_value = hint->value;
95
hint->value = value ? SDL_strdup(value) : NULL;
96
SDL_HintWatch *entry = hint->callbacks;
99
SDL_HintWatch *next = entry->next;
100
entry->callback(entry->userdata, name, old_value, value);
105
hint->priority = priority;
109
hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
111
hint->value = value ? SDL_strdup(value) : NULL;
112
hint->priority = priority;
113
hint->callbacks = NULL;
114
result = SDL_SetPointerPropertyWithCleanup(hints, name, hint, CleanupHintProperty, NULL);
118
SDL_UnlockProperties(hints);
123
SDL_bool SDL_ResetHint(const char *name)
125
if (!name || !*name) {
126
return SDL_InvalidParamError("name");
129
const char *env = SDL_getenv(name);
131
const SDL_PropertiesID hints = GetHintProperties(false);
138
SDL_LockProperties(hints);
140
SDL_Hint *hint = (SDL_Hint *)SDL_GetPointerProperty(hints, name, NULL);
142
if ((!env && hint->value) || (env && !hint->value) || (env && SDL_strcmp(env, hint->value) != 0)) {
143
for (SDL_HintWatch *entry = hint->callbacks; entry;) {
145
SDL_HintWatch *next = entry->next;
146
entry->callback(entry->userdata, name, hint->value, env);
150
SDL_free(hint->value);
152
hint->priority = SDL_HINT_DEFAULT;
156
SDL_UnlockProperties(hints);
161
static void SDLCALL ResetHintsCallback(void *userdata, SDL_PropertiesID hints, const char *name)
163
SDL_Hint *hint = (SDL_Hint *)SDL_GetPointerProperty(hints, name, NULL);
168
const char *env = SDL_getenv(name);
169
if ((!env && hint->value) || (env && !hint->value) || (env && SDL_strcmp(env, hint->value) != 0)) {
170
SDL_HintWatch *entry = hint->callbacks;
173
SDL_HintWatch *next = entry->next;
174
entry->callback(entry->userdata, name, hint->value, env);
178
SDL_free(hint->value);
180
hint->priority = SDL_HINT_DEFAULT;
183
void SDL_ResetHints(void)
185
SDL_EnumerateProperties(GetHintProperties(false), ResetHintsCallback, NULL);
188
SDL_bool SDL_SetHint(const char *name, const char *value)
190
return SDL_SetHintWithPriority(name, value, SDL_HINT_NORMAL);
193
const char *SDL_GetHint(const char *name)
199
const char *result = SDL_getenv(name);
201
const SDL_PropertiesID hints = GetHintProperties(false);
203
SDL_LockProperties(hints);
205
SDL_Hint *hint = (SDL_Hint *)SDL_GetPointerProperty(hints, name, NULL);
207
if (!result || hint->priority == SDL_HINT_OVERRIDE) {
208
result = SDL_GetPersistentString(hint->value);
212
SDL_UnlockProperties(hints);
218
int SDL_GetStringInteger(const char *value, int default_value)
220
if (!value || !*value) {
221
return default_value;
223
if (*value == '0' || SDL_strcasecmp(value, "false") == 0) {
226
if (*value == '1' || SDL_strcasecmp(value, "true") == 0) {
229
if (*value == '-' || SDL_isdigit(*value)) {
230
return SDL_atoi(value);
232
return default_value;
235
bool SDL_GetStringBoolean(const char *value, bool default_value)
237
if (!value || !*value) {
238
return default_value;
240
if (*value == '0' || SDL_strcasecmp(value, "false") == 0) {
246
SDL_bool SDL_GetHintBoolean(const char *name, SDL_bool default_value)
248
const char *hint = SDL_GetHint(name);
249
return SDL_GetStringBoolean(hint, default_value);
252
SDL_bool SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
254
if (!name || !*name) {
255
return SDL_InvalidParamError("name");
256
} else if (!callback) {
257
return SDL_InvalidParamError("callback");
260
const SDL_PropertiesID hints = GetHintProperties(true);
265
SDL_HintWatch *entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry));
269
entry->callback = callback;
270
entry->userdata = userdata;
274
SDL_LockProperties(hints);
276
SDL_RemoveHintCallback(name, callback, userdata);
278
SDL_Hint *hint = (SDL_Hint *)SDL_GetPointerProperty(hints, name, NULL);
282
hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
285
SDL_UnlockProperties(hints);
289
hint->priority = SDL_HINT_DEFAULT;
290
hint->callbacks = NULL;
291
result = SDL_SetPointerPropertyWithCleanup(hints, name, hint, CleanupHintProperty, NULL);
296
entry->next = hint->callbacks;
297
hint->callbacks = entry;
300
const char *value = SDL_GetHint(name);
301
callback(userdata, name, value, value);
303
SDL_UnlockProperties(hints);
308
void SDL_RemoveHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
310
if (!name || !*name) {
314
const SDL_PropertiesID hints = GetHintProperties(false);
319
SDL_LockProperties(hints);
320
SDL_Hint *hint = (SDL_Hint *)SDL_GetPointerProperty(hints, name, NULL);
322
SDL_HintWatch *prev = NULL;
323
for (SDL_HintWatch *entry = hint->callbacks; entry; entry = entry->next) {
324
if ((callback == entry->callback) && (userdata == entry->userdata)) {
326
prev->next = entry->next;
328
hint->callbacks = entry->next;
336
SDL_UnlockProperties(hints);
339
void SDL_QuitHints(void)
341
SDL_DestroyProperties(SDL_hint_props);