Index: code/branches/chat2/data/defaultConfig/keybindings.ini
===================================================================
--- code/branches/chat2/data/defaultConfig/keybindings.ini	(revision 6835)
+++ code/branches/chat2/data/defaultConfig/keybindings.ini	(revision 6836)
@@ -7,5 +7,5 @@
 KeyApostrophe=
 KeyApps=
-KeyB=
+KeyB =
 KeyBack=
 KeyBackslash=
Index: code/branches/chat2/data/gui/layouts/ChatBox.layout
===================================================================
--- code/branches/chat2/data/gui/layouts/ChatBox.layout	(revision 6836)
+++ code/branches/chat2/data/gui/layouts/ChatBox.layout	(revision 6836)
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="DefaultWindow" Name="Root" >
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Window Type="TaharezLook/FrameWindow" Name="/ChatBox" >
+            <Property Name="Text" Value="Chat" />
+            <Property Name="TitlebarFont" Value="Commonwealth-10" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="TitlebarEnabled" Value="True" />
+            <Property Name="UnifiedAreaRect" Value="{{0.01,0},{0.03,0},{0.6,0},{0.69375,0}}" />
+            <Window Type="TaharezLook/Listbox" Name="/ChatBox/List" >
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.02,0},{0.078,0},{0.98,0},{1,-30}}" />
+            </Window>
+            <Window Type="TaharezLook/Editbox" Name="/ChatBox/Text" >
+                <Property Name="Text" Value="Error: you did not register any font or none were valid" />
+                <Property Name="MaxTextLength" Value="1073741823" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.02,0},{1,-30},{0.98,0},{1,-5}}" />
+            </Window>
+        </Window>
+        <Window Type="TaharezLook/Editbox" Name="/ChatBox/History" >
+            <Property Name="Text" Value="5" />
+            <Property Name="MaxTextLength" Value="1073741823" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.77,0},{0.03,0},{0.81,0},{0.1,0}}" />
+        </Window>
+        <Window Type="TaharezLook/StaticText" Name="/ChatBox/HistoryLabel" >
+            <Property Name="Text" Value="History size:" />
+            <Property Name="HorzFormatting" Value="RightAligned" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.65,0},{0.03,0},{0.77,0},{0.1,0}}" />
+        </Window>
+        <Window Type="TaharezLook/StaticText" Name="/ChatBox/FonSizeLabel" >
+            <Property Name="Font" Value="Commonwealth-10" />
+            <Property Name="Text" Value="Font size:" />
+            <Property Name="HorzFormatting" Value="RightAligned" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.65,0},{0.1,0},{0.77,0},{0.17,0}}" />
+        </Window>
+        <Window Type="TaharezLook/Spinner" Name="/ChatBox/FontSize" >
+            <Property Name="Text" Value="10" />
+            <Property Name="StepSize" Value="1" />
+            <Property Name="CurrentValue" Value="10" />
+            <Property Name="MaximumValue" Value="72" />
+            <Property Name="MinimumValue" Value="-32768" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.77,0},{0.1,0},{0.83,0},{0.17,0}}" />
+        </Window>
+        <Window Type="TaharezLook/StaticText" Name="/ChatBox/FontNameLabel" >
+            <Property Name="Font" Value="Commonwealth-10" />
+            <Property Name="Text" Value="Font name:" />
+            <Property Name="HorzFormatting" Value="RightAligned" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.65,0},{0.17,0},{0.77,0},{0.24,0}}" />
+        </Window>
+        <Window Type="TaharezLook/Combobox" Name="/ChatBox/FontName" >
+            <Property Name="Text" Value="ChatBoxFont" />
+            <Property Name="ReadOnly" Value="True" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.77,0},{0.17,0},{0.99,0},{0.45,0}}" />
+            <Property Name="MaxEditTextLength" Value="1073741823" />
+        </Window>
+    </Window>
+</GUILayout>
Index: code/branches/chat2/src/libraries/network/ChatListener.cc
===================================================================
--- code/branches/chat2/src/libraries/network/ChatListener.cc	(revision 6835)
+++ code/branches/chat2/src/libraries/network/ChatListener.cc	(revision 6836)
@@ -36,4 +36,14 @@
         RegisterRootObject(ChatListener);
     }
+
+    //void ChatListener::incomingChat( const std::string& message,
+      //unsigned int senderID )
+    //{
+      //COUT(0) << "Chat: \"" << message << "\"\n";
+
+
+    //}
+
+
 }
 
Index: code/branches/chat2/src/libraries/network/ChatListener.h
===================================================================
--- code/branches/chat2/src/libraries/network/ChatListener.h	(revision 6835)
+++ code/branches/chat2/src/libraries/network/ChatListener.h	(revision 6836)
@@ -38,7 +38,9 @@
     {
         public:
+	    /* constructor, destructor */
             ChatListener();
             virtual ~ChatListener() {}
 
+            /* What to do with incoming chat */
             virtual void incomingChat(const std::string& message, unsigned int senderID) = 0;
     };
Index: code/branches/chat2/src/libraries/network/Host.h
===================================================================
--- code/branches/chat2/src/libraries/network/Host.h	(revision 6835)
+++ code/branches/chat2/src/libraries/network/Host.h	(revision 6836)
@@ -49,5 +49,5 @@
 class _NetworkExport Host{
   private:
-    //TODO add theese functions or adequate
+    //TODO add these functions or adequate
     //virtual bool processChat(packet::Chat *message, unsigned int clientID)=0;
     //virtual bool sendChat(packet::Chat *chat)=0;
Index: code/branches/chat2/src/libraries/network/packet/Chat.cc
===================================================================
--- code/branches/chat2/src/libraries/network/packet/Chat.cc	(revision 6835)
+++ code/branches/chat2/src/libraries/network/packet/Chat.cc	(revision 6836)
@@ -37,4 +37,6 @@
 
 #define   PACKET_FLAGS_CHAT PacketFlag::Reliable
+
+/* Some lengths */
 #define   _PACKETID         0
 const int _PLAYERID     =   _PACKETID + sizeof(Type::Value);
@@ -45,10 +47,20 @@
  : Packet()
 {
+  /* Add chat flag to packet flags */
   flags_ = flags_ | PACKET_FLAGS_CHAT;
+
+  /* set message length to length of input string + 1 */
   messageLength_ = message.length()+1;
+
+  /* allocate memory for the data */
   data_=new unsigned char[ getSize() ];
+
   *(Type::Value *)(data_ + _PACKETID ) = Type::Chat;
   *(unsigned int *)(data_ + _PLAYERID ) = playerID;
   *(unsigned int *)(data_ + _MESSAGELENGTH ) = messageLength_;
+
+  /* cast the hell out of the message string, and copy it into the 
+   * data buffer. 
+   */
   memcpy( data_+_MESSAGE, static_cast<void*>(const_cast<char*>(message.c_str())), messageLength_ );
 }
Index: code/branches/chat2/src/libraries/network/packet/Chat.h
===================================================================
--- code/branches/chat2/src/libraries/network/packet/Chat.h	(revision 6835)
+++ code/branches/chat2/src/libraries/network/packet/Chat.h	(revision 6836)
@@ -41,15 +41,29 @@
 {
 public:
+  /* constructors */
   Chat( const std::string& message, unsigned int playerID );
   Chat( uint8_t* data, unsigned int clientID );
+
+  /* destructor */
   ~Chat();
 
+  /* get size of packet */
   inline unsigned int getSize() const;
+
+  /* process chat message packet and remove it afterwards */
   bool process();
 
+  /* Get the length of the message (not the full size of the packet) */
   unsigned int getMessageLength(){ return messageLength_; };
+
+  /* return message content */
   unsigned char *getMessage();
+
 private:
+
+  /* Message length */
   uint32_t messageLength_;
+
+  /* Client ID (an integral value for identification) */
   unsigned int clientID_;
 };
Index: code/branches/chat2/src/orxonox/CMakeLists.txt
===================================================================
--- code/branches/chat2/src/orxonox/CMakeLists.txt	(revision 6835)
+++ code/branches/chat2/src/orxonox/CMakeLists.txt	(revision 6836)
@@ -32,4 +32,6 @@
   PlayerManager.cc
   Radar.cc
+  ChatHistory.cc
+  ChatInputHandler.cc
 COMPILATION_BEGIN SceneCompilation.cc
   CameraManager.cc
Index: code/branches/chat2/src/orxonox/ChatHistory.cc
===================================================================
--- code/branches/chat2/src/orxonox/ChatHistory.cc	(revision 6836)
+++ code/branches/chat2/src/orxonox/ChatHistory.cc	(revision 6836)
@@ -0,0 +1,189 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ChatHistory.h"
+#include <core/ScopedSingletonManager.h>
+
+#ifndef CHATTEST
+namespace orxonox
+{
+  /* singleton */
+  ManageScopedSingleton( ChatHistory, ScopeID::Root, false );
+#endif
+
+  /* constructor */
+#ifndef CHATTEST
+  //ChatHistory::ChatHistory( BaseObject* creator ) : BaseObject(creator) 
+  ChatHistory::ChatHistory() 
+#else
+  ChatHistory::ChatHistory()
+#endif
+  {
+    /* register the object */
+#ifndef CHATTEST
+    RegisterObject(ChatHistory);
+#endif
+
+    this->hist_log_enabled = true;
+
+    /* Read setting for logfiles */
+    if( hist_log_enabled ) /* NOTE Make this a check for the logfile setting */
+    { this->chat_hist_openlog();
+
+      /* push starting line */
+      this->chat_hist_logline( "--- Logfile opened ---" );
+    }
+
+    /* Read setting for maximum number of lines and set limit */
+    this->hist_maxlines = 200; /* NOTE to be changed, 200 is just for testing */
+  }
+
+  /* destructor */
+  ChatHistory::~ChatHistory()
+  {
+    chat_hist_closelog();
+    
+    /* clear list */
+    this->hist_buffer.clear();
+  }
+
+  /* react to incoming chat */
+  void ChatHistory::incomingChat(const std::string& message, 
+    unsigned int senderID)
+  {
+    /* --> a) look up the actual name of the sender */
+    std::string text;
+
+    COUT(0) << "Meow.\n";
+
+#ifndef CHATTEST
+    if (senderID != CLIENTID_UNKNOWN)
+    {
+       std::string name = "unknown";
+       PlayerInfo* player = PlayerManager::getInstance().getClient(senderID);
+       if (player)
+         name = player->getName();
+
+         text = name + ": " + message;
+    }
+    else
+      text = message;
+#else
+    text = message;
+#endif
+
+    /* add the line to the history */
+    this->chat_hist_addline( text );
+
+    /* add the line to the log */
+    this->chat_hist_logline( text );
+  } 
+
+  /* Synchronize logfile onto the hard drive */ /* MARK MARK */
+  int ChatHistory::syncLog()
+  {
+    //if( this->hist_logfile )
+      //this->hist_logfile.sync();
+    return 0;
+  }
+
+  /* add a line to this history */
+  int ChatHistory::chat_hist_addline( const std::string& toadd )
+  {
+    /* crop history at the end if it's too large */
+    while( this->hist_buffer.size() > this->hist_maxlines+1 )
+      this->hist_buffer.pop_front();
+
+    /* push to the front of the history */
+    this->hist_buffer.push_back( toadd );
+    return 0;
+  }
+
+  /* log a line to a logfile */
+  int ChatHistory::chat_hist_logline( const std::string& toadd )
+  { 
+    /* output the line to the file if logging is enabled */
+    if( this->hist_log_enabled )
+      this->hist_logfile << toadd << std::endl;
+    return 0;
+  }
+
+  /* open logfile */
+  int ChatHistory::chat_hist_openlog()
+  {
+    /* TODO: find out the name of the file to log to via settings 
+     *       and set the this->hist_logfile_path variable to it
+     */
+#ifndef CHATTEST
+    this->hist_logfile.open( (PathConfig::getInstance().getLogPathString() +
+      "chatlog.log").c_str(),
+      std::fstream::out | std::fstream::app );
+#else
+    this->hist_logfile.open( "/tmp/chatlog.log",
+      std::fstream::out | std::fstream::app );
+#endif
+
+    /* TODO check whether this works (not sure how you'd like it?) */
+    if( !this->hist_logfile )
+    { this->hist_log_enabled = false;
+#ifndef CHATTEST
+      COUT(2) << "Warning: Could not open logfile." << std::endl;
+#endif
+    }
+
+    /* if it worked */
+    return 0;
+  }
+
+  /* close logfile */
+  void ChatHistory::chat_hist_closelog()
+  {
+    if( this->hist_logfile )
+    { this->chat_hist_logline( "--- Logfile closed ---" );
+      this->hist_logfile.close();
+    }
+  }
+
+  /* output history for debugging */
+  void ChatHistory::debug_printhist()
+  {
+    /* create deque iterator */
+    std::deque<std::string>::iterator it;
+
+    /* output all the strings */
+    for( it = this->hist_buffer.begin(); it != this->hist_buffer.end();
+      ++it )
+      std::cout << *it << std::endl;
+
+    /* output size */
+    std::cout << "Size: " << hist_buffer.size() << std::endl;
+  }
+
+#ifndef CHATTEST
+}
+#endif
Index: code/branches/chat2/src/orxonox/ChatHistory.h
===================================================================
--- code/branches/chat2/src/orxonox/ChatHistory.h	(revision 6836)
+++ code/branches/chat2/src/orxonox/ChatHistory.h	(revision 6836)
@@ -0,0 +1,149 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include <deque>
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <cassert>
+
+/* define this if you're unit testing */
+//#define CHATTEST 
+
+#ifndef CHATTEST
+#include <OrxonoxPrereqs.h>
+#include <PlayerManager.h>
+#include <infos/PlayerInfo.h>
+#include <core/BaseObject.h>
+#include <network/ChatListener.h>
+#include <core/PathConfig.h>
+#include <util/Singleton.h>
+#endif
+
+#ifndef _ChatHistory_H__
+#define _ChatHistory_H__
+
+
+/* Class to implement chat history */
+#ifndef CHATTEST
+namespace orxonox
+{
+#endif
+
+  /* constructor */
+#ifndef CHATTEST
+  class _OrxonoxExport ChatHistory : public ChatListener,
+    public Singleton<ChatHistory>
+
+#else
+  class ChatHistory 
+#endif
+  {
+    public:
+      /* constructors, destructors */
+#ifndef CHATTEST
+      ChatHistory();
+      friend class Singleton<ChatHistory>;
+#else
+      ChatHistory();
+#endif
+      virtual ~ChatHistory();
+
+  
+    //protected:
+      /** what to do with incoming chat 
+       * 
+       * \param message The incoming message 
+       * \param senderID Identification number of the sender
+       */
+      virtual void incomingChat(const std::string& message, 
+        unsigned int senderID);
+      
+      /** Synchronize logfile onto the hard drive 
+       *
+       * \return 0 for success, other for error
+       */
+      int syncLog();
+
+      /** debug-print: output the whole history to stdout */
+      void debug_printhist();
+      
+    private:
+      /* FIELDS */
+      /** Vector to store the history in */
+      std::deque<std::string> hist_buffer;
+
+      /** Maximum number of lines stored in this history */
+      unsigned int hist_maxlines;
+
+      /** is logging enabled? */
+      bool hist_log_enabled;
+
+      /** path of logfile on the file system */
+      std::string hist_logfile_path;
+
+      /** Output file stream for logfile */
+      std::ofstream hist_logfile;
+
+#ifndef CHATTEST
+      static ChatHistory* singletonPtr_s;
+#endif
+
+
+
+      /* METHODS */
+      /** Append line to chat history
+       *
+       * \param toadd The line to add to the history
+       * \return 0 for success, other for error TODO: Throw exception
+       */
+      int chat_hist_addline( const std::string& toadd );
+
+      /** Append line to logfile
+       *
+       * \param toadd The line to add to the logfile
+       * \return 0 for success, other for error TODO: Throw exception
+       */
+      int chat_hist_logline( const std::string& toadd );
+
+      /** open logfile to log to
+       *
+       * \return 0 for success,s other for error
+       */
+      int chat_hist_openlog();
+
+
+      /** close logfile */
+      void chat_hist_closelog();
+  };
+
+#ifndef CHATTEST
+}
+#endif
+
+#endif /* _ChatHistory_H__ */
Index: code/branches/chat2/src/orxonox/ChatInputHandler.cc
===================================================================
--- code/branches/chat2/src/orxonox/ChatInputHandler.cc	(revision 6836)
+++ code/branches/chat2/src/orxonox/ChatInputHandler.cc	(revision 6836)
@@ -0,0 +1,186 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ChatInputHandler.h"
+#include <core/ScopedSingletonManager.h>
+#include "core/ConsoleCommand.h"
+#include "core/CoreIncludes.h"
+#include <string>
+
+namespace orxonox 
+{
+  /* singleton */
+  ManageScopedSingleton( ChatInputHandler, ScopeID::Graphics, false );
+  SetConsoleCommandAlias( ChatInputHandler, activate_static, "startchat",
+    true );
+
+  /* constructor */
+  ChatInputHandler::ChatInputHandler()
+  {
+    /* register the object  */
+    RegisterObject(ChatInputHandler);
+
+    /* create necessary objects */
+    this->inpbuf = new InputBuffer();
+
+    /* configure the input buffer */
+    configureInputBuffer();
+
+    this->inputState = InputManager::getInstance().createInputState( "chatinput", false, false, InputStatePriority::Dynamic );
+    this->inputState->setKeyHandler(this->inpbuf);
+
+    //[> set console shortcut <]
+    //this->getIdentifier()->addConsoleCommand(createConsoleCommand(createFunctor(
+      //&ChatInputHandler::activate, this), "startchat"), false);
+  }
+
+  void ChatInputHandler::configureInputBuffer()
+  {
+	  /* input has changed */
+    this->inpbuf->registerListener(this, &ChatInputHandler::inputChanged, true);
+		
+		/* add a line */
+    this->inpbuf->registerListener(this, &ChatInputHandler::addline,         '\r',   false);
+    this->inpbuf->registerListener(this, &ChatInputHandler::addline,         '\n',   false);
+
+		/* backspace */
+    this->inpbuf->registerListener(this, &ChatInputHandler::backspace,       '\b',   true);
+    this->inpbuf->registerListener(this, &ChatInputHandler::backspace,       '\177', true);
+
+		/* exit the chatinputhandler thingy (tbd) */
+    this->inpbuf->registerListener(this, &ChatInputHandler::exit,            '\033', true); // escape
+
+		/* delete character */
+    this->inpbuf->registerListener(this, &ChatInputHandler::deleteChar,      KeyCode::Delete);
+
+		/* cursor movement */
+    this->inpbuf->registerListener(this, &ChatInputHandler::cursorRight,     KeyCode::Right);
+    this->inpbuf->registerListener(this, &ChatInputHandler::cursorLeft,      KeyCode::Left);
+    this->inpbuf->registerListener(this, &ChatInputHandler::cursorEnd,       KeyCode::End);
+    this->inpbuf->registerListener(this, &ChatInputHandler::cursorHome,      KeyCode::Home);
+  }
+
+
+  /* activate, deactivate */
+  void ChatInputHandler::activate_static()
+  { ChatInputHandler::getInstance().activate(); }
+  
+  void ChatInputHandler::activate()
+  {
+    /* start listening */
+    COUT(0) << "chatinput activated." << std::endl;
+    InputManager::getInstance().enterState("chatinput");
+  }
+
+  void ChatInputHandler::deactivate() 
+  {
+    /* stop listening */
+    InputManager::getInstance().leaveState("chatinput");
+  }
+
+
+
+  /* callbacks for InputBuffer */
+  void ChatInputHandler::inputChanged()
+  {
+    //this->updateListeners<&ShellListener::inputChanged>();
+    //this->updateListeners<&ShellListener::cursorChanged>();
+  }
+
+  void ChatInputHandler::addline()
+  {
+    /* MARK MARK */
+
+    /* actually do send what was input */
+    /* a) get the string out of the inputbuffer */
+    std::string msgtosend = this->inpbuf->get();
+
+    /* b) clear the input buffer */
+    if (this->inpbuf->getSize() > 0)
+      this->inpbuf->clear();
+
+    /* c) send the chat via some call */
+    Host::Chat( msgtosend );
+
+    /* d) stop listening to input  */
+    this->deactivate();
+  }
+
+  void ChatInputHandler::backspace()
+  {
+    this->inpbuf->removeBehindCursor();
+    //this->updateListeners<&ShellListener::inputChanged>();
+    //this->updateListeners<&ShellListener::cursorChanged>();
+  }
+
+  void ChatInputHandler::deleteChar()
+  {
+    this->inpbuf->removeAtCursor();
+    //this->updateListeners<&ShellListener::inputChanged>();
+  }
+
+  void ChatInputHandler::cursorRight()
+  {
+    this->inpbuf->increaseCursor();
+    //this->updateListeners<&ShellListener::cursorChanged>();
+  }
+  
+  void ChatInputHandler::cursorLeft()
+  {
+    this->inpbuf->decreaseCursor();
+    //this->updateListeners<&ShellListener::cursorChanged>();
+  }
+  
+  void ChatInputHandler::cursorEnd()
+  {
+    this->inpbuf->setCursorToEnd();
+    //this->updateListeners<&ShellListener::cursorChanged>();
+  }
+
+  void ChatInputHandler::cursorHome()
+  {
+    this->inpbuf->setCursorToBegin();
+    //this->updateListeners<&ShellListener::cursorChanged>();
+  }
+
+  void ChatInputHandler::exit()
+  {
+    //if (this->inpbuf->getSize() > 0)
+    //{
+      //this->clearInput();
+      //return;
+    //}
+
+    //this->clearInput();
+    //this->scrollPosition_ = 0;
+    //this->scrollIterator_ = this->outputLines_.begin();
+
+    //this->updateListeners<&ShellListener::exit>();
+  }
+
+}
Index: code/branches/chat2/src/orxonox/ChatInputHandler.h
===================================================================
--- code/branches/chat2/src/orxonox/ChatInputHandler.h	(revision 6836)
+++ code/branches/chat2/src/orxonox/ChatInputHandler.h	(revision 6836)
@@ -0,0 +1,99 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ChatInputHandler_H__
+#define _ChatInputHandler_H__
+
+/* std includes */
+#include <deque>
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <cassert>
+
+/* project includes */
+#include <OrxonoxPrereqs.h>
+#include <core/BaseObject.h>
+#include <core/PathConfig.h>
+
+#include "core/input/InputBuffer.h"
+#include "core/input/InputManager.h"
+#include "core/input/InputState.h"
+
+#include "../libraries/network/Host.h"
+#include <util/Singleton.h>
+
+
+namespace orxonox
+{
+  /* class to handle chat using an InputBuffer */
+  class _OrxonoxExport ChatInputHandler : public Singleton<ChatInputHandler>,
+    public OrxonoxClass
+  {
+    private:
+      /** Input buffer, to be used to catch input from the
+       * keyboard 
+       */
+      InputBuffer *inpbuf;
+
+      /** input state */
+      InputState *inputState;
+
+      /** setup input buffer, the constructor calls this */
+      void configureInputBuffer();
+
+      /* singleton pointer */
+      static ChatInputHandler* singletonPtr_s;
+
+    public:
+      /** constructor */
+      ChatInputHandler();
+      friend class Singleton<ChatInputHandler>;
+
+      /* start listening, stop listening */
+      static void activate_static();
+      void activate();
+      void deactivate();
+
+      /* callbacks for input handler */
+      void inputChanged();
+      void addline();
+      void backspace();
+      void deleteChar();
+      void cursorRight();
+      void cursorLeft();
+      void cursorEnd();
+      void cursorHome();
+      void exit();
+  };
+
+
+}
+
+
+#endif /*_ChatInputHandler_H__*/
Index: code/branches/chat2/src/orxonox/graphics/CEGuiSample.cc
===================================================================
--- code/branches/chat2/src/orxonox/graphics/CEGuiSample.cc	(revision 6836)
+++ code/branches/chat2/src/orxonox/graphics/CEGuiSample.cc	(revision 6836)
@@ -0,0 +1,304 @@
+/***********************************************************************
+    filename:   CEGuiSample.cpp
+    created:    24/9/2004
+    author:     Paul D Turner
+*************************************************************************/
+/***************************************************************************
+ *   Copyright (C) 2004 - 2008 Paul D Turner & The CEGUI Development Team
+ *
+ *   Permission is hereby granted, free of charge, to any person obtaining
+ *   a copy of this software and associated documentation files (the
+ *   "Software"), to deal in the Software without restriction, including
+ *   without limitation the rights to use, copy, modify, merge, publish,
+ *   distribute, sublicense, and/or sell copies of the Software, and to
+ *   permit persons to whom the Software is furnished to do so, subject to
+ *   the following conditions:
+ *
+ *   The above copyright notice and this permission notice shall be
+ *   included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ ***************************************************************************/
+#include "CEGuiSample.h"
+
+#ifdef HAVE_CONFIG_H
+#   include "config.h"
+#endif
+#include "CEGUISamplesConfig.h"
+
+// includes for renderer selector classes
+#if defined( __WIN32__ ) || defined( _WIN32 )
+#   include "Win32CEGuiRendererSelector.h"
+#elif defined(__linux__)
+#   ifdef CEGUI_SAMPLES_USE_GTK2
+#       include "GTK2CEGuiRendererSelector.h"
+#   else
+#       include "CLICEGuiRendererSelector.h"
+#   endif
+#elif defined(__APPLE__)
+#   include "MacCEGuiRendererSelector.h"
+#endif
+
+// includes for application types
+#ifdef CEGUI_SAMPLES_USE_OGRE
+#   include "CEGuiOgreBaseApplication.h"
+#endif
+#ifdef CEGUI_SAMPLES_USE_OPENGL
+#   include "CEGuiOpenGLBaseApplication.h"
+#endif
+#ifdef CEGUI_SAMPLES_USE_IRRLICHT
+#   include "CEGuiIrrlichtBaseApplication.h"
+#endif
+#ifdef CEGUI_SAMPLES_USE_DIRECTFB
+#   include "CEGuiDirectFBBaseApplication.h"
+#endif
+#if defined( __WIN32__ ) || defined( _WIN32 )
+#   ifdef CEGUI_SAMPLES_USE_DIRECTX_8
+#       include "CEGuiD3D81BaseApplication.h"
+#   endif
+#   ifdef CEGUI_SAMPLES_USE_DIRECTX_9
+#       include "CEGuiD3D9BaseApplication.h"
+#   endif
+#   ifdef CEGUI_SAMPLES_USE_DIRECTX_10
+#       include "CEGuiD3D10BaseApplication.h"
+#   endif
+#endif
+// now we include the base CEGuiBaseApplication just in case someone has managed to
+// get this far without any of the renderers.  This ensures the framework will build,
+// although there will be no renderers available for selection in the samples.
+#include "CEGuiBaseApplication.h"
+
+#include "CEGUI.h"
+
+#ifdef CEGUI_WITH_XERCES
+#   include "CEGUIXercesParser.h"
+#endif
+
+// Include iostream if not on windows.
+#if defined( __WIN32__ ) || defined( _WIN32 )
+#else
+#    include <iostream>
+#endif
+
+
+/*************************************************************************
+    Constructor
+*************************************************************************/
+CEGuiSample::CEGuiSample() :
+        d_rendererSelector(0),
+        d_sampleApp(0)
+{}
+
+
+/*************************************************************************
+    Destructor
+*************************************************************************/
+CEGuiSample::~CEGuiSample()
+{
+    if (d_sampleApp)
+    {
+        d_sampleApp->cleanup();
+        delete d_sampleApp;
+    }
+
+    if (d_rendererSelector)
+    {
+        delete d_rendererSelector;
+    }
+
+}
+
+
+/*************************************************************************
+    Application entry point
+*************************************************************************/
+int CEGuiSample::run()
+{
+    try
+    {
+        if (initialise())
+            cleanup();
+    }
+    catch (CEGUI::Exception& exc)
+    {
+        outputExceptionMessage(exc.getMessage().c_str());
+    }
+    catch (std::exception& exc)
+    {
+        outputExceptionMessage(exc.what());
+    }
+    catch(...)
+    {
+        outputExceptionMessage("Unknown exception was caught!");
+    }
+
+    return 0;
+}
+
+
+/*************************************************************************
+    Initialise the sample application
+*************************************************************************/
+bool CEGuiSample::initialise()
+{
+    // Setup renderer selection dialog for Win32
+#if defined( __WIN32__ ) || defined( _WIN32 )
+    d_rendererSelector = new Win32CEGuiRendererSelector;
+
+    // enable renderer types supported for Win32
+#ifdef CEGUI_SAMPLES_USE_DIRECTX_8
+    d_rendererSelector->setRendererAvailability(Direct3D81GuiRendererType);
+#endif
+#ifdef CEGUI_SAMPLES_USE_DIRECTX_9
+    d_rendererSelector->setRendererAvailability(Direct3D9GuiRendererType);
+#endif
+#ifdef CEGUI_SAMPLES_USE_DIRECTX_10
+    d_rendererSelector->setRendererAvailability(Direct3D10GuiRendererType);
+#endif
+
+#elif defined(__linux__)
+    // decide which method to use for renderer selection
+#   ifdef CEGUI_SAMPLES_USE_GTK2
+        d_rendererSelector = new GTK2CEGuiRendererSelector();
+#   else
+        d_rendererSelector = new CLICEGuiRendererSelector();
+#   endif
+
+#elif defined(__APPLE__)
+     d_rendererSelector = new MacCEGuiRendererSelector();
+#endif
+
+    // enable available renderer types
+#ifdef CEGUI_SAMPLES_USE_OGRE
+    d_rendererSelector->setRendererAvailability(OgreGuiRendererType);
+#endif
+#ifdef CEGUI_SAMPLES_USE_OPENGL
+    d_rendererSelector->setRendererAvailability(OpenGLGuiRendererType);
+#endif
+#ifdef CEGUI_SAMPLES_USE_IRRLICHT
+    d_rendererSelector->setRendererAvailability(IrrlichtGuiRendererType);
+#endif
+#ifdef CEGUI_SAMPLES_USE_DIRECTFB
+    d_rendererSelector->setRendererAvailability(DirectFBGuiRendererType);
+#endif
+
+    // get selection from user
+    if (d_rendererSelector->invokeDialog())
+    {
+        // create appropriate application type based upon users selection
+        switch(d_rendererSelector->getSelectedRendererType())
+        {
+#ifdef CEGUI_SAMPLES_USE_OGRE
+        case OgreGuiRendererType:
+            d_sampleApp = new CEGuiOgreBaseApplication();
+            break;
+#endif
+#if defined( __WIN32__ ) || defined( _WIN32 )
+#ifdef CEGUI_SAMPLES_USE_DIRECTX_8
+        case Direct3D81GuiRendererType:
+            d_sampleApp = new CEGuiD3D81BaseApplication();
+            break;
+#endif
+#ifdef CEGUI_SAMPLES_USE_DIRECTX_9
+        case Direct3D9GuiRendererType:
+            d_sampleApp = new CEGuiD3D9BaseApplication();
+            break;
+#endif // DX9
+#ifdef CEGUI_SAMPLES_USE_DIRECTX_10
+        case Direct3D10GuiRendererType:
+            d_sampleApp = new CEGuiD3D10BaseApplication();
+            break;
+#endif // DX10
+#endif // Win32
+#ifdef CEGUI_SAMPLES_USE_OPENGL
+        case OpenGLGuiRendererType:
+            d_sampleApp = new CEGuiOpenGLBaseApplication();
+            break;
+#endif
+#ifdef CEGUI_SAMPLES_USE_IRRLICHT
+        case IrrlichtGuiRendererType:
+            d_sampleApp = new CEGuiIrrlichtBaseApplication();
+            break;
+#endif
+#ifdef CEGUI_SAMPLES_USE_DIRECTFB
+        case DirectFBGuiRendererType:
+            d_sampleApp = new CEGuiDirectFBBaseApplication();
+            break;
+#endif
+
+        default:
+            throw CEGUI::GenericException("No renderer was selected!");
+            break;
+        }
+
+        // set the default resource groups to be used
+        CEGUI::Imageset::setDefaultResourceGroup("imagesets");
+        CEGUI::Font::setDefaultResourceGroup("fonts");
+        CEGUI::Scheme::setDefaultResourceGroup("schemes");
+        CEGUI::WidgetLookManager::setDefaultResourceGroup("looknfeels");
+        CEGUI::WindowManager::setDefaultResourceGroup("layouts");
+        CEGUI::ScriptModule::setDefaultResourceGroup("lua_scripts");
+#ifdef CEGUI_WITH_XERCES
+        CEGUI::XercesParser::setSchemaDefaultResourceGroup("schemas");
+#endif
+
+        // execute the base application (which sets up the demo via 'this' and runs it.
+        if (d_sampleApp->execute(this))
+        {
+            // signal that app initialised and ran
+            return true;
+        }
+
+        // sample app did not initialise, delete the object.
+        delete d_sampleApp;
+        d_sampleApp = 0;
+    }
+
+    // delete renderer selector object
+    delete d_rendererSelector;
+    d_rendererSelector = 0;
+
+    // signal app did not initialise and run.
+    return false;
+}
+
+
+/*************************************************************************
+    Cleanup the sample application.
+*************************************************************************/
+void CEGuiSample::cleanup()
+{
+    if (d_sampleApp)
+    {
+        d_sampleApp->cleanup();
+        delete d_sampleApp;
+        d_sampleApp = 0;
+    }
+
+    if (d_rendererSelector)
+    {
+        delete d_rendererSelector;
+        d_rendererSelector = 0;
+    }
+
+}
+
+
+/*************************************************************************
+    Output a message to the user in some OS independant way.
+*************************************************************************/
+void CEGuiSample::outputExceptionMessage(const char* message) const
+{
+#if defined(__WIN32__) || defined(_WIN32)
+    MessageBoxA(0, message, "CEGUI - Exception", MB_OK|MB_ICONERROR);
+#else
+    std::cout << "An exception was thrown within the sample framework:" << std::endl;
+    std::cout << message << std::endl;
+#endif
+}
Index: code/branches/chat2/src/orxonox/graphics/CEGuiSample.h
===================================================================
--- code/branches/chat2/src/orxonox/graphics/CEGuiSample.h	(revision 6836)
+++ code/branches/chat2/src/orxonox/graphics/CEGuiSample.h	(revision 6836)
@@ -0,0 +1,130 @@
+/***********************************************************************
+    filename:   CEGuiSample.h
+    created:    24/9/2004
+    author:     Paul D Turner
+*************************************************************************/
+/***************************************************************************
+ *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
+ *
+ *   Permission is hereby granted, free of charge, to any person obtaining
+ *   a copy of this software and associated documentation files (the
+ *   "Software"), to deal in the Software without restriction, including
+ *   without limitation the rights to use, copy, modify, merge, publish,
+ *   distribute, sublicense, and/or sell copies of the Software, and to
+ *   permit persons to whom the Software is furnished to do so, subject to
+ *   the following conditions:
+ *
+ *   The above copyright notice and this permission notice shall be
+ *   included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ ***************************************************************************/
+#ifndef _CEGuiSample_h_
+#define _CEGuiSample_h_
+
+#if (defined( __WIN32__ ) || defined( _WIN32 )) && !defined (CEGUI_STATIC)
+#   ifdef CEGUISAMPLE_EXPORTS
+#       define CEGUISAMPLE_API __declspec(dllexport)
+#   else
+#       define CEGUISAMPLE_API __declspec(dllimport)
+#   endif
+#else
+#       define CEGUISAMPLE_API
+#endif
+
+
+// forward declarations
+class CEGuiBaseApplication;
+class CEGuiRendererSelector;
+
+
+/*!
+\brief
+    This is a base class that is intended to be used for all sample applications.
+    Here we take care of common things such the renderer selection and application
+    startup.
+*/
+class CEGUISAMPLE_API CEGuiSample
+{
+public:
+    /*!
+    \brief
+        Constructor.
+    */
+    CEGuiSample();
+
+
+    /*!
+    \brief
+        Destructor.
+    */
+    virtual ~CEGuiSample();
+
+
+    /*!
+    \brief
+        Application entry point.
+
+    \return
+        code to be returned by the application.
+    */
+    int run();
+
+
+    /*!
+    \brief
+        Sample specific initialisation goes here.  This method is called by the application base object created
+        as part of the initialise call.
+
+    \return
+        false if something went wrong.
+    */
+    virtual bool initialiseSample()  = 0;
+
+
+    /*!
+    \brief
+        Cleans up resources allocated in the initialiseSample call.
+    */
+    virtual void cleanupSample() = 0;
+
+
+protected:
+    /*!
+    \brief
+        Initialises the sample system, this includes asking the user for a render to use and
+        the subsequent creation of the required systems to support that renderer.
+
+    \return
+        false if anything went wrong.
+    */
+    virtual bool initialise();
+
+
+    /*!
+    \brief
+        Cleans up all resources allocated by the initialise call.
+    */
+    virtual void cleanup();
+
+
+    /*!
+    \brief
+        Output a message to the user in some OS independant way.
+    */
+    void outputExceptionMessage(const char* message) const;
+
+    /*************************************************************************
+        Data fields
+    *************************************************************************/
+    CEGuiRendererSelector*  d_rendererSelector;     //!< Points to the renderer selector object.
+    CEGuiBaseApplication*   d_sampleApp;            //!< Pointer to the base application object.
+};
+
+#endif  // end of guard _CEGuiSample_h_
Index: code/branches/chat2/src/orxonox/graphics/ChatBox.cc
===================================================================
--- code/branches/chat2/src/orxonox/graphics/ChatBox.cc	(revision 6836)
+++ code/branches/chat2/src/orxonox/graphics/ChatBox.cc	(revision 6836)
@@ -0,0 +1,343 @@
+#include "ChatBox.h"
+
+#include "CEGuiSample.h"
+#include "CEGUI/CEGUI.h"
+#include "CEGUI/CEGUIXMLAttributes.h"
+
+bool ChatBox::initialiseSample()
+{
+  using namespace CEGUI;
+  try
+  {
+    // Retrieve the window manager
+    WindowManager& winMgr = WindowManager::getSingleton();
+
+    // Load the TaharezLook scheme and set up the default mouse cursor and font
+    SchemeManager::getSingleton().loadScheme("TaharezLook.scheme");
+    System::getSingleton().setDefaultMouseCursor("TaharezLook", "MouseArrow");
+    if(!FontManager::getSingleton().isFontPresent("Commonwealth-10"))
+      FontManager::getSingleton().createFont("Commonwealth-10.font");
+
+    // Set the GUI Sheet
+    Window* sheet = winMgr.createWindow("DefaultWindow", "root_wnd");
+    System::getSingleton().setGUISheet(sheet);
+
+    // Load a layout
+    Window* guiLayout = winMgr.loadWindowLayout("ChatBox.layout");
+    sheet->addChildWindow(guiLayout);
+
+    // Obtain the handles of some widgets
+    Window* historySize = winMgr.getWindow("/ChatBox/History");
+    Window* fontName = winMgr.getWindow("/ChatBox/FontName");
+    Spinner* fontSize = static_cast<Spinner*>(winMgr.getWindow("/ChatBox/FontSize"));
+    Window* chatText = winMgr.getWindow("/ChatBox/Text");
+
+    // Disable widgets until a valid font is registered
+    fontName->setEnabled(false);
+    fontSize->setEnabled(false);
+    chatText->setEnabled(false);
+
+    // Retrieve the design-specified values
+    mHistorySize = static_cast<size_t>(PropertyHelper::stringToUint(historySize->getText()));
+    mDefaultFontSize = fontSize->getText();
+    mChatFontName = fontName->getText();
+    setHistorySize(mHistorySize);
+    fontName->setText("");
+
+    // Configure the history size
+    // Pressing <ENTER> changes the maximal number of entries within the history Listbox
+    historySize->subscribeEvent(Editbox::EventTextAccepted,  Event::Subscriber(&ChatBox::Event_HistorySizeChange, this)); 
+
+    // Configure the text Editbox
+    // Pressing <ENTER> puts the text into the history Listbox
+    chatText->subscribeEvent(Editbox::EventTextAccepted,  Event::Subscriber(&ChatBox::Event_ChatTextAdded,  this)); 
+
+    // Configure the font name Combobox
+    // Selecting a name changes the font used in the history Listbox and the text Editbox
+    fontName->subscribeEvent(Combobox::EventTextChanged,  Event::Subscriber(&ChatBox::Event_FontChange,  this)); 
+
+    // Configure the font size Spinner
+    // Selecting a size changes the font size used in the history Listbox and the text Editbox
+    fontSize->subscribeEvent(Spinner::EventValueChanged,  Event::Subscriber(&ChatBox::Event_FontChange,  this)); 
+    fontSize->setTextInputMode(Spinner::Integer);
+    fontSize->setMinimumValue(4.0f);
+    fontSize->setMaximumValue(72.0f);
+    fontSize->setStepSize(1.0f);
+    fontSize->setCurrentValue(PropertyHelper::stringToFloat(mDefaultFontSize));
+
+    // Initialize the list of fonts
+    // The first registered font becomes the active font
+    registerFont("Commonwealth",  "Commonv2c.ttf");
+    registerFont("DejaVuSans",    "DejaVuSans.ttf");
+    registerFont("Iconified",    "Iconiv2.ttf");
+    registerFont("MissingFile",    "MissingFile.ttf");  // What happens if a font is missing?
+    registerFont("Pixmap Font",    "FairChar-30.font"); // And what about a non-Freetype font?
+  }
+  catch(Exception &e)
+  {
+    #if defined( __WIN32__ ) || defined( _WIN32 )
+      MessageBox(NULL, e.getMessage().c_str(), "Error initializing the demo", MB_OK | MB_ICONERROR | MB_TASKMODAL);
+    #else
+      //std::cout << "Error initializing the demo:" << e.getMessage().c_str() << "\n";
+    #endif
+  }
+
+  return true;
+}
+
+void ChatBox::cleanupSample(void)
+{
+}
+
+bool ChatBox::Event_HistorySizeChange(const CEGUI::EventArgs& args)
+{
+  using namespace CEGUI;
+
+  WindowManager& winMgr = WindowManager::getSingleton();
+  CEGUI::Window* historySize = winMgr.getWindow("/ChatBox/History");
+  int size = PropertyHelper::stringToInt( historySize->getText() );
+  setHistorySize(size);
+  return true;
+}
+
+bool ChatBox::Event_ChatTextAdded(const CEGUI::EventArgs& args)
+{
+  using namespace CEGUI;
+
+  WindowManager& winMgr = WindowManager::getSingleton();
+  Editbox* chatText = static_cast<Editbox*> (winMgr.getWindow("/ChatBox/Text"));
+  addChatText(chatText->getText());
+
+  // Clear the text in the Editbox
+  chatText->setText("");
+  return true;
+}
+
+bool ChatBox::Event_FontChange(const CEGUI::EventArgs& args)
+{
+  using namespace CEGUI;
+  WindowManager& winMgr = WindowManager::getSingleton();
+  Window* fontName = winMgr.getWindow("/ChatBox/FontName");
+  String name = fontName->getText();
+
+  Spinner* fontSize = static_cast<Spinner*>(winMgr.getWindow("/ChatBox/FontSize"));
+  String size = PropertyHelper::floatToString(fontSize->getCurrentValue());
+
+  Window* chatText = winMgr.getWindow("/ChatBox/Text");
+  chatText->setText(name + " - " + size);
+
+  changeFont(name, size);
+  return true;
+}
+
+void ChatBox::setHistorySize(const size_t& pSize)
+{
+  using namespace CEGUI;
+
+  if(pSize > 0)
+  {
+    // A better validation would be to enforce a minimal and a maximal size
+    mHistorySize = pSize;
+
+    WindowManager& winMgr = WindowManager::getSingleton();
+    Listbox* chatHistory = static_cast<Listbox*> (winMgr.getWindow("/ChatBox/List"));
+    ListboxItem* chatItem;
+    while(chatHistory->getItemCount() > mHistorySize)
+    {
+      // There are too many items within the history Listbox, purging them one at a time
+      chatItem = chatHistory->getListboxItemFromIndex(0);
+      chatHistory->removeItem(chatItem);
+    }
+  }
+}
+
+void ChatBox::addChatText(const CEGUI::String& pText)
+{
+  using namespace CEGUI;
+
+  WindowManager& winMgr = WindowManager::getSingleton();
+  Listbox* chatHistory = static_cast<Listbox*> (winMgr.getWindow("/ChatBox/List"));
+
+  // If there's text then add it
+  if(pText.size())
+  {
+    // Add the Editbox text to the history Listbox
+    ListboxTextItem* chatItem;
+    if(chatHistory->getItemCount() == mHistorySize)
+    {
+      /* We have reached the capacity of the Listbox so re-use the first Listbox item.
+         This code is a little crafty.  By default the ListboxTextItem is created with
+         the auto-delete flag set to true, which results in its automatic deletion when
+         removed from the Listbox.  So we change that flag to false, extract the item
+         from the Listbox, change its text, put the auto-delete flag back to true, and
+         finally put the item back into the Listbox. */
+      chatItem = static_cast<ListboxTextItem*>(chatHistory->getListboxItemFromIndex(0));
+      chatItem->setAutoDeleted(false);
+      chatHistory->removeItem(chatItem);
+      chatItem->setAutoDeleted(true);
+      chatItem->setText(pText);
+    }
+    else
+    {
+      // Create a new listbox item
+      chatItem = new ListboxTextItem(pText);
+    }
+    chatHistory->addItem(chatItem);
+    chatHistory->ensureItemIsVisible(chatHistory->getItemCount());
+  }
+}
+
+void ChatBox::registerFont(const CEGUI::String& pLogicalName, const CEGUI::String& pFileName)
+{
+  using namespace CEGUI;
+
+  // Ensure that font names are registered only once
+  if(mFontList.find(pLogicalName) == mFontList.end())
+  {
+    // Test the font so that only valid fonts are available
+    String testFont = mChatFontName;
+    if(mFontList.size() != 0)
+    {
+      // If the list is empty then attempt to create the font using the "real" font name
+      // Otherwise use a "test" font name so as not to corrupt the "real" one
+      testFont += "__test_font__";
+    }
+    Font* font = makeFont(testFont, pFileName, mDefaultFontSize);
+    if(mFontList.size() != 0 
+      && FontManager::getSingleton().isFontPresent(testFont))
+    {
+      // Since this was only a test font we destroy it
+      FontManager::getSingleton().destroyFont(testFont);
+    }
+    if(!font)
+    {
+      // This font is invalid
+      if(FontManager::getSingleton().isFontPresent(testFont))
+        return;
+      else
+      return;
+    }
+
+    WindowManager& winMgr = WindowManager::getSingleton();
+    Combobox* fontName = static_cast<Combobox*>(winMgr.getWindow("/ChatBox/FontName"));
+    mFontList[pLogicalName] = pFileName;
+    ListboxTextItem* fontNameItem = new ListboxTextItem(pLogicalName);
+    fontNameItem->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush");
+    fontName->addItem(fontNameItem);
+    if(fontName->getItemCount() == 1)
+    {
+      // Enable widgets now that at least one valid font has been found
+      Spinner* fontSize = static_cast<Spinner*>(winMgr.getWindow("/ChatBox/FontSize"));
+      Window* chatText = winMgr.getWindow("/ChatBox/Text");
+      fontName->setEnabled(true);
+      fontSize->setEnabled(true);
+      chatText->setEnabled(true);
+
+      // The first registered font becomes the active font
+      fontName->setText(pLogicalName); // This triggers a call to changeFont
+      fontName->setItemSelectState(fontNameItem, true);
+    }
+  }
+}
+
+CEGUI::Font* ChatBox::makeFont(const CEGUI::String& pFontName, const CEGUI::String& pFileName, const CEGUI::String& pSize)
+{
+  using namespace CEGUI;
+
+  Font* font;
+  try
+  {
+    if(FontManager::getSingleton().isFontPresent(pFontName))
+    {
+      // The chat font is reused rather than deleted and recreated
+      // every time an attribute changes.  For this reason it is
+      // important to use a unique logical name for the font.
+      font = FontManager::getSingleton().getFont(pFontName);
+      font->setProperty("FileName", pFileName);
+      font->setProperty("PointSize", pSize);
+    }
+    else
+    {
+      // This is the first time we make the chat font so we need to create it
+      XMLAttributes xmlAttributes;
+
+      // CEGUIFont.cpp
+      xmlAttributes.add("Name", pFontName);
+      xmlAttributes.add("Filename", pFileName);
+      xmlAttributes.add("ResourceGroup", "");
+      xmlAttributes.add("AutoScaled", "true");
+      xmlAttributes.add("NativeHorzRes", "800");
+      xmlAttributes.add("NativeVertRes", "600");
+
+      // CEGUIXMLAttributes.cpp
+      xmlAttributes.add("Size", pSize);
+      xmlAttributes.add("AntiAlias", "true");
+
+      font = FontManager::getSingleton().createFont("FreeType", xmlAttributes);
+    }
+    font->load();
+  }
+  catch(Exception& e)
+  {
+    // Display the error message in the chat window
+    //addChatText(e.getMessage());
+    font = 0;
+  }
+
+  return font;
+}
+
+void ChatBox::changeFont(const CEGUI::String& pFontLogicalName, const CEGUI::String& pFontSize)
+{
+  using namespace CEGUI;
+  WindowManager& winMgr = WindowManager::getSingleton();
+
+  if(!FontManager::getSingleton().isFontPresent(mChatFontName))
+  {
+    addChatText("You must call registerFont() at least once with a valid font");
+    return;
+  }
+
+  FontList::iterator itFontList = mFontList.find(pFontLogicalName);
+  if(itFontList == mFontList.end())
+  {
+    addChatText(pFontLogicalName + " has not been registered");
+    return;
+  }
+
+  // Measure the height of the selected font
+  Font* currentFont = makeFont(mChatFontName, (*itFontList).second, pFontSize);
+  float fontHeight = currentFont->getFontHeight();
+
+  /* Alter the area of the Editbox.  The original value is {{0.01,0},{1,-30},{0.99,0},{1,-5}}
+     The value we are altering is the "-30" within the second couplet, defining the position of
+     the upper y coordinate of the Editbox.  We base the new value on the position of the lower
+     y coordinate, which is "-5", and the height of the font.  To this we add some space "10" to
+     account for the Editbox's border. */
+  Editbox* editBox = static_cast<Editbox*> (winMgr.getWindow("/ChatBox/Text"));
+  URect chatTextArea = editBox->getArea();
+  chatTextArea.d_min.d_y.d_offset = chatTextArea.d_max.d_y.d_offset
+                  - fontHeight
+                  - 10;
+  editBox->setArea(chatTextArea);
+  editBox->setFont(currentFont);
+
+  /* Alther the area of the Listbox.  Here we only need the lower y coordinate.  Since this
+     value is the same as the upper y coordinate of the Editbox we do not need to calculate
+     it.  We also change the font of the Listbox and call upon handleUpdatedItemData() to
+     update the current Listbox items.  Finally we ensure that the last entry is still
+     visible. */
+  Listbox* listBox = static_cast<Listbox*> (winMgr.getWindow("/ChatBox/List"));
+  URect listTextArea = listBox->getArea();
+  listTextArea.d_max.d_y.d_offset = chatTextArea.d_min.d_y.d_offset;
+  listBox->setArea(listTextArea);
+  listBox->setFont(currentFont);
+  listBox->handleUpdatedItemData();
+  size_t itemCount = listBox->getItemCount();
+  if(itemCount)
+  {
+    ListboxItem* currentItem = listBox->getListboxItemFromIndex(itemCount - 1);
+    listBox->ensureItemIsVisible(currentItem);
+  }
+}
+
Index: code/branches/chat2/src/orxonox/graphics/ChatBox.h
===================================================================
--- code/branches/chat2/src/orxonox/graphics/ChatBox.h	(revision 6836)
+++ code/branches/chat2/src/orxonox/graphics/ChatBox.h	(revision 6836)
@@ -0,0 +1,43 @@
+#ifndef _ChatBox_h_
+#define _ChatBox_h_
+
+#include "CEGuiSample.h"
+#include "CEGUI/CEGUI.h"
+#include "CEGUI/CEGUIXMLAttributes.h"
+
+class ChatBox : public CEGuiSample
+{
+  public:
+    bool initialiseSample();
+    void cleanupSample(void);
+    bool Event_HistorySizeChange(const CEGUI::EventArgs& args);
+    bool Event_ChatTextAdded(const CEGUI::EventArgs& args);
+    bool Event_FontChange(const CEGUI::EventArgs& args);
+    void setHistorySize(const size_t& pSize);
+    void addChatText(const CEGUI::String& pText);
+    void registerFont(const CEGUI::String& pLogicalName, const CEGUI::String& pFileName);
+
+  protected:
+    CEGUI::Font* makeFont(const CEGUI::String& pFontName, const CEGUI::String& pFileName, const CEGUI::String& pSize);
+    void changeFont(const CEGUI::String& pFontLogicalName, const CEGUI::String& pFontSize);
+
+  private:
+    // Type of list for registered fonts
+    typedef std::map<CEGUI::String, CEGUI::String> FontList;
+
+    // List of registered fonts
+    FontList mFontList;
+
+    // Maximal number of entries to retain within the Listbox
+    size_t mHistorySize;
+
+    // Logical font name dedicated to the chat box
+    // This allows us to modify the properties of that font and not affect the fonts used elsewhere
+    CEGUI::String mChatFontName;
+
+    // Default font size
+    CEGUI::String mDefaultFontSize;
+};
+
+
+#endif
