diff --git a/src/conf.c b/src/conf.c
index 17dd719..e12691c 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -153,6 +153,7 @@ int conf_loadConfig(const char* file) {
   } else {
     // Failed to load the config file..
     DEBUG("Config file '%s' not found.", file);
+    lua_close(L);
     return 1;
   }
   lua_close(L);
diff --git a/src/input.c b/src/input.c
index 8fdcb33..cac9d85 100644
--- a/src/input.c
+++ b/src/input.c
@@ -2,6 +2,7 @@
 #include "log.h"
 #include "player.h"
 #include "pause.h"
+#include "toolkit.h"
 #include "input.h"
 
 #define KEY_PRESS   ( 1.)
@@ -53,7 +54,7 @@ void input_setDefault(void) {
   input_setKeybind("mapzoomin",       KEYBIND_KEYBOARD, SDLK_UP,      0);
   input_setKeybind("mapzoomout",      KEYBIND_KEYBOARD, SDLK_DOWN,    0);
   input_setKeybind("screenshot",      KEYBIND_KEYBOARD, SDLK_F12,     0);
-  input_setKeybind("pause",           KEYBIND_KEYBOARD, SDLK_p,       0);
+  input_setKeybind("pause",           KEYBIND_KEYBOARD, SDLK_F1,      0);
 }
 
 // Initialization/exit functions (does not assign keys).
@@ -99,7 +100,7 @@ void input_setKeybind(char* keybind, KeybindType type, int key, int reverse) {
 // value  : Value of keypress (defined above).
 // abs    : Whether or not it's an abs value (For those pesky joysticks.
 // =====================================================================
-#define KEY(s) strcmp(input_keybinds[keynum]->name, s)==0
+#define KEY(s) (strcmp(input_keybinds[keynum]->name, s)==0)
 static void input_key(int keynum, double value, int abs) {
   // Accelerating.
   if(KEY("accel")) {
@@ -198,7 +199,8 @@ static void input_key(int keynum, double value, int abs) {
   // Pause the game.
   if(KEY("pause")) {
     if(value == KEY_PRESS) {
-      if(paused) unpause();
+      if(!toolkit)
+        if(paused) unpause();
     } else pause();
   }
 }
@@ -292,6 +294,12 @@ void input_handle(SDL_Event* event) {
     case SDL_KEYUP:
       input_keyup(event->key.keysym.sym);
       break;
+    // Toolkit.
+    case SDL_MOUSEMOTION:
+    case SDL_MOUSEBUTTONDOWN:
+    case SDL_MOUSEBUTTONUP:
+      if(toolkit) toolkit_mouseEvent(event);
+      break;
   }
 }
 
diff --git a/src/land.c b/src/land.c
new file mode 100644
index 0000000..7f56c2b
--- /dev/null
+++ b/src/land.c
@@ -0,0 +1,30 @@
+#include "toolkit.h"
+#include "pause.h"
+#include "land.h"
+
+int landed = 0;
+
+static int land_wid = 0;
+static Planet* planet = NULL;
+
+// Land the player.
+void land(Planet* p) {
+  if(landed) return;
+
+  planet = p;
+  pause();
+  land_wid = window_create(-1, -1, 400, 300);
+  window_addButton(land_wid, 400-80-20, 20, 80, 40, "takeoff", "Takeoff", (void(*)(char*))takeoff);
+  landed = 1;
+}
+
+// Takeoff from the planet.
+void takeoff(void) {
+  if(!landed) return;
+
+  planet = NULL;
+  unpause();
+  window_destroy(land_wid);
+  landed = 0;
+}
+
diff --git a/src/land.h b/src/land.h
new file mode 100644
index 0000000..f2efde7
--- /dev/null
+++ b/src/land.h
@@ -0,0 +1,8 @@
+#pragma once
+#include "space.h"
+
+extern int landed;
+
+void land(Planet* p);
+void takeoff(void);
+
diff --git a/src/main.c b/src/main.c
index dac9317..75a809c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -51,6 +51,7 @@ static void display_fps(const double dt);
 static void window_caption(void);
 static void data_name(void);
 // Update.
+static void fps_control(void);
 static void update_space(void);
 static void render_space(void);
 
@@ -151,7 +152,8 @@ int main(int argc, char** argv) {
     }
 
     glClear(GL_COLOR_BUFFER_BIT);
-
+    
+    fps_control(); // Who doesn't love FPS control?
     if(!paused) update_space(); // Update the game.
 
     render_space();
@@ -186,24 +188,21 @@ int main(int argc, char** argv) {
 // Updates the game.
 static double fps_dt = 1.;
 static double dt = 0.;
-static void update_space(void) {
+static void fps_control(void) {
   // dt in ms/1000.
   dt = (double)(SDL_GetTicks() - gtime) / 1000.;
   gtime = SDL_GetTicks();
   
-  // TODO: This could use some work.
-  if(dt > MINIMUM_FPS) {
-    Vec2 pos;
-    vect_csetmin(&pos, 10., (double)(gl_screen.h-40));
-    SDL_GL_SwapBuffers();
-    return;
-  }
-  // If FPS is limited.
-  else if((max_fps != 0) && (dt < 1./max_fps)) {
+  // If the fps is limited..
+  if((max_fps != 0) && (dt < 1./max_fps)) {
     double delay = 1./max_fps - dt;
     SDL_Delay(delay);
     fps_dt += delay; // Make sure it displays the propper FPS.
   }
+}
+
+// Update the game.
+static void update_space(void) {
   weapons_update(dt);
   pilots_update(dt);
 }
diff --git a/src/opengl.c b/src/opengl.c
index b6a169e..a9433b1 100644
--- a/src/opengl.c
+++ b/src/opengl.c
@@ -19,8 +19,11 @@
 #define FONT_DEF "../gfx/fonts/font.ttf"
 
 // Default colors.
-glColour cGrey   = { .r = 0.75, .g = 0.75, .b = 0.75, .a = 1 };
-glColour cGreen  = { .r = 0.20, .g = 0.80, .b = 0.20, .a = 1 };
+gl_colour cLightGrey   = { .r = 0.80, .g = 0.80, .b = 0.80, .a = 1 };
+gl_colour cGrey        = { .r = 0.65, .g = 0.65, .b = 0.65, .a = 1 };
+gl_colour cDarkGrey    = { .r = 0.50, .g = 0.50, .b = 0.50, .a = 1 };
+gl_colour cGreen       = { .r = 0.20, .g = 0.80, .b = 0.20, .a = 1 };
+gl_colour cRed         = { .r = 0.80, .g = 0.20, .b = 0.20, .a = 1 };
 
 // offsets to Adjust the pilot's place onscreen to be in the middle, even with the GUI.
 extern double gui_xoff;
@@ -349,7 +352,7 @@ void gl_getSpriteFromDir(int* x, int* y, const gl_texture* t, const double dir)
 // ================
 
 // Blit the sprite at given position.
-void gl_blitSprite(const gl_texture* sprite, const Vec2* pos, const int sx, const int sy, const glColour* c) {
+void gl_blitSprite(const gl_texture* sprite, const Vec2* pos, const int sx, const int sy, const gl_colour* c) {
   // Don't bother drawing if offscreen -- waste of cycles.
   if(fabs(VX(*pos) -VX(*gl_camera)+gui_xoff) > gl_screen.w / 2 + sprite->sw / 2 ||
         fabs(VY(*pos) -VY(*gl_camera)+gui_yoff) > gl_screen.h / 2 + sprite->sh / 2)
@@ -391,7 +394,7 @@ void gl_blitSprite(const gl_texture* sprite, const Vec2* pos, const int sx, cons
 }
 
 // Just straight out blit the thing at position.
-void gl_blitStatic(const gl_texture* texture, const Vec2* pos, const glColour* c) {
+void gl_blitStatic(const gl_texture* texture, const Vec2* pos, const gl_colour* c) {
   glEnable(GL_TEXTURE_2D);
   glMatrixMode(GL_PROJECTION);
   glPushMatrix(); // Set up translation matrix.
@@ -425,7 +428,7 @@ void gl_bindCamera(const Vec2* pos) {
 
 // Print text on screen! YES!!!! Just like printf! But different!
 // Defaults ft_font to gl_defFont if NULL.
-void gl_print(const gl_font* ft_font, const Vec2* pos, const glColour* c, const char* fmt, ...) {
+void gl_print(const gl_font* ft_font, const Vec2* pos, const gl_colour* c, const char* fmt, ...) {
   //float h = ft_font->h / .63; // Slightly increases font size.
   char text[256];
   va_list ap;
diff --git a/src/opengl.h b/src/opengl.h
index e0244c4..c4b4e87 100644
--- a/src/opengl.h
+++ b/src/opengl.h
@@ -30,12 +30,15 @@ extern gl_info gl_screen; // Local structure set with gl_init etc.
 // Colours.
 typedef struct {
   double r, g, b, a;
-} glColour;
+} gl_colour;
 #define COLOUR(x) glColor4d((x).r, (x).g, (x).b, (x).a)
 
 // Default colors.
-extern glColour cGrey;
-extern glColour cGreen;
+extern gl_colour cLightGrey;
+extern gl_colour cGrey;
+extern gl_colour cDarkGrey;
+extern gl_colour cGreen;
+extern gl_colour cRed;
 
 // Spritesheet info.
 typedef struct {
@@ -69,11 +72,11 @@ void gl_freeTexture(gl_texture* texture);
 
 // Rendering.
 void gl_blitSprite(const gl_texture* sprite, const Vec2* pos, 
-      const int sx, const int sy, const glColour* c);
+      const int sx, const int sy, const gl_colour* c);
 
-void gl_blitStatic(const gl_texture* texture, const Vec2* pos, const glColour* c);
+void gl_blitStatic(const gl_texture* texture, const Vec2* pos, const gl_colour* c);
 void gl_bindCamera(const Vec2* pos);
-void gl_print(const gl_font* ft_font, const Vec2* pos, const glColour* c, const char* fmt, ...);
+void gl_print(const gl_font* ft_font, const Vec2* pos, const gl_colour* c, const char* fmt, ...);
 int  gl_printWidth(const gl_font* ft_font, const char* fmt, ...);
 
 // Initialize/cleanup.
diff --git a/src/outfit.c b/src/outfit.c
index f5479fc..a9dce7c 100644
--- a/src/outfit.c
+++ b/src/outfit.c
@@ -278,8 +278,8 @@ int outfit_load(void) {
 void outfit_free(void) {
   int i;
   for(i = 0; i < outfits; i++) {
-    if(outfit_isWeapon(&outfit_stack[i]) && outfit_stack[i].gfx_space)
-      gl_freeTexture(outfit_stack[i].gfx_space);
+    // Free graphics.
+    if(outfit_stack[i].gfx_space) gl_freeTexture(outfit_stack[i].gfx_space);
 
     if(outfit_isLauncher(&outfit_stack[i]) && outfit_stack[i].ammo)
       free(outfit_stack[i].ammo);
diff --git a/src/pause.c b/src/pause.c
index b08471a..93325d3 100644
--- a/src/pause.c
+++ b/src/pause.c
@@ -20,7 +20,6 @@ static void pilots_unpause(void);
 void pause(void) {
   if(paused) return; // Well well.. We are paused already.
 
-  gtime -= SDL_GetTicks();
   pilots_pause();
   weapons_pause();
 
@@ -30,7 +29,6 @@ void pause(void) {
 void unpause(void) {
   if(!paused) return; // We are unpaused already.
 
-  gtime += SDL_GetTicks();
   pilots_unpause();
   weapons_unpause();
 
diff --git a/src/player.c b/src/player.c
index 34c883c..ec283c2 100644
--- a/src/player.c
+++ b/src/player.c
@@ -8,6 +8,7 @@
 #include "xml.h"
 #include "space.h"
 #include "rng.h"
+#include "land.h"
 #include "player.h"
 
 #define XML_GUI_ID    "GUIs" // XML section identifier.
@@ -39,20 +40,20 @@ extern int pilots;
 
 // -- Colours.
 // Standard colors.
-glColour cConsole          = { .r = 0.5, .g = 0.8, .b = 0.5, .a = 1. };
+gl_colour cConsole          = { .r = 0.5, .g = 0.8, .b = 0.5, .a = 1. };
 
-glColour cInert            = { .r = 0.6, .g = 0.6, .b = 0.6, .a = 1. };
-glColour cNeutral          = { .r = 0.9, .g = 1.0, .b = 0.3, .a = 1. };
-glColour cFriend           = { .r = 0.0, .g = 1.0, .b = 0.0, .a = 1. };
-glColour cHostile          = { .r = 0.9, .g = 0.2, .b = 0.2, .a = 1. };
+gl_colour cInert            = { .r = 0.6, .g = 0.6, .b = 0.6, .a = 1. };
+gl_colour cNeutral          = { .r = 0.9, .g = 1.0, .b = 0.3, .a = 1. };
+gl_colour cFriend           = { .r = 0.0, .g = 1.0, .b = 0.0, .a = 1. };
+gl_colour cHostile          = { .r = 0.9, .g = 0.2, .b = 0.2, .a = 1. };
 
-glColour cRadar_player     = { .r = 0.4, .g = 0.8, .b = 0.4, .a = 1. };
-glColour cRadar_targ       = { .r = 0.0, .g = 0.7, .b = 1.0, .a = 1. };
-glColour cRadar_weap       = { .r = 0.8, .g = 0.2, .b = 0.2, .a = 1. };
+gl_colour cRadar_player     = { .r = 0.4, .g = 0.8, .b = 0.4, .a = 1. };
+gl_colour cRadar_targ       = { .r = 0.0, .g = 0.7, .b = 1.0, .a = 1. };
+gl_colour cRadar_weap       = { .r = 0.8, .g = 0.2, .b = 0.2, .a = 1. };
 // Bars.
-glColour cShield           = { .r = 0.2, .g = 0.2, .b = 0.8, .a = 1. };
-glColour cArmor            = { .r = 0.5, .g = 0.5, .b = 0.5, .a = 1. };
-glColour cEnergy           = { .r = 0.2, .g = 0.8, .b = 0.2, .a = 1. };
+gl_colour cShield           = { .r = 0.2, .g = 0.2, .b = 0.8, .a = 1. };
+gl_colour cArmor            = { .r = 0.5, .g = 0.5, .b = 0.5, .a = 1. };
+gl_colour cEnergy           = { .r = 0.2, .g = 0.8, .b = 0.2, .a = 1. };
 
 typedef struct {
   double w,h; // Dimensions.
@@ -115,7 +116,7 @@ extern void planets_minimap(const double res, const double w, const double h, co
 static void rect_parse(const xmlNodePtr parent, double* x, double* y, double* w, double* h);
 static int gui_parse(const xmlNodePtr parent, const char* name);
 static void gui_renderPilot(const Pilot* p);
-static void gui_renderBar(const glColour* c, const Vec2* p, const Rect* r, const double w);
+static void gui_renderBar(const gl_colour* c, const Vec2* p, const Rect* r, const double w);
 
 // Create a new player.
 void player_new(void) {
@@ -216,7 +217,7 @@ void player_render(void) {
   Pilot* p;
   Planet* planet;
   Vec2 v;
-  glColour* c;
+  gl_colour* c;
   gl_font* f;
 
   // Render the player target graphics.
@@ -467,7 +468,7 @@ static void gui_renderPilot(const Pilot* p) {
 }
 
 // Render a bar.
-static void gui_renderBar(const glColour* c, const Vec2* p, const Rect* r, const double w) {
+static void gui_renderBar(const gl_colour* c, const Vec2* p, const Rect* r, const double w) {
   int x, y, sx, sy;
 
   glBegin(GL_QUADS);
@@ -858,6 +859,11 @@ void player_targetPlanet(void) {
 
 // Attempt to land or target closest planet if no land target.
 void player_land(void) {
+  if(landed) {
+    // Player is already landed.
+    takeoff();
+    return;
+  }
   Planet* planet = &cur_system->planets[planet_target];
   if(planet_target >= 0) {
     if(vect_dist(&player->solid->vel, &planet->pos) > planet->gfx_space->sw) {
@@ -868,8 +874,7 @@ void player_land(void) {
       player_message("You are going too fast to land on %s", planet->name);
       return;
     }
-    // TODO: Landing.
-    player_message("D'aww.. Allanis was too lazy to do it properly.");
+    land(planet); // Land the player.
   } else {
     // Get nearest planet target.
     int i;
diff --git a/src/ship.c b/src/ship.c
index c482317..ec9a791 100644
--- a/src/ship.c
+++ b/src/ship.c
@@ -191,8 +191,9 @@ void ships_free(void) {
   ShipOutfit* so, *sot;
   int i;
   for(i = 0; i < ships; i++) {
-    if((ship_stack+i)->name) // Free the name.
-      free((ship_stack+i)->name);
+    // Free stored strings.
+    if((ship_stack+i)->name) free(ship_stack[i].name);
+    if((ship_stack+i)->gui) free(ship_stack[i].gui);
     so = (ship_stack+i)->outfit;
     while(so) { // free the ship outfit.
       sot = so;
diff --git a/src/toolkit.c b/src/toolkit.c
index 44bbf9f..a10bebf 100644
--- a/src/toolkit.c
+++ b/src/toolkit.c
@@ -1,14 +1,41 @@
 #include "log.h"
 #include "pause.h"
+#include "opengl.h"
 #include "toolkit.h"
 
+typedef enum {
+  WIDGET_NULL,
+  WIDGET_BUTTON,
+  WIDGET_TEXT
+} WidgetType;
+
+typedef enum {
+  WIDGET_STATUS_NORMAL,
+  WIDGET_STATUS_MOUSEOVER,
+  WIDGET_STATUS_MOUSEDOWN,
+} WidgetStatus;
+
+typedef struct {
+  char* name; // Widget name.
+  WidgetType type; // type..
+
+  double x,y; // Position.
+  double w,h; // Dimensions.
+
+  WidgetStatus status;
+
+  void(*fptr) (char*); // Callback.
+  char* string; // Stored text.
+} Widget;
+
 typedef struct {
   unsigned int id; // Unique identifier.
 
   double x,y; // Position.
   double w,h; // Dimensions.
 
-  gl_texture* t; // Possible texture.
+  Widget* widgets; // Widget storage.
+  int nwidgets; // Total number of widgets.
 } Window;
 
 static unsigned int genwid = 0; // Generate unique id.
@@ -16,46 +43,109 @@ static unsigned int genwid = 0; // Generate unique id.
 int toolkit = 0;
 
 #define MIN_WINDOWS 3
-static Window** windows = NULL;
+static Window* windows = NULL;
 static int nwindows = 0;
 static int mwindows = 0;
 
+static Widget* window_newWidget(const unsigned int wid);
+static void widget_cleanup(Widget* widget);
+static void window_render(Window* w);
+
+// Add a button that when pressed will trigger call, passing it's name as the
+// only parameter.
+void window_addButton(const unsigned int wid, const int x, const int y, const int w,
+      const int h, char* name, char* display, void (*call)(char*)) {
+  
+  Widget* widget = window_newWidget(wid);
+
+  widget->type = WIDGET_BUTTON;
+  widget->name = strdup(name);
+  widget->string = strdup(display);
+
+  // Set the properties.
+  widget->x = (double) x;
+  widget->y = (double) y;
+  widget->w = (double) w;
+  widget->h = (double) h;
+  widget->fptr = call;
+}
+
+// Return pointer to newly allocated widget.
+static Widget* window_newWidget(const unsigned int wid) {
+  int i;
+  for(i = 0; i < nwindows; i++)
+    if(windows[i].id == wid)
+      break;
+
+  if(i == nwindows) return NULL;
+
+  Widget* w = NULL;
+
+  windows[i].widgets = realloc(windows[i].widgets, sizeof(Widget)*(++windows[i].nwidgets));
+  if(windows[i].widgets == NULL) WARN("Out of memory");
+
+  w = &windows[i].widgets[windows[i].nwidgets - 1];
+
+  w->type = WIDGET_NULL;
+  w->status = WIDGET_STATUS_NORMAL;
+  return w;
+}
+
 // Create a window.
-unsigned int window_create(int x, int y, int w, int h, gl_texture* t) {
-  Window* wtmp = NULL;
-  if(nwindows == mwindows) {
-    // We have reached the memory limit.
-    windows = realloc(windows, sizeof(Window*)*(++mwindows));
+unsigned int window_create(const int x, const int y, const int w, const int h) {
+  if(nwindows >= mwindows) {
+    // We have reached our memory limit.
+    windows = realloc(windows, sizeof(Window)*(++mwindows));
     if(windows == NULL) WARN("Out of memory");
   }
-  wtmp = malloc(sizeof(Window));
-  if(wtmp == NULL) WARN("Out of memory");
 
-  int wid = (++genwid); // Unique id
+  const int wid = (++genwid); // Unique id
 
-  wtmp->id = wid;
+  windows[nwindows].id = wid;
 
-  wtmp->x = x;
-  wtmp->y = y;
-  wtmp->h = h;
-  wtmp->w = w;
-  wtmp->t = t;
+  windows[nwindows].w = (double) w;
+  windows[nwindows].h = (double) h;
+  if((x == -1) && (y == -1)) {
+    // Center.
+    windows[nwindows].x = windows[nwindows].w/2.;
+    windows[nwindows].y = windows[nwindows].h/2.;
+  } else {
+    windows[nwindows].x = (double) x;
+    windows[nwindows].y = (double) y;
+  }
+  
+  windows[nwindows].widgets = NULL;
+  windows[nwindows].nwidgets = 0;
 
-  windows[nwindows++] = wtmp;
+  nwindows++;
 
-  if(toolkit == 0) toolkit = 1; // Enable the toolkit.
+  if(toolkit == 0) {
+    // Toolkit is enabled.
+    SDL_ShowCursor(SDL_ENABLE);
+    toolkit = 1; // Enable it.
+  }
 
   return wid;
 }
 
+// Destroy a widget.
+static void widget_cleanup(Widget* widget) {
+  if(widget->name) free(widget->name);
+
+  if((widget->type == WIDGET_TEXT) && widget->string)
+    free(widget->string);
+}
+
 // Destroy a window.
 void window_destroy(unsigned int wid) {
-  int i;
+  int i, j;
 
   // Destroy the window.
   for(i = 0; i < nwindows; i++)
-    if(windows[i]->id == wid) {
-      free(windows[i]);
+    if(windows[i].id == wid) {
+      for(j = 0; j < windows[i].nwidgets; j++)
+        widget_cleanup(&windows[i].widgets[j]);
+      free(windows[i].widgets);
       break;
     }
   // Move the other windows down a layer.
@@ -63,12 +153,138 @@ void window_destroy(unsigned int wid) {
     windows[i] = windows[i+1];
 
     nwindows--;
-    if(nwindows == 0) toolkit = 0; // Disable the toolkit.
+    if(nwindows == 0) {
+      // No windows left.
+      SDL_ShowCursor(SDL_DISABLE);
+      toolkit = 0; // Disable the toolkit.
+    }
+}
+
+// Render a window.
+static void window_render(Window* w) {
+  int i, j;
+  double x, y;
+  Widget* wgt;
+  Vec2 v;
+
+  x = w->x - (double)gl_screen.w/2.;
+  y = w->y - (double)gl_screen.h/2.;
+
+  // Translate to window position  (bottom left).
+  glMatrixMode(GL_PROJECTION);
+  glPushMatrix(); // Projection translation matrix.
+  glTranslated(x, y, 0.);
+
+  // Window background.
+  glBegin(GL_TRIANGLE_STRIP);
+    COLOUR(cLightGrey);
+
+    glVertex2d(0.,      0.);
+    glVertex2d(w->w,    0.);
+    glVertex2d(0.,    w->h);
+    glVertex2d(w->w,  w->h);
+  glEnd();
+
+  glPopMatrix(); // Gl Projection.
+
+  // Widgets.
+  for(i = 0; i < w->nwidgets; i++) {
+    wgt = &w->widgets[i];
+
+    switch(wgt->type) {
+      case WIDGET_NULL:
+        break;
+      case WIDGET_BUTTON:
+        glMatrixMode(GL_PROJECTION);
+        glPushMatrix(); // Projection matrix.
+        glTranslated(x + wgt->x, y + wgt->y, 0.);
+
+        glBegin(GL_TRIANGLE_STRIP);
+          switch(wgt->status) {
+            // Set the colour.
+            case WIDGET_STATUS_NORMAL:      COLOUR(cDarkGrey);  break;
+            case WIDGET_STATUS_MOUSEOVER:   COLOUR(cGrey);      break;
+            case WIDGET_STATUS_MOUSEDOWN:   COLOUR(cGreen);     break;
+          }
+          
+          glVertex2d(0.,          0.);
+          glVertex2d(wgt->w,      0.);
+          glVertex2d(0.,      wgt->h);
+          glVertex2d(wgt->w,  wgt->h);
+        glEnd();
+        glPopMatrix();
+
+        j = gl_printWidth(NULL, wgt->string);
+        vect_csetmin(&v, w->x + wgt->x + (wgt->w - (double)j)/2.,
+              w->y + wgt->y + (wgt->h - gl_defFont.h)/2.);
+        gl_print(NULL, &v, &cRed, wgt->string);
+        break;
+      case WIDGET_TEXT:
+        break;
+    }
+  }
 }
 
 // Render the window.
 void toolkit_render(void) {
+  int i;
+  for(i = 0; i < nwindows; i++)
+    window_render(&windows[i]);
+}
 
+// Input.
+static int mouse_down = 0;
+void toolkit_mouseEvent(SDL_Event* event) {
+  int i;
+  double x, y;
+  Window* w;
+  Widget* wgt;
+
+  // Set mouse button status.
+  if(event->type == SDL_MOUSEBUTTONDOWN) mouse_down = 1;
+  else if(event->type == SDL_MOUSEBUTTONUP) mouse_down = 0;
+  // Ignore movements if mouse is down.
+  else if((event->type == SDL_MOUSEMOTION) && mouse_down) return;
+
+  // Absolute positions.
+  if(event->type == SDL_MOUSEMOTION) {
+    x = (double)event->motion.x;
+    y = gl_screen.h - (double)event->motion.y;
+  }
+  else if((event->type == SDL_MOUSEBUTTONDOWN) || (event->type == SDL_MOUSEBUTTONUP)) {
+    x = (double)event->button.x;
+    y = gl_screen.h - (double)event->motion.y;
+  }
+
+  w = &windows[nwindows-1];
+
+  if((x < w->x) || (x > (w->x + w->w)) || (y < w->y) || (y > (w->y + w->h)))
+    return; // Not in current window.
+
+  // Relative positions.
+  x -= w->x;
+  y -= w->y;
+
+  for(i = 0; i < w->nwidgets; i++) {
+    wgt = &w->widgets[i];
+    if((x > wgt->x) && (x < (wgt->x + wgt->w)) && (y > wgt->y) && (y < (wgt->y + wgt->h))) {
+      switch(event->type) {
+        case SDL_MOUSEMOTION:
+          wgt->status = WIDGET_STATUS_MOUSEOVER;
+          break;
+        case SDL_MOUSEBUTTONDOWN:
+          wgt->status = WIDGET_STATUS_MOUSEDOWN;
+          break;
+        case SDL_MOUSEBUTTONUP:
+          if(wgt->status == WIDGET_STATUS_MOUSEDOWN) {
+            if(wgt->type == WIDGET_BUTTON) (*wgt->fptr)(wgt->name);
+          }
+          wgt->status = WIDGET_STATUS_NORMAL;
+          break;
+      }
+    } else
+      wgt->status = WIDGET_STATUS_NORMAL;
+  }
 }
 
 // Init.
@@ -76,7 +292,7 @@ int toolkit_init(void) {
   windows = malloc(sizeof(Window)*MIN_WINDOWS);
   nwindows = 0;
   mwindows = MIN_WINDOWS;
-
+  SDL_ShowCursor(SDL_DISABLE);
   return 0;
 }
 
@@ -84,7 +300,7 @@ int toolkit_init(void) {
 void toolkit_exit(void) {
   int i;
   for(i = 0; i < nwindows; i++) {
-    window_destroy(windows[i]->id);
+    window_destroy(windows[i].id);
   free(windows);
   }
 }
diff --git a/src/toolkit.h b/src/toolkit.h
index ba55485..8b98af0 100644
--- a/src/toolkit.h
+++ b/src/toolkit.h
@@ -1,17 +1,25 @@
 #pragma once
 #include "opengl.h"
+#include "SDL.h"
 
 extern int toolkit;
 
 // Creation.
-unsigned int window_create(int x, int y, int w, int h, gl_texture* t);
+unsigned int window_create(const int x, const int y, const int w, const int h);
+
+void window_addButton(const unsigned int wid, const int x, const int y,
+      const int w, const int h, char* name, char* display,
+      void(*call)(char*));
 
 // Destroy window.
-void window_destroy(unsigned int wid);
+void window_destroy(const unsigned int wid);
 
 // Render.
 void toolkit_render(void);
 
+// Input.
+void toolkit_mouseEvent(SDL_Event* event);
+
 // Init/Exit.
 int toolkit_init(void);
 void toolkit_exit(void);
diff --git a/src/xml.h b/src/xml.h
index 1d918f9..36e89aa 100644
--- a/src/xml.h
+++ b/src/xml.h
@@ -12,7 +12,7 @@
 // Get the property s of node n. This mallocs.
 #define xml_nodeProp(n,s) (char*)xmlGetProp(n, (xmlChar*)s)
 
-#define xml_get(n)      (char*)(n)->children->content
-#define xml_getInt(n)   atoi((char*)(n)->children->content)
-#define xml_getFloat(n) atof((char*)(n)->children->content)
+#define xml_get(n)      ((char*)(n)->children->content)
+#define xml_getInt(n)   (atoi((char*)(n)->children->content))
+#define xml_getFloat(n) (atof((char*)(n)->children->content))