src/SDL_hints.c
changeset 7432 58908b180ebd
parent 7191 75360622e65f
child 7716 be4cda94bce2
equal deleted inserted replaced
7431:0fc94f315dac 7432:58908b180ebd
    19   3. This notice may not be removed or altered from any source distribution.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    20 */
    21 #include "SDL_config.h"
    21 #include "SDL_config.h"
    22 
    22 
    23 #include "SDL_hints.h"
    23 #include "SDL_hints.h"
    24 #include "SDL_hints_c.h"
    24 #include "SDL_error.h"
    25 
    25 
    26 
    26 
    27 /* Assuming there aren't many hints set and they aren't being queried in
    27 /* Assuming there aren't many hints set and they aren't being queried in
    28    critical performance paths, we'll just use a linked list here.
    28    critical performance paths, we'll just use linked lists here.
    29  */
    29  */
       
    30 typedef struct SDL_HintWatch {
       
    31     SDL_HintCallback callback;
       
    32     void *userdata;
       
    33     struct SDL_HintWatch *next;
       
    34 } SDL_HintWatch;
       
    35 
    30 typedef struct SDL_Hint {
    36 typedef struct SDL_Hint {
    31     char *name;
    37     char *name;
    32     char *value;
    38     char *value;
    33     SDL_HintPriority priority;
    39     SDL_HintPriority priority;
    34     SDL_HintChangedCb callback;
    40     SDL_HintWatch *callbacks;
    35     struct SDL_Hint *next;
    41     struct SDL_Hint *next;
    36 } SDL_Hint;
    42 } SDL_Hint;
    37 
    43 
    38 static SDL_Hint *SDL_hints;
    44 static SDL_Hint *SDL_hints;
    39 
       
    40 SDL_bool
       
    41 SDL_RegisterHintChangedCb(const char *name, SDL_HintChangedCb hintCb)
       
    42 {
       
    43     SDL_Hint *hint;
       
    44 
       
    45     for (hint = SDL_hints; hint; hint = hint->next) {
       
    46         if (SDL_strcmp(name, hint->name) == 0) {
       
    47             hint->callback = hintCb;
       
    48             return SDL_TRUE;
       
    49         }
       
    50     }
       
    51 
       
    52     return SDL_FALSE;
       
    53 }
       
    54 
    45 
    55 SDL_bool
    46 SDL_bool
    56 SDL_SetHintWithPriority(const char *name, const char *value,
    47 SDL_SetHintWithPriority(const char *name, const char *value,
    57                         SDL_HintPriority priority)
    48                         SDL_HintPriority priority)
    58 {
    49 {
    59     const char *env;
    50     const char *env;
    60     SDL_Hint *hint;
    51     SDL_Hint *hint;
       
    52     SDL_HintWatch *entry;
    61 
    53 
    62     if (!name || !value) {
    54     if (!name || !value) {
    63         return SDL_FALSE;
    55         return SDL_FALSE;
    64     }
    56     }
    65 
    57 
    71     for (hint = SDL_hints; hint; hint = hint->next) {
    63     for (hint = SDL_hints; hint; hint = hint->next) {
    72         if (SDL_strcmp(name, hint->name) == 0) {
    64         if (SDL_strcmp(name, hint->name) == 0) {
    73             if (priority < hint->priority) {
    65             if (priority < hint->priority) {
    74                 return SDL_FALSE;
    66                 return SDL_FALSE;
    75             }
    67             }
    76             if (SDL_strcmp(hint->value, value) != 0) {
    68             if (!hint->value || !value || SDL_strcmp(hint->value, value) != 0) {
    77                 if (hint->callback != NULL) {
    69                 for (entry = hint->callbacks; entry; ) {
    78                     (*hint->callback)(name, hint->value, value);
    70                     /* Save the next entry in case this one is deleted */
    79                 }
    71                     SDL_HintWatch *next = entry->next;
    80                 SDL_free(hint->value);
    72                     entry->callback(entry->userdata, name, hint->value, value);
    81                 hint->value = SDL_strdup(value);
    73                     entry = next;
       
    74                 }
       
    75                 if (hint->value) {
       
    76                     SDL_free(hint->value);
       
    77                 }
       
    78                 if (value) {
       
    79                     hint->value = SDL_strdup(value);
       
    80                 } else {
       
    81                     hint->value = NULL;
       
    82                 }
    82             }
    83             }
    83             hint->priority = priority;
    84             hint->priority = priority;
    84             return SDL_TRUE;
    85             return SDL_TRUE;
    85         }
    86         }
    86     }
    87     }
    89     hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
    90     hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
    90     if (!hint) {
    91     if (!hint) {
    91         return SDL_FALSE;
    92         return SDL_FALSE;
    92     }
    93     }
    93     hint->name = SDL_strdup(name);
    94     hint->name = SDL_strdup(name);
    94     hint->value = SDL_strdup(value);
    95     hint->value = value ? SDL_strdup(value) : NULL;
    95     hint->priority = priority;
    96     hint->priority = priority;
    96     hint->callback = NULL;
    97     hint->callbacks = NULL;
    97     hint->next = SDL_hints;
    98     hint->next = SDL_hints;
    98     SDL_hints = hint;
    99     SDL_hints = hint;
    99     return SDL_TRUE;
   100     return SDL_TRUE;
   100 }
   101 }
   101 
   102 
   121         }
   122         }
   122     }
   123     }
   123     return env;
   124     return env;
   124 }
   125 }
   125 
   126 
       
   127 void
       
   128 SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
       
   129 {
       
   130     SDL_Hint *hint;
       
   131     SDL_HintWatch *entry;
       
   132     const char *value;
       
   133 
       
   134     if (!name || !*name) {
       
   135         SDL_InvalidParamError("name");
       
   136         return;
       
   137     }
       
   138     if (!callback) {
       
   139         SDL_InvalidParamError("callback");
       
   140         return;
       
   141     }
       
   142 
       
   143     SDL_DelHintCallback(name, callback, userdata);
       
   144 
       
   145     entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry));
       
   146     entry->callback = callback;
       
   147     entry->userdata = userdata;
       
   148 
       
   149     for (hint = SDL_hints; hint; hint = hint->next) {
       
   150         if (SDL_strcmp(name, hint->name) == 0) {
       
   151             break;
       
   152         }
       
   153     }
       
   154     if (!hint) {
       
   155         /* Need to add a hint entry for this watcher */
       
   156         hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
       
   157         if (!hint) {
       
   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
       
   178 SDL_DelHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
       
   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 
   126 void SDL_ClearHints(void)
   203 void SDL_ClearHints(void)
   127 {
   204 {
   128     SDL_Hint *hint;
   205     SDL_Hint *hint;
       
   206     SDL_HintWatch *entry;
   129 
   207 
   130     while (SDL_hints) {
   208     while (SDL_hints) {
   131         hint = SDL_hints;
   209         hint = SDL_hints;
   132         SDL_hints = hint->next;
   210         SDL_hints = hint->next;
   133 
   211 
   134         SDL_free(hint->name);
   212         SDL_free(hint->name);
   135         SDL_free(hint->value);
   213         if (hint->value) {
       
   214             SDL_free(hint->value);
       
   215         }
       
   216         for (entry = hint->callbacks; entry; ) {
       
   217             SDL_HintWatch *freeable = entry;
       
   218             entry = entry->next;
       
   219             SDL_free(freeable);
       
   220         }
   136         SDL_free(hint);
   221         SDL_free(hint);
   137     }
   222     }
   138 }
   223 }
   139 
   224 
   140 /* vi: set ts=4 sw=4 expandtab: */
   225 /* vi: set ts=4 sw=4 expandtab: */