SDL  2.0
SDL_hints.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 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 
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 {
32  void *userdata;
35 
36 typedef struct SDL_Hint {
37  char *name;
38  char *value;
41  struct SDL_Hint *next;
42 } SDL_Hint;
43 
45 
47 SDL_SetHintWithPriority(const char *name, const char *value,
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
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  if (!entry) {
141  SDL_OutOfMemory();
142  return;
143  }
144  entry->callback = callback;
145  entry->userdata = userdata;
146 
147  for (hint = SDL_hints; hint; hint = hint->next) {
148  if (SDL_strcmp(name, hint->name) == 0) {
149  break;
150  }
151  }
152  if (!hint) {
153  /* Need to add a hint entry for this watcher */
154  hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
155  if (!hint) {
156  SDL_OutOfMemory();
157  SDL_free(entry);
158  return;
159  }
160  hint->name = SDL_strdup(name);
161  hint->value = NULL;
162  hint->priority = SDL_HINT_DEFAULT;
163  hint->callbacks = NULL;
164  hint->next = SDL_hints;
165  SDL_hints = hint;
166  }
167 
168  /* Add it to the callbacks for this hint */
169  entry->next = hint->callbacks;
170  hint->callbacks = entry;
171 
172  /* Now call it with the current value */
173  value = SDL_GetHint(name);
174  callback(userdata, name, value, value);
175 }
176 
177 void
179 {
180  SDL_Hint *hint;
181  SDL_HintWatch *entry, *prev;
182 
183  for (hint = SDL_hints; hint; hint = hint->next) {
184  if (SDL_strcmp(name, hint->name) == 0) {
185  prev = NULL;
186  for (entry = hint->callbacks; entry; entry = entry->next) {
187  if (callback == entry->callback && userdata == entry->userdata) {
188  if (prev) {
189  prev->next = entry->next;
190  } else {
191  hint->callbacks = entry->next;
192  }
193  SDL_free(entry);
194  break;
195  }
196  prev = entry;
197  }
198  return;
199  }
200  }
201 }
202 
203 void SDL_ClearHints(void)
204 {
205  SDL_Hint *hint;
206  SDL_HintWatch *entry;
207 
208  while (SDL_hints) {
209  hint = SDL_hints;
210  SDL_hints = hint->next;
211 
212  SDL_free(hint->name);
213  SDL_free(hint->value);
214  for (entry = hint->callbacks; entry; ) {
215  SDL_HintWatch *freeable = entry;
216  entry = entry->next;
217  SDL_free(freeable);
218  }
219  SDL_free(hint);
220  }
221 }
222 
223 /* vi: set ts=4 sw=4 expandtab: */
void * userdata
Definition: SDL_hints.c:32
const char * SDL_GetHint(const char *name)
Get a hint.
Definition: SDL_hints.c:104
void SDL_DelHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
Remove a function watching a particular hint.
Definition: SDL_hints.c:178
struct SDL_Hint * next
Definition: SDL_hints.c:41
void SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
Definition: SDL_hints.c:122
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
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
An enumeration of hint priorities.
Definition: SDL_hints.h:636
GLuint const GLchar * name
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
SDL_bool
Definition: SDL_stdinc.h:126
GLsizei const GLfloat * value
void SDL_free(void *mem)
SDL_bool SDL_SetHint(const char *name, const char *value)
Set a hint with normal priority.
Definition: SDL_hints.c:98
SDL_HintWatch * callbacks
Definition: SDL_hints.c:40
#define SDL_getenv
#define NULL
Definition: begin_code.h:143
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_HintPriority priority
Definition: SDL_hints.c:39
#define SDL_strdup
void SDL_ClearHints(void)
Clear all hints.
Definition: SDL_hints.c:203
#define SDL_malloc
#define SDL_strcmp
char * value
Definition: SDL_hints.c:38
SDL_HintCallback callback
Definition: SDL_hints.c:31
struct SDL_HintWatch * next
Definition: SDL_hints.c:33
char * name
Definition: SDL_hints.c:37
static SDL_Hint * SDL_hints
Definition: SDL_hints.c:44