26a27
> #define DEBUG 1
36,41c37,61
< #define LETTERS_ARRAY_LENGTH 3
< static char *letters_array[LETTERS_ARRAY_LENGTH] = {
<   "0123456789",
<   G_CSET_A_2_Z,
<   G_CSET_a_2_z
< };
---
> /* both letters_array and keymap should be read in
>  * dynamically at run-time from files based on 
>  * user locale
>  */
> 
> /* letters_array contains letters you want shown
>  * on each play level
>  * there appear to be 6 levels, apparently hard-coded
>  * somewhere in the program
>  */
> 
> #define MAXLEVEL 6
> char *letters_array[MAXLEVEL];
> 
> /* keymap contains pairs of chars. The first char is the ASCII
>  * on the keyboard map, the second is the unichar that 
>  * is also represented by that key.  That way, if there is more
>  * than one character represented by a key, the user doesn't
>  * have to use alternate input methods.
>  * both chars are packed into the same string; this makes it
>  * easier to deal with.
>  */
> 
> int keyMapSize;
> char **keyMap;
142a163,251
> int fill_letters(char **letterString,char *buffer) {
>    *letterString = g_malloc(strlen(buffer)+1);
>    sprintf(*letterString,"%s",buffer);
>    }
> 
> int load_default_charset() {
>    printf("in load_default_charset\n");
>    fill_letters(&letters_array[0],"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
>    fill_letters(&letters_array[1],"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
>    fill_letters(&letters_array[2],"abcdefghijklmnopqrstuvwxyz");
>    fill_letters(&letters_array[3],"abcdefghijklmnopqrstuvwxyz0123456789");
>    fill_letters(&letters_array[4],"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
>    fill_letters(&letters_array[5],"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
>    keyMapSize = 0;
>    return TRUE;
>    }
> 
> int load_charset_from_file(FILE *fp) {
>    int level, fp_ret_code, currKeyMap;
>    char lineBuffer[4096], strBuffer[4096], charBuffer[8];
> 
>    /* keymap size is dynamically allocated */
> 
>    keyMapSize = 64;
>    currKeyMap = 0;
>    keyMap = (char **)g_malloc((sizeof (char *))*keyMapSize);
>    
> 
>    printf("in load_charset_from_file\n");
> 
>    /* first read each line into a buffer */
>    while( fgets(lineBuffer,4095,fp) ) {
>       /* if it's a comment, skip line */
>       if ( lineBuffer[0] == '#' ) continue;
>       /* if it's not a comment, it can only be one of 2 things
>        * a level string, where it starts with "level "
>        * and the format is "level %d %s" or
>        * a keymap which starts with "key" and the format is "key %c%lc"
>        */
>       if( sscanf(lineBuffer,"level %d %s",&level, strBuffer) == 2 ) {
>          /* we have a level charset */
>          if (level > MAXLEVEL || level < 1) {
>             g_message("level %d outside range of 1 to %s in line %s ",level,MAXLEVEL,lineBuffer);
>             return FALSE;
>             }
>          fill_letters(&letters_array[level-1],strBuffer);
>          }
>       else if( sscanf(lineBuffer,"key %7s",charBuffer) == 1) {
>          /* we potentially have a keymap */
>          if( !g_utf8_validate(charBuffer,-1,(void *)NULL) ) {
>             /* it's not a valid UTF-8 string */
>             g_message("malformed UTF-8 character string >%s< ",charBuffer);
>             return FALSE;
>             }
>          keyMap[currKeyMap] = (char *)g_malloc((sizeof (char))*8);
>          sprintf(keyMap[currKeyMap],"%s",charBuffer);
>          currKeyMap++;
>          if(currKeyMap == keyMapSize) {
>             keyMapSize *= 2;
>             keyMap = (char **)realloc(keyMap,(sizeof(char *))*keyMapSize);
>             }
>          }
>      else
>        g_message("unknown command in file: %s",lineBuffer);
>    }
>    return TRUE;
> }   
> 
> int get_charset(char *locale) {
>   char *filename;
>   FILE *charsfd = NULL;
>                                                                                                                      
>   /* First Try to find a file matching the level and the locale */
>   filename = g_strdup_printf("%s%s.%.2s",
>                              PACKAGE_DATA_DIR, "/gletters/gletters",
>                              locale);
>   g_message("Trying to open file %s ", filename);
>   charsfd = fopen (filename, "r");
>   g_free(filename);
>                                                                                                                      
>   if (charsfd == (FILE *)NULL) {
>       g_message("failed to open file.\n");
>       load_default_charset();
>       }
>   else if (load_charset_from_file(charsfd))
>       g_message("loaded charset from file.\n");
>    else load_default_charset();
> }
> 
151d259
< 
152a261,271
>       get_charset(gcompris_get_locale());
> 
> /*
>  *    We need more levels than 6.  We should have a progressive level of difficulty
>  *    by grade level if the locale requires it.
>  * 
>  *    For ja_JP, for example, we should have about 18 levels, starting with
>  *    caps, then adding digits, lower case, hiragana, katakana, and then 12
>  *    levels of Kanji
>  *
>  */
154c273,289
<       gcomprisBoard->number_of_sublevel=10; /* Go to next level after this number of 'play' */
---
> 
> /*
>  *    we really want to have sublevel dynamically assigned based on no. of chars at current level
>  *    since in alternate alphabets the nubmer of characters can get very large
>  *    I'm thinking grade level Kanji, where by 12th grade there are 1800 +/- chars we should be 
>  *    dropping
>  *
>  *    10 just is not a sufficient number with that large a charset
>  *    
>  *    I've tried the line below, but doesn't seen to have any effect.
>  *    I'm guessing that sublevel is hardcoded somewhere
>  *
>  *    gcomprisBoard->number_of_sublevel=max(8,g_utf8_strlen(letters_array[gcomprisBoard->level-1],-1));
>  *
>  *    for now go with original sublevel ct.
>  */
>       gcomprisBoard->number_of_sublevel=10;
197,200c332,347
< gint key_press(guint keyval)
< {
<   gchar *old_value;
<   gchar *old_name;
---
> gint is_falling_letter(char *utfchar) {
>    gchar *old_value;
>    gchar *old_name;
> 
>    if (g_hash_table_lookup_extended (letters_table,
>                                     utfchar,
>                                     (gpointer) &old_name,
>                                     (gpointer) &old_value))
>        {
>        player_win(item_find_by_title(utfchar));
>        return TRUE;
>        }
>    return FALSE;
>    }
> 
> gint key_press(guint keyval) {
202c349,351
<   char str[2];
---
>   char lcStr[6],ucStr[6], *str;
>   char utf8char[6];
>   int i;
269,276c418,424
<   c = tolower(keyval); 
<   str[0] = c;
<   str[1] = '\0';
<   if (g_hash_table_lookup_extended (letters_table,
< 				    (char *)&str,
< 				    (gpointer) &old_name,
< 				    (gpointer) &old_value))
<     {
---
> /* first check the obvious - simple keystrokes 
>    check for keymap 
>    convert to unichar/utf8
>    set to lower case
>    check direct match
>    check upper case match
>  */
278c426,427
<       player_win(item_find_by_title((char *)&str));
---
>   for(i = 0; i < keyMapSize; ++i) {
>      if (keyval == keyMap[i][0]) {
280,283c429,436
<     }
<   else
<     {
<       gchar *list_of_letters[255];
---
>         /* match in keymap */
>         sprintf(utf8char, "%s", keyMap[i]+1);
>         if( is_falling_letter(utf8char) ) {
>             str = utf8char;
>             break;
>             }
>         }
>      }
285d437
<       list_of_letters[0] = '\0';
287,290d438
<       /* We have to loop to concat the letters */
<       g_hash_table_foreach (letters_table,
< 			    (GHFunc) add_char,
< 			    list_of_letters);
292,293c440,467
<       /* Log what happened, what was expected, what we got */
<       gcompris_log_set_comment(gcomprisBoard, list_of_letters, str);
---
>       /* no match in keymap */
>     if (i == keyMapSize) {
> 
>        sprintf(utf8char, "%c", gdk_keyval_to_unicode(keyval));
>        g_unichar_to_utf8 (gdk_keyval_to_unicode(keyval),utf8char);
> 
>        sprintf(lcStr,"%s",g_utf8_strdown(utf8char,-1));
>        sprintf(ucStr,"%s",g_utf8_strup(utf8char,-1));
> 
>        if ( is_falling_letter(lcStr) ) {
>               str = lcStr;
>               }
>        else if( is_falling_letter(ucStr) ) {
>               str = ucStr;
>               }
>        else {
>           str = utf8char;
>           player_loose();
>           }
>      }
> 
>      gchar *list_of_letters[255];
>      list_of_letters[0] = '\0';
> 
>      /* We have to loop to concat the letters */
>      g_hash_table_foreach (letters_table,
>          (GHFunc) add_char,
>          list_of_letters);
295,296c469,471
<       player_loose();
<     }
---
>      /* Log what happened, what was expected, what we got */
> 
>      gcompris_log_set_comment(gcomprisBoard, list_of_letters, str);
428c603
<   int i;
---
>   int i,j,k;
430c605
<   char *lettersItem;
---
>   char *lettersItem, *str_p;
437c612
<   lettersItem = g_malloc (2);
---
>   lettersItem = g_malloc (6);
443a619,622
> 
>   printf("dump: %d, %s\n",gcomprisBoard->level,letters_array[gcomprisBoard->level-1]);
> 
>   k=g_utf8_strlen(letters_array[gcomprisBoard->level-1],-1);
445,451c624,625
<     i=rand()%strlen(letters_array[gcomprisBoard->level%LETTERS_ARRAY_LENGTH]);
<     sprintf(lettersItem, "%c",
< 	    letters_array[gcomprisBoard->level%LETTERS_ARRAY_LENGTH][i]);
< 
<     /* Changing the letter to lower case : should be easier but these works */
<     c = tolower(lettersItem[0]); 
<     sprintf(lettersItem, "%c", c);
---
>     str_p=letters_array[gcomprisBoard->level-1];
>     i=1+(int)((float)k*rand()/(RAND_MAX+1.0));
453c627,631
<   } while(item_find_by_title(lettersItem)!=NULL);
---
>     for( j = 0; j < i; j++) {
>         str_p=g_utf8_find_next_char(str_p,NULL);
>        }
>     sprintf(lettersItem, "%lc",
> 	    g_utf8_get_char(str_p));
455c633
<   lettersItem[1] = '\0';
---
>   } while(item_find_by_title(lettersItem)!=NULL);
464d641
< 
472c649
<   x = 80 + (rand()%(gcomprisBoard->width-160));
---
>   x = 80 + (int)((float)(gcomprisBoard->width-160)*rand()/(RAND_MAX+1.0));
