SDL

Форк
0
/
SDL_hints.c 
343 строки · 9.4 Кб
1
/*
2
  Simple DirectMedia Layer
3
  Copyright (C) 1997-2024 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_c.h"
24

25
typedef struct SDL_HintWatch
26
{
27
    SDL_HintCallback callback;
28
    void *userdata;
29
    struct SDL_HintWatch *next;
30
} SDL_HintWatch;
31

32
typedef struct SDL_Hint
33
{
34
    char *value;
35
    SDL_HintPriority priority;
36
    SDL_HintWatch *callbacks;
37
} SDL_Hint;
38

39
static SDL_PropertiesID SDL_hint_props = 0;
40

41
static SDL_PropertiesID GetHintProperties(bool create)
42
{
43
    if (!SDL_hint_props && create) {
44
        SDL_hint_props = SDL_CreateProperties();
45
    }
46
    return SDL_hint_props;
47
}
48

49
void SDL_InitHints(void)
50
{
51
    // Just make sure the hint properties are created on the main thread
52
    (void)GetHintProperties(true);
53
}
54

55
static void SDLCALL CleanupHintProperty(void *userdata, void *value)
56
{
57
    SDL_Hint *hint = (SDL_Hint *) value;
58
    SDL_free(hint->value);
59

60
    SDL_HintWatch *entry = hint->callbacks;
61
    while (entry) {
62
        SDL_HintWatch *freeable = entry;
63
        entry = entry->next;
64
        SDL_free(freeable);
65
    }
66
    SDL_free(hint);
67
}
68

69
SDL_bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPriority priority)
70
{
71
    if (!name || !*name) {
72
        return SDL_InvalidParamError("name");
73
    }
74

75
    const char *env = SDL_getenv(name);
76
    if (env && (priority < SDL_HINT_OVERRIDE)) {
77
        return SDL_SetError("An environment variable is taking priority");
78
    }
79

80
    const SDL_PropertiesID hints = GetHintProperties(true);
81
    if (!hints) {
82
        return false;
83
    }
84

85
    bool result = false;
86

87
    SDL_LockProperties(hints);
88

89
    SDL_Hint *hint = (SDL_Hint *)SDL_GetPointerProperty(hints, name, NULL);
90
    if (hint) {
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;
94

95
                hint->value = value ? SDL_strdup(value) : NULL;
96
                SDL_HintWatch *entry = hint->callbacks;
97
                while (entry) {
98
                    // Save the next entry in case this one is deleted
99
                    SDL_HintWatch *next = entry->next;
100
                    entry->callback(entry->userdata, name, old_value, value);
101
                    entry = next;
102
                }
103
                SDL_free(old_value);
104
            }
105
            hint->priority = priority;
106
            result = true;
107
        }
108
    } else {  // Couldn't find the hint? Add a new one.
109
        hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
110
        if (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);
115
        }
116
    }
117

118
    SDL_UnlockProperties(hints);
119

120
    return result;
121
}
122

123
SDL_bool SDL_ResetHint(const char *name)
124
{
125
    if (!name || !*name) {
126
        return SDL_InvalidParamError("name");
127
    }
128

129
    const char *env = SDL_getenv(name);
130

131
    const SDL_PropertiesID hints = GetHintProperties(false);
132
    if (!hints) {
133
        return false;
134
    }
135

136
    bool result = false;
137

138
    SDL_LockProperties(hints);
139

140
    SDL_Hint *hint = (SDL_Hint *)SDL_GetPointerProperty(hints, name, NULL);
141
    if (hint) {
142
        if ((!env && hint->value) || (env && !hint->value) || (env && SDL_strcmp(env, hint->value) != 0)) {
143
            for (SDL_HintWatch *entry = hint->callbacks; entry;) {
144
                // Save the next entry in case this one is deleted
145
                SDL_HintWatch *next = entry->next;
146
                entry->callback(entry->userdata, name, hint->value, env);
147
                entry = next;
148
            }
149
        }
150
        SDL_free(hint->value);
151
        hint->value = NULL;
152
        hint->priority = SDL_HINT_DEFAULT;
153
        result = true;
154
    }
155

156
    SDL_UnlockProperties(hints);
157

158
    return result;
159
}
160

161
static void SDLCALL ResetHintsCallback(void *userdata, SDL_PropertiesID hints, const char *name)
162
{
163
    SDL_Hint *hint = (SDL_Hint *)SDL_GetPointerProperty(hints, name, NULL);
164
    if (!hint) {
165
        return;  // uh...okay.
166
    }
167

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;
171
        while (entry) {
172
            // Save the next entry in case this one is deleted
173
            SDL_HintWatch *next = entry->next;
174
            entry->callback(entry->userdata, name, hint->value, env);
175
            entry = next;
176
        }
177
    }
178
    SDL_free(hint->value);
179
    hint->value = NULL;
180
    hint->priority = SDL_HINT_DEFAULT;
181
}
182

183
void SDL_ResetHints(void)
184
{
185
    SDL_EnumerateProperties(GetHintProperties(false), ResetHintsCallback, NULL);
186
}
187

188
SDL_bool SDL_SetHint(const char *name, const char *value)
189
{
190
    return SDL_SetHintWithPriority(name, value, SDL_HINT_NORMAL);
191
}
192

193
const char *SDL_GetHint(const char *name)
194
{
195
    if (!name) {
196
        return NULL;
197
    }
198

199
    const char *result = SDL_getenv(name);
200

201
    const SDL_PropertiesID hints = GetHintProperties(false);
202
    if (hints) {
203
        SDL_LockProperties(hints);
204

205
        SDL_Hint *hint = (SDL_Hint *)SDL_GetPointerProperty(hints, name, NULL);
206
        if (hint) {
207
            if (!result || hint->priority == SDL_HINT_OVERRIDE) {
208
                result = SDL_GetPersistentString(hint->value);
209
            }
210
        }
211

212
        SDL_UnlockProperties(hints);
213
    }
214

215
    return result;
216
}
217

218
int SDL_GetStringInteger(const char *value, int default_value)
219
{
220
    if (!value || !*value) {
221
        return default_value;
222
    }
223
    if (*value == '0' || SDL_strcasecmp(value, "false") == 0) {
224
        return 0;
225
    }
226
    if (*value == '1' || SDL_strcasecmp(value, "true") == 0) {
227
        return 1;
228
    }
229
    if (*value == '-' || SDL_isdigit(*value)) {
230
        return SDL_atoi(value);
231
    }
232
    return default_value;
233
}
234

235
bool SDL_GetStringBoolean(const char *value, bool default_value)
236
{
237
    if (!value || !*value) {
238
        return default_value;
239
    }
240
    if (*value == '0' || SDL_strcasecmp(value, "false") == 0) {
241
        return false;
242
    }
243
    return true;
244
}
245

246
SDL_bool SDL_GetHintBoolean(const char *name, SDL_bool default_value)
247
{
248
    const char *hint = SDL_GetHint(name);
249
    return SDL_GetStringBoolean(hint, default_value);
250
}
251

252
SDL_bool SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
253
{
254
    if (!name || !*name) {
255
        return SDL_InvalidParamError("name");
256
    } else if (!callback) {
257
        return SDL_InvalidParamError("callback");
258
    }
259

260
    const SDL_PropertiesID hints = GetHintProperties(true);
261
    if (!hints) {
262
        return false;
263
    }
264

265
    SDL_HintWatch *entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry));
266
    if (!entry) {
267
        return false;
268
    }
269
    entry->callback = callback;
270
    entry->userdata = userdata;
271

272
    bool result = false;
273

274
    SDL_LockProperties(hints);
275

276
    SDL_RemoveHintCallback(name, callback, userdata);
277

278
    SDL_Hint *hint = (SDL_Hint *)SDL_GetPointerProperty(hints, name, NULL);
279
    if (hint) {
280
        result = true;
281
    } else {  // Need to add a hint entry for this watcher
282
        hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
283
        if (!hint) {
284
            SDL_free(entry);
285
            SDL_UnlockProperties(hints);
286
            return false;
287
        } else {
288
            hint->value = NULL;
289
            hint->priority = SDL_HINT_DEFAULT;
290
            hint->callbacks = NULL;
291
            result = SDL_SetPointerPropertyWithCleanup(hints, name, hint, CleanupHintProperty, NULL);
292
        }
293
    }
294

295
    // Add it to the callbacks for this hint
296
    entry->next = hint->callbacks;
297
    hint->callbacks = entry;
298

299
    // Now call it with the current value
300
    const char *value = SDL_GetHint(name);
301
    callback(userdata, name, value, value);
302

303
    SDL_UnlockProperties(hints);
304

305
    return result;
306
}
307

308
void SDL_RemoveHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
309
{
310
    if (!name || !*name) {
311
        return;
312
    }
313

314
    const SDL_PropertiesID hints = GetHintProperties(false);
315
    if (!hints) {
316
        return;
317
    }
318

319
    SDL_LockProperties(hints);
320
    SDL_Hint *hint = (SDL_Hint *)SDL_GetPointerProperty(hints, name, NULL);
321
    if (hint) {
322
        SDL_HintWatch *prev = NULL;
323
        for (SDL_HintWatch *entry = hint->callbacks; entry; entry = entry->next) {
324
            if ((callback == entry->callback) && (userdata == entry->userdata)) {
325
                if (prev) {
326
                    prev->next = entry->next;
327
                } else {
328
                    hint->callbacks = entry->next;
329
                }
330
                SDL_free(entry);
331
                break;
332
            }
333
            prev = entry;
334
        }
335
    }
336
    SDL_UnlockProperties(hints);
337
}
338

339
void SDL_QuitHints(void)
340
{
341
    SDL_DestroyProperties(SDL_hint_props);
342
    SDL_hint_props = 0;
343
}
344

345

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.