Added support for silver's Benjamin font.
[supertux.git] / src / text.cpp
index f095ab5..6e66f3d 100644 (file)
@@ -1,14 +1,22 @@
+//  $Id$
+// 
+//  SuperTux
+//  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
 //
-// C Implementation: text
-//
-// Description:
-//
-//
-// Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
-//
-// Copyright: See COPYING file that comes with this distribution
-//
+//  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 <stdlib.h>
 #include <string.h>
 #include "screen.h"
 #include "text.h"
 
-void text_load(text_type* ptext, const std::string& file, int kind, int w, int h)
+Text::Text(const std::string& file, int kind_, int w_, int h_)
 {
+  kind = kind_;
+  w = w_;
+  h = h_;
+
   int mx, my;
   SDL_Surface *conv;
   int pixels;
@@ -39,14 +51,11 @@ void text_load(text_type* ptext, const std::string& file, int kind, int w, int h
       mx = 0;
       my = 0;
     }
-  ptext->kind = kind;
-  ptext->w = w;
-  ptext->h = h;
 
-  ptext->chars = new Surface(file, USE_ALPHA);
+  chars = new Surface(file, USE_ALPHA);
 
-  /* Load shadow font. */
-  conv = SDL_DisplayFormatAlpha(ptext->chars->impl->sdl_surface);
+  // Load shadow font.
+  conv = SDL_DisplayFormatAlpha(chars->impl->get_sdl_surface());
   pixels = conv->w * conv->h;
   SDL_LockSurface(conv);
   for(i = 0; i < pixels; ++i)
@@ -56,51 +65,62 @@ void text_load(text_type* ptext, const std::string& file, int kind, int w, int h
     }
   SDL_UnlockSurface(conv);
   SDL_SetAlpha(conv, SDL_SRCALPHA, 128);
-  ptext->shadow_chars = new Surface(conv, USE_ALPHA);
+  shadow_chars = new Surface(conv, USE_ALPHA);
 
   SDL_FreeSurface(conv);
 }
 
-void text_draw(text_type* ptext,const  char* text, int x, int y, int shadowsize, int update)
+Text::~Text()
+{
+  delete chars;
+  delete shadow_chars;
+}
+
+void
+Text::draw(const  char* text, int x, int y, int shadowsize, int update)
 {
   if(text != NULL)
     {
       if(shadowsize != 0)
-        text_draw_chars(ptext, ptext->shadow_chars, text,x+shadowsize,y+shadowsize, update);
+        draw_chars(shadow_chars, text,x+shadowsize,y+shadowsize, update);
 
-      text_draw_chars(ptext, ptext->chars, text,x,y, update);
+      draw_chars(chars, text,x,y, update);
     }
 }
 
-void text_draw_chars(text_type* ptext, Surface* pchars,const  char* text, int x, int y, int update)
+void
+Text::draw_chars(Surface* pchars,const  char* text, int x, int y, int update)
 {
   int i,j,len;
-  int w, h;
 
   len = strlen(text);
-  w = ptext->w;
-  h = ptext->h;
+  int w = this->w;
+  int h = this->h;
 
-  if(ptext->kind == TEXT_TEXT)
+  if(kind == TEXT_TEXT)
     {
       for( i = 0, j = 0; i < len; ++i,++j)
         {
-          if( text[i] >= 'A' && text[i] <= 'Z')
-            pchars->draw_part((int)(text[i] - 'A')*w, 0, x+(j*w), y, ptext->w, ptext->h, 255,  update);
-          else if( text[i] >= 'a' && text[i] <= 'z')
-            pchars->draw_part((int)(text[i] - 'a')*w, h, x+(j*w), y, ptext->w, ptext->h, 255,  update);
-          else if ( text[i] >= '!' && text[i] <= '9')
-            pchars->draw_part((int)(text[i] - '!')*w, h*2, x+(j*w), y, ptext->w, ptext->h, 255,  update);
-          else if ( text[i] == '?')
-            pchars->draw_part(25*w, h*2, x+(j*w), y, ptext->w, ptext->h, 255,  update);
+          if( text[i] >= ' ' && text[i] <= '/')
+            pchars->draw_part((int)(text[i] - ' ')*w,  0 , x+(j*w), y, w, h, 255,  update);
+          else if( text[i] >= '0' && text[i] <= '?')
+            pchars->draw_part((int)(text[i] - '0')*w, h*1, x+(j*w), y, w, h, 255,  update);
+          else if ( text[i] >= '@' && text[i] <= 'O')
+            pchars->draw_part((int)(text[i] - '@')*w, h*2, x+(j*w), y, w, h, 255,  update);
+          else if ( text[i] >= 'P' && text[i] <= '_')
+            pchars->draw_part((int)(text[i] - 'P')*w, h*3, x+(j*w), y, w, h, 255,  update);
+          else if ( text[i] >= '`' && text[i] <= 'o')
+            pchars->draw_part((int)(text[i] - '`')*w, h*4, x+(j*w), y, w, h, 255,  update);
+          else if ( text[i] >= 'p' && text[i] <= '~')
+            pchars->draw_part((int)(text[i] - 'p')*w, h*5, x+(j*w), y, w, h, 255,  update);
           else if ( text[i] == '\n')
             {
-              y += ptext->h + 2;
+              y += h + 2;
               j = 0;
             }
         }
     }
-  else if(ptext->kind == TEXT_NUM)
+  else if(kind == TEXT_NUM)
     {
       for( i = 0, j = 0; i < len; ++i, ++j)
         {
@@ -108,25 +128,26 @@ void text_draw_chars(text_type* ptext, Surface* pchars,const  char* text, int x,
             pchars->draw_part((int)(text[i] - '0')*w, 0, x+(j*w), y, w, h, 255, update);
           else if ( text[i] == '\n')
             {
-              y += ptext->h + 2;
+              y += h + 2;
               j = 0;
             }
         }
     }
 }
 
-void text_draw_align(text_type* ptext, const char* text, int x, int y,
-                     TextHAlign halign, TextVAlign valign, int shadowsize, int update)
+void
+Text::draw_align(const char* text, int x, int y,
+                      TextHAlign halign, TextVAlign valign, int shadowsize, int update)
 {
   if(text != NULL)
     {
       switch (halign)
         {
         case A_RIGHT:
-          x += -(strlen(text)*ptext->w);
+          x += -(strlen(text)*w);
           break;
         case A_HMIDDLE:
-          x += -((strlen(text)*ptext->w)/2);
+          x += -((strlen(text)*w)/2);
           break;
         case A_LEFT:
           // default
@@ -136,58 +157,52 @@ void text_draw_align(text_type* ptext, const char* text, int x, int y,
       switch (valign)
         {
         case A_BOTTOM:
-          y -= ptext->h;
+          y -= h;
           break;
           
         case A_VMIDDLE:
-          y -= ptext->h/2;
+          y -= h/2;
 
         case A_TOP:
           // default
           break;
         }
 
-      text_draw(ptext, text, x, y, shadowsize, update);
+      draw(text, x, y, shadowsize, update);
     }
 }
 
-void text_drawf(text_type* ptext,const  char* text, int x, int y, TextHAlign halign, TextVAlign valign, int shadowsize, int update)
+void
+Text::drawf(const  char* text, int x, int y,
+                 TextHAlign halign, TextVAlign valign, int shadowsize, int update)
 {
   if(text != NULL)
     {
       if(halign == A_RIGHT)  /* FIXME: this doesn't work correctly for strings with newlines.*/
-        x += screen->w - (strlen(text)*ptext->w);
+        x += screen->w - (strlen(text)*w);
       else if(halign == A_HMIDDLE)
-        x += screen->w/2 - ((strlen(text)*ptext->w)/2);
+        x += screen->w/2 - ((strlen(text)*w)/2);
 
       if(valign == A_BOTTOM)
-        y += screen->h - ptext->h;
+        y += screen->h - h;
       else if(valign == A_VMIDDLE)
-        y += screen->h/2 - ptext->h/2;
+        y += screen->h/2 - h/2;
 
-      text_draw(ptext,text,x,y,shadowsize, update);
+      draw(text,x,y,shadowsize, update);
     }
 }
 
-void text_free(text_type* ptext)
-{
-  if(ptext->kind == TEXT_TEXT)
-    delete ptext->chars;
-  else if(ptext->kind == TEXT_NUM)
-    delete ptext->chars;
-}
-
 /* --- ERASE TEXT: --- */
 
-void erasetext(text_type* ptext,const  char * text, int x, int y, Surface * ptexture, int update, int shadowsize)
+void
+Text::erasetext(const  char * text, int x, int y, Surface * ptexture, int update, int shadowsize)
 {
   SDL_Rect dest;
 
-
   dest.x = x;
   dest.y = y;
-  dest.w = strlen(text) * ptext->w + shadowsize;
-  dest.h = ptext->h;
+  dest.w = strlen(text) * w + shadowsize;
+  dest.h = h;
 
   if (dest.w > screen->w)
     dest.w = screen->w;
@@ -201,7 +216,155 @@ void erasetext(text_type* ptext,const  char * text, int x, int y, Surface * ptex
 
 /* --- ERASE CENTERED TEXT: --- */
 
-void erasecenteredtext(text_type* ptext,const  char * text, int y, Surface * ptexture, int update, int shadowsize)
+void
+Text::erasecenteredtext(const  char * text, int y, Surface * ptexture, int update, int shadowsize)
+{
+  erasetext(text, screen->w / 2 - (strlen(text) * 8), y, ptexture, update, shadowsize);
+}
+
+
+/* --- SCROLL TEXT FUNCTION --- */
+
+#define MAX_VEL     10
+#define SPEED_INC   0.01
+#define SCROLL      60
+#define ITEMS_SPACE 4
+
+void display_text_file(const std::string& file, const std::string& surface, float scroll_speed)
 {
-  erasetext(ptext, text, screen->w / 2 - (strlen(text) * 8), y, ptexture, update, shadowsize);
+  Surface* sur = new Surface(datadir + surface, IGNORE_ALPHA);
+  display_text_file(file, sur, scroll_speed);
+  delete sur;
 }
+
+void display_text_file(const std::string& file, Surface* surface, float scroll_speed)
+{
+  int done;
+  float scroll;
+  float speed;
+  int y;
+  int length;
+  FILE* fi;
+  char temp[1024];
+  string_list_type names;
+  char filename[1024];
+  string_list_init(&names);
+  sprintf(filename,"%s/%s", datadir.c_str(), file.c_str());
+  if((fi = fopen(filename,"r")) != NULL)
+    {
+      while(fgets(temp, sizeof(temp), fi) != NULL)
+        {
+          temp[strlen(temp)-1]='\0';
+          string_list_add_item(&names,temp);
+        }
+      fclose(fi);
+    }
+  else
+    {
+      string_list_add_item(&names,"File was not found!");
+      string_list_add_item(&names,filename);
+      string_list_add_item(&names,"Shame on the guy, who");
+      string_list_add_item(&names,"forgot to include it");
+      string_list_add_item(&names,"in your SuperTux distribution.");
+    }
+
+
+  scroll = 0;
+  speed = scroll_speed / 50;
+  done = 0;
+
+  length = names.num_items;
+
+  SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
+
+  Uint32 lastticks = SDL_GetTicks();
+  while(done == 0)
+    {
+      /* in case of input, exit */
+      SDL_Event event;
+      while(SDL_PollEvent(&event))
+        switch(event.type)
+          {
+          case SDL_KEYDOWN:
+            switch(event.key.keysym.sym)
+              {
+              case SDLK_UP:
+                speed -= SPEED_INC;
+                break;
+              case SDLK_DOWN:
+                speed += SPEED_INC;
+                break;
+              case SDLK_SPACE:
+              case SDLK_RETURN:
+                if(speed >= 0)
+                  scroll += SCROLL;
+                break;
+              case SDLK_ESCAPE:
+                done = 1;
+                break;
+              default:
+                break;
+              }
+            break;
+          case SDL_QUIT:
+            done = 1;
+            break;
+          default:
+            break;
+          }
+
+      if(speed > MAX_VEL)
+        speed = MAX_VEL;
+      else if(speed < -MAX_VEL)
+        speed = -MAX_VEL;
+
+      /* draw the credits */
+      surface->draw_bg();
+
+      y = 0;
+      for(int i = 0; i < length; i++)
+        {
+        switch(names.item[i][0])
+          {
+          case ' ':
+            white_small_text->drawf(names.item[i]+1, 0, screen->h+y-int(scroll),
+                A_HMIDDLE, A_TOP, 1);
+            y += white_small_text->h+ITEMS_SPACE;
+            break;
+          case '       ':
+            white_text->drawf(names.item[i]+1, 0, screen->h+y-int(scroll),
+                A_HMIDDLE, A_TOP, 1);
+            y += white_text->h+ITEMS_SPACE;
+            break;
+          case '-':
+            white_big_text->drawf(names.item[i]+1, 0, screen->h+y-int(scroll),
+                A_HMIDDLE, A_TOP, 3);
+            y += white_big_text->h+ITEMS_SPACE;
+            break;
+          default:
+            blue_text->drawf(names.item[i], 0, screen->h+y-int(scroll),
+                A_HMIDDLE, A_TOP, 1);
+            y += blue_text->h+ITEMS_SPACE;
+            break;
+          }
+        }
+
+      flipscreen();
+
+      if(screen->h+y-scroll < 0 && 20+screen->h+y-scroll < 0)
+        done = 1;
+
+      Uint32 ticks = SDL_GetTicks();
+      scroll += speed * (ticks - lastticks);
+      lastticks = ticks;
+      if(scroll < 0)
+        scroll = 0;
+
+      SDL_Delay(10);
+    }
+  string_list_free(&names);
+
+  SDL_EnableKeyRepeat(0, 0);    // disables key repeating
+  Menu::set_current(main_menu);
+}
+