pingus-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Pingus-CVS] r2641 - in branches/pingus_sdl/src: . lisp math physfs


From: grumbel at BerliOS
Subject: [Pingus-CVS] r2641 - in branches/pingus_sdl/src: . lisp math physfs
Date: Sun, 14 Jan 2007 00:42:26 +0100

Author: grumbel
Date: 2007-01-14 00:42:24 +0100 (Sun, 14 Jan 2007)
New Revision: 2641

Added:
   branches/pingus_sdl/src/lisp/
   branches/pingus_sdl/src/lisp/getters.cpp
   branches/pingus_sdl/src/lisp/getters.hpp
   branches/pingus_sdl/src/lisp/lexer.cpp
   branches/pingus_sdl/src/lisp/lexer.hpp
   branches/pingus_sdl/src/lisp/lisp.cpp
   branches/pingus_sdl/src/lisp/lisp.hpp
   branches/pingus_sdl/src/lisp/parser.cpp
   branches/pingus_sdl/src/lisp/parser.hpp
   branches/pingus_sdl/src/lisp/properties.cpp
   branches/pingus_sdl/src/lisp/properties.hpp
   branches/pingus_sdl/src/lisp/property_iterator.hpp
   branches/pingus_sdl/src/lisp/writer.cpp
   branches/pingus_sdl/src/lisp/writer.hpp
   branches/pingus_sdl/src/math/vector2i.cpp
   branches/pingus_sdl/src/physfs/
   branches/pingus_sdl/src/physfs/physfs_sdl.cpp
   branches/pingus_sdl/src/physfs/physfs_sdl.hpp
   branches/pingus_sdl/src/physfs/physfs_stream.cpp
   branches/pingus_sdl/src/physfs/physfs_stream.hpp
Modified:
   branches/pingus_sdl/src/SConscript
   branches/pingus_sdl/src/math/vector2i.hpp
   branches/pingus_sdl/src/sprite.cpp
Log:
- commit some additional libraries

Modified: branches/pingus_sdl/src/SConscript
===================================================================
--- branches/pingus_sdl/src/SConscript  2007-01-13 21:37:11 UTC (rev 2640)
+++ branches/pingus_sdl/src/SConscript  2007-01-13 23:42:24 UTC (rev 2641)
@@ -43,7 +43,7 @@
 #   clanMikMod-0.8         ">=" 0.8.0')
 
 env.ParseConfig('sdl-config  --cflags --libs')
-env['LIBS'] += ['SDL_image']
+env['LIBS'] += ['SDL_image', 'physfs']
 
 # sdl_env.ParseConfig('sdl-config  --cflags --libs')
 # sdl_env['LIBS'] += ['SDL_image']
@@ -164,6 +164,13 @@
 'gui/screen_ptr.cxx', 
 'gui/surface_button.cxx',
 
+'lisp/getters.cpp',
+'lisp/lexer.cpp',
+'lisp/lisp.cpp',
+'lisp/parser.cpp',
+'lisp/properties.cpp',
+'lisp/writer.cpp',
+
 # # 'input/axes/button_axis.cxx', 
 # # 'input/axes/inverted_axis.cxx', 
 # # 'input/axes/joystick_axis.cxx', 
@@ -246,7 +253,9 @@
 'tinygettext/tinygettext.cxx', 
 # 'true_server.cxx', 
 'math/vector2f.cpp',
-'math/vector3f.cpp', 
+'math/vector3f.cpp',
+'physfs/physfs_sdl.cpp',
+'physfs/physfs_stream.cpp',
 # 'world.cxx', 
 # 'worldmap/dot.cxx', 
 # 'worldmap/dot_factory.cxx', 

Added: branches/pingus_sdl/src/lisp/getters.cpp
===================================================================
--- branches/pingus_sdl/src/lisp/getters.cpp    2007-01-13 21:37:11 UTC (rev 
2640)
+++ branches/pingus_sdl/src/lisp/getters.cpp    2007-01-13 23:42:24 UTC (rev 
2641)
@@ -0,0 +1,42 @@
+#include <config.h>
+#include "getters.hpp"
+
+namespace lisp
+{
+
+bool get(const Lisp* lisp, bool& val)
+{
+  if(lisp->get_type() != Lisp::TYPE_BOOL)
+    return false;
+  val = lisp->get_bool();
+  return true;
+}
+
+bool get(const Lisp* lisp, float& val)
+{
+  if(lisp->get_type() == Lisp::TYPE_INT)
+    val = lisp->get_int();
+  else if(lisp->get_type() == Lisp::TYPE_FLOAT)
+    val = lisp->get_float();
+  else
+    return false;
+  return true;
+}
+
+bool get(const Lisp* lisp, int& val)
+{
+  if(lisp->get_type() != Lisp::TYPE_INT)
+    return false;
+  val = lisp->get_int();
+  return true;
+}
+
+bool get(const Lisp* lisp, std::string& val)
+{
+  if(lisp->get_type() != Lisp::TYPE_STRING)
+    return false;
+  val = lisp->get_string();
+  return true;
+}
+
+}

Added: branches/pingus_sdl/src/lisp/getters.hpp
===================================================================
--- branches/pingus_sdl/src/lisp/getters.hpp    2007-01-13 21:37:11 UTC (rev 
2640)
+++ branches/pingus_sdl/src/lisp/getters.hpp    2007-01-13 23:42:24 UTC (rev 
2641)
@@ -0,0 +1,60 @@
+/** This header defines functions that assign the value of Lisp objects to
+ * normal C++ datatypes.
+ *
+ * The get function is overloaded for a set of default datatypes. You can add
+ * further overloads in your own code. The get functions return true if the
+ * value could be converted and false otherwise.
+ *
+ * The property_get function expect a list whose values 1-n are transformed to 
a
+ * C++ object. This is typically used from the code in the Properties class. 
You
+ * can also write custom overloads in your code.
+ */
+#ifndef __GETTERS_HPP__
+#define __GETTERS_HPP__
+
+#include "lisp.hpp"
+
+namespace lisp
+{
+
+bool get(const Lisp* lisp, bool& val);
+bool get(const Lisp* lisp, float& val);
+bool get(const Lisp* lisp, int& val);
+bool get(const Lisp* lisp, std::string& val);
+bool get(const Lisp* lisp, const Lisp*& val);
+
+template<typename T>
+static inline bool property_get(const Lisp* lisp, T& val)
+{  
+  if(lisp->get_list_size() != 2)
+    return false;
+  
+  const Lisp* el = lisp->get_list_elem(1);
+  return get(el, val);
+}
+
+static inline bool property_get(const Lisp* lisp, const Lisp*& val)
+{
+  val = lisp;
+  return true;
+}
+
+template<typename T>
+static inline bool property_get(const Lisp* lisp, std::vector<T>& list)
+{
+  list.clear();
+  for(size_t n = 1; n < lisp->get_list_size(); ++n) {
+    T val;
+    if(get(lisp->get_list_elem(n), val) == false) {
+      list.clear();
+      return false;
+    }
+    list.push_back(val);
+  }
+  return true;
+}
+
+}
+
+#endif
+

Added: branches/pingus_sdl/src/lisp/lexer.cpp
===================================================================
--- branches/pingus_sdl/src/lisp/lexer.cpp      2007-01-13 21:37:11 UTC (rev 
2640)
+++ branches/pingus_sdl/src/lisp/lexer.cpp      2007-01-13 23:42:24 UTC (rev 
2641)
@@ -0,0 +1,217 @@
+//  $Id: lexer.cpp 2379 2005-05-01 19:02:16Z matzebraun $
+//
+//  Copyright (C) 2004 Matthias Braun <address@hidden>
+//  code in this file based on lispreader from Mark Probst
+//
+//  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#include <config.h>
+
+#include <sstream>
+#include <stdexcept>
+#include <iostream>
+
+#include "lexer.hpp"
+
+namespace lisp
+{
+
+class EOFException
+{
+};
+
+Lexer::Lexer(std::istream& newstream)
+    : stream(newstream), eof(false), linenumber(0)
+{
+  try {
+    // trigger a refill of the buffer
+    c = 0;
+    bufend = 0;
+    nextChar();
+  } catch(EOFException& e) {
+  }
+}
+
+Lexer::~Lexer()
+{
+}
+
+void
+Lexer::nextChar()
+{
+  ++c;
+  if(c >= bufend) {
+    if(eof)
+      throw EOFException();
+    stream.read(buffer, BUFFER_SIZE);
+    size_t bytes_read = stream.gcount();
+    
+    c = buffer;
+    bufend = buffer + bytes_read;
+
+    // the following is a hack that appends an additional ' ' at the end of
+    // the file to avoid problems when parsing symbols/elements and a sudden
+    // EOF. This is faster than relying on unget and IMO also nicer.
+    if(bytes_read == 0 || stream.eof()) {
+      eof = true;
+      *bufend = ' ';
+      ++bufend;
+    }
+  }
+}
+
+Lexer::TokenType
+Lexer::getNextToken()
+{
+  static const char* delims = "\"();";
+
+  try {
+    while(isspace(*c)) {
+      if(*c == '\n')
+        ++linenumber;
+      nextChar();
+    };
+    
+    token_length = 0;
+    
+    switch(*c) {
+      case ';': // comment
+        while(true) {
+          nextChar();
+          if(*c == '\n') {
+            ++linenumber;
+            break;
+          }
+        }
+        return getNextToken(); // and again
+      case '(':
+        nextChar();
+        return TOKEN_OPEN_PAREN;
+      case ')':
+        nextChar();
+        return TOKEN_CLOSE_PAREN;
+      case '"': {  // string
+        int startline = linenumber;
+        try {
+          while(1) {
+            nextChar();
+            if(*c == '"')
+              break;
+            else if(*c == '\n')
+              linenumber++;
+            else if(*c == '\\') {
+              nextChar();
+              switch(*c) {
+                case 'n':
+                  *c = '\n';
+                  break;
+                case 't':
+                  *c = '\t';
+                  break;
+              }
+            }
+            if(token_length < MAX_TOKEN_LENGTH)
+              token_string[token_length++] = *c;
+          }
+          token_string[token_length] = 0;
+        } catch(EOFException& ) {
+          std::stringstream msg;
+          msg << "Parse error in line " << startline << ": "
+            << "EOF while parsing string.";
+          throw std::runtime_error(msg.str());
+        }
+        nextChar();
+        return TOKEN_STRING;
+      }
+      case '#': // constant
+        try {
+          nextChar();
+          
+          while(isalnum(*c) || *c == '_') {
+            if(token_length < MAX_TOKEN_LENGTH)
+              token_string[token_length++] = *c;
+            nextChar();
+          }
+          token_string[token_length] = 0;
+        } catch(EOFException& ) {
+          std::stringstream msg;
+          msg << "Parse Error in line " << linenumber << ": "
+            << "EOF while parsing constant.";
+          throw std::runtime_error(msg.str());
+        }
+
+        if(strcmp(token_string, "t") == 0)
+          return TOKEN_TRUE;
+        if(strcmp(token_string, "f") == 0)
+          return TOKEN_FALSE;
+
+        // we only handle #t and #f constants at the moment...
+
+        {
+          std::stringstream msg;
+          msg << "Parse Error in line " << linenumber << ": "
+            << "Unknown constant '" << token_string << "'.";
+          throw std::runtime_error(msg.str());
+        }
+
+      default:
+        if(isdigit(*c) || *c == '-' || *c == '.') {
+          bool have_nondigits = false;
+          bool have_digits = false;
+          int have_floating_point = 0;
+          
+          do {
+            if(isdigit(*c))
+              have_digits = true;
+            else if(*c == '.')
+              ++have_floating_point;
+            else if(isalnum(*c) || *c == '_')
+              have_nondigits = true;  
+            
+            if(token_length < MAX_TOKEN_LENGTH)
+              token_string[token_length++] = *c;
+
+            nextChar();
+          } while(!isspace(*c) && !strchr(delims, *c));
+
+          token_string[token_length] = 0;
+          
+          // no nextChar
+
+          if(have_nondigits || !have_digits || have_floating_point > 1)
+            return TOKEN_SYMBOL;
+          else if(have_floating_point == 1)
+            return TOKEN_REAL;
+          else
+            return TOKEN_INTEGER;
+        } else {
+          do {
+            if(token_length < MAX_TOKEN_LENGTH)
+              token_string[token_length++] = *c;
+            nextChar();
+          } while(!isspace(*c) && !strchr(delims, *c));
+          token_string[token_length] = 0;
+          
+          // no nextChar
+
+          return TOKEN_SYMBOL;
+        }       
+    }
+  } catch(EOFException& ) {
+    return TOKEN_EOF;
+  }
+}
+
+} // end of namespace lisp
+

Added: branches/pingus_sdl/src/lisp/lexer.hpp
===================================================================
--- branches/pingus_sdl/src/lisp/lexer.hpp      2007-01-13 21:37:11 UTC (rev 
2640)
+++ branches/pingus_sdl/src/lisp/lexer.hpp      2007-01-13 23:42:24 UTC (rev 
2641)
@@ -0,0 +1,70 @@
+//  $Id: lexer.h 2379 2005-05-01 19:02:16Z matzebraun $
+//
+//  Copyright (C) 2004 Matthias Braun <address@hidden>
+//  code in this file based on lispreader from Mark Probst
+//
+//  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#ifndef __LISPLEXER_H__
+#define __LISPLEXER_H__
+
+namespace lisp
+{
+
+class Lexer
+{
+public:
+  enum TokenType {
+    TOKEN_EOF,
+    TOKEN_OPEN_PAREN,
+    TOKEN_CLOSE_PAREN,
+    TOKEN_SYMBOL,
+    TOKEN_STRING,
+    TOKEN_INTEGER,
+    TOKEN_REAL,
+    TOKEN_TRUE,
+    TOKEN_FALSE
+  };
+    
+  Lexer(std::istream& stream);
+  ~Lexer();
+
+  TokenType getNextToken();
+  const char* getString() const
+  { return token_string; }
+  int getLineNumber() const
+  { return linenumber; }
+    
+private:
+  enum {
+    MAX_TOKEN_LENGTH = 16384,
+    BUFFER_SIZE = 1024
+  };
+    
+  inline void nextChar();
+    
+  std::istream& stream;
+  bool eof;
+  int linenumber;
+  char buffer[BUFFER_SIZE+1];
+  char* bufend;
+  char* c;
+  char token_string[MAX_TOKEN_LENGTH + 1];
+  int token_length;
+};
+
+} // end of namespace lisp
+
+#endif
+

Added: branches/pingus_sdl/src/lisp/lisp.cpp
===================================================================
--- branches/pingus_sdl/src/lisp/lisp.cpp       2007-01-13 21:37:11 UTC (rev 
2640)
+++ branches/pingus_sdl/src/lisp/lisp.cpp       2007-01-13 23:42:24 UTC (rev 
2641)
@@ -0,0 +1,111 @@
+//  $Id: lisp.cpp 2379 2005-05-01 19:02:16Z matzebraun $
+//
+//  TuxKart - a fun racing game with go-kart
+//  Copyright (C) 2004 Matthias Braun <address@hidden>
+//  code in this file based on lispreader from Mark Probst
+//
+//  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#include <config.h>
+#include <assert.h>
+#include "lisp.hpp"
+
+namespace lisp
+{
+    
+Lisp::Lisp(int val)
+  : type(TYPE_INT)
+{
+  v.int_ = val;
+}
+
+Lisp::Lisp(float val)
+  : type(TYPE_FLOAT)
+{
+  v.float_ = val;
+}
+
+Lisp::Lisp(bool val)
+  : type(TYPE_BOOL)
+{
+  v.bool_ = val;
+}
+
+Lisp::Lisp(LispType newtype, const std::string& str)
+  : type(newtype)
+{
+  assert(newtype == TYPE_SYMBOL || type == TYPE_STRING);
+  v.string = new char[str.size()+1];
+  memcpy(v.string, str.c_str(), str.size()+1);
+}
+
+Lisp::Lisp(const std::vector<Lisp*>& list_elements)
+  : type(TYPE_LIST)
+{
+  v.list.size = list_elements.size();
+  v.list.entries = new Lisp* [v.list.size];
+  for(size_t i = 0; i < v.list.size; ++i) {
+    v.list.entries[i] = list_elements[i];
+  }
+}
+
+Lisp::~Lisp()
+{
+  if(type == TYPE_SYMBOL || type == TYPE_STRING) {
+    delete[] v.string;
+  } else if(type == TYPE_LIST) {
+    for(size_t i = 0; i < v.list.size; ++i)
+      delete v.list.entries[i];
+    delete[] v.list.entries;
+  }
+}
+
+void
+Lisp::print(std::ostream& out, int indent) const
+{
+  for(int i = 0; i < indent; ++i)
+    out << ' ';
+ 
+  switch(type) {
+    case TYPE_LIST:
+      out << "(\n";
+      for(size_t i = 0; i < v.list.size; ++i)
+        v.list.entries[i]->print(out, indent+2);
+      for(int i = 0; i < indent; ++i)
+        out << ' ';                      
+      out << ")";
+      break;
+    case TYPE_STRING:
+      out << '\'' << v.string << '\'';
+      break;
+    case TYPE_INT:
+      out << v.int_;
+      break;
+    case TYPE_FLOAT:
+      out << v.float_;
+      break;
+    case TYPE_SYMBOL:
+      out << v.string;
+      break;
+    case TYPE_BOOL:
+      out << (v.bool_ ? "true" : "false");
+      break;
+    default:
+      out << "UNKNOWN?!?";
+      break;
+  }
+  out << '\n';
+}
+
+} // end of namespace lisp

Added: branches/pingus_sdl/src/lisp/lisp.hpp
===================================================================
--- branches/pingus_sdl/src/lisp/lisp.hpp       2007-01-13 21:37:11 UTC (rev 
2640)
+++ branches/pingus_sdl/src/lisp/lisp.hpp       2007-01-13 23:42:24 UTC (rev 
2641)
@@ -0,0 +1,120 @@
+//  $Id: lisp.h 2419 2005-05-06 19:08:24Z matzebraun $
+//
+//  Copyright (C) 2004 Matthias Braun <address@hidden>
+//  code in this file based on lispreader from Mark Probst
+//
+//  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#ifndef __LISP_HPP__
+#define __LISP_HPP__
+
+#include <string>
+#include <vector>
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+#include <assert.h>
+
+namespace lisp
+{
+
+class Lisp
+{
+public:
+  enum LispType {
+    TYPE_LIST,
+    TYPE_SYMBOL,
+    TYPE_INT,
+    TYPE_STRING,
+    TYPE_FLOAT,
+    TYPE_BOOL
+  };
+
+  /// construct a new Lisp object symbol or string object
+  Lisp(LispType newtype, const std::string& value);
+  Lisp(const std::vector<Lisp*>& list_elements);
+  Lisp(int val);
+  Lisp(float val);
+  Lisp(bool val);
+  ~Lisp();                                             
+
+  LispType get_type() const
+  { return type; } 
+
+  size_t get_list_size() const
+  {
+    return v.list.size;
+  }
+  Lisp* get_list_elem(size_t i) const
+  {
+    assert(i < v.list.size);
+    return v.list.entries[i];
+  }
+
+  const char* get_string() const
+  {
+    if(type != TYPE_STRING)
+      throw std::runtime_error("Lisp is not a string");
+    return v.string;
+  }
+
+  const char* get_symbol() const
+  {
+    if(type != TYPE_SYMBOL)
+      throw std::runtime_error("Lisp is not a symbol");
+    return v.string;
+  }
+
+  int get_int() const
+  {
+    if(type != TYPE_INT)
+      throw std::runtime_error("Lisp is not an int");
+    return v.int_;
+  }
+
+  float get_float() const
+  {
+    if(type != TYPE_FLOAT)
+      throw std::runtime_error("Lisp is not a float");
+    return v.float_;
+  }
+
+  bool get_bool() const
+  {
+    if(type != TYPE_BOOL)
+      throw std::runtime_error("Lisp is not a bool");
+    return v.bool_;
+  }
+
+  void print(std::ostream& out = std::cout, int indent = 0) const;
+
+private:
+  union
+  {
+    struct {
+      Lisp** entries;
+      size_t size;
+    } list;
+    char* string;
+    int int_;
+    bool bool_;
+    float float_;
+  } v;
+  LispType type;
+};
+
+} // end of namespace lisp
+
+#endif
+

Added: branches/pingus_sdl/src/lisp/parser.cpp
===================================================================
--- branches/pingus_sdl/src/lisp/parser.cpp     2007-01-13 21:37:11 UTC (rev 
2640)
+++ branches/pingus_sdl/src/lisp/parser.cpp     2007-01-13 23:42:24 UTC (rev 
2641)
@@ -0,0 +1,196 @@
+//  $Id: parser.cpp 2575 2005-06-07 15:59:27Z matzebraun $
+//
+//  TuxKart - a fun racing game with go-kart
+//  Copyright (C) 2004 Matthias Braun <address@hidden>
+//  code in this file based on lispreader from Mark Probst
+//
+//  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#include <config.h>
+
+#include <sstream>
+#include <cassert>
+#include <iostream>
+#include <string>
+#include <exception>
+
+#include "../tinygettext/tinygettext.hxx"
+#include "physfs/physfs_stream.hpp"
+#include "parser.hpp"
+#include "lisp.hpp"
+
+namespace lisp
+{
+
+class ParseError : public std::exception
+{
+public:
+  ParseError(const Parser* parser, const std::string& message) throw()
+  {
+    std::ostringstream msg;
+    msg << "Parse error in file '" << parser->filename << "' line "
+      << parser->lexer->getLineNumber() << ": " << message;
+    string = msg.str();
+  }
+  ~ParseError() throw()
+  {}
+
+  const char* what() const throw()
+  {
+    return string.c_str();
+  }
+
+private:
+  std::string string;
+};
+
+Parser::Parser()
+  : lexer(0), dictionary_manager(0), dictionary(0)
+{
+  dictionary_manager = new TinyGetText::DictionaryManager();
+  dictionary_manager->set_charset("UTF-8");
+}
+
+Parser::~Parser()
+{
+  delete lexer;
+  delete dictionary_manager;
+}
+
+static std::string dirname(std::string filename)
+{
+  std::string::size_type p = filename.find_last_of('/');
+  if(p == std::string::npos)
+    return "";
+
+  return filename.substr(0, p+1);
+}
+
+Lisp*
+Parser::parse(const std::string& filename)
+{
+  IFileStream in(filename);
+  if(!in.good()) {
+    std::stringstream msg;
+    msg << "Parser problem: Couldn't open file '" << filename << "'.";
+    throw std::runtime_error(msg.str());
+  }
+
+  return parse(in, filename);
+}
+
+Lisp*
+Parser::parse(std::istream& stream, const std::string& filename)
+{
+  std::auto_ptr<Parser> parser (new Parser());
+
+  parser->filename = filename;
+  parser->dictionary_manager->add_directory(dirname(filename));
+  parser->dictionary = & (parser->dictionary_manager->get_dictionary());
+  parser->lexer = new Lexer(stream);
+
+  parser->token = parser->lexer->getNextToken();
+  if(parser->token != Lexer::TOKEN_OPEN_PAREN)
+    throw ParseError(parser.get(), "file doesn't start with '('");
+
+  std::auto_ptr<Lisp> result (parser->parse());
+  if(parser->token != Lexer::TOKEN_EOF) {
+    if(parser->token == Lexer::TOKEN_CLOSE_PAREN)
+      throw ParseError(parser.get(), "too many ')'");
+    else
+      throw ParseError(parser.get(), "extra tokens at end of file");
+  }
+    
+  return result.release();
+}
+
+Lisp*
+Parser::parse()
+{
+  std::vector<Lisp*> entries;
+  try {
+    while(token != Lexer::TOKEN_CLOSE_PAREN && token != Lexer::TOKEN_EOF) {
+      switch(token) {
+        case Lexer::TOKEN_OPEN_PAREN:
+          token = lexer->getNextToken();
+        
+          // Handle (_ "blup") strings that need to be translated
+          if(token == Lexer::TOKEN_SYMBOL
+              && strcmp(lexer->getString(), "_") == 0) {
+            token = lexer->getNextToken();
+            if(token != Lexer::TOKEN_STRING)
+              throw ParseError(this, "Expected string after '(_' sequence");
+            if(dictionary) {
+              std::string translation = 
dictionary->translate(lexer->getString());
+              entries.push_back(new Lisp(Lisp::TYPE_STRING, translation));
+            } else {
+              entries.push_back(new Lisp(Lisp::TYPE_STRING, 
lexer->getString()));
+            }
+            
+            token = lexer->getNextToken();
+            if(token != Lexer::TOKEN_CLOSE_PAREN)
+              throw ParseError(this, "Expected ')' after '(_ ""' sequence");
+            break;
+          }
+        
+          entries.push_back(parse());
+          if(token != Lexer::TOKEN_CLOSE_PAREN) {
+            if(token == Lexer::TOKEN_EOF)
+              throw ParseError(this, "Expected ')' token, got EOF");
+            else
+              throw ParseError(this, "Expected ')' token");
+          }
+          break;
+        case Lexer::TOKEN_SYMBOL:
+          entries.push_back(new Lisp(Lisp::TYPE_SYMBOL, lexer->getString()));
+          break;
+        case Lexer::TOKEN_STRING:
+          entries.push_back(new Lisp(Lisp::TYPE_STRING, lexer->getString()));
+          break;
+        case Lexer::TOKEN_INTEGER: {
+          int val;
+          sscanf(lexer->getString(), "%d", &val);
+          entries.push_back(new Lisp(val));
+          break;
+        }
+        case Lexer::TOKEN_REAL: {
+          float val;
+          sscanf(lexer->getString(), "%f", &val);
+          entries.push_back(new Lisp(val));
+          break;
+        }
+        case Lexer::TOKEN_TRUE:
+          entries.push_back(new Lisp(true));
+          break;
+        case Lexer::TOKEN_FALSE:
+          entries.push_back(new Lisp(false));
+          break;
+        default:
+          // this should never happen
+          assert(false);
+      }
+
+      token = lexer->getNextToken();
+    }
+  } catch(...) {
+    for(std::vector<Lisp*>::iterator i = entries.begin();
+        i != entries.end(); ++i)
+      delete *i;
+    throw;
+  }
+  
+  return new Lisp(entries);
+}
+
+} // end of namespace lisp

Added: branches/pingus_sdl/src/lisp/parser.hpp
===================================================================
--- branches/pingus_sdl/src/lisp/parser.hpp     2007-01-13 21:37:11 UTC (rev 
2640)
+++ branches/pingus_sdl/src/lisp/parser.hpp     2007-01-13 23:42:24 UTC (rev 
2641)
@@ -0,0 +1,59 @@
+//  $Id: parser.h 2379 2005-05-01 19:02:16Z matzebraun $
+//
+//  TuxKart - a fun racing game with go-kart
+//  Copyright (C) 2004 Matthias Braun <address@hidden>
+//
+//  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#ifndef __LISPPARSER_H__
+#define __LISPPARSER_H__
+
+#include <string>
+#include "lexer.hpp"
+
+namespace TinyGetText {
+class Dictionary;
+class DictionaryManager;
+}
+
+namespace lisp
+{
+
+class Lisp;
+
+class Parser
+{
+public:
+  ~Parser();
+  static Lisp* parse(const std::string& filename);
+  static Lisp* parse(std::istream& stream, const std::string& filename = "");
+
+private:
+  friend class ParseError;
+
+  Parser();
+  
+  Lisp* parse();
+  
+  std::string filename;
+  Lexer* lexer;
+  TinyGetText::DictionaryManager* dictionary_manager;
+  TinyGetText::Dictionary* dictionary;
+  Lexer::TokenType token;
+};
+
+} // end of namespace lisp
+
+#endif
+

Added: branches/pingus_sdl/src/lisp/properties.cpp
===================================================================
--- branches/pingus_sdl/src/lisp/properties.cpp 2007-01-13 21:37:11 UTC (rev 
2640)
+++ branches/pingus_sdl/src/lisp/properties.cpp 2007-01-13 23:42:24 UTC (rev 
2641)
@@ -0,0 +1,51 @@
+#include <config.h>
+
+#include "lisp.hpp"
+#include "properties.hpp"
+
+namespace lisp
+{
+
+Properties::Properties(const Lisp* lisp)
+{
+  if (lisp)
+    {
+      if(lisp->get_type() != Lisp::TYPE_LIST)
+        throw std::runtime_error("Lisp is not a list");
+
+      for(size_t i = 0; i < lisp->get_list_size(); ++i) {
+        const Lisp* child = lisp->get_list_elem(i);
+        if(i == 0 && child->get_type() == Lisp::TYPE_SYMBOL)
+          continue;
+        if(child->get_type() != Lisp::TYPE_LIST)
+          throw std::runtime_error("child of properties lisp is not a list");
+        if(child->get_list_size() > 1)
+          {    
+            const Lisp* name = child->get_list_elem(0);
+            if(name->get_type() != Lisp::TYPE_SYMBOL)
+              throw std::runtime_error("property has no symbol as name");
+            properties.insert(std::make_pair(
+                                             std::string(name->get_symbol()), 
ListEntry(child)));
+          }
+      }
+    }
+}
+
+Properties::~Properties()
+{
+}
+
+void
+Properties::print_unused_warnings(const std::string& context) const
+{
+  for(PropertyMap::const_iterator i = properties.begin();
+      i != properties.end(); ++i) {
+    if(i->second.used)
+      continue;
+
+    std::cout << "Warning: property '" << i->first << "' not used (in "
+              << context << ")\n";
+  }
+}
+
+}

Added: branches/pingus_sdl/src/lisp/properties.hpp
===================================================================
--- branches/pingus_sdl/src/lisp/properties.hpp 2007-01-13 21:37:11 UTC (rev 
2640)
+++ branches/pingus_sdl/src/lisp/properties.hpp 2007-01-13 23:42:24 UTC (rev 
2641)
@@ -0,0 +1,85 @@
+#ifndef __PROPERTIES_HPP__
+#define __PROPERTIES_HPP__
+
+#include <vector>
+#include "getters.hpp"
+#include "property_iterator.hpp"
+
+namespace lisp
+{
+
+class Properties
+{
+public:
+  Properties(const lisp::Lisp* lisp);
+  ~Properties();
+
+  /**
+   * fetches the value of a property. returns true if the property was defined
+   * and could be converted into the target type, false otherwise.
+   * You have to define get() or property_get() functions to support new
+   * datatypes. See getters.hpp for details
+   */
+  template<typename T>
+  bool get(const std::string& name, T& val)
+  {
+    PropertyMap::iterator i = properties.find(name);
+    if(i == properties.end())
+      return false;
+    if(property_get(i->second.lisp, val) == false)
+      return false;
+    i->second.used = true;
+    return true;
+  }
+
+  /** 
+   * Ignore a property so that it doesn't give a warning, usefull for
+   * example if some tags are only used by the editor but not by the
+   * game.
+   */
+  void ignore(const std::string& name)
+  {
+    PropertyMap::iterator i = properties.find(name);
+    if(i != properties.end())
+      i->second.used = true;
+  }
+
+  /**
+   * returns an iterator over all properties with a certain name
+   */
+  template<typename T>
+  bool get_iter(const std::string& name, PropertyIterator<T>& iter)
+  {
+    PropertyMap::iterator beg = properties.lower_bound(name);
+    if(beg == properties.end() || beg->first != name) {
+      iter = PropertyIterator<T>(properties.end(), properties.end());
+      return false;
+    }
+    PropertyMap::iterator end = properties.upper_bound(name);
+        
+    iter = PropertyIterator<T>(beg, end);
+    return true;
+  }
+
+  /**
+   * returns an iterator over all properties
+   */
+  PropertyIterator<const Lisp*> get_iter()
+  {
+    return PropertyIterator<const Lisp*>(properties.begin(), properties.end());
+  }
+
+  /**
+   * Prints a warning for properties that have not been accessed. This 
typically
+   * indicates typos that the user should know about
+   */
+  void print_unused_warnings(const std::string& context) const;
+
+private:
+  PropertyMap properties;
+};
+
+}
+
+#endif
+

Added: branches/pingus_sdl/src/lisp/property_iterator.hpp
===================================================================
--- branches/pingus_sdl/src/lisp/property_iterator.hpp  2007-01-13 21:37:11 UTC 
(rev 2640)
+++ branches/pingus_sdl/src/lisp/property_iterator.hpp  2007-01-13 23:42:24 UTC 
(rev 2641)
@@ -0,0 +1,74 @@
+#ifndef __PROPERTY_ITERATOR_HPP__
+#define __PROPERTY_ITERATOR_HPP__
+
+#include <map>
+#include <string>
+
+namespace lisp
+{
+
+struct ListEntry {
+  ListEntry(const lisp::Lisp* lisp)
+    : lisp(lisp), used(false)
+  {}
+  
+  const Lisp* lisp;
+  bool used;
+};
+typedef std::multimap<std::string, ListEntry> PropertyMap;
+
+template<typename T>
+class PropertyIterator
+{
+public:
+  PropertyIterator()
+  {
+    end = i;
+  }
+
+  T* operator ->() const
+  {
+    return &currentval;
+  }
+  T operator*() const
+  {
+    return currentval;
+  }
+  bool next() {
+    bool res;
+    do {
+      if(i == end)
+        return false;
+      res = property_get(i->second.lisp, currentval);
+      if(res) {
+        i->second.used = true;
+        current_item = i->first;
+      }
+      ++i;
+      if(res)
+        return true;
+    } while(true);
+  }
+  
+  const std::string& item() const
+  {
+    return current_item;
+  }
+  
+private:
+  friend class Properties;
+
+  PropertyIterator(PropertyMap::iterator begin, PropertyMap::iterator end)
+    : i(begin), end(end)
+  {
+  }
+    
+  PropertyMap::iterator i;
+  PropertyMap::iterator end;
+  std::string current_item;
+  T currentval;
+};
+
+}
+
+#endif

Added: branches/pingus_sdl/src/lisp/writer.cpp
===================================================================
--- branches/pingus_sdl/src/lisp/writer.cpp     2007-01-13 21:37:11 UTC (rev 
2640)
+++ branches/pingus_sdl/src/lisp/writer.cpp     2007-01-13 23:42:24 UTC (rev 
2641)
@@ -0,0 +1,152 @@
+//  $Id: writer.cpp 2575 2005-06-07 15:59:27Z matzebraun $
+//
+//  SuperTux -  A Jump'n Run
+//  Copyright (C) 2004 Matthias Braun <address@hidden
+//
+//  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#include <config.h>
+
+#include <iostream>
+
+#include "writer.hpp"
+#include "physfs/physfs_stream.hpp"
+
+namespace lisp
+{
+
+Writer::Writer(const std::string& filename)
+{
+  out = new OFileStream(filename);
+  out_owned = true;
+  indent_depth = 0;
+}
+  
+Writer::Writer(std::ostream* newout)
+{
+  out = newout;
+  out_owned = false;
+  indent_depth = 0;
+}
+
+Writer::~Writer()
+{
+  if(lists.size() > 0) {
+    std::cerr << "Warning: Not all sections closed in lispwriter!\n";
+  }
+  if(out_owned)
+    delete out;
+}
+
+void
+Writer::write_comment(const std::string& comment)
+{
+  *out << "; " << comment << "\n";
+}
+
+void
+Writer::start_list(const std::string& listname)
+{
+  indent();
+  *out << '(' << listname << '\n';
+  indent_depth += 2;
+
+  lists.push_back(listname);
+}
+
+void
+Writer::end_list(const std::string& listname)
+{
+  if(lists.size() == 0) {
+    std::cerr << "Trying to close list '" << listname 
+              << "', which is not open.\n";
+    return;
+  }
+  if(lists.back() != listname) {
+    std::cerr << "Warning: trying to close list '" << listname 
+              << "' while list '" << lists.back() << "' is open.\n";
+    return;
+  }
+  lists.pop_back();
+  
+  indent_depth -= 2;
+  indent();
+  *out << ")\n";
+}
+
+void
+Writer::write_int(const std::string& name, int value)
+{
+  indent();
+  *out << '(' << name << ' ' << value << ")\n";
+}
+
+void
+Writer::write_float(const std::string& name, float value)
+{
+  indent();
+  *out << '(' << name << ' ' << value << ")\n";
+}
+
+void
+Writer::write_string(const std::string& name, const std::string& value,
+    bool translatable)
+{
+  indent();
+  *out << '(' << name;
+  if(translatable) {
+    *out << " (_ \"" << value << "\"))\n";
+  } else {
+    *out << " \"" << value << "\")\n";
+  }
+}
+
+void
+Writer::write_bool(const std::string& name, bool value)
+{
+  indent();
+  *out << '(' << name << ' ' << (value ? "#t" : "#f") << ")\n";
+}
+
+void
+Writer::write_int_vector(const std::string& name,
+    const std::vector<int>& value)
+{
+  indent();
+  *out << '(' << name;
+  for(std::vector<int>::const_iterator i = value.begin(); i != value.end(); 
++i)
+    *out << " " << *i;
+  *out << ")\n";
+}
+
+void
+Writer::write_int_vector(const std::string& name,
+    const std::vector<unsigned int>& value)
+{
+  indent();
+  *out << '(' << name;
+  for(std::vector<unsigned int>::const_iterator i = value.begin(); i != 
value.end(); ++i)
+    *out << " " << *i;
+  *out << ")\n";
+}
+
+void
+Writer::indent()
+{
+  for(int i = 0; i<indent_depth; ++i)
+    *out << ' ';
+}
+
+} // end of namespace lisp

Added: branches/pingus_sdl/src/lisp/writer.hpp
===================================================================
--- branches/pingus_sdl/src/lisp/writer.hpp     2007-01-13 21:37:11 UTC (rev 
2640)
+++ branches/pingus_sdl/src/lisp/writer.hpp     2007-01-13 23:42:24 UTC (rev 
2641)
@@ -0,0 +1,64 @@
+//  $Id: writer.h 2575 2005-06-07 15:59:27Z matzebraun $
+//
+//  SuperTux -  A Jump'n Run
+//  Copyright (C) 2004 Matthias Braun <address@hidden
+//
+//  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#ifndef SUPERTUX_LISPWRITER_H
+#define SUPERTUX_LISPWRITER_H
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace lisp
+{
+
+  class Writer
+  {
+  public:
+    Writer(const std::string& filename);
+    Writer(std::ostream* out);
+    ~Writer();
+
+    void write_comment(const std::string& comment);
+
+    void start_list(const std::string& listname);
+
+    void write_int(const std::string& name, int value);
+    void write_float(const std::string& name, float value);
+    void write_string(const std::string& name, const std::string& value,
+        bool translatable = false);
+    void write_bool(const std::string& name, bool value);
+    void write_int_vector(const std::string& name, const std::vector<int>& 
value);
+    void write_int_vector(const std::string& name, const std::vector<unsigned 
int>& value);
+    // add more write-functions when needed...
+
+    void end_list(const std::string& listname);
+
+  private:
+    void indent();
+
+    std::ostream* out;
+    bool out_owned;
+    int indent_depth;
+    std::vector<std::string> lists;
+  };
+  
+} //namespace lisp
+
+#endif //SUPERTUX_LISPWRITER_H
+

Added: branches/pingus_sdl/src/math/vector2i.cpp
===================================================================
--- branches/pingus_sdl/src/math/vector2i.cpp   2007-01-13 21:37:11 UTC (rev 
2640)
+++ branches/pingus_sdl/src/math/vector2i.cpp   2007-01-13 23:42:24 UTC (rev 
2641)
@@ -0,0 +1,67 @@
+/*  $Id$
+**   __      __ __             ___        __   __ __   __
+**  /  \    /  \__| ____    __| _/_______/  |_|__|  | |  |   ____
+**  \   \/\/   /  |/    \  / __ |/  ___/\   __\  |  | |  | _/ __ \
+**   \        /|  |   |  \/ /_/ |\___ \  |  | |  |  |_|  |_\  ___/
+**    \__/\  / |__|___|  /\____ /____  > |__| |__|____/____/\___  >
+**         \/          \/      \/    \/                         \/
+**  Copyright (C) 2005 Ingo Ruhnke <address@hidden>
+**
+**  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., 59 Temple Place - Suite 330, Boston, MA
+**  02111-1307, USA.
+*/
+
+#include "vector2i.hpp"
+
+Vector2i
+Vector2i::operator+ (const Vector2i& add) const
+{
+  return Vector2i(x + sub.x, y + sub.y);
+}
+
+Vector2i
+Vector2i::operator- (const Vector2i& sub) const
+{
+  return Vector2i(x - sub.x, y - sub.y);
+}
+
+Vector2i
+Vector2i::operator* (int  mul) const
+{
+  return Vector2i(x * mul, y * mul);
+}
+
+Vector2i&
+Vector2i::operator+= (const Vector2i& add)
+{
+  x += sub.x;
+  y += sub.y;
+}
+
+Vector2i&
+Vector2i::operator-= (const Vector2i& sub)
+{
+  x -= sub.x;
+  y -= sub.y;
+}
+
+Vector2i&
+Vector2i::operator*= (int mul)
+{
+  x *= mul;
+  y *= mul;
+}
+
+/* EOF */

Modified: branches/pingus_sdl/src/math/vector2i.hpp
===================================================================
--- branches/pingus_sdl/src/math/vector2i.hpp   2007-01-13 21:37:11 UTC (rev 
2640)
+++ branches/pingus_sdl/src/math/vector2i.hpp   2007-01-13 23:42:24 UTC (rev 
2641)
@@ -27,9 +27,21 @@
   int x;
   int y;
 
+  Vector2i()
+    : x(0), y(0) {}
+
   Vector2i(int x_, int y_) 
     : x(x_), y(y_) {}
 
+  Vector2i operator- () const;
+
+  Vector2i operator+ (const Vector2i& add) const;
+  Vector2i operator- (const Vector2i& sub) const;
+  Vector2i operator* (int  mul) const;
+
+  Vector2i& operator+= (const Vector2i& add);
+  Vector2i& operator-= (const Vector2i& sub);
+  Vector2i& operator*= (int mul);
 };
 
 #endif

Added: branches/pingus_sdl/src/physfs/physfs_sdl.cpp
===================================================================
--- branches/pingus_sdl/src/physfs/physfs_sdl.cpp       2007-01-13 21:37:11 UTC 
(rev 2640)
+++ branches/pingus_sdl/src/physfs/physfs_sdl.cpp       2007-01-13 23:42:24 UTC 
(rev 2641)
@@ -0,0 +1,93 @@
+/*
+Copyright (C) 2005 Matthias Braun <address@hidden>
+
+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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include <config.h>
+
+#include "physfs_sdl.hpp"
+
+#include <physfs.h>
+
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+
+#include <assert.h>
+
+static int func_seek(struct SDL_RWops* context, int offset, int whence)
+{
+    PHYSFS_file* file = (PHYSFS_file*) context->hidden.unknown.data1;
+    int res;
+    switch(whence) {
+        case SEEK_SET:
+            res = PHYSFS_seek(file, offset);
+            break;
+        case SEEK_CUR:
+            res = PHYSFS_seek(file, PHYSFS_tell(file) + offset);
+            break;
+        case SEEK_END:
+            res = PHYSFS_seek(file, PHYSFS_fileLength(file) + offset);
+            break;
+        default:
+            res = 0;
+            assert(false);
+            break;
+    }
+    if(res == 0) {
+        std::cerr << "Error seeking in file: " << PHYSFS_getLastError() << 
"\n";
+        return -1;
+    }
+
+    return (int) PHYSFS_tell(file);
+}
+
+static int func_read(struct SDL_RWops* context, void* ptr, int size, int 
maxnum)
+{
+    PHYSFS_file* file = (PHYSFS_file*) context->hidden.unknown.data1;
+
+    int res = PHYSFS_read(file, ptr, size, maxnum);
+    return res;
+}
+
+static int func_close(struct SDL_RWops* context)
+{
+    PHYSFS_file* file = (PHYSFS_file*) context->hidden.unknown.data1;
+    
+    PHYSFS_close(file);
+    delete context;
+
+    return 0;
+}
+
+SDL_RWops* get_physfs_SDLRWops(const std::string& filename)
+{
+    PHYSFS_file* file = (PHYSFS_file*) PHYSFS_openRead(filename.c_str());
+    if(!file) {
+        std::stringstream msg;
+        msg << "Couldn't open '" << filename << "': "
+            << PHYSFS_getLastError();
+        throw std::runtime_error(msg.str());
+    }
+    
+    SDL_RWops* ops = new SDL_RWops();
+    ops->type = 0;
+    ops->hidden.unknown.data1 = file;
+    ops->seek = func_seek;
+    ops->read = func_read;
+    ops->write = 0;
+    ops->close = func_close;
+    return ops;
+}

Added: branches/pingus_sdl/src/physfs/physfs_sdl.hpp
===================================================================
--- branches/pingus_sdl/src/physfs/physfs_sdl.hpp       2007-01-13 21:37:11 UTC 
(rev 2640)
+++ branches/pingus_sdl/src/physfs/physfs_sdl.hpp       2007-01-13 23:42:24 UTC 
(rev 2641)
@@ -0,0 +1,27 @@
+/*
+Copyright (C) 2005 Matthias Braun <address@hidden>
+
+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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef __PHYSFSSDL_HPP__
+#define __PHYSFSSDL_HPP__
+
+#include <SDL.h>
+#include <string>
+
+SDL_RWops* get_physfs_SDLRWops(const std::string& filename);
+
+#endif
+

Added: branches/pingus_sdl/src/physfs/physfs_stream.cpp
===================================================================
--- branches/pingus_sdl/src/physfs/physfs_stream.cpp    2007-01-13 21:37:11 UTC 
(rev 2640)
+++ branches/pingus_sdl/src/physfs/physfs_stream.cpp    2007-01-13 23:42:24 UTC 
(rev 2641)
@@ -0,0 +1,173 @@
+/*
+Copyright (C) 2005 Matthias Braun <address@hidden>
+
+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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include <config.h>
+
+#include "physfs_stream.hpp"
+
+#include <assert.h>
+#include <physfs.h>
+#include <stdexcept>
+#include <sstream>
+
+IFileStreambuf::IFileStreambuf(const std::string& filename)
+{
+    file = PHYSFS_openRead(filename.c_str());
+    if(file == 0) {
+        std::stringstream msg;
+        msg << "Couldn't open file '" << filename << "': "
+            << PHYSFS_getLastError();
+        throw std::runtime_error(msg.str());
+    }
+}
+
+IFileStreambuf::~IFileStreambuf()
+{
+    PHYSFS_close(file);
+}
+
+int
+IFileStreambuf::underflow()
+{
+    if(PHYSFS_eof(file)) {
+        return traits_type::eof();
+    }
+   
+    PHYSFS_sint64 bytesread = PHYSFS_read(file, buf, 1, sizeof(buf));
+    if(bytesread <= 0) {
+        return traits_type::eof();
+    }
+    setg(buf, buf, buf + bytesread);
+
+    // without the conversation some characters (255?) would be
+    // handled like EOF
+    return traits_type::to_int_type(buf[0]);
+}
+
+IFileStreambuf::pos_type
+IFileStreambuf::seekpos(pos_type pos, std::ios_base::openmode)
+{
+  if(PHYSFS_seek(file, static_cast<PHYSFS_uint64> (pos)) == 0) {
+    return pos_type(off_type(-1));
+  }
+
+  // the seek invalidated the buffer
+  setg(buf, buf, buf);
+  return pos;
+}
+
+IFileStreambuf::pos_type
+IFileStreambuf::seekoff(off_type off, std::ios_base::seekdir dir,
+                        std::ios_base::openmode mode)
+{
+  off_type pos = off;
+  PHYSFS_sint64 ptell = PHYSFS_tell(file);
+  
+  switch(dir) {
+    case std::ios_base::beg:
+      break;
+    case std::ios_base::cur:
+      if(off == 0)
+        return static_cast<pos_type> (ptell) - static_cast<pos_type> (egptr() 
- gptr());
+      pos += static_cast<off_type> (ptell) - static_cast<off_type> (egptr() - 
gptr());
+      break;
+    case std::ios_base::end:
+      pos += static_cast<off_type> (PHYSFS_fileLength(file));
+      break;
+    default:
+#ifdef DEBUG
+      assert(false);
+#else
+      return pos_type(off_type(-1));
+#endif
+  }
+
+  return seekpos(static_cast<pos_type> (pos), mode);
+}
+
+//---------------------------------------------------------------------------
+
+OFileStreambuf::OFileStreambuf(const std::string& filename)
+{
+    file = PHYSFS_openWrite(filename.c_str());
+    if(file == 0) {
+        std::stringstream msg;
+        msg << "Couldn't open file '" << filename << "': "
+            << PHYSFS_getLastError();
+        throw std::runtime_error(msg.str());
+    }
+    
+    setp(buf, buf+sizeof(buf));
+}
+
+OFileStreambuf::~OFileStreambuf()
+{
+    sync();
+    PHYSFS_close(file);
+}
+
+int
+OFileStreambuf::overflow(int c)
+{
+    if(pbase() == pptr())
+        return 0;
+
+    size_t size = pptr() - pbase();
+    PHYSFS_sint64 res = PHYSFS_write(file, pbase(), 1, size);
+    if(res <= 0)
+        return traits_type::eof();
+    
+    if(c != traits_type::eof()) {
+        PHYSFS_sint64 res = PHYSFS_write(file, &c, 1, 1);
+        if(res <= 0)
+            return traits_type::eof();
+    }
+
+    setp(buf, buf + res);
+    return 0;
+}
+
+int
+OFileStreambuf::sync()
+{
+    return overflow(traits_type::eof());
+}
+
+//---------------------------------------------------------------------------
+
+IFileStream::IFileStream(const std::string& filename)
+    : std::istream(new IFileStreambuf(filename))
+{
+}
+
+IFileStream::~IFileStream()
+{
+    delete rdbuf();
+}
+
+//---------------------------------------------------------------------------
+
+OFileStream::OFileStream(const std::string& filename)
+    : std::ostream(new OFileStreambuf(filename))
+{
+}
+
+OFileStream::~OFileStream()
+{
+    delete rdbuf();
+}
+

Added: branches/pingus_sdl/src/physfs/physfs_stream.hpp
===================================================================
--- branches/pingus_sdl/src/physfs/physfs_stream.hpp    2007-01-13 21:37:11 UTC 
(rev 2640)
+++ branches/pingus_sdl/src/physfs/physfs_stream.hpp    2007-01-13 23:42:24 UTC 
(rev 2641)
@@ -0,0 +1,77 @@
+/*
+Copyright (C) 2004 by Matthias Braun <address@hidden>
+ 
+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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef __PHYSFSSTREAM_HPP__
+#define __PHYSFSSTREAM_HPP__
+
+#include <stdio.h>
+#include <physfs.h>
+#include <string>
+#include <streambuf>
+#include <iostream>
+
+/** This class implements a C++ streambuf object for physfs files.
+ * So that you can use normal istream operations on them
+ */
+class IFileStreambuf : public std::streambuf
+{
+public:
+    IFileStreambuf(const std::string& filename);
+    ~IFileStreambuf();
+    
+protected:
+    virtual int underflow();
+    virtual pos_type seekoff(off_type pos, std::ios_base::seekdir,
+        std::ios_base::openmode);
+    virtual pos_type seekpos(pos_type pos, std::ios_base::openmode);
+
+private:
+    PHYSFS_file* file;
+    char buf[1024];
+};
+
+class OFileStreambuf : public std::streambuf
+{
+public:
+    OFileStreambuf(const std::string& filename);
+    ~OFileStreambuf();
+
+protected:
+    virtual int overflow(int c);
+    virtual int sync();
+
+private:
+    PHYSFS_file* file;
+    char buf[1024];
+};
+
+class IFileStream : public std::istream
+{
+public:
+    IFileStream(const std::string& filename);
+    ~IFileStream();
+};
+
+class OFileStream : public std::ostream
+{
+public:
+    OFileStream(const std::string& filename);
+    ~OFileStream();
+};
+
+#endif
+

Modified: branches/pingus_sdl/src/sprite.cpp
===================================================================
--- branches/pingus_sdl/src/sprite.cpp  2007-01-13 21:37:11 UTC (rev 2640)
+++ branches/pingus_sdl/src/sprite.cpp  2007-01-13 23:42:24 UTC (rev 2641)
@@ -27,6 +27,8 @@
 #include <sstream>
 #include <assert.h>
 #include "SDL.h"
+#include "origin.hpp"
+#include "math/vector2i.hpp"
 #include "SDL_image.h"
 #include "sprite.hpp"
 
@@ -34,6 +36,8 @@
 {
 public:
   SDL_Surface* surface;
+  Vector2i     offset;
+  Origin       origin;
 
   SpriteImpl(const std::string& name) 
   {
@@ -50,7 +54,27 @@
       {
         std::cout << "Loaded sprite: " << name << std::endl;
       }
+
+    //offset.x = surface->w/2;
+    //offset.y = surface->h/2;
   }
+
+  ~SpriteImpl()
+  {
+    SDL_FreeSurface(surface);
+  }
+
+  void draw(float x, float y, SDL_Surface* target)
+  {
+    SDL_Rect pos;
+    
+    pos.x = (Sint16)(x - offset.x);
+    pos.y = (Sint16)(y - offset.y);
+    pos.w = 0;
+    pos.h = 0;
+    
+    SDL_BlitSurface(surface, NULL, target, &pos);
+  }
 };
 
 Sprite::Sprite()
@@ -71,12 +95,7 @@
 Sprite::draw(float x, float y, SDL_Surface* target)
 {
   //std::cout << "Sprite: draw; " << x << ", " << y << std::endl;
-  SDL_Rect pos;
-  pos.x = (Sint16)x;
-  pos.y = (Sint16)y;
-  pos.w = 0;
-  pos.h = 0;
-  SDL_BlitSurface(impl->surface, NULL, target, &pos);
+  impl->draw(x, y, target);
 }
 
 int





reply via email to

[Prev in Thread] Current Thread [Next in Thread]