diff --git a/src/generic_system_view.cpp b/src/generic_system_view.cpp
index 1a3df94..fad687f 100644
--- a/src/generic_system_view.cpp
+++ b/src/generic_system_view.cpp
@@ -5,8 +5,9 @@
 
 GenericSystemView::GenericSystemView(void) : View() {
   px = py = pidx = 0xdeadbeef;
-  m_scannerLayout = new Gui::Fixed(140, 2, 360, 60);
+  m_scannerLayout = new Gui::Fixed(360, 60);
   m_scannerLayout->SetTransparency(true);
+  Gui::Screen::AddBaseWidget(m_scannerLayout, 140, 2);
 
   m_systemName = new Gui::Label("");
   m_systemName->SetColor(1, 1, 0);
diff --git a/src/glfreetype.cpp b/src/glfreetype.cpp
index a5a1a3a..cb0b556 100644
--- a/src/glfreetype.cpp
+++ b/src/glfreetype.cpp
@@ -299,6 +299,36 @@ void FontFace::RenderString(const char* str) {
   glPopMatrix();
 }
 
+/* 'Markup' indeed. #rgb hex is change colour, no sensible escape. */
+void FontFace::RenderMarkup(const char* str) {
+  glPushMatrix();
+  int len = strlen(str);
+  for(unsigned int i = 0; i < len; i++) {
+    if(str[i] == '#') {
+      int hexcol;
+      if(sscanf(str+i, "#%3x", &hexcol)==1) {
+        Uint8 col[3];
+        col[0] = (hexcol&0xf00)>>4;
+        col[1] = (hexcol&0xf0);
+        col[2] = (hexcol&0xf)<<4;
+        glColor3ubv(col);
+        i+=3;
+        continue;
+      }
+    }
+    if(str[i] == '\n') {
+      glPopMatrix();
+      glTranslatef(0, -m_height, 0);
+      glPushMatrix();
+    } else {
+      glfglyph_t* glyph = &m_glyphs[str[i]];
+      if(glyph->numidx) RenderGlyph(str[i]);
+      glTranslatef(glyph->advx, 0, 0);
+    }
+  }
+  glPopMatrix();
+}
+
 FontFace::FontFace(const char* filename_ttf) {
   FT_Face face;
   if(0 != FT_New_Face(library, filename_ttf, 0, &face)) {
diff --git a/src/glfreetype.h b/src/glfreetype.h
index 7e1074a..52fb433 100644
--- a/src/glfreetype.h
+++ b/src/glfreetype.h
@@ -7,6 +7,7 @@ public:
   FontFace(const char* filename_ttf);
   void RenderGlyph(int chr);
   void RenderString(const char* str);
+  void RenderMarkup(const char* str);
 
   /* Of Ms. */
   float GetHeight(void) { return m_height; }
diff --git a/src/gui_button.cpp b/src/gui_button.cpp
index 05c22a0..278fc6a 100644
--- a/src/gui_button.cpp
+++ b/src/gui_button.cpp
@@ -11,20 +11,22 @@ Button::Button(void) {
   SetSize(BUTTON_SIZE, BUTTON_SIZE);
 }
 
-void Button::OnMouseDown(MouseButtonEvent* e) {
+bool Button::OnMouseDown(MouseButtonEvent* e) {
   if(e->button == 1) {
     m_isPressed = true;
     onPress.emit();
     /* Wait for mouse release, regardless of where on screen. */
     _m_release = RawEvents::onMouseUp.connect(sigc::mem_fun(this, &Button::OnRawMouseUp));
   }
+  return false;
 }
 
-void Button::OnMouseUp(MouseButtonEvent* e) {
+bool Button::OnMouseUp(MouseButtonEvent* e) {
   if((e->button == 1) && m_isPressed) {
     m_isPressed = false;
     onClick.emit();
   }
+  return false;
 }
 
 void Button::OnActivate(void) {
diff --git a/src/gui_button.h b/src/gui_button.h
index d8b3031..b85ebca 100644
--- a/src/gui_button.h
+++ b/src/gui_button.h
@@ -7,8 +7,8 @@ namespace Gui {
   public:
     Button(void);
     virtual ~Button(void) {}
-    virtual void OnMouseDown(MouseButtonEvent* e);
-    virtual void OnMouseUp(MouseButtonEvent* e);
+    virtual bool OnMouseDown(MouseButtonEvent* e);
+    virtual bool OnMouseUp(MouseButtonEvent* e);
     virtual void OnActivate(void);
 
     /* 
diff --git a/src/gui_container.cpp b/src/gui_container.cpp
index a897783..977671d 100644
--- a/src/gui_container.cpp
+++ b/src/gui_container.cpp
@@ -3,7 +3,8 @@
 
 namespace Gui {
 
-void Container::HandleMouseEvent(MouseButtonEvent* e) {
+
+bool Container::HandleMouseEvent(MouseButtonEvent* e) {
   float x = e->x;
   float y = e->y;
   for(std::list<widget_pos>::iterator i = m_children.begin(); i != m_children.end(); ++i) {
@@ -22,13 +23,16 @@ void Container::HandleMouseEvent(MouseButtonEvent* e) {
        (y >= pos[1]) && (y < pos[1]+size[1])) {
       e->x = x-pos[0];
       e->y = y-pos[1];
+      bool alive;
       if(e->isdown) {
-        (*i).w->OnMouseDown(e);
+        alive = (*i).w->OnMouseDown(e);
       } else {
-        (*i).w->OnMouseUp(e);
+        alive = (*i).w->OnMouseUp(e);
       }
+      if(!alive) return false;
     }
   }
+  return true;
 }
 
 void Container::DeleteAllChildren(void) {
@@ -66,12 +70,12 @@ void Container::Draw(void) {
   }
 }
 
-void Container::OnMouseDown(MouseButtonEvent* e) {
-  HandleMouseEvent(e);
+bool Container::OnMouseDown(MouseButtonEvent* e) {
+  return HandleMouseEvent(e);
 }
 
-void Container::OnMouseUp(MouseButtonEvent* e) {
-  HandleMouseEvent(e);
+bool Container::OnMouseUp(MouseButtonEvent* e) {
+  return HandleMouseEvent(e);
 }
 
 void Container::ShowAll(void) {
diff --git a/src/gui_container.h b/src/gui_container.h
index 50e6734..982c15f 100644
--- a/src/gui_container.h
+++ b/src/gui_container.h
@@ -7,14 +7,14 @@
 namespace Gui {
   class Container : public Widget {
   public:
-    void OnMouseDown(MouseButtonEvent* e);
-    void OnMouseUp(MouseButtonEvent* e);
+    bool OnMouseDown(MouseButtonEvent* e);
+    bool OnMouseUp(MouseButtonEvent* e);
     void DeleteAllChildren(void);
     virtual void Draw(void);
     virtual void ShowAll(void);
     virtual void HideAll(void);
   private:
-    void HandleMouseEvent(MouseButtonEvent* e);
+    bool HandleMouseEvent(MouseButtonEvent* e);
   protected:
     void PrependChild(Widget* w, float x, float y);
     void AppendChild(Widget* w, float x, float y);
diff --git a/src/gui_events.h b/src/gui_events.h
index 2ab060c..5da523e 100644
--- a/src/gui_events.h
+++ b/src/gui_events.h
@@ -3,7 +3,8 @@ namespace Gui {
   struct MouseButtonEvent {
     Uint8 isdown;
     Uint8 button;
-    float x, y;
+    float x, y; /* Widget coords. */
+    float screenX, screenY; /* Screen coords. */
   };
 }
 
diff --git a/src/gui_fixed.cpp b/src/gui_fixed.cpp
index a58706e..0805e1c 100644
--- a/src/gui_fixed.cpp
+++ b/src/gui_fixed.cpp
@@ -4,14 +4,12 @@
 
 namespace Gui {
 
-Fixed::Fixed(float x, float y, float w, float h) {
-  SetPosition(x, y);
+Fixed::Fixed(float w, float h) {
   SetSize(w, h);
   memcpy(m_bgcol, Color::bg, 3*sizeof(float));
   m_w = w; m_h = h;
   m_transparent = false;
   m_eventMask = EVENT_ALL;
-  Screen::AddBaseWidget(this);
 }
 
 void Fixed::GetSizeRequested(float size[2]) {
diff --git a/src/gui_fixed.h b/src/gui_fixed.h
index 8544ece..b69b9c6 100644
--- a/src/gui_fixed.h
+++ b/src/gui_fixed.h
@@ -7,7 +7,7 @@
 namespace Gui {
   class Fixed : public Container {
   public:
-    Fixed(float x, float y, float w, float h);
+    Fixed(float w, float h);
     void Add(Widget* child, float x, float y);
     void Remove(Widget* child);
     virtual void Draw(void);
diff --git a/src/gui_label.cpp b/src/gui_label.cpp
index 6f59633..9587776 100644
--- a/src/gui_label.cpp
+++ b/src/gui_label.cpp
@@ -22,7 +22,7 @@ void Label::SetText(std::string& text) {
 
 void Label::Draw(void) {
   glColor3fv(m_color);
-  Screen::RenderString(m_text);
+  Screen::RenderMarkup(m_text);
 }
 
 void Label::GetSizeRequested(float size[2]) {
diff --git a/src/gui_radio_button.cpp b/src/gui_radio_button.cpp
index f80852c..975d962 100644
--- a/src/gui_radio_button.cpp
+++ b/src/gui_radio_button.cpp
@@ -15,9 +15,10 @@ RadioButton::~RadioButton(void) {
 
 }
 
-void RadioButton::OnMouseDown(MouseButtonEvent* e) {
+bool RadioButton::OnMouseDown(MouseButtonEvent* e) {
   onPress.emit();
   OnActivate();
+  return false;
 }
 
 void RadioButton::OnActivate(void) {
diff --git a/src/gui_radio_button.h b/src/gui_radio_button.h
index 5febb17..a151f24 100644
--- a/src/gui_radio_button.h
+++ b/src/gui_radio_button.h
@@ -14,7 +14,7 @@ namespace Gui {
 		virtual ~RadioButton();
 		virtual void Draw();
 		virtual void GetSizeRequested(float &w, float &h);
-		virtual void OnMouseDown(MouseButtonEvent *e);
+		virtual bool OnMouseDown(MouseButtonEvent *e);
 		virtual void OnActivate();
 		virtual void SetSelected(bool state) { m_pressed = state; }
 		bool GetSelected() { return m_pressed; }
diff --git a/src/gui_screen.cpp b/src/gui_screen.cpp
index 693c09a..af14297 100644
--- a/src/gui_screen.cpp
+++ b/src/gui_screen.cpp
@@ -79,7 +79,8 @@ void Screen::Draw(void) {
   LeaveOrtho();
 }
 
-void Screen::AddBaseWidget(Widget* w) {
+void Screen::AddBaseWidget(Widget* w, int x, int y) {
+  w->SetPosition(x, y);
   Screen::widgets.push_back(w);
 }
 
@@ -97,6 +98,8 @@ void Screen::OnClick(SDL_MouseButtonEvent* e) {
   ev.isdown = (e->type == SDL_MOUSEBUTTONDOWN);
   ev.x = x;
   ev.y = y;
+  ev.screenX = x;
+  ev.screenY = y;
   OnClickTestLabels(ev);
   for(std::list<Widget*>::iterator i = Screen::widgets.begin(); i != Screen::widgets.end(); ++i) {
     float size[2], pos[2];
@@ -151,6 +154,13 @@ void Screen::RenderString(const std::string& s) {
   glPopMatrix();
 }
 
+void Screen::RenderMarkup(const std::string& s) {
+  glPushMatrix();
+  glScalef(Screen::font_xsize, Screen::font_ysize, 1);
+  font->RenderMarkup(s.c_str());
+  glPopMatrix();
+}
+
 bool Screen::CanPutLabel(float x, float y) {
   for(std::vector<LabelPos>::iterator i = labelPositions.begin(); i != labelPositions.end(); ++i) {
     if((fabs(x-(*i).x) < 5) &&
diff --git a/src/gui_screen.h b/src/gui_screen.h
index ab72bcb..dad9894 100644
--- a/src/gui_screen.h
+++ b/src/gui_screen.h
@@ -9,11 +9,12 @@ namespace Gui {
   public:
     static void Init(int real_width, int real_height, int ui_width, int ui_height);
     static void Draw(void);
-    static void AddBaseWidget(Widget* w);
+    static void AddBaseWidget(Widget* w, int x, int y);
     static void RemoveBaseWidget(Widget* w);
     static void OnClick(SDL_MouseButtonEvent* e);
     static void OnKeyDown(const SDL_keysym* sym);
     static void RenderString(const std::string& s);
+    static void RenderMarkup(const std::string& s);
     static void PutClickableLabel(const std::string& s, float x, float y,
                                   sigc::slot<void, const Gui::MouseButtonEvent*> slot);
     static void RenderLabel(const std::string& s, float x, float y);
diff --git a/src/gui_toggle_button.cpp b/src/gui_toggle_button.cpp
index 7321469..5c6a009 100644
--- a/src/gui_toggle_button.cpp
+++ b/src/gui_toggle_button.cpp
@@ -10,7 +10,7 @@ ToggleButton::ToggleButton(void) {
   SetSize(BUTTON_SIZE, BUTTON_SIZE);
 }
 
-void ToggleButton::OnMouseDown(MouseButtonEvent* e) {
+bool ToggleButton::OnMouseDown(MouseButtonEvent* e) {
   if(e->button == 1) {
     onPress.emit();
     m_pressed = !m_pressed;
@@ -20,6 +20,7 @@ void ToggleButton::OnMouseDown(MouseButtonEvent* e) {
       onDeselect.emit(this);
     }
   }
+  return false;
 }
 
 void ToggleButton::GetSizeRequested(float& w, float& h) {
diff --git a/src/gui_toggle_button.h b/src/gui_toggle_button.h
index 7020130..a5ca6e9 100644
--- a/src/gui_toggle_button.h
+++ b/src/gui_toggle_button.h
@@ -9,7 +9,7 @@ namespace Gui {
     virtual void Draw(void);
     virtual ~ToggleButton(void) {}
     virtual void GetSizeRequested(float& w, float& h);
-    virtual void OnMouseDown(MouseButtonEvent* e);
+    virtual bool OnMouseDown(MouseButtonEvent* e);
     void SetPressed(bool s) { m_pressed = s; }
     bool GetPressed(void)   { return m_pressed; }
 
diff --git a/src/gui_widget.h b/src/gui_widget.h
index 71448fa..7be0b0d 100644
--- a/src/gui_widget.h
+++ b/src/gui_widget.h
@@ -20,8 +20,9 @@ namespace Gui {
     Container* GetParent(void)          { return m_parent; }
     void SetParent(Container* p)        { m_parent = p; }
 
-    virtual void OnMouseDown(MouseButtonEvent* e) {}
-    virtual void OnMouseUp(MouseButtonEvent* e)   {}
+    /* Event handlers should return false to stop propagating event. */
+    virtual bool OnMouseDown(MouseButtonEvent* e) { return false; }
+    virtual bool OnMouseUp(MouseButtonEvent* e)   { return false; }
     virtual void OnActivate(void)                 {}
     /* Only to be called by Screen::OnKeyDown. */
     void OnPreShortcut(const SDL_keysym* sym);
diff --git a/src/main.cpp b/src/main.cpp
index 1be50c3..15fd495 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -192,7 +192,7 @@ void L3D::MainLoop(void) {
   StarSystem s(0, 0, 0);
   HyperspaceTo(&s);
 
-  const float zpos = EARTH_RADIUS * 7;
+  const float zpos = EARTH_RADIUS * 1;
   Frame* pframe = *(Space::rootFrame->m_children.begin());
   player->SetFrame(pframe);
   player->SetPosition(vector3d(0, zpos*0.1, zpos));
@@ -207,13 +207,11 @@ void L3D::MainLoop(void) {
     Space::AddBody(body);
   }
 
-  {
-    SpaceStation* body = new SpaceStation();
-    body->SetLabel("Poemi-chan's Folly");
-    body->SetFrame(pframe);
-    body->SetPosition(vector3d(5000, zpos*0.1, zpos-10000));
-    Space::AddBody(body);
-  }
+  SpaceStation* station = new SpaceStation();
+  station->SetLabel("Poemi-chan's Folly");
+  station->SetFrame(pframe);
+  station->SetPosition(vector3d(5000, zpos*0.1, zpos-10000));
+  Space::AddBody(station);
 
   Gui::Init(scrWidth, scrHeight, 640, 480);
 
@@ -229,6 +227,7 @@ void L3D::MainLoop(void) {
   infoView          = new InfoView();
 
   SetView(world_view);
+  player->SetDockedWith(station);
 
   Uint32 last_stats = SDL_GetTicks();
   int frame_stat = 0;
diff --git a/src/object_viewer_view.h b/src/object_viewer_view.h
index c2dfae7..f2dbfbb 100644
--- a/src/object_viewer_view.h
+++ b/src/object_viewer_view.h
@@ -11,7 +11,6 @@ public:
   virtual void Update(void);
   virtual void Draw3D(void);
 private:
-  virtual void OnMouseDown(Gui::MouseButtonEvent* e) { }
   matrix4x4d viewingRotation;
   float viewingDist;
   Gui::Label* m_infoLabel;
diff --git a/src/ship.cpp b/src/ship.cpp
index cc7a654..6a16b47 100644
--- a/src/ship.cpp
+++ b/src/ship.cpp
@@ -27,6 +27,7 @@ Ship::Ship(ShipType::Type shipType) : DynamicBody() {
   m_wheelTransition = 0;
   m_wheelState    = 0;
   m_dockedWith    = 0;
+  dockingTimer    = 0;
   m_navTarget     = 0;
   m_combatTarget  = 0;
   m_shipType      = shipType;
@@ -83,6 +84,7 @@ void Ship::CalcStats(shipstats_t* stats) {
 }
 
 void Ship::TimeStepUpdate(const float timeStep) {
+  dockingTimer = (dockingTimer-timeStep > 0 ? dockingTimer-timeStep : 0);
   /* ODE tri mesh likes to know our old position. */
   TriMeshUpdateLastPos();
   const ShipType& stype = GetShipType();
@@ -163,6 +165,7 @@ void Ship::SetDockedWith(SpaceStation* s) {
 
   } else {
     m_dockedWith = s;
+    dockingTimer = 0.0f;
     SetVelocity(vector3d(0, 0, 0));
     SetAngVelocity(vector3d(0, 0, 0));
   }
@@ -177,6 +180,16 @@ void Ship::SetWheelState(bool down) {
   else m_wheelTransition = -1;
 }
 
+void Ship::SetNavTarget(Body* const target) {
+  m_navTarget = target;
+  L3D::world_view->UpdateCommsOptions();
+}
+
+void Ship::SetCombatTarget(Body* const target) {
+  m_combatTarget = target;
+  L3D::world_view->UpdateCommsOptions();
+}
+
 /* Assumed to be at model coords. */
 void Ship::RenderLaserfire(void) {
   const ShipType& stype = GetShipType();
diff --git a/src/ship.h b/src/ship.h
index e38a6f8..5ffa422 100644
--- a/src/ship.h
+++ b/src/ship.h
@@ -20,9 +20,9 @@ public:
   virtual Object::Type GetType(void) { return Object::SHIP; }
   virtual void SetDockedWith(SpaceStation*);
   SpaceStation* GetDockedWith(void) { return m_dockedWith; }
-  void SetNavTarget(Body* const target) { m_navTarget = target; }
+  void SetNavTarget(Body* const target);
   Body* GetNavTarget(void) const { return m_navTarget; }
-  void SetCombatTarget(Body* const target) { m_combatTarget = target; }
+  void SetCombatTarget(Body* const target);
   Body* GetCombatTarget(void) const { return m_combatTarget; }
   virtual void Render(const Frame* camFrame);
   void SetThrusterState(enum ShipType::Thruster t, float level);
@@ -33,6 +33,8 @@ public:
   void CalcStats(shipstats_t* stats);
   void UpdateMass(void);
   void SetWheelState(bool down);
+  float GetDockingTimer(void) { return dockingTimer; }
+  void SetDockingTimer(float t) { dockingTimer = t; }
   virtual void TimeStepUpdate(const float timeStep);
   virtual void NotifyDeath(const Body* const dyingBody);
 
@@ -55,6 +57,7 @@ private:
 
   float m_thrusters[ShipType::THRUSTER_MAX];
   float m_angThrusters[3];
+  float dockingTimer;
   dGeomID m_tempLaserGeom[ShipType::GUNMOUNT_MAX];
 
   LaserObj m_laserCollisionObj;
diff --git a/src/ship_cpanel.cpp b/src/ship_cpanel.cpp
index ee06ec5..d4fa6cf 100644
--- a/src/ship_cpanel.cpp
+++ b/src/ship_cpanel.cpp
@@ -5,8 +5,8 @@
 #include "player.h"
 #include "info_view.h"
 
-ShipCpanel::ShipCpanel(void) : Gui::Fixed(0, 0, 640, 64) {
-  //SetBgColor(1, 0, 0);
+ShipCpanel::ShipCpanel(void) : Gui::Fixed(640, 64) {
+  Gui::Screen::AddBaseWidget(this, 0, 0);
   SetTransparency(true);
 
   Gui::Image* img = new Gui::Image("icons/cpanel.png");
@@ -77,12 +77,31 @@ ShipCpanel::ShipCpanel(void) : Gui::Fixed(0, 0, 640, 64) {
   m_clock = new Gui::Label("");
   m_clock->SetColor(1, 0.7, 0);
   Add(m_clock, 2, 48);
+
+  tempMsg = new Gui::Label("");
+  Add(tempMsg, 170, 44);
+}
+
+void ShipCpanel::SetTemporaryMessage(Body* const sender, std::string msg) {
+  std::string str = "#0f0"+msg;
+  if(sender) {
+    str = std::string("'ca0")+"Message from "+sender->GetLabel()+":\n"+str;
+  }
+  tempMsg->SetText(str);
+  tempMsgAge = L3D::GetGameTime();
 }
 
 void ShipCpanel::Draw(void) {
   std::string time = date_format(L3D::GetGameTime());
   m_clock->SetText(time);
 
+  if(tempMsgAge) {
+    if(L3D::GetGameTime() - tempMsgAge > 5.0) {
+      tempMsg->SetText("");
+      tempMsgAge = 0;
+    }
+  }
+
   Gui::Fixed::Draw();
   Remove(m_scannerWidget);
 }
diff --git a/src/ship_cpanel.h b/src/ship_cpanel.h
index f619df9..d87f564 100644
--- a/src/ship_cpanel.h
+++ b/src/ship_cpanel.h
@@ -2,11 +2,14 @@
 #include "libs.h"
 #include "gui.h"
 
+class Body;
+
 class ShipCpanel : public Gui::Fixed {
 public:
   ShipCpanel(void);
   virtual void Draw(void);
   void SetScannerWidget(Widget* w); /* Must be done each frame. */
+  void SetTemporaryMessage(Body* const sender, std::string msg);
 private:
   void OnChangeCamView(Gui::MultiStateImageButton* b);
   void OnChangeMapView(Gui::MultiStateImageButton* b);
@@ -16,5 +19,8 @@ private:
 
   Widget* m_scannerWidget;
   Gui::Label* m_clock;
+
+  Gui::Label* tempMsg;
+  float tempMsgAge;
 };
 
diff --git a/src/space_station.cpp b/src/space_station.cpp
index 5b5bb79..ce8d485 100644
--- a/src/space_station.cpp
+++ b/src/space_station.cpp
@@ -57,7 +57,6 @@ void SpaceStation::GetDockingSurface(CollMeshSet* mset, int midx) {
 }
 
 SpaceStation::SpaceStation(void) : ModelBody() {
-  allowDocking = true;
   SetModel(STATION_SBRE_MODEL);
   matrix4x4d m = matrix4x4d::RotateYMatrix(M_PI-M_PI/6);
   SetRotation(m);
@@ -83,13 +82,17 @@ SpaceStation::~SpaceStation(void) {
 
 }
 
+bool SpaceStation::GetDockingClearance(Ship* s) {
+  s->SetDockingTimer(68*10);
+  return true;
+}
+
 bool SpaceStation::OnCollision(Body* b, Uint32 flags) {
   if(flags == 1) {
     /* Hitting docking area of a station. */
     if(b->GetType() == Object::SHIP) {
       Ship* s = static_cast<Ship*>(b);
-      if(!s->GetDockedWith() && allowDocking) {
-        allowDocking = false;
+      if((!s->GetDockedWith()) && (s->GetDockingTimer() != 0.0f)) {
         s->Disable();
         s->SetDockedWith(this);
         printf("Docking!\n");
diff --git a/src/space_station.h b/src/space_station.h
index d839ede..cae27cc 100644
--- a/src/space_station.h
+++ b/src/space_station.h
@@ -3,6 +3,7 @@
 #include "model_body.h"
 
 class CollMeshSet;
+class Ship;
 
 class SpaceStation : public ModelBody {
 public:
@@ -12,13 +13,11 @@ public:
   virtual Object::Type GetType(void) { return Object::SPACESTATION; }
   virtual void Render(const Frame* camFrame);
   void GetDockingSurface(CollMeshSet* mset, int midx);
+  bool GetDockingClearance(Ship* s);
   struct dockingport_t {
     vector3d center;
     vector3d normal;
     vector3d horiz;
   } port;
-
-private:
-  bool allowDocking;
 };
 
diff --git a/src/view.h b/src/view.h
index 281aa6c..3f743a2 100644
--- a/src/view.h
+++ b/src/view.h
@@ -11,12 +11,16 @@
  */
  class View : public Gui::Fixed {
  public:
-  View(void) : Gui::Fixed(0, 64, 640, 416) {
-    m_rightButtonBar = new Gui::Fixed(512, 0, 128, 26);
-    m_rightButtonBar->SetBgColor(.65, .65, .65);
+  View(void) : Gui::Fixed(640, 416) {
+    Gui::Screen::AddBaseWidget(this, 0, 64);
 
-    m_rightRegion2 = new Gui::Fixed(517, 26, 122, 17);
+    m_rightButtonBar = new Gui::Fixed(128, 26);
+    m_rightButtonBar->SetBgColor(.65, .65, .65);
+    Gui::Screen::AddBaseWidget(m_rightButtonBar, 512, 0);
+
+    m_rightRegion2 = new Gui::Fixed(122, 17);
     m_rightRegion2->SetTransparency(true);
+    Gui::Screen::AddBaseWidget(m_rightRegion2, 517, 26);
   }
   virtual ~View(void) { delete m_rightButtonBar; delete m_rightRegion2; }
   virtual void ShowAll(void) {
diff --git a/src/world_view.cpp b/src/world_view.cpp
index 2cf478d..052d464 100644
--- a/src/world_view.cpp
+++ b/src/world_view.cpp
@@ -3,6 +3,8 @@
 #include "frame.h"
 #include "player.h"
 #include "space.h"
+#include "space_station.h"
+#include "ship_cpanel.h"
 
 static const float lightCol[] = { 1, 1, .9, 0 };
 const float WorldView::PICK_OBJECT_RECT_SIZE = 20.0f;
@@ -10,7 +12,14 @@ const float WorldView::PICK_OBJECT_RECT_SIZE = 20.0f;
 #define BG_STAR_MAX 5000
 
 WorldView::WorldView(void): View() {
+  float size[2];
+  GetSize(size);
+
   SetTransparency(true);
+
+  commsOptions = new Fixed(size[0], size[1]/2);
+  commsOptions->SetTransparency(true);
+  Add(commsOptions, 10, 20);
   
   Gui::MultiStateImageButton* wheels_button = new Gui::MultiStateImageButton();
   wheels_button->SetShortcut(SDLK_F7, KMOD_NONE);
@@ -114,24 +123,68 @@ void WorldView::Update(void) {
   /* Player control inputs. */
   if(L3D::player)
     L3D::player->PollControls();
+
+  Body* target = L3D::player->GetNavTarget();
+  if(target) {
+    commsOptions->ShowAll();
+  } else {
+    //commsOptions->HideAll();
+  }
 }
 
-void WorldView::OnMouseDown(Gui::MouseButtonEvent* e) {
-  if(1 == e->button && !L3D::MouseButtonState(3)) {
-    /* Left click in view when RMB not pressed => Select target. */
-    float screenPos[2];
-    GetPosition(screenPos);
-    /* Put mouse coords into screen space. */
-    screenPos[0] += e->x;
-    screenPos[1] += e->y;
-    Body* const target = PickBody(screenPos[0], screenPos[1]);
-    if(L3D::player) {
-      /* TODO: If in nav mode, SetNavTarget(), else SetCombatTarget(). */
-      L3D::player->SetNavTarget(target);
+Gui::Button* WorldView::AddCommsOption(std::string msg, int ypos) {
+  Gui::Label* l  = new Gui::Label(msg);
+  commsOptions->Add(l, 50, ypos);
+
+  Gui::TransparentButton* b = new Gui::TransparentButton();
+  commsOptions->Add(b, 16, ypos);
+  return b;
+}
+
+static void PlayerRequestDockingClearance(SpaceStation* s) {
+  s->GetDockingClearance(L3D::player);
+  L3D::cpan->SetTemporaryMessage(s, "Docking clearance granted.");
+}
+
+void WorldView::UpdateCommsOptions(void) {
+  Body* const navtarget = L3D::player->GetNavTarget();
+  commsOptions->DeleteAllChildren();
+
+  float size[2];
+  commsOptions->GetSize(size);
+  int ypos = size[1]-16;
+  if(navtarget) {
+    if(navtarget->GetType() == Object::SPACESTATION) {
+      commsOptions->Add(new Gui::Label(navtarget->GetLabel()), 16, ypos);
+      ypos -= 32;
+      Gui::Button* b = AddCommsOption("Request docking clearance", ypos);
+      b->onClick.connect(sigc::bind(sigc::ptr_fun(&PlayerRequestDockingClearance), (SpaceStation*)navtarget));
+      ypos -= 32;
+    } else {
+      commsOptions->Add(new Gui::Label(navtarget->GetLabel()), 16, ypos);
+      ypos -= 32;
+      std::string msg = "Do something to "+navtarget->GetLabel();
+      Gui::Button* b = AddCommsOption(msg, ypos);
+      ypos -= 32;
     }
   }
 }
 
+bool WorldView::OnMouseDown(Gui::MouseButtonEvent* e) {
+  /* If continuing to propagate mouse event, see if target is clicked on. */
+  if(Container::OnMouseDown(e)) {
+    if(1 == e->button && !L3D::MouseButtonState(3)) {
+      /* Left click in view when RMB not pressed => Select target. */
+      Body* const target = PickBody(e->screenX, e->screenY);
+      if(L3D::player) {
+        /* TODO: If in nav mode, SetNavTarget(), else SetCombatTarget(). */
+        L3D::player->SetNavTarget(target);
+      }
+    }
+  }
+  return true;
+}
+
 Body* WorldView::PickBody(const float screenX, const float screenY) const {
   Body* selected = 0;
 
diff --git a/src/world_view.h b/src/world_view.h
index 5d0e54a..31552e0 100644
--- a/src/world_view.h
+++ b/src/world_view.h
@@ -12,12 +12,15 @@ public:
   virtual void Draw3D(void);
   matrix4x4d viewingRotation;
   static const float PICK_OBJECT_RECT_SIZE;
+  void UpdateCommsOptions(void);
 private:
+  Gui::Button* AddCommsOption(const std::string msg, int ypos);
   void OnClickHyperspace(void);
   void OnChangeWheelsState(Gui::MultiStateImageButton* b);
-  virtual void OnMouseDown(Gui::MouseButtonEvent* e);
+  virtual bool OnMouseDown(Gui::MouseButtonEvent* e);
   Body* PickBody(const float screenX, const float screenY) const;
   Gui::ImageButton* m_hyperspaceButton;
   GLuint m_bgstarsDlist;
+  Gui::Fixed* commsOptions;
 };