-Incorporated Marcin Ko��cielnicki patch that reintroduces the flying
[supertux.git] / lib / video / font.cpp
index a2a5922..12d96c7 100644 (file)
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
 
+#include <config.h>
+
 #include <cstdlib>
 #include <cstring>
+#include <stdexcept>
 
-#include "../app/globals.h"
-#include "../video/screen.h"
-#include "../video/font.h"
-#include "../video/drawing_context.h"
-#include "../utils/lispreader.h"
+#include "app/globals.h"
+#include "lisp/parser.h"
+#include "lisp/lisp.h"
+#include "screen.h"
+#include "font.h"
+#include "drawing_context.h"
 
 using namespace SuperTux;
 
@@ -74,15 +78,16 @@ float
 Font::get_text_width(const std::string& text) const
 {
   /** Let's calculate the size of the biggest paragraph */
-  std::string::size_type l, hl;
-  hl = 0; l = -1;
+  std::string::size_type l, hl, ol;
+  hl = 0; l = 0;
   while(true)
     {
+    ol = l;
     l = text.find("\n", l+1);
     if(l == std::string::npos)
       break;
-    if(hl < l)
-      hl = l;
+    if(hl < l-ol)
+      hl = l-ol;
     }
   if(hl == 0)
     hl = text.size();
@@ -95,11 +100,11 @@ Font::get_text_height(const std::string& text) const
 {
   /** Let's calculate height of the text */
   std::string::size_type l, hh;
-  hh = h; l = -1;
+  hh = h; l = 0;
   while(true)
     {
     l = text.find("\n", l+1);
-    if(l == (int)std::string::npos)
+    if(l == std::string::npos)
       break;
     hh += h + 2;
     }
@@ -116,31 +121,33 @@ Font::get_height() const
 void
 Font::draw(const std::string& text, const Vector& pos_, int allignment, Uint32 drawing_effect, int alpha)
 {
-  // calculate X positions based on the allignment type
-  Vector pos = Vector(pos_);
-  if(allignment == CENTER_ALLIGN)
-    pos.x -= get_text_width(text) / 2;
-  else if(allignment == RIGHT_ALLIGN)
-    pos.x -= get_text_width(text);
-
   /* Cut lines changes into seperate strings, needed to support center/right text
      allignments with break lines.
      Feel free to replace this hack with a more elegant solution
   */
   char temp[1024];
   std::string::size_type l, i, y;
+  bool done = false;
   i = y = 0;
 
-  while(true)
+  while(!done)
     {
     l = text.find("\n", i);
     if(l == std::string::npos)
       {
-      temp[text.copy(temp, text.size() - i, i)] = '\0';
-      draw_text(temp, pos + Vector(0,y), drawing_effect, alpha);
-      break;
+      l = text.size();
+      done = true;
       }
+
     temp[text.copy(temp, l - i, i)] = '\0';
+
+    // calculate X positions based on the allignment type
+    Vector pos = Vector(pos_);
+    if(allignment == CENTER_ALLIGN)
+      pos.x -= get_text_width(temp) / 2;
+    else if(allignment == RIGHT_ALLIGN)
+      pos.x -= get_text_width(temp);
+
     draw_text(temp, pos + Vector(0,y), drawing_effect, alpha);
 
     i = l+1;
@@ -197,23 +204,32 @@ Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos,
 #define SCROLL      60
 #define ITEMS_SPACE 4
 
-void SuperTux::display_text_file(const std::string& file, float scroll_speed, Font* heading_font, Font* normal_font, Font* small_font, Font* reference_font )
+void SuperTux::display_text_file(const std::string& file, float scroll_speed,
+    Font* heading_font, Font* normal_font, Font* small_font,
+    Font* reference_font)
 {
   std::string text;
+  std::string background_file;
   std::vector<std::string> names;
 
-  LispReader* reader = LispReader::load(datadir + "/" + file, "supertux-text");
+  std::string filename = datadir + "/" + file;
+  lisp::Parser parser;
+  try {
+    std::auto_ptr<lisp::Lisp> root (parser.parse(filename));
 
-  if(!reader)
-    {
-    std::cerr << "Error: Could not open text. Ignoring...\n";
+    const lisp::Lisp* text_lisp = root->get_lisp("supertux-text");
+    if(!text_lisp)
+      throw std::runtime_error("File isn't a supertux-text file");
+    
+    if(!text_lisp->get("text", text))
+      throw std::runtime_error("file doesn't contain a text field");
+    if(!text_lisp->get("background", background_file))
+      throw std::runtime_error("file doesn't contain a background file");
+  } catch(std::exception& e) {
+    std::cerr << "Couldn't load file '" << filename << "': " << e.what() <<
+      "\n";
     return;
-    }
-
-  reader->read_string("text", text, true);
-  std::string background_file;
-  reader->read_string("background", background_file, true);
-  delete reader;
+  }
 
   // Split text string lines into a vector
   names.clear();
@@ -244,6 +260,7 @@ void SuperTux::display_text_file(const std::string& file, float scroll_speed, Fo
   int done = 0;
   float scroll = 0;
   float speed = scroll_speed / 50;
+  float left_border = 50;
 
   DrawingContext context;
   SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
@@ -300,18 +317,32 @@ void SuperTux::display_text_file(const std::string& file, float scroll_speed, Fo
         }
 
         Font* font = 0;
+        bool center = true;
         switch(names[i][0])
         {
           case ' ': font = small_font; break;
           case '\t': font = normal_font; break;
           case '-': font = heading_font; break;
           case '*': font = reference_font; break;
-          default: font = reference_font; break;
+          case '#': font = normal_font; center = false; break;
+          default: 
+            break;
         }
-
-        context.draw_text(font,
-            names[i].substr(1, names[i].size()-1),
-            Vector(screen->w/2, screen->h + y - scroll), CENTER_ALLIGN, LAYER_FOREGROUND1);
+        
+        if(font) {
+          if(center) {
+            context.draw_text(font,
+                              names[i].substr(1, names[i].size()-1),
+                              Vector(screen->w/2, screen->h + y - scroll),
+                              CENTER_ALLIGN, LAYER_FOREGROUND1);
+          } else {
+            context.draw_text(font,
+                              names[i].substr(1, names[i].size()-1),
+                              Vector(left_border, screen->h + y - scroll),
+                              LEFT_ALLIGN, LAYER_FOREGROUND1);
+          }
+        }                   
+          
         y += font->get_height() + ITEMS_SPACE;
       }