SDL  2.0
SDL_hints.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "./SDL_internal.h"
22 
23 #include "SDL_hints.h"
24 #include "SDL_error.h"
25 #include "SDL_hints_c.h"
26 
27 
28 /* Assuming there aren't many hints set and they aren't being queried in
29  critical performance paths, we'll just use linked lists here.
30  */
31 typedef struct SDL_HintWatch {
33  void *userdata;
36 
37 typedef struct SDL_Hint {
38  char *name;
39  char *value;
42  struct SDL_Hint *next;
43 } SDL_Hint;
44 
46 
48 SDL_SetHintWithPriority(const char *name, const char *value,
50 {
51  const char *env;
52  SDL_Hint *hint;
53  SDL_HintWatch *entry;
54 
55  if (!name || !value) {
56  return SDL_FALSE;
57  }
58 
59  env = SDL_getenv(name);
60  if (env && priority < SDL_HINT_OVERRIDE) {
61  return SDL_FALSE;
62  }
63 
64  for (hint = SDL_hints; hint; hint = hint->next) {
65  if (SDL_strcmp(name, hint->name) == 0) {
66  if (priority < hint->priority) {
67  return SDL_FALSE;
68  }
69  if (!hint->value || !value || SDL_strcmp(hint->value, value) != 0) {
70  for (entry = hint->callbacks; entry; ) {
71  /* Save the next entry in case this one is deleted */
72  SDL_HintWatch *next = entry->next;
73  entry->callback(entry->userdata, name, hint->value, value);
74  entry = next;
75  }
76  SDL_free(hint->value);
77  hint->value = value ? SDL_strdup(value) : NULL;
78  }
79  hint->priority = priority;
80  return SDL_TRUE;
81  }
82  }
83 
84  /* Couldn't find the hint, add a new one */
85  hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
86  if (!hint) {
87  return SDL_FALSE;
88  }
89  hint->name = SDL_strdup(name);
90  hint->value = value ? SDL_strdup(value) : NULL;
91  hint->priority = priority;
92  hint->callbacks = NULL;
93  hint->next = SDL_hints;
94  SDL_hints = hint;
95  return SDL_TRUE;
96 }
97 
99 SDL_SetHint(const char *name, const char *value)
100 {
102 }
103 
104 const char *
105 SDL_GetHint(const char *name)
106 {
107  const char *env;
108  SDL_Hint *hint;
109 
110  env = SDL_getenv(name);
111  for (hint = SDL_hints; hint; hint = hint->next) {
112  if (SDL_strcmp(name, hint->name) == 0) {
113  if (!env || hint->priority == SDL_HINT_OVERRIDE) {
114  return hint->value;
115  }
116  break;
117  }
118  }
119  return env;
120 }
121 
122 SDL_bool
123 SDL_GetStringBoolean(const char *value, SDL_bool default_value)
124 {
125  if (!value || !*value) {
126  return default_value;
127  }
128  if (*value == '0' || SDL_strcasecmp(value, "false") == 0) {
129  return SDL_FALSE;
130  }
131  return SDL_TRUE;
132 }
133 
134 SDL_bool
135 SDL_GetHintBoolean(const char *name, SDL_bool default_value)
136 {
137  const char *hint = SDL_GetHint(name);
138  return SDL_GetStringBoolean(hint, default_value);
139 }
140 
141 void
142 SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
143 {
144  SDL_Hint *hint;
145  SDL_HintWatch *entry;
146  const char *value;
147 
148  if (!name || !*name) {
149  SDL_InvalidParamError("name");
150  return;
151  }
152  if (!callback) {
153  SDL_InvalidParamError("callback");
154  return;
155  }
156 
157  SDL_DelHintCallback(name, callback, userdata);
158 
159  entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry));
160  if (!entry) {
161  SDL_OutOfMemory();
162  return;
163  }
164  entry->callback = callback;
165  entry->userdata = userdata;
166 
167  for (hint = SDL_hints; hint; hint = hint->next) {
168  if (SDL_strcmp(name, hint->name) == 0) {
169  break;
170  }
171  }
172  if (!hint) {
173  /* Need to add a hint entry for this watcher */
174  hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
175  if (!hint) {
176  SDL_OutOfMemory();
177  SDL_free(entry);
178  return;
179  }
180  hint->name = SDL_strdup(name);
181  hint->value = NULL;
182  hint->priority = SDL_HINT_DEFAULT;
183  hint->callbacks = NULL;
184  hint->next = SDL_hints;
185  SDL_hints = hint;
186  }
187 
188  /* Add it to the callbacks for this hint */
189  entry->next = hint->callbacks;
190  hint->callbacks = entry;
191 
192  /* Now call it with the current value */
194  callback(userdata, name, value, value);
195 }
196 
197 void
198 SDL_DelHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
199 {
200  SDL_Hint *hint;
201  SDL_HintWatch *entry, *prev;
202 
203  for (hint = SDL_hints; hint; hint = hint->next) {
204  if (SDL_strcmp(name, hint->name) == 0) {
205  prev = NULL;
206  for (entry = hint->callbacks; entry; entry = entry->next) {
207  if (callback == entry->callback && userdata == entry->userdata) {
208  if (prev) {
209  prev->next = entry->next;
210  } else {
211  hint->callbacks = entry->next;
212  }
213  SDL_free(entry);
214  break;
215  }
216  prev = entry;
217  }
218  return;
219  }
220  }
221 }
222 
223 void SDL_ClearHints(void)
224 {
225  SDL_Hint *hint;
226  SDL_HintWatch *entry;
227 
228  while (SDL_hints) {
229  hint = SDL_hints;
230  SDL_hints = hint->next;
231 
232  SDL_free(hint->name);
233  SDL_free(hint->value);
234  for (entry = hint->callbacks; entry; ) {
235  SDL_HintWatch *freeable = entry;
236  entry = entry->next;
237  SDL_free(freeable);
238  }
239  SDL_free(hint);
240  }
241 }
242 
243 /* vi: set ts=4 sw=4 expandtab: */
SDL_DelHintCallback
void SDL_DelHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
Remove a function watching a particular hint.
Definition: SDL_hints.c:198
SDL_AddHintCallback
void SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
Add a function to watch a particular hint.
Definition: SDL_hints.c:142
SDL_hints
static SDL_Hint * SDL_hints
Definition: SDL_hints.c:45
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:48
SDL_GetHint
const char * SDL_GetHint(const char *name)
Get a hint.
Definition: SDL_hints.c:105
NULL
#define NULL
Definition: begin_code.h:167
SDL_error.h
SDL_Hint
Definition: SDL_hints.c:37
SDL_HintPriority
SDL_HintPriority
An enumeration of hint priorities.
Definition: SDL_hints.h:1279
SDL_InvalidParamError
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
callback
static Uint32 callback(Uint32 interval, void *param)
Definition: testtimer.c:34
SDL_HINT_DEFAULT
@ SDL_HINT_DEFAULT
Definition: SDL_hints.h:1280
SDL_Hint::callbacks
SDL_HintWatch * callbacks
Definition: SDL_hints.c:41
SDL_strcasecmp
#define SDL_strcasecmp
Definition: SDL_dynapi_overrides.h:419
SDL_Hint::next
struct SDL_Hint * next
Definition: SDL_hints.c:42
SDL_HintWatch::userdata
void * userdata
Definition: SDL_hints.c:33
SDL_Hint::value
char * value
Definition: SDL_hints.c:39
SDL_internal.h
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
name
GLuint const GLchar * name
Definition: SDL_opengl_glext.h:663
SDL_SetHint
SDL_bool SDL_SetHint(const char *name, const char *value)
Set a hint with normal priority.
Definition: SDL_hints.c:99
SDL_HintWatch::next
struct SDL_HintWatch * next
Definition: SDL_hints.c:34
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
SDL_GetHintBoolean
SDL_bool SDL_GetHintBoolean(const char *name, SDL_bool default_value)
Get a hint.
Definition: SDL_hints.c:135
SDL_HintWatch
Definition: SDL_hints.c:31
SDL_Hint::name
char * name
Definition: SDL_hints.c:38
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_HintWatch::callback
SDL_HintCallback callback
Definition: SDL_hints.c:32
SDL_HintCallback
void(* SDL_HintCallback)(void *userdata, const char *name, const char *oldValue, const char *newValue)
type definition of the hint callback function.
Definition: SDL_hints.h:1324
SDL_getenv
#define SDL_getenv
Definition: SDL_dynapi_overrides.h:378
value
GLsizei const GLfloat * value
Definition: SDL_opengl_glext.h:701
SDL_ClearHints
void SDL_ClearHints(void)
Clear all hints.
Definition: SDL_hints.c:223
SDL_hints.h
SDL_hints_c.h
SDL_strdup
#define SDL_strdup
Definition: SDL_dynapi_overrides.h:397
SDL_GetStringBoolean
SDL_bool SDL_GetStringBoolean(const char *value, SDL_bool default_value)
Definition: SDL_hints.c:123
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:162
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:374
SDL_strcmp
#define SDL_strcmp
Definition: SDL_dynapi_overrides.h:417
SDL_HINT_NORMAL
@ SDL_HINT_NORMAL
Definition: SDL_hints.h:1281
SDL_HINT_OVERRIDE
@ SDL_HINT_OVERRIDE
Definition: SDL_hints.h:1282
SDL_Hint::priority
SDL_HintPriority priority
Definition: SDL_hints.c:40