[Tux4kids-commits] r65 - tuxmath/trunk/src

dbruce at alioth.debian.org dbruce at alioth.debian.org
Thu Mar 8 21:26:14 CET 2007


Author: dbruce
Date: 2006-12-02 00:34:38 +0000 (Sat, 02 Dec 2006)
New Revision: 65

Added:
   tuxmath/trunk/src/alphabet.c
   tuxmath/trunk/src/gettext.c
   tuxmath/trunk/src/loaders.c
   tuxmath/trunk/src/pause.c
   tuxmath/trunk/src/theme.c
   tuxmath/trunk/src/titlescreen.c
   tuxmath/trunk/src/titlescreen.h
Log:
menu redo


Added: tuxmath/trunk/src/alphabet.c
===================================================================
--- tuxmath/trunk/src/alphabet.c	2006-12-02 00:28:17 UTC (rev 64)
+++ tuxmath/trunk/src/alphabet.c	2006-12-02 00:34:38 UTC (rev 65)
@@ -0,0 +1,369 @@
+/***************************************************************************
+                          alphabet.c 
+ -  description: Init SDL
+                             -------------------
+    begin                : Jan 6 2003
+    copyright            : (C) 2003 by Jesse Andrews
+    email                : jdandr2 at tux4kids.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "titlescreen.h"
+
+/* the colors we use throughout the game */
+
+SDL_Color black;
+SDL_Color gray;
+SDL_Color dark_blue;
+SDL_Color red;
+SDL_Color white;
+SDL_Color yellow;
+
+/* Used for word list functions (see below): */
+static int WORD_qty;
+unsigned char WORDS[MAX_NUM_WORDS][MAX_WORD_SIZE+1];
+
+/* --- setup the alphabet --- */
+void set_letters(unsigned char *t) {
+	int i;
+
+	ALPHABET_SIZE = 0;
+	for (i=0; i<256; i++)
+		ALPHABET[i]=0;
+
+	for (i=0; i<strlen(t); i++)
+		if (t[i]!=' ') {
+			ALPHABET[(int)t[i]]=1;
+			ALPHABET_SIZE++;
+		}
+}
+
+void clear_keyboard( void ) {
+	int i,j;
+
+	ALPHABET_SIZE = 0;
+	for (i=0; i<256; i++) {
+		ALPHABET[i]=0;
+		for (j=0; j<10; j++)
+			FINGER[i][j]=0;
+		KEYMAP[i]=i;
+	}
+}
+
+void LoadKeyboard( void ) {
+	unsigned char fn[FNLEN];
+	int l;
+
+	clear_keyboard();
+
+	for (l=useEnglish; l<2; l++) {
+		sprintf( fn , "%s/keyboard.lst", realPath[l]);
+		if ( checkFile(fn) ) {
+			unsigned char str[255];
+			FILE *f;
+			int i,j;
+
+			f = fopen( fn, "r" );
+
+			if (f == NULL)
+				continue;
+
+			do {
+				fscanf( f, "%[^\n]\n", str);
+				if (strlen(str) > 3) {
+
+					/* format is: FINGER(s)|Char(s) Upper/Lower */
+
+					/* advance past the fingers */
+
+					for (i=0; i<strlen(str) && str[i] != '|'; i++);
+
+					i++; // pass the '|'
+					j = i; 
+					ALPHABET[(int)str[j]] = 1;  // first character is default
+
+					for (i++; i<strlen(str); i++)
+						KEYMAP[(int)str[i]] = str[j];
+
+					/* set the fingers for this letter */
+
+					for (i=0; i<j-1; i++)
+						if (str[i]>='0' && str[i]<='9')
+							FINGER[str[j]][(int)(str[i]-'0')]=1;
+
+					ALPHABET_SIZE++;
+				}
+
+			} while (!feof(f));
+
+			fclose(f);
+
+			return;
+		}
+	}
+
+	fprintf( stderr, "Error finding file for keyboard setup!\n" );
+}
+
+SDL_Surface* black_outline(unsigned char *t, TTF_Font *font, SDL_Color *c) {
+	SDL_Surface *out, *tmp, *tmp2;
+	SDL_Rect dstrect;
+
+	/* --- create the blocky black "outline" of the text --- */
+        
+        DEBUGCODE { fprintf( stderr, "black_outline of \"%s\"\n", t ); }
+
+	tmp = TTF_RenderText_Shaded(font, t, black,black);
+	tmp2 = SDL_CreateRGBSurface(SDL_SWSURFACE, (tmp->w)+5, (tmp->h)+5, BPP, rmask, gmask, bmask, amask);
+	out = SDL_DisplayFormatAlpha(tmp2);
+	SDL_FreeSurface(tmp2);
+
+	dstrect.w = tmp->w;
+	dstrect.h = tmp->h;
+
+        for (dstrect.x = 1; dstrect.x < 4; dstrect.x++)
+            for (dstrect.y = 1; dstrect.y < 4; dstrect.y++)
+                SDL_BlitSurface( tmp, NULL, out, &dstrect );
+
+	SDL_FreeSurface(tmp);
+
+	/* --- Put the color version of the text on top! --- */
+
+	tmp = TTF_RenderText_Blended(font, t, *c);
+
+	dstrect.x = dstrect.y = 2;
+
+	SDL_BlitSurface(tmp, NULL, out, &dstrect);
+
+	SDL_FreeSurface(tmp);
+
+	/* --- Convert to the screen format for quicker blits --- */
+
+	tmp = SDL_DisplayFormatAlpha(out);
+	SDL_FreeSurface(out);
+
+	return tmp;
+}
+
+void show_letters( void ) {
+	int i, l=0;
+	SDL_Surface *abit;
+	SDL_Rect dst;
+	int stop = 0;
+	unsigned char t[255];
+
+	for (i=0; i<256; i++)
+		if (ALPHABET[i])
+			t[l++]=i;
+
+	t[l] = 0;
+
+	abit = black_outline(t, font, &white);
+
+	dst.x = 320 - (abit->w / 2);
+	dst.y = 275;
+	dst.w = abit->w;
+	dst.h = abit->h;
+
+	SDL_BlitSurface(abit, NULL, screen, &dst);
+
+	SDL_FreeSurface(abit);
+
+	abit = black_outline("Alphabet Set To:", font, &white);
+	dst.x = 320 - (abit->w / 2);
+	dst.y = 200;
+	dst.w = abit->w;
+	dst.h = abit->h;
+
+	SDL_BlitSurface(abit, NULL, screen, &dst);
+
+	SDL_UpdateRect(screen, 0, 0, 0 ,0);
+
+	while (!stop) 
+		while (SDL_PollEvent(&event)) 
+			switch (event.type) {
+				case SDL_QUIT:
+					exit(0);
+				case SDL_KEYDOWN:
+				case SDL_MOUSEBUTTONDOWN:
+					stop = 1;
+			}
+
+	SDL_FreeSurface(abit);
+}
+
+/* --- get a letter --- */
+unsigned char get_letter(void) {
+	static int last = -1; // we don't want to return same letter twice in a row
+	int letter;
+	do {
+		letter = rand() % 255;
+	} while ((letter == last && ALPHABET_SIZE > 1) || ALPHABET[letter] == 0);
+
+	last = letter;
+
+	return letter;
+}
+
+/******************************************************************************
+*                           WORD FILE & DATA STRUCTURE                        *
+******************************************************************************/
+
+
+
+/* WORDS_init: clears the number of words
+ */
+void WORDS_init( void ) {
+	WORD_qty = 0;
+}
+
+/* WORDS_use_alphabet: setups the WORDS so that it really
+ * returns a LETTER when WORDS_get() is called
+ */
+void WORDS_use_alphabet( void ) {
+	int i;
+
+	LOG("Entering WORDS_use_alphabet()\n");
+
+	WORD_qty = 0;
+	/* This totally mucks up i18n abilities :( */
+	for (i=65; i<90; i++) 
+	{
+		if (ALPHABET[i]) {
+			WORDS[WORD_qty][0] = (unsigned char)i;
+			WORDS[WORD_qty][1] = '\0';
+			WORD_qty++;
+
+			DEBUGCODE { fprintf(stderr, "Adding %c\n", (unsigned char)i); }
+		}
+	}
+	/* Make sure list is terminated with null character */
+	WORDS[WORD_qty][0] = '\0';
+
+	DOUT(WORD_qty);
+	LOG("Leaving WORDS_use_alphabet()\n");
+}
+
+/* WORDS_get: returns a random word that wasn't returned
+ * the previous time (unless there is only 1 word!!!)
+ */
+unsigned char* WORDS_get( void ) {
+	static int last_choice = -1;
+	int choice;
+
+	LOG("Entering WORDS_get()\n");
+	DEBUGCODE { fprintf(stderr, "WORD_qty is: %d\n", WORD_qty); }
+
+	/* Now count list to make sure WORD_qty is correct: */
+
+	WORD_qty = 0;
+	while (WORDS[WORD_qty][0] != '\0')
+	{
+	  WORD_qty++;
+	}
+
+	DEBUGCODE { fprintf(stderr, "After count, WORD_qty is: %d\n", WORD_qty); }
+
+        if (0 == WORD_qty)
+	{
+	  LOG("No words in list\n");
+          return NULL;
+	}
+
+        if (WORD_qty > MAX_NUM_WORDS)
+	{
+	  LOG("Error: WORD_qty greater than array size\n");
+          return NULL;
+	}
+
+        if (WORD_qty < 0)
+	{
+	  LOG("Error: WORD_qty negative\n");
+          return NULL;
+	}
+
+	do {
+		choice = (rand() % WORD_qty);
+	} while ((choice == last_choice) || (WORD_qty < 2));
+
+	last_choice = choice;
+
+	DEBUGCODE { fprintf(stderr, "Selected word is: %s\n", WORDS[choice]); }
+	return WORDS[choice];
+}
+
+
+
+/* WORDS_use: adds the words from a given wordlist
+ * it ignores any words too long or that has bad
+ * character (such as #)
+ */
+void WORDS_use( char *wordFn ) {
+	int j;
+	unsigned char temp_word[FNLEN];
+	FILE *wordFile=NULL;
+
+	DEBUGCODE { fprintf(stderr, "Entering WORDS_use() for file: %s\n", wordFn); }
+
+	WORD_qty = 0;
+
+	/* --- open the file --- */
+
+	wordFile = fopen( wordFn, "r" );
+
+	if ( wordFile == NULL ) {
+		fprintf(stderr, "ERROR: could not load wordlist: %s\n", wordFn );
+		fprintf(stderr, "Using ALPHABET instead\n");
+		WORDS_use_alphabet( );
+		return;
+	}
+
+	
+	/* --- load words for this curlevel ---  */
+
+
+	DEBUGCODE { fprintf(stderr, "WORD FILE OPENNED @ %s\n", wordFn); }
+
+	/* ignore the title */
+	fscanf( wordFile, "%[^\n]\n", temp_word);
+
+	while (!feof(wordFile) && (WORD_qty < MAX_NUM_WORDS)) {
+		fscanf( wordFile, "%[^\n]\n", temp_word);
+
+		for (j = 0; j < strlen(temp_word); j++)
+			if (temp_word[j] == '\n' || temp_word[j] == '\r')
+				temp_word[j] = '\0';
+
+		/* --- check its size, if too big, ignore it --- */
+
+		if (strlen(temp_word) >= 1 && strlen(temp_word) <= MAX_WORD_SIZE) {
+
+			/* --- add word --- */
+			if (WORD_qty < MAX_NUM_WORDS)
+			{
+				strcpy( WORDS[WORD_qty], temp_word );
+				WORD_qty++;
+			}
+		}
+	}
+        
+	/* Make sure list is terminated with null character */
+	WORDS[WORD_qty][0] = '\0';
+
+	DOUT(WORD_qty);
+
+	if (WORD_qty == 0)
+		WORDS_use_alphabet( );
+
+	fclose(wordFile);
+
+	LOG("Leaving WORDS_use()\n");
+}

Added: tuxmath/trunk/src/gettext.c
===================================================================
--- tuxmath/trunk/src/gettext.c	2006-12-02 00:28:17 UTC (rev 64)
+++ tuxmath/trunk/src/gettext.c	2006-12-02 00:34:38 UTC (rev 65)
@@ -0,0 +1,185 @@
+/***************************************************************************
+gettext.c 
+-  description: a crossplatform minimal gettext library
+-------------------
+begin                : Sunday Feb 23, 2003
+copyright            : (C) 2003 by Jesse Andrews
+email                : jdandr2 at uky.edu
+***************************************************************************/
+
+/***************************************************************************
+*                                                                         *
+*   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.                                   *
+*                                                                         *
+***************************************************************************/
+#include <stdio.h>
+
+#include "titlescreen.h"
+
+/* we will store our list in a linked list since
+ * we don't expect too large of a list (famous last words!)
+ */
+
+struct node {
+	unsigned char *in;          // the english
+	unsigned char *out;         // the translation
+	struct node *next; // ptr to next in list, NULL if last
+};
+
+typedef struct node item; 
+
+item *HEAD=NULL;
+
+/* --- add a word to the linked list --- */
+
+void add_word(unsigned char *in, unsigned char *out) {
+	item *cur;
+	/* -- allocate space for the node in the list -- */
+	cur = (item *)malloc(sizeof(item));
+
+	/* -- allocate space for strings, and copy over -- */
+	cur->in = (unsigned char *)malloc(strlen(in)+2);
+	strncpy(cur->in, in, strlen(in)+1);
+	cur->out = (unsigned char *)malloc(strlen(out)+2);
+	strncpy(cur->out, out, strlen(out)+1);
+
+	/* -- add to the front of the list -- */
+	cur->next = HEAD;
+	HEAD = cur;
+}
+
+int load_trans(char *file) {
+	/* this function will load the passed file (a .po file)
+	 * if need be, it should erase any previously loaded
+	 * translations.
+	 *
+	 * the filename passed must exist!
+	 *
+	 * returns: 0 if ok
+	 * 	-1 if file could not be located
+	 * 	-2 if file has errors in it
+	 */
+
+	item *ptr;
+	FILE *f;
+	unsigned char str[FNLEN];
+	unsigned char in[FNLEN];
+	unsigned char out[FNLEN];
+
+	LOG( "Clearing previous translation list\n" );
+
+	while(HEAD != NULL) {
+		ptr = HEAD->next;
+		free(HEAD);
+		HEAD = ptr;
+	}
+
+	/* Yes, I know, I should use YACC/LEX
+	 * but, until you provide an GPL YACC/LEX 
+	 * implimentation on Mac OS _CLASSIC_, we have
+	 * to do things so they are portable, which
+	 * means, we have to parse our files by hand
+	 * using "state machines"
+	 */
+
+
+	LOG( "Loading translation file\n" );
+	f = fopen( file, "r" );
+
+	if (f == NULL) return -1;
+	
+	/* ### ADD ERROR CHECKING ### */
+
+	do {
+		fscanf(f, "%[^\n]\n", str);
+
+		/* get rid of any comments! */
+		{
+			unsigned char mode='O';
+			int i;
+			for (i=0; i<strlen(str); i++) {
+				if (mode == 'O') {
+					switch (str[i]) {
+						case '"': mode = 'I'; break;
+						case '#': str[i]='\0'; break;
+					}
+				} else {
+					switch (str[i]) {
+						case '\\': 
+							if (mode != 'S') mode = 'S';
+							else mode = 'I';
+							break;
+						case '"': 
+							if (mode != 'S') mode ='O'; 
+							break;
+						default:
+							mode = 'I'; // get rid of any /
+					}
+				}
+			}
+		}
+
+		/* we force msgid or msgstr to be at the begining of the line! */
+
+		if (strncmp(str, "msgid", 5) == 0) {
+			int start=0, endloc=0, i;
+			for (i=0; i<strlen(str); i++)
+				if (str[i] == '"') {
+					if (!start)
+						start = i;
+					else
+						endloc = i;
+				}
+			str[endloc]='\0';
+			strcpy(in, str+start+1);
+		}
+		if (strncmp(str, "msgstr", 6) == 0) {
+			int start=0,endloc=0, i;
+			for (i=0; i<strlen(str); i++)
+				if (str[i] == '"') {
+					if (!start)
+						start = i;
+					else
+						endloc = i;
+				}
+			str[endloc]='\0';
+			strcpy(out, str+start+1);
+			add_word(in, out);
+		}
+
+	} while( !feof(f) );
+
+	LOG( "Completed loading of translation file\n" );
+
+	return 0;
+}
+
+unsigned char * gettext( unsigned char *in ) {
+	/* this function will attempt to translate the string
+	 * "in" to an "translation of in" if one exists.
+	 * if it doesn't exist in the translation set, it 
+	 * returns "in".
+	 */
+
+	/* go through each time until we find what we want...
+	 * if the number of translated words we use increases, 
+	 * we should move to a hash table.
+	 */
+
+	item *cur=HEAD;
+
+	if (useEnglish)
+		return in;
+
+	while (cur != NULL) 
+		if (strcmp(cur->in, in) == 0)
+			return cur->out;
+		else
+			cur = cur->next;
+
+	/* if we didn't find anything return what we were asked */
+	return in;
+}

Added: tuxmath/trunk/src/loaders.c
===================================================================
--- tuxmath/trunk/src/loaders.c	2006-12-02 00:28:17 UTC (rev 64)
+++ tuxmath/trunk/src/loaders.c	2006-12-02 00:34:38 UTC (rev 65)
@@ -0,0 +1,389 @@
+/***************************************************************************
+ -  file: loaders.c
+ -  description: Functions to load multimedia for Tux Typing
+                             -------------------
+    begin                : Thu May 4 2000
+    copyright            : (C) 2000 by Sam Hart
+                         : (C) 2003 by Jesse Andrews
+    email                : tuxtype-dev at tux4kids.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+//#include "globals.h"
+//#include "funcs.h"
+
+#include "titlescreen.h"
+
+/* check to see if file exists, if so return true */
+int checkFile( const char *file ) {
+	static struct stat fileStats;
+
+	fileStats.st_mode = 0;
+
+	stat( file, &fileStats );
+		
+	return (S_IFREG & fileStats.st_mode);
+}
+
+void LoadLang( void ) {
+	char fn[FNLEN];
+
+	/* we only need to load a lang.po file if we
+	 * are actually using a theme, so this is a little
+	 * different than the other loaders 
+	 */ 
+
+	if (useEnglish) {
+		/* clear translations and return! */
+		return;
+	}
+
+	/* --- create full path to the lang.po file --- */
+
+	sprintf( fn, "%s/lang.po", realPath[0]);
+	if (load_trans( fn )) {
+		/* failed to find a lang.po file, clear gettext & return */
+		return;
+	}
+}
+
+int max( int n1, int n2 ) {
+	return (n1 > n2 ? n1 : n2);
+}
+
+/**********************
+ Flip:
+   input: a SDL_Surface, x, y
+   output: a copy of the SDL_Surface flipped via rules:
+
+     if x is a positive value, then flip horizontally
+     if y is a positive value, then flip vertically
+
+     note: you can have it flip both
+**********************/
+SDL_Surface *flip( SDL_Surface *in, int x, int y ) {
+	SDL_Surface *out, *tmp;
+	SDL_Rect from_rect, to_rect;
+	Uint32	flags;
+	Uint32  colorkey=0;
+
+	/* --- grab the settings for the incoming pixmap --- */
+
+	SDL_LockSurface(in);
+	flags = in->flags;
+
+	/* --- change in's flags so ignore colorkey & alpha --- */
+
+	if (flags & SDL_SRCCOLORKEY) {
+		in->flags &= ~SDL_SRCCOLORKEY;
+		colorkey = in->format->colorkey;
+	}
+	if (flags & SDL_SRCALPHA) {
+		in->flags &= ~SDL_SRCALPHA;
+	}
+
+	SDL_UnlockSurface(in);
+
+	/* --- create our new surface --- */
+
+	out = SDL_CreateRGBSurface(
+		SDL_SWSURFACE,
+		in->w, in->h, 32, rmask, gmask, bmask, amask);
+
+	/* --- flip horizontally if requested --- */
+
+	if (x) {
+		from_rect.h = to_rect.h = in->h;
+		from_rect.w = to_rect.w = 1;
+		from_rect.y = to_rect.y = 0;
+		from_rect.x = 0;
+		to_rect.x = in->w - 1;
+
+		do {
+			SDL_BlitSurface(in, &from_rect, out, &to_rect);
+			from_rect.x++;
+			to_rect.x--;
+		} while (to_rect.x >= 0);
+	}
+
+	/* --- flip vertically if requested --- */
+
+	if (y) {
+		from_rect.h = to_rect.h = 1;
+		from_rect.w = to_rect.w = in->w;
+		from_rect.x = to_rect.x = 0;
+		from_rect.y = 0;
+		to_rect.y = in->h - 1;
+
+		do {
+			SDL_BlitSurface(in, &from_rect, out, &to_rect);
+			from_rect.y++;
+			to_rect.y--;
+		} while (to_rect.y >= 0);
+	}
+
+	/* --- restore colorkey & alpha on in and setup out the same --- */
+
+	SDL_LockSurface(in);
+
+	if (flags & SDL_SRCCOLORKEY) {
+		in->flags |= SDL_SRCCOLORKEY;
+		in->format->colorkey = colorkey;
+		tmp = SDL_DisplayFormat(out);
+		SDL_FreeSurface(out);
+		out = tmp;
+		out->flags |= SDL_SRCCOLORKEY;
+		out->format->colorkey = colorkey;
+	} else if (flags & SDL_SRCALPHA) {
+		in->flags |= SDL_SRCALPHA;
+		tmp = SDL_DisplayFormatAlpha(out);
+		SDL_FreeSurface(out);
+		out = tmp;
+	} else {
+		tmp = SDL_DisplayFormat(out);
+		SDL_FreeSurface(out);
+		out = tmp;
+	}
+
+	SDL_UnlockSurface(in);
+
+	return out;
+}
+
+TTF_Font *LoadFont( char *fontfile, int fontsize ) {
+	TTF_Font *loadedFont;
+	char fn[FNLEN];
+	int i;
+/* char themeName[FNLEN]; */
+
+
+	/* 
+	 *
+	 *
+	 * this will fail now, as those fonts have been removed
+	 * 
+	 *
+	 * this routine is only left here for reference
+	 * 
+	 *
+	 *
+	 */
+	/* try to find font first in theme dir, then in default */
+	for (i=useEnglish; i<2; i++) {
+		sprintf( fn, "%s/fonts/%s", realPath[i], fontfile );
+	DEBUGCODE { fprintf(stderr, "LoadFont(): looking for %s using data paths\n", fn ); }
+		if ( checkFile(fn) ) {
+			/* try to load the font, if successful, return font*/
+
+			loadedFont = TTF_OpenFont( fn, fontsize );
+
+			if (loadedFont != NULL)
+				return loadedFont;
+		}
+	}
+
+		
+
+	/* this works only on debian */ 
+	/* "fallback" (the above _will_ fall): load the font with fixed-path */
+	
+	sprintf( fn, "%s/%s", "/usr/share/fonts/truetype/ttf-gentium/", fontfile );
+	DEBUGCODE { fprintf(stderr, "LoadFont(): looking for %s\n in OS' font path\n", fn ); }
+
+	if ( checkFile(fn) ) {
+		/* try to load the font, if successful, return font*/
+
+		loadedFont = TTF_OpenFont( fn, fontsize );
+
+		if (loadedFont != NULL)
+			return loadedFont;
+	}
+
+	fprintf(stderr, "FATAL ERROR: couldn't load font: %s\n", fontfile);
+	exit(1);
+
+	return NULL;
+}
+
+/***********************
+	LoadImage : Load an image and set transparent if requested
+************************/
+SDL_Surface *LoadImage( char *datafile, int mode )
+{
+	int i;
+	SDL_Surface  *tmp_pic = NULL, *final_pic = NULL;
+	char         fn[FNLEN];
+
+	DEBUGCODE { fprintf(stderr, "LoadImage: loading %s\n", datafile ); }
+
+	/* truth table for start of loop, since we only use theme on those conditions!
+              useEng    IMG_NO_THEME    i
+                 0           0          0
+                 0           1          1
+                 1           0          1
+                 1           1          1
+	 */
+
+	for (i = (useEnglish || (mode & IMG_NO_THEME)); i<2; i++) {
+
+		sprintf( fn, "%s/images/%s", realPath[i], datafile );
+		DEBUGCODE { fprintf(stderr, "LoadImage: looking in %s\n", fn); }
+
+		if ( checkFile( fn ) ) {
+			LOG ("file found\n");
+			tmp_pic = IMG_Load( fn );
+			if (tmp_pic != NULL)
+				break; 
+			else
+				fprintf(stderr, "Warning: graphics file %s is corrupt\n", fn);
+		}
+		else LOG ("file NOT found\n");
+	}
+
+	if (tmp_pic == NULL) {
+		if (mode & IMG_NOT_REQUIRED) 
+			return NULL;
+
+		fprintf(stderr, "ERROR could not load required graphics file %s\n", datafile);
+		exit(1);
+	}
+
+	/* finally setup the image to the proper format */
+
+	switch (mode & IMG_MODES) {
+
+		case IMG_REGULAR: { 
+			final_pic = SDL_DisplayFormat(tmp_pic);
+			SDL_FreeSurface(tmp_pic);
+			break;
+		}
+
+		case IMG_ALPHA: {
+			final_pic = SDL_DisplayFormatAlpha(tmp_pic);
+			SDL_FreeSurface(tmp_pic);
+			break;
+		}
+
+		case IMG_COLORKEY: {
+			SDL_LockSurface(tmp_pic);
+			SDL_SetColorKey(tmp_pic, (SDL_SRCCOLORKEY | SDL_RLEACCEL), SDL_MapRGB(tmp_pic->format, 255, 255, 0));
+			final_pic = SDL_DisplayFormat(tmp_pic);
+			SDL_FreeSurface(tmp_pic);
+			break;
+		}
+
+		default: {
+			LOG ("Image mode not recognized\n");
+		}
+	}
+
+	LOG( "LOADIMAGE: Done\n" );
+
+	return (final_pic);
+}
+
+sprite* FlipSprite( sprite *in, int X, int Y ) {
+	sprite *out;
+
+	out = malloc(sizeof(sprite));
+	if (in->default_img != NULL)
+		out->default_img = flip( in->default_img, X, Y );
+	else
+		out->default_img = NULL;
+	for ( out->num_frames=0; out->num_frames<in->num_frames; out->num_frames++ )
+		out->frame[out->num_frames] = flip( in->frame[out->num_frames], X, Y );
+	out->cur = 0;
+	return out;
+}
+
+sprite* LoadSprite( char* name, int MODE ) {
+	sprite *new_sprite;
+	char fn[FNLEN];
+	int x;
+
+	/* JA --- HACK check out what has changed with new code */
+
+	new_sprite = malloc(sizeof(sprite));
+
+	sprintf(fn, "%sd.png", name);
+	new_sprite->default_img = LoadImage( fn, MODE|IMG_NOT_REQUIRED );
+	for (x = 0; x < MAX_SPRITE_FRAMES; x++) {
+		sprintf(fn, "%s%d.png", name, x);
+		new_sprite->frame[x] = LoadImage( fn, MODE|IMG_NOT_REQUIRED );
+		if ( new_sprite->frame[x] == NULL ) {
+			new_sprite->cur = 0;
+			new_sprite->num_frames = x;
+			break;
+		}
+	}
+
+	DEBUGCODE {
+		fprintf( stderr, "loading sprite %s - contains %d frames\n",
+		        name, new_sprite->num_frames );
+	}
+
+	return new_sprite;
+}
+
+void FreeSprite( sprite *gfx ) {
+	int x;
+	for (x = 0; x < gfx->num_frames; x++)
+		SDL_FreeSurface( gfx->frame[x] );
+	SDL_FreeSurface( gfx->default_img );
+	free(gfx);
+}
+
+/***************************
+	LoadSound : Load a sound/music patch from a file.
+****************************/
+Mix_Chunk      *LoadSound( char *datafile )
+{ 
+	Mix_Chunk *tempChunk=NULL;
+	char fn[FNLEN];
+	int i;
+
+	for (i = useEnglish; i<2; i++) {
+		sprintf(fn , "%s/sounds/%s", realPath[i], datafile);
+		if ( checkFile(fn) ) {
+			tempChunk = Mix_LoadWAV(fn);
+			if (tempChunk)
+				return tempChunk;
+		}
+	}
+
+	/* didn't find anything... fail peacefully */
+
+	return NULL;
+}
+
+/************************
+	LoadMusic : Load
+	music from a datafile
+*************************/
+Mix_Music *LoadMusic(char *datafile )
+{ 
+	char            fn[FNLEN];
+	Mix_Music	*tempMusic;
+	int i;
+
+	for (i = useEnglish; i<2; i++) {
+		sprintf( fn , "%s/sounds/%s", realPath[i], datafile );
+		if ( checkFile(fn) ) {
+			tempMusic = Mix_LoadMUS(fn);
+			if (tempMusic)
+				return tempMusic;
+		}
+	}
+
+	/* didn't find anything... fail peacefully */
+
+	return NULL;
+}

Added: tuxmath/trunk/src/pause.c
===================================================================
--- tuxmath/trunk/src/pause.c	2006-12-02 00:28:17 UTC (rev 64)
+++ tuxmath/trunk/src/pause.c	2006-12-02 00:34:38 UTC (rev 65)
@@ -0,0 +1,336 @@
+/***************************************************************************
+pause.c 
+-  description: pause screen for the games
+-------------------
+begin                : Jan 22, 2003
+copyright            : (C) 2003 by Jesse Andrews
+email                : jdandr2 at uky.edu
+***************************************************************************/
+
+/***************************************************************************
+*                                                                         *
+*   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.                                   *
+*                                                                         *
+***************************************************************************/
+
+#include "titlescreen.h"
+
+Mix_Chunk *pause_sfx;
+SDL_Surface *up, *down, *left, *right;
+SDL_Rect rectUp, rectDown, rectLeft, rectRight;
+TTF_Font *f1, *f2;
+extern settings localsettings;
+
+void pause_load_media(void) {
+	if (sys_sound) 
+		pause_sfx = LoadSound( "tock.wav" );
+
+	up = LoadImage("up.png", IMG_ALPHA);
+	rectUp.w = up->w; rectUp.h = up->h;
+
+	down = LoadImage("down.png", IMG_ALPHA);
+	rectDown.w = down->w; rectDown.h = down->h;
+
+	left = LoadImage("left.png", IMG_ALPHA);
+	rectLeft.w = left->w; rectLeft.h = left->h;
+
+	right = LoadImage("right.png", IMG_ALPHA);
+	rectRight.w = right->w; rectRight.h = right->h;
+
+	f1 = LoadFont( ttf_font, 24 );
+	f2 = LoadFont( ttf_font, 36 );
+}
+
+void pause_unload_media(void) {
+	if (sys_sound)
+		Mix_FreeChunk(pause_sfx);
+	SDL_FreeSurface(up);
+	SDL_FreeSurface(down);
+	SDL_FreeSurface(left);
+	SDL_FreeSurface(right);
+	TTF_CloseFont(f1);
+	TTF_CloseFont(f2);
+}
+
+void pause_draw_info(void) {
+	SDL_Rect s;
+	SDL_Surface *t;
+
+	rectLeft.y = rectRight.y = 200;
+	rectDown.y = rectUp.y = 300;
+
+	rectLeft.x = rectDown.x = 320 - (7*16) - rectLeft.w - 4;
+	rectRight.x = rectUp.x  = 320 + (7*16) + 4;
+
+	if (sys_sound) {
+
+		SDL_BlitSurface(left, NULL, screen, &rectLeft);
+		SDL_BlitSurface(right, NULL, screen, &rectRight);
+
+		SDL_BlitSurface(down, NULL, screen, &rectDown);
+		SDL_BlitSurface(up, NULL, screen, &rectUp);
+	}
+
+	if (sys_sound) {
+
+		t = black_outline(_("Sound Effects Volume"), f1, &white);
+		s.y = 160;
+		s.x = 320 - t->w/2;
+		SDL_BlitSurface(t, NULL, screen, &s);
+		SDL_FreeSurface(t);
+
+		t = black_outline(_("Music Volume"), f1, &white);
+		s.y = 260;
+		s.x = 320 - t->w/2;
+		SDL_BlitSurface(t, NULL, screen, &s);
+		SDL_FreeSurface(t);
+
+	} else {
+
+		t = black_outline(_("Sound & Music Disabled"), f1, &white);
+		s.y = 160;
+		s.x = 320 - t->w/2;
+		SDL_BlitSurface(t, NULL, screen, &s);
+		SDL_FreeSurface(t);
+	}
+
+	t = black_outline(_("Paused!"), f2, &white);
+	s.y = 60;
+	s.x = 320 - t->w/2;
+	SDL_BlitSurface(t, NULL, screen, &s);
+	SDL_FreeSurface(t);
+
+	t = black_outline(_("Press escape again to return to menu"), f1, &white);
+	s.y = 400;
+	s.x = 320 - t->w/2;
+	SDL_BlitSurface(t, NULL, screen, &s);
+	SDL_FreeSurface(t);
+
+	t = black_outline(_("Press space bar to return to game"), f1, &white);
+	s.y = 440;
+	s.x = 320 - t->w/2;
+	SDL_BlitSurface(t, NULL, screen, &s);
+	SDL_FreeSurface(t);
+}
+
+void draw_vols(int sfx, int mus) {
+	SDL_Rect s,m;
+	int i;
+
+	s.y = rectLeft.y; 
+	m.y = rectDown.y;
+	m.w = s.w = 5;
+	s.x = rectLeft.x + rectLeft.w + 5;
+	m.x = rectDown.x + rectDown.w + 5;
+	m.h = s.h = 40;
+
+	for (i = 1; i<=32; i++){
+		if (sfx >= i*4)
+			SDL_FillRect(screen, &s, SDL_MapRGB(screen->format, 0, 0, 127+sfx));
+		else
+			SDL_FillRect(screen, &s, SDL_MapRGB(screen->format, 0, 0, 0));
+
+		if (mus >= i*4)
+			SDL_FillRect(screen, &m, SDL_MapRGB(screen->format, 0, 0, 127+mus));
+		else
+			SDL_FillRect(screen, &m, SDL_MapRGB(screen->format, 0, 0, 0));
+
+		m.x = s.x += 7;
+	}
+}
+
+/* ==== fillscreen ====
+ * RESULT: it will darken the screen by a factor of 4
+ * WARNING: only works on 16bit screens right now!
+ */
+void darkenscreen( void ){
+	Uint16 rm = screen->format->Rmask;
+	Uint16 gm = screen->format->Gmask;
+	Uint16 bm = screen->format->Bmask;
+	Uint16 *p; 
+	int x, y;
+
+	p = screen->pixels;
+
+	for (y = 0; y<480; y++) 
+		for (x = 0; x<640; x++) {
+			*p = (((*p&rm)>>2)&rm) | (((*p&gm)>>2)&gm) | (((*p&bm)>>2)&bm); p++;
+		}
+}
+
+int inRect( SDL_Rect r, int x, int y) {
+	if ((x < r.x) || (y < r.y) || (x > r.x + r.w) || (y > r.y + r.h))
+		return 0;
+	return 1;
+}
+
+// QUESTION: For usability sake, should escape return to the game
+//           and the user have to choose to quit the game, or ???
+/**********************
+Pause : Pause the game
+***********************/
+int Pause( void ) {
+	int paused = 1;
+	int sfx_volume=0;
+	int old_sfx_volume;
+	int mus_volume=0;
+	int old_mus_volume;
+	int mousePressed = 0;
+	int quit=0;
+	int tocks=0;  // used for keeping track of when a tock has happened
+	SDL_Event event;
+
+	LOG( "---GAME PAUSED---\n" );
+
+	/* --- stop all sounds, play pause noise --- */
+
+	if (sys_sound) {
+ 		Mix_Pause(-1);
+		Mix_PlayChannel(-1, pause_sfx, 0);
+		sfx_volume = Mix_Volume(-1, -1);  // get sfx volume w/o changing it
+		mus_volume = Mix_VolumeMusic(-1); // get mus volume w/o changing it
+	}
+
+	/* --- show the pause screen --- */
+
+	SDL_ShowCursor(1);
+
+	// Darken the screen...
+	darkenscreen(); 
+
+	pause_draw_info();
+	if (sys_sound) {
+		draw_vols(sfx_volume, mus_volume);
+	}
+
+	SDL_Flip(screen);
+
+	SDL_EnableKeyRepeat( 1, 20 );
+
+	/* --- wait for space, click, or exit --- */
+
+	while (paused) {
+		old_sfx_volume = sfx_volume;
+		old_mus_volume = mus_volume;
+		while (SDL_PollEvent(&event)) 
+			switch (event.type) {
+				case SDL_QUIT: 
+					exit(0);
+					break;
+				case SDL_KEYUP:
+					if (sys_sound && 
+					   ((event.key.keysym.sym == SDLK_RIGHT) ||
+					    (event.key.keysym.sym == SDLK_LEFT))) 
+					    	tocks = 0;
+					break;
+				case SDL_KEYDOWN:
+					if (event.key.keysym.sym == SDLK_SPACE) 
+						paused = 0;
+					if (event.key.keysym.sym == SDLK_ESCAPE) {
+						paused = 0;
+						quit = 1;
+					}
+					if (sys_sound) { 
+						if (event.key.keysym.sym == SDLK_RIGHT) 
+							sfx_volume += 4;
+						if (event.key.keysym.sym == SDLK_LEFT) 
+							sfx_volume -= 4;
+						if (event.key.keysym.sym == SDLK_UP) 
+							mus_volume += 4;
+						if (event.key.keysym.sym == SDLK_DOWN) 
+							mus_volume -= 4;
+					}
+					break;
+				case SDL_MOUSEBUTTONDOWN:
+					mousePressed = 1;
+					tocks = 0;
+					break;
+				case SDL_MOUSEBUTTONUP:
+					mousePressed = 0;
+					break;
+
+					break;
+			}
+		if (sys_sound && mousePressed) {
+			int x, y;
+
+			SDL_GetMouseState(&x, &y);
+			/* check to see if they clicked on a button */
+
+			if (inRect(rectUp, x, y)) {
+				mus_volume += 4;
+			} else if (inRect(rectDown, x, y)) {
+				mus_volume -= 4;
+			} else if (inRect(rectRight, x, y)) {
+				sfx_volume += 4;
+			} else if (inRect(rectLeft, x, y)) {
+				sfx_volume -= 4;
+			} else {
+
+				/* check to see if they clicked a bar */
+
+				if ((x > rectLeft.x + rectLeft.w) && (x < rectRight.x)) {
+					if ((y >= rectLeft.y) && (y <= rectLeft.y + rectLeft.h)) {
+						sfx_volume = 4+(int)(128.0 * ((x - rectLeft.x - rectLeft.w - 1.0) / (rectRight.x - rectLeft.x - rectLeft.w - 2.0)));
+					}
+					if ((y >= rectDown.y) && (y <= rectDown.y + rectDown.h)) {
+						mus_volume = 4+(int)(128.0 * ((x - rectLeft.x - rectLeft.w - 1.0) / (rectRight.x - rectLeft.x - rectLeft.w - 2.0)));
+					}
+
+				}
+			}
+		}
+
+		if (sys_sound) {
+
+			if (sfx_volume > MIX_MAX_VOLUME)
+				sfx_volume = MIX_MAX_VOLUME;
+			if (sfx_volume < 0)
+				sfx_volume = 0;
+			if (mus_volume > MIX_MAX_VOLUME)
+				mus_volume = MIX_MAX_VOLUME;
+			if (mus_volume < 0)
+				mus_volume = 0;
+
+			if ((mus_volume != old_mus_volume) || 
+			    (sfx_volume != old_sfx_volume)) {
+
+				if (mus_volume != old_mus_volume)
+					Mix_VolumeMusic(mus_volume);
+
+				if (sfx_volume != old_sfx_volume) {
+					Mix_Volume(-1,sfx_volume);
+					if (tocks%4==0)
+						Mix_PlayChannel(-1, pause_sfx, 0);
+					tocks++;
+			    }
+
+				draw_vols(sfx_volume, mus_volume);
+				localsettings.mus_volume=mus_volume;
+				localsettings.sfx_volume=sfx_volume;
+				SDL_Flip(screen);
+			}
+		}
+
+		SDL_Delay(33);
+	}
+
+	/* --- Return to previous state --- */
+
+	SDL_EnableKeyRepeat( 0, SDL_DEFAULT_REPEAT_INTERVAL );
+
+	SDL_ShowCursor(0);
+
+	if (sys_sound) {
+		Mix_PlayChannel(-1, pause_sfx, 0);
+		Mix_Resume(-1);
+	}
+
+	LOG( "---GAME RESUMED---\n" );
+
+	return (quit);
+}
+

Added: tuxmath/trunk/src/theme.c
===================================================================
--- tuxmath/trunk/src/theme.c	2006-12-02 00:28:17 UTC (rev 64)
+++ tuxmath/trunk/src/theme.c	2006-12-02 00:34:38 UTC (rev 65)
@@ -0,0 +1,346 @@
+/***************************************************************************
+                          theme.c 
+ -  description: theme related code
+                             -------------------
+    begin                : Jan 6 2003
+    copyright            : (C) 2003 by Jesse Andrews et al
+    email                : jdandr2 at tux4kids.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+//#include "globals.h"
+//#include "funcs.h"
+
+#include "titlescreen.h"
+
+#define NUM_PATHS 4
+
+const char PATHS[NUM_PATHS][FNLEN] = {
+	"./data",
+	"/usr/share/"PACKAGE"/data",
+	"/usr/local/share/"PACKAGE"/data",
+	DATA_PREFIX"/share/"PACKAGE"/data"
+};
+
+SDL_Surface *letters[255] = { NULL };
+unsigned char ALPHABET[256];
+unsigned char KEYMAP[256];
+unsigned char FINGER[256][10];
+int ALPHABET_SIZE;
+unsigned char realPath[2][FNLEN];
+char themeName[FNLEN];
+int useEnglish;
+
+
+#define MAX_LANGUAGES 100
+
+/* setup_theme: this function is in charge of setting up
+ * the paths that the loaders use.  It will set a variable
+ * numPaths = 1 or 2.  1 if we are just using the default,
+ * 2 if there are two themes.  Then it will edit the varible
+ * Paths[].  It will always put the theme path first, then
+ * the default path
+ */
+void setupTheme( char *dirName ) {
+	static struct stat dirStats;
+	int i;
+	int found = 0;
+	useEnglish=1; // default is to use English if we cannot find theme
+
+	for (i=0; i<NUM_PATHS && !found; i++) {
+
+		DEBUGCODE{
+		fprintf(stderr, "setupTheme(): checking for: %s\n", PATHS[i]);
+		}
+
+		dirStats.st_mode = 0;
+		stat( PATHS[i], &dirStats );
+		if (S_IFDIR & dirStats.st_mode) {
+			strncpy( realPath[1], PATHS[i], FNLEN-1);
+			strncpy( themeName, "", FNLEN-1 );
+			found = 1; /* so quit looking */
+
+			DEBUGCODE{
+			fprintf(stderr, "path '%s' found, copy to realPath[1]\n", PATHS[i]);
+			}
+		}
+		else {
+			DEBUGCODE{
+			fprintf(stderr, "path '%s' not found.\n", PATHS[i]);
+			}
+		}
+
+	}
+
+	if (dirName != NULL) {
+		char fullDir[FNLEN];
+
+		/* find the path to the theme */
+		sprintf( fullDir, "%s/themes/%s", realPath[1], dirName );
+		dirStats.st_mode = 0;
+		stat( fullDir, &dirStats );
+		if (S_IFDIR & dirStats.st_mode) {
+			useEnglish=0;
+			strncpy( realPath[0], fullDir, FNLEN-1 );
+			strncpy( themeName, dirName, FNLEN-1 );
+		}
+	}
+	DEBUGCODE
+	{
+		fprintf(stderr, "Leaving setupTheme():\n");
+		if (dirName != NULL)
+			fprintf(stderr, "realPath[0] = %s\n", realPath[0]);
+		fprintf(stderr, "realPath[1] = %s\n", realPath[1]);
+	}
+	
+}
+
+void chooseTheme( void ) {
+	SDL_Surface *titles[MAX_LANGUAGES];
+	SDL_Surface *select[MAX_LANGUAGES];
+	SDL_Surface *left, *right;
+	SDL_Rect leftRect, rightRect;
+	SDL_Surface *world, *map, *photo;
+	SDL_Rect worldRect, photoRect;
+	SDL_Rect titleRects[8];
+	int stop = 0;
+	int loc = 0;
+	int old_loc = 1;
+
+	int themes = 1;
+	int i;
+	unsigned char fn[FNLEN];
+	unsigned char themeNames[MAX_LANGUAGES][FNLEN];
+	unsigned char themePaths[MAX_LANGUAGES][FNLEN];
+
+	int old_useEnglish;
+	char old_realPath[FNLEN];
+
+	DIR *themesDir;
+	struct dirent *themesFile;
+	struct stat fileStats;
+
+	old_useEnglish = useEnglish;
+	strncpy( old_realPath, realPath[0], FNLEN-1 );
+
+	sprintf( fn, "%s/themes/", realPath[1]);
+	themesDir = opendir(fn);
+
+	do {
+		themesFile = readdir(themesDir);
+		if (!themesFile)
+			break;
+
+		/* we ignore any hidden file and CVS */
+
+		if (themesFile->d_name[0] == '.') 
+			continue;
+
+		if (strcmp("CVS", themesFile->d_name)==0)
+			continue;
+
+		/* check to see if it is a directory */
+		sprintf( fn, "%s/themes/%s", realPath[1], themesFile->d_name);
+
+		fileStats.st_mode=0;
+		stat( fn, &fileStats );
+
+		if (S_IFDIR & fileStats.st_mode) {
+		    /* HACK: we should get the names from file :) */
+		    strncpy( themeNames[themes], themesFile->d_name, FNLEN-1);
+		    strncpy( themePaths[themes++], themesFile->d_name, FNLEN-1 );
+		}
+	} while (1);
+
+	closedir(themesDir);
+
+	useEnglish = 1;
+        // HACK: is font empty now???
+	font = LoadFont( ttf_font, ttf_font_size );
+
+	titles[0] = black_outline( "english", font, &white );
+	select[0] = black_outline( "english", font, &yellow);
+	for (i = 1; i<themes; i++) {
+		titles[i] = black_outline( themeNames[i], font, &white );
+		select[i] = black_outline( themeNames[i], font, &yellow);
+	}
+
+	world = LoadImage("world.png", IMG_ALPHA);
+	worldRect.x = 480 - (world->w/2);
+	worldRect.w = world->w;
+	worldRect.y = 10;
+	worldRect.h = world->h;
+
+	
+
+	TTF_CloseFont(font);
+
+	useEnglish = old_useEnglish;
+
+	bkg = LoadImage("main_bkg.png", IMG_REGULAR);
+
+	left = LoadImage("left.png", IMG_ALPHA);
+	leftRect.w = left->w; leftRect.h = left->h;
+	leftRect.x = 160 - 80 - (leftRect.w/2); leftRect.y = 430;
+
+	right = LoadImage("right.png", IMG_ALPHA);
+	rightRect.w = right->w; rightRect.h = right->h;
+	rightRect.x = 160 + 80 - (rightRect.w/2); rightRect.y = 430;
+
+	/* set initial rect sizes */
+	titleRects[0].y = 30;
+	titleRects[0].w = titleRects[0].h = titleRects[0].x = 0;
+	for (i = 1; i<8; i++) {
+		titleRects[i].y = titleRects[i-1].y + 50;
+		titleRects[i].w = titleRects[i].h = titleRects[i].x = 0;
+	}
+	
+
+	while (!stop) {
+		while (SDL_PollEvent(&event)) 
+			switch (event.type) {
+				case SDL_QUIT:
+					exit(0);
+					break;
+				case SDL_MOUSEMOTION: 
+					for (i=0; (i<8) && (loc-(loc%8)+i<themes); i++)
+						if (inRect( titleRects[i], event.motion.x, event.motion.y )) {
+							loc = loc-(loc%8)+i;
+							break;
+						}
+					
+					break;
+				case SDL_MOUSEBUTTONDOWN: 
+					if (inRect( leftRect, event.button.x, event.button.y )) 
+						if (loc-(loc%8)-8 >= 0) {
+							loc=loc-(loc%8)-8;
+							break;
+						}
+					if (inRect( rightRect, event.button.x, event.button.y )) 
+						if (loc-(loc%8)+8 < themes) {
+							loc=loc-(loc%8)+8;
+							break;
+						}
+					for (i=0; (i<8) && (loc-(loc%8)+i<themes); i++) 
+						if (inRect(titleRects[i], event.button.x, event.button.y)) {
+							loc = loc-(loc%8)+i;
+							if (loc) {
+								/* --- set theme --- */
+								setupTheme(themePaths[loc]);
+							} else {
+								/* --- english --- */
+								setupTheme(NULL);
+							}
+							stop = 1;
+							break;
+						}
+					break;
+				case SDL_KEYDOWN:
+					if (event.key.keysym.sym == SDLK_ESCAPE) { 
+						useEnglish = old_useEnglish;
+						strncpy( realPath[0], old_realPath, FNLEN-1 );
+						stop = 1; 
+						break; 
+					}
+					if (event.key.keysym.sym == SDLK_RETURN) { 
+						if (loc) {
+							/* --- set theme --- */
+							setupTheme(themePaths[loc]);
+						} else {
+							/* --- english --- */
+							setupTheme(NULL);
+						}
+						stop = 1;
+						break;
+					}
+
+					if ((event.key.keysym.sym == SDLK_LEFT) || (event.key.keysym.sym == SDLK_PAGEUP)) {
+						if (loc-(loc%8)-8 >= 0) 
+							loc=loc-(loc%8)-8;
+					}
+
+					if ((event.key.keysym.sym == SDLK_RIGHT) || (event.key.keysym.sym == SDLK_PAGEDOWN)) {
+						if (loc-(loc%8)+8 < themes)
+							loc=(loc-(loc%8)+8);
+					}
+
+
+					if (event.key.keysym.sym == SDLK_UP) {
+						if (loc > 0)
+							loc--;
+					}
+
+					if (event.key.keysym.sym == SDLK_DOWN) {
+						if (loc+1<themes)
+							loc++;
+					}
+			}
+
+		if (old_loc != loc) {
+			int start;
+
+			SDL_BlitSurface( bkg, NULL, screen, NULL );
+
+			SDL_BlitSurface( world, NULL, screen, &worldRect );
+
+		        if (loc) setupTheme(themePaths[loc]); else setupTheme(NULL);
+
+			map = LoadImage( "map.png", IMG_ALPHA|IMG_NOT_REQUIRED );
+			if (map) {
+				SDL_BlitSurface( map, NULL, screen, &worldRect );
+				SDL_FreeSurface( map );
+			}
+
+			photo = LoadImage( "photo.png", IMG_ALPHA|IMG_NOT_REQUIRED );
+			if (photo) {
+				photoRect.x = 480 - (photo->w/2);
+				photoRect.y = 250;
+				photoRect.w = photo->w;
+				photoRect.h = photo->h;
+				SDL_BlitSurface( photo, NULL, screen, &photoRect );
+				SDL_FreeSurface( photo );
+			}
+
+			start = loc - (loc % 8);
+			for (i = start; i<MIN(start+8,themes); i++) {
+				titleRects[i%8].x = 160 - (titles[i]->w/2);
+				if (i == loc)
+					SDL_BlitSurface(select[loc], NULL, screen, &titleRects[i%8]);
+				else
+					SDL_BlitSurface(titles[i], NULL, screen, &titleRects[i%8]);
+			}
+
+			/* --- draw buttons --- */
+
+			if (start>0) 
+				SDL_BlitSurface( left, NULL, screen, &leftRect );
+
+			if (start+8<themes) 
+				SDL_BlitSurface( right, NULL, screen, &rightRect );
+
+			SDL_UpdateRect(screen, 0, 0, 0 ,0);
+		}
+		SDL_Delay(40);
+		old_loc = loc;
+	}
+
+	/* --- clear graphics before quiting --- */ 
+
+	for (i = 0; i<themes; i++) {
+		SDL_FreeSurface(titles[i]);
+		SDL_FreeSurface(select[i]);
+	}
+
+	SDL_FreeSurface(world);
+	SDL_FreeSurface(bkg);
+	SDL_FreeSurface(left);
+	SDL_FreeSurface(right);
+}

Added: tuxmath/trunk/src/titlescreen.c
===================================================================
--- tuxmath/trunk/src/titlescreen.c	2006-12-02 00:28:17 UTC (rev 64)
+++ tuxmath/trunk/src/titlescreen.c	2006-12-02 00:34:38 UTC (rev 65)
@@ -0,0 +1,1318 @@
+/***************************************************************************
+ -  file: titlescreen.c
+ -  description: splash, title and menu screen functionality 
+                            ------------------
+    begin                : Thur May 4 2000
+    copyright            : (C) 2000 by Sam Hart
+                         : (C) 2003 by Jesse Andrews
+    email                : tuxtype-dev at tux4kids.net
+***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+
+
+#include "titlescreen.h"
+
+// globals from tuxtype's globals.h defined outside of titlescreen.c (in tuxtype):
+int debugOn; //FIXME switch to TUXMATH_DEBUG
+TTF_Font  *font;
+SDL_Event  event;
+SDL_Surface *bkg;
+
+/* --- media for menus --- */
+
+/* --- define menu structure --- */
+/* (these values are all in the Game_Type enum in globals.h) */
+const int menu_item[][6]= {{0, 0,         0,         0,          0},
+			   {0, CASCADE,   LEVEL1,    LEVEL1,  NOT_CODED },
+			   {0, LASER,     LEVEL2,    LEVEL2,  FREETYPE   },
+			   {0, LESSONS,  LEVEL3,    LEVEL3,  PROJECT_INFO },
+			   {0, OPTIONS,   INSTRUCT,  LEVEL4,  SET_LANGUAGE},
+			   {0, QUIT_GAME, MAIN,      MAIN,    MAIN}};
+
+/* --- menu text --- */
+const unsigned char *menu_text[][6]= 
+{{"", "",            "",             "",            ""    },
+ {"", gettext_noop("Fish Cascade"), gettext_noop("Easy"),         gettext_noop("Space Cadet"), gettext_noop("Edit Word Lists")},
+ {"", gettext_noop("Comet Zap"),    gettext_noop("Medium"),       gettext_noop("Pilot"),       gettext_noop("Practice")},
+ {"", gettext_noop("Lessons"),     gettext_noop("Hard"),         gettext_noop("Ace"),         gettext_noop("Project Info")},
+ {"", gettext_noop("Options"),      gettext_noop("Instructions"), gettext_noop("Commander"),   gettext_noop("Setup Language")},
+ {"", gettext_noop("Quit"),         gettext_noop("Main Menu"),    gettext_noop("Main Menu"),   gettext_noop("Main Menu")}};
+
+/* --- menu icons --- */
+const unsigned char *menu_icon[][6]= 
+{{"", "", "", "", ""},
+ {"", "cascade", "easy",   "grade1_", "list"   },
+ {"", "comet",   "medium", "grade2_", "practice" },
+ {"", "lesson","hard",   "grade3_", "keyboard"   },
+ {"", "option",  "tutor",  "grade4_", "lang" },
+ {"", "quit",    "main",   "main",    "main"   }};
+
+/* images of regular and selected text of menu items: */
+SDL_Surface *reg_text[TITLE_MENU_ITEMS + 1][TITLE_MENU_DEPTH + 1];
+SDL_Surface *sel_text[TITLE_MENU_ITEMS + 1][TITLE_MENU_DEPTH + 1];
+sprite *reg;
+sprite *sel;
+/* this will contain pointers to all of the menu 'icons' */
+sprite *menu_gfx[TITLE_MENU_ITEMS + 1][TITLE_MENU_DEPTH + 1];
+/* keep track of the width of each menu: */
+int     menu_width[TITLE_MENU_DEPTH + 1];
+
+/* NOTE for 'depth', think pages like a restaurant menu, */
+/* not heirarchical depth - choice of term is misleading */
+int menu_depth; // how deep we are in the menu
+int menu_sound; // status of menu sound effects
+int menu_music; // status of menu sound effects
+settings localsettings;
+
+/* --- other media --- */
+SDL_Surface *title;
+SDL_Surface *speaker;
+SDL_Surface *speakeroff;
+sprite *Tux;
+Mix_Chunk *snd_move, *snd_select;
+
+/* --- locations we need --- */
+SDL_Rect text_dst[TITLE_MENU_ITEMS + 1];     // location of text for menu
+SDL_Rect menu_gfxdest[TITLE_MENU_ITEMS + 1]; // location of animated icon
+/* These are the rectangular mouse event "buttons" for each menu item */
+SDL_Rect menu_button[TITLE_MENU_ITEMS + 1];  // size of "button"
+
+
+/* Local function prototypes: */
+int chooseWordlist(void);
+void draw_button(int id, sprite* s);
+void TitleScreen_load_menu(void);
+void TitleScreen_unload_menu(void);
+void TitleScreen_load_media(void);
+void TitleScreen_unload_media(void);
+void NotImplemented(void);
+
+
+
+void draw_button( int id, sprite *s ) {
+	SDL_Rect button;
+
+	button.x = menu_button[id].x;
+	button.y = menu_button[id].y;
+	button.w = s->frame[0]->w;
+	button.h = s->frame[0]->h;
+	SDL_BlitSurface(s->frame[0], NULL, screen, &button);
+	button.w = s->frame[1]->w;
+	for (button.x += s->frame[0]->w; button.x < (menu_button[id].x + menu_width[menu_depth]); button.x += s->frame[1]->w) 
+		SDL_BlitSurface(s->frame[1], NULL, screen, &button);
+	button.w = s->frame[2]->w;
+	SDL_BlitSurface(s->frame[2], NULL, screen, &button);
+}
+
+
+void TitleScreen_load_menu( void ) {
+	unsigned char fn[FNLEN];
+	int max, i, j;
+
+	SDL_ShowCursor(1);
+
+	LOG("loading & parsing menu\n");
+	
+	for (j = 1; j <= TITLE_MENU_DEPTH; j++)  /* Each 'depth' is a different menu */
+	{
+		max = 0;
+		for (i = 1; i <= TITLE_MENU_ITEMS; i++)
+		{
+
+			/* --- create text surfaces --- */
+
+			reg_text[i][j] = black_outline( _((unsigned char*)menu_text[i][j]), font, &white);
+			sel_text[i][j] = black_outline( _((unsigned char*)menu_text[i][j]), font, &yellow);
+
+			if (sel_text[i][j]->w > max)
+				max = sel_text[i][j]->w;
+
+			/* --- load animated icon for menu item --- */
+
+			sprintf(fn, "menu/%s", menu_icon[i][j]);
+			menu_gfx[i][j] = LoadSprite(fn, IMG_ALPHA);
+		}
+		menu_width[j] = max + 20 + 40; // Not clear where '20' and '40' are coming from
+	}
+
+	LOG("done creating graphics, now setting positions\n");
+
+
+	/* --- setup menu item destinations --- */
+
+
+	menu_button[1].x = 240;
+	menu_button[1].y = 100;
+	menu_button[1].w = menu_width[1];  //calc from width of widest menu item
+	menu_button[1].h = sel->frame[1]->h; //height of sprite image
+
+	menu_gfxdest[1].x = menu_button[1].x + 6; // inset graphic by (6, 4) */
+	menu_gfxdest[1].y = menu_button[1].y + 4;
+	menu_gfxdest[1].w = 40;
+	menu_gfxdest[1].h = 50;
+
+	text_dst[1].y = menu_button[1].y+15;
+
+	/* FIXME each menu item drawn hardcoded 60 pixels below last - */
+	/* perhaps increment should be "menu_button[j-1].h + MENU_ITEM_GAP" */
+	for (j=2; j<6; j++) 
+	{
+		/* --- setup vertical location of button text --- */
+		text_dst[j].y = text_dst[j-1].y + 60;
+
+		/* --- setup location of button background --- */
+		menu_button[j].x = menu_button[j-1].x;
+		menu_button[j].y = menu_button[j-1].y + 60;
+		menu_button[j].w = menu_button[j-1].w;
+		menu_button[j].h = menu_button[j-1].h;
+
+		/* --- setup location of animated icon --- */
+		menu_gfxdest[j].x = menu_gfxdest[j-1].x;
+		menu_gfxdest[j].y = menu_gfxdest[j-1].y + 60;
+		menu_gfxdest[j].w = menu_gfxdest[j-1].w;
+		menu_gfxdest[j].h = menu_gfxdest[j-1].h;
+	}
+}
+
+void TitleScreen_unload_menu( void ) {
+	int i,j;
+
+	for (i = 1; i <= TITLE_MENU_ITEMS; i++)
+		for (j = 1; j <= TITLE_MENU_DEPTH; j++) {
+			SDL_FreeSurface(reg_text[i][j]);
+			SDL_FreeSurface(sel_text[i][j]);
+			FreeSprite(menu_gfx[i][j]);
+	}
+}
+
+void TitleScreen_load_media( void ) {
+
+	/* --- load sounds --- */
+	DEBUGCODE
+	{
+		fprintf(stderr, "Entering TitleScreen_load_media():\n");
+		fprintf(stderr, "realPath[0] = %s\n", realPath[0]);
+		fprintf(stderr, "realPath[1] = %s\n", realPath[1]);
+	}
+
+	if (menu_sound){
+	    snd_move = LoadSound("tock.wav");
+	    snd_select = LoadSound("pop.wav");
+	}
+ 
+	/* --- load graphics --- */
+
+	title = LoadImage( "title1.png", IMG_ALPHA );
+	speaker = LoadImage( "sound.png", IMG_ALPHA );
+	speakeroff = LoadImage( "nosound.png", IMG_ALPHA );
+	bkg = LoadImage( "main_bkg.png", IMG_REGULAR );
+
+	sel = LoadSprite("menu/sel", IMG_ALPHA);
+	reg = LoadSprite("menu/reg", IMG_ALPHA);
+
+	Tux = LoadSprite("tux", IMG_ALPHA);
+
+	font = LoadFont( menu_font, menu_font_size );
+	/* Should probably call this directly from TitleScreen() */
+	TitleScreen_load_menu();
+}
+
+void TitleScreen_unload_media( void ) {
+
+	/* --- unload sounds --- */
+
+	if (menu_sound){
+	    Mix_FreeChunk(snd_move);
+	    Mix_FreeChunk(snd_select);
+	}
+
+	/* --- unload graphics --- */
+
+	SDL_FreeSurface(title);
+	SDL_FreeSurface(speaker);
+	SDL_FreeSurface(speakeroff);
+	SDL_FreeSurface(bkg);
+
+	FreeSprite(sel);
+	FreeSprite(reg);
+
+	FreeSprite(Tux);
+
+	TTF_CloseFont(font);
+	TitleScreen_unload_menu();
+}
+
+void NotImplemented(void) {
+	SDL_Surface *s1, *s2, *s3, *s4;
+	sprite *tux;
+	SDL_Rect loc;
+	int finished=0,i;
+
+        LOG( "NotImplemented() - creating text\n" );
+
+	s1 = black_outline( _("Work In Progress!"), font, &white);
+	s2 = black_outline( _("This feature is not ready yet"), font, &white);
+	s3 = black_outline( _("Discuss the future of TuxTyping at"), font, &white);
+
+	/* we always want the URL in english */
+	if (!useEnglish) {
+		TTF_Font *english_font;
+		useEnglish = 1;
+		english_font = LoadFont( menu_font, menu_font_size );
+		s4 = black_outline( "http://tuxtype.sf.net/forums", english_font, &white);
+		TTF_CloseFont(english_font);
+		useEnglish = 0;
+	} else 
+		s4 = black_outline( "http://tuxtype.sf.net/forums", font, &white);
+
+        LOG( "NotImplemented() - drawing screen\n" );
+
+	SDL_BlitSurface( bkg, NULL, screen, NULL );
+	loc.x = 320-(s1->w/2); loc.y = 10;
+	SDL_BlitSurface( s1, NULL, screen, &loc);
+	loc.x = 320-(s2->w/2); loc.y = 60;
+	SDL_BlitSurface( s2, NULL, screen, &loc);
+	loc.x = 320-(s3->w/2); loc.y = 400;
+	SDL_BlitSurface( s3, NULL, screen, &loc);
+	loc.x = 320-(s4->w/2); loc.y = 440;
+	SDL_BlitSurface( s4, NULL, screen, &loc);
+
+	tux = LoadSprite("tux/tux-egypt", IMG_ALPHA);
+
+	loc.x = 320-(tux->frame[0]->w/2);
+	loc.y = 200;
+	loc.w = tux->frame[0]->w;
+	loc.h = tux->frame[0]->h;
+	SDL_BlitSurface( tux->frame[tux->cur], NULL, screen, &loc);
+
+	SDL_UpdateRect(screen, 0, 0, 0, 0);
+
+	i=0;
+	while (!finished) {
+		while (SDL_PollEvent(&event)) 
+			switch (event.type) {
+				case SDL_QUIT:
+					exit(0);
+				case SDL_MOUSEBUTTONDOWN:
+				case SDL_KEYDOWN:
+					finished=1;
+			}
+		i++;
+		if (i%5==0) {
+			next_frame(tux);
+			SDL_BlitSurface( bkg, &loc, screen, &loc);
+			SDL_BlitSurface( tux->frame[tux->cur], NULL, screen, &loc);
+			SDL_UpdateRect(screen, loc.x, loc.y, loc.w, loc.h);
+		}
+
+			
+		SDL_Delay(40);
+	}
+
+	SDL_FreeSurface(s1);
+	SDL_FreeSurface(s2);
+	SDL_FreeSurface(s3);
+	SDL_FreeSurface(s4);
+	FreeSprite(tux);
+}
+
+/****************************************
+* TitleScreen: Display the title screen *
+*****************************************
+* display title screen, get input
+*/
+void TitleScreen( void )
+{
+
+  SDL_Rect dest,
+	 Tuxdest,
+	 Titledest,
+	 spkrdest,
+	 cursor;
+
+  Uint32 frame = 0;
+  Uint32 start = 0;
+
+  int i, j, tux_frame = 0;
+  int done = 0;
+  int firstloop = 1;
+  int menu_opt = NONE;
+  int sub_menu = NONE;
+  int update_locs = 1;
+  int redraw = 0;
+  int key_menu = 1;
+  int old_key_menu = 5;
+  char phrase[128];
+
+  debugOn = 1; //for now
+
+  if (sys_sound)
+  {
+    menu_sound=1;
+    menu_music=localsettings.menu_music;
+  }
+
+
+  /* FIXME phrase(s) should come from file */
+  strncpy( phrase, "Now is the time for all good men to come to the aid of their country.", 128);
+  start = SDL_GetTicks();
+
+
+  /*
+  * StandbyScreen: Display the Standby screen.... 
+  */
+
+  if (show_tux4kids)
+  {
+    SDL_Surface *standby;
+    standby = LoadImage("standby.png", IMG_REGULAR|IMG_NO_THEME);
+
+    dest.x = ((screen->w) / 2) - (standby->w) / 2;  // Center horizontally
+    dest.y = ((screen->h) / 2) - (standby->h) / 2;  // Center vertically
+    dest.w = standby->w;
+    dest.h = standby->h;
+
+    SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
+    SDL_BlitSurface(standby, NULL, screen, &dest);
+    SDL_UpdateRect(screen, 0, 0, 0, 0);
+    SDL_FreeSurface(standby);  // Unload image
+  }
+
+
+  /* Load media and menu data: */
+  TitleScreen_load_media();
+  SDL_WM_GrabInput(SDL_GRAB_ON); // User input goes to TuxType, not window manager
+
+
+  /***************************
+  * Tux and Title animations *
+  ***************************/
+
+  LOG( "->Now Animating Tux and Title onto the screen\n" );
+
+  Tuxdest.x = 0;
+  Tuxdest.y = screen->h;
+  Tuxdest.w = Tux->frame[0]->w;
+  Tuxdest.h = Tux->frame[0]->h;
+
+  Titledest.x = screen->w;
+  Titledest.y = 10;
+  Titledest.w = title->w;
+  Titledest.h = title->h;
+
+  spkrdest.x = 520;
+  spkrdest.y = 420;
+  spkrdest.w = speaker->w;
+  spkrdest.h = speaker->h;
+
+  /* --- wait if the first time in the game --- */
+
+  if (show_tux4kids)
+  {
+    while ((SDL_GetTicks() - start) < 2000)
+    {
+      SDL_Delay(50);
+    }
+    show_tux4kids = 0;
+  }
+
+  SDL_ShowCursor(1);    
+  /* FIXME not sure the next line works in Windows: */
+  TransWipe(bkg, RANDOM_WIPE, 10, 20);
+
+
+  /* --- Pull tux & logo onscreen --- */
+  for (i = 0; i < (PRE_ANIM_FRAMES * PRE_FRAME_MULT); i++)
+  {
+    start = SDL_GetTicks();
+    SDL_BlitSurface(bkg, &Tuxdest, screen, &Tuxdest);
+    SDL_BlitSurface(bkg, &Titledest, screen, &Titledest);
+
+    Tuxdest.y -= Tux->frame[0]->h / (PRE_ANIM_FRAMES * PRE_FRAME_MULT);
+    Titledest.x -= (screen->w) / (PRE_ANIM_FRAMES * PRE_FRAME_MULT);
+
+    SDL_BlitSurface(Tux->frame[0], NULL, screen, &Tuxdest);
+    SDL_BlitSurface(title, NULL, screen, &Titledest);
+
+    SDL_UpdateRect(screen, Tuxdest.x, Tuxdest.y, Tuxdest.w, Tuxdest.h);
+    SDL_UpdateRect(screen, Titledest.x, Titledest.y, Titledest.w+40, Titledest.h);
+
+    while ((SDL_GetTicks() - start) < 33) 
+    {
+      SDL_Delay(2);
+    }
+  }
+
+  SDL_BlitSurface(title, NULL, screen, &Titledest);
+
+  /* Pick speaker graphic according to whether music is on: */
+  if ( menu_music )
+    SDL_BlitSurface(speaker, NULL, screen, &spkrdest);
+  else
+    SDL_BlitSurface(speakeroff, NULL, screen, &spkrdest);
+
+  /* Start playing menu music if desired: */
+  if (menu_music)
+    audioMusicLoad( "tuxi.ogg", -1 );
+
+  LOG( "Tux and Title are in place now\n" );
+
+  /* Move mouse to top button: */
+  cursor.x = menu_button[1].x + (menu_button[1].w / 2);
+  cursor.y = menu_button[1].y + (3 * menu_button[1].h / 4);
+  SDL_WarpMouse(cursor.x, cursor.y);
+  SDL_WM_GrabInput(SDL_GRAB_OFF);
+
+
+
+  /****************************
+  * Main Loop Starts Here ... *
+  ****************************/
+
+
+  menu_depth = 1;
+  firstloop = 1;
+  Tuxdest.y = screen->h - Tux->frame[0]->h;
+
+
+  while (!done) 
+  {
+
+    start=SDL_GetTicks();
+
+    /* ---process input queue --- */
+
+    menu_opt = NONE; // clear the option so we don't change twice!
+
+    old_key_menu = key_menu;
+
+    /* Retrieve any user interface events: */
+    while (SDL_PollEvent(&event))
+    {
+      switch (event.type)
+      {
+
+        case SDL_MOUSEMOTION:
+        {
+          cursor.x = event.motion.x;
+          cursor.y = event.motion.y;
+          break;
+        }
+
+
+        /* Handle mouse clicks based on mouse location: */
+        case SDL_MOUSEBUTTONDOWN:
+        {
+          cursor.x = event.motion.x;
+          cursor.y = event.motion.y;
+
+          for (j = 1; j <= TITLE_MENU_ITEMS; j++)
+          {
+            if ((cursor.x >= menu_button[j].x && cursor.x <= (menu_button[j].x + menu_button[j].w)) && 
+                (cursor.y >= menu_button[j].y && cursor.y <= (menu_button[j].y + menu_button[j].h)))
+            {
+              menu_opt = menu_item[j][menu_depth];
+              if (menu_sound)
+              {
+                playsound(snd_select);
+              }
+              DEBUGCODE
+              {
+                fprintf(stderr, "->>BUTTON CLICK menu_opt = %d\n", menu_opt);
+                fprintf(stderr, "->J = %d menu_depth=%d\n", j, menu_depth);
+              }
+            }
+          }
+
+          /* If mouse over speaker, toggle menu music off or on: */
+          if ((cursor.x >= spkrdest.x && cursor.x <= (spkrdest.x + spkrdest.w)) && 
+              (cursor.y >= spkrdest.y && cursor.y <= (spkrdest.y + spkrdest.h)))
+          {
+            if (menu_music)
+            {
+              audioMusicUnload();
+              menu_music = 0;
+            }
+            else
+            {
+              menu_music = 1;
+              audioMusicLoad("tuxi.ogg", -1);
+            }
+            redraw = 1;
+          }
+          break;
+        }
+
+
+
+        case SDL_QUIT:
+        {
+          menu_opt = QUIT_GAME;
+          break;
+        }
+
+
+        /* Handle key press events based on key value: */
+        case SDL_KEYDOWN:
+        {
+          switch (event.key.keysym.sym)
+          {
+            case SDLK_ESCAPE:
+            {
+              /* Go to main menu (if in submenu) or quit: */
+              if (menu_depth != 1) 
+                menu_opt = MAIN;
+              else
+                menu_opt = QUIT_GAME;
+
+              if (menu_sound)
+                playsound(snd_select);
+              break;
+            }
+
+
+            /* Toggle screen mode: */
+            case SDLK_F10: /* NOTE Cool! - should add this to TuxMath*/
+            {
+              switch_screen_mode();
+              redraw = 1;
+              break;
+            }
+
+
+            /* Toggle menu music: */
+            case SDLK_F11:
+            {
+              if (menu_music)
+              {
+                audioMusicUnload( );
+                menu_music=0;
+              }
+              else
+              {
+                menu_music=1;
+                audioMusicLoad("tuxi.ogg", -1);
+              }
+              redraw = 1;
+              break;
+            }
+
+
+            /* --- reload translation/graphics/media: for themers/translaters --- */
+            case SDLK_F12:
+            {
+              TitleScreen_unload_media();
+              LoadLang();
+              TitleScreen_load_media();
+              redraw = 1;
+              break;
+            }
+
+
+            case SDLK_UP:
+            {
+              if (menu_sound)
+                playsound(snd_move);
+              key_menu--;
+              if (key_menu < 1)
+                key_menu = 5;
+              break;
+            }
+
+
+            case SDLK_DOWN:
+            {
+              key_menu++;
+              if (menu_sound)
+                playsound(snd_move);
+              if (key_menu > 5)
+                key_menu = 1;
+              break;
+            }
+
+
+            case SDLK_RETURN:
+            {
+              if (key_menu)
+              {
+                menu_opt = menu_item[key_menu][menu_depth];
+                if (menu_sound)
+                  playsound(snd_select);
+              }
+              break;
+            }
+
+
+            default:     /* Some other key pressed - do nothing: */
+            {
+              break;
+            }
+          }             /* End of switch(event.key.keysym.sym) statement */
+        }               /* End of case: SDL_KEYDOWN: */
+
+
+        default:        /* Some other type of SDL event - do nothing;    */
+        {
+          break;
+        }
+      }                 /* End of switch(event.type) statement           */
+    }	              /* End of while (SDL_PollEvent(&event)) loop     */
+
+
+
+    /* --- warp mouse to follow keyboard input --- */
+
+    if (old_key_menu != key_menu)
+    {
+      cursor.x = menu_button[key_menu].x + (menu_button[key_menu].w / 2);
+      cursor.y = menu_button[key_menu].y + (3 * menu_button[key_menu].h / 4);
+      SDL_WarpMouse(cursor.x, cursor.y);
+    }
+
+
+
+    /* --- do menu processing --- */
+
+
+    if (menu_opt == QUIT_GAME)
+      done = 1;
+
+
+    if (menu_opt == LASER)
+    {
+      menu_depth = LASER_SUBMENU;
+      sub_menu = LASER;
+      update_locs = 1;
+      redraw = 1;
+    }
+
+
+    if (menu_opt == CASCADE)
+    {
+      menu_depth = CASCADE_SUBMENU;
+      sub_menu = CASCADE;
+      update_locs = 1;
+      redraw=1;
+    }
+
+
+    if (menu_opt == OPTIONS)
+    {
+      menu_depth = OPTIONS_SUBMENU;
+      sub_menu = OPTIONS;
+      update_locs = 1;
+      redraw = 1;
+    }
+
+
+    if (menu_opt == MAIN)
+    {
+      menu_depth = ROOTMENU;
+      update_locs = 1;
+      redraw = 1;
+    }
+
+
+    if (menu_opt == NOT_CODED)
+    {
+      NotImplemented();
+      redraw = 1;
+    }
+
+
+    if (menu_opt == PROJECT_INFO)
+    {
+      projectInfo();
+      redraw = 1;
+    }
+
+
+    if (menu_opt == LESSONS)
+    {
+      SDL_BlitSurface(bkg, NULL, screen, NULL);
+      SDL_Flip( screen );
+      TitleScreen_unload_media();
+
+      if (menu_music)
+        audioMusicUnload( );
+
+      testLesson();
+
+      TitleScreen_load_media();
+      redraw = 1;
+
+      if (menu_music)
+        audioMusicLoad( "tuxi.ogg", -1 );
+    }
+
+
+    if (menu_opt == SET_LANGUAGE)
+    {
+      TitleScreen_unload_media();
+      chooseTheme();
+      LoadLang();
+      LoadKeyboard();
+      TitleScreen_load_media();
+      redraw = 1;
+
+      if (menu_music)
+        audioMusicLoad( "tuxi.ogg", -1 );
+    }
+
+
+    if (menu_opt == LEVEL1)
+    {
+      if (chooseWordlist()) 
+      {
+        TitleScreen_unload_media();
+
+        switch (sub_menu)
+        {
+          case CASCADE: PlayCascade( EASY ); break;
+          case LASER:   laser_game(  EASY ); break;
+        }
+
+        TitleScreen_load_media();
+
+        if (menu_music)
+          audioMusicLoad( "tuxi.ogg", -1 );
+      }
+
+      redraw = 1;
+    }
+
+
+    if (menu_opt == LEVEL2)
+    {
+      if (chooseWordlist())
+      {
+        TitleScreen_unload_media();
+
+        switch (sub_menu)
+        {
+          case CASCADE: PlayCascade( MEDIUM ); break;
+          case LASER:   laser_game(  MEDIUM ); break;
+        }
+
+        TitleScreen_load_media();
+
+        if (menu_music)
+          audioMusicLoad( "tuxi.ogg", -1 );
+      }
+
+      redraw = 1;
+    }
+
+
+
+    if (menu_opt == LEVEL3)
+    {
+      if (chooseWordlist())
+      {
+        TitleScreen_unload_media();
+
+        switch (sub_menu)
+        {
+          case CASCADE: PlayCascade( HARD ); break;
+          case LASER:   laser_game(  HARD ); break;
+        }
+
+        TitleScreen_load_media();
+
+        if (menu_music)
+          audioMusicLoad( "tuxi.ogg", -1 );
+      }
+
+      redraw = 1;
+    }
+
+
+
+    if (menu_opt == LEVEL4)
+    {
+      if (chooseWordlist())
+      {
+        TitleScreen_unload_media();
+
+        switch (sub_menu)
+        {
+          case CASCADE: PlayCascade( INSANE ); break;
+          case LASER:   laser_game(  INSANE ); break;
+        }
+
+        TitleScreen_load_media();
+
+        if (menu_music)
+          audioMusicLoad( "tuxi.ogg", -1 );
+      }
+
+      redraw = 1;
+    }
+
+
+
+    if (menu_opt == INSTRUCT)
+    {
+      TitleScreen_unload_media();
+
+      switch (sub_menu)
+      {
+        case CASCADE: InstructCascade(); break;
+        case LASER:   InstructLaser();   break;
+      }
+
+      TitleScreen_load_media();
+
+      if (menu_music)
+        audioMusicLoad( "tuxi.ogg", -1 );
+
+      redraw = 1;
+    }
+
+
+
+    if (menu_opt == FREETYPE)
+    {
+      TitleScreen_unload_media();
+      Phrases( phrase );
+      //Practice();
+      TitleScreen_load_media();
+      redraw = 1;
+    }
+
+    /* ------ End menu_opt processing ----------- */
+
+
+
+    if (redraw)
+    {
+      SDL_BlitSurface(bkg, NULL, screen, NULL); 
+      SDL_BlitSurface(title, NULL, screen, &Titledest);
+
+      if ( menu_music )
+        SDL_BlitSurface(speaker, NULL, screen, &spkrdest);
+      else
+        SDL_BlitSurface(speakeroff, NULL, screen, &spkrdest);
+
+      SDL_UpdateRect(screen, 0, 0, 0, 0);
+      frame = redraw = 0;   // so we redraw tux
+      update_locs = 1;      // so we redraw menu
+      firstloop = 1;
+    }
+
+
+
+    /* --- create new menu screen when needed --- */
+
+    if (update_locs)
+    {
+      /* --- erase the last menu --- */
+      for (i = 1; i <= TITLE_MENU_ITEMS; i++)
+      {
+        text_dst[i].x = 290;
+        text_dst[i].w = reg_text[i][menu_depth]->w;
+        text_dst[i].h = reg_text[i][menu_depth]->h;
+        SDL_BlitSurface(bkg, &menu_button[i], screen, &menu_button[i]);
+        menu_button[i].w = menu_width[menu_depth] + (2*reg->frame[2]->w);
+      }
+
+      update_locs = 0;
+
+      /* --- draw the full menu --- */
+
+      for (j = 1; j <= TITLE_MENU_ITEMS; j++)
+      {
+        draw_button(j, reg);
+        SDL_BlitSurface(reg_text[j][menu_depth], NULL, screen, &text_dst[j]);
+        SDL_BlitSurface(menu_gfx[j][menu_depth]->default_img, NULL, screen, &menu_gfxdest[j]);
+      }
+    }
+
+
+
+    /* --- make tux blink --- */
+
+    switch (frame % TUX6)
+    {
+      case 0:    tux_frame = 1; break;
+      case TUX1: tux_frame = 2; break;
+      case TUX2: tux_frame = 3; break;
+      case TUX3: tux_frame = 4; break;			
+      case TUX4: tux_frame = 3; break;
+      case TUX5: tux_frame = 2; break;
+      default: tux_frame = 0;
+    }
+
+    if (tux_frame)
+    {
+      SDL_BlitSurface(bkg, &Tuxdest, screen, &Tuxdest);
+      SDL_BlitSurface(Tux->frame[tux_frame - 1], NULL, screen, &Tuxdest);
+    }
+
+
+    /* --- check if mouse is in a menu option --- */
+
+    key_menu = 0;
+
+    for (j = 1; j <= TITLE_MENU_ITEMS; j++)
+    {
+      if ((cursor.x >= menu_button[j].x && cursor.x <= (menu_button[j].x + menu_button[j].w)) &&
+          (cursor.y >= menu_button[j].y && cursor.y <= (menu_button[j].y + menu_button[j].h)))
+      {
+        key_menu = j; // update menu to point
+        break;        // Don't need to check rest of menu
+      }
+    }
+
+
+    /* --- return old selection to unselected state --- */
+
+    if (old_key_menu && (key_menu != old_key_menu))
+    {
+      SDL_BlitSurface(bkg, &menu_button[old_key_menu], screen, &menu_button[old_key_menu]);
+      draw_button( old_key_menu, reg );
+      SDL_BlitSurface(reg_text[old_key_menu][menu_depth], NULL, screen, &text_dst[old_key_menu]);
+      SDL_BlitSurface(menu_gfx[old_key_menu][menu_depth]->default_img, NULL, screen, &menu_gfxdest[old_key_menu]);
+    }
+
+
+    /* --- draw current selection --- */
+
+    if ((key_menu != 0) &&
+       ((old_key_menu != key_menu) || (frame % 5 == 0))) // Redraw every fifth frame?
+    {
+      if (key_menu != old_key_menu)
+      {
+        rewind(menu_gfx[key_menu][menu_depth]);
+        playsound(snd_move);
+      }
+
+      SDL_BlitSurface(bkg, &menu_button[key_menu], screen, &menu_button[key_menu]);
+      draw_button( key_menu, sel );
+      SDL_BlitSurface(sel_text[key_menu][menu_depth], NULL, screen, &text_dst[key_menu]);
+      SDL_BlitSurface(menu_gfx[key_menu][menu_depth]->frame[menu_gfx[key_menu][menu_depth]->cur], NULL, screen, &menu_gfxdest[key_menu]);
+
+      next_frame(menu_gfx[key_menu][menu_depth]);
+    }
+
+
+    // HACK This is still more than we need to update every frame but
+    // it cuts cpu on my machine %60 so it seems better...
+    if ( menu_music )
+      SDL_BlitSurface(speaker, NULL, screen, &spkrdest);
+    else
+      SDL_BlitSurface(speakeroff, NULL, screen, &spkrdest);
+
+    SDL_UpdateRect(screen, spkrdest.x, spkrdest.y, spkrdest.w, spkrdest.h);
+
+    for ( i=1; i<6; i++ )
+    {
+      SDL_UpdateRect(screen, menu_button[i].x, menu_button[i].y, menu_button[i].w, menu_button[i].h);
+    }
+
+    if (tux_frame)
+      SDL_UpdateRect(screen, Tuxdest.x+37, Tuxdest.y+40, 70, 45);
+
+    if (firstloop)
+      SDL_UpdateRect(screen, Tuxdest.x, Tuxdest.y, Tuxdest.w, Tuxdest.h);
+
+    firstloop = 0;
+
+    /* Wait so we keep frame rate constant: */
+    while ((SDL_GetTicks() - start) < 33)
+    {
+      SDL_Delay(20);
+    }
+
+    frame++;
+  } /* ----------- End of 'while(!done)' loop ------------  */
+
+
+
+  LOG( "->>Freeing title screen images\n" );
+
+  localsettings.menu_music=menu_music;
+  TitleScreen_unload_media();
+
+  LOG( "->TitleScreen():END \n" );
+}
+
+
+
+#define MAX_WORD_LISTS 100
+
+/* returns 0 if user pressed escape ...
+ *         1 if word list was set correctly
+ */
+int chooseWordlist( void ) {
+	SDL_Surface *titles[MAX_WORD_LISTS];
+	SDL_Surface *select[MAX_WORD_LISTS];
+	SDL_Surface *left, *right;
+	SDL_Rect leftRect, rightRect;
+	SDL_Rect titleRects[8];
+	int stop = 0;
+	int loc = 0;
+	int old_loc = 1;
+	int lists = 1;
+	int i;
+	unsigned char wordPath[FNLEN];
+	unsigned char wordlistFile[MAX_WORD_LISTS][200];
+	unsigned char wordlistName[MAX_WORD_LISTS][200];
+
+	DIR *wordsDir;
+	struct dirent *wordsFile;
+	struct stat fileStats;
+	FILE *tempFile;
+
+	LOG("Entering chooseWordlist():\n");
+
+	/* find the directory to load wordlists from */
+
+	for (i=useEnglish; i<2; i++) {
+		fileStats.st_mode = 0; // clear last use!
+		sprintf( wordPath, "%s/words", realPath[i] );
+		stat( wordPath, &fileStats );
+		if ( fileStats.st_mode & S_IFDIR )
+			break;
+	}
+
+	if (i==2) {
+		fprintf(stderr, "ERROR: Unable to find wordlist directory\n");
+		exit(1);
+	}
+
+	DEBUGCODE { fprintf(stderr, "wordPath is: %s\n", wordPath); }
+
+	/* create a list of all the .txt files */
+
+	wordsDir = opendir( wordPath );	
+
+	do {
+		wordsFile = readdir(wordsDir);
+		if (!wordsFile)
+			break;
+
+		/* must have at least .txt at the end */
+		if (strlen(wordsFile->d_name) < 5)
+			continue;
+
+		if (strcmp(&wordsFile->d_name[strlen(wordsFile->d_name)-4],".txt"))
+			continue;
+
+		sprintf( wordlistFile[lists], "%s/%s", wordPath, wordsFile->d_name );
+
+		/* load the name for the wordlist from the file ... (1st line) */
+		tempFile = fopen( wordlistFile[lists], "r" );
+		if (tempFile==NULL) continue;
+		fscanf( tempFile, "%[^\n]\n", wordlistName[lists] );
+
+		/* check to see if it has a \r at the end of it (dos format!) */
+		if (wordlistName[lists][ strlen(wordlistName[lists])-1 ] == '\r')
+			wordlistName[lists][ strlen(wordlistName[lists])-1 ] = '\0';
+		lists++;
+
+		fclose(tempFile);
+		
+	} while (1);
+
+	closedir( wordsDir );	
+
+	/* let the user pick the list */
+
+	titles[0] = black_outline( _("Alphabet"), font, &white );
+	select[0] = black_outline( _("Alphabet"), font, &yellow);
+	for (i = 1; i<lists; i++) {
+		titles[i] = black_outline( wordlistName[i], font, &white );
+		select[i] = black_outline( wordlistName[i], font, &yellow);
+	}
+
+	SDL_FreeSurface(bkg);
+        bkg = LoadImage("main_bkg.png", IMG_REGULAR);
+
+        left = LoadImage("left.png", IMG_ALPHA);       
+        leftRect.w = left->w; leftRect.h = left->h;
+        leftRect.x = 320 - 80 - (leftRect.w/2); leftRect.y = 430;
+
+        right = LoadImage("right.png", IMG_ALPHA);
+        rightRect.w = right->w; rightRect.h = right->h;
+        rightRect.x = 320 + 80 - (rightRect.w/2); rightRect.y = 430;
+
+        /* set initial rect sizes */
+        titleRects[0].y = 30;
+        titleRects[0].w = titleRects[0].h = titleRects[0].x = 0;
+        for (i = 1; i<8; i++) { 
+                titleRects[i].y = titleRects[i-1].y + 50;
+                titleRects[i].w = titleRects[i].h = titleRects[i].x = 0;
+        }
+
+        while (!stop) {
+                while (SDL_PollEvent(&event))
+                        switch (event.type) {
+                                case SDL_QUIT:
+                                        exit(0);
+                                        break;
+                                case SDL_MOUSEMOTION:
+                                        for (i=0; (i<8) && (loc-(loc%8)+i<lists); i++)
+                                                if (inRect( titleRects[i], event.motion.x, event.motion.y )) {
+                                                        loc = loc-(loc%8)+i;
+                                                        break;
+                                                }
+
+                                        break;
+                                case SDL_MOUSEBUTTONDOWN:
+                                        if (inRect( leftRect, event.button.x, event.button.y ))
+                                                if (loc-(loc%8)-8 >= 0) {
+                                                        loc=loc-(loc%8)-8;
+                                                        break;
+                                                }
+                                        if (inRect( rightRect, event.button.x, event.button.y ))
+                                                if (loc-(loc%8)+8 < lists) {
+                                                        loc=loc-(loc%8)+8;
+                                                        break;
+                                                }
+                                        for (i=0; (i<8) && (loc-(loc%8)+i<lists); i++)
+                                                if (inRect(titleRects[i], event.button.x, event.button.y)) {
+                                                        loc = loc-(loc%8)+i;
+							WORDS_init(); /* clear old selection */
+							if (loc==0)
+								WORDS_use_alphabet(); 
+							else
+								WORDS_use( wordlistFile[loc] ); 
+                                                        stop = 1;
+                                                        break;
+                                                }
+                                        break;
+                                case SDL_KEYDOWN:
+                                        if (event.key.keysym.sym == SDLK_ESCAPE) { stop = 2; break; }
+                                        if (event.key.keysym.sym == SDLK_RETURN) {
+						WORDS_init(); /* clear old selection */
+						if (loc==0)
+							WORDS_use_alphabet(); 
+						else
+							WORDS_use( wordlistFile[loc] ); 
+                                                stop = 1;
+                                                break;
+                                        }
+
+                                        if ((event.key.keysym.sym == SDLK_LEFT) || (event.key.keysym.sym == SDLK_PAGEUP)) {
+                                                if (loc-(loc%8)-8 >= 0)
+                                                        loc=loc-(loc%8)-8;
+                                        }
+
+                                        if ((event.key.keysym.sym == SDLK_RIGHT) || (event.key.keysym.sym == SDLK_PAGEDOWN)) {
+                                                if (loc-(loc%8)+8 < lists)
+                                                        loc=(loc-(loc%8)+8);
+                                        }
+
+                                        if (event.key.keysym.sym == SDLK_UP) {
+                                                if (loc > 0)
+                                                        loc--;
+                                        }
+
+                                        if (event.key.keysym.sym == SDLK_DOWN) {
+                                                if (loc+1<lists)
+                                                        loc++;
+                                        }
+                        }
+
+                if (old_loc != loc) {
+                        int start;
+
+                        SDL_BlitSurface( bkg, NULL, screen, NULL );
+
+                        start = loc - (loc % 8);
+                        for (i = start; i<MIN(start+8,lists); i++) {
+                                titleRects[i%8].x = 320 - (titles[i]->w/2);
+                                if (i == loc)
+                                        SDL_BlitSurface(select[loc], NULL, screen, &titleRects[i%8]);
+                                else
+                                        SDL_BlitSurface(titles[i], NULL, screen, &titleRects[i%8]);
+                        }
+
+                        /* --- draw buttons --- */
+
+                        if (start>0)
+                                SDL_BlitSurface( left, NULL, screen, &leftRect );
+
+                        if (start+8<lists)
+                                SDL_BlitSurface( right, NULL, screen, &rightRect );
+
+                        SDL_UpdateRect(screen, 0, 0, 0 ,0);
+                }
+                SDL_Delay(40);
+                old_loc = loc;
+        }
+
+	/* --- clear graphics before leaving function --- */ 
+
+	for (i = 0; i<lists; i++) {
+		SDL_FreeSurface(titles[i]);
+		SDL_FreeSurface(select[i]);
+	}
+
+	SDL_FreeSurface(left);
+	SDL_FreeSurface(right);
+
+        DEBUGCODE { fprintf( stderr, "Leaving chooseWordlist();\n" ); }
+
+	if (stop == 2)
+		return 0;
+
+	return 1;
+}
+
+
+
+void switch_screen_mode(void)
+{
+  SDL_Surface *tmp;
+  SDL_Rect src, dst;
+  int window=0;
+  src.x = 0; src.y = 0;
+  src.w = RES_X; src.h = RES_Y;
+  dst.x = 0; dst.y = 0;
+
+  tmp = SDL_CreateRGBSurface(
+      SDL_SWSURFACE,
+      RES_X,
+      RES_Y,
+      BPP,
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+      0xff000000,
+      0x00ff0000,
+      0x0000ff00,
+      0x000000ff
+#else
+      0x000000ff,
+      0x0000ff00,
+      0x00ff0000,
+      0xff000000
+#endif
+      );
+  if (screen->flags & SDL_FULLSCREEN)
+	window=1;
+  SDL_BlitSurface(screen,&src,tmp,&dst);
+  SDL_UpdateRect(tmp,0,0,RES_X,RES_Y);
+  SDL_FreeSurface(screen);
+  screen = NULL;
+
+  if ( window ){
+	screen = SDL_SetVideoMode(RES_X,RES_Y,BPP, SDL_SWSURFACE|SDL_HWPALETTE);
+  } else {
+	screen = SDL_SetVideoMode(RES_X,RES_Y,BPP, SDL_SWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN);
+  }
+  SDL_BlitSurface(tmp,&src,screen,&dst);
+  SDL_UpdateRect(tmp,0,0,RES_X,RES_Y);
+  SDL_FreeSurface(tmp);
+
+}
+

Added: tuxmath/trunk/src/titlescreen.h
===================================================================
--- tuxmath/trunk/src/titlescreen.h	2006-12-02 00:28:17 UTC (rev 64)
+++ tuxmath/trunk/src/titlescreen.h	2006-12-02 00:34:38 UTC (rev 65)
@@ -0,0 +1,263 @@
+#ifdef WIN32 
+#undef DATA_PREFIX
+#define DATA_PREFIX ".//"
+#endif
+
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+#define rmask 0xff000000
+#define gmask 0x00ff0000
+#define bmask 0x0000ff00
+#define amask 0x000000ff
+#else
+#define rmask 0x000000ff
+#define gmask 0x0000ff00
+#define bmask 0x00ff0000
+#define amask 0xff000000
+#endif
+
+
+#ifndef TITLESCREEN_H
+#define TITLESCREEN_H
+
+#define to_upper(c) (((c) >= 'a' && (c) <= 'z') ? (c) -32 : (c))
+#define COL2RGB( col ) SDL_MapRGB( screen->format, col->r, col->g, col->b )
+
+#define FNLEN	200
+
+#define RES_X	640
+#define RES_Y	480
+#define BPP	16	
+
+
+#define MAX_SPRITE_FRAMES 30
+
+#include <string.h>
+#include <math.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#include <SDL.h>
+#include <SDL_image.h>
+#include <SDL_mixer.h>
+#include <SDL_ttf.h>
+
+
+#include "../config.h"
+
+
+
+#define next_frame(SPRITE) if ((SPRITE)->num_frames) (SPRITE)->cur = (((SPRITE)->cur)+1) % (SPRITE)->num_frames;
+#define rewind(SPRITE) (SPRITE)->cur = 0;
+
+#define MIN(x,y) ((x) < (y) ? (x) : (y))
+#define MAX(x,y) ((x) > (y) ? (x) : (y))
+
+typedef struct {
+    char lang[FNLEN];
+    char path[FNLEN];
+    char window[FNLEN];
+    int sfx_volume;
+    int mus_volume;
+    int menu_music;
+} settings;
+
+typedef struct {
+	SDL_Surface *frame[MAX_SPRITE_FRAMES];
+	SDL_Surface *default_img;
+	int num_frames;
+	int cur;
+} sprite;
+
+#define _(str) gettext (str)
+#define gettext_noop(str) (str)
+
+/* LOGGING works as such:
+ *
+ * - Use LOG if you want to output a string LOG( "Hello World");
+ *   
+ * - Use DOUT if you want to output a value of a variable and the
+ *   name of the variable gives enough context:
+ *   DOUT( specialCode );  would add to stderr: "specialCode = 1\n" or
+ *   whatever value specialCode had
+ *   
+ * - Use DEBUGCODE if you need to do something more complicated like
+ *   DEBUGCODE { fprintf(stderr, "examining letter %d\n", x); }
+ *   since DOUT(x) "x = 1\n" gives little information since x is used
+ *   all over the place!
+ */
+
+#define LOG( str ) if (debugOn) fprintf( stderr, str );
+#define DEBUGCODE if (debugOn) 
+#define DOUT(x) if (debugOn) fprintf(stderr, "%s = %d\n", #x, x);
+
+
+
+#define menu_font	"GenAI102.ttf" /* or "DejaVuSans-Bold.ttf"  or "FreeSansBold.ttf" */ 	/* was menu.ttf */
+#define menu_font_size	20
+
+#define ttf_font	"GenAI102.ttf" /* or "DejaVuSans-Bold.ttf" or "FreeSansBold.ttf" */  	/* was letters.ttf */
+#define ttf_font_size	20
+
+#define MAX_NUM_WORDS   500
+#define MAX_WORD_SIZE   8
+
+#define WAIT_MS				2500
+#define	FRAMES_PER_SEC	                50
+#define FULL_CIRCLE		        140
+
+/* Menu Prototypes */
+enum Game_Type { 
+	QUIT_GAME, CASCADE, OPTIONS, LESSONS,
+	INSTRUCT_CASCADE, CASCADE1, CASCADE2, CASCADE3, CASCADE4,
+	INSTRUCT_LASER,    LASER1,    LASER2,    LASER3,    LASER4,
+	FREETYPE, ASDF, ALL, MAIN, SET_LANGUAGE, PROJECT_INFO, EDIT_WORDLIST,
+	LEVEL1, LEVEL2, LEVEL3, LEVEL4, LASER, INSTRUCT, NOT_CODED, NONE};
+
+/* Title sequence constants */
+#define PRE_ANIM_FRAMES			10
+#define PRE_FRAME_MULT			3
+#define MENU_SEP			20
+
+/* paths */
+
+#define IMG_REGULAR  0x01
+#define IMG_COLORKEY 0x02
+#define IMG_ALPHA    0x04
+#define IMG_MODES    0x07
+
+#define IMG_NOT_REQUIRED 0x10
+#define IMG_NO_THEME     0x20
+
+//Game difficulty levels
+enum { EASY, MEDIUM, HARD, INSANE, INF_PRACT };
+#define NUM_LEVELS		        4
+
+extern SDL_Surface *screen;
+extern TTF_Font  *font;
+extern SDL_Event  event;
+
+extern SDL_Color black;
+extern SDL_Color gray;
+extern SDL_Color dark_blue;
+extern SDL_Color red;
+extern SDL_Color white;
+extern SDL_Color yellow;
+
+extern SDL_Surface *bkg;
+extern SDL_Surface *letters[255];
+
+extern unsigned char ALPHABET[256];
+extern unsigned char KEYMAP[256];
+extern unsigned char FINGER[256][10];
+extern int ALPHABET_SIZE;
+
+//global vars
+extern int speed_up;
+extern int show_tux4kids;
+extern int debugOn;
+extern int o_lives;
+extern int sound_vol;
+extern int hidden; // Read the README file in the image directory for info on this ;)
+
+/* Alternative language/word/image/sound theming */
+extern unsigned char realPath[2][FNLEN];
+extern char themeName[FNLEN];
+extern int useEnglish;
+
+enum {
+	WIN_WAV,
+	BITE_WAV,
+	LOSE_WAV,
+	RUN_WAV,
+	SPLAT_WAV,
+	WINFINAL_WAV,
+	EXCUSEME_WAV,
+	PAUSE_WAV,
+	NUM_WAVES
+};
+
+extern Mix_Chunk      *sound[NUM_WAVES];
+extern Mix_Music      *music;
+extern int sys_sound;
+
+#define MUSIC_FADE_OUT_MS	80
+
+enum {
+    WIPE_BLINDS_VERT,
+    WIPE_BLINDS_HORIZ,
+    WIPE_BLINDS_BOX,
+    RANDOM_WIPE,
+
+    NUM_WIPES
+};
+// End of code from tuxtype's globals.h
+
+
+/* --- SETUP MENU OPTIONS --- */
+
+#define TITLE_MENU_ITEMS                5
+#define TITLE_MENU_DEPTH                4
+
+#define OPTIONS_SUBMENU                 4
+#define LASER_SUBMENU	        	3
+#define CASCADE_SUBMENU	        	2
+#define ROOTMENU		        1
+
+
+/* --- timings for tux blinking --- */
+#define TUX1                            115
+#define TUX2                            118
+#define TUX3                            121
+#define TUX4                            124
+#define TUX5                            127
+#define TUX6                            130
+
+
+/* Function prototypes for titlescreen.c */
+
+extern void TitleScreen( void );
+extern void switch_screen_mode( void );
+extern int Phrases(char *practice_phrase);
+
+/* in theme.c (from tuxtype): */
+extern void chooseTheme(void);
+extern void setupTheme( char *dirname );
+
+/* in loaders.c (from tuxtype): */
+extern int         checkFile( const char *file );
+extern TTF_Font    *LoadFont( char *fontfile, int fontsize );
+extern void         LoadLang( void );
+extern Mix_Chunk   *LoadSound( char *datafile );
+extern SDL_Surface *LoadImage( char *datafile, int mode );
+extern sprite      *LoadSprite( char *name, int MODE );
+extern sprite      *FlipSprite( sprite *in, int X, int Y );
+extern void         FreeSprite( sprite *gfx );
+extern Mix_Music   *LoadMusic( char *datafile );
+extern SDL_Surface *flip( SDL_Surface *in, int x, int y );
+
+/* in alphabet.c (from tuxtype) */
+extern void LoadKeyboard( void );
+extern void set_letters( unsigned char *t );
+extern unsigned char get_letter( void );
+extern void custom_letter_setup( void );
+extern void show_letters( void );
+extern SDL_Surface* black_outline( unsigned char *t, TTF_Font* font, SDL_Color* c );
+extern void WORDS_init( void );
+extern void WORDS_use_alphabet( void );
+extern void WORDS_use( char *wordFn );
+extern unsigned char* WORDS_get( void );
+
+/* in gettext.c (from tuxtype): */
+extern unsigned char *gettext( unsigned char *in );
+extern int  load_trans( char *file );
+
+/* in pause.c * (from tuxtype): */
+extern int  Pause( void );
+extern void pause_load_media( void );
+extern void pause_unload_media( void );
+extern int  inRect( SDL_Rect r, int x, int y);
+
+#endif //TITLESCREEN_H




More information about the Tux4kids-commits mailing list