Back to index

gcompris  8.2.2
gletters.c
Go to the documentation of this file.
00001 /* gcompris - gletters.c
00002  *
00003  * Time-stamp: <2006/08/21 23:33:17 bruno>
00004  *
00005  * Copyright (C) 2000 Bruno Coudoin
00006  *
00007  *   This program is free software; you can redistribute it and/or modify
00008  *   it under the terms of the GNU General Public License as published by
00009  *   the Free Software Foundation; either version 2 of the License, or
00010  *   (at your option) any later version.
00011  *
00012  *   This program is distributed in the hope that it will be useful,
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *   GNU General Public License for more details.
00016  *
00017  *   You should have received a copy of the GNU General Public License
00018  *   along with this program; if not, write to the Free Software
00019  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  */
00021 
00022 #include <string.h>
00023 
00024 #include "gcompris/gcompris.h"
00025 
00026 #define SOUNDLISTFILE PACKAGE
00027 #define MAX_RAND_ATTEMPTS 5
00028 
00029 static GList *item_list = NULL;
00030 static GList *item2del_list = NULL;
00031 
00032 static GcomprisBoard *gcomprisBoard = NULL;
00033 
00034 static gint dummy_id = 0;
00035 static gint drop_items_id = 0;
00036 
00037 /* Sublevels are now allocated dynamically
00038  * based on the number of chars at that level
00039  * Set DEFAULT_SUBLEVEL to the minimum
00040  * number of sublevels you want
00041  */
00042 
00043 #define DEFAULT_SUBLEVEL 8
00044 
00045 /* these constants control how fast letters fall
00046  * the base rate is fixed
00047  * the increment governs increase per level
00048  * the smaller the numbers, the faster the letters fall
00049  */
00050 
00051 #define FALL_RATE_BASE 40
00052 static float fallRateBase = FALL_RATE_BASE;
00053 #define FALL_RATE_MULT 100
00054 static float fallRateMult = FALL_RATE_MULT;
00055 
00056 /* these constants control how often letters are dropped
00057  * the base rate is fixed
00058  * the increment governs increase per level
00059  */
00060 
00061 #define DROP_RATE_BASE 1000
00062 static float dropRateBase = DROP_RATE_BASE;
00063 #define DROP_RATE_MULT 8000
00064 static float dropRateMult = DROP_RATE_MULT;
00065 
00066 /* both letters_array and keymap are read in
00067  * dynamically at run-time from files based on
00068  * user locale
00069  */
00070 
00071 /* letters_array contains letters you want shown
00072  * on each play level
00073  * there can be an arbitrary number of levels,
00074  * but there are only graphics to level 9
00075  * so that's where we stop
00076  */
00077 
00078 #define MAXLEVEL 10
00079 static int maxLevel;
00080 static char *letters_array[MAXLEVEL];
00081 
00082 /* keymap contains pairs of chars. The first char is
00083  * on the keyboard map, the second is the unichar that
00084  * is also represented by that key.  That way, if there is more
00085  * than one character represented by a key, the user doesn't
00086  * have to use alternate input methods.
00087  * It turns out that some keyboards generate long unichars,
00088  * so keymap has to be big enough for 2 unichars
00089  * both chars are packed into the same string; this makes it
00090  * easier to deal with.
00091  */
00092 
00093 static int keyMapSize;
00094 static char **keyMap;
00095 
00096 /* Hash table of all displayed letters  */
00097 static GHashTable *letters_table= NULL;
00098 
00099 static void start_board (GcomprisBoard *agcomprisBoard);
00100 static void pause_board (gboolean pause);
00101 static void end_board (void);
00102 static gboolean is_our_board (GcomprisBoard *gcomprisBoard);
00103 static void set_level (guint level);
00104 static gint key_press(guint keyval, gchar *commit_str, gchar *preedit_str);
00105 static void gletter_config_start(GcomprisBoard *agcomprisBoard,
00106                                         GcomprisProfile *aProfile);
00107 static void gletter_config_stop(void);
00108 
00109 static GnomeCanvasItem *gletters_create_item(GnomeCanvasGroup *parent);
00110 static gint gletters_drop_items (GtkWidget *widget, gpointer data);
00111 static gint gletters_move_items (GtkWidget *widget, gpointer data);
00112 static void gletters_destroy_item(GnomeCanvasItem *item);
00113 static void gletters_destroy_items(void);
00114 static void gletters_destroy_all_items(void);
00115 static void gletters_next_level(void);
00116 static void gletters_add_new_item(void);
00117 
00118 static void player_win(GnomeCanvasItem *item);
00119 static void player_loose(void);
00120 static GnomeCanvasItem *item_find_by_title (const gunichar *title);
00121 static gunichar *key_find_by_item (const GnomeCanvasItem *item);
00122 
00123 static  guint32              fallSpeed = 0;
00124 static  double               speed = 0.0;
00125 static  int               gamewon;
00126 
00127 static gboolean with_sound = FALSE;
00128 
00129 /* Description of this plugin */
00130 static BoardPlugin menu_bp =
00131   {
00132     NULL,
00133     NULL,
00134     N_("Simple Letters"),
00135     N_("Type the falling letters before they reach the ground"),
00136     "Bruno Coudoin <bruno.coudoin@free.fr>",
00137     NULL,
00138     NULL,
00139     NULL,
00140     NULL,
00141     start_board,
00142     pause_board,
00143     end_board,
00144     is_our_board,
00145     key_press,
00146     NULL,
00147     set_level,
00148     NULL,
00149     NULL,
00150     gletter_config_start,
00151     gletter_config_stop
00152   };
00153 
00154 /*
00155  * Main entry point mandatory for each Gcompris's game
00156  * ---------------------------------------------------
00157  *
00158  */
00159 
00160 GET_BPLUGIN_INFO(gletters)
00161 
00162 /*
00163  * in : boolean TRUE = PAUSE : FALSE = UNPAUSE
00164  *
00165  */
00166 
00167 static void level_set_score() {
00168   int l;
00169 
00170   g_message("letters_array length for level %d is %ld\n",
00171            gcomprisBoard->level,
00172            g_utf8_strlen(letters_array[gcomprisBoard->level-1],-1));
00173   l = g_utf8_strlen(letters_array[gcomprisBoard->level-1],-1)/3;
00174   gcomprisBoard->number_of_sublevel = (DEFAULT_SUBLEVEL>l?DEFAULT_SUBLEVEL:l);
00175 
00176   gc_score_start(SCORESTYLE_NOTE,
00177                      gcomprisBoard->width - 220,
00178                      gcomprisBoard->height - 50,
00179                      gcomprisBoard->number_of_sublevel);
00180   gc_bar_set(GC_BAR_CONFIG|GC_BAR_LEVEL);
00181 }
00182 
00183 static void pause_board (gboolean pause)
00184 {
00185   if(gcomprisBoard==NULL)
00186     return;
00187 
00188   if(pause)
00189     {
00190       if (dummy_id) {
00191        gtk_timeout_remove (dummy_id);
00192        dummy_id = 0;
00193       }
00194       if (drop_items_id) {
00195        gtk_timeout_remove (drop_items_id);
00196        drop_items_id = 0;
00197       }
00198     }
00199   else
00200     {
00201       if(gamewon == TRUE) /* the game is won */
00202        {
00203          level_set_score();
00204          gletters_next_level();
00205        }
00206 
00207       if(!drop_items_id) {
00208        drop_items_id = gtk_timeout_add (1000,
00209                                     (GtkFunction) gletters_drop_items, NULL);
00210       }
00211       if(!dummy_id) {
00212        dummy_id = gtk_timeout_add (1000, (GtkFunction) gletters_move_items, NULL);
00213       }
00214     }
00215 }
00216 
00217 static gboolean uppercase_only;
00218 
00219 int load_default_charset() {
00220   g_message("in load_default_charset\n");
00221 
00222   gchar *numbers;
00223   gchar *alphabet_lowercase;
00224   gchar *alphabet_uppercase;
00225 
00226   /* TRANSLATORS: Put here the numbers in your language */
00227   numbers=_("0123456789");
00228   g_assert(g_utf8_validate(numbers,-1,NULL)); // require by all utf8-functions
00229 
00230   /* TRANSLATORS: Put here the alphabet lowercase in your language */
00231   alphabet_lowercase=_("abcdefghijklmnopqrstuvwxyz");
00232   g_assert(g_utf8_validate(alphabet_lowercase,-1,NULL)); // require by all utf8-functions
00233 
00234   g_warning("Using lowercase %s", alphabet_lowercase);
00235 
00236   /* TRANSLATORS: Put here the alphabet uppercase in your language */
00237   alphabet_uppercase=_("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
00238   g_assert(g_utf8_validate(alphabet_uppercase,-1,NULL)); // require by all utf8-functions
00239   g_warning("Using uppercase %s", alphabet_uppercase);
00240 
00241   letters_array[0] = g_strdup(alphabet_uppercase);
00242   letters_array[1] = g_strdup_printf("%s%s",
00243                                  alphabet_uppercase,
00244                                  numbers);
00245   if (!uppercase_only){
00246   letters_array[2] = g_strdup(alphabet_lowercase);
00247   letters_array[3] = g_strdup_printf("%s%s",
00248                                  alphabet_lowercase,
00249                                  numbers);
00250   letters_array[4] = g_strdup_printf("%s%s",
00251                                  alphabet_lowercase,
00252                                  alphabet_uppercase);
00253   letters_array[5] = g_strdup_printf("%s%s%s",
00254                                  alphabet_lowercase,
00255                                  alphabet_uppercase,
00256                                  numbers);
00257   } else{
00258     g_warning("Uppercase only is set");
00259       letters_array[2] = g_strdup(alphabet_uppercase);
00260     letters_array[3] = g_strdup_printf("%s%s",
00261                                    alphabet_uppercase,
00262                                    numbers);
00263     letters_array[4] = g_strdup_printf("%s%s",
00264                                    alphabet_uppercase,
00265                                    numbers);
00266     letters_array[5] = g_strdup_printf("%s%s",
00267                                    alphabet_uppercase,
00268                                    numbers);
00269   }
00270 
00271 
00272   keyMapSize = 0;
00273   maxLevel = 6;
00274   return TRUE;
00275 }
00276 
00277 int whitespace(char *buffer) {
00278   int i;
00279   i = 0;
00280   while(buffer[i] != '\0') {
00281     if(buffer[i] == ' ' || buffer[i] == '\t' || buffer[i++] == '\n')
00282       continue;
00283     else return FALSE;
00284   }
00285   return TRUE;
00286 }
00287 
00288 /*
00289  */
00290 static void start_board (GcomprisBoard *agcomprisBoard)
00291 {
00292   GHashTable *config = gc_db_get_board_conf();
00293 
00294   gc_locale_set(g_hash_table_lookup( config, "locale"));
00295 
00296   gchar *up_init_str = g_hash_table_lookup( config, "uppercase_only");
00297 
00298   if (up_init_str && (strcmp(up_init_str, "True")==0))
00299     uppercase_only = TRUE;
00300   else
00301     uppercase_only = FALSE;
00302 
00303   gchar *control_sound = g_hash_table_lookup( config, "with_sound");
00304 
00305   if (control_sound && strcmp(g_hash_table_lookup( config, "with_sound"),"True")==0)
00306     with_sound = TRUE;
00307   else
00308     with_sound = FALSE;
00309 
00310   g_hash_table_destroy(config);
00311 
00312   if(agcomprisBoard!=NULL)
00313     {
00314       gcomprisBoard=agcomprisBoard;
00315       load_default_charset();
00316       gc_set_background(gnome_canvas_root(gcomprisBoard->canvas), "images/scenery_background.png");
00317       gcomprisBoard->maxlevel=maxLevel;
00318       gcomprisBoard->level = 1;
00319       level_set_score();
00320       gletters_next_level();
00321       gamewon = FALSE;
00322       pause_board(FALSE);
00323     }
00324 }
00325 
00326 
00327 
00328 static void
00329 end_board ()
00330 {
00331   int i;
00332   if(gcomprisBoard!=NULL)
00333     {
00334       pause_board(TRUE);
00335       gc_score_end();
00336       gletters_destroy_all_items();
00337       g_message("freeing memory");
00338       for (i = 0; i < maxLevel; i++)
00339        g_free(letters_array[i]);
00340 
00341       for (i = 0; i < keyMapSize; i++)
00342        g_free(keyMap[i]);
00343 
00344       g_free(keyMap);
00345     }
00346 
00347   gc_locale_reset();
00348 
00349   gcomprisBoard = NULL;
00350 }
00351 
00352 static void
00353 set_level (guint level)
00354 {
00355 
00356   if(gcomprisBoard!=NULL)
00357     {
00358       gcomprisBoard->level=level;
00359       level_set_score();
00360       gletters_next_level();
00361     }
00362 }
00363 
00364 /* Append in char_list one of the falling letter */
00365 static void add_char(char *key, char *value, char *char_list)
00366 {
00367   strcat(char_list, key);
00368 }
00369 
00370 gboolean unichar_comp(gpointer key,
00371                     gpointer value,
00372                     gpointer user_data)
00373 {
00374   gunichar *target = (gunichar *) user_data;
00375   if (*((gunichar *)key) == *target)
00376     return TRUE;
00377 
00378   return FALSE;
00379 }
00380 
00381 gint is_falling_letter(gunichar  unichar)
00382 {
00383   GnomeCanvasItem *item;
00384 
00385   if ((item = g_hash_table_find(letters_table,
00386                             unichar_comp,
00387                             &unichar)))
00388     {
00389       player_win(item);
00390       return TRUE;
00391     }
00392   return FALSE;
00393 }
00394 
00395 static gint key_press(guint keyval, gchar *commit_str, gchar *preedit_str) {
00396   gint length_passed, i;
00397   gunichar c;
00398   gchar  list_of_letters[255];
00399   gchar *str;
00400 
00401   if(!gcomprisBoard)
00402     return FALSE;
00403 
00404   /* i suppose even numbers are passed through IM_context */
00405   if ((commit_str == NULL) && (preedit_str == NULL))
00406     return FALSE;
00407 
00408   gchar *string_passed;
00409   if (commit_str)
00410     string_passed = commit_str;
00411   else
00412     string_passed = preedit_str;
00413 
00414   str = g_strdup(string_passed);
00415 
00416   length_passed = g_utf8_strlen(string_passed, -1);
00417 
00418   for (i=0; i < length_passed; i++){
00419     c = g_utf8_get_char (string_passed);
00420     if (is_falling_letter(c)){
00421       gc_im_reset();
00422       return TRUE;
00423     }
00424 
00425     /* if uppercase_only is set we do not care about upper or lower case at all */
00426     gint level_uppercase;
00427     if (uppercase_only)
00428       level_uppercase = 10;
00429     else
00430       level_uppercase = 3;
00431 
00432     /* for 2 (or all) first level don't care abour uppercase/lowercase */
00433     if ((gcomprisBoard->level < level_uppercase) &&
00434        (is_falling_letter(g_unichar_toupper(c)))){
00435       gc_im_reset();
00436       return TRUE;
00437     }
00438 
00439     string_passed = g_utf8_next_char (string_passed);
00440   }
00441 
00442   list_of_letters[0] = '\0';
00443 
00444   /* We have to loop to concat the letters */
00445   g_hash_table_foreach (letters_table,
00446                      (GHFunc) add_char,
00447                      list_of_letters);
00448 
00449   /* Log what happened, what was expected, what we got */
00450 
00451   gc_log_set_comment(gcomprisBoard, list_of_letters, str);
00452   g_free(str);
00453 
00454   return TRUE;
00455 }
00456 
00457 static gboolean
00458 is_our_board (GcomprisBoard *gcomprisBoard)
00459 {
00460   if (gcomprisBoard)
00461     {
00462       if(g_strcasecmp(gcomprisBoard->type, "gletters")==0)
00463        {
00464          /* Set the plugin entry */
00465          gcomprisBoard->plugin=&menu_bp;
00466 
00467          return TRUE;
00468        }
00469     }
00470   return FALSE;
00471 }
00472 
00473 
00474 /*-------------------------------------------------------------------------------*/
00475 /*-------------------------------------------------------------------------------*/
00476 /*-------------------------------------------------------------------------------*/
00477 /*-------------------------------------------------------------------------------*/
00478 
00479 /* set initial values for the next level */
00480 static void gletters_next_level()
00481 {
00482 
00483   gamewon = FALSE;
00484   gc_bar_set_level(gcomprisBoard);
00485 
00486   gletters_destroy_all_items();
00487 
00488   /* Try the next level */
00489   speed=fallRateBase+(fallRateMult/gcomprisBoard->level);
00490   fallSpeed=dropRateBase+(dropRateMult/gcomprisBoard->level);
00491 
00492   gcomprisBoard->sublevel=1;
00493   gc_score_set(gcomprisBoard->sublevel);
00494 }
00495 
00496 
00497 static void gletters_move_item(GnomeCanvasItem *item)
00498 {
00499   double x1, y1, x2, y2;
00500 
00501   gnome_canvas_item_move(item, 0, 2.0);
00502 
00503   gnome_canvas_item_get_bounds    (item,
00504                                &x1,
00505                                &y1,
00506                                &x2,
00507                                &y2);
00508 
00509   if(y1>gcomprisBoard->height) {
00510     item2del_list = g_list_append (item2del_list, item);
00511     player_loose();
00512   }
00513 }
00514 
00515 static void gletters_destroy_item(GnomeCanvasItem *item)
00516 {
00517   gunichar *key;
00518 
00519   key = key_find_by_item(item);
00520 
00521   item_list = g_list_remove (item_list, item);
00522 
00523   item2del_list = g_list_remove (item2del_list, item);
00524 
00525   /* Remove old letter; this destroy the canvas item  */
00526   g_warning("destroying %d", *key);
00527   g_hash_table_remove (letters_table, key);
00528 
00529 }
00530 
00531 /* Destroy items that falls out of the canvas */
00532 static void gletters_destroy_items()
00533 {
00534   GnomeCanvasItem *item;
00535 
00536   while(g_list_length(item2del_list)>0)
00537     {
00538       item = g_list_nth_data(item2del_list, 0);
00539       gletters_destroy_item(item);
00540     }
00541 }
00542 
00543 /* Destroy all the items */
00544 static void gletters_destroy_all_items()
00545 {
00546   GnomeCanvasItem *item;
00547 
00548   if(item_list)
00549     while(g_list_length(item_list)>0)
00550       {
00551        item = g_list_nth_data(item_list, 0);
00552        gletters_destroy_item(item);
00553       }
00554 
00555   /* Delete the letters_table */
00556   if(letters_table) {
00557     g_hash_table_destroy (letters_table);
00558     letters_table=NULL;
00559   }
00560 }
00561 
00562 /*
00563  * This does the moves of the game items on the play canvas
00564  *
00565  */
00566 static gint gletters_move_items (GtkWidget *widget, gpointer data)
00567 {
00568   g_list_foreach (item_list, (GFunc) gletters_move_item, NULL);
00569 
00570   /* Destroy items that falls out of the canvas */
00571   gletters_destroy_items();
00572 
00573   dummy_id = gtk_timeout_add (speed,
00574                            (GtkFunction) gletters_move_items, NULL);
00575 
00576   return(FALSE);
00577 }
00578 
00579 
00580 void destroy_canvas_item(gpointer item)
00581 {
00582   //g_free(g_object_get_data (G_OBJECT(item),"unichar_key"));
00583   //g_free(g_object_get_data (G_OBJECT(item),"utf8_key"));
00584   gtk_object_destroy (GTK_OBJECT(item));
00585 }
00586 
00587 static GnomeCanvasItem *gletters_create_item(GnomeCanvasGroup *parent)
00588 {
00589   GnomeCanvasItem *item;
00590   gint i,j,k;
00591   guint x;
00592   gunichar *lettersItem;
00593   gchar *str_p, *letter;
00594 
00595   if (!letters_table)
00596     {
00597       letters_table = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, destroy_canvas_item);
00598     }
00599 
00600   /* Beware, since we put the letters in a hash table, we do not allow the same
00601    * letter to be displayed two times
00602    */
00603 
00604   g_warning("dump: %d, %s\n",gcomprisBoard->level,letters_array[gcomprisBoard->level-1]);
00605 
00606   k = g_utf8_strlen(letters_array[gcomprisBoard->level-1],-1);
00607 
00608   lettersItem = g_new(gunichar,1);
00609   gint attempt=0;
00610   do
00611     {
00612       attempt++;
00613       str_p = letters_array[gcomprisBoard->level-1];
00614       i = (int)((float)k*rand()/(RAND_MAX+1.0));
00615 
00616       for(j = 0; j < i; j++)
00617        {
00618          str_p=g_utf8_next_char(str_p);
00619        }
00620 
00621       *lettersItem = g_utf8_get_char (str_p);
00622 
00623     } while((attempt<MAX_RAND_ATTEMPTS) && (item_find_by_title(lettersItem)!=NULL));
00624 
00625   if (item_find_by_title(lettersItem)!=NULL)
00626     {
00627       g_free(lettersItem);
00628       return NULL;
00629     }
00630 
00631   letter = g_new0(gchar, 6);
00632   g_unichar_to_utf8 ( *lettersItem, letter);
00633 
00634   if (with_sound)
00635     {
00636       gchar *str2 = NULL;
00637       gchar *letter_unichar_name = gc_sound_alphabet(letter);
00638 
00639       str2 = g_strdup_printf("sounds/$LOCALE/alphabet/%s", letter_unichar_name);
00640 
00641       gc_sound_play_ogg(str2, NULL);
00642 
00643       g_free(letter_unichar_name);
00644       g_free(str2);
00645     }
00646 
00647   item =                                  \
00648     gnome_canvas_item_new (parent,
00649                         gnome_canvas_group_get_type (),
00650                         "x", (double) 0,
00651                         "y", (double) -12,
00652                         NULL);
00653 
00654   x = 80 + (int)((float)(gcomprisBoard->width-160)*rand()/(RAND_MAX+1.0));
00655   gnome_canvas_item_new (GNOME_CANVAS_GROUP(item),
00656                       gnome_canvas_text_get_type (),
00657                       "text", letter,
00658                       "font", gc_skin_font_board_huge_bold,
00659                       "x", (double) x,
00660                       "y", (double) -20,
00661                       "anchor", GTK_ANCHOR_CENTER,
00662                       "fill_color_rgba", 0x8c8cFFFF,
00663                       NULL);
00664   x -= 2;
00665   gnome_canvas_item_new (GNOME_CANVAS_GROUP(item),
00666                       gnome_canvas_text_get_type (),
00667                       "text", letter,
00668                       "font", gc_skin_font_board_huge_bold,
00669                       "x", (double) x,
00670                       "y", (double) -22,
00671                       "anchor", GTK_ANCHOR_CENTER,
00672                       "fill_color_rgba", 0x254c87FF,
00673                       NULL);
00674 
00675   g_object_set_data (G_OBJECT(item), "unichar_key", lettersItem);
00676   g_object_set_data (G_OBJECT(item), "utf8_key", letter);
00677 
00678   item_list = g_list_append (item_list, item);
00679 
00680   /* Add letter to hash table of all falling letters. */
00681   g_hash_table_insert (letters_table, lettersItem, item);
00682 
00683   g_free(letter);
00684 
00685   g_warning("done\n");
00686 
00687   return (item);
00688 }
00689 
00690 static void gletters_add_new_item()
00691 {
00692   gletters_create_item(gnome_canvas_root(gcomprisBoard->canvas));
00693 }
00694 
00695 /*
00696  * This is called on a low frequency and is used to drop new items
00697  *
00698  */
00699 static gint gletters_drop_items (GtkWidget *widget, gpointer data)
00700 {
00701   gletters_add_new_item();
00702 
00703   drop_items_id = gtk_timeout_add (fallSpeed,
00704                                (GtkFunction) gletters_drop_items, NULL);
00705   return (FALSE);
00706 }
00707 
00708 static void player_win(GnomeCanvasItem *item)
00709 {
00710   g_message("in player_win\n");
00711 
00712   gletters_destroy_item(item);
00713   gc_sound_play_ogg ("sounds/gobble.ogg", NULL);
00714 
00715   gcomprisBoard->sublevel++;
00716 
00717   if(gcomprisBoard->sublevel > gcomprisBoard->number_of_sublevel)
00718     {
00719       /* Try the next level */
00720       gcomprisBoard->level++;
00721       if(gcomprisBoard->level>gcomprisBoard->maxlevel) { // the current board is finished : bail out
00722         gc_score_end();
00723        gc_bonus_end_display(BOARD_FINISHED_RANDOM);
00724        return;
00725       }
00726 
00727       gamewon = TRUE;
00728       gletters_destroy_all_items();
00729       gc_bonus_display(gamewon, BONUS_SMILEY);
00730     }
00731   else
00732     {
00733       gc_score_set(gcomprisBoard->sublevel);
00734 
00735       /* Drop a new item now to speed up the game */
00736       if(g_list_length(item_list)==0)
00737        {
00738          if (drop_items_id) {
00739            /* Remove pending new item creation to sync the falls */
00740            gtk_timeout_remove (drop_items_id);
00741            drop_items_id = 0;
00742          }
00743          if(!drop_items_id) {
00744            drop_items_id = gtk_timeout_add (0,
00745                                         (GtkFunction) gletters_drop_items, NULL);
00746          }
00747        }
00748     }
00749   g_warning("leaving player_win\n");
00750 }
00751 
00752 static void player_loose()
00753 {
00754   g_warning("entering player_loose\n");
00755 
00756   gc_sound_play_ogg ("sounds/crash.ogg", NULL);
00757   g_warning("leaving player_loose\n");
00758 }
00759 
00760 static gunichar *
00761 key_find_by_item (const GnomeCanvasItem *item)
00762 {
00763   return g_object_get_data (G_OBJECT(item), "unichar_key");
00764 }
00765 
00766 static GnomeCanvasItem *
00767 item_find_by_title (const gunichar *title)
00768 {
00769   if (!letters_table)
00770     return NULL;
00771 
00772   return g_hash_table_lookup (letters_table, title);
00773 }
00774 
00775 
00776 /***********************************
00777 ************************************
00778     Config
00779 ************************************/
00780 
00781 /* ======================= */
00782 /* = config_start        = */
00783 /* ======================= */
00784 
00785 static GcomprisProfile *profile_conf;
00786 static GcomprisBoard   *board_conf;
00787 
00788 static void save_table (gpointer key,
00789                      gpointer value,
00790                      gpointer user_data)
00791 {
00792   gc_db_set_board_conf ( profile_conf,
00793                          board_conf,
00794                          (gchar *) key,
00795                          (gchar *) value);
00796 }
00797 
00798 /* a GcomprisConfCallback
00799  */
00800 static void conf_ok(GHashTable *table)
00801 {
00802   if (!table){
00803     if (gcomprisBoard)
00804       pause_board(FALSE);
00805     return;
00806   }
00807 
00808   g_hash_table_foreach(table, save_table, NULL);
00809 
00810   if (gcomprisBoard){
00811     gc_locale_reset();
00812 
00813     GHashTable *config;
00814 
00815     if (profile_conf)
00816       config = gc_db_get_board_conf();
00817     else
00818       config = table;
00819 
00820     gc_locale_set(g_hash_table_lookup( config, "locale"));
00821 
00822     gchar *up_init_str = g_hash_table_lookup( config, "uppercase_only");
00823 
00824     if (up_init_str && (strcmp(up_init_str, "True")==0))
00825       uppercase_only = TRUE;
00826     else
00827       uppercase_only = FALSE;
00828 
00829     gchar *control_sound = g_hash_table_lookup( config, "with_sound");
00830 
00831     if (control_sound && strcmp(g_hash_table_lookup( config, "with_sound"),"True")==0)
00832       with_sound = TRUE;
00833     else
00834       with_sound = FALSE;
00835 
00836     if (profile_conf)
00837       g_hash_table_destroy(config);
00838 
00839     load_default_charset();
00840 
00841     level_set_score();
00842     gletters_next_level();
00843 
00844     pause_board(FALSE);
00845 
00846   }
00847 
00848   board_conf = NULL;
00849   profile_conf = NULL;
00850 
00851 }
00852 
00853 static void
00854 gletter_config_start(GcomprisBoard *agcomprisBoard,
00855                   GcomprisProfile *aProfile)
00856 {
00857   board_conf = agcomprisBoard;
00858   profile_conf = aProfile;
00859 
00860   gchar *label;
00861 
00862   if (gcomprisBoard)
00863     pause_board(TRUE);
00864 
00865   label = g_strdup_printf("<b>%s</b> configuration\n for profile <b>%s</b>",
00866                        agcomprisBoard->name, aProfile ? aProfile->name : "");
00867 
00868   gc_board_config_window_display(label, (GcomprisConfCallback )conf_ok);
00869 
00870   g_free(label);
00871 
00872   /* init the combo to previously saved value */
00873   GHashTable *config = gc_db_get_conf( profile_conf, board_conf);
00874 
00875   gchar *locale = g_hash_table_lookup( config, "locale");
00876 
00877   gc_board_config_combo_locales( locale);
00878 
00879   gboolean up_init = FALSE;
00880 
00881   gchar *up_init_str = g_hash_table_lookup( config, "uppercase_only");
00882 
00883   if (up_init_str && (strcmp(up_init_str, "True")==0))
00884     up_init = TRUE;
00885 
00886   gc_board_conf_separator();
00887 
00888   gchar *control_sound = g_hash_table_lookup( config, "with_sound");
00889   if (control_sound && strcmp(g_hash_table_lookup( config, "with_sound"),"True")==0)
00890     with_sound = TRUE;
00891   else
00892     with_sound = FALSE;
00893 
00894   gc_board_config_boolean_box("Enable sounds", "with_sound", with_sound);
00895 
00896   gc_board_conf_separator();
00897 
00898   gc_board_config_boolean_box(_("Uppercase only text"),
00899                      "uppercase_only",
00900                      up_init);
00901 
00902 }
00903 
00904 
00905 /* ======================= */
00906 /* = config_stop        = */
00907 /* ======================= */
00908 static void
00909 gletter_config_stop()
00910 {
00911 }