Index: client/.gitignore
===================================================================
--- client/.gitignore	(revision 439f7bc1eec5d0b56344db9cc23399640026dba2)
+++ client/.gitignore	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
@@ -4,4 +4,4 @@
 Client.sdf
 Client.opensdf
-client
+gameClient
 allegro.log
Index: client/Client/Button.cpp
===================================================================
--- client/Client/Button.cpp	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
+++ client/Client/Button.cpp	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
@@ -0,0 +1,42 @@
+#include "Button.h"
+
+Button::Button(int x, int y, int width, int height, ALLEGRO_FONT *font, string str, void (*callback)()) :
+   GuiComponent(x, y, width, height, font)
+{
+   this->str = str;
+   this->callback = callback;
+}
+
+Button::~Button(void)
+{
+}
+
+void Button::draw(ALLEGRO_DISPLAY *display)
+{
+   al_set_target_bitmap(bitmap);
+   al_clear_to_color(al_map_rgb(0, 0, 0));
+
+   int fontHeight = al_get_font_line_height(font);
+
+   al_draw_text(font, al_map_rgb(0, 255, 0), this->width/2, (this->height-fontHeight)/2, ALLEGRO_ALIGN_CENTRE, str.c_str());
+   al_draw_rectangle(1, 1, this->width, this->height, al_map_rgb(0, 255, 0), 1);
+
+   al_set_target_bitmap(al_get_backbuffer(display));
+   al_draw_bitmap(bitmap, x, y, 0);
+}
+
+bool Button::handleEvent(ALLEGRO_EVENT& e)
+{
+   if (e.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
+      if (e.mouse.button == 1) {
+         if (this->x < e.mouse.x && e.mouse.x < (this->x+this->width)
+            && this->y < e.mouse.y && e.mouse.y < (this->y+this->height))
+         {
+            this->callback();
+            return true;
+         }
+      }
+   }
+
+   return false;
+}
Index: client/Client/Button.h
===================================================================
--- client/Client/Button.h	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
+++ client/Client/Button.h	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
@@ -0,0 +1,25 @@
+#ifndef _BUTTON_H
+#define _BUTTON_H
+
+#include "GuiComponent.h"
+
+#include <string>
+
+using namespace std;
+
+class Button :
+   public GuiComponent
+{
+private:
+   string str;
+   void (*callback)();
+
+public:
+   Button(int x, int y, int width, int height, ALLEGRO_FONT *font, string str, void (*callback)());
+   ~Button(void);
+
+   void draw(ALLEGRO_DISPLAY *display);
+   bool handleEvent(ALLEGRO_EVENT& e);
+};
+
+#endif
Index: client/Client/Client.vcxproj
===================================================================
--- client/Client/Client.vcxproj	(revision 439f7bc1eec5d0b56344db9cc23399640026dba2)
+++ client/Client/Client.vcxproj	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
@@ -66,5 +66,9 @@
     <ClCompile Include="..\..\common\message.cpp" />
     <ClCompile Include="chat.cpp" />
+    <ClCompile Include="Button.cpp" />
+    <ClCompile Include="GuiComponent.cpp" />
     <ClCompile Include="main.cpp" />
+    <ClCompile Include="Textbox.cpp" />
+    <ClCompile Include="Window.cpp" />
   </ItemGroup>
   <ItemGroup>
@@ -72,4 +76,8 @@
     <ClInclude Include="..\..\common\message.h" />
     <ClInclude Include="chat.h" />
+    <ClInclude Include="Button.h" />
+    <ClInclude Include="GuiComponent.h" />
+    <ClInclude Include="Textbox.h" />
+    <ClInclude Include="Window.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
Index: client/Client/Client.vcxproj.filters
===================================================================
--- client/Client/Client.vcxproj.filters	(revision 439f7bc1eec5d0b56344db9cc23399640026dba2)
+++ client/Client/Client.vcxproj.filters	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
@@ -20,4 +20,10 @@
       <UniqueIdentifier>{6c9ad2f2-bc8d-4e25-9c5c-c4440c60991c}</UniqueIdentifier>
     </Filter>
+    <Filter Include="Header Files\gui">
+      <UniqueIdentifier>{c6c812ef-0533-42bc-9d71-aa40428b5ca8}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\gui">
+      <UniqueIdentifier>{10ae8361-2a07-4085-b595-761b47868bad}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
@@ -29,4 +35,16 @@
     </ClCompile>
     <ClCompile Include="chat.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="GuiComponent.cpp">
+      <Filter>Source Files\gui</Filter>
+    </ClCompile>
+    <ClCompile Include="Textbox.cpp">
+      <Filter>Source Files\gui</Filter>
+    </ClCompile>
+    <ClCompile Include="Button.cpp">
+      <Filter>Source Files\gui</Filter>
+    </ClCompile>
+    <ClCompile Include="Window.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -42,4 +60,16 @@
       <Filter>Header Files\common</Filter>
     </ClInclude>
+    <ClInclude Include="GuiComponent.h">
+      <Filter>Header Files\gui</Filter>
+    </ClInclude>
+    <ClInclude Include="Textbox.h">
+      <Filter>Header Files\gui</Filter>
+    </ClInclude>
+    <ClInclude Include="Button.h">
+      <Filter>Header Files\gui</Filter>
+    </ClInclude>
+    <ClInclude Include="Window.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>
Index: client/Client/GuiComponent.cpp
===================================================================
--- client/Client/GuiComponent.cpp	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
+++ client/Client/GuiComponent.cpp	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
@@ -0,0 +1,25 @@
+#include "GuiComponent.h"
+
+GuiComponent::GuiComponent(int x, int y, int width, int height, ALLEGRO_FONT *font)
+{
+   this->x = x;
+   this->y = y;
+   this->width = width;
+   this->height = height;
+   this->font = font;
+   this->bitmap = al_create_bitmap(width, height);
+}
+
+GuiComponent::~GuiComponent(void)
+{
+   al_destroy_bitmap(this->bitmap);
+}
+
+void GuiComponent::draw(ALLEGRO_DISPLAY *display)
+{
+}
+
+bool GuiComponent::handleEvent(ALLEGRO_EVENT& e)
+{
+   return false;
+}
Index: client/Client/GuiComponent.h
===================================================================
--- client/Client/GuiComponent.h	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
+++ client/Client/GuiComponent.h	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
@@ -0,0 +1,23 @@
+#ifndef _GUICOMPONENT_H
+#define _GUICOMPONENT_H
+
+#include <allegro5/allegro.h>
+#include <allegro5/allegro_primitives.h>
+#include <allegro5/allegro_font.h>
+
+class GuiComponent
+{
+protected:
+   int x, y, width, height;
+   ALLEGRO_BITMAP *bitmap;
+   ALLEGRO_FONT *font;
+
+public:
+   GuiComponent(int x, int y, int width, int height, ALLEGRO_FONT *font);
+   virtual ~GuiComponent(void);
+
+   virtual void draw(ALLEGRO_DISPLAY *display);
+   virtual bool handleEvent(ALLEGRO_EVENT& e);
+};
+
+#endif
Index: client/Client/Textbox.cpp
===================================================================
--- client/Client/Textbox.cpp	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
+++ client/Client/Textbox.cpp	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
@@ -0,0 +1,89 @@
+#include "Textbox.h"
+
+#include <iostream>
+
+using namespace std;
+
+Textbox::Textbox(int x, int y, int width, int height, ALLEGRO_FONT *font) :
+   GuiComponent(x, y, width, height, font)
+{
+   str = "";
+   selected = false;
+}
+
+Textbox::~Textbox(void)
+{
+}
+
+const string& Textbox::getStr() const
+{
+   return str;
+}
+
+void Textbox::clear(void)
+{
+   str.clear();
+}
+
+void Textbox::draw(ALLEGRO_DISPLAY *display)
+{
+   al_set_target_bitmap(bitmap);
+   al_clear_to_color(al_map_rgb(0, 0, 0));
+
+   int textWidth = al_get_text_width(font, str.c_str());
+   int fontHeight = al_get_font_line_height(font);
+   
+   int textPos = 1;
+   if(textWidth > this->width)
+      textPos = this->width-textWidth-3;
+
+   al_draw_text(font, al_map_rgb(0, 255, 0), textPos, (this->height-fontHeight)/2, ALLEGRO_ALIGN_LEFT, str.c_str());
+   al_draw_rectangle(1, 1, this->width, this->height, al_map_rgb(0, 255, 0), 1);
+
+   al_set_target_bitmap(al_get_backbuffer(display));
+   al_draw_bitmap(bitmap, x, y, 0);
+}
+
+bool Textbox::handleEvent(ALLEGRO_EVENT& e)
+{
+   ALLEGRO_KEYBOARD_STATE keys;
+   al_get_keyboard_state(&keys);
+
+   if (e.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
+      if (e.mouse.button == 1) {
+         if (this->x < e.mouse.x && e.mouse.x < (this->x+this->width)
+            && this->y < e.mouse.y && e.mouse.y < (this->y+this->height))
+         {
+            selected = true;
+            return true;
+         }else
+            selected = false;
+      }
+
+      return false;
+   }
+
+   if (!selected)
+      return false;
+
+   if (e.type == ALLEGRO_EVENT_KEY_DOWN) {
+      char newChar = 0;
+
+      if (ALLEGRO_KEY_A <= e.keyboard.keycode && e.keyboard.keycode <= ALLEGRO_KEY_Z) {
+         newChar = 'a'+e.keyboard.keycode-ALLEGRO_KEY_A;
+         if (al_key_down(&keys, ALLEGRO_KEY_LSHIFT) || al_key_down(&keys, ALLEGRO_KEY_RSHIFT))
+            newChar -= 32;
+      }
+      else if (ALLEGRO_KEY_0 <= e.keyboard.keycode && e.keyboard.keycode <= ALLEGRO_KEY_9)
+         newChar = '0'+e.keyboard.keycode-ALLEGRO_KEY_0;
+      else if (e.keyboard.keycode = ALLEGRO_KEY_BACKSPACE && str.size() > 0)
+         str = str.substr(0, str.size()-1);
+
+      if (newChar != 0) {
+         str.append(1, newChar);
+         return true;
+      }
+   }
+
+   return false;
+}
Index: client/Client/Textbox.h
===================================================================
--- client/Client/Textbox.h	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
+++ client/Client/Textbox.h	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
@@ -0,0 +1,32 @@
+#ifndef _TEXTBOX_H
+#define _TEXTBOX_H
+
+#include "GuiComponent.h"
+
+#include <string>
+
+using namespace std;
+
+class Textbox :
+   public GuiComponent
+{
+private:
+   string str;
+   bool selected;
+
+public:
+   Textbox(int x, int y, int width, int height, ALLEGRO_FONT *font);
+   ~Textbox(void);
+
+   // This might lead to a memory leak if the textbox is deleted because it
+   // returns a reference to the string.
+   // string getStr() const; will copy the string and return it instead
+   const string& getStr() const;
+
+   void clear(void);
+   void draw(ALLEGRO_DISPLAY *display);
+   bool handleEvent(ALLEGRO_EVENT& e);
+};
+
+#endif
+
Index: client/Client/Window.cpp
===================================================================
--- client/Client/Window.cpp	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
+++ client/Client/Window.cpp	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
@@ -0,0 +1,41 @@
+#include "Window.h"
+
+Window::Window(int x, int y, int width, int height) :
+   GuiComponent(x, y, width, height, NULL)
+{
+}
+
+Window::~Window(void)
+{
+   for(int x=0; x<this->vctGui.size(); x++)
+      delete this->vctGui[x];
+}
+
+void Window::addComponent(GuiComponent *comp)
+{
+   this->vctGui.push_back(comp);
+}
+
+GuiComponent* Window::getComponent(int x)
+{
+   return this->vctGui[x];
+}
+
+void Window::draw(ALLEGRO_DISPLAY *display)
+{
+   al_clear_to_color(al_map_rgb(0, 0, 0));
+
+   for(int x=0; x<this->vctGui.size(); x++)
+      this->vctGui[x]->draw(display);
+}
+
+bool Window::handleEvent(ALLEGRO_EVENT& e)
+{
+   for(int x=0; x<this->vctGui.size(); x++) {
+      if(this->vctGui[x]->handleEvent(e)) {
+         return true;
+      }
+   }
+
+   return false;
+}
Index: client/Client/Window.h
===================================================================
--- client/Client/Window.h	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
+++ client/Client/Window.h	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
@@ -0,0 +1,26 @@
+#ifndef _WINDOW_H
+#define _WINDOW_H
+
+#include "GuiComponent.h"
+
+#include <vector>
+
+using namespace std;
+
+class Window :
+   public GuiComponent
+{
+private:
+   vector<GuiComponent*> vctGui;
+
+public:
+   Window(int x, int y, int width, int height);
+   ~Window(void);
+
+   void addComponent(GuiComponent *comp);
+   GuiComponent* getComponent(int x);
+   void draw(ALLEGRO_DISPLAY *display);
+   bool handleEvent(ALLEGRO_EVENT& e);
+};
+
+#endif
Index: client/Client/chat.cpp
===================================================================
--- client/Client/chat.cpp	(revision 439f7bc1eec5d0b56344db9cc23399640026dba2)
+++ client/Client/chat.cpp	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
@@ -19,5 +19,5 @@
 {
    for(int x=0; x<vctChat.size(); x++)
-      al_draw_text(font, color, 10, 10+x*15, ALLEGRO_ALIGN_LEFT, vctChat[x].c_str());
+      al_draw_text(font, color, 10, 140+x*15, ALLEGRO_ALIGN_LEFT, vctChat[x].c_str());
 
    al_draw_text(font, color, 10, 460, ALLEGRO_ALIGN_LEFT, strPrompt.c_str());
@@ -30,19 +30,19 @@
 
 // returns true if the event was consumed, false if it should be passed on
-bool chat::processEvent(ALLEGRO_EVENT ev)
+bool chat::handleEvent(ALLEGRO_EVENT e)
 {
    ALLEGRO_KEYBOARD_STATE keys;
    al_get_keyboard_state(&keys);
 
-   if (ev.type == ALLEGRO_EVENT_KEY_DOWN) {
+   if (e.type == ALLEGRO_EVENT_KEY_DOWN) {
       char newChar = 0;
 
-      if (ALLEGRO_KEY_A <= ev.keyboard.keycode && ev.keyboard.keycode <= ALLEGRO_KEY_Z) {
-         newChar = 'a'+ev.keyboard.keycode-ALLEGRO_KEY_A;
+      if (ALLEGRO_KEY_A <= e.keyboard.keycode && e.keyboard.keycode <= ALLEGRO_KEY_Z) {
+         newChar = 'a'+e.keyboard.keycode-ALLEGRO_KEY_A;
          if (al_key_down(&keys, ALLEGRO_KEY_LSHIFT) || al_key_down(&keys, ALLEGRO_KEY_RSHIFT))
             newChar -= 32;
       }
-      if (ALLEGRO_KEY_0 <= ev.keyboard.keycode && ev.keyboard.keycode <= ALLEGRO_KEY_9)
-         newChar = '0'+ev.keyboard.keycode-ALLEGRO_KEY_0;
+      if (ALLEGRO_KEY_0 <= e.keyboard.keycode && e.keyboard.keycode <= ALLEGRO_KEY_9)
+         newChar = '0'+e.keyboard.keycode-ALLEGRO_KEY_0;
 
       if (newChar != 0) {
@@ -51,5 +51,5 @@
       }
 
-      if (ev.keyboard.keycode == ALLEGRO_KEY_ENTER) {
+      if (e.keyboard.keycode == ALLEGRO_KEY_ENTER) {
          strEnteredInput = strPrompt;
          strPrompt.clear();
Index: client/Client/chat.h
===================================================================
--- client/Client/chat.h	(revision 439f7bc1eec5d0b56344db9cc23399640026dba2)
+++ client/Client/chat.h	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
@@ -24,5 +24,5 @@
    void addLine(string s);
 
-   bool processEvent(ALLEGRO_EVENT ev);
+   bool handleEvent(ALLEGRO_EVENT e);
 };
 
Index: client/Client/main.cpp
===================================================================
--- client/Client/main.cpp	(revision 439f7bc1eec5d0b56344db9cc23399640026dba2)
+++ client/Client/main.cpp	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
@@ -18,5 +18,4 @@
 #include <string>
 #include <iostream>
-#include <vector>
 
 #include <allegro5/allegro.h>
@@ -26,4 +25,7 @@
 #include "../../common/message.h"
 
+#include "Window.h"
+#include "Textbox.h"
+#include "Button.h"
 #include "chat.h"
 
@@ -36,5 +38,12 @@
 void initWinSock();
 void shutdownWinSock();
-void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole, string &username);
+void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole);
+
+// callbacks
+void registerAccount();
+void login();
+void logout();
+void quit();
+void sendChatMessage();
 
 void error(const char *);
@@ -53,7 +62,25 @@
 enum STATE {
    STATE_START,
-   STATE_LOGIN,
-   STATE_LOGOUT
+   STATE_LOGIN // this means you're already logged in
 };
+
+int state;
+
+bool doexit;
+
+Window* wndLogin;
+Window* wndMain;
+Window* wndCurrent;
+
+Textbox* txtUsername;
+Textbox* txtPassword;
+Textbox* txtChat;
+
+int sock;
+struct sockaddr_in server, from;
+struct hostent *hp;
+NETWORK_MSG msgTo, msgFrom;
+string username;
+chat chatConsole;
  
 int main(int argc, char **argv)
@@ -63,13 +90,12 @@
    ALLEGRO_TIMER *timer = NULL;
    ALLEGRO_BITMAP *bouncer = NULL;
+   bool key[4] = { false, false, false, false };
+   bool redraw = true;
+   doexit = false;
+
    float bouncer_x = SCREEN_W / 2.0 - BOUNCER_SIZE / 2.0;
    float bouncer_y = SCREEN_H / 2.0 - BOUNCER_SIZE / 2.0;
-   bool key[4] = { false, false, false, false };
-   bool redraw = true;
-   bool doexit = false;
-
-   int state = STATE_START;
-
-   chat chatConsole;
+
+   state = STATE_START;
 
    if(!al_init()) {
@@ -78,4 +104,5 @@
    }
 
+   al_init_primitives_addon();
    al_init_font_addon();
    al_init_ttf_addon();
@@ -93,4 +120,9 @@
       return -1;
    }
+
+    if(!al_install_mouse()) {
+      fprintf(stderr, "failed to initialize the mouse!\n");
+      return -1;
+   }
  
    timer = al_create_timer(1.0 / FPS);
@@ -106,5 +138,24 @@
       return -1;
    }
- 
+
+   wndLogin = new Window(0, 0, SCREEN_W, SCREEN_H);
+   wndLogin->addComponent(new Textbox(104, 40, 100, 20, font));
+   wndLogin->addComponent(new Textbox(104, 70, 100, 20, font));
+   wndLogin->addComponent(new Button(22, 100, 90, 20, font, "Register", registerAccount));
+   wndLogin->addComponent(new Button(122, 100, 60, 20, font, "Login", login));
+   wndLogin->addComponent(new Button(540, 10, 80, 20, font, "Quit", quit));
+
+   txtUsername = (Textbox*)wndLogin->getComponent(0);
+   txtPassword = (Textbox*)wndLogin->getComponent(1);
+
+   wndMain = new Window(0, 0, SCREEN_W, SCREEN_H);
+   wndMain->addComponent(new Textbox(95, 40, 525, 20, font));
+   wndMain->addComponent(new Button(95, 70, 160, 20, font, "Send Message", sendChatMessage));
+   wndMain->addComponent(new Button(540, 10, 80, 20, font, "Logout", logout));
+
+   txtChat = (Textbox*)wndMain->getComponent(0);
+
+   wndCurrent = wndLogin;
+
    bouncer = al_create_bitmap(BOUNCER_SIZE, BOUNCER_SIZE);
    if(!bouncer) {
@@ -131,18 +182,11 @@
  
    al_register_event_source(event_queue, al_get_display_event_source(display));
- 
    al_register_event_source(event_queue, al_get_timer_event_source(timer));
- 
    al_register_event_source(event_queue, al_get_keyboard_event_source());
+   al_register_event_source(event_queue, al_get_mouse_event_source());
  
    al_clear_to_color(al_map_rgb(0,0,0));
  
    al_flip_display();
-
-   int sock;
-   struct sockaddr_in server, from;
-   struct hostent *hp;
-   NETWORK_MSG msgTo, msgFrom;
-   string username;
 
    if (argc != 3) {
@@ -171,6 +215,9 @@
       ALLEGRO_EVENT ev;
       al_wait_for_event(event_queue, &ev);
- 
-      if(ev.type == ALLEGRO_EVENT_TIMER) {
+
+      if(wndCurrent->handleEvent(ev)) {
+         // do nothing
+      }
+      else if(ev.type == ALLEGRO_EVENT_TIMER) {
          if(key[KEY_UP] && bouncer_y >= 4.0) {
             bouncer_y -= 4.0;
@@ -195,81 +242,20 @@
       }
       else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) {
-         bool eventConsumed = chatConsole.processEvent(ev);
-
-         if (eventConsumed) {
-            string input = chatConsole.getInput();
-            if (!input.empty()) {
-               cout << "input: " << input << endl;
-               strcpy(msgTo.buffer, input.c_str());
-
-               switch(state)
-               {
-                  case STATE_START:
-                  {
-                     username = input;
-                     strcpy(msgTo.buffer+input.size()+1, "MyPassword");
-                     msgTo.type = MSG_TYPE_REGISTER;
-                     //msgTo.type = MSG_TYPE_LOGIN;
-
-                     sendMessage(&msgTo, sock, &server);
-                     receiveMessage(&msgFrom, sock, &from);
-                     processMessage(msgFrom, state, chatConsole, username);
-                     cout << "state: " << state << endl;
-
-                     break;
-                  }
-                  case STATE_LOGIN:
-                  {
-                     if (input.compare("quit") == 0 ||
-                         input.compare("exit") == 0 ||
-                         input.compare("logout") == 0)
-                     {
-                        strcpy(msgTo.buffer, username.c_str());
-                        msgTo.type = MSG_TYPE_LOGOUT;
-                     }
-                     else
-                        msgTo.type = MSG_TYPE_CHAT;
-
-                     sendMessage(&msgTo, sock, &server);
-                     receiveMessage(&msgFrom, sock, &from);
-                     processMessage(msgFrom, state, chatConsole, username);
-                     cout << "state: " << state << endl;
-
-                     break;
-                  }
-                  case STATE_LOGOUT:
-                  {
-                     chatConsole.addLine("You're logged out, so you can't send any messages to the server.");
-
-                     cout << "You're logged out, so you can't send any messages to the server." << endl;
-                  
-                     break;
-                  }
-                  default:
-                  {
-                     cout << "The state has an invalid value: " << state << endl;
-                  
-                     break;
-                  }
-               }
-            }
-         }else {
-            switch(ev.keyboard.keycode) {
-               case ALLEGRO_KEY_UP:
-                  key[KEY_UP] = true;
-                  break;
- 
-               case ALLEGRO_KEY_DOWN:
-                  key[KEY_DOWN] = true;
-                  break;
- 
-               case ALLEGRO_KEY_LEFT: 
-                  key[KEY_LEFT] = true;
-                  break;
- 
-               case ALLEGRO_KEY_RIGHT:
-                  key[KEY_RIGHT] = true;
-                  break;
-            }
+         switch(ev.keyboard.keycode) {
+            case ALLEGRO_KEY_UP:
+               key[KEY_UP] = true;
+               break;
+ 
+            case ALLEGRO_KEY_DOWN:
+               key[KEY_DOWN] = true;
+               break;
+ 
+            case ALLEGRO_KEY_LEFT: 
+               key[KEY_LEFT] = true;
+               break;
+ 
+            case ALLEGRO_KEY_RIGHT:
+               key[KEY_RIGHT] = true;
+               break;
          }
       }
@@ -301,9 +287,17 @@
          redraw = false;
  
-         al_clear_to_color(al_map_rgb(0,0,0));
+         wndCurrent->draw(display);
  
          al_draw_bitmap(bouncer, bouncer_x, bouncer_y, 0);
 
          chatConsole.draw(font, al_map_rgb(255,255,255));
+
+         if(wndCurrent == wndLogin) {
+            al_draw_text(font, al_map_rgb(0, 255, 0), 4, 43, ALLEGRO_ALIGN_LEFT, "Username:");
+            al_draw_text(font, al_map_rgb(0, 255, 0), 1, 73, ALLEGRO_ALIGN_LEFT, "Password:");
+         }
+         else if(wndCurrent == wndMain) {
+            al_draw_text(font, al_map_rgb(0, 255, 0), 4, 43, ALLEGRO_ALIGN_LEFT, "Message:");
+         }
 
          al_flip_display();
@@ -319,4 +313,7 @@
    shutdownWinSock();
    
+   delete wndLogin;
+   delete wndMain;
+
    al_destroy_event_queue(event_queue);
    al_destroy_bitmap(bouncer);
@@ -360,5 +357,5 @@
 }
 
-void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole, string &username)
+void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole)
 {
    string response = string(msg.buffer);
@@ -372,16 +369,31 @@
          chatConsole.addLine(response);
 
-         /*
-         if (response.compare("Player has already logged in.") == 0)
+         switch(msg.type)
          {
-            cout << "User login failed" << endl;
-            username.clear();
-         }
-         else
-         {
-            cout << "User login successful" << endl;
-            state = STATE_LOGIN;
-         }
-         */
+            case MSG_TYPE_REGISTER:
+            {
+               break;
+            }
+            case MSG_TYPE_LOGIN:
+            {
+               if (response.compare("Player has already logged in.") == 0)
+               {
+                  username.clear();
+                  cout << "User login failed" << endl;
+               }
+               else if (response.compare("Incorrect username or password") == 0)
+               {
+                  username.clear();
+                  cout << "User login failed" << endl;
+               }
+               else
+               {
+                  state = STATE_LOGIN;
+                  wndCurrent = wndMain;
+                  cout << "User login successful" << endl;
+               }
+               break;
+            }
+         }
 
          break;
@@ -391,20 +403,27 @@
          chatConsole.addLine(response);
 
-         if (response.compare("You have successfully logged out. You may quit the game.") == 0)
+          switch(msg.type)
          {
-            cout << "Logged out" << endl;
-            state = STATE_LOGOUT;
-         }
-         else
-         {
-            cout << "Added new line" << endl;
+            case MSG_TYPE_REGISTER:
+            {
+               break;
+            }
+            case MSG_TYPE_LOGIN:
+            {
+               if (response.compare("You have successfully logged out.") == 0)
+               {
+                  cout << "Logged out" << endl;
+                  state = STATE_START;
+                  wndCurrent = wndLogin;
+               }
+               else
+               {
+                  cout << "Added new line" << endl;
+               }
+
+               break;
+            }
          }
                      
-         break;
-      }
-      case STATE_LOGOUT:
-      {
-         cout << "Bug: You're logged out, so you shouldn't be receiving any messages." << endl;
-                  
          break;
       }
@@ -417,2 +436,74 @@
    }
 }
+
+void registerAccount()
+{
+   string username = txtUsername->getStr();
+   string password = txtPassword->getStr();
+
+   txtUsername->clear();
+   txtPassword->clear();
+
+   msgTo.type = MSG_TYPE_REGISTER;
+
+   strcpy(msgTo.buffer, username.c_str());
+   strcpy(msgTo.buffer+username.size()+1, password.c_str());
+
+   sendMessage(&msgTo, sock, &server);
+   receiveMessage(&msgFrom, sock, &from);
+   processMessage(msgFrom, state, chatConsole);
+   cout << "state: " << state << endl;
+}
+
+void login()
+{
+   string strUsername = txtUsername->getStr();
+   string strPassword = txtPassword->getStr();
+   username = strUsername;
+
+   txtUsername->clear();
+   txtPassword->clear();
+
+   msgTo.type = MSG_TYPE_LOGIN;
+
+   strcpy(msgTo.buffer, strUsername.c_str());
+   strcpy(msgTo.buffer+username.size()+1, strPassword.c_str());
+
+   sendMessage(&msgTo, sock, &server);
+   receiveMessage(&msgFrom, sock, &from);
+   processMessage(msgFrom, state, chatConsole);
+   cout << "state: " << state << endl;
+}
+
+void logout()
+{
+   txtChat->clear();
+
+   msgTo.type = MSG_TYPE_LOGOUT;
+
+   strcpy(msgTo.buffer, username.c_str());
+
+   sendMessage(&msgTo, sock, &server);
+   receiveMessage(&msgFrom, sock, &from);
+   processMessage(msgFrom, state, chatConsole);
+}
+
+void quit()
+{
+   doexit = true;
+}
+
+void sendChatMessage()
+{
+   string msg = txtChat->getStr();
+
+   txtChat->clear();
+
+   msgTo.type = MSG_TYPE_CHAT;
+
+   strcpy(msgTo.buffer, msg.c_str());
+
+   sendMessage(&msgTo, sock, &server);
+   receiveMessage(&msgFrom, sock, &from);
+   processMessage(msgFrom, state, chatConsole);
+}
Index: client/makefile
===================================================================
--- client/makefile	(revision 439f7bc1eec5d0b56344db9cc23399640026dba2)
+++ client/makefile	(revision 87b3ee2526ba9b73d93862e48b4d519434148b39)
@@ -1,2 +1,2 @@
-client : ../common/message.cpp Client/main.cpp
+gameClient : ../common/message.cpp Client/main.cpp
 	g++ -o $@ $?
