gcompris r3722 - in trunk: . boards/missing_letter src/boards src/gcompris



Author: bcoudoin
Date: Mon Feb 16 23:32:03 2009
New Revision: 3722
URL: http://svn.gnome.org/viewvc/gcompris?rev=3722&view=rev

Log:

	- Miquel DE IZARRA Added support for editing the content
	  of the missing letter activity.


Added:
   trunk/boards/missing_letter/board2.xml.in
   trunk/boards/missing_letter/board3.xml.in
   trunk/boards/missing_letter/board4.xml.in
   trunk/src/boards/missingletter_config.c
Modified:
   trunk/ChangeLog
   trunk/boards/missing_letter/Makefile.am
   trunk/boards/missing_letter/board1.xml.in
   trunk/src/boards/Makefile.am
   trunk/src/boards/missingletter.c
   trunk/src/boards/reading.c
   trunk/src/gcompris/board_config_wordlist.c
   trunk/src/gcompris/gc_net.c
   trunk/src/gcompris/gc_net.h
   trunk/src/gcompris/gcompris.c

Modified: trunk/boards/missing_letter/Makefile.am
==============================================================================
--- trunk/boards/missing_letter/Makefile.am	(original)
+++ trunk/boards/missing_letter/Makefile.am	Mon Feb 16 23:32:03 2009
@@ -2,7 +2,10 @@
 xmldir = $(pkgdatadir)/@PACKAGE_DATA_DIR@/missing_letter
 
 xml_in_files = \
-	board1.xml.in
+	board1.xml.in \
+	board2.xml.in \
+	board3.xml.in \
+	board4.xml.in
 
 xml_DATA = $(xml_in_files:.xml.in=.xml)
 

Modified: trunk/boards/missing_letter/board1.xml.in
==============================================================================
--- trunk/boards/missing_letter/board1.xml.in	(original)
+++ trunk/boards/missing_letter/board1.xml.in	Mon Feb 16 23:32:03 2009
@@ -36,113 +36,5 @@
   	<pixmapfile>imageid/bed.png</pixmapfile>
 	<_data>bed/_ed/b/l/f</_data>
   </Board>
-  <Board>
-  	<pixmapfile>imageid/bottle.png</pixmapfile>
-	<_data>bottle/_ottle/b/t/p</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/cake.png</pixmapfile>
-	<_data>cake/_ake/c/p/d</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/ballon.png</pixmapfile>
-	<_data>ball/_all/b/p/d</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/avion.png</pixmapfile>
-	<_data>plane/p_ane/l/j/i</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/chien.png</pixmapfile>
-	<_data>dog/d_g/o/g/a</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/fish.png</pixmapfile>
-	<_data>fish/_ish/f/h/l</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/car.png</pixmapfile>
-	<_data>car/_ar/c/k/b</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/cartable.png</pixmapfile>
-	<_data>satchel/_atchel/s/c/l</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/banana.png</pixmapfile>
-	<_data>banana/_anana/b/p/d</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/maison.png</pixmapfile>
-	<_data>house/h_use/o/f/u</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/pomme.png</pixmapfile>
-	<_data>apple/appl_/e/h/a</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/bed.png</pixmapfile>
-	<_data>bed/b_d/e/a/i</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/bottle.png</pixmapfile>
-	<_data>bottle/b_ttle/o/u/d</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/cake.png</pixmapfile>
-	<_data>cake/c_ke/a/o/e</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/ballon.png</pixmapfile>
-	<_data>ball/b_ll/a/u/o</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/avion.png</pixmapfile>
-	<_data>plane/pl_ne/a/o/s</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/chien.png</pixmapfile>
-	<_data>dog/do_/g/p/q</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/fish.png</pixmapfile>
-	<_data>fish/fis_/h/o/i</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/car.png</pixmapfile>
-	<_data>car/ca_/r/w/k</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/cartable.png</pixmapfile>
-	<_data>satchel/sa_chel/t/p/c</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/banana.png</pixmapfile>
-	<_data>banana/ba_ana/n/m/b</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/maison.png</pixmapfile>
-	<_data>house/_ouse/h/e/j</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/pomme.png</pixmapfile>
-	<_data>apple/app_e/l/h/n</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/bed.png</pixmapfile>
-	<_data>bed/be_/d/p/b</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/bottle.png</pixmapfile>
-	<_data>bottle/bott_e/l/y/r</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/cake.png</pixmapfile>
-	<_data>cake/ca_e/k/q/c</_data>
-  </Board>
-  <Board>
-  	<pixmapfile>imageid/ballon.png</pixmapfile>
-	<_data>ball/bal_/l/h/s</_data>
-  </Board>
 </missing_letter>
 

Added: trunk/boards/missing_letter/board2.xml.in
==============================================================================
--- (empty file)
+++ trunk/boards/missing_letter/board2.xml.in	Mon Feb 16 23:32:03 2009
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<missing_letter>
+  <Board>
+  	<pixmapfile>imageid/bottle.png</pixmapfile>
+	<_data>bottle/_ottle/b/t/p</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/cake.png</pixmapfile>
+	<_data>cake/_ake/c/p/d</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/ballon.png</pixmapfile>
+	<_data>ball/_all/b/p/d</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/avion.png</pixmapfile>
+	<_data>plane/p_ane/l/j/i</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/chien.png</pixmapfile>
+	<_data>dog/d_g/o/g/a</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/fish.png</pixmapfile>
+	<_data>fish/_ish/f/h/l</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/car.png</pixmapfile>
+	<_data>car/_ar/c/k/b</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/cartable.png</pixmapfile>
+	<_data>satchel/_atchel/s/c/l</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/banana.png</pixmapfile>
+	<_data>banana/_anana/b/p/d</_data>
+  </Board>
+</missing_letter>
+

Added: trunk/boards/missing_letter/board3.xml.in
==============================================================================
--- (empty file)
+++ trunk/boards/missing_letter/board3.xml.in	Mon Feb 16 23:32:03 2009
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<missing_letter>
+  <Board>
+  	<pixmapfile>imageid/maison.png</pixmapfile>
+	<_data>house/h_use/o/f/u</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/pomme.png</pixmapfile>
+	<_data>apple/appl_/e/h/a</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/bed.png</pixmapfile>
+	<_data>bed/b_d/e/a/i</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/bottle.png</pixmapfile>
+	<_data>bottle/b_ttle/o/u/d</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/cake.png</pixmapfile>
+	<_data>cake/c_ke/a/o/e</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/ballon.png</pixmapfile>
+	<_data>ball/b_ll/a/u/o</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/avion.png</pixmapfile>
+	<_data>plane/pl_ne/a/o/s</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/chien.png</pixmapfile>
+	<_data>dog/do_/g/p/q</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/fish.png</pixmapfile>
+	<_data>fish/fis_/h/o/i</_data>
+  </Board>
+</missing_letter>
+

Added: trunk/boards/missing_letter/board4.xml.in
==============================================================================
--- (empty file)
+++ trunk/boards/missing_letter/board4.xml.in	Mon Feb 16 23:32:03 2009
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<missing_letter>
+  <Board>
+  	<pixmapfile>imageid/car.png</pixmapfile>
+	<_data>car/ca_/r/w/k</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/cartable.png</pixmapfile>
+	<_data>satchel/sa_chel/t/p/c</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/banana.png</pixmapfile>
+	<_data>banana/ba_ana/n/m/b</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/maison.png</pixmapfile>
+	<_data>house/_ouse/h/e/j</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/pomme.png</pixmapfile>
+	<_data>apple/app_e/l/h/n</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/bed.png</pixmapfile>
+	<_data>bed/be_/d/p/b</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/bottle.png</pixmapfile>
+	<_data>bottle/bott_e/l/y/r</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/cake.png</pixmapfile>
+	<_data>cake/ca_e/k/q/c</_data>
+  </Board>
+  <Board>
+  	<pixmapfile>imageid/ballon.png</pixmapfile>
+	<_data>ball/bal_/l/h/s</_data>
+  </Board>
+</missing_letter>
+

Modified: trunk/src/boards/Makefile.am
==============================================================================
--- trunk/src/boards/Makefile.am	(original)
+++ trunk/src/boards/Makefile.am	Mon Feb 16 23:32:03 2009
@@ -161,7 +161,7 @@
 
 libmissingletter_la_LDFLAGS = $(shared) $(no_undefined) -module -avoid-version $(gc_libs) $(XML_LIBS)
 libmissingletter_la_LIBADD =
-libmissingletter_la_SOURCES = missingletter.c
+libmissingletter_la_SOURCES = missingletter.c missingletter_config.c
 
 
 libclick_on_letter_la_LDFLAGS = $(shared) $(no_undefined) -module -avoid-version $(gc_libs)

Modified: trunk/src/boards/missingletter.c
==============================================================================
--- trunk/src/boards/missingletter.c	(original)
+++ trunk/src/boards/missingletter.c	Mon Feb 16 23:32:03 2009
@@ -26,7 +26,7 @@
 
 #define SOUNDLISTFILE PACKAGE
 
-static GcomprisBoard *gcomprisBoard = NULL;
+GcomprisBoard *gcomprisBoard_missing = NULL;
 static gboolean board_paused = TRUE;
 
 static void		 start_board (GcomprisBoard *agcomprisBoard);
@@ -42,6 +42,9 @@
 					     GcomprisProfile *aProfile);
 static void		 config_stop(void);
 
+/* from missingletter_config.c */
+void config_missing_letter(GcomprisBoardConf *config);
+
 typedef struct _Board Board;
 struct _Board {
   char  *pixmapfile;
@@ -55,12 +58,10 @@
 static Board * board;
 
 /* XML */
-static gboolean		 read_xml_file(char *fname);
 static void		 init_xml(void);
-static void		 add_xml_data(xmlDocPtr, xmlNodePtr, GNode *);
-static void		 parse_doc(xmlDocPtr doc);
-static gboolean		 read_xml_file(char *fname);
-static void		 destroy_board_list();
+static void		 add_xml_data(xmlDocPtr, xmlNodePtr, GList**);
+gboolean		 missing_read_xml_file(char *fname, GList**);
+void			 missing_destroy_board_list(GList *);
 static void		 destroy_board(Board * board);
 
 /* This is the list of boards */
@@ -69,12 +70,7 @@
 #define VERTICAL_SEPARATION 30
 #define HORIZONTAL_SEPARATION 30
 
-//NUMBER_OF_SUBLEVELS*NUMBER_OF_LEVELS must equal the number of boards in XML file
-#define NUMBER_OF_SUBLEVELS 9
-#define NUMBER_OF_LEVELS 4
-
 /* ================================================================ */
-static int board_number; // between 0 and board_list.length-1
 static int right_word; // between 1 and 3, indicates which choice is the right one (the player clicks on it
 
 static GnomeCanvasGroup *boardRootItem = NULL;
@@ -131,7 +127,7 @@
  */
 static void pause_board (gboolean pause)
 {
-  if(gcomprisBoard==NULL)
+  if(gcomprisBoard_missing==NULL)
     return;
 
   gc_bar_hide(FALSE);
@@ -149,6 +145,7 @@
 static void start_board (GcomprisBoard *agcomprisBoard)
 {
   GHashTable *config = gc_db_get_board_conf();
+  gchar * filename;
 
   gc_locale_set(g_hash_table_lookup( config, "locale"));
 
@@ -156,19 +153,23 @@
 
   if(agcomprisBoard!=NULL)
     {
-      gcomprisBoard=agcomprisBoard;
-      gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),
+      gcomprisBoard_missing=agcomprisBoard;
+      gc_set_background(gnome_canvas_root(gcomprisBoard_missing->canvas),
 			"opt/missingletter-bg.jpg");
-      gcomprisBoard->level=1;
-      gcomprisBoard->maxlevel=NUMBER_OF_LEVELS;
-      gcomprisBoard->sublevel=1;
-      gcomprisBoard->number_of_sublevel=NUMBER_OF_SUBLEVELS; /* Go to next level after this number of 'play' */
+      gcomprisBoard_missing->level=1;
+
+      /* Calculate the maxlevel based on the available data file for this board */
+      gcomprisBoard_missing->maxlevel = 1;
+      while((filename = gc_file_find_absolute("%s/board%d.xml",
+      	gcomprisBoard_missing->boarddir, ++gcomprisBoard_missing->maxlevel)))
+	  g_free(filename);
+
+      gcomprisBoard_missing->maxlevel--;
+
+      gcomprisBoard_missing->sublevel=1;
+      gcomprisBoard_missing->number_of_sublevel=G_MAXINT;
+
       init_xml();
-      g_assert(NUMBER_OF_LEVELS*NUMBER_OF_SUBLEVELS == g_list_length(board_list));
-      gc_score_start(SCORESTYLE_NOTE,
-			   50,
-			   gcomprisBoard->height - 50,
-			   gcomprisBoard->number_of_sublevel);
       gc_bar_set(GC_BAR_CONFIG | GC_BAR_LEVEL);
 
       missing_letter_next_level();
@@ -181,27 +182,29 @@
 static void end_board ()
 {
 
-  if(gcomprisBoard!=NULL)
+  if(gcomprisBoard_missing!=NULL)
     {
       pause_board(TRUE);
       gc_score_end();
       missing_letter_destroy_all_items();
-      destroy_board_list();
+      missing_destroy_board_list(board_list);
+      board_list = NULL;
     }
 
   gc_locale_reset();
 
-  gcomprisBoard = NULL;
+  gcomprisBoard_missing = NULL;
 }
 
 static void
 set_level (guint level)
 {
 
-  if(gcomprisBoard!=NULL)
+  if(gcomprisBoard_missing!=NULL)
     {
-      gcomprisBoard->level=level;
-      gcomprisBoard->sublevel=1;
+      gcomprisBoard_missing->level=level;
+      gcomprisBoard_missing->sublevel=1;
+      init_xml();
       missing_letter_next_level();
     }
 }
@@ -227,16 +230,16 @@
 /* set initial values for the next level */
 static void missing_letter_next_level()
 {
-  gc_bar_set_level(gcomprisBoard);
+  gc_bar_set_level(gcomprisBoard_missing);
 
   missing_letter_destroy_all_items();
   selected_button = NULL;
   gamewon = FALSE;
 
-  gc_score_set(gcomprisBoard->sublevel);
+  gc_score_set(gcomprisBoard_missing->sublevel);
 
   /* Try the next level */
-  missing_letter_create_item(gnome_canvas_root(gcomprisBoard->canvas));
+  missing_letter_create_item(gnome_canvas_root(gcomprisBoard_missing->canvas));
 
 }
 /* ==================================== */
@@ -267,27 +270,24 @@
   gint txt_area_x = 515;
   gint txt_area_y = 435;
 
-  board_number = (gcomprisBoard->level-1) * NUMBER_OF_SUBLEVELS + gcomprisBoard->sublevel-1;
-
-  g_assert(board_number >= 0  && board_number < g_list_length(board_list));
   place = g_random_int_range( 0, 3);
   g_assert(place >= 0  && place < 3);
 
   right_word = place+1;
 
   boardRootItem = GNOME_CANVAS_GROUP(
-				     gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
+				     gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard_missing->canvas),
 							    gnome_canvas_group_get_type (),
 							    "x", (double) 0,
 							    "y", (double) 0,
 							    NULL));
   button_pixmap = gc_skin_pixmap_load("button.png");
   /* display the image */
-  board = g_list_nth_data(board_list, board_number);
+  board = g_list_nth_data(board_list, gcomprisBoard_missing->sublevel-1);
   g_assert(board != NULL);
   pixmap = gc_pixmap_load(board->pixmapfile);
 
-  yOffset = (gcomprisBoard->height - gdk_pixbuf_get_height(button_pixmap) - gdk_pixbuf_get_height(pixmap) - 2*VERTICAL_SEPARATION)/2;
+  yOffset = (gcomprisBoard_missing->height - gdk_pixbuf_get_height(button_pixmap) - gdk_pixbuf_get_height(pixmap) - 2*VERTICAL_SEPARATION)/2;
 
   text_s = gnome_canvas_item_new (boardRootItem,
 				gnome_canvas_text_get_type (),
@@ -344,7 +344,7 @@
     break;
   }
 
-  yOffset = ( gcomprisBoard->height - 3*gdk_pixbuf_get_height(button_pixmap) - 2*VERTICAL_SEPARATION) / 2;
+  yOffset = ( gcomprisBoard_missing->height - 3*gdk_pixbuf_get_height(button_pixmap) - 2*VERTICAL_SEPARATION) / 2;
   xOffset = (img_area_x-gdk_pixbuf_get_width(button_pixmap))/2;
   button1 = gnome_canvas_item_new (boardRootItem,
 				   gnome_canvas_pixbuf_get_type (),
@@ -437,13 +437,15 @@
 }
 /* ==================================== */
 static void game_won() {
-  gcomprisBoard->sublevel++;
+  gcomprisBoard_missing->sublevel++;
 
-  if(gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) {
+  if(gcomprisBoard_missing->sublevel>gcomprisBoard_missing->number_of_sublevel) {
     /* Try the next level */
-    gcomprisBoard->sublevel=1;
-    gcomprisBoard->level++;
-    if(gcomprisBoard->level>gcomprisBoard->maxlevel) {
+    gcomprisBoard_missing->sublevel=1;
+    gcomprisBoard_missing->level++;
+    init_xml();
+
+    if(gcomprisBoard_missing->level>gcomprisBoard_missing->maxlevel) {
 	gc_bonus_end_display(GC_BOARD_FINISHED_TUXPLANE);
 	return;
     }
@@ -562,16 +564,27 @@
 {
   char *filename;
 
-  filename = gc_file_find_absolute("%s/board1.xml",
-				   gcomprisBoard->boarddir);
-
-  g_assert(read_xml_file(filename)== TRUE);
-
+  if(board_list)
+  {
+    missing_destroy_board_list(board_list);
+    board_list = NULL;
+  }
+  filename = gc_file_find_absolute("%s/board%d.xml",
+				   gcomprisBoard_missing->boarddir,
+				   gcomprisBoard_missing->level);
+  missing_read_xml_file(filename, &board_list);
+  gcomprisBoard_missing->number_of_sublevel = g_list_length(board_list);
   g_free(filename);
+
+  gc_score_end();
+  gc_score_start(SCORESTYLE_NOTE,
+		  50,
+		  gcomprisBoard_missing->height - 50,
+		  gcomprisBoard_missing->number_of_sublevel);
 }
 
 /* ==================================== */
-static void add_xml_data(xmlDocPtr doc, xmlNodePtr xmlnode, GNode * child)
+static void add_xml_data(xmlDocPtr doc, xmlNodePtr xmlnode, GList **list)
 {
   gchar *pixmapfile = NULL;
   gchar *question = NULL, *answer = NULL;
@@ -593,22 +606,17 @@
       {
 	if(data==NULL)
 	  {
-	    data = gettext((gchar *)xmlNodeListGetString(doc, xmlnode->xmlChildrenNode, 1));
+	    gchar *tmp;
+	    tmp = (gchar *)xmlNodeListGetString(doc, xmlnode->xmlChildrenNode, 1);
+	    data = g_strdup(gettext(tmp));
+	    g_free(tmp);
 	  }
       }
     xmlnode = xmlnode->next;
   }
 
-  // I really don't know why this test, but otherwise, the list is doubled
-  // with 1 line on 2 filled with NULL elements
-  if ( pixmapfile == NULL || data == NULL)
-    return;
-
-/*  if ((i=sscanf(data, "%s / %s / %s / %s / %s", answer, question, l1, l2, l3)) != 5)
-		printf("Error sscanf result != 5 = %i\n",i);
-*/
   gchar **all_answer = g_strsplit(data, "/", 5);
-  /* Dont free data, it's a gettext static message */
+  g_free(data);
 
   answer = all_answer[0];
   question = all_answer[1];
@@ -627,28 +635,18 @@
 
   g_strfreev(all_answer);
 
-  board_list = g_list_append (board_list, board);
+  *list = g_list_append (*list, board);
 }
 
-/* ==================================== */
-static void parse_doc(xmlDocPtr doc)
-{
-  xmlNodePtr node;
-
-  for(node = doc->children->children; node != NULL; node = node->next) {
-    if ( g_strcasecmp((gchar *)node->name, "Board") == 0 )
-      add_xml_data(doc, node,NULL);
-  }
-
-}
 
 /* ==================================== */
 /* read an xml file into our memory structures and update our view,
    dump any old data we have in memory if we can load a new set */
-static gboolean read_xml_file(char *fname)
+gboolean missing_read_xml_file(char *fname, GList **list)
 {
   /* pointer to the new doc */
   xmlDocPtr doc;
+  xmlNodePtr node;
 
   g_return_val_if_fail(fname!=NULL,FALSE);
 
@@ -669,17 +667,21 @@
     return FALSE;
   }
 
-  parse_doc(doc);
+  for(node = doc->children->children; node != NULL; node = node->next) {
+    if ( g_strcasecmp((gchar *)node->name, "Board") == 0 )
+      add_xml_data(doc, node, list);
+  }
   xmlFreeDoc(doc);
   return TRUE;
 }
+
 /* ======================================= */
-static void destroy_board_list() {
+void missing_destroy_board_list(GList *list) {
   Board *board;
-  while(g_list_length(board_list)>0)
+  while(g_list_length(list)>0)
     {
-      board = g_list_nth_data(board_list, 0);
-      board_list = g_list_remove (board_list, board);
+      board = g_list_nth_data(list, 0);
+      list = g_list_remove (list, board);
       destroy_board(board);
     }
 }
@@ -721,14 +723,14 @@
 static GcomprisConfCallback conf_ok(GHashTable *table)
 {
   if (!table){
-    if (gcomprisBoard)
+    if (gcomprisBoard_missing)
       pause_board(FALSE);
     return NULL;
   }
 
   g_hash_table_foreach(table, (GHFunc) save_table, NULL);
 
-  if (gcomprisBoard){
+  if (gcomprisBoard_missing){
     gc_locale_reset();
 
     GHashTable *config;
@@ -743,8 +745,6 @@
     if (profile_conf)
       g_hash_table_destroy(config);
 
-    destroy_board_list();
-
     init_xml();
 
     missing_letter_next_level();
@@ -753,6 +753,7 @@
 
     board_conf = NULL;
   profile_conf = NULL;
+  pause_board(FALSE);
 
   return NULL;
 }
@@ -764,7 +765,7 @@
   board_conf = agcomprisBoard;
   profile_conf = aProfile;
 
-  if (gcomprisBoard)
+  if (gcomprisBoard_missing)
     pause_board(TRUE);
 
   gchar *label = g_strdup_printf(_("<b>%s</b> configuration\n for profile <b>%s</b>"),
@@ -782,7 +783,7 @@
   gchar *locale = g_hash_table_lookup( config, "locale");
 
   gc_board_config_combo_locales(bconf, locale);
-
+  config_missing_letter(bconf);
 }
 
 

Added: trunk/src/boards/missingletter_config.c
==============================================================================
--- (empty file)
+++ trunk/src/boards/missingletter_config.c	Mon Feb 16 23:32:03 2009
@@ -0,0 +1,599 @@
+#include "gcompris/gcompris.h"
+#include <string.h>
+
+/* from missingletter.c */
+typedef struct _Board Board;
+struct _Board {
+  char  *pixmapfile;
+  char *question;
+  char *answer;
+  char  *l1;
+  char  *l2;
+  char  *l3;
+  };
+
+extern GcomprisBoard *gcomprisBoard_missing;
+gboolean              missing_read_xml_file(char *fname, GList**);
+void                  missing_destroy_board_list(GList *);
+
+typedef struct
+  {
+    GtkComboBox *combo_level;
+    GtkTreeView *view;
+
+    GtkFileChooserButton *pixmap;
+    GtkEntry *question, *answer, *choice;
+    gboolean changed;
+  } _config_missing;
+
+enum
+  {
+    QUESTION_COLUMN,
+    ANSWER_COLUMN,
+    CHOICE_COLUMN,
+    PIXMAP_COLUMN,
+    PIXBUF_COLUMN,
+    N_COLUMNS
+  };
+
+#define ICON_SIZE 32
+
+static void new_clicked(GtkButton *b, gpointer data)
+{
+  _config_missing *u = (_config_missing*)data;
+  GtkListStore *ls;
+  GtkTreeIter iter;
+
+  ls = GTK_LIST_STORE(gtk_tree_view_get_model(u->view));
+  gtk_list_store_append(ls, &iter);
+  gtk_list_store_set(ls, &iter,
+                     QUESTION_COLUMN, "",
+                     ANSWER_COLUMN, "",
+                     CHOICE_COLUMN, "",
+                     PIXMAP_COLUMN, "",
+                     PIXBUF_COLUMN, NULL,
+                     -1);
+  GtkTreeSelection* sel = gtk_tree_view_get_selection(u->view);
+  gtk_tree_selection_select_iter(sel , &iter);
+}
+
+static void delete_clicked(GtkButton *b, gpointer data)
+{
+  _config_missing *u = (_config_missing*)data;
+  GtkTreeSelection *selection = gtk_tree_view_get_selection(u->view);
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+
+  if (gtk_tree_selection_get_selected (selection, &model, &iter))
+    {
+      gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
+      u->changed = TRUE;
+    }
+}
+
+static gboolean valid_entry(gchar *question, gchar *answer,
+			    gchar *choice, gchar *pixmap)
+{
+  gboolean result=FALSE;
+  gchar **split;
+
+  if(choice && question && answer && pixmap &&
+     strlen(choice)==3 && strlen(question) && strlen(answer)
+     && strchr(question, '_'))
+    {
+      split = g_strsplit(question, "_", 2);
+      if(g_str_has_prefix(answer, split[0]) &&
+         g_str_has_suffix(answer, split[1]) &&
+         answer[strlen(split[0])] == choice[0])
+        result = TRUE;
+      g_strfreev(split);
+    }
+  return result;
+}
+
+static void apply_clicked(GtkButton *b, gpointer data)
+{
+  _config_missing *u = (_config_missing*)data;
+  const gchar *question, *answer, *choice;
+  gchar *pixmap, *pixfile;
+  GtkTreeSelection *selection = gtk_tree_view_get_selection(u->view);
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+
+  question = gtk_entry_get_text(u->question);
+  answer = gtk_entry_get_text(u->answer);
+  choice = gtk_entry_get_text(u->choice);
+  pixmap = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(u->pixmap));
+
+  if(valid_entry((gchar*)question, (gchar*) answer, (gchar*)choice, pixmap))
+    {
+      if (gtk_tree_selection_get_selected (selection, &model, &iter))
+        {
+          pixfile = gc_cache_import_pixmap(pixmap, "imageid", 300, 300);
+          GdkPixbuf *pixbuf =
+	    gdk_pixbuf_new_from_file_at_size(pixmap, ICON_SIZE,
+					     ICON_SIZE, NULL);
+
+          gtk_list_store_set(GTK_LIST_STORE(model),&iter,
+                             QUESTION_COLUMN, question,
+                             ANSWER_COLUMN, answer,
+                             CHOICE_COLUMN, choice,
+                             PIXMAP_COLUMN, pixfile,
+                             PIXBUF_COLUMN, pixbuf,
+                             -1);
+          u->changed = TRUE;
+          g_free(pixfile);
+          g_object_unref(pixbuf);
+        }
+    }
+  g_free(pixmap);
+}
+
+static void up_clicked(GtkButton *b, gpointer data)
+{
+  _config_missing *u = (_config_missing*)data;
+  GtkTreeSelection *selection = gtk_tree_view_get_selection(u->view);
+  GtkTreeIter itera, iterb;
+  GtkTreeModel *model;
+  GtkTreePath *tpa, *tpb;
+  gchar *pa, *pb;
+
+  if (gtk_tree_selection_get_selected (selection, &model, &itera))
+    {
+      pa = gtk_tree_model_get_string_from_iter(model, &itera);
+      tpa = gtk_tree_path_new_from_string(pa);
+      tpb = gtk_tree_path_copy(tpa);
+      gtk_tree_path_prev(tpb);
+      pb = gtk_tree_path_to_string(tpb);
+      gtk_tree_model_get_iter_from_string(model, &iterb, pb);
+      gtk_list_store_swap(GTK_LIST_STORE(model), &itera, &iterb);
+      gtk_tree_path_free(tpa);
+      gtk_tree_path_free(tpb);
+      g_free(pa);
+      g_free(pb);
+      u->changed = TRUE;
+    }
+}
+
+static void down_clicked(GtkButton *b, gpointer data)
+{
+  _config_missing *u = (_config_missing*)data;
+  GtkTreeSelection *selection = gtk_tree_view_get_selection(u->view);
+  GtkTreeIter itera, iterb;
+  GtkTreeModel *model;
+  GtkTreePath *tpa, *tpb;
+  gchar *pa, *pb;
+
+  if (gtk_tree_selection_get_selected (selection, &model, &itera))
+    {
+      pa = gtk_tree_model_get_string_from_iter(model, &itera);
+      tpa = gtk_tree_path_new_from_string(pa);
+      tpb = gtk_tree_path_copy(tpa);
+      gtk_tree_path_next(tpb);
+      pb = gtk_tree_path_to_string(tpb);
+      if(gtk_tree_model_get_iter_from_string(model, &iterb, pb))
+        gtk_list_store_swap(GTK_LIST_STORE(model), &itera, &iterb);
+      gtk_tree_path_free(tpa);
+      gtk_tree_path_free(tpb);
+      g_free(pa);
+      g_free(pb);
+      u->changed = TRUE;
+    }
+}
+
+static gboolean _save(GtkTreeModel *model, GtkTreePath *path,
+                      GtkTreeIter *iter, gpointer data)
+{
+  gchar *question, *answer, *choice, *pixmap;
+  gchar *tmp = NULL;
+  xmlNodePtr root, node;
+
+  gtk_tree_model_get (model, iter,
+                      QUESTION_COLUMN, &question,
+                      ANSWER_COLUMN, &answer,
+                      CHOICE_COLUMN, &choice,
+                      PIXMAP_COLUMN, &pixmap,
+                      -1);
+  if(valid_entry(question, answer, choice, pixmap))
+    {
+      tmp = g_strdup_printf("%s/%s/%c/%c/%c",
+			    answer, question,
+			    choice[0], choice[1], choice[2]);
+
+      root =(xmlNodePtr)data;
+      node = xmlNewChild(root, NULL, BAD_CAST "Board", NULL);
+      xmlNewChild(node, NULL,BAD_CAST "pixmapfile", BAD_CAST pixmap);
+      xmlNewChild(node, NULL, BAD_CAST "data", BAD_CAST tmp);
+    }
+  g_free(tmp);
+  g_free(question);
+  g_free(answer);
+  g_free(choice);
+  return FALSE;
+}
+
+static void save_clicked(GtkButton *b, gpointer data)
+{
+  _config_missing *u = (_config_missing*)data;
+  GtkTreeModel *model;
+  gchar *filename;
+  xmlNodePtr root;
+  xmlDocPtr doc;
+  int level;
+
+  level = gtk_combo_box_get_active(u->combo_level)+1;
+  if(level==0)
+    return;
+  if(! u->changed)
+    return;
+  model = gtk_tree_view_get_model(u->view);
+  doc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
+  root = xmlNewNode(NULL, BAD_CAST "missing_letter");
+  xmlDocSetRootElement(doc,root);
+
+  gtk_tree_model_foreach(model, _save, root);
+
+  filename =
+    gc_file_find_absolute_writeable("%s/board%d.xml",
+				    gcomprisBoard_missing->boarddir, level);
+  if(xmlSaveFormatFileEnc(filename, doc, NULL, 1)<0)
+    g_warning("Fail to write %s", filename);
+  g_free(filename);
+  xmlFreeDoc(doc);
+  u->changed = FALSE;
+}
+
+static void level_changed(GtkComboBox *combo, gpointer data)
+{
+  _config_missing *u = (_config_missing*)data;
+  GtkListStore *ls;
+  GtkTreeIter iter;
+  gchar *filename;
+  GList *list=NULL, *l;
+  gchar *tmp;
+  int level, result;
+
+  level = gtk_combo_box_get_active(u->combo_level)+1;
+  if(level==0)
+    return;
+  if(u->changed)
+    {
+      GtkWidget *dialog;
+
+      dialog = gtk_dialog_new_with_buttons("Save changes ?",
+                                           NULL,
+                                           GTK_DIALOG_MODAL,
+                                           GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+                                           GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+                                           NULL);
+      result = gtk_dialog_run(GTK_DIALOG(dialog));
+      switch(result)
+        {
+        case GTK_RESPONSE_ACCEPT:
+          save_clicked(NULL, data);
+          break;
+        default:
+          u->changed=FALSE;
+          break;
+        }
+      gtk_widget_destroy (dialog);
+    }
+  ls = GTK_LIST_STORE(gtk_tree_view_get_model(u->view));
+  filename = gc_file_find_absolute("%s/board%d.xml",
+                                   gcomprisBoard_missing->boarddir, level);
+  missing_read_xml_file(filename,&list);
+  g_free(filename);
+  gtk_list_store_clear(ls);
+  for(l=list; l; l=l->next)
+    {
+      Board *b = l->data;
+      gchar *pixfile = gc_file_find_absolute(b->pixmapfile);
+      GdkPixbuf *pixbuf;
+
+      pixbuf =
+	gdk_pixbuf_new_from_file_at_size(pixfile, ICON_SIZE, ICON_SIZE,
+					 NULL);
+
+      tmp = g_strdup_printf("%s%s%s", b->l1, b->l2, b->l3);
+
+      gtk_list_store_append(ls, &iter);
+      gtk_list_store_set(ls, &iter,
+                         QUESTION_COLUMN, b->question,
+                         ANSWER_COLUMN, b->answer,
+                         CHOICE_COLUMN, tmp,
+                         PIXMAP_COLUMN, b->pixmapfile,
+                         PIXBUF_COLUMN, pixbuf,
+                         -1);
+      g_free(tmp);
+      g_free(pixfile);
+      g_object_unref(pixbuf);
+    }
+  missing_destroy_board_list(list);
+}
+
+static void text_changed(GtkWidget *widget, gpointer data)
+{
+  _config_missing *u = (_config_missing*)data;
+
+  const gchar *question, *answer, *choice;
+
+  question = gtk_entry_get_text(u->question);
+  answer = gtk_entry_get_text(u->answer);
+  choice = gtk_entry_get_text(u->choice);
+
+  if(widget == (GtkWidget*)u->answer)
+    {
+      if(g_str_has_prefix(answer,question))
+        {
+          gtk_entry_set_text(u->question,answer);
+        }
+    }
+  else if(widget ==(GtkWidget*) u->question)
+    {
+      if(strchr(question, '_'))
+        {
+          gchar ** split = g_strsplit(question,"_",2);
+          if(answer[strlen(split[0])]!= choice[0])
+            {
+              gchar *tmp;
+              tmp = g_new0(gchar, 4);
+              tmp[0]= answer[strlen(split[0])];
+              gtk_entry_set_text(u->choice, tmp);
+              g_free(tmp);
+            }
+          g_strfreev(split);
+        }
+    }
+}
+
+void selection_changed (GtkTreeSelection *selection,gpointer data)
+{
+  _config_missing *u = (_config_missing*)data;
+  gchar *question, *answer, *choice, *pixmap, *pixfile;
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+
+  if (gtk_tree_selection_get_selected (selection, &model, &iter))
+    {
+      gtk_tree_model_get (model, &iter,
+                          QUESTION_COLUMN, &question,
+                          ANSWER_COLUMN, &answer,
+                          CHOICE_COLUMN, &choice,
+                          PIXMAP_COLUMN, &pixmap,
+                          -1);
+      gtk_entry_set_text(u->question, question);
+      gtk_entry_set_text(u->answer, answer);
+      gtk_entry_set_text(u->choice, choice);
+      pixfile = gc_file_find_absolute(pixmap);
+      gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(u->pixmap), pixfile);
+
+      g_free(question);
+      g_free(answer);
+      g_free(choice);
+      g_free(pixmap);
+      g_free(pixfile);
+    }
+}
+
+void destroy_conf_data(void *not_used, gpointer *data)
+{
+  g_free(data);
+}
+
+static void configure_colummns(GtkTreeView *treeview)
+{
+  GtkCellRenderer *renderer;
+  GtkTreeViewColumn *column;
+
+  /* pixbuf column */
+  renderer = gtk_cell_renderer_pixbuf_new();
+  column = gtk_tree_view_column_new_with_attributes(_("Pixbuf"),
+                                                    renderer, "pixbuf", PIXBUF_COLUMN, NULL);
+  gtk_tree_view_append_column(treeview, column);
+
+  /* Answer column */
+  renderer = gtk_cell_renderer_text_new();
+  column = gtk_tree_view_column_new_with_attributes(_("Answer"),
+                                                    renderer, "text", ANSWER_COLUMN, NULL);
+  gtk_tree_view_append_column(treeview, column);
+
+  /* Question column */
+  renderer = gtk_cell_renderer_text_new();
+  column = gtk_tree_view_column_new_with_attributes(_("Question"),
+                                                    renderer, "text", QUESTION_COLUMN, NULL);
+  gtk_tree_view_append_column(treeview, column);
+
+  /* Choice column */
+  renderer = gtk_cell_renderer_text_new();
+  column = gtk_tree_view_column_new_with_attributes(_("Choice"),
+                                                    renderer, "text", CHOICE_COLUMN, NULL);
+  gtk_tree_view_append_column(treeview, column);
+#if 0
+  /* pixmap column */
+  renderer = gtk_cell_renderer_text_new();
+  column = gtk_tree_view_column_new_with_attributes(_("Pixmap"),
+                                                    renderer, "text", PIXMAP_COLUMN, NULL);
+  gtk_tree_view_append_column(treeview, column);
+#endif
+}
+
+  void config_missing_letter(GcomprisBoardConf *config)
+  {
+    GtkWidget *frame, *view, *pixmap, *question, *answer, *choice;
+    GtkWidget *level, *vbox, *hbox, *label;
+    GtkWidget *bbox, *button, *table;
+    GtkFileFilter *file_filter;
+    _config_missing *conf_data;
+    int i;
+
+    conf_data = g_new0(_config_missing,1);
+
+    /* frame */
+    frame = gtk_frame_new("");
+    gtk_widget_show(frame);
+    gtk_box_pack_start(GTK_BOX(config->main_conf_box), frame, TRUE, TRUE, 8);
+
+    vbox = gtk_vbox_new(FALSE, 8);
+    gtk_widget_show(vbox);
+    gtk_container_add(GTK_CONTAINER(frame), vbox);
+
+    /* hbox */
+    hbox = gtk_hbox_new(FALSE, 8);
+    gtk_widget_show(hbox);
+    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 8);
+
+    /* combo level */
+    label = gtk_label_new(_("Choice of the level"));
+    gtk_widget_show(label);
+    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 8);
+
+    level = gtk_combo_box_new_text();
+    for(i=1; i< gcomprisBoard_missing->maxlevel; i++)
+      {
+        gchar *tmp;
+        tmp = g_strdup_printf(_("Level %d"), i);
+        gtk_combo_box_append_text(GTK_COMBO_BOX(level), tmp);
+        g_free(tmp);
+      }
+    gtk_widget_show(level);
+    gtk_box_pack_start(GTK_BOX(hbox), level, FALSE, FALSE, 8);
+
+    /* list view */
+    GtkListStore *list = gtk_list_store_new(N_COLUMNS,
+                                            G_TYPE_STRING,   /*Question */
+                                            G_TYPE_STRING,   /* Answer */
+                                            G_TYPE_STRING,   /* Choice */
+                                            G_TYPE_STRING,   /* pixmap */
+                                            GDK_TYPE_PIXBUF  /* pixbuf */
+                                            );
+
+    view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list));
+    configure_colummns(GTK_TREE_VIEW(view));
+    gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view), TRUE);
+    gtk_tree_view_set_search_column (GTK_TREE_VIEW (view), ANSWER_COLUMN);
+    gtk_widget_set_size_request(view, -1, 200);
+    gtk_widget_show(view);
+
+    GtkScrolledWindow *scroll = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL,NULL));
+    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
+                                    GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+    gtk_widget_show(GTK_WIDGET(scroll));
+    gtk_container_add(GTK_CONTAINER(scroll), view);
+
+    gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(scroll), TRUE, TRUE, 10);
+
+    /* button box */
+    bbox = gtk_hbutton_box_new();
+    gtk_widget_show(bbox);
+    gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 8);
+    button = gtk_button_new_from_stock(GTK_STOCK_NEW);
+    gtk_widget_show(button);
+    gtk_container_add(GTK_CONTAINER(bbox), button);
+    g_signal_connect(G_OBJECT(button), "clicked",
+                     G_CALLBACK(new_clicked), (gpointer) conf_data);
+
+    button = gtk_button_new_from_stock(GTK_STOCK_DELETE);
+    gtk_widget_show(button);
+    gtk_container_add(GTK_CONTAINER(bbox), button);
+    g_signal_connect(G_OBJECT(button), "clicked",
+                     G_CALLBACK(delete_clicked), (gpointer) conf_data);
+
+    button = gtk_button_new_from_stock(GTK_STOCK_APPLY);
+    gtk_widget_show(button);
+    gtk_container_add(GTK_CONTAINER(bbox), button);
+    g_signal_connect(G_OBJECT(button), "clicked",
+                     G_CALLBACK(apply_clicked), (gpointer) conf_data);
+
+    button = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
+    gtk_widget_show(button);
+    gtk_container_add(GTK_CONTAINER(bbox), button);
+    g_signal_connect(G_OBJECT(button), "clicked",
+                     G_CALLBACK(up_clicked), (gpointer) conf_data);
+
+    button = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
+    gtk_widget_show(button);
+    gtk_container_add(GTK_CONTAINER(bbox), button);
+    g_signal_connect(G_OBJECT(button), "clicked",
+                     G_CALLBACK(down_clicked), (gpointer) conf_data);
+
+    button = gtk_button_new_from_stock(GTK_STOCK_SAVE);
+    gtk_widget_show(button);
+    gtk_container_add(GTK_CONTAINER(bbox), button);
+    g_signal_connect(G_OBJECT(button), "clicked",
+                     G_CALLBACK(save_clicked), (gpointer) conf_data);
+
+    /* table */
+    table = gtk_table_new(2, 4, FALSE);
+    gtk_widget_show(table);
+    gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 8);
+
+    /* answer */
+    label = gtk_label_new(_("Answer"));
+    gtk_widget_show(label);
+    gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
+
+    answer = gtk_entry_new();
+    gtk_widget_show(answer);
+    gtk_table_attach_defaults(GTK_TABLE(table), answer, 1, 2, 0, 1);
+
+    /* pixmap */
+    label = gtk_label_new(_("Picture"));
+    gtk_widget_show(label);
+    gtk_table_attach_defaults(GTK_TABLE(table), label, 2, 3, 0, 1);
+
+    pixmap = gtk_file_chooser_button_new(_("Choice of the filename"),
+                                         GTK_FILE_CHOOSER_ACTION_OPEN);
+
+    file_filter = gtk_file_filter_new();
+    gtk_file_filter_add_pixbuf_formats(file_filter);
+    gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(pixmap), file_filter);
+    gtk_widget_show(pixmap);
+    gtk_table_attach_defaults(GTK_TABLE(table), pixmap, 3, 4, 0, 1);
+
+    /* question */
+    label = gtk_label_new(_("Question"));
+    gtk_widget_show(label);
+    gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
+
+    question = gtk_entry_new();
+    gtk_widget_show(question);
+    gtk_table_attach_defaults(GTK_TABLE(table), question, 1, 2, 1, 2);
+
+    /* choice */
+    label = gtk_label_new(_("Choice"));
+    gtk_widget_show(label);
+    gtk_table_attach_defaults(GTK_TABLE(table), label, 2, 3, 1, 2);
+
+    choice = gtk_entry_new();
+    gtk_entry_set_max_length(GTK_ENTRY(choice), 3);
+    gtk_widget_show(choice);
+    gtk_table_attach_defaults(GTK_TABLE(table), choice, 3, 4, 1, 2);
+
+    conf_data -> combo_level = GTK_COMBO_BOX(level);
+    conf_data -> view = GTK_TREE_VIEW(view);
+    conf_data -> pixmap = GTK_FILE_CHOOSER_BUTTON(pixmap);
+    conf_data -> question = GTK_ENTRY(question);
+    conf_data -> answer = GTK_ENTRY(answer);
+    conf_data -> choice = GTK_ENTRY(choice);
+
+    GtkTreeSelection *selection;
+    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
+    gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
+
+    g_signal_connect(G_OBJECT(selection),
+                     "changed",
+                     G_CALLBACK(selection_changed),
+                     (gpointer) conf_data);
+    g_signal_connect(G_OBJECT(frame), "destroy",
+                     G_CALLBACK(destroy_conf_data), (gpointer) conf_data);
+    g_signal_connect(G_OBJECT(level), "changed",
+                     G_CALLBACK(level_changed), (gpointer) conf_data);
+    g_signal_connect(G_OBJECT(question), "changed",
+                     G_CALLBACK(text_changed), (gpointer) conf_data);
+    g_signal_connect(G_OBJECT(answer), "changed",
+                     G_CALLBACK(text_changed), (gpointer) conf_data);
+
+    gtk_combo_box_set_active(GTK_COMBO_BOX(level), 0);
+    level_changed(GTK_COMBO_BOX(level),conf_data);
+  }
+

Modified: trunk/src/boards/reading.c
==============================================================================
--- trunk/src/boards/reading.c	(original)
+++ trunk/src/boards/reading.c	Mon Feb 16 23:32:03 2009
@@ -457,7 +457,15 @@
       word = g_strdup(textToFind);
     }
 
-  g_assert(word!=NULL);
+  if(word==NULL)
+  {
+  	gc_dialog(_("Skip this level. Not enough word in the list !"),
+		(DialogBoxCallBack)reading_next_level);
+	gcomprisBoard->level++;
+	if(gcomprisBoard->level>gcomprisBoard->maxlevel) // the current board is finished : bail out
+		gc_bonus_end_display(GC_BOARD_FINISHED_RANDOM);
+	return FALSE;
+  }
 
   if(textToFindIndex>=0)
     textToFindIndex--;
@@ -776,6 +784,7 @@
 get_random_word(const gchar* except)
 {
   gchar *word;
+  int count=0;
 
   word = gc_wordlist_random_word_get(gc_wordlist, gcomprisBoard->level);
 
@@ -783,6 +792,12 @@
     while(strcmp(except, word)==0)
       {
 	g_free(word);
+
+	if(count++>100)
+	{
+		word = NULL;
+		break;
+	}
 	word = gc_wordlist_random_word_get(gc_wordlist, gcomprisBoard->level);
       }
 

Modified: trunk/src/gcompris/board_config_wordlist.c
==============================================================================
--- trunk/src/gcompris/board_config_wordlist.c	(original)
+++ trunk/src/gcompris/board_config_wordlist.c	Mon Feb 16 23:32:03 2009
@@ -49,7 +49,7 @@
 	}
 
 	wordsArray = g_malloc0(sizeof(gpointer)*(g_slist_length(lw->words)+1));
-	
+
 	for(i=0, list = lw->words; list; list=list->next)
 	{
 		wordsArray[i]=(gchar*)list->data;
@@ -159,7 +159,7 @@
 static void _destroy(GtkWidget *w, gpointer data)
 {
 	user_param_type_wordlist *u = (user_param_type_wordlist*)data;
-	
+
 	gc_wordlist_free(u->wordlist);
 	g_free(u);
 }
@@ -177,7 +177,7 @@
 	const gchar *locale;
 
 	/* frame */
-	frame = gtk_frame_new("Change wordlist");
+	frame = gtk_frame_new(_("Configure the list of words"));
 	gtk_widget_show(frame);
 	gtk_box_pack_start(GTK_BOX(config->main_conf_box), frame, FALSE, FALSE, 8);
 
@@ -206,7 +206,7 @@
 
 	gtk_widget_show(combo_lang);
 	hbox = gtk_hbox_new(FALSE, 8);
-	label = gtk_label_new(_("Choice language"));
+	label = gtk_label_new(_("Choice of the language"));
 	gtk_widget_show(label);
 	gtk_widget_show(hbox);
 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 8);
@@ -218,7 +218,7 @@
 
 	gtk_widget_show(combo_level);
 	hbox = gtk_hbox_new(FALSE, 8);
-	label = gtk_label_new(_("Choice level"));
+	label = gtk_label_new(_("Choice of the level"));
 	gtk_widget_show(label);
 	gtk_widget_show(hbox);
 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 8);
@@ -243,7 +243,7 @@
 	gtk_widget_show(hbox);
 	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 8);
 
-	GtkWidget * b_default = gtk_button_new_with_label(_("Return to default"));
+	GtkWidget * b_default = gtk_button_new_with_label(_("Back to default"));
 	gtk_widget_show(b_default);
 	gtk_box_pack_start(GTK_BOX(hbox), b_default, FALSE, FALSE, 8);
 

Modified: trunk/src/gcompris/gc_net.c
==============================================================================
--- trunk/src/gcompris/gc_net.c	(original)
+++ trunk/src/gcompris/gc_net.c	Mon Feb 16 23:32:03 2009
@@ -171,6 +171,11 @@
         g_file_set_contents(cache, buf, buflen, NULL);
 	g_free(buf);
       }
+      else
+      { /* file is in content.txt but not in server */
+      	g_free(cache);
+      	cache = NULL;
+      }
     }
   }
   g_free(file);
@@ -257,6 +262,44 @@
 	g_hash_table_insert(cache_content, g_strdup(filename), g_strdup("0"));
 }
 
+gchar* gc_cache_import_pixmap(gchar *filename, gchar *boarddir, gint width, gint height)
+{
+	GdkPixbuf *pixmap;
+	gchar *basename, *file, *ext, *name, *abs;
+
+	if(!g_path_is_absolute(filename))
+		return g_strdup(filename);
+	basename = g_path_get_basename(filename);
+	name = g_build_filename(boarddir, basename,NULL);
+	abs = gc_file_find_absolute(name);
+	if(abs && strcmp(abs,filename)==0)
+	{
+		g_free(basename);
+		g_free(abs);
+		return name;
+	}
+	pixmap = gdk_pixbuf_new_from_file_at_size(filename, width, height,NULL);
+	if(!pixmap)
+	{
+		g_free(abs);
+		g_free(basename);
+		g_free(name);
+		return NULL;
+	}
+
+	file = gc_file_find_absolute_writeable(name);
+	ext = strchr(basename, '.')+1;
+	if(strcmp(ext, "jpg")==0)
+		ext ="jpeg";
+
+	gdk_pixbuf_save(pixmap, file, ext, NULL,NULL);
+
+	g_free(abs);
+	g_free(basename);
+	g_free(file);
+	return name;
+}
+
 void gc_cache_remove(gchar *filename)
 {
 	g_remove(filename);

Modified: trunk/src/gcompris/gc_net.h
==============================================================================
--- trunk/src/gcompris/gc_net.h	(original)
+++ trunk/src/gcompris/gc_net.h	Mon Feb 16 23:32:03 2009
@@ -40,6 +40,7 @@
 
 void gc_cache_init(void);
 void gc_cache_add(gchar *filename);
+gchar* gc_cache_import_pixmap(gchar *filename, gchar *boarddir, gint width, gint height);
 void gc_cache_remove(gchar *filename);
 void gc_cache_save(void);
 void gc_cache_destroy(void);

Modified: trunk/src/gcompris/gcompris.c
==============================================================================
--- trunk/src/gcompris/gcompris.c	(original)
+++ trunk/src/gcompris/gcompris.c	Mon Feb 16 23:32:03 2009
@@ -1712,8 +1712,7 @@
 	  }
 	}
       }
-      /* FIXME: Need to translate */
-      printf("Number of activities: %d\n", board_count);
+      printf(_("Number of activities: %d\n"), board_count);
 
       exit(0);
     }
@@ -1749,7 +1748,7 @@
 	{
 	  if (g_access(properties->database, R_OK)==-1)
 	    {
-	      printf("%s exists but is not readable or writable", properties->database);
+	      printf(_("%s exists but is not readable or writable"), properties->database);
 	      exit(0);
 	    }
 	}
@@ -1808,8 +1807,10 @@
   if (popt_server){
 #ifdef USE_GNET
       properties->server = g_strdup(popt_server);
+      printf("   Server '%s'\n", properties->server);
 #else
-      printf("The --server option cannot be used because GCompris has been compiled without network support!");
+      printf(_("The --server option cannot be used because"
+	       "GCompris has been compiled without network support!"));
       exit(1);
 #endif
   }
@@ -1823,7 +1824,11 @@
   }
 
   if (popt_server){
+    if(popt_cache_dir)
       properties->cache_dir = g_strdup(popt_cache_dir);
+    else
+      properties->cache_dir = g_build_filename(g_get_user_cache_dir(), "gcompris", NULL);
+    printf("   Cache dir '%s'\n",properties->cache_dir);
   }
 
   if (popt_drag_mode){
@@ -1855,7 +1860,8 @@
 
     if(properties->profile == NULL)
       {
-	printf("ERROR: Profile '%s' is not found. Run 'gcompris --profile-list' to list available ones\n",
+	printf(_("ERROR: Profile '%s' is not found."
+		 " Run 'gcompris --profile-list' to list available ones\n"),
 	       popt_profile);
 	exit(1);
       }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]