[Tux4kids-commits] r226 - in tuxtype/trunk: . tuxtype

dbruce-guest at alioth.debian.org dbruce-guest at alioth.debian.org
Mon Sep 3 23:40:40 UTC 2007


Author: dbruce-guest
Date: 2007-09-03 23:40:40 +0000 (Mon, 03 Sep 2007)
New Revision: 226

Modified:
   tuxtype/trunk/ChangeLog
   tuxtype/trunk/INSTALL
   tuxtype/trunk/README-CROSSBUILD.txt
   tuxtype/trunk/tuxtype/alphabet.c
   tuxtype/trunk/tuxtype/funcs.h
   tuxtype/trunk/tuxtype/globals.h
   tuxtype/trunk/tuxtype/laser.c
   tuxtype/trunk/tuxtype/playgame.c
   tuxtype/trunk/tuxtype/practice.c
   tuxtype/trunk/tuxtype/setup.c
   tuxtype/trunk/tuxtype/theme.c
Log:
Work to keep "practice" activity from crashing in German and other languages.


Modified: tuxtype/trunk/ChangeLog
===================================================================
--- tuxtype/trunk/ChangeLog	2007-09-03 08:08:21 UTC (rev 225)
+++ tuxtype/trunk/ChangeLog	2007-09-03 23:40:40 UTC (rev 226)
@@ -1,4 +1,18 @@
-v 1.5.12
+v 1.5.13
+03 Sep 2007
+[ David Bruce ]
+       - practice.c revised significantly to prevent crashes if
+         keyboard.lst erroneous or incomplete - if entry not found
+         in FINGER[] array for a character, fingering hint not
+         shown but program still functions. "Practice" now uses the
+         same RenderLetters() code as the Cascade and Comet Zap
+         activities.
+       - BlackOutLine() for single letters now uses 
+         TTF_RenderUNICODE_Blended() rather than
+         TTF_RenderGlyph_Blended() because the former version
+         renders all glyphs to a consistent baseline, simplifying
+         our code.
+
 26 Aug 2007
 [ David Bruce ]
        - got rid of autogen.sh - autoreconf is recommended way to

Modified: tuxtype/trunk/INSTALL
===================================================================
--- tuxtype/trunk/INSTALL	2007-09-03 08:08:21 UTC (rev 225)
+++ tuxtype/trunk/INSTALL	2007-09-03 23:40:40 UTC (rev 226)
@@ -21,7 +21,7 @@
 
 if you run into problems rerun:
 
-autoreconf
+autoreconf --install
 
 We want this to work for everybody, everywhere, if it doesn't
 work for you please contact calarndt at tux4kids.org

Modified: tuxtype/trunk/README-CROSSBUILD.txt
===================================================================
--- tuxtype/trunk/README-CROSSBUILD.txt	2007-09-03 08:08:21 UTC (rev 225)
+++ tuxtype/trunk/README-CROSSBUILD.txt	2007-09-03 23:40:40 UTC (rev 226)
@@ -83,7 +83,7 @@
          and "make distclean" to get rid of the autogenerated files.
 
       7. From the trunk dir, run:
-         ./autoreconf
+         ./autoreconf --install
          ./cross-configure.sh --with-sdl-prefix
          ./cross-make.sh
          ./cross-make.sh nsis

Modified: tuxtype/trunk/tuxtype/alphabet.c
===================================================================
--- tuxtype/trunk/tuxtype/alphabet.c	2007-09-03 08:08:21 UTC (rev 225)
+++ tuxtype/trunk/tuxtype/alphabet.c	2007-09-03 23:40:40 UTC (rev 226)
@@ -177,7 +177,10 @@
 }
 
 
-SDL_Surface* BlackOutline(const unsigned char *t, TTF_Font *font, const SDL_Color *c)
+/* NOTE if we can consistently use SDLPango on all platforms, we can simply */
+/* rename the pango version to BlackOutline() and get rid of this one.      */
+/* The input for this function should be UTF-8.                             */
+SDL_Surface* BlackOutline(const unsigned char* t, const TTF_Font* font, const SDL_Color* c)
 {
   SDL_Surface* out = NULL;
   SDL_Surface* black_letters = NULL;
@@ -269,7 +272,7 @@
 
 /* This version basically uses the SDLPango lib instead of */
 /* TTF_RenderUTF*_Blended() to properly render Indic text. */
-SDL_Surface* BlackOutline_SDLPango(const unsigned char *t, TTF_Font *font, const SDL_Color *c)
+SDL_Surface* BlackOutline_SDLPango(const unsigned char* t, const TTF_Font* font, const SDL_Color* c)
 {
   SDL_Surface* out = NULL;
   SDL_Surface* black_letters = NULL;
@@ -355,9 +358,11 @@
 /* End of win32-excluded coded */
 
 
-/* This version takes a single wide character and renders it with the */
-/* Unicode glyph versions of the SDL_ttf functions:                         */
-SDL_Surface* BlackOutline_wchar(wchar_t t, TTF_Font* font, const SDL_Color* c)
+
+
+/* This version takes a wide character string and renders it with the */
+/* Unicode string versions of the SDL_ttf functions:                  */
+SDL_Surface* BlackOutline_Unicode(const Uint16* t, const TTF_Font* font, const SDL_Color* c)
 {
   SDL_Surface* out = NULL;
   SDL_Surface* black_letters = NULL;
@@ -372,11 +377,11 @@
     return NULL;
   }
 
-  black_letters = TTF_RenderGlyph_Blended(font, t, black);
+  black_letters = TTF_RenderUNICODE_Blended(font, t, black);
 
   if (!black_letters)
   {
-    fprintf (stderr, "Warning - BlackOutline_wchar() could not create image for %lc\n", t);
+    fprintf (stderr, "Warning - BlackOutline_wchar() could not create image for %S\n", t);
     return NULL;
   }
 
@@ -402,7 +407,7 @@
   SDL_FreeSurface(black_letters);
 
   /* --- Put the color version of the text on top! --- */
-  white_letters = TTF_RenderGlyph_Blended(font, t, *c);
+  white_letters = TTF_RenderUNICODE_Blended(font, t, *c);
   dstrect.x = 1;
   dstrect.y = 1;
   SDL_BlitSurface(white_letters, NULL, bg, &dstrect);
@@ -712,14 +717,11 @@
 
 
 
-
-/* Now that the words are stored internally as wchars, we use the */
-/* Unicode glyph version of black_outline():                      */
+/* This version creates the letters using TTF_RenderUNICODE_Blended */
 int RenderLetters(const TTF_Font* letter_font)
 {
-  wchar_t t;
-  int i;
-  int maxy;
+  Uint16 t[2];
+  int i, j;  /* i is chars attempted, j is chars actually rendered. */
 
   if (!letter_font)
   {
@@ -727,31 +729,25 @@
     return 0;
   }
 
-  /* The following will supercede the old code: */
   i = num_chars_used = 0;
+  j = 0;
+  t[1] = '\0';
+
   while (char_list[i] != '\0')
   {
-    t = char_list[i];
-
-    if(TTF_GlyphMetrics(letter_font, t, NULL , NULL, NULL,
-                        &maxy, NULL) == -1)
-    {
-      fprintf(stderr, "Could not get glyph metrics for %lc", t);
-      i++;
-      continue;
-    }
-
+    t[0] = char_list[i];
+    
     DEBUGCODE
     {
-      fprintf(stderr, "Creating SDL_Surface for list element %d, char = %lc\n", i, t);
+      fprintf(stderr, "Creating SDL_Surface for list element %d, char = %lc\n", i, *t);
     }
 
-    char_glyphs[i].unicode_value = t;
-    char_glyphs[i].white_glyph = BlackOutline_wchar(t, letter_font, &white);
-    char_glyphs[i].red_glyph = BlackOutline_wchar(t, letter_font, &red);
-    char_glyphs[i].max_y = maxy;
+    char_glyphs[j].unicode_value = t[0];
+    char_glyphs[j].white_glyph = BlackOutline_Unicode(t, letter_font, &white);
+    char_glyphs[j].red_glyph = BlackOutline_Unicode(t, letter_font, &red);
 
     i++;
+    j++;
     num_chars_used++;
   }
   /* Remember how many letters we added: */
@@ -759,6 +755,7 @@
 }
 
 
+
 void FreeLetters(void)
 {
   int i;
@@ -767,6 +764,9 @@
   {
     SDL_FreeSurface(char_glyphs[i].white_glyph);
     SDL_FreeSurface(char_glyphs[i].red_glyph);
+    char_glyphs[i].unicode_value = 0;
+    char_glyphs[i].white_glyph = NULL;
+    char_glyphs[i].red_glyph = NULL;
   } 
   /* List now empty: */
   num_chars_used = 0;
@@ -818,35 +818,8 @@
 }
 
 
-/* Since SDL drawing just uses the upper left corner, but text needs to be drawn relative to */
-/* the glyph origin (i.e. the lower left corner for a character that doesn't go below        */
-/* the baseline), we need to convert them - basically just subtracting the max_y, which is   */
-/* the glyph's height above the baseline.                                                    */
-/*  So - 'x' and 'y' before the function should be the coords where the *origin* is supposed */
-/* to be, and after the function they will contain the correct coords for blitting of the    */
-/* glyph. OK?                                                                                */
-int GetGlyphCoords(wchar_t t, int* x, int* y)
-{
-  int i;
 
-  for (i = 0;
-       char_glyphs[i].unicode_value != t && i <= num_chars_used;
-       i++)
-  {}
 
-  if (i > num_chars_used)
-  {
-    /* Didn't find character: */
-    fprintf(stderr, "Could not find glyph for unicode character %lc\n", t);
-    return 0;
-  }
-  
-  /* Set "upper left" coordinates for blitting (currently, don't need to */
-  /* do anything to x):                                                  */
-  *y -= char_glyphs[i].max_y;
-  return 1;
-}
-
 /****************************************************/
 /*                                                  */
 /*       Local ("private") functions:               */
@@ -884,6 +857,43 @@
 
 
 
+void ResetCharList(void)
+{
+  char_list[0] = '\0';
+}
+
+
+
+/* Creates a list of distinct Unicode characters in       */
+/* the argument string for subsequent rendering.          */
+/* Like gen_char_list() but takes a string argument       */
+/* instead of going through the currently selected        */
+/* word list. Argument should be UTF-8                    */
+/* Can be called multiple times on different strings      */
+/* to accumulate entire repertoire - call ResetCharList() */
+/* to start over                                          */
+void GenCharListFromString(const char* UTF8_str)
+{
+  int i = 0;
+  wchar_t wchar_buf[MAX_UNICODES];
+
+  convert_from_UTF8(wchar_buf, UTF8_str);
+
+  /* FNLEN is max length of phrase (I think) */
+  while (wchar_buf[i] != '\0' && i < FNLEN) 
+  {
+    add_char(wchar_buf[i]);
+    i++;
+  }
+
+  DEBUGCODE
+  {
+    fprintf(stderr, "char_list = %S\n", char_list);
+  }
+}
+
+
+
 /* FIXME this function is currently dead code */
 /* --- setup the alphabet --- */
 static void set_letters(unsigned char *t) {
@@ -905,7 +915,7 @@
 /* Checks to see if the argument is already in the list and adds    */
 /* it if necessary.  Returns 1 if char added, 0 if already in list, */
 /* -1 if list already up to maximum size:                           */
-
+/* FIXME performance would be better with hashtable                 */
 static int add_char(wchar_t uc)
 {
   int i = 0;

Modified: tuxtype/trunk/tuxtype/funcs.h
===================================================================
--- tuxtype/trunk/tuxtype/funcs.h	2007-09-03 08:08:21 UTC (rev 225)
+++ tuxtype/trunk/tuxtype/funcs.h	2007-09-03 23:40:40 UTC (rev 226)
@@ -21,23 +21,26 @@
 
 
 /* In alphabet.c */
-SDL_Surface* BlackOutline(const unsigned char *t, TTF_Font* font, const SDL_Color* c);
-SDL_Surface* BlackOutline_wchar(wchar_t t, TTF_Font* font, const SDL_Color* c);
+SDL_Surface* BlackOutline(const unsigned char *t, const TTF_Font* font, const SDL_Color* c);
+SDL_Surface* BlackOutline_Unicode(const Uint16* t, const TTF_Font* font, const SDL_Color* c);
 
 #ifndef WIN32
-SDL_Surface* BlackOutline_SDLPango(const unsigned char *t, TTF_Font* font, const SDL_Color* c);
+SDL_Surface* BlackOutline_SDLPango(const unsigned char* t, const TTF_Font* font, const SDL_Color* c);
 #endif
 
+/* (still in alphabet.c:) */
 void ClearWordList(void);
 void FreeLetters(void);
 void GenerateWordList(const char* wordFn);
+void GenCharListFromString(const char* UTF8_str);
+void ResetCharList(void);
 wchar_t GetLetter(void);
 wchar_t* GetWord(void);
 SDL_Surface* GetWhiteGlyph(wchar_t t);
 SDL_Surface* GetRedGlyph(wchar_t t);
-int GetGlyphCoords(wchar_t t, int* x, int* y);
 int LoadKeyboard(void);
 int RenderLetters(const TTF_Font* letter_font);
+
 void UseAlphabet(void);
 
 

Modified: tuxtype/trunk/tuxtype/globals.h
===================================================================
--- tuxtype/trunk/tuxtype/globals.h	2007-09-03 08:08:21 UTC (rev 225)
+++ tuxtype/trunk/tuxtype/globals.h	2007-09-03 23:40:40 UTC (rev 226)
@@ -241,5 +241,4 @@
   wchar_t unicode_value;
   SDL_Surface* white_glyph;
   SDL_Surface* red_glyph;
-  int max_y;
 } uni_glyph;

Modified: tuxtype/trunk/tuxtype/laser.c
===================================================================
--- tuxtype/trunk/tuxtype/laser.c	2007-09-03 08:08:21 UTC (rev 225)
+++ tuxtype/trunk/tuxtype/laser.c	2007-09-03 23:40:40 UTC (rev 226)
@@ -872,17 +872,17 @@
 
 static void laser_draw_let(wchar_t c, int x, int y)
 {
-  int top_x, top_y;
+  /* Draw letter in correct place relative to comet: */
+  const int offset_x = -10; /* Values determined by trial and error: */
+  const int offset_y = -50;
+
   SDL_Rect dst;
-  /* Start with coords for where we want glyph origin to go: */
-  top_x = x - (GetWhiteGlyph(c)->w/2);
-  top_y = y - 10;
-  /* Correct for varying height of glyphs: */
-  GetGlyphCoords(c, &top_x, &top_y);
-  /* Plug into the SDL_Rect and blit: */
-  dst.x = top_x;
-  dst.y = top_y;
-  SDL_BlitSurface(GetWhiteGlyph(c), NULL, screen, &dst); 
+  SDL_Surface* s;
+  dst.x = x + offset_x;
+  dst.y = y + offset_y;
+  s = GetWhiteGlyph(c);
+  if (s)
+    SDL_BlitSurface(s, NULL, screen, &dst); 
 }
 
 

Modified: tuxtype/trunk/tuxtype/playgame.c
===================================================================
--- tuxtype/trunk/tuxtype/playgame.c	2007-09-03 08:08:21 UTC (rev 225)
+++ tuxtype/trunk/tuxtype/playgame.c	2007-09-03 23:40:40 UTC (rev 226)
@@ -137,9 +137,7 @@
 	LoadTuxAnims(); 
 	LoadFishies();
 	LoadOthers();
-printf("before RenderLetters\n");
 	RenderLetters(font);
-printf("after RenderLetters\n");
 
 	LOG( " starting game \n ");
 	while (still_playing) {
@@ -1385,10 +1383,10 @@
 	int j = 0;
 	int red_letters = 0;
 	int current_letter;
-	/* 'x_origin' and 'y_origin' are where the glyph origin should be          */
-	/* located relative to the fishy graphic (lower left corner of most chars) */
-	const int x_origin = 10;
-        const int y_origin = 30;
+	/* 'x_inset' and 'y_inset' are where the glyph to be drawn relative        */
+	/* the fishy graphic:                                                      */
+	const int x_inset = 10;
+        const int y_inset = 10;
 	/* letter_x and letter_y are where the upper left corner of the glyph needs */
         /* to be located - (e.g. how SDL blitting understands locations)           */
         int letter_x = 0;
@@ -1449,14 +1447,11 @@
                   else
                     letter_surface = GetWhiteGlyph(current_letter);
 
-		  /* Set "letter_x" and "letter_y to where we want the *origin* drawn: */
-		  letter_x = fish_object[which].x + (j * fishy->frame[0]->w) + x_origin;
-		  letter_y = fish_object[which].y + y_origin;
-		  /* Now get correct upper-left coords for this particular glyph: */
-		  GetGlyphCoords(current_letter, &letter_x, &letter_y);
+		  /* Set "letter_x" and "letter_y to where we want the letter drawn: */
+		  letter_x = fish_object[which].x + (j * fishy->frame[0]->w) + x_inset;
+		  letter_y = fish_object[which].y + y_inset;
 
 		  DrawObject(letter_surface, letter_x, letter_y);
-
 		}
 	}
 /*        LOG ("Leaving DrawFish()\n");*/

Modified: tuxtype/trunk/tuxtype/practice.c
===================================================================
--- tuxtype/trunk/tuxtype/practice.c	2007-09-03 08:08:21 UTC (rev 225)
+++ tuxtype/trunk/tuxtype/practice.c	2007-09-03 23:40:40 UTC (rev 226)
@@ -30,7 +30,7 @@
 
 /*local function prototypes: */
 static int get_phrase(const char* phr);
-static void practice_load_media(void);
+static int practice_load_media(void);
 static void practice_unload_media(void);
 static void print_at(const char* pphrase, int wrap, int x, int y);
 static void show(unsigned char t);
@@ -43,136 +43,238 @@
 /************************************************************************/
 
 
+/* FIXME this is not UTF-8/Unicode compatible */
+int Phrases(char* pphrase )
+{
 
-int Phrases(char* pphrase ) {
+  /* TODO 
+  * 
+  * 
+  * 
+  */
 
-	/* TODO 
-	 * 
-	 * 
-	 * 
-	 */
+  Uint32 start = 0, a = 0;
+  int quit = 0,
+      i = 0,
+      c = 0,
+      wp = 0,
+      z = 0,
+      total = 0,
+      state = 0;
+  int key[100] = {0};
+  SDL_Rect dst, dst2, dst3, dst4, dst5;
+  char keytime[FNLEN],
+       totaltime[FNLEN];
+  SDL_Surface* srfc = NULL;
 
-	Uint32 start=0,a=0;
-	int 	quit=0,
-		i=0,
-		c=0,
-		wp=0,
-		z=0,
-		total=0,
-		state=0;
-	int key[100];
-	SDL_Rect dst, dst2, dst3, dst4,dst5;
-	char keytime[FNLEN],
-	     totaltime[FNLEN];
 
-	practice_load_media();
-	SDL_BlitSurface(bg, NULL, screen, NULL);
-	SDL_BlitSurface(hands, NULL, screen, &hand_loc);
-	SDL_Flip(screen);
+  
+  if (!practice_load_media())
+  {
+    fprintf(stderr, "Phrases() - practice_load_media() failed, returning.\n");
+    return 0;
+  }
 
-	wp = get_phrase(pphrase);
-	if (!strncmp(phrase[0], "", 1))
-		strncpy(pphrase, phrase[0], 80);
+  SDL_BlitSurface(bg, NULL, screen, NULL);
+  SDL_BlitSurface(hands, NULL, screen, &hand_loc);
+  SDL_Flip(screen);
 
- 	dst.x = 320 - (letters[65]->w/2);	dst.y = 100;	dst.w = letters[65]->w;	dst.h = letters[65]->h;
- 	dst2.x = 50;				dst2.y = 400;	dst2.w = letters[65]->w;	dst2.h = letters[65]->h;
- 	dst3.x = 50;				dst3.y = 400;	dst3.w = 160;			dst3.h = 50;
- 	dst4.x = 480;				dst4.y = 400;	dst4.w = 240;			dst4.h = 50;
- 	dst5.x = 480;				dst5.y = 400;	dst5.w = 240;			dst5.h = 50;
-	dst.x = 40;
+  wp = get_phrase(pphrase);
 
-	start = SDL_GetTicks();
+  if (!strncmp(phrase[0], "", 1))
+    strncpy(pphrase, phrase[0], 80);
 
-	do {
-		switch (state) {
-		case 0:
-			start = SDL_GetTicks();
-			SDL_BlitSurface(hands, NULL, screen, &hand_loc);
-			state = 1;
-			break;
-		case 1:
-			if (SDL_GetTicks() - start > 500) {
-				for (i=0; i<10; i++)
-					if (FINGER[(int)pphrase[c]][i]){
-						SDL_BlitSurface(hand[i], NULL, screen, &hand_loc);
-					}
-				state = 2;
-			}
-			break;
-		case 2:
-			if (state == 2 && SDL_GetTicks() - start > 750) {
-				state = 3;
-			}
-			break;
-		case 3:
-			SDL_BlitSurface(hands, NULL, screen, &hand_loc);
-			state = 12;
-			break;  
-		case 4:
-			for (i=0; i<10; i++)
-				if (FINGER[(int)pphrase[c]][i])
-					SDL_BlitSurface(hand[i], NULL, screen, &hand_loc);
-			state = 11;
-			break;
-		default:
-			state -= 2; // this is to make the flashing slower
-		}
+  if (!letters[65])
+  {
+    fprintf(stderr, "Phrases() - letters[65] not defined - bailing out.\n");
+    return 0;
+  }
 
-		while  (SDL_PollEvent(&event)) {
-				if (event.type == SDL_KEYDOWN) {
-					a=SDL_GetTicks();
-					key[c]=a-start;
-					total += key[c];
-					sprintf(keytime, "%.2f", (float) key[c] / 1000);
-					sprintf(totaltime, "%.2f", (float) total / 1000);
-					start = a;
-					if (event.key.keysym.sym == SDLK_ESCAPE)
-						quit=1;
-					if (event.key.keysym.sym == SDLK_DOWN) {
-						//practice next phase in list
-						//a=a;
-					} else {
-						if (ALPHABET[event.key.keysym.unicode] && pphrase[c]==(char)event.key.keysym.unicode){
-						state=0;
-						dst2.x=40;
-						dst4.x=480;
-						SDL_BlitSurface(bg, &dst3, screen, &dst2);
-						SDL_BlitSurface(bg, &dst5, screen, &dst4);
-						SDL_Flip(screen);
-						SDL_BlitSurface(letters[event.key.keysym.unicode], NULL, screen, &dst);
-						for (z=0;z<strlen(keytime);z++){
- 							SDL_BlitSurface(letters[(int)keytime[z]], NULL, screen, &dst2);
-							dst2.x = dst2.x + letters[(int)keytime[z]]->w-2;
-						}
-						for (z=0;z<strlen(totaltime);z++){
-							SDL_BlitSurface(letters[(int)totaltime[z]], NULL, screen, &dst4);
-							dst4.x = dst4.x + letters[(int)totaltime[z]]->w-2;
-						}
-						dst.x = (dst.x + letters[event.key.keysym.unicode]->w) - 5;
-						if (c==(strlen(pphrase)-1)){
-							print_at("Great!",6 ,275 ,200);
-							SDL_Flip(screen);
-							SDL_Delay(2500);
-							quit=1;
-						}
-						if (c==wp){
-						c++;
-						dst.x=40;
-						dst.y=142;
-						}
-						c++;
-						} else {
-							if ( event.key.keysym.sym != SDLK_RSHIFT && event.key.keysym.sym != SDLK_LSHIFT )
-								PlaySound(wrong);
-						}
-					}
-				}
-		}
-	SDL_Flip(screen);
-	SDL_Delay(30);
-	}while (!quit);
-	practice_unload_media();
-	return 1;
+  dst.x = 320 - (letters[65]->w/2);
+  dst.y = 100;
+  dst.w = letters[65]->w;
+  dst.h = letters[65]->h;
+
+  dst2.x = 50;
+  dst2.y = 400;
+  dst2.w = letters[65]->w;
+  dst2.h = letters[65]->h;
+
+  dst3.x = 50;
+  dst3.y = 400;
+  dst3.w = 160;
+  dst3.h = 50;
+
+  dst4.x = 480;
+  dst4.y = 400;
+  dst4.w = 240;
+  dst4.h = 50;
+
+  dst5.x = 480;
+  dst5.y = 400;
+  dst5.w = 240;
+  dst5.h = 50;
+
+  dst.x = 40;
+
+  start = SDL_GetTicks();
+
+  do
+  {
+    switch (state)
+    {
+      case 0:
+        start = SDL_GetTicks();
+        SDL_BlitSurface(hands, NULL, screen, &hand_loc);
+        state = 1;
+        break;
+
+      case 1:
+        if (SDL_GetTicks() - start > 500)
+        {
+          for (i = 0; i < 10; i++)
+          { 
+            if (((int)pphrase[c] >= 0) /* Prevent bounds violation */
+              &&((int)pphrase[c] < 256) 
+              && FINGER[(int)pphrase[c]][i])
+            {
+              SDL_BlitSurface(hand[i], NULL, screen, &hand_loc);
+            }
+          }
+          state = 2;
+        }
+        break;
+
+      case 2:
+        if (state == 2 && SDL_GetTicks() - start > 750)
+        {
+          state = 3;
+        }
+        break;
+
+      case 3:
+       SDL_BlitSurface(hands, NULL, screen, &hand_loc);
+       state = 12;
+       break;  
+
+      case 4:
+        for (i = 0; i < 10; i++)
+        {
+          if (((int)pphrase[c] >= 0) /* Prevent bounds violation */
+            &&((int)pphrase[c] < 256) /* This can't actually occur for type char */
+            && FINGER[(int)pphrase[c]][i])
+          {
+            SDL_BlitSurface(hand[i], NULL, screen, &hand_loc);
+          }
+        }
+        state = 11;
+        break;
+
+      default:
+      state -= 2; // this is to make the flashing slower
+    }
+
+
+    while  (SDL_PollEvent(&event))
+    {
+      if (event.type == SDL_KEYDOWN)
+      {
+        a = SDL_GetTicks();
+        key[c] = a - start;
+        total += key[c];
+        sprintf(keytime, "%.2f", (float) key[c] / 1000);
+        sprintf(totaltime, "%.2f", (float) total / 1000);
+        start = a;
+
+        if (event.key.keysym.sym == SDLK_ESCAPE)
+          quit = 1;
+
+        if (event.key.keysym.sym == SDLK_DOWN) 
+        {
+          //practice next phase in list
+          //a=a;
+        }
+        else
+        {
+          /* Keep from segfaulting on unicode chars beyond 255 */
+          /* until practice mode is fixed:                     */
+          if (event.key.keysym.unicode > 255)
+          {
+            fprintf(stderr, "Practice mode cannot handle this unicode char\n");
+            continue;
+          }
+
+          if (pphrase[c]==(char)event.key.keysym.unicode)
+          {
+            state = 0;
+            dst2.x = 40;
+            dst4.x = 480;
+            SDL_BlitSurface(bg, &dst3, screen, &dst2);
+            SDL_BlitSurface(bg, &dst5, screen, &dst4);
+            SDL_Flip(screen);
+
+            srfc = GetWhiteGlyph(event.key.keysym.unicode);
+            if (srfc)
+            { 
+              SDL_BlitSurface(srfc, NULL, screen, &dst);
+              dst.x = (dst.x + srfc->w) - 5;
+            }
+ 
+            for (z = 0; z < strlen(keytime); z++)
+            {
+              srfc = GetWhiteGlyph((int)keytime[z]);
+              if (srfc)
+              {
+                SDL_BlitSurface(srfc, NULL, screen, &dst2);
+                dst2.x = dst2.x + srfc->w - 2;
+              }
+            }
+
+            for (z = 0;z < strlen(totaltime); z++)
+            {
+              srfc = GetWhiteGlyph((int)totaltime[z]);
+              if (srfc)
+              {
+                SDL_BlitSurface(srfc, NULL, screen, &dst4);
+                dst4.x = dst4.x + srfc->w - 2;
+              }
+            }
+
+
+            if (c == (strlen(pphrase) - 1))
+            {
+              print_at("Great!",6 ,275 ,200);
+              SDL_Flip(screen);
+              SDL_Delay(2500);
+              quit = 1;
+            }
+
+            if (c == wp)
+            {
+              c++;
+              dst.x = 40;
+              dst.y = 142;
+            }
+
+            c++;
+          }
+          else
+          {
+            if (event.key.keysym.sym != SDLK_RSHIFT
+             && event.key.keysym.sym != SDLK_LSHIFT)
+             PlaySound(wrong);
+          }
+        }
+      }
+    }
+    SDL_Flip(screen);
+    SDL_Delay(30);
+
+  }while (!quit);
+
+  practice_unload_media();
+
+  return 1;
 }
 
 
@@ -185,41 +287,64 @@
 
 
 /* FIXME use RenderLetters(), etc */
-static void practice_load_media(void)
+static int practice_load_media(void)
 {
-	int i;	
-	unsigned char fn[FNLEN];
-	unsigned char let[5];
+  int i;	
+  unsigned char fn[FNLEN];
+  unsigned char let[5];
+  int load_failed = 0;
 
-	LOG("Loading practice media\n");
-	for (i=0; i<10; i++) {
-		sprintf(fn, "hands/%d.png", i);
-		hand[i] = LoadImage(fn, IMG_ALPHA);
-	}
-	hands = LoadImage("hands/hands.png", IMG_ALPHA);
+  LOG("Loading practice media\n");
 
-	hand_loc.x = (screen->w/2) - (hand[0]->w/2);
-	hand_loc.y = screen->h - (hand[0]->h);
-	hand_loc.w = (hand[0]->w);
-	hand_loc.h = (hand[0]->h);
 
-	bg = LoadImage("main_bkg.png", IMG_ALPHA);
+  hands = LoadImage("hands/hands.png", IMG_ALPHA);
+  bg = LoadImage("main_bkg.png", IMG_ALPHA);
+  wrong = LoadSound("tock.wav");
 
-	font = LoadFont(settings.theme_font_name, 32 );
+  for (i = 0; i < 10; i++)
+  {
+    sprintf(fn, "hands/%d.png", i);
+    hand[i] = LoadImage(fn, IMG_ALPHA);
+    if (!hand[i])
+      load_failed = 1;
+  }
 
-	wrong = LoadSound("tock.wav");
+  /* Get out if anything failed to load: */
+  if (load_failed
+    ||!hands
+    ||!bg
+    ||!wrong)
+  {
+    fprintf(stderr, "practice_load_media() - failed to load needed media \n");
+    practice_unload_media;
+    return 0;
+  }
 
-	let[1]=0;
-	for (i=1; i<255; i++)
-		if (ALPHABET[i]) {
-			let[0]=i;
-			letters[i] = BlackOutline(let, font, &white); 
-		}
+  /* Should be safe from here on out: */
 
-	TTF_CloseFont(font);
-        font = NULL;
+  hand_loc.x = (screen->w/2) - (hand[0]->w/2);
+  hand_loc.y = screen->h - (hand[0]->h);
+  hand_loc.w = (hand[0]->w);
+  hand_loc.h = (hand[0]->h);
 
-	LOG("DONE - Loading practice media\n");
+  /* Now render letters for glyphs in alphabet: */
+  font = LoadFont(settings.theme_font_name, 32 );
+
+  /* FIXME below problem with i18n: */
+  let[1]=0;
+  for (i=1; i<255; i++)
+    /* until we fix or get rid of ALPHABET[], just render the whole range: */
+    if (ALPHABET[i])
+    {
+      let[0] = i;
+      letters[i] = BlackOutline(let, font, &white); 
+    }
+
+  TTF_CloseFont(font);
+  font = NULL;
+
+  LOG("DONE - Loading practice media\n");
+  return 1;
 }
 
 
@@ -238,7 +363,7 @@
           SDL_FreeSurface(hand[i]);
           hand[i] = NULL;
         }
-	for (i=1; i<255; i++) 
+	for (i = 1; i < 255; i++) 
 		if (ALPHABET[i])
                 { 
 		  SDL_FreeSurface(letters[i]);
@@ -249,124 +374,233 @@
 }
 
 
-
+/* looks like dead code: */
 static void show(unsigned char t)
 {
 	SDL_Rect dst;
-	dst.x = 320 - (letters[(int)t]->w/2);
+        SDL_Surface* s = NULL;
+
+        s= GetWhiteGlyph((int)t);
+        if (!s)
+          return; 
+	dst.x = 320 - (s->w/2);
 	dst.y = 100;
-	dst.w = letters[(int)t]->w;
-	dst.h = letters[(int)t]->h;
-	SDL_BlitSurface(letters[(int)t], NULL, screen, &dst);
+	dst.w = s->w;
+	dst.h = s->h;
+	SDL_BlitSurface(s, NULL, screen, &dst);
 }
 
 
 
 static int get_phrase(const char* phr)
 {
-	int pc=0,
-	    pw[256] = { 0 },
-	    wp=0,
-	    i=0,
-	    c=0,
-	    z=0;
-	char fn[FNLEN];
+  int pc = 0;  // 'phrase count' (?)
+  int pw[256] = { 0 };
+  int wp = 0, i = 0, c = 0, z = 0;
+  char fn[FNLEN];
 
-	/* If we didn't receive a phrase get the first one from the file...*/
-	
-	if (strncmp("", phr, 40)==0){
-	FILE *pf;
-	/* set the phrases directory/file */
-	#ifdef WIN32
-		snprintf( fn, FNLEN-1, "userdata/phrases.txt" );
-	#else
-		snprintf( fn, FNLEN-1, (const char*)"%s/.tuxtype/phrases.txt", getenv("HOME") );
-	#endif
+  /* If we didn't receive a phrase get the first one from the file...*/
+  if (strncmp("", phr, 40) == 0)
+  {
+    FILE* pf; /*   "phrase file"   */
+    /* set the phrases directory/file */
+    /* FIXME I think the phrases should be under data or the theme */
+#ifdef WIN32
+    snprintf(fn, FNLEN - 1, "userdata/phrases.txt");
+#else
+    snprintf(fn, FNLEN - 1, (const char*)"%s/.tuxtype/phrases.txt", getenv("HOME"));
+#endif
 
-	DEBUGCODE { printf("get_phrases(): phrases file is '%s'\n", fn ); }
-	LOG("get_phrases(): trying to open phrases file\n");
-	pf = fopen( fn, "r" );
-	if (pf == NULL) 
-		return(wp);
-	while (!feof(pf)) {
-		fscanf( pf, "%[^\n]\n", phrase[pc] );
-		pc++;
-		DEBUGCODE { printf( "%s", phrase[pc] ); }
-	}
-	fclose( pf );
-	pc--;
-	} else {
-		pc=1;
-		strncpy(phrase[0], phr, 80);
-	}
+    DEBUGCODE { printf("get_phrases(): phrases file is '%s'\n", fn ); }
+    LOG("get_phrases(): trying to open phrases file\n");
+    pf = fopen( fn, "r" );
+    if (pf == NULL) 
+      return(wp);  /* why not just 'return 0;' ??? */
 
-	//Calculate and record pixel width of phrases
- 		for (c=0;c<=pc;c++){
- 			for(i=0; i<strlen(phrase[c]); i++){
-				if (letters[(int)phrase[c][i]] == NULL)
-					printf("no letter defined in keyboard.lst\n");
-				else
- 					pw[c]+= letters[(int)phrase[c][i]]->w-5;
- 			}
- 		}
+    /* So now copy each line into phrases array: */
+    while (!feof(pf) && pc < 256) 
+    {
+      fscanf( pf, "%[^\n]\n", phrase[pc] );
+      pc++;
+      DEBUGCODE {printf("%s", phrase[pc]);}
+    }
+    if (pc == 256)
+      LOG("File contains more than max allowed phrases - stopping\n");
 
-	//Find wrapping point
-	for ( c=0; c<=pc; c++ ){
-			if (pw[c]<598){
-				if ( c==0 ){
-					wp=strlen(phrase[c]);
-					print_at( phrase[0], wp, 40, 10 );
-				}
-			}else{
-				z=0;
-				wp=0;
-				for (i=0;i<strlen(phrase[c]);i++){
-					z += letters[(int)phrase[c][i]]->w-5;
-					if (wp == 0 && z > 598){
-					wp = i-1;
-					break;
-					}
-				}
-				for (i=wp;i>=0;i--){
-					if ( strncmp( " ", &phrase[c][i], 1 ) == 0 ){
-					wp=i-1;
-					break;
-					}
-				}
-				if ( c==0 ){
-				print_at( phrase[0], wp, 40, 10 );
-				}
-			}
-	}
-	return(wp);
+    fclose(pf);
+    pc--;
+  } 
+  else
+  {
+    pc = 1;
+    strncpy(phrase[0], phr, 80);
+  }
+
+
+  /* Need to generate glyphs for all the needed Unicode chars: */
+
+  ResetCharList();
+  /* 'A' (i.e. 65) always has to go into list because width used for layout */
+  /* HACK also need chars for "Great!" because of congrats message - this   */
+  /* obviously is not a general solution. Numerals also needed for timers.  */
+  {
+    char* let = "AGreat!0123456789.";
+    GenCharListFromString(let);
+  }
+
+
+  /* Scan through all the phrases and put needed chars into list: */
+  for (c = 0; c <= pc; c++)
+    GenCharListFromString(phrase[c]);
+
+  /* Now render letters for glyphs in list: */
+  font = LoadFont(settings.theme_font_name, 32 );
+  if (!font)
+  {
+    fprintf(stderr, "get_phrase() - could not load font\n");
+    return 0;
+  }
+
+  RenderLetters(font);
+
+  TTF_CloseFont(font);
+  font = NULL;
+
+
+  //Calculate and record pixel width of phrases
+  {
+    SDL_Surface* let = NULL;
+    for (c = 0; c <= pc; c++)
+    {
+      for(i = 0; i < strlen(phrase[c]); i++)
+      {
+        let = GetWhiteGlyph((int)phrase[c][i]);
+        if (let)  
+          pw[c]+= let->w - 5;
+        else
+        {
+          fprintf(stderr, "get_phrase() - needed glyph not in letters[]\n");
+          return;
+        }
+      }
+    }
+  }
+
+  //Find wrapping point
+  for (c = 0; c <= pc; c++)
+  {
+    if (pw[c] < 598)  // If the phrase is less than 598 pixels wide
+    {
+      if (c == 0)
+      {
+        wp = strlen(phrase[c]);
+        print_at(phrase[0], wp, 40, 10);
+      }
+    }
+    else
+    {
+      z = 0;
+      wp = 0;
+
+      for (i = 0; i < strlen(phrase[c]); i++)
+      {
+        /* Should be safe (if no glyph, will have returned above) */
+        z += GetWhiteGlyph((int)phrase[c][i])->w-5;
+        if (wp == 0 && z > 598)
+        {
+          wp = i - 1;
+          break;
+        }
+      }
+
+      for (i = wp; i >= 0; i--)
+      {
+        if (strncmp(" ", &phrase[c][i], 1) == 0)
+        {
+          wp = i-1;
+          break;
+        }
+      }
+
+      if (c == 0)
+      {
+        print_at(phrase[0], wp, 40, 10);
+      }
+    }
+  }
+  LOG("Leaving get_phrase()\n");
+  return(wp);
 }
 
 
 
 static void print_at(const char *pphrase, int wrap, int x, int y)
 {
-	int z=0;
-	letter_loc.x = x;
-	letter_loc.y = y;
-	letter_loc.w = letters[65]->w;
-	letter_loc.h = letters[65]->h;
-	if ( wrap == strlen(pphrase) ){
-		for (z=0;z<strlen(pphrase);z++){
-			SDL_BlitSurface(letters[(int)pphrase[z]], NULL, screen, &letter_loc);
-			letter_loc.x = (letter_loc.x + letters[(int)pphrase[z]]->w)-5;
-		}
-	}else{
-		for (z=0;z<=wrap;z++){
-			SDL_BlitSurface(letters[(int)pphrase[z]], NULL, screen, &letter_loc);
-			letter_loc.x = (letter_loc.x + letters[(int)pphrase[z]]->w)-5;
-		}
-		letter_loc.x = 40;
-                // - (letter_loc.h/4) to account for free space at top and bottom of rendered letters
-		letter_loc.y = letter_loc.y + letter_loc.h - (letter_loc.h/4);
-		for (z=wrap+2;z<strlen(pphrase);z++){
-			SDL_BlitSurface(letters[(int)pphrase[z]], NULL, screen, &letter_loc);
-			letter_loc.x = (letter_loc.x + letters[(int)pphrase[z]]->w)-5;
-		}
-	}
+  int z = 0;
+  SDL_Surface* surf = NULL;
+  letter_loc.x = x;
+  letter_loc.y = y;
+  letter_loc.w = GetWhiteGlyph(65)->w;
+  letter_loc.h = GetWhiteGlyph(65)->h;
+
+  LOG("Entering print_at()\n");
+
+  if (wrap >= strlen(pphrase)) // I think this means it fits on a single line
+  {
+    for (z = 0; z <strlen(pphrase); z++)
+    {
+      surf = GetWhiteGlyph((wchar_t)pphrase[z]);
+      if (surf)
+      {
+        DEBUGCODE{printf("surf not NULL for %c\n", pphrase[z]);}
+        SDL_BlitSurface(surf, NULL, screen, &letter_loc);
+        letter_loc.x = (letter_loc.x + surf->w) - 5;
+      }
+      else
+      {
+        fprintf(stderr, "print_at(): needed glyph for %c not found\n",
+                pphrase[z]);
+      }
+    }
+  }
+  else  /* Another line required - code only seems to support 1 or 2 lines! */
+  {
+    for (z = 0; z <= wrap; z++) 
+    {
+      surf = GetWhiteGlyph((wchar_t)pphrase[z]);
+      if (surf)
+      {
+        DEBUGCODE{printf("surf not NULL for %c\n", pphrase[z]);}
+        SDL_BlitSurface(surf, NULL, screen, &letter_loc);
+        letter_loc.x = (letter_loc.x + surf->w) - 5;      }
+      else
+      {
+        fprintf(stderr, "print_at(): needed glyph for %c not found\n",
+                pphrase[z]);
+      }
+    }
+
+    /* Move 'cursor' back to left and down one line: */
+    letter_loc.x = 40;
+    // - (letter_loc.h/4) to account for free space at top and bottom of rendered letters
+    letter_loc.y = letter_loc.y + letter_loc.h - (letter_loc.h/4);
+
+    for (z = wrap + 2; z <strlen(pphrase); z++)
+    {
+      surf = GetWhiteGlyph((wchar_t)pphrase[z]);
+      if (surf)
+      {
+        DEBUGCODE{printf("surf not NULL for %c\n", pphrase[z]);}
+        SDL_BlitSurface(surf, NULL, screen, &letter_loc);
+        letter_loc.x = (letter_loc.x + surf->w) - 5;
+      }
+      else
+      {
+        fprintf(stderr, "print_at(): needed glyph for %c not found",
+                pphrase[z]);
+      }
+    }
+  }
+  LOG("Leaving print_at()\n");
 }
 

Modified: tuxtype/trunk/tuxtype/setup.c
===================================================================
--- tuxtype/trunk/tuxtype/setup.c	2007-09-03 08:08:21 UTC (rev 225)
+++ tuxtype/trunk/tuxtype/setup.c	2007-09-03 23:40:40 UTC (rev 226)
@@ -93,6 +93,7 @@
 	LOG( "LibInit():\n-About to init SDL Library\n" );
 
 	if (SDL_Init(lib_flags) < 0) 
+		/* FIXME this looks wrong - if no sys_sound, we don't init video??? */
 		if (settings.sys_sound) {
 			if (SDL_Init(SDL_INIT_VIDEO) < 0) {
 				fprintf(stderr, "Couldn't initialize SDL: %s\n",
@@ -109,11 +110,17 @@
 
 	LOG( "-SDL Library init'd successfully\n" );
 
-	if (settings.sys_sound) 
-		if (Mix_OpenAudio( 22050, AUDIO_S16, 1, 2048) < 0) {
-			fprintf( stderr, "Warning: couldn't set 22050 Hz 8-bit audio\n - Reasons: %s\n", SDL_GetError());
-			settings.sys_sound=0;
-		}
+	/* FIXME should read settings before we do this: */ 
+	if (settings.sys_sound)
+        { 
+          if (Mix_OpenAudio(22050, AUDIO_S16, 1, 2048) == -1)
+          {
+            fprintf( stderr, "Warning: couldn't set 22050 Hz 8-bit audio\n - Reasons: %s\n", SDL_GetError());
+            settings.sys_sound=0;
+          }
+          else
+            LOG("Mix_OpenAudio() successful\n");
+        }
 
 	LOG( "-about to init SDL_ttf\n" );
 

Modified: tuxtype/trunk/tuxtype/theme.c
===================================================================
--- tuxtype/trunk/tuxtype/theme.c	2007-09-03 08:08:21 UTC (rev 225)
+++ tuxtype/trunk/tuxtype/theme.c	2007-09-03 23:40:40 UTC (rev 226)
@@ -22,7 +22,7 @@
 
 SDL_Surface* letters[255] = {NULL}; //get rid of this
 wchar_t ALPHABET[256];
-unsigned char FINGER[256][10];
+unsigned char FINGER[256][10] = {0};
 int ALPHABET_SIZE;
 
 




More information about the Tux4kids-commits mailing list