zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_hints.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2013 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_config.h"
22 
23 #include "SDL_hints.h"
24 #include "SDL_error.h"
25 
26 
27 /* Assuming there aren't many hints set and they aren't being queried in
28  critical performance paths, we'll just use linked lists here.
29  */
30 typedef struct SDL_HintWatch {
31  SDL_HintCallback callback;
32  void *userdata;
33  struct SDL_HintWatch *next;
35 
36 typedef struct SDL_Hint {
37  char *name;
38  char *value;
39  SDL_HintPriority priority;
40  SDL_HintWatch *callbacks;
41  struct SDL_Hint *next;
42 } SDL_Hint;
43 
45 
47 SDL_SetHintWithPriority(const char *name, const char *value,
48  SDL_HintPriority priority)
49 {
50  const char *env;
51  SDL_Hint *hint;
52  SDL_HintWatch *entry;
53 
54  if (!name || !value) {
55  return SDL_FALSE;
56  }
57 
58  env = SDL_getenv(name);
59  if (env && priority < SDL_HINT_OVERRIDE) {
60  return SDL_FALSE;
61  }
62 
63  for (hint = SDL_hints; hint; hint = hint->next) {
64  if (SDL_strcmp(name, hint->name) == 0) {
65  if (priority < hint->priority) {
66  return SDL_FALSE;
67  }
68  if (!hint->value || !value || SDL_strcmp(hint->value, value) != 0) {
69  for (entry = hint->callbacks; entry; ) {
70  /* Save the next entry in case this one is deleted */
71  SDL_HintWatch *next = entry->next;
72  entry->callback(entry->userdata, name, hint->value, value);
73  entry = next;
74  }
75  SDL_free(hint->value);
76  hint->value = value ? SDL_strdup(value) : NULL;
77  }
78  hint->priority = priority;
79  return SDL_TRUE;
80  }
81  }
82 
83  /* Couldn't find the hint, add a new one */
84  hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
85  if (!hint) {
86  return SDL_FALSE;
87  }
88  hint->name = SDL_strdup(name);
89  hint->value = value ? SDL_strdup(value) : NULL;
90  hint->priority = priority;
91  hint->callbacks = NULL;
92  hint->next = SDL_hints;
93  SDL_hints = hint;
94  return SDL_TRUE;
95 }
96 
98 SDL_SetHint(const char *name, const char *value)
99 {
100  return SDL_SetHintWithPriority(name, value, SDL_HINT_NORMAL);
101 }
102 
103 const char *
104 SDL_GetHint(const char *name)
105 {
106  const char *env;
107  SDL_Hint *hint;
108 
109  env = SDL_getenv(name);
110  for (hint = SDL_hints; hint; hint = hint->next) {
111  if (SDL_strcmp(name, hint->name) == 0) {
112  if (!env || hint->priority == SDL_HINT_OVERRIDE) {
113  return hint->value;
114  }
115  break;
116  }
117  }
118  return env;
119 }
120 
121 void
122 SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
123 {
124  SDL_Hint *hint;
125  SDL_HintWatch *entry;
126  const char *value;
127 
128  if (!name || !*name) {
129  SDL_InvalidParamError("name");
130  return;
131  }
132  if (!callback) {
133  SDL_InvalidParamError("callback");
134  return;
135  }
136 
137  SDL_DelHintCallback(name, callback, userdata);
138 
139  entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry));
140  entry->callback = callback;
141  entry->userdata = userdata;
142 
143  for (hint = SDL_hints; hint; hint = hint->next) {
144  if (SDL_strcmp(name, hint->name) == 0) {
145  break;
146  }
147  }
148  if (!hint) {
149  /* Need to add a hint entry for this watcher */
150  hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
151  if (!hint) {
152  return;
153  }
154  hint->name = SDL_strdup(name);
155  hint->value = NULL;
156  hint->priority = SDL_HINT_DEFAULT;
157  hint->callbacks = NULL;
158  hint->next = SDL_hints;
159  SDL_hints = hint;
160  }
161 
162  /* Add it to the callbacks for this hint */
163  entry->next = hint->callbacks;
164  hint->callbacks = entry;
165 
166  /* Now call it with the current value */
167  value = SDL_GetHint(name);
168  callback(userdata, name, value, value);
169 }
170 
171 void
172 SDL_DelHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
173 {
174  SDL_Hint *hint;
175  SDL_HintWatch *entry, *prev;
176 
177  for (hint = SDL_hints; hint; hint = hint->next) {
178  if (SDL_strcmp(name, hint->name) == 0) {
179  prev = NULL;
180  for (entry = hint->callbacks; entry; entry = entry->next) {
181  if (callback == entry->callback && userdata == entry->userdata) {
182  if (prev) {
183  prev->next = entry->next;
184  } else {
185  hint->callbacks = entry->next;
186  }
187  SDL_free(entry);
188  break;
189  }
190  prev = entry;
191  }
192  return;
193  }
194  }
195 }
196 
197 void SDL_ClearHints(void)
198 {
199  SDL_Hint *hint;
200  SDL_HintWatch *entry;
201 
202  while (SDL_hints) {
203  hint = SDL_hints;
204  SDL_hints = hint->next;
205 
206  SDL_free(hint->name);
207  SDL_free(hint->value);
208  for (entry = hint->callbacks; entry; ) {
209  SDL_HintWatch *freeable = entry;
210  entry = entry->next;
211  SDL_free(freeable);
212  }
213  SDL_free(hint);
214  }
215 }
216 
217 /* vi: set ts=4 sw=4 expandtab: */
#define NULL
Definition: ftobjs.h:61
SDL_bool
Definition: SDL_stdinc.h:116
DECLSPEC SDL_bool SDLCALL SDL_SetHint(const char *name, const char *value)
Set a hint with normal priority.
Definition: SDL_hints.c:98
DECLSPEC void SDLCALL SDL_free(void *mem)
SDL_HintPriority
An enumeration of hint priorities.
Definition: SDL_hints.h:280
EGLImageKHR EGLint * name
Definition: eglext.h:284
DECLSPEC void SDLCALL SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
Definition: SDL_hints.c:122
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
struct SDL_HintWatch SDL_HintWatch
DECLSPEC char *SDLCALL SDL_strdup(const char *str)
Definition: SDL_string.c:511
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
DECLSPEC int SDLCALL SDL_strcmp(const char *str1, const char *str2)
Definition: SDL_string.c:910
DECLSPEC const char *SDLCALL SDL_GetHint(const char *name)
Get a hint.
Definition: SDL_hints.c:104
jmp_buf env
Definition: jumphack.c:12
struct SDL_Hint SDL_Hint
EGLSurface EGLint void ** value
Definition: eglext.h:301
DECLSPEC SDL_bool SDLCALL SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPriority priority)
Set a hint with a specific priority.
Definition: SDL_hints.c:47
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:323
DECLSPEC char *SDLCALL SDL_getenv(const char *name)
Definition: SDL_getenv.c:179
DECLSPEC void SDLCALL SDL_DelHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
Remove a function watching a particular hint.
Definition: SDL_hints.c:172
DECLSPEC void SDLCALL SDL_ClearHints(void)
Clear all hints.
Definition: SDL_hints.c:197
static SDL_Hint * SDL_hints
Definition: SDL_hints.c:44