[Tux4kids-commits] r351 - in tuxmath/trunk: doc src

tholy-guest at alioth.debian.org tholy-guest at alioth.debian.org
Sun Dec 2 07:34:36 UTC 2007


Author: tholy-guest
Date: 2007-12-02 07:34:35 +0000 (Sun, 02 Dec 2007)
New Revision: 351

Modified:
   tuxmath/trunk/doc/README.txt
   tuxmath/trunk/doc/changelog
   tuxmath/trunk/src/fileops.c
   tuxmath/trunk/src/titlescreen.c
   tuxmath/trunk/src/titlescreen.h
Log:
Improve the user login to make the facility more robust (if slightly more annoying to set up, for now).


Modified: tuxmath/trunk/doc/README.txt
===================================================================
--- tuxmath/trunk/doc/README.txt	2007-12-01 01:35:31 UTC (rev 350)
+++ tuxmath/trunk/doc/README.txt	2007-12-02 07:34:35 UTC (rev 351)
@@ -377,20 +377,36 @@
         (let's say it's "/servervolume/"), create a directory which
         we'll call "tuxmath_users" for current purposes.
 
-     2. Create subdirectories of "tuxmath_users." The basic idea is
-        that you'll create a directory tree that mirrors how you want
-        students to select themselves.  For example, a large school
-        with many classrooms might create directories called
-        "Kindergarten," "1st grade," and so on.  Then inside
-        "Kindergarten" you might want to create directories for each
-        classroom, say "Mrs. Smith" and "Mr. Jones."  A smaller school
-        might choose to skip the by-grade organization and go straight
-        to each classroom; a single computer in a single classroom
-        might skip these altogether.
+     2. In tuxmath_users, create a text file called
+        "user_menu_entries."  This file contains the list of choices
+        that students will be presented with upon login, one entry per
+        line.  For example, a large school with many classrooms might
+        have choices called "Kindergarten," "1st grade," and so on.
 
-     3. At the finest level, create one subdirectory for each student.
+     3. In the same directory, create sub-directories that have the
+        same names that appear in user_menu_entries.
 
-     4. Finally, adjust the launch command for tuxmath to pass the
+     4. Create further user_menu_entries and further subdirectories
+        inside each of these.  For example, in "Kindergarten" you
+        might want to create directories for each classroom, say
+        "Mrs. Smith" and "Mr. Jones."  A smaller school might choose
+        to skip the by-grade organization and go straight to each
+        classroom; a single computer in a single classroom might skip
+        these altogether.  Always make sure that the user_menu_entry
+        file matches the directory structure (although having extra
+        directories will not cause a problem).
+
+     5. At the finest level, create a menu item and one subdirectory
+        for each student.
+
+     6. Optionally, in "tuxmath_users" you can also create a file
+        called "user_login_questions" that poses a question at each
+        step of the hierarchy.  For example, it might contain three
+        lines, "Choose your grade:", "Choose your teacher:", "Who are
+        you?" If you omit this file, then students will simply be
+        presented with the list without any kind of prompt.
+
+     7. Finally, adjust the launch command for tuxmath to pass the
         command line option "--homedir /severvolume/tuxmath_users"
         (along with any other options) upon launching tuxmath.  Note
         that an individual classroom could make use of this

Modified: tuxmath/trunk/doc/changelog
===================================================================
--- tuxmath/trunk/doc/changelog	2007-12-01 01:35:31 UTC (rev 350)
+++ tuxmath/trunk/doc/changelog	2007-12-02 07:34:35 UTC (rev 351)
@@ -1,3 +1,11 @@
+2007.Nov.26 (svn.debian.org/tux4kids - revision 350)
+  Options:
+	
+      * Reworked the user login to make it more robust and
+	user-friendly.  This version should be pretty generally usable.
+	
+      Tim Holy <holy at wustl.edu>
+
 2007.Nov.26 (svn.debian.org/tux4kids - revision 342)
   Options:
       * Added support for user login. This should be helpful in school
@@ -3,4 +11,6 @@
 	settings where all students log in with the same username.  See
 	the README for details.
+
+      Tim Holy <holy at wustl.edu>
 	
 2007.Nov.18 (svn.debian.org/tux4kids - revision 327)

Modified: tuxmath/trunk/src/fileops.c
===================================================================
--- tuxmath/trunk/src/fileops.c	2007-12-01 01:35:31 UTC (rev 350)
+++ tuxmath/trunk/src/fileops.c	2007-12-02 07:34:35 UTC (rev 351)
@@ -2590,6 +2590,7 @@
 /* Utility function to test whether a given dirent represents a directory */
 /* Note this assumes a base of the user's current data directory, it's
    not a general function. */
+/*
 int isdir(const struct dirent *dirEntry)
 {
   struct stat fileStat;
@@ -2616,58 +2617,126 @@
   else
     return 0;
 }
+*/
 
+/* A utility function to read lines from a textfile.  Upon exit, it */
+/* returns the # of lines successfully read, and sets the pointer   */
+/* array so that (*lines)[i] is a pointer to the text on the ith    */
+/* line.  Note this function also cleans up trailing whitespace,    */
+/* and skips blank lines.                                           */
+/* On entry, *lines must be NULL, as a sign that any previously     */
+/* allocated memory has been freed.                                 */
+int read_lines_from_file(FILE *fp,char ***lines)
+{
+  char *fgets_return_val;
+  char name_buf[NAME_BUF_SIZE];
+  int n_entries;
+  int length;
 
-/* Checks to see if the current data dir has subdirectories, and if so  */
-/* returns their names. This is used in cases where users must select   */
-/* their login information. Returns the number of subdirectories (0 if  */
-/* there are none), and sets the input argument to a malloc-ed array    */
-/* names (sets to NULL if there are no subdirectories).                 */
-int tuxmath_dir_subdirs(char ***subdir_names)
+  n_entries = 0;
+  if(*lines != NULL) {
+    printf("Error: lines buffer was not NULL upon entry");
+    exit(EXIT_FAILURE);
+  }
+
+  fgets_return_val = fgets(name_buf,NAME_BUF_SIZE,fp);
+  while (fgets_return_val != NULL) {
+    // Strip terminal whitespace and \r
+    length = strlen(name_buf);
+    while (length>0 && (name_buf[length - 1] == '\r' || name_buf[length - 1] == '\n'|| name_buf[length-1] == ' ' || name_buf[length-1] == '\t')) {
+      name_buf[length - 1] = '\0';
+      length--;
+    }
+    if (length == 0) {
+      // If we get to a blank line, skip over it
+      fgets_return_val = fgets(name_buf,NAME_BUF_SIZE,fp);
+      continue;
+    }
+    n_entries++;
+    *lines = realloc(*lines,n_entries*sizeof(char*));
+    if (*lines == NULL) {
+      // Memory allocation error
+      printf("Error #1 allocating memory in read_lines_from_file\n");
+      exit(EXIT_FAILURE);
+    }
+    // Copy the cleaned-up line to the list
+    (*lines)[n_entries-1] = strdup(name_buf);
+    if ((*lines)[n_entries-1] == NULL) {
+      // Memory allocation error
+      printf("Error #2 allocating memory in read_lines_from_file\n");
+      exit(EXIT_FAILURE);
+    }
+    // Read the next line
+    fgets_return_val = fgets(name_buf,NAME_BUF_SIZE,fp);
+  }
+  return n_entries;
+}
+
+/* Checks to see if the current homedir has a menu_entries file, and if */
+/* so returns the names of the menu entries. This is used in cases      */
+/* where users must select their login information. Returns the number  */
+/* of menu entries (0 if there are none), and sets the input            */
+/* argument to a malloc-ed array of names (sets to NULL if there are no */
+/* choices to be made).  */
+int read_user_menu_entries(char ***user_names)
 {
-  struct dirent **namelist;
-  int n_entries,i;
-  char opt_path[PATH_MAX];
+  FILE *fp;
+  int n_entries;
+  char opt_path[PATH_MAX],menu_entries_file[PATH_MAX];
 
-#ifdef BUILD_MINGW32
-  // Fixme: The scandir for Windows doesn't support filtering, so this
-  // feature is currently disabled on Windows. Perhaps we just have to
-  // abandon scandir??
-  *subdir_names = NULL;
-  return 0;
-#else
+  // Look for a menu_entries file
   get_user_data_dir_with_subdir(opt_path);
-  n_entries = scandir(opt_path, &namelist, isdir, alphasort);
-  if (n_entries > 0) {
-    *subdir_names = (char **) malloc(n_entries*sizeof(char*));
-    for (i = 0; i < n_entries; i++)
-      (*subdir_names)[i] = strdup(namelist[i]->d_name);
-    free(namelist);
-    return n_entries;
+  strncpy(menu_entries_file,opt_path,PATH_MAX);
+  strncat(menu_entries_file,"user_menu_entries",PATH_MAX-strlen(menu_entries_file));
+  n_entries = 0;
+  fp = fopen(menu_entries_file,"r");
+  if (fp)
+  {
+    // There is a menu_entries file, read it
+    n_entries = read_lines_from_file(fp,user_names);
+    fclose(fp);
   }
-  else {
-    *subdir_names = NULL;
-    return 0;
-  }
-#endif
+
+  return n_entries;
 }
 
+/* Reads the user_login_questions file. The syntax is identical to
+   read_user_menu_entries. */
+int read_user_login_questions(char ***user_login_questions)
+{
+  FILE *fp;
+  int n_entries;
+  char opt_path[PATH_MAX],user_login_questions_file[PATH_MAX];
+
+  // Look for a user_login_questions file
+  get_user_data_dir_with_subdir(opt_path);
+  strncpy(user_login_questions_file,opt_path,PATH_MAX);
+  strncat(user_login_questions_file,"user_login_questions",PATH_MAX-strlen(user_login_questions_file));
+   n_entries = 0;
+  fp = fopen(user_login_questions_file,"r");
+  if (fp)
+  {
+    // There is a user_login_questions file, read it
+    n_entries = read_lines_from_file(fp,user_login_questions);
+    fclose(fp);
+   }
+ 
+  return n_entries;
+}
+
 /* A utility function to go up one level in a directory hierarchy */
 void dirname_up(char *dirname)
 {
   int len;
 
   len = strlen(dirname);
-  printf("up1: len = %d\n",len);
   // Pass over all trailing "/"
   while (len > 0 && dirname[len-1] == '/')
     len--;
-  printf("up2: len = %d\n",len);
 
   // Now pass over all non-"/" characters at the end
   while (len > 0 && dirname[len-1] != '/')
     len--;
-  printf("up3: len = %d\n",len);
   
   // Terminate the string after that next-to-last "/"
   dirname[len] = '\0';

Modified: tuxmath/trunk/src/titlescreen.c
===================================================================
--- tuxmath/trunk/src/titlescreen.c	2007-12-01 01:35:31 UTC (rev 350)
+++ tuxmath/trunk/src/titlescreen.c	2007-12-02 07:34:35 UTC (rev 351)
@@ -921,51 +921,79 @@
 /* 0 indicates that a choice has been made.                     */
 int run_login_menu(void)
 {
+  int n_login_questions = 0;
+  char **user_login_questions = NULL;
+  int n_users = 0;
+  char **user_names = NULL;
+  
   menu_options menu_opts;
   int chosen_login = -1;
   char *user_home;
-  char **subdir_names;
-  int n_subdirs;
   int level;
-  char opt_path[PATH_MAX];
+  int i;
+  char *trailer_quit = "Quit";
+  char *trailer_back = "Back";
 
-  set_default_menu_options(&menu_opts);
+  // Check for & read user_login_questions file
+  n_login_questions = read_user_login_questions(&user_login_questions);
+
+  // Check for & read user_menu_entries file
+  n_users = read_user_menu_entries(&user_names);
+  
+  if (n_users == 0)
+    return 0;   // a quick exit, there's only one user
+
   level = 0;
-  // Get current home directory
   user_home = get_user_data_dir();
+  set_default_menu_options(&menu_opts);
+  if (n_login_questions > 0)
+    menu_opts.title = user_login_questions[0];
+  menu_opts.trailer = trailer_quit;
 
-  n_subdirs = tuxmath_dir_subdirs(&subdir_names);
-  while (n_subdirs) {
+  while (n_users) {
     // Get the user choice
-    chosen_login = choose_menu_item(subdir_names, NULL, n_subdirs, menu_opts);
-    if (chosen_login == -1) {
-      // User pressed escape, handle by quitting or going up a level
-      free(subdir_names);
-      if (level == 0)
-	return -1;   // Indicate that the user is quitting without logging in
+    chosen_login = choose_menu_item(user_names, NULL, n_users, menu_opts);
+    if (chosen_login == -1 || chosen_login == n_users) {
+      // User pressed escape or selected Quit/Back, handle by quitting
+      // or going up a level
+      if (level == 0) {
+	// We are going to quit without logging in. So, we don't have
+	// to worry about cleaning up memory.
+	return -1;
+      }
       else {
 	// Go back up one level of the directory tree
-	printf("Going up a level\n");
-	printf("Previous home: %s\n",user_home);
 	dirname_up(user_home);
 	level--;
-	printf("New home: %s\n",user_home);
-	n_subdirs = tuxmath_dir_subdirs(&subdir_names);
+	menu_opts.starting_entry = -1;
       }
     }
     else {
       // User chose an entry, set it up
-      strcat(user_home,subdir_names[chosen_login]);
+      strcat(user_home,user_names[chosen_login]);
       strcat(user_home,"/");
       level++;
-      free(subdir_names);
-      // Keep checking to see if we need to descend further
-      n_subdirs = tuxmath_dir_subdirs(&subdir_names);
+      menu_opts.starting_entry = 0;
     }
+    // Free the entries from the previous menu
+    for (i = 0; i < n_users; i++)
+      free(user_names[i]);
+    free(user_names);
+    user_names = NULL;
+    // Set the title appropriately for the next menu
+    if (level < n_login_questions)
+      menu_opts.title = user_login_questions[level];
+    else
+      menu_opts.title = NULL;
+    if (level == 0)
+      menu_opts.trailer = trailer_quit;
+    else
+      menu_opts.trailer = trailer_back;
+    // Check to see if there are more choices to be made
+    n_users = read_user_menu_entries(&user_names);
   }
-  get_user_data_dir_with_subdir(opt_path);
-  printf("User data directory: %s\n", opt_path);
 
+  // The user home directory is set, signal success
   return 0;
 }
 
@@ -1006,6 +1034,8 @@
   int click_flag = 1;
   int use_sprite = 0;
   int warp_mouse = 0;
+  int title_offset = 0;
+  int have_trailer = 0;
 
 #ifdef TUXMATH_DEBUG
   fprintf(stderr, "Entering choose_menu_item():\n");
@@ -1018,8 +1048,13 @@
 #endif
 
   /**** Memory allocation for menu text  ****/
-  menu_item_unselected = (SDL_Surface**)malloc(n_menu_entries * sizeof(SDL_Surface*));
-  menu_item_selected = (SDL_Surface**)malloc(n_menu_entries * sizeof(SDL_Surface*));
+  title_offset = 0;
+  if (menu_opts.title != NULL)
+    title_offset = 1;
+  if (menu_opts.trailer != NULL)
+    have_trailer = 1;
+  menu_item_unselected = (SDL_Surface**)malloc((n_menu_entries+title_offset+have_trailer) * sizeof(SDL_Surface*));
+  menu_item_selected = (SDL_Surface**)malloc((n_menu_entries+title_offset+have_trailer) * sizeof(SDL_Surface*));
   if (menu_item_unselected == NULL || menu_item_selected == NULL) {
     free(menu_item_unselected);
     free(menu_item_selected);
@@ -1027,11 +1062,24 @@
   }
 
   /**** Render the menu choices                               ****/
+  if (title_offset)
+  {
+    menu_item_unselected[0] = BlackOutline( _(menu_opts.title),default_font,&red);
+    // It will never be selected, so we don't have to do anything for selected.
+    menu_item_selected[0] = NULL;
+  }
   for (i = 0; i < n_menu_entries; i++)
   {
-    menu_item_unselected[i] = BlackOutline( _(menu_text[i]), default_font, &white );
-    menu_item_selected[i] = BlackOutline( _(menu_text[i]), default_font, &yellow);
+    menu_item_unselected[i+title_offset] = BlackOutline( _(menu_text[i]), default_font, &white );
+    menu_item_selected[i+title_offset] = BlackOutline( _(menu_text[i]), default_font, &yellow);
   }
+  if (have_trailer) {
+    menu_item_unselected[n_menu_entries+title_offset] = BlackOutline( _(menu_opts.trailer), default_font, &white );
+    menu_item_selected[n_menu_entries+title_offset] = BlackOutline( _(menu_opts.trailer), default_font, &yellow);
+  }
+  // We won't need the menu_text again, so now we can keep track of
+  // the total entries including the title & trailer
+  n_menu_entries += title_offset+have_trailer;
 
   /**** Calculate the menu item heights and the number of     ****/
   /**** entries per screen                                    ****/
@@ -1100,7 +1148,7 @@
   /* Set initial menu rect sizes. The widths will change depending      */
   /* on the size of the text displayed in each rect.  Set the widths    */
   /* for the current screen of menu items.                              */
-  loc = menu_opts.starting_entry;  // Choose initial selected item
+  loc = menu_opts.starting_entry + title_offset;  // Initially selected item
   loc_screen_start = loc - (loc % n_entries_per_screen);
   if (loc_screen_start < 0 || loc_screen_start*n_entries_per_screen > n_menu_entries)
     loc_screen_start = 0;  // in case starting_entry was -1 (or wasn't set)
@@ -1152,6 +1200,7 @@
   /******** Main loop:                                *********/
   redraw = 1;  // force a full redraw on first pass
   old_loc_screen_start = loc_screen_start;
+  while (SDL_PollEvent(&event));  // clear pending events
   while (!stop)
   {
     frame_start = SDL_GetTicks();         /* For keeping frame rate constant.*/
@@ -1335,7 +1384,7 @@
             {
               if (Opts_MenuSound())
                 playsound(SND_TOCK);
-              if (loc > 0)
+              if (loc > title_offset)
                 {loc--;}
 	      else if (n_menu_entries <= n_entries_per_screen) {
 		loc = n_menu_entries-1;  // wrap around if only 1 screen
@@ -1358,7 +1407,7 @@
               if (loc >= 0 && loc + 1 < n_menu_entries)
                 {loc++;}
 	      else if (n_menu_entries <= n_entries_per_screen)
-		loc = 0;       // wrap around if only 1 screen
+		loc = title_offset;       // wrap around if only 1 screen
 	      else if (loc == -1)
 		loc = loc_screen_start;
 	      if (loc != old_loc)
@@ -1403,6 +1452,10 @@
     }  // End SDL_PollEvent while loop
 
 
+    // Make sure the menu title is not selected
+    if (loc == 0 && title_offset)
+      loc = title_offset;
+
     /* Redraw screen: */
     if (loc >= 0)
       loc_screen_start = loc - (loc % n_entries_per_screen);
@@ -1426,13 +1479,18 @@
 	menu_button_rect[imod].w = 0;  // so undrawn buttons don't affect width
       for (i = loc_screen_start, imod = 0; i < loc_screen_start+n_entries_per_screen && i < n_menu_entries; i++, imod++) {
 	menu_text_rect[imod].w = menu_item_unselected[i]->w;
-	menu_button_rect[imod].w = menu_text_rect[imod].w + 30;
-	if (menu_sprites != NULL)
-	  menu_button_rect[imod].w += 60;
+	if (i >= title_offset) {
+	  menu_button_rect[imod].w = menu_text_rect[imod].w + 30;
+	  if (menu_sprites != NULL)
+	    menu_button_rect[imod].w += 60;
+	}
       }
 
       if (menu_opts.button_same_width)
 	set_buttons_max_width(menu_button_rect,n_entries_per_screen);
+      // Make sure the menu title mouse button didn't get turned on
+      if (loc_screen_start == 0 && title_offset)
+	menu_button_rect[0].w = 0;
 
       for (i = loc_screen_start, imod = 0; i < loc_screen_start+n_entries_per_screen && i < n_menu_entries; i++, imod++) {
 	if (i == loc) {  //Draw text in yellow
@@ -1440,11 +1498,12 @@
 	  SDL_BlitSurface(menu_item_selected[loc], NULL, screen, &menu_text_rect[imod]);
 	}
 	else {          //Draw text in white
-	  DrawButton(&menu_button_rect[imod], 10, REG_RGBA);
+	  if (menu_button_rect[imod].w > 0)
+	    DrawButton(&menu_button_rect[imod], 10, REG_RGBA);
 	  SDL_BlitSurface(menu_item_unselected[i], NULL, screen, &menu_text_rect[imod]);
 	}
-	if (menu_sprites != NULL && menu_sprites[i] != NULL)
-	  SDL_BlitSurface(menu_sprites[i]->default_img, NULL, screen, &menu_sprite_rect[imod]);
+	if (menu_sprites != NULL && (i >= title_offset) && menu_sprites[i-title_offset] != NULL)
+	  SDL_BlitSurface(menu_sprites[i-title_offset]->default_img, NULL, screen, &menu_sprite_rect[imod]);
       }
 
       /* --- draw 'left' and 'right' buttons --- */
@@ -1473,7 +1532,7 @@
       // By just redrawing the old and new selections, we avoid flickering.
       if (old_loc >= 0) {
 	imod = old_loc-loc_screen_start;
-	use_sprite = (menu_sprites != NULL && menu_sprites[old_loc] != NULL);
+	use_sprite = (menu_sprites != NULL && old_loc >= title_offset && menu_sprites[old_loc-title_offset] != NULL);
 	SDL_BlitSurface(images[IMG_MENU_BKG], &menu_button_rect[imod], screen, &menu_button_rect[imod]);   // redraw background
 	if (use_sprite) {
 	  // Some of the sprites extend beyond the menu button, so we
@@ -1483,7 +1542,7 @@
 	DrawButton(&menu_button_rect[imod], 10, REG_RGBA);  // draw button
 	SDL_BlitSurface(menu_item_unselected[old_loc], NULL, screen, &menu_text_rect[imod]);  // draw text
 	if (use_sprite) {
-	  SDL_BlitSurface(menu_sprites[old_loc]->default_img, NULL, screen, &menu_sprite_rect[imod]);
+	  SDL_BlitSurface(menu_sprites[old_loc-title_offset]->default_img, NULL, screen, &menu_sprite_rect[imod]);
 	  // Also update the sprite rect (in some cases the sprite
 	  // extends beyond the menu button)
 	  SDL_UpdateRect(screen, menu_sprite_rect[imod].x, menu_sprite_rect[imod].y, menu_sprite_rect[imod].w, menu_sprite_rect[imod].h);
@@ -1493,24 +1552,24 @@
 
       if (loc >= 0) {
 	imod = loc-loc_screen_start;
-	use_sprite = (menu_sprites != NULL && menu_sprites[loc] != NULL);
+	use_sprite = (menu_sprites != NULL && loc >= title_offset && menu_sprites[loc] != NULL);
 	SDL_BlitSurface(images[IMG_MENU_BKG], &menu_button_rect[imod], screen, &menu_button_rect[imod]);
 	if (use_sprite)
 	  SDL_BlitSurface(images[IMG_MENU_BKG], &menu_sprite_rect[imod], screen, &menu_sprite_rect[imod]);
 	DrawButton(&menu_button_rect[imod], 10, SEL_RGBA);
 	SDL_BlitSurface(menu_item_selected[loc], NULL, screen, &menu_text_rect[imod]);
 	if (use_sprite) {
-	  menu_sprites[loc]->cur = 0;  // start at beginning of animation sequence
-	  SDL_BlitSurface(menu_sprites[loc]->frame[menu_sprites[loc]->cur], NULL, screen, &menu_sprite_rect[imod]);
+	  menu_sprites[loc-title_offset]->cur = 0;  // start at beginning of animation sequence
+	  SDL_BlitSurface(menu_sprites[loc-title_offset]->frame[menu_sprites[loc-title_offset]->cur], NULL, screen, &menu_sprite_rect[imod]);
 	  SDL_UpdateRect(screen, menu_sprite_rect[imod].x, menu_sprite_rect[imod].y, menu_sprite_rect[imod].w, menu_sprite_rect[imod].h);
-	  next_frame(menu_sprites[loc]);
+	  next_frame(menu_sprites[loc-title_offset]);
 	}
 	SDL_UpdateRect(screen, menu_button_rect[imod].x, menu_button_rect[imod].y, menu_button_rect[imod].w, menu_button_rect[imod].h);
       }
     } else if (frame_counter % 5 == 0 && loc >= 0) {
       // No user input changed anything, but check to see if we need to
       // animate the sprite
-      if (menu_sprites != NULL && menu_sprites[loc] != NULL) {
+      if (menu_sprites != NULL && loc >= title_offset && menu_sprites[loc-title_offset] != NULL) {
 	imod = loc-loc_screen_start;
 	//SDL_BlitSurface(images[IMG_MENU_BKG], &menu_button_rect[imod], screen, &menu_button_rect[imod]);
 	SDL_BlitSurface(images[IMG_MENU_BKG], &menu_sprite_rect[imod], screen, &menu_sprite_rect[imod]);
@@ -1521,9 +1580,9 @@
 	// update that rect. If something else changes and we go to
 	// full-screen updates, then remove the "commenting-out" on
 	// the two lines above
-	SDL_BlitSurface(menu_sprites[loc]->frame[menu_sprites[loc]->cur], NULL, screen, &menu_sprite_rect[imod]);
+	SDL_BlitSurface(menu_sprites[loc-title_offset]->frame[menu_sprites[loc-title_offset]->cur], NULL, screen, &menu_sprite_rect[imod]);
 	SDL_UpdateRect(screen, menu_sprite_rect[imod].x, menu_sprite_rect[imod].y, menu_sprite_rect[imod].w, menu_sprite_rect[imod].h);
-	next_frame(menu_sprites[loc]);
+	next_frame(menu_sprites[loc-title_offset]);
       }
     }
 
@@ -1591,7 +1650,7 @@
   if (stop == 2)
     return -1;
   else
-    return loc;
+    return loc - title_offset;
 }
 
 
@@ -1888,4 +1947,6 @@
   menu_opts->buttonheight = -1;
   menu_opts->ygap = 10;
   menu_opts->button_same_width = 1;
+  menu_opts->title = NULL;
+  menu_opts->trailer = NULL;
 }

Modified: tuxmath/trunk/src/titlescreen.h
===================================================================
--- tuxmath/trunk/src/titlescreen.h	2007-12-01 01:35:31 UTC (rev 350)
+++ tuxmath/trunk/src/titlescreen.h	2007-12-02 07:34:35 UTC (rev 351)
@@ -66,6 +66,8 @@
   int buttonheight; // size of menu item button  (-1 if calculated)
   int ygap;  // vertical gap between entries
   int button_same_width; // should all buttons have the same width?
+  char *title;
+  char *trailer;
 } menu_options;
 
 




More information about the Tux4kids-commits mailing list