Back to index

gcompris  8.2.2
properties.c
Go to the documentation of this file.
00001 /* gcompris - properties.c
00002  *
00003  * Time-stamp: <2006/08/21 23:26:56 bruno>
00004  *
00005  * Copyright (C) 2000,2003 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., 675 Mass Ave, Cambridge, MA 02139, USA.
00020  */
00021 
00022 #include <glib/gstdio.h>
00023 #include <fcntl.h>
00024 #include <string.h>
00025 
00026 #include "gcompris.h"
00027 
00028 /* This should be detected in the configure for good portability */
00029 #define HAVE_SETENV 1
00030 
00031 #ifdef WIN32
00032 # define WIN32_LEAN_AND_MEAN
00033 # include <windows.h>
00034 #endif
00035 
00036 static gchar *config_file = NULL;
00037 
00038 /*
00039  * return 1 if parsing OK, 0 otherwise
00040  * the return value is returned in retval
00041  */
00042 static guint
00043 scan_get_int(GScanner *scanner, int *retval) {
00044   GTokenType token = g_scanner_get_next_token (scanner);
00045   token = g_scanner_get_next_token (scanner);
00046   if(token == G_TOKEN_INT) {
00047     /* we got it */
00048     GTokenValue value = g_scanner_cur_value(scanner);
00049     *retval = value.v_int;
00050     return 1;
00051   }
00052   return 0;
00053 }
00054 
00055 /*
00056  * return String if parsing OK, NULL otherwise
00057  */
00058 static gchar *
00059 scan_get_string(GScanner *scanner) {
00060   GTokenType token = g_scanner_get_next_token (scanner);
00061   token = g_scanner_get_next_token (scanner);
00062   if(token == G_TOKEN_STRING) {
00063     /* we got it */
00064     GTokenValue value = g_scanner_cur_value(scanner);
00065     return (g_strdup(value.v_string));
00066   }
00067   return NULL;
00068 }
00069 
00070 
00071 /* get the gcompris user directory name */
00072 /* Architecture dependant: "gcompris" in Win9x, */
00073 /* "/.gcompris" in POSIX compliant systems */
00074 
00075 gchar *
00076 gc_prop_user_root_directory_get ()
00077 {
00078   G_CONST_RETURN gchar *home_dir = g_get_home_dir();
00079 
00080   if (home_dir == NULL) /* Win9x */
00081     return g_strdup("gcompris");
00082   else
00083     return g_strconcat(home_dir, "/.gcompris", NULL);
00084 }
00085 
00091 gchar *
00092 gc_prop_config_file_get()
00093 {
00094   gchar *dir;
00095   if(config_file)
00096     return(config_file);
00097   dir = gc_prop_user_root_directory_get();
00098   /* Was never called, must calculate it */
00099   if (g_get_home_dir()==NULL) {
00100     config_file = g_strconcat(dir, "/gcompris.cfg", NULL);
00101   } else {
00102     config_file = g_strconcat(dir, "/gcompris.conf", NULL);
00103   }
00104   g_free(dir);
00105    return(config_file);
00106 }
00107 
00108 /* get the default database name */
00109 #define DEFAULT_DATABASE "gcompris_sqlite.db"
00110 #define PROFILES_ROOT "profiles"
00111 
00112 gchar *
00113 gc_prop_default_database_name_get (gchar *shared_dir)
00114 {
00115   gchar *dir_base = g_strconcat( shared_dir, "/",  PROFILES_ROOT, NULL);
00116   gc_util_create_rootdir(dir_base);
00117   g_free(dir_base);
00118   return g_strconcat( shared_dir, "/",  PROFILES_ROOT, "/",  DEFAULT_DATABASE, NULL);
00119 
00120 }
00121 
00122 GcomprisProperties *
00123 gc_prop_new ()
00124 {
00125   GcomprisProperties *tmp;
00126   char          *config_file = gc_prop_config_file_get();
00127   GScanner      *scanner;
00128   gchar              *content;
00129   gsize              length;
00130   gchar         *full_rootdir;
00131   const gchar   *locale;
00132   gchar         *user_dir;
00133 
00134   tmp = (GcomprisProperties *) malloc (sizeof (GcomprisProperties));
00135   tmp->music          = 1;
00136   tmp->fx             = 1;
00137   tmp->screensize     = 1;
00138   tmp->fullscreen     = 1;
00139   tmp->noxf86vm              = FALSE;
00140   tmp->timer          = 1;
00141   tmp->skin           = g_strdup("babytoy");
00142   tmp->key            = g_strdup("default");
00143   tmp->locale            = NULL;
00144   tmp->difficulty_max    = 0;
00145   tmp->filter_style      = GCOMPRIS_FILTER_NONE; /* No difficulty filter by default */
00146   tmp->difficulty_filter = 1;                           /* No difficulty filter by default */
00147   tmp->disable_quit      = 0;                           /* Used to remove the quit button from the bar. Use it for kiosk mode */
00148   tmp->disable_config    = 0;                           /* Used to remove the config button from the bar. Use it for kiosk mode */
00149   tmp->display_resource  = 0;
00150   tmp->root_menu         = "/";
00151   tmp->local_directory   = NULL;
00152   tmp->profile           = NULL;
00153   tmp->logged_user       = NULL;
00154 
00155   tmp->administration    = FALSE;
00156   tmp->reread_menu       = FALSE;
00157   tmp->experimental      = FALSE;
00158   tmp->menu_position     = NULL;
00159 
00160   tmp->server            = NULL;
00161 
00162   tmp->package_data_dir           = NULL;
00163   tmp->package_locale_dir         = NULL;
00164   tmp->package_plugin_dir         = NULL;
00165   tmp->package_python_plugin_dir  = NULL;
00166   tmp->system_icon_dir            = NULL;
00167   tmp->cache_dir                  = NULL;
00168 
00169   user_dir = gc_prop_user_root_directory_get() ;
00170   gc_util_create_rootdir( user_dir );
00171 
00172   tmp->shared_dir        = g_strconcat(user_dir, "/shared", NULL);
00173   gc_util_create_rootdir( tmp->shared_dir );
00174 
00175   tmp->users_dir        = g_strconcat(user_dir, "/users", NULL);
00176   gc_util_create_rootdir( tmp->users_dir );
00177 
00178   tmp->user_data_dir = g_strconcat(user_dir, "/Plugins/boards", NULL);
00179   gc_util_create_rootdir( tmp->user_data_dir );
00180 
00181   /* Needs to be set after command line parsing */
00182   tmp->database          = NULL;
00183 
00184   full_rootdir = g_strconcat(user_dir, "/user_data", NULL);
00185   gc_util_create_rootdir(full_rootdir);
00186   g_free(full_rootdir);
00187 
00188   full_rootdir = g_strconcat(user_dir, "/user_data/images", NULL);
00189   gc_util_create_rootdir(full_rootdir);
00190   g_free(full_rootdir);
00191 
00192   full_rootdir = g_strconcat(user_dir, "/", PROFILES_ROOT, NULL);
00193   gc_util_create_rootdir(full_rootdir);
00194   g_free(full_rootdir);
00195 
00196   g_free(user_dir);
00197 
00198   g_warning("config_file %s", config_file);
00199 
00200   if(g_file_get_contents(config_file,
00201                       &content,
00202                       &length,
00203                       NULL)) {
00204 
00205     /* create a new scanner */
00206     scanner = g_scanner_new(NULL);
00207 
00208     /* set up the scanner to read from the file */
00209     g_scanner_input_text(scanner, content, length);
00210 
00211     /* while the next token is something else other than end of file */
00212     while(g_scanner_peek_next_token(scanner) != G_TOKEN_EOF) {
00213 
00214       /* get the next token */
00215       GTokenType tokent = g_scanner_get_next_token(scanner);
00216       switch(tokent) {
00217       case G_TOKEN_IDENTIFIER: {
00218        gchar *token;
00219        /* if we have a symbol, check it's ours */
00220        GTokenValue value = g_scanner_cur_value(scanner);
00221        token = g_strdup(value.v_identifier);
00222 
00223        if(!strcmp(value.v_identifier, "music")) {
00224          if(!scan_get_int(scanner, &tmp->music))
00225            g_warning("Config file parsing error on token %s", token);
00226        } else if(!strcmp(value.v_identifier, "fx")) {
00227          if(!scan_get_int(scanner, &tmp->fx))
00228            g_warning("Config file parsing error on token %s", token);
00229        } else if(!strcmp(value.v_identifier, "screensize")) {
00230          if(!scan_get_int(scanner, &tmp->screensize))
00231            g_warning("Config file parsing error on token %s", token);
00232        } else if(!strcmp(value.v_identifier, "fullscreen")) {
00233          if(!scan_get_int(scanner, &tmp->fullscreen))
00234            g_warning("Config file parsing error on token %s", token);
00235        } else if(!strcmp(value.v_identifier, "noxf86vm")) {
00236          if(!scan_get_int(scanner, &tmp->noxf86vm))
00237            g_warning("Config file parsing error on token %s", token);
00238        } else if(!strcmp(value.v_identifier, "timer")) {
00239          if(!scan_get_int(scanner, &tmp->timer))
00240            g_warning("Config file parsing error on token %s", token);
00241        } else if(!strcmp(value.v_identifier, "difficulty_filter")) {
00242          if(!scan_get_int(scanner, &tmp->difficulty_filter))
00243            g_warning("Config file parsing error on token %s", token);
00244        } else if(!strcmp(value.v_identifier, "disable_quit")) {
00245          if(!scan_get_int(scanner, &tmp->disable_quit))
00246            g_warning("Config file parsing error on token %s", token);
00247        } else if(!strcmp(value.v_identifier, "disable_config")) {
00248          if(!scan_get_int(scanner, &tmp->disable_config))
00249            g_warning("Config file parsing error on token %s", token);
00250        } else if(!strcmp(value.v_identifier, "filter_style")) {
00251          if(!scan_get_int(scanner, &tmp->filter_style))
00252            g_warning("Config file parsing error on token %s", token);
00253        } else if(!strcmp(value.v_identifier, "skin")) {
00254         g_free(tmp->skin);
00255          tmp->skin = scan_get_string(scanner);
00256          if(!tmp->skin)
00257            g_warning("Config file parsing error on token %s", token);
00258        } else if(!strcmp(value.v_identifier, "locale")) {
00259          tmp->locale = scan_get_string(scanner);
00260          if(!tmp->locale)
00261            g_warning("Config file parsing error on token %s", token);
00262        } else if(!strcmp(value.v_identifier, "key")) {
00263       g_free(tmp->key);
00264          tmp->key = scan_get_string(scanner);
00265          if(!tmp->key)
00266            g_warning("Config file parsing error on token %s", token);
00267        }
00268        else if(!strcmp(value.v_identifier, "database")) {
00269          tmp->database = scan_get_string(scanner);
00270          if(!tmp->database)
00271            g_warning("Config file parsing error on token %s", token);
00272        }
00273        g_free(token);
00274        break;
00275       }
00276       default:
00277        break;
00278       }
00279     }
00280 
00281     /* destroy the scanner */
00282     g_scanner_destroy(scanner);
00283     g_free(content);
00284   }
00285 
00286   /*
00287    * Warning, gcompris need a proper locale prefix to find suitable dataset
00288    * Some system use LOCALE 'C' for english. We have to set it explicitly
00289    */
00290   if(!tmp->locale) {
00291 
00292 #if defined WIN32
00293     tmp->locale = g_win32_getlocale();
00294 #else
00295     locale = g_getenv("LC_ALL");
00296     if(locale == NULL)
00297       locale = g_getenv("LC_MESSAGES");
00298     if(locale == NULL)
00299       locale = g_getenv("LANG");
00300 
00301     if (locale != NULL && !strcmp(locale, "C"))
00302       {
00303        tmp->locale          = "en_US.UTF-8";
00304       }
00305 #endif
00306   }
00307 
00308   if(!tmp->locale) {
00309     /* No user specified locale = '' */
00310     tmp->locale             = strdup("");
00311   }
00312 
00313   return (tmp);
00314 }
00315 
00316 void
00317 gc_prop_destroy (GcomprisProperties *props)
00318 {
00319   if(!props)
00320     return;
00321   g_free(props->user_data_dir);
00322   g_free(props->package_data_dir);
00323   g_free(props->package_locale_dir);
00324   g_free(props->package_plugin_dir);
00325   g_free(props->package_python_plugin_dir);
00326   g_free(props->system_icon_dir);
00327   g_free(props->cache_dir);
00328   g_free(props->locale);
00329   g_free(props->skin);
00330   g_free(props->key);
00331   gc_profile_destroy(props->profile);
00332   gc_user_destroy(props->logged_user);
00333   g_free(props->database);
00334   g_free(props->shared_dir);
00335   g_free(props->users_dir);
00336   g_free(props->menu_position);
00337   g_free(props->server);
00338   g_free (props);
00339   g_warning("properties free");
00340 }
00341 
00342 void
00343 gc_prop_save (GcomprisProperties *props)
00344 {
00345   char *config_file = gc_prop_config_file_get();
00346   FILE *filefd;
00347 
00348   filefd = g_fopen(config_file, "w+");
00349 
00350   if(!filefd) {
00351       g_warning("cannot open '%s', configuration file not saved\n",(char *) config_file);
00352       return;
00353     }
00354 
00355   fprintf(filefd, "%s=%d\n", "music",                   props->music);
00356   fprintf(filefd, "%s=%d\n", "fx",               props->fx);
00357   fprintf(filefd, "%s=%d\n", "screensize",              props->screensize);
00358   fprintf(filefd, "%s=%d\n", "fullscreen",              props->fullscreen);
00359   fprintf(filefd, "%s=%d\n", "timer",                   props->timer);
00360 
00361   fprintf(filefd, "%s=\"%s\"\n", "skin",         props->skin);
00362   fprintf(filefd, "%s=\"%s\"\n", "locale",              props->locale);
00363   fprintf(filefd, "%s=\"%s\"\n", "key",                 props->key);
00364 
00365   fprintf(filefd, "%s=\"%s\"\n", "database",            props->database);
00366 
00367   fclose(filefd);
00368 }
00369 
00370 gchar*
00371 gc_prop_user_dirname_get(GcomprisUser *user)
00372 {
00373   GcomprisProperties *properties = gc_prop_get ();
00374 
00375   gchar *user_dirname = g_strconcat (properties->users_dir,
00376                                  "/",
00377                                  user->login,
00378                                  NULL);
00379 
00380   gc_util_create_rootdir(user_dirname);
00381 
00382   return user_dirname;
00383 }
00384 
00385 gchar*
00386 gc_prop_current_user_dirname_get()
00387 {
00388   return gc_prop_user_dirname_get(gc_profile_get_current_user());
00389 }
00390 
00391 gchar*
00392 gc_prop_board_dirname_get(GcomprisBoard *board)
00393 {
00394   GcomprisProperties *properties = gc_prop_get ();
00395 
00396   gchar *board_main = g_strconcat (properties->shared_dir, "/boards", NULL);
00397   gc_util_create_rootdir(board_main);
00398 
00399   gchar *board_dirname = g_strconcat (board_main, "/", board->name, NULL);
00400   gc_util_create_rootdir(board_dirname);
00401 
00402   g_free(board_main);
00403   return board_dirname;
00404 }
00405 
00406 gchar*
00407 gc_prop_current_board_dirname_get()
00408 {
00409   return gc_prop_board_dirname_get(gc_board_get_current());
00410 }
00411 
00412 
00413 int
00414 gc_setenv (const char * name, const char * value) {
00415 #if defined WIN32
00416   size_t namelen = strlen(name);
00417   size_t valuelen = (value==NULL ? 0 : strlen(value));
00418   /* On Woe32, each process has two copies of the environment variables,
00419      one managed by the OS and one managed by the C library. We set
00420      the value in both locations, so that other software that looks in
00421      one place or the other is guaranteed to see the value. Even if it's
00422      a bit slow. See also
00423      <http://article.gmane.org/gmane.comp.gnu.mingw.user/8272>
00424      <http://article.gmane.org/gmane.comp.gnu.mingw.user/8273>
00425      <http://www.cygwin.com/ml/cygwin/1999-04/msg00478.html> */
00426   if (!SetEnvironmentVariableA(name,value))
00427     return -1;
00428   //#endif
00429   //#if defined(HAVE_PUTENV)
00430   char* buffer = (char*)malloc(namelen+1+valuelen+1);
00431   if (!buffer)
00432     return -1; /* no need to set errno = ENOMEM */
00433   memcpy(buffer,name,namelen);
00434   if (value != NULL) {
00435     buffer[namelen] = '=';
00436     memcpy(buffer+namelen+1,value,valuelen);
00437     buffer[namelen+1+valuelen] = 0;
00438   } else
00439     buffer[namelen] = 0;
00440   return putenv(buffer);
00441 #elif defined(HAVE_SETENV)
00442   return setenv(name,value,1);
00443 #else
00444   /* Uh oh, neither putenv() nor setenv() ... */
00445   return -1;
00446 #endif
00447 }