slouken@5189
|
1 |
/*
|
slouken@5535
|
2 |
Simple DirectMedia Layer
|
slouken@8149
|
3 |
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
slouken@5189
|
4 |
|
slouken@5535
|
5 |
This software is provided 'as-is', without any express or implied
|
slouken@5535
|
6 |
warranty. In no event will the authors be held liable for any damages
|
slouken@5535
|
7 |
arising from the use of this software.
|
slouken@5189
|
8 |
|
slouken@5535
|
9 |
Permission is granted to anyone to use this software for any purpose,
|
slouken@5535
|
10 |
including commercial applications, and to alter it and redistribute it
|
slouken@5535
|
11 |
freely, subject to the following restrictions:
|
slouken@5189
|
12 |
|
slouken@5535
|
13 |
1. The origin of this software must not be misrepresented; you must not
|
slouken@5535
|
14 |
claim that you wrote the original software. If you use this software
|
slouken@5535
|
15 |
in a product, an acknowledgment in the product documentation would be
|
slouken@5535
|
16 |
appreciated but is not required.
|
slouken@5535
|
17 |
2. Altered source versions must be plainly marked as such, and must not be
|
slouken@5535
|
18 |
misrepresented as being the original software.
|
slouken@5535
|
19 |
3. This notice may not be removed or altered from any source distribution.
|
slouken@5189
|
20 |
*/
|
icculus@8093
|
21 |
#include "./SDL_internal.h"
|
slouken@5189
|
22 |
|
slouken@5189
|
23 |
#include "SDL_hints.h"
|
slouken@7432
|
24 |
#include "SDL_error.h"
|
slouken@5189
|
25 |
|
slouken@5189
|
26 |
|
slouken@5189
|
27 |
/* Assuming there aren't many hints set and they aren't being queried in
|
slouken@7432
|
28 |
critical performance paths, we'll just use linked lists here.
|
slouken@5189
|
29 |
*/
|
slouken@7432
|
30 |
typedef struct SDL_HintWatch {
|
slouken@7432
|
31 |
SDL_HintCallback callback;
|
slouken@7432
|
32 |
void *userdata;
|
slouken@7432
|
33 |
struct SDL_HintWatch *next;
|
slouken@7432
|
34 |
} SDL_HintWatch;
|
slouken@7432
|
35 |
|
slouken@5189
|
36 |
typedef struct SDL_Hint {
|
slouken@5189
|
37 |
char *name;
|
slouken@5189
|
38 |
char *value;
|
slouken@5189
|
39 |
SDL_HintPriority priority;
|
slouken@7432
|
40 |
SDL_HintWatch *callbacks;
|
slouken@5189
|
41 |
struct SDL_Hint *next;
|
slouken@5189
|
42 |
} SDL_Hint;
|
slouken@5189
|
43 |
|
slouken@5189
|
44 |
static SDL_Hint *SDL_hints;
|
slouken@5189
|
45 |
|
tim@5555
|
46 |
SDL_bool
|
slouken@5200
|
47 |
SDL_SetHintWithPriority(const char *name, const char *value,
|
slouken@5200
|
48 |
SDL_HintPriority priority)
|
slouken@5189
|
49 |
{
|
slouken@5189
|
50 |
const char *env;
|
icculus@6389
|
51 |
SDL_Hint *hint;
|
slouken@7432
|
52 |
SDL_HintWatch *entry;
|
slouken@5189
|
53 |
|
slouken@5189
|
54 |
if (!name || !value) {
|
slouken@5189
|
55 |
return SDL_FALSE;
|
slouken@5189
|
56 |
}
|
slouken@5189
|
57 |
|
slouken@5189
|
58 |
env = SDL_getenv(name);
|
slouken@5189
|
59 |
if (env && priority < SDL_HINT_OVERRIDE) {
|
slouken@5189
|
60 |
return SDL_FALSE;
|
slouken@5189
|
61 |
}
|
slouken@5189
|
62 |
|
icculus@6389
|
63 |
for (hint = SDL_hints; hint; hint = hint->next) {
|
slouken@5189
|
64 |
if (SDL_strcmp(name, hint->name) == 0) {
|
slouken@5189
|
65 |
if (priority < hint->priority) {
|
slouken@5189
|
66 |
return SDL_FALSE;
|
slouken@5189
|
67 |
}
|
slouken@7432
|
68 |
if (!hint->value || !value || SDL_strcmp(hint->value, value) != 0) {
|
slouken@7432
|
69 |
for (entry = hint->callbacks; entry; ) {
|
slouken@7432
|
70 |
/* Save the next entry in case this one is deleted */
|
slouken@7432
|
71 |
SDL_HintWatch *next = entry->next;
|
slouken@7432
|
72 |
entry->callback(entry->userdata, name, hint->value, value);
|
slouken@7432
|
73 |
entry = next;
|
tim@5555
|
74 |
}
|
slouken@7719
|
75 |
SDL_free(hint->value);
|
slouken@7716
|
76 |
hint->value = value ? SDL_strdup(value) : NULL;
|
slouken@5189
|
77 |
}
|
slouken@5189
|
78 |
hint->priority = priority;
|
slouken@5189
|
79 |
return SDL_TRUE;
|
slouken@5189
|
80 |
}
|
slouken@5189
|
81 |
}
|
slouken@5189
|
82 |
|
slouken@5189
|
83 |
/* Couldn't find the hint, add a new one */
|
slouken@5189
|
84 |
hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
|
slouken@5189
|
85 |
if (!hint) {
|
slouken@5189
|
86 |
return SDL_FALSE;
|
slouken@5189
|
87 |
}
|
slouken@5189
|
88 |
hint->name = SDL_strdup(name);
|
slouken@7432
|
89 |
hint->value = value ? SDL_strdup(value) : NULL;
|
slouken@5189
|
90 |
hint->priority = priority;
|
slouken@7432
|
91 |
hint->callbacks = NULL;
|
slouken@5189
|
92 |
hint->next = SDL_hints;
|
slouken@5189
|
93 |
SDL_hints = hint;
|
slouken@5189
|
94 |
return SDL_TRUE;
|
slouken@5189
|
95 |
}
|
slouken@5189
|
96 |
|
slouken@5200
|
97 |
SDL_bool
|
slouken@5200
|
98 |
SDL_SetHint(const char *name, const char *value)
|
slouken@5200
|
99 |
{
|
slouken@5200
|
100 |
return SDL_SetHintWithPriority(name, value, SDL_HINT_NORMAL);
|
slouken@5200
|
101 |
}
|
slouken@5200
|
102 |
|
slouken@5189
|
103 |
const char *
|
slouken@5189
|
104 |
SDL_GetHint(const char *name)
|
slouken@5189
|
105 |
{
|
slouken@5189
|
106 |
const char *env;
|
slouken@5189
|
107 |
SDL_Hint *hint;
|
slouken@5189
|
108 |
|
slouken@5189
|
109 |
env = SDL_getenv(name);
|
slouken@5189
|
110 |
for (hint = SDL_hints; hint; hint = hint->next) {
|
slouken@5189
|
111 |
if (SDL_strcmp(name, hint->name) == 0) {
|
slouken@5189
|
112 |
if (!env || hint->priority == SDL_HINT_OVERRIDE) {
|
slouken@5189
|
113 |
return hint->value;
|
slouken@5189
|
114 |
}
|
slouken@5189
|
115 |
break;
|
slouken@5189
|
116 |
}
|
slouken@5189
|
117 |
}
|
slouken@5189
|
118 |
return env;
|
slouken@5189
|
119 |
}
|
slouken@5189
|
120 |
|
slouken@7432
|
121 |
void
|
slouken@7432
|
122 |
SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
|
slouken@7432
|
123 |
{
|
slouken@7432
|
124 |
SDL_Hint *hint;
|
slouken@7432
|
125 |
SDL_HintWatch *entry;
|
slouken@7432
|
126 |
const char *value;
|
slouken@7432
|
127 |
|
slouken@7432
|
128 |
if (!name || !*name) {
|
slouken@7432
|
129 |
SDL_InvalidParamError("name");
|
slouken@7432
|
130 |
return;
|
slouken@7432
|
131 |
}
|
slouken@7432
|
132 |
if (!callback) {
|
slouken@7432
|
133 |
SDL_InvalidParamError("callback");
|
slouken@7432
|
134 |
return;
|
slouken@7432
|
135 |
}
|
slouken@7432
|
136 |
|
slouken@7432
|
137 |
SDL_DelHintCallback(name, callback, userdata);
|
slouken@7432
|
138 |
|
slouken@7432
|
139 |
entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry));
|
slouken@7432
|
140 |
entry->callback = callback;
|
slouken@7432
|
141 |
entry->userdata = userdata;
|
slouken@7432
|
142 |
|
slouken@7432
|
143 |
for (hint = SDL_hints; hint; hint = hint->next) {
|
slouken@7432
|
144 |
if (SDL_strcmp(name, hint->name) == 0) {
|
slouken@7432
|
145 |
break;
|
slouken@7432
|
146 |
}
|
slouken@7432
|
147 |
}
|
slouken@7432
|
148 |
if (!hint) {
|
slouken@7432
|
149 |
/* Need to add a hint entry for this watcher */
|
slouken@7432
|
150 |
hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
|
slouken@7432
|
151 |
if (!hint) {
|
slouken@7432
|
152 |
return;
|
slouken@7432
|
153 |
}
|
slouken@7432
|
154 |
hint->name = SDL_strdup(name);
|
slouken@7432
|
155 |
hint->value = NULL;
|
slouken@7432
|
156 |
hint->priority = SDL_HINT_DEFAULT;
|
slouken@7432
|
157 |
hint->callbacks = NULL;
|
slouken@7432
|
158 |
hint->next = SDL_hints;
|
slouken@7432
|
159 |
SDL_hints = hint;
|
slouken@7432
|
160 |
}
|
slouken@7432
|
161 |
|
slouken@7432
|
162 |
/* Add it to the callbacks for this hint */
|
slouken@7432
|
163 |
entry->next = hint->callbacks;
|
slouken@7432
|
164 |
hint->callbacks = entry;
|
slouken@7432
|
165 |
|
slouken@7432
|
166 |
/* Now call it with the current value */
|
slouken@7432
|
167 |
value = SDL_GetHint(name);
|
slouken@7432
|
168 |
callback(userdata, name, value, value);
|
slouken@7432
|
169 |
}
|
slouken@7432
|
170 |
|
slouken@7432
|
171 |
void
|
slouken@7432
|
172 |
SDL_DelHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
|
slouken@7432
|
173 |
{
|
slouken@7432
|
174 |
SDL_Hint *hint;
|
slouken@7432
|
175 |
SDL_HintWatch *entry, *prev;
|
slouken@7432
|
176 |
|
slouken@7432
|
177 |
for (hint = SDL_hints; hint; hint = hint->next) {
|
slouken@7432
|
178 |
if (SDL_strcmp(name, hint->name) == 0) {
|
slouken@7432
|
179 |
prev = NULL;
|
slouken@7432
|
180 |
for (entry = hint->callbacks; entry; entry = entry->next) {
|
slouken@7432
|
181 |
if (callback == entry->callback && userdata == entry->userdata) {
|
slouken@7432
|
182 |
if (prev) {
|
slouken@7432
|
183 |
prev->next = entry->next;
|
slouken@7432
|
184 |
} else {
|
slouken@7432
|
185 |
hint->callbacks = entry->next;
|
slouken@7432
|
186 |
}
|
slouken@7432
|
187 |
SDL_free(entry);
|
slouken@7432
|
188 |
break;
|
slouken@7432
|
189 |
}
|
slouken@7432
|
190 |
prev = entry;
|
slouken@7432
|
191 |
}
|
slouken@7432
|
192 |
return;
|
slouken@7432
|
193 |
}
|
slouken@7432
|
194 |
}
|
slouken@7432
|
195 |
}
|
slouken@7432
|
196 |
|
slouken@5273
|
197 |
void SDL_ClearHints(void)
|
slouken@5189
|
198 |
{
|
slouken@5189
|
199 |
SDL_Hint *hint;
|
slouken@7432
|
200 |
SDL_HintWatch *entry;
|
slouken@5189
|
201 |
|
slouken@5189
|
202 |
while (SDL_hints) {
|
slouken@5189
|
203 |
hint = SDL_hints;
|
slouken@5189
|
204 |
SDL_hints = hint->next;
|
slouken@5189
|
205 |
|
slouken@5189
|
206 |
SDL_free(hint->name);
|
slouken@7719
|
207 |
SDL_free(hint->value);
|
slouken@7432
|
208 |
for (entry = hint->callbacks; entry; ) {
|
slouken@7432
|
209 |
SDL_HintWatch *freeable = entry;
|
slouken@7432
|
210 |
entry = entry->next;
|
slouken@7432
|
211 |
SDL_free(freeable);
|
slouken@7432
|
212 |
}
|
slouken@5189
|
213 |
SDL_free(hint);
|
slouken@5189
|
214 |
}
|
slouken@5189
|
215 |
}
|
slouken@5189
|
216 |
|
slouken@5189
|
217 |
/* vi: set ts=4 sw=4 expandtab: */
|