New grow and skid sounds from remaxim
[supertux.git] / src / console.cpp
index ead9128..9c82a0e 100644 (file)
@@ -19,6 +19,9 @@
 #include <config.h>
 
 #include <iostream>
+#include <math.h>
+#include <SDL_timer.h>
+#include <SDL_keyboard.h>
 #include "console.hpp"
 #include "video/drawing_context.hpp"
 #include "video/surface.hpp"
@@ -50,8 +53,7 @@ Console::~Console()
 void
 Console::init_graphics()
 {
-  font.reset(new Font("images/engine/fonts/white-small.png",
-                      "images/engine/fonts/shadow-small.png", 8, 9, 1));
+  font.reset(new Font(Font::FIXED,"fonts/andale12.stf",1));
   fontheight = font->get_height();
   background.reset(new Surface("images/engine/console.png"));
   background2.reset(new Surface("images/engine/console2.png"));
@@ -68,15 +70,6 @@ Console::flush(ConsoleStreamBuffer* buffer)
       outputBuffer.str(std::string());
     }
   }
-  if (buffer == &inputBuffer) {
-    std::string s = inputBuffer.str();
-    if ((s.length() > 0) && ((s[s.length()-1] == '\n') || (s[s.length()-1] == '\r'))) {
-      while ((s[s.length()-1] == '\n') || (s[s.length()-1] == '\r')) s.erase(s.length()-1);
-      addLines("> "+s);
-      parse(s);
-      inputBuffer.str(std::string());
-    }
-  }
 }
 
 void
@@ -145,18 +138,40 @@ Console::execute_script(const std::string& command)
   }
 }
 
+void 
+Console::input(char c)
+{
+  inputBuffer.insert(inputBufferPosition, 1, c);
+  inputBufferPosition++;
+}
+
 void
 Console::backspace()
 {
-  std::string s = inputBuffer.str();
-  if (s.length() > 0) {
-    s.erase(s.length()-1);
-    inputBuffer.str(s);
-    inputBuffer.pubseekoff(0, std::ios_base::end, std::ios_base::out);
+  if ((inputBufferPosition > 0) && (inputBuffer.length() > 0)) {
+    inputBuffer.erase(inputBufferPosition-1, 1);
+    inputBufferPosition--;
+  }
+}
+
+void
+Console::eraseChar()
+{
+  if (inputBufferPosition < (int)inputBuffer.length()) {
+    inputBuffer.erase(inputBufferPosition, 1);
   }
 }
 
 void
+Console::enter()
+{
+  addLines("> "+inputBuffer);
+  parse(inputBuffer);
+  inputBuffer = "";
+  inputBufferPosition = 0;
+}
+
+void
 Console::scroll(int numLines)
 {
   offset += numLines;
@@ -175,13 +190,24 @@ Console::show_history(int offset)
     offset++;
   }
   if (history_position == history.end()) {
-    inputBuffer.str(std::string());
+    inputBuffer = "";
+    inputBufferPosition = 0;
   } else {
-    inputBuffer.str(*history_position);
-    inputBuffer.pubseekoff(0, std::ios_base::end, std::ios_base::out);
+    inputBuffer = *history_position;
+    inputBufferPosition = inputBuffer.length();
   }
 }
 
+void 
+Console::move_cursor(int offset)
+{
+  if (offset == -65535) inputBufferPosition = 0;
+  if (offset == +65535) inputBufferPosition = inputBuffer.length();
+  inputBufferPosition+=offset;
+  if (inputBufferPosition < 0) inputBufferPosition = 0;
+  if (inputBufferPosition > (int)inputBuffer.length()) inputBufferPosition = inputBuffer.length();
+}
+
 // Helper functions for Console::autocomplete
 // TODO: Fix rough documentation
 namespace {
@@ -205,7 +231,7 @@ sq_insert_command(std::list<std::string>& cmds, HSQUIRRELVM vm, std::string tabl
       key_string+=".";
       if (search_prefix.substr(0, key_string.length()) == key_string) {
         sq_getclass(vm, -1);
-       sq_insert_commands(cmds, vm, key_string, search_prefix);
+        sq_insert_commands(cmds, vm, key_string, search_prefix);
         sq_pop(vm, 1);
       }
       break;
@@ -213,7 +239,7 @@ sq_insert_command(std::list<std::string>& cmds, HSQUIRRELVM vm, std::string tabl
     case OT_CLASS:
       key_string+=".";
       if (search_prefix.substr(0, key_string.length()) == key_string) {
-       sq_insert_commands(cmds, vm, key_string, search_prefix);
+        sq_insert_commands(cmds, vm, key_string, search_prefix);
       }
       break;
     case OT_CLOSURE:
@@ -251,7 +277,14 @@ sq_insert_commands(std::list<std::string>& cmds, HSQUIRRELVM vm, std::string tab
 void
 Console::autocomplete()
 {
-  std::string prefix = inputBuffer.str();
+  //int autocompleteFrom = inputBuffer.find_last_of(" ();+", inputBufferPosition);
+  int autocompleteFrom = inputBuffer.find_last_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_->.", inputBufferPosition);
+  if (autocompleteFrom != (int)std::string::npos) {
+    autocompleteFrom += 1;
+  } else {
+    autocompleteFrom = 0;
+  }
+  std::string prefix = inputBuffer.substr(autocompleteFrom, inputBufferPosition - autocompleteFrom);
   addLines("> "+prefix);
 
   std::list<std::string> cmds;
@@ -277,8 +310,9 @@ Console::autocomplete()
   if (cmds.size() == 0) addLines("No known command starts with \""+prefix+"\"");
   if (cmds.size() == 1) {
     // one match: just replace input buffer with full command
-    inputBuffer.str(cmds.front());
-    inputBuffer.pubseekoff(0, std::ios_base::end, std::ios_base::out);
+    std::string replaceWith = cmds.front();
+    inputBuffer.replace(autocompleteFrom, prefix.length(), replaceWith);
+    inputBufferPosition += (replaceWith.length() - prefix.length());
   }
   if (cmds.size() > 1) {
     // multiple matches: show all matches and set input buffer to longest common prefix
@@ -291,8 +325,9 @@ Console::autocomplete()
         if (cmd.compare(0, n, commonPrefix) != 0) commonPrefix.resize(n-1); else break;
       }
     }
-    inputBuffer.str(commonPrefix);
-    inputBuffer.pubseekoff(0, std::ios_base::end, std::ios_base::out);
+    std::string replaceWith = commonPrefix;
+    inputBuffer.replace(autocompleteFrom, prefix.length(), replaceWith);
+    inputBufferPosition += (replaceWith.length() - prefix.length());
   }
 }
 
@@ -312,8 +347,10 @@ Console::addLine(std::string s)
 
   // wrap long lines
   std::string overflow;
+  unsigned int line_count = 0;
   do {
     lines.push_front(Font::wrap_to_chars(s, 99, &overflow));
+    line_count++;
     s = overflow;
   } while (s.length() > 0);
 
@@ -325,7 +362,7 @@ Console::addLine(std::string s)
   if (height < 64) {
     if(height < 4)
       height = 4;
-    height += fontheight;
+    height += fontheight * line_count;
   }
 
   // reset console to full opacity
@@ -405,7 +442,8 @@ Console::hide()
   stayOpen = 0;
 
   // clear input buffer
-  inputBuffer.str(std::string());
+  inputBuffer = "";
+  inputBufferPosition = 0;
   SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
 }
 
@@ -448,7 +486,9 @@ Console::draw(DrawingContext& context)
   context.set_alpha(alpha);
   context.draw_surface(background2.get(), Vector(SCREEN_WIDTH/2 - background->get_width()/2 - background->get_width() + backgroundOffset, height - background->get_height()), layer);
   context.draw_surface(background2.get(), Vector(SCREEN_WIDTH/2 - background->get_width()/2 + backgroundOffset, height - background->get_height()), layer);
-  context.draw_surface(background.get(), Vector(SCREEN_WIDTH/2 - background->get_width()/2, height - background->get_height()), layer);
+  for (int x = (SCREEN_WIDTH/2 - background->get_width()/2 - (static_cast<int>(ceilf((float)SCREEN_WIDTH / (float)background->get_width()) - 1) * background->get_width())); x < SCREEN_WIDTH; x+=background->get_width()) {
+    context.draw_surface(background.get(), Vector(x, height - background->get_height()), layer);
+  }
   backgroundOffset+=10;
   if (backgroundOffset > (int)background->get_width()) backgroundOffset -= (int)background->get_width();
 
@@ -456,23 +496,28 @@ Console::draw(DrawingContext& context)
 
   if (focused) {
     lineNo++;
-    float py = height-4-1*9;
-    context.draw_text(font.get(), "> "+inputBuffer.str()+"_", Vector(4, py), LEFT_ALLIGN, layer);
+    float py = height-4-1 * font->get_height();
+    context.draw_text(font.get(), "> "+inputBuffer, Vector(4, py), ALIGN_LEFT, layer);
+    if (SDL_GetTicks() % 1000 < 750) {
+      int cursor_px = 2 + inputBufferPosition;
+      context.draw_text(font.get(), "_", Vector(4 + (cursor_px * font->get_text_width("X")), py), ALIGN_LEFT, layer);
+    }
   }
 
   int skipLines = -offset;
   for (std::list<std::string>::iterator i = lines.begin(); i != lines.end(); i++) {
     if (skipLines-- > 0) continue;
     lineNo++;
-    float py = height-4-lineNo*9;
-    if (py < -9) break;
-    context.draw_text(font.get(), *i, Vector(4, py), LEFT_ALLIGN, layer);
+    float py = height - 4 - lineNo*font->get_height();
+    if (py < -font->get_height()) break;
+    context.draw_text(font.get(), *i, Vector(4, py), ALIGN_LEFT, layer);
   }
   context.pop_transform();
 }
 
 Console* Console::instance = NULL;
-ConsoleStreamBuffer Console::inputBuffer;
+int Console::inputBufferPosition = 0;
+std::string Console::inputBuffer;
 ConsoleStreamBuffer Console::outputBuffer;
-std::ostream Console::input(&Console::inputBuffer);
 std::ostream Console::output(&Console::outputBuffer);
+