]> git.sesse.net Git - vlc/blobdiff - src/misc/configuration.c
* src/misc/charset.c: New function vlc_fix_readdir_charset. It is used
[vlc] / src / misc / configuration.c
index ebeeeedb3a5836cd78bf9bc66fc82cdc75b939db..820cb4da6dd3fb639e6967c9a290e7103a43e439 100644 (file)
@@ -1,10 +1,10 @@
 /*****************************************************************************
  * configuration.c management of the modules configuration
  *****************************************************************************
- * Copyright (C) 2001 VideoLAN
- * $Id: configuration.c,v 1.69 2003/11/05 18:59:01 gbazin Exp $
+ * Copyright (C) 2001-2004 the VideoLAN team
+ * $Id$
  *
- * Authors: Gildas Bazin <gbazin@netcourrier.com>
+ * Authors: Gildas Bazin <gbazin@videolan.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -27,9 +27,7 @@
 #include <stdio.h>                                              /* sprintf() */
 #include <stdlib.h>                                      /* free(), strtol() */
 #include <string.h>                                              /* strdup() */
-#ifdef HAVE_ERRNO_H
-#   include <errno.h>                                               /* errno */
-#endif
+#include <errno.h>                                                  /* errno */
 
 #ifdef HAVE_UNISTD_H
 #    include <unistd.h>                                          /* getuid() */
 #if defined( HAVE_SYS_TYPES_H )
 #   include <sys/types.h>
 #endif
-#if defined( WIN32 ) && !defined( UNDER_CE )
-#   include <direct.h>
+#if defined( WIN32 )
+#   if !defined( UNDER_CE )
+#       include <direct.h>
+#   endif
+#include <tchar.h>
 #endif
 
 
@@ -95,6 +96,9 @@ int __config_GetType( vlc_object_t *p_this, const char *psz_name )
         break;
 
     case CONFIG_ITEM_MODULE:
+    case CONFIG_ITEM_MODULE_CAT:
+    case CONFIG_ITEM_MODULE_LIST:
+    case CONFIG_ITEM_MODULE_LIST_CAT:
         i_type = VLC_VAR_MODULE;
         break;
 
@@ -202,12 +206,16 @@ char * __config_GetPsz( vlc_object_t *p_this, const char *psz_name )
     if( (p_config->i_type!=CONFIG_ITEM_STRING) &&
         (p_config->i_type!=CONFIG_ITEM_FILE) &&
         (p_config->i_type!=CONFIG_ITEM_DIRECTORY) &&
+        (p_config->i_type!=CONFIG_ITEM_MODULE_LIST) &&
+        (p_config->i_type!=CONFIG_ITEM_MODULE_LIST_CAT) &&
+        (p_config->i_type!=CONFIG_ITEM_MODULE_CAT) &&
         (p_config->i_type!=CONFIG_ITEM_MODULE) )
     {
         msg_Err( p_this, "option %s does not refer to a string", psz_name );
         return NULL;
     }
 
+
     /* return a copy of the string */
     vlc_mutex_lock( p_config->p_lock );
     if( p_config->psz_value ) psz_value = strdup( p_config->psz_value );
@@ -231,6 +239,7 @@ void __config_PutPsz( vlc_object_t *p_this,
 
     p_config = config_FindConfig( p_this, psz_name );
 
+
     /* sanity checks */
     if( !p_config )
     {
@@ -240,6 +249,9 @@ void __config_PutPsz( vlc_object_t *p_this,
     if( (p_config->i_type!=CONFIG_ITEM_STRING) &&
         (p_config->i_type!=CONFIG_ITEM_FILE) &&
         (p_config->i_type!=CONFIG_ITEM_DIRECTORY) &&
+        (p_config->i_type!=CONFIG_ITEM_MODULE_LIST) &&
+        (p_config->i_type!=CONFIG_ITEM_MODULE_CAT) &&
+        (p_config->i_type!=CONFIG_ITEM_MODULE_LIST_CAT) &&
         (p_config->i_type!=CONFIG_ITEM_MODULE) )
     {
         msg_Err( p_this, "option %s does not refer to a string", psz_name );
@@ -254,6 +266,8 @@ void __config_PutPsz( vlc_object_t *p_this,
     if( psz_value && *psz_value ) p_config->psz_value = strdup( psz_value );
     else p_config->psz_value = NULL;
 
+    p_config->b_dirty = VLC_TRUE;
+
     val.psz_string = p_config->psz_value;
 
     vlc_mutex_unlock( p_config->p_lock );
@@ -317,6 +331,8 @@ void __config_PutInt( vlc_object_t *p_this, const char *psz_name, int i_value )
         p_config->i_value = i_value;
     }
 
+    p_config->b_dirty = VLC_TRUE;
+
     val.i_int = p_config->i_value;
 
     if( p_config->pf_callback )
@@ -373,6 +389,8 @@ void __config_PutFloat( vlc_object_t *p_this,
         p_config->f_value = f_value;
     }
 
+    p_config->b_dirty = VLC_TRUE;
+
     val.f_float = p_config->f_value;
 
     if( p_config->pf_callback )
@@ -499,10 +517,18 @@ void config_Duplicate( module_t *p_module, module_config_t *p_orig )
     {
         p_module->p_config[i] = p_orig[i];
 
+        p_module->p_config[i].i_value_orig = p_orig[i].i_value;
+        p_module->p_config[i].f_value_orig = p_orig[i].f_value;
+        p_module->p_config[i].i_value_saved = p_orig[i].i_value;
+        p_module->p_config[i].f_value_saved = p_orig[i].f_value;
+        p_module->p_config[i].psz_value_saved = 0;
+
         p_module->p_config[i].psz_type = p_orig[i].psz_type ?
                                    strdup( p_orig[i].psz_type ) : NULL;
         p_module->p_config[i].psz_name = p_orig[i].psz_name ?
                                    strdup( p_orig[i].psz_name ) : NULL;
+        p_module->p_config[i].psz_current = p_orig[i].psz_current?
+                                   strdup( p_orig[i].psz_current ) : NULL;
         p_module->p_config[i].psz_text = p_orig[i].psz_text ?
                                    strdup( _(p_orig[i].psz_text) ) : NULL;
         p_module->p_config[i].psz_longtext = p_orig[i].psz_longtext ?
@@ -524,8 +550,8 @@ void config_Duplicate( module_t *p_module, module_config_t *p_orig )
                 if( p_module->p_config[i].ppsz_list )
                 {
                     for( j = 0; j < p_orig[i].i_list; j++ )
-                        p_module->p_config[i].ppsz_list[j] =
-                            strdup( p_orig[i].ppsz_list[j] );
+                        p_module->p_config[i].ppsz_list[j] = p_orig[i].ppsz_list[j] ?
+                            strdup( p_orig[i].ppsz_list[j] ) : NULL ;
                     p_module->p_config[i].ppsz_list[j] = NULL;
                 }
             }
@@ -536,8 +562,8 @@ void config_Duplicate( module_t *p_module, module_config_t *p_orig )
                 if( p_module->p_config[i].ppsz_list_text )
                 {
                     for( j = 0; j < p_orig[i].i_list; j++ )
-                        p_module->p_config[i].ppsz_list_text[j] =
-                            strdup( _(p_orig[i].ppsz_list_text[j]) );
+                        p_module->p_config[i].ppsz_list_text[j] = _(p_orig[i].ppsz_list_text[j]) ?
+                            strdup( _(p_orig[i].ppsz_list_text[j] ) ) : NULL ;
                     p_module->p_config[i].ppsz_list_text[j] = NULL;
                 }
             }
@@ -554,6 +580,26 @@ void config_Duplicate( module_t *p_module, module_config_t *p_orig )
             }
         }
 
+        /* duplicate the actions list */
+        if( p_orig[i].i_action )
+        {
+            int j;
+
+            p_module->p_config[i].ppf_action =
+                malloc( p_orig[i].i_action * sizeof(void *) );
+            p_module->p_config[i].ppsz_action_text =
+                malloc( p_orig[i].i_action * sizeof(char *) );
+
+            for( j = 0; j < p_orig[i].i_action; j++ )
+            {
+                p_module->p_config[i].ppf_action[j] =
+                    p_orig[i].ppf_action[j];
+                p_module->p_config[i].ppsz_action_text[j] =
+                    p_orig[i].ppsz_action_text[j] ?
+                    strdup( p_orig[i].ppsz_action_text[j] ) : NULL;
+            }
+        }
+
         p_module->p_config[i].pf_callback = p_orig[i].pf_callback;
     }
 }
@@ -581,6 +627,9 @@ void config_Free( module_t *p_module )
         if( p_item->psz_name )
             free( p_item->psz_name );
 
+        if( p_item->psz_current )
+            free( p_item->psz_current );
+
         if( p_item->psz_text )
             free( p_item->psz_text );
 
@@ -593,6 +642,9 @@ void config_Free( module_t *p_module )
         if( p_item->psz_value_orig )
             free( p_item->psz_value_orig );
 
+        if( p_item->psz_value_saved )
+            free( p_item->psz_value_saved );
+
         if( p_item->i_list )
         {
             for( i = 0; i < p_item->i_list; i++ )
@@ -606,6 +658,17 @@ void config_Free( module_t *p_module )
             if( p_item->ppsz_list_text ) free( p_item->ppsz_list_text );
             if( p_item->pi_list ) free( p_item->pi_list );
         }
+
+        if( p_item->i_action )
+        {
+            for( i = 0; i < p_item->i_action; i++ )
+            {
+                if( p_item->ppsz_action_text[i] )
+                    free( p_item->ppsz_action_text[i] );
+            }
+            if( p_item->ppf_action ) free( p_item->ppf_action );
+            if( p_item->ppsz_action_text ) free( p_item->ppsz_action_text );
+        }
     }
 
     free( p_module->p_config );
@@ -816,6 +879,7 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
                         if( !*psz_option_value )
                             break;                    /* ignore empty option */
                         p_item->i_value = strtol( psz_option_value, 0, 0 );
+                        p_item->i_value_saved = p_item->i_value;
 #if 0
                         msg_Dbg( p_this, "option \"%s\", value %i",
                                  p_item->psz_name, p_item->i_value );
@@ -826,7 +890,8 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
                         if( !*psz_option_value )
                             break;                    /* ignore empty option */
                         p_item->f_value = (float)atof( psz_option_value);
-#if O
+                        p_item->f_value_saved = p_item->f_value;
+#if 0
                         msg_Dbg( p_this, "option \"%s\", value %f",
                                  p_item->psz_name, (double)p_item->f_value );
 #endif
@@ -834,7 +899,8 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
                     case CONFIG_ITEM_KEY:
                         if( !*psz_option_value )
                             break;                    /* ignore empty option */
-                        p_item->i_value = ConfigStringToKey( psz_option_value );
+                        p_item->i_value = ConfigStringToKey(psz_option_value);
+                        p_item->i_value_saved = p_item->i_value;
                         break;
 
                     default:
@@ -847,6 +913,15 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
                         p_item->psz_value = *psz_option_value ?
                             strdup( psz_option_value ) : NULL;
 
+                        if( p_item->psz_value_saved )
+                            free( p_item->psz_value_saved );
+                        p_item->psz_value_saved = 0;
+                        if( !p_item->psz_value || !p_item->psz_value_orig ||
+                            (p_item->psz_value && p_item->psz_value_orig &&
+                             strcmp(p_item->psz_value,p_item->psz_value_orig)))
+                            p_item->psz_value_saved = p_item->psz_value ?
+                                strdup( p_item->psz_value ) : 0;
+
                         vlc_mutex_unlock( p_item->p_lock );
 
 #if 0
@@ -872,6 +947,52 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
     return 0;
 }
 
+/*****************************************************************************
+ * config_CreateDir: Create configuration directory if it doesn't exist.
+ *****************************************************************************/
+int config_CreateDir( vlc_object_t *p_this, char *psz_dirname )
+{
+    if( !psz_dirname && !*psz_dirname ) return -1;
+
+#if defined( UNDER_CE )
+    {
+        wchar_t psz_new[ MAX_PATH ];
+        char psz_mod[MAX_PATH];
+        int i = 0;
+
+        /* Convert '/' into '\' */
+        while( *psz_dirname )
+        {
+            if( *psz_dirname == '/' ) psz_mod[i] = '\\';
+            else psz_mod[i] = *psz_dirname;
+            psz_dirname++;
+            i++;
+        }
+        psz_mod[i] = 0;
+
+        MultiByteToWideChar( CP_ACP, 0, psz_mod, -1, psz_new, MAX_PATH );
+        if( CreateDirectory( psz_new, NULL ) )
+        {
+            msg_Err( p_this, "could not create %s", psz_mod );
+        }
+    }
+
+#else
+#   if defined( WIN32 )
+    if( mkdir( psz_dirname ) && errno != EEXIST )
+#   else
+    if( mkdir( psz_dirname, 0755 ) && errno != EEXIST )
+#   endif
+    {
+        msg_Err( p_this, "could not create %s (%s)",
+                 psz_dirname, strerror(errno) );
+    }
+
+#endif
+
+    return 0;
+}
+
 /*****************************************************************************
  * config_SaveConfigFile: Save a module's config options.
  *****************************************************************************
@@ -891,7 +1012,8 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
  * save.
  * Really stupid no ?
  *****************************************************************************/
-int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
+int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
+                    vlc_bool_t b_autosave )
 {
     module_t *p_parser;
     vlc_list_t *p_list;
@@ -930,35 +1052,7 @@ int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
             return -1;
         }
 
-#if defined( UNDER_CE )
-        {
-            wchar_t psz_new[ MAX_PATH ];
-            MultiByteToWideChar( CP_ACP, 0, psz_filename, -1, psz_new,
-                                 MAX_PATH );
-            if( CreateDirectory( psz_new, NULL ) )
-            {
-                msg_Err( p_this, "could not create %s", psz_filename );
-            }
-        }
-
-#elif defined( HAVE_ERRNO_H )
-#   if defined( WIN32 )
-        if( mkdir( psz_filename ) && errno != EEXIST )
-#   else
-        if( mkdir( psz_filename, 0755 ) && errno != EEXIST )
-#   endif
-        {
-            msg_Err( p_this, "could not create %s (%s)",
-                             psz_filename, strerror(errno) );
-        }
-
-#else
-        if( mkdir( psz_filename ) )
-        {
-            msg_Err( p_this, "could not create %s", psz_filename );
-        }
-
-#endif
+        config_CreateDir( p_this, psz_filename );
 
         strcat( psz_filename, "/" CONFIG_FILE );
     }
@@ -1033,8 +1127,10 @@ int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
                 /* we don't have this section in our list so we need to back
                  * it up */
                 *p_index2 = 0;
+#if 0
                 msg_Dbg( p_this, "backing up config for unknown module \"%s\"",
                                  &p_line[1] );
+#endif
                 *p_index2 = ']';
 
                 b_backup = 1;
@@ -1086,8 +1182,9 @@ int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
         if( !p_parser->i_config_items )
             continue;
 
-        msg_Dbg( p_this, "saving config for module \"%s\"",
-                         p_parser->psz_object_name );
+        if( psz_module_name )
+            msg_Dbg( p_this, "saving config for module \"%s\"",
+                     p_parser->psz_object_name );
 
         fprintf( file, "[%s]", p_parser->psz_object_name );
         if( p_parser->psz_longname )
@@ -1099,10 +1196,28 @@ int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
              p_item->i_type != CONFIG_HINT_END;
              p_item++ )
         {
-            char *psz_key;
+            char  *psz_key;
+            int   i_value = p_item->i_value;
+            float f_value = p_item->f_value;
+            char  *psz_value = p_item->psz_value;
+
             if( p_item->i_type & CONFIG_HINT )
                 /* ignore hints */
                 continue;
+            /* Ignore deprecated options */
+            if( p_item->psz_current )
+                continue;
+            if( b_autosave && !p_item->b_autosave )
+            {
+                i_value = p_item->i_value_saved;
+                f_value = p_item->f_value_saved;
+                psz_value = p_item->psz_value_saved;
+                if( !psz_value ) psz_value = p_item->psz_value_orig;
+            }
+            else
+            {
+                p_item->b_dirty = VLC_FALSE;
+            }
 
             switch( p_item->i_type )
             {
@@ -1112,40 +1227,57 @@ int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
                     fprintf( file, "# %s (%s)\n", p_item->psz_text,
                              (p_item->i_type == CONFIG_ITEM_BOOL) ?
                              _("boolean") : _("integer") );
-                if( p_item->i_value == p_item->i_value_orig )
+                if( i_value == p_item->i_value_orig )
                     fprintf( file, "#" );
-                fprintf( file, "%s=%i\n", p_item->psz_name, p_item->i_value );
+                fprintf( file, "%s=%i\n", p_item->psz_name, i_value );
+
+                p_item->i_value_saved = i_value;
                 break;
+
             case CONFIG_ITEM_KEY:
                 if( p_item->psz_text )
                     fprintf( file, "# %s (%s)\n", p_item->psz_text,
                              _("key") );
-                psz_key = ConfigKeyToString( p_item->i_value );
+                if( i_value == p_item->i_value_orig )
+                    fprintf( file, "#" );
+                psz_key = ConfigKeyToString( i_value );
                 fprintf( file, "%s=%s\n", p_item->psz_name,
                          psz_key ? psz_key : "" );
                 if ( psz_key ) free( psz_key );
+
+                p_item->i_value_saved = i_value;
                 break;
-                
+
             case CONFIG_ITEM_FLOAT:
                 if( p_item->psz_text )
                     fprintf( file, "# %s (%s)\n", p_item->psz_text,
                              _("float") );
-                if( p_item->f_value == p_item->f_value_orig )
+                if( f_value == p_item->f_value_orig )
                     fprintf( file, "#" );
-                fprintf( file, "%s=%f\n", p_item->psz_name,
-                         (double)p_item->f_value );
+                fprintf( file, "%s=%f\n", p_item->psz_name, (double)f_value );
+
+                p_item->f_value_saved = f_value;
                 break;
 
             default:
                 if( p_item->psz_text )
                     fprintf( file, "# %s (%s)\n", p_item->psz_text,
                              _("string") );
-                if( (!p_item->psz_value && !p_item->psz_value_orig) ||
-                    (p_item->psz_value && p_item->psz_value_orig &&
-                     !strcmp( p_item->psz_value, p_item->psz_value_orig )) )
+                if( (!psz_value && !p_item->psz_value_orig) ||
+                    (psz_value && p_item->psz_value_orig &&
+                     !strcmp( psz_value, p_item->psz_value_orig )) )
                     fprintf( file, "#" );
                 fprintf( file, "%s=%s\n", p_item->psz_name,
-                         p_item->psz_value ? p_item->psz_value : "" );
+                         psz_value ? psz_value : "" );
+
+                if( b_autosave && !p_item->b_autosave ) break;
+
+                if( p_item->psz_value_saved ) free( p_item->psz_value_saved );
+                p_item->psz_value_saved = 0;
+                if( (psz_value && p_item->psz_value_orig &&
+                     strcmp( psz_value, p_item->psz_value_orig )) ||
+                    !psz_value || !p_item->psz_value_orig)
+                    p_item->psz_value_saved = psz_value ? strdup(psz_value):0;
             }
         }
 
@@ -1167,6 +1299,43 @@ int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
     return 0;
 }
 
+int config_AutoSaveConfigFile( vlc_object_t *p_this )
+{
+    vlc_list_t *p_list;
+    module_t *p_parser;
+    module_config_t *p_item;
+    int i_index, i_count;
+
+    /* Check if there's anything to save */
+    vlc_mutex_lock( &p_this->p_vlc->config_lock );
+    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
+    i_count = p_list->i_count;
+    for( i_index = 0; i_index < i_count; i_index++ )
+    {
+        p_parser = (module_t *)p_list->p_values[i_index].p_object ;
+
+        if( !p_parser->i_config_items ) continue;
+
+        for( p_item = p_parser->p_config;
+             p_item->i_type != CONFIG_HINT_END;
+             p_item++ )
+        {
+            if( p_item->b_autosave && p_item->b_dirty ) break;
+        }
+        if( p_item->i_type != CONFIG_HINT_END ) break;
+    }
+    vlc_list_release( p_list );
+    vlc_mutex_unlock( &p_this->p_vlc->config_lock );
+
+    if( i_index == i_count ) return VLC_SUCCESS;
+    return SaveConfigFile( p_this, 0, VLC_TRUE );
+}
+
+int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
+{
+    return SaveConfigFile( p_this, psz_module_name, VLC_FALSE );
+}
+
 /*****************************************************************************
  * config_LoadCmdLine: parse command line
  *****************************************************************************
@@ -1377,41 +1546,86 @@ int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc, char *ppsz_argv[],
 
             /* Store the configuration option */
             p_conf = config_FindConfig( p_this, psz_name );
+            if( p_conf )
+            {
+                /* Check if the option is deprecated */
+                if( p_conf->psz_current )
+                {
+                    if( !strcmp(p_conf->psz_current,"SUPPRESSED") )
+                    {
+                       if( !b_ignore_errors ) 
+                        {
+                            fprintf(stderr,
+                                    "Warning: option --%s is no longer used.\n",
+                                    p_conf->psz_name);
+                        }
+                       continue;
+                    }
+                    if( !b_ignore_errors )
+                    {
+                        if( p_conf->b_strict )
+                        {
+                            fprintf( stderr,
+                                     "Error: option --%s is deprecated. "
+                                     "Use --%s instead.\n",
+                                     p_conf->psz_name, p_conf->psz_current);
+                            /*free */
+                            for( i_index = 0; p_longopts[i_index].name; i_index++ )
+                                free( (char *)p_longopts[i_index].name );
+
+                            free( p_longopts );
+                            free( psz_shortopts );
+                            return -1;
+                        }
+                        fprintf(stderr,
+                                "Warning: option --%s is deprecated. "
+                                "You should use --%s instead.\n",
+                                p_conf->psz_name, p_conf->psz_current);
+                    }
+                    psz_name=p_conf->psz_current;
+                    p_conf = config_FindConfig( p_this, psz_name );
+                }
 
-            if( p_conf ) switch( p_conf->i_type )
+            switch( p_conf->i_type )
             {
-            case CONFIG_ITEM_STRING:
-            case CONFIG_ITEM_FILE:
-            case CONFIG_ITEM_DIRECTORY:
-            case CONFIG_ITEM_MODULE:
-                config_PutPsz( p_this, psz_name, optarg );
-                break;
-            case CONFIG_ITEM_INTEGER:
-                config_PutInt( p_this, psz_name, strtol(optarg, 0, 0));
-                break;
-            case CONFIG_ITEM_FLOAT:
-                config_PutFloat( p_this, psz_name, (float)atof(optarg) );
-                break;
-            case CONFIG_ITEM_KEY:
-                config_PutInt( p_this, psz_name, ConfigStringToKey( optarg ) );
-                break;
-            case CONFIG_ITEM_BOOL:
-                config_PutInt( p_this, psz_name, !flag );
-                break;
+                case CONFIG_ITEM_STRING:
+                case CONFIG_ITEM_FILE:
+                case CONFIG_ITEM_DIRECTORY:
+                case CONFIG_ITEM_MODULE:
+                case CONFIG_ITEM_MODULE_LIST:
+                case CONFIG_ITEM_MODULE_LIST_CAT:
+                case CONFIG_ITEM_MODULE_CAT:
+                    config_PutPsz( p_this, psz_name, optarg );
+                    break;
+                case CONFIG_ITEM_INTEGER:
+                    config_PutInt( p_this, psz_name, strtol(optarg, 0, 0));
+                    break;
+                case CONFIG_ITEM_FLOAT:
+                    config_PutFloat( p_this, psz_name, (float)atof(optarg) );
+                    break;
+                case CONFIG_ITEM_KEY:
+                    config_PutInt( p_this, psz_name, ConfigStringToKey( optarg ) );
+                    break;
+                case CONFIG_ITEM_BOOL:
+                    config_PutInt( p_this, psz_name, !flag );
+                    break;
             }
 
             continue;
         }
-
-        /* A short option has been recognized */
-        if( pp_shortopts[i_cmd] != NULL )
+    }
+    /* A short option has been recognized */
+    if( pp_shortopts[i_cmd] != NULL )
+    {
+        switch( pp_shortopts[i_cmd]->i_type )
         {
-            switch( pp_shortopts[i_cmd]->i_type )
-            {
             case CONFIG_ITEM_STRING:
             case CONFIG_ITEM_FILE:
             case CONFIG_ITEM_DIRECTORY:
             case CONFIG_ITEM_MODULE:
+            case CONFIG_ITEM_MODULE_CAT:
+            case CONFIG_ITEM_MODULE_LIST:
+            case CONFIG_ITEM_MODULE_LIST_CAT:
                 config_PutPsz( p_this, pp_shortopts[i_cmd]->psz_name, optarg );
                 break;
             case CONFIG_ITEM_INTEGER:
@@ -1457,8 +1671,9 @@ int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc, char *ppsz_argv[],
         /* Internal error: unknown option */
         if( !b_ignore_errors )
         {
-            fprintf( stderr, "%s: unknown option ",
-                             p_this->p_vlc->psz_object_name );
+            fprintf( stderr, "%s: unknown option"
+                     " or missing mandatory argument ",
+                     p_this->p_vlc->psz_object_name );
             if( optopt )
             {
                 fprintf( stderr, "`-%c'\n", optopt );
@@ -1470,6 +1685,8 @@ int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc, char *ppsz_argv[],
             fprintf( stderr, "Try `%s --help' for more information.\n",
                              p_this->p_vlc->psz_object_name );
 
+            for( i_index = 0; p_longopts[i_index].name; i_index++ )
+                free( (char *)p_longopts[i_index].name );
             free( p_longopts );
             free( psz_shortopts );
             return -1;
@@ -1501,28 +1718,31 @@ char *config_GetHomeDir( void )
     struct passwd *p_pw = NULL;
 #endif
 
-#if defined(WIN32) || defined(UNDER_CE)
+#if defined(WIN32) && !defined(UNDER_CE)
     typedef HRESULT (WINAPI *SHGETFOLDERPATH)( HWND, int, HANDLE, DWORD,
-                                               LPTSTR );
+                                               LPSTR );
+#ifndef CSIDL_FLAG_CREATE
 #   define CSIDL_FLAG_CREATE 0x8000
+#endif
+#ifndef CSIDL_APPDATA
 #   define CSIDL_APPDATA 0x1A
+#endif
+#ifndef SHGFP_TYPE_CURRENT
 #   define SHGFP_TYPE_CURRENT 0
+#endif
 
     HINSTANCE shfolder_dll;
     SHGETFOLDERPATH SHGetFolderPath ;
 
     /* load the shfolder dll to retrieve SHGetFolderPath */
-    if( ( shfolder_dll = LoadLibrary("shfolder.dll") ) != NULL )
+    if( ( shfolder_dll = LoadLibrary( _T("SHFolder.dll") ) ) != NULL )
     {
         SHGetFolderPath = (void *)GetProcAddress( shfolder_dll,
-                                                  "SHGetFolderPathA" );
+                                                  _T("SHGetFolderPathA") );
         if ( SHGetFolderPath != NULL )
         {
             p_homedir = (char *)malloc( MAX_PATH );
-            if( !p_homedir )
-            {
-                return NULL;
-            }
+            if( !p_homedir ) return NULL;
 
             /* get the "Application Data" folder for the current user */
             if( S_OK == SHGetFolderPath( NULL,
@@ -1534,9 +1754,28 @@ char *config_GetHomeDir( void )
                 return p_homedir;
             }
             free( p_homedir );
+            p_homedir = NULL;
         }
         FreeLibrary( shfolder_dll );
     }
+
+#elif defined(UNDER_CE)
+
+#ifndef CSIDL_APPDATA
+#   define CSIDL_APPDATA 0x1A
+#endif
+
+    wchar_t p_whomedir[MAX_PATH];
+
+    /* get the "Application Data" folder for the current user */
+    if( SHGetSpecialFolderPath( NULL, p_whomedir, CSIDL_APPDATA, 1 ) )
+    {
+        p_homedir = (char *)malloc( MAX_PATH );
+        if( !p_homedir ) return NULL;
+
+        sprintf( p_homedir, "%ls", p_whomedir );
+        return p_homedir;
+    }
 #endif
 
 #if defined(HAVE_GETPWUID)
@@ -1571,22 +1810,22 @@ static int ConfigStringToKey( char *psz_key )
     char *psz_parser = strchr( psz_key, '-' );
     while( psz_parser && psz_parser != psz_key )
     {
-        for( i = 0; i < sizeof(modifiers) / sizeof(key_descriptor_t); i++ )
+        for( i = 0; i < sizeof(vlc_modifiers) / sizeof(key_descriptor_t); i++ )
         {
-            if( !strncasecmp( modifiers[i].psz_key_string, psz_key,
-                              strlen( modifiers[i].psz_key_string ) ) )
+            if( !strncasecmp( vlc_modifiers[i].psz_key_string, psz_key,
+                              strlen( vlc_modifiers[i].psz_key_string ) ) )
             {
-                i_key |= modifiers[i].i_key_code;
+                i_key |= vlc_modifiers[i].i_key_code;
             }
         }
         psz_key = psz_parser + 1;
         psz_parser = strchr( psz_key, '-' );
     }
-    for( i = 0; i < sizeof(keys) / sizeof( key_descriptor_t ); i++ )
+    for( i = 0; i < sizeof(vlc_keys) / sizeof( key_descriptor_t ); i++ )
     {
-        if( !strcasecmp( keys[i].psz_key_string, psz_key ) )
+        if( !strcasecmp( vlc_keys[i].psz_key_string, psz_key ) )
         {
-            i_key |= keys[i].i_key_code;
+            i_key |= vlc_keys[i].i_key_code;
             break;
         }
     }
@@ -1605,20 +1844,20 @@ static char *ConfigKeyToString( int i_key )
     }
     *psz_key = '\0';
     p = psz_key;
-    for( index = 0; index < (sizeof(modifiers) / sizeof(key_descriptor_t));
+    for( index = 0; index < (sizeof(vlc_modifiers) / sizeof(key_descriptor_t));
          index++ )
     {
-        if( i_key & modifiers[index].i_key_code )
+        if( i_key & vlc_modifiers[index].i_key_code )
         {
-            p += sprintf( p, "%s-", modifiers[index].psz_key_string );
+            p += sprintf( p, "%s-", vlc_modifiers[index].psz_key_string );
         }
     }
-    for( index = 0; index < (sizeof(keys) / sizeof( key_descriptor_t));
+    for( index = 0; index < (sizeof(vlc_keys) / sizeof( key_descriptor_t));
          index++)
     {
-        if( (int)( i_key & ~KEY_MODIFIER ) == keys[index].i_key_code )
+        if( (int)( i_key & ~KEY_MODIFIER ) == vlc_keys[index].i_key_code )
         {
-            p += sprintf( p, "%s", keys[index].psz_key_string );
+            p += sprintf( p, "%s", vlc_keys[index].psz_key_string );
             break;
         }
     }