[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