Extended SDL_SetWindowData() to allow arbitrary named values.
authorSam Lantinga <slouken@libsdl.org>
Thu, 03 Feb 2011 11:16:57 -0800
changeset 5165 2b1989f59674
parent 5164 97423d858a1a
child 5166 4d39eeaad00b
Extended SDL_SetWindowData() to allow arbitrary named values.
include/SDL_video.h
src/video/SDL_sysvideo.h
src/video/SDL_video.c
--- a/include/SDL_video.h	Thu Feb 03 10:03:55 2011 -0800
+++ b/include/SDL_video.h	Thu Feb 03 11:16:57 2011 -0800
@@ -483,24 +483,39 @@
                                                SDL_Surface * icon);
 
 /**
- *  \brief Associate an arbitrary pointer with a window.
+ *  \brief Associate an arbitrary named pointer with a window.
  *  
+ *  \param window   The window to associate with the pointer.
+ *  \param name     The name of the pointer.
+ *  \param userdata The associated pointer.
+ *
+ *  \return The previous value associated with 'name'
+ *
+ *  \note The name is case-sensitive.
+ *
  *  \sa SDL_GetWindowData()
  */
-extern DECLSPEC void SDLCALL SDL_SetWindowData(SDL_Window * window,
-                                               void *userdata);
+extern DECLSPEC void* SDLCALL SDL_SetWindowData(SDL_Window * window,
+                                                const char *name,
+                                                void *userdata);
 
 /**
  *  \brief Retrieve the data pointer associated with a window.
  *  
+ *  \param window   The window to query.
+ *  \param name     The name of the pointer.
+ *
+ *  \return The value associated with 'name'
+ *  
  *  \sa SDL_SetWindowData()
  */
-extern DECLSPEC void *SDLCALL SDL_GetWindowData(SDL_Window * window);
+extern DECLSPEC void *SDLCALL SDL_GetWindowData(SDL_Window * window,
+                                                const char *name);
 
 /**
  *  \brief Set the position of a window.
  *  
- *  \param window The window to reposition.
+ *  \param window   The window to reposition.
  *  \param x        The x coordinate of the window, ::SDL_WINDOWPOS_CENTERED, or
                     ::SDL_WINDOWPOS_UNDEFINED.
  *  \param y        The y coordinate of the window, ::SDL_WINDOWPOS_CENTERED, or
--- a/src/video/SDL_sysvideo.h	Thu Feb 03 10:03:55 2011 -0800
+++ b/src/video/SDL_sysvideo.h	Thu Feb 03 11:16:57 2011 -0800
@@ -59,6 +59,13 @@
     int (*ResizeWindowShape)(SDL_Window *window);
 };
 
+typedef struct SDL_WindowUserData
+{
+    char *name;
+    void *data;
+    struct SDL_WindowUserData *next;
+} SDL_WindowUserData;
+
 /* Define the SDL window structure, corresponding to toplevel windows */
 struct SDL_Window
 {
@@ -75,7 +82,8 @@
     
     SDL_WindowShaper *shaper;
 
-    void *userdata;
+    SDL_WindowUserData *data;
+
     void *driverdata;
 
     SDL_Window *prev;
--- a/src/video/SDL_video.c	Thu Feb 03 10:03:55 2011 -0800
+++ b/src/video/SDL_video.c	Thu Feb 03 11:16:57 2011 -0800
@@ -982,20 +982,60 @@
     }
 }
 
-void
-SDL_SetWindowData(SDL_Window * window, void *userdata)
+void*
+SDL_SetWindowData(SDL_Window * window, const char *name, void *userdata)
 {
-    CHECK_WINDOW_MAGIC(window, );
+    SDL_WindowUserData *prev, *data;
+
+    CHECK_WINDOW_MAGIC(window, NULL);
+
+    /* See if the named data already exists */
+    prev = NULL;
+    for (data = window->data; data; prev = data, data = data->next) {
+        if (SDL_strcmp(data->name, name) == 0) {
+            void *last_value = data->data;
 
-    window->userdata = userdata;
+            if (userdata) {
+                /* Set the new value */
+                data->data = userdata;
+            } else {
+                /* Delete this value */
+                if (prev) {
+                    prev->next = data->next;
+                } else {
+                    window->data = data->next;
+                }
+                SDL_free(data->name);
+                SDL_free(data);
+            }
+            return last_value;
+        }
+    }
+
+    /* Add new data to the window */
+    if (userdata) {
+        data = (SDL_WindowUserData *)SDL_malloc(sizeof(*data));
+        data->name = SDL_strdup(name);
+        data->data = userdata;
+        data->next = window->data;
+        window->data = data;
+    }
+    return NULL;
 }
 
 void *
-SDL_GetWindowData(SDL_Window * window)
+SDL_GetWindowData(SDL_Window * window, const char *name)
 {
+    SDL_WindowUserData *data;
+
     CHECK_WINDOW_MAGIC(window, NULL);
 
-    return window->userdata;
+    for (data = window->data; data; data = data->next) {
+        if (SDL_strcmp(data->name, name) == 0) {
+            return data->data;
+        }
+    }
+    return NULL;
 }
 
 void
@@ -1293,10 +1333,6 @@
 
     CHECK_WINDOW_MAGIC(window, );
 
-    if (window->title) {
-        SDL_free(window->title);
-    }
-
     /* Restore video mode, etc. */
     SDL_UpdateFullscreenMode(window, SDL_FALSE);
 
@@ -1310,6 +1346,18 @@
     /* Now invalidate magic */
     window->magic = NULL;
 
+    /* Free memory associated with the window */
+    if (window->title) {
+        SDL_free(window->title);
+    }
+    while (window->data) {
+        SDL_WindowUserData *data = window->data;
+
+        window->data = data->next;
+        SDL_free(data->name);
+        SDL_free(data);
+    }
+
     /* Unlink the window from the list */
     display = window->display;
     if (window->next) {