src/SDL_hints.c
author Sam Lantinga
Mon, 09 Jan 2017 11:58:01 -0800
changeset 10802 6afc9b833867
parent 10737 3406a0f8b041
child 11513 5eafaa1085a1
permissions -rw-r--r--
We only need the first few keymaps corresponding to the following constants:
K_NORMTAB, K_SHIFTTAB, K_ALTTAB, K_ALTSHIFTTAB

In the normal case we'll load all the keymaps from the kernel, but this reduces the size of the SDL library for the fallback case when we can't get to the tty.
slouken@5189
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 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@10499
   121
SDL_bool
slouken@10499
   122
SDL_GetHintBoolean(const char *name, SDL_bool default_value)
slouken@10499
   123
{
slouken@10499
   124
    const char *hint = SDL_GetHint(name);
slouken@10499
   125
    if (!hint) {
slouken@10499
   126
        return default_value;
slouken@10499
   127
    }
slouken@10499
   128
    if (*hint == '0' || SDL_strcasecmp(hint, "false") == 0) {
slouken@10499
   129
        return SDL_FALSE;
slouken@10499
   130
    }
slouken@10499
   131
    return SDL_TRUE;
slouken@10499
   132
}
slouken@10499
   133
slouken@7432
   134
void
slouken@7432
   135
SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
slouken@7432
   136
{
slouken@7432
   137
    SDL_Hint *hint;
slouken@7432
   138
    SDL_HintWatch *entry;
slouken@7432
   139
    const char *value;
slouken@7432
   140
slouken@7432
   141
    if (!name || !*name) {
slouken@7432
   142
        SDL_InvalidParamError("name");
slouken@7432
   143
        return;
slouken@7432
   144
    }
slouken@7432
   145
    if (!callback) {
slouken@7432
   146
        SDL_InvalidParamError("callback");
slouken@7432
   147
        return;
slouken@7432
   148
    }
slouken@7432
   149
slouken@7432
   150
    SDL_DelHintCallback(name, callback, userdata);
slouken@7432
   151
slouken@7432
   152
    entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry));
philipp@9202
   153
    if (!entry) {
philipp@9202
   154
        SDL_OutOfMemory();
philipp@9202
   155
        return;
philipp@9202
   156
    }
slouken@7432
   157
    entry->callback = callback;
slouken@7432
   158
    entry->userdata = userdata;
slouken@7432
   159
slouken@7432
   160
    for (hint = SDL_hints; hint; hint = hint->next) {
slouken@7432
   161
        if (SDL_strcmp(name, hint->name) == 0) {
slouken@7432
   162
            break;
slouken@7432
   163
        }
slouken@7432
   164
    }
slouken@7432
   165
    if (!hint) {
slouken@7432
   166
        /* Need to add a hint entry for this watcher */
slouken@7432
   167
        hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
slouken@7432
   168
        if (!hint) {
philipp@9202
   169
            SDL_OutOfMemory();
philipp@9204
   170
            SDL_free(entry);
slouken@7432
   171
            return;
slouken@7432
   172
        }
slouken@7432
   173
        hint->name = SDL_strdup(name);
slouken@7432
   174
        hint->value = NULL;
slouken@7432
   175
        hint->priority = SDL_HINT_DEFAULT;
slouken@7432
   176
        hint->callbacks = NULL;
slouken@7432
   177
        hint->next = SDL_hints;
slouken@7432
   178
        SDL_hints = hint;
slouken@7432
   179
    }
slouken@7432
   180
slouken@7432
   181
    /* Add it to the callbacks for this hint */
slouken@7432
   182
    entry->next = hint->callbacks;
slouken@7432
   183
    hint->callbacks = entry;
slouken@7432
   184
slouken@7432
   185
    /* Now call it with the current value */
slouken@7432
   186
    value = SDL_GetHint(name);
slouken@7432
   187
    callback(userdata, name, value, value);
slouken@7432
   188
}
slouken@7432
   189
slouken@7432
   190
void
slouken@7432
   191
SDL_DelHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
slouken@7432
   192
{
slouken@7432
   193
    SDL_Hint *hint;
slouken@7432
   194
    SDL_HintWatch *entry, *prev;
slouken@7432
   195
slouken@7432
   196
    for (hint = SDL_hints; hint; hint = hint->next) {
slouken@7432
   197
        if (SDL_strcmp(name, hint->name) == 0) {
slouken@7432
   198
            prev = NULL;
slouken@7432
   199
            for (entry = hint->callbacks; entry; entry = entry->next) {
slouken@7432
   200
                if (callback == entry->callback && userdata == entry->userdata) {
slouken@7432
   201
                    if (prev) {
slouken@7432
   202
                        prev->next = entry->next;
slouken@7432
   203
                    } else {
slouken@7432
   204
                        hint->callbacks = entry->next;
slouken@7432
   205
                    }
slouken@7432
   206
                    SDL_free(entry);
slouken@7432
   207
                    break;
slouken@7432
   208
                }
slouken@7432
   209
                prev = entry;
slouken@7432
   210
            }
slouken@7432
   211
            return;
slouken@7432
   212
        }
slouken@7432
   213
    }
slouken@7432
   214
}
slouken@7432
   215
slouken@5273
   216
void SDL_ClearHints(void)
slouken@5189
   217
{
slouken@5189
   218
    SDL_Hint *hint;
slouken@7432
   219
    SDL_HintWatch *entry;
slouken@5189
   220
slouken@5189
   221
    while (SDL_hints) {
slouken@5189
   222
        hint = SDL_hints;
slouken@5189
   223
        SDL_hints = hint->next;
slouken@5189
   224
slouken@5189
   225
        SDL_free(hint->name);
slouken@7719
   226
        SDL_free(hint->value);
slouken@7432
   227
        for (entry = hint->callbacks; entry; ) {
slouken@7432
   228
            SDL_HintWatch *freeable = entry;
slouken@7432
   229
            entry = entry->next;
slouken@7432
   230
            SDL_free(freeable);
slouken@7432
   231
        }
slouken@5189
   232
        SDL_free(hint);
slouken@5189
   233
    }
slouken@5189
   234
}
slouken@5189
   235
slouken@5189
   236
/* vi: set ts=4 sw=4 expandtab: */