diff --git a/glib/glib.symbols b/glib/glib.symbols
index ddf7a2e..90d167d 100644
--- a/glib/glib.symbols
+++ b/glib/glib.symbols
@@ -835,6 +835,7 @@ g_option_context_get_main_group
 g_option_context_get_summary
 g_option_context_new
 g_option_context_parse
+g_option_context_parse_command_line
 g_option_context_set_description
 g_option_context_set_help_enabled
 g_option_context_set_ignore_unknown_options
@@ -850,6 +851,12 @@ g_option_group_set_error_hook
 g_option_group_set_parse_hooks
 g_option_group_set_translate_func
 g_option_group_set_translation_domain
+g_command_line_new
+g_command_line_new_from_utf8
+g_command_line_new_from_locale
+g_command_line_copy
+g_command_line_get_arguments
+g_command_line_free
 #endif
 #endif
 
diff --git a/glib/goption.c b/glib/goption.c
index 9747d47..cbe06dd 100644
--- a/glib/goption.c
+++ b/glib/goption.c
@@ -2,6 +2,7 @@
  *
  *  Copyright (C) 1999, 2003 Red Hat Software
  *  Copyright (C) 2004       Anders Carlsson <andersca@gnome.org>
+ *  Copyright (C) 2010       Krzysztof Kosiński <tweenk.pl@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -139,6 +140,12 @@
 #include <stdio.h>
 #include <errno.h>
 
+#ifdef G_OS_WIN32
+#define STRICT
+#include <windows.h>
+#undef STRICT
+#endif
+
 #define TRANSLATE(group, str) (((group)->translate_func ? (* (group)->translate_func) ((str), (group)->translate_data) : (str)))
 
 #define NO_ARG(entry) ((entry)->arg == G_OPTION_ARG_NONE ||       \
@@ -148,6 +155,11 @@
 #define OPTIONAL_ARG(entry) ((entry)->arg == G_OPTION_ARG_CALLBACK &&  \
                        (entry)->flags & G_OPTION_FLAG_OPTIONAL_ARG)
 
+static const gchar *unknown_program_name = "<unknown>";
+
+/* This structure stores the values that were originally present
+ * in the option variables supplied by the user. We need them to revert
+ * all changes to those values if an error occurs during the parsing. */
 typedef struct 
 {
   GOptionArg arg_type;
@@ -172,6 +184,8 @@ typedef struct
   } allocated;
 } Change;
 
+/* This structure stores changes to be done to argv once parsing
+ * is finished. */
 typedef struct
 {
   gchar **ptr;
@@ -195,12 +209,7 @@ struct _GOptionContext
   
   GOptionGroup    *main_group;
 
-  /* We keep a list of change so we can revert them */
   GList           *changes;
-  
-  /* We also keep track of all argv elements 
-   * that should be NULLed or modified.
-   */
   GList           *pending_nulls;
 };
 
@@ -225,6 +234,12 @@ struct _GOptionGroup
   GOptionErrorFunc error_func;
 };
 
+struct _GCommandLine
+{
+  gchar    **argv;
+  gint       argc;
+};
+
 static void free_changes_list (GOptionContext *context,
 			       gboolean        revert);
 static void free_pending_nulls (GOptionContext *context,
@@ -1118,7 +1133,7 @@ add_pending_null (GOptionContext *context,
 
   context->pending_nulls = g_list_prepend (context->pending_nulls, n);
 }
-		  
+
 static gboolean
 parse_arg (GOptionContext *context,
 	   GOptionGroup   *group,
@@ -1126,7 +1141,7 @@ parse_arg (GOptionContext *context,
 	   const gchar    *value,
 	   const gchar    *option_name,
 	   GError        **error)
-     
+
 {
   Change *change;
 
@@ -1144,31 +1159,21 @@ parse_arg (GOptionContext *context,
       }	     
     case G_OPTION_ARG_STRING:
       {
-	gchar *data;
-	
-	data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
-
-	if (!data)
-	  return FALSE;
+	gchar *data = g_strdup (value);
 
 	change = get_change (context, G_OPTION_ARG_STRING,
 			     entry->arg_data);
 	g_free (change->allocated.str);
-	
+
 	change->prev.str = *(gchar **)entry->arg_data;
 	change->allocated.str = data;
-	
+
 	*(gchar **)entry->arg_data = data;
 	break;
       }
     case G_OPTION_ARG_STRING_ARRAY:
       {
-	gchar *data;
-
-	data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
-
-	if (!data)
-	  return FALSE;
+	gchar *data = g_strdup (value);
 
 	change = get_change (context, G_OPTION_ARG_STRING_ARRAY,
 			     entry->arg_data);
@@ -1197,14 +1202,11 @@ parse_arg (GOptionContext *context,
       {
 	gchar *data;
 
-#ifdef G_OS_WIN32
-	data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
+	data = g_filename_from_utf8 (value, -1, NULL, NULL, error);
 	
 	if (!data)
 	  return FALSE;
-#else
-	data = g_strdup (value);
-#endif
+
 	change = get_change (context, G_OPTION_ARG_FILENAME,
 			     entry->arg_data);
 	g_free (change->allocated.str);
@@ -1219,15 +1221,12 @@ parse_arg (GOptionContext *context,
     case G_OPTION_ARG_FILENAME_ARRAY:
       {
 	gchar *data;
-	
-#ifdef G_OS_WIN32
-	data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
+
+	data = g_filename_from_utf8 (value, -1, NULL, NULL, error);
 	
 	if (!data)
 	  return FALSE;
-#else
-	data = g_strdup (value);
-#endif
+
 	change = get_change (context, G_OPTION_ARG_STRING_ARRAY,
 			     entry->arg_data);
 
@@ -1276,15 +1275,9 @@ parse_arg (GOptionContext *context,
 	else if (entry->flags & G_OPTION_FLAG_NO_ARG)
 	  data = NULL;
 	else if (entry->flags & G_OPTION_FLAG_FILENAME)
-	  {
-#ifdef G_OS_WIN32
-  	    data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
-#else
-	    data = g_strdup (value);
-#endif
-	  }
+  	  data = g_filename_from_utf8 (value, -1, NULL, NULL, error);
 	else
-	  data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
+	  data = g_strdup (value);
 
 	if (!(entry->flags & (G_OPTION_FLAG_NO_ARG|G_OPTION_FLAG_OPTIONAL_ARG)) && 
 	    !data)
@@ -1597,10 +1590,10 @@ free_changes_list (GOptionContext *context,
 	      break;
 	    case G_OPTION_ARG_STRING:
 	    case G_OPTION_ARG_FILENAME:
-              g_free (change->allocated.str);
+	      g_free (change->allocated.str);
 	      *(gchar **)change->arg_data = change->prev.str;
 	      break;
-	    case G_OPTION_ARG_STRING_ARRAY:
+	    case G_OPTION_ARG_STRING_ARRAY: 
 	    case G_OPTION_ARG_FILENAME_ARRAY:
 	      g_strfreev (change->allocated.array.data);
 	      *(gchar ***)change->arg_data = change->prev.array;
@@ -1611,6 +1604,7 @@ free_changes_list (GOptionContext *context,
 	    case G_OPTION_ARG_INT64:
 	      *(gint64 *)change->arg_data = change->prev.int64;
 	      break;
+
 	    default:
 	      g_assert_not_reached ();
 	    }
@@ -1637,12 +1631,17 @@ free_pending_nulls (GOptionContext *context,
 	{
 	  if (n->value)
 	    {
-	      /* Copy back the short options */
+	      /* Remove parsed short options */
 	      *(n->ptr)[0] = '-';	      
 	      strcpy (*n->ptr + 1, n->value);
 	    }
 	  else
-	    *n->ptr = NULL;
+	    {
+	      /* (*n->ptr) points into GCommandLine, so we must free it
+	       * to avoid a leak */
+	      g_free (*n->ptr);
+	      *n->ptr = NULL;
+	    }
 	}
       
       g_free (n->value);
@@ -1654,10 +1653,9 @@ free_pending_nulls (GOptionContext *context,
 }
 
 /**
- * g_option_context_parse:
+ * g_option_context_parse_command_line:
  * @context: a #GOptionContext
- * @argc: a pointer to the number of command line arguments
- * @argv: a pointer to the array of command line arguments
+ * @command_line: command line to parse
  * @error: a return location for errors 
  * 
  * Parses the command line arguments, recognizing options
@@ -1666,50 +1664,51 @@ free_pending_nulls (GOptionContext *context,
  * called.
  *
  * If the parsing is successful, any parsed arguments are
- * removed from the array and @argc and @argv are updated 
- * accordingly. A '--' option is stripped from @argv
+ * removed from the command line. Calling
+ * g_command_line_get_arguments() after parsing will only
+ * return the unparsed arguments. A '--' option is removed
  * unless there are unparsed options before and after it, 
  * or some of the options after it start with '-'. In case 
- * of an error, @argc and @argv are left unmodified. 
+ * of an error, the command line is left unmodified. 
  *
  * If automatic <option>--help</option> support is enabled
  * (see g_option_context_set_help_enabled()), and the 
- * @argv array contains one of the recognized help options,
+ * command line contains one of the recognized help options,
  * this function will produce help output to stdout and
  * call <literal>exit (0)</literal>.
- *
- * Note that function depends on the 
- * <link linkend="setlocale">current locale</link> for 
- * automatic character set conversion of string and filename
- * arguments.
  * 
  * Return value: %TRUE if the parsing was successful, 
  *               %FALSE if an error occurred
  *
- * Since: 2.6
+ * Since: 2.24
  **/
 gboolean
-g_option_context_parse (GOptionContext   *context,
-			gint             *argc,
-			gchar          ***argv,
-			GError          **error)
+g_option_context_parse_command_line (GOptionContext *context,
+                                     GCommandLine   *command_line,
+                                     GError        **error)
 {
+  g_return_val_if_fail (command_line != NULL, FALSE);
+
   gint i, j, k;
   GList *list;
+  gint *argc;
+  gchar ***argv;
+
+  argc = &command_line->argc;
+  argv = &command_line->argv;
 
   /* Set program name */
   if (!g_get_prgname())
     {
-      if (argc && argv && *argc)
-	{
+      if (*argc >= 1)
+        {
 	  gchar *prgname;
-	  
 	  prgname = g_path_get_basename ((*argv)[0]);
 	  g_set_prgname (prgname);
 	  g_free (prgname);
 	}
       else
-	g_set_prgname ("<unknown>");
+	g_set_prgname (unknown_program_name);
     }
 
   /* Call pre-parse hooks */
@@ -1735,207 +1734,203 @@ g_option_context_parse (GOptionContext   *context,
 	goto fail;
     }
 
-  if (argc && argv)
+  gboolean stop_parsing = FALSE;
+  gboolean has_unknown = FALSE;
+  gint separator_pos = 0;
+
+  for (i = 1; i < *argc; i++)
     {
-      gboolean stop_parsing = FALSE;
-      gboolean has_unknown = FALSE;
-      gint separator_pos = 0;
+      gchar *arg, *dash;
+      gboolean parsed = FALSE;
 
-      for (i = 1; i < *argc; i++)
+      if ((*argv)[i][0] == '-' && (*argv)[i][1] != '\0' && !stop_parsing)
 	{
-	  gchar *arg, *dash;
-	  gboolean parsed = FALSE;
-
-	  if ((*argv)[i][0] == '-' && (*argv)[i][1] != '\0' && !stop_parsing)
+	  if ((*argv)[i][1] == '-')
 	    {
-	      if ((*argv)[i][1] == '-')
-		{
-		  /* -- option */
+	      /* -- option */
 
-		  arg = (*argv)[i] + 2;
+	      arg = (*argv)[i] + 2;
 
-		  /* '--' terminates list of arguments */
-		  if (*arg == 0)
-		    {
-		      separator_pos = i;
-		      stop_parsing = TRUE;
-		      continue;
-		    }
+	      /* '--' terminates list of arguments */
+	      if (*arg == 0)
+		{
+		  separator_pos = i;
+		  stop_parsing = TRUE;
+		  continue;
+		}
 
-		  /* Handle help options */
-		  if (context->help_enabled)
+	      /* Handle help options */
+	      if (context->help_enabled)
+		{
+		  if (strcmp (arg, "help") == 0)
+		    print_help (context, TRUE, NULL);
+		  else if (strcmp (arg, "help-all") == 0)
+		    print_help (context, FALSE, NULL);  
+		  else if (strncmp (arg, "help-", 5) == 0)
 		    {
-		      if (strcmp (arg, "help") == 0)
-			print_help (context, TRUE, NULL);
-		      else if (strcmp (arg, "help-all") == 0)
-			print_help (context, FALSE, NULL);		      
-		      else if (strncmp (arg, "help-", 5) == 0)
+		      list = context->groups;
+		      
+		      while (list)
 			{
-			  list = context->groups;
+			  GOptionGroup *group = list->data;
+			  
+			  if (strcmp (arg + 5, group->name) == 0)
+			    print_help (context, FALSE, group);
 			  
-			  while (list)
-			    {
-			      GOptionGroup *group = list->data;
-			      
-			      if (strcmp (arg + 5, group->name) == 0)
-				print_help (context, FALSE, group);		      			      
-			      
-			      list = list->next;
-			    }
+			  list = list->next;
 			}
 		    }
+		}
 
-		  if (context->main_group &&
-		      !parse_long_option (context, context->main_group, &i, arg,
+	      if (context->main_group &&
+		  !parse_long_option (context, context->main_group, &i, arg,
+				      FALSE, argc, argv, error, &parsed))
+		goto fail;
+
+	      if (parsed)
+		continue;
+	      
+	      /* Try the groups */
+	      list = context->groups;
+	      while (list)
+		{
+		  GOptionGroup *group = list->data;
+		  
+		  if (!parse_long_option (context, group, &i, arg, 
 					  FALSE, argc, argv, error, &parsed))
 		    goto fail;
-
+		  
 		  if (parsed)
-		    continue;
+		    break;
 		  
+		  list = list->next;
+		}
+	      
+	      if (parsed)
+		continue;
+
+	      /* Now look for --<group>-<option> */
+	      dash = strchr (arg, '-');
+	      if (dash)
+		{
 		  /* Try the groups */
 		  list = context->groups;
 		  while (list)
 		    {
 		      GOptionGroup *group = list->data;
 		      
-		      if (!parse_long_option (context, group, &i, arg, 
-					      FALSE, argc, argv, error, &parsed))
-			goto fail;
-		      
-		      if (parsed)
-			break;
+		      if (strncmp (group->name, arg, dash - arg) == 0)
+			{
+			  if (!parse_long_option (context, group, &i, dash + 1,
+						  TRUE, argc, argv, error, &parsed))
+			    goto fail;
+			  
+			  if (parsed)
+			    break;
+			}
 		      
 		      list = list->next;
 		    }
-		  
-		  if (parsed)
-		    continue;
-
-		  /* Now look for --<group>-<option> */
-		  dash = strchr (arg, '-');
-		  if (dash)
+		}
+	      
+	      if (context->ignore_unknown)
+		continue;
+	    }
+	  else
+	    { /* short option */
+	      gint new_i = i, arg_length;
+	      gboolean *nulled_out = NULL;
+	      gboolean has_h_entry = context_has_h_entry (context);
+	      arg = (*argv)[i] + 1;
+	      arg_length = strlen (arg);
+	      nulled_out = g_newa (gboolean, arg_length);
+	      memset (nulled_out, 0, arg_length * sizeof (gboolean));
+	      for (j = 0; j < arg_length; j++)
+		{
+		  if (context->help_enabled && (arg[j] == '?' ||
+		    (arg[j] == 'h' && !has_h_entry)))
+		    print_help (context, TRUE, NULL);
+		  parsed = FALSE;
+		  if (context->main_group &&
+		      !parse_short_option (context, context->main_group,
+					   i, &new_i, arg[j],
+					   argc, argv, error, &parsed))
+		    goto fail;
+		  if (!parsed)
 		    {
 		      /* Try the groups */
 		      list = context->groups;
 		      while (list)
 			{
 			  GOptionGroup *group = list->data;
-			  
-			  if (strncmp (group->name, arg, dash - arg) == 0)
-			    {
-			      if (!parse_long_option (context, group, &i, dash + 1,
-						      TRUE, argc, argv, error, &parsed))
-				goto fail;
-			      
-			      if (parsed)
-				break;
-			    }
-			  
+			  if (!parse_short_option (context, group, i, &new_i, arg[j],
+						   argc, argv, error, &parsed))
+			    goto fail;
+			  if (parsed)
+			    break;
 			  list = list->next;
 			}
 		    }
 		  
-		  if (context->ignore_unknown)
+		  if (context->ignore_unknown && parsed)
+		    nulled_out[j] = TRUE;
+		  else if (context->ignore_unknown)
 		    continue;
+		  else if (!parsed)
+		    break;
+		  /* !context->ignore_unknown && parsed */
 		}
-	      else
-		{ /* short option */
-		  gint new_i = i, arg_length;
-		  gboolean *nulled_out = NULL;
-                  gboolean has_h_entry = context_has_h_entry (context);
-		  arg = (*argv)[i] + 1;
-                  arg_length = strlen (arg);
-                  nulled_out = g_newa (gboolean, arg_length);
-                  memset (nulled_out, 0, arg_length * sizeof (gboolean));
+	      if (context->ignore_unknown)
+		{
+		  gchar *new_arg = NULL; 
+		  gint arg_index = 0;
 		  for (j = 0; j < arg_length; j++)
 		    {
-		      if (context->help_enabled && (arg[j] == '?' ||
-                        (arg[j] == 'h' && !has_h_entry)))
-                        print_help (context, TRUE, NULL);
-                      parsed = FALSE;
-		      if (context->main_group &&
-			  !parse_short_option (context, context->main_group,
-					       i, &new_i, arg[j],
-					       argc, argv, error, &parsed))
-                        goto fail;
-		      if (!parsed)
-			{
-			  /* Try the groups */
-			  list = context->groups;
-			  while (list)
-			    {
-			      GOptionGroup *group = list->data;
-			      if (!parse_short_option (context, group, i, &new_i, arg[j],
-						       argc, argv, error, &parsed))
-				goto fail;
-			      if (parsed)
-				break;
-			      list = list->next;
-			    }
-			}
-                      
-		      if (context->ignore_unknown && parsed)
-                        nulled_out[j] = TRUE;
-                      else if (context->ignore_unknown)
-                        continue;
-                      else if (!parsed)
-                        break;
-                      /* !context->ignore_unknown && parsed */
-		    }
-		  if (context->ignore_unknown)
-		    {
-		      gchar *new_arg = NULL; 
-		      gint arg_index = 0;
-		      for (j = 0; j < arg_length; j++)
+		      if (!nulled_out[j])
 			{
-			  if (!nulled_out[j])
-			    {
-			      if (!new_arg)
-				new_arg = g_malloc (arg_length + 1);
-			      new_arg[arg_index++] = arg[j];
-			    }
+			  if (!new_arg)
+			    new_arg = g_malloc (arg_length + 1);
+			  new_arg[arg_index++] = arg[j];
 			}
-		      if (new_arg)
-			new_arg[arg_index] = '\0';
-		      add_pending_null (context, &((*argv)[i]), new_arg);
-		    }
-		  else if (parsed)
-		    {
-		      add_pending_null (context, &((*argv)[i]), NULL);
-		      i = new_i;
 		    }
+		  if (new_arg)
+		    new_arg[arg_index] = '\0';
+		  add_pending_null (context, &((*argv)[i]), new_arg);
 		}
-	      
-	      if (!parsed)
-		has_unknown = TRUE;
-
-	      if (!parsed && !context->ignore_unknown)
+	      else if (parsed)
 		{
-		  g_set_error (error,
-			       G_OPTION_ERROR, G_OPTION_ERROR_UNKNOWN_OPTION,
-				   _("Unknown option %s"), (*argv)[i]);
-		  goto fail;
+		  add_pending_null (context, &((*argv)[i]), NULL);
+		  i = new_i;
 		}
 	    }
-	  else
+	  
+	  if (!parsed)
+	    has_unknown = TRUE;
+
+	  if (!parsed && !context->ignore_unknown)
 	    {
-	      /* Collect remaining args */
-	      if (context->main_group &&
-		  !parse_remaining_arg (context, context->main_group, &i,
-					argc, argv, error, &parsed))
-		goto fail;
-	      
-	      if (!parsed && (has_unknown || (*argv)[i][0] == '-'))
-		separator_pos = 0;
+	      g_set_error (error,
+			   G_OPTION_ERROR, G_OPTION_ERROR_UNKNOWN_OPTION,
+			       _("Unknown option %s"), (*argv)[i]);
+	      goto fail;
 	    }
 	}
-
-      if (separator_pos > 0)
-	add_pending_null (context, &((*argv)[separator_pos]), NULL);
-	
+      else
+	{
+	  /* Collect remaining args */
+	  if (context->main_group &&
+	      !parse_remaining_arg (context, context->main_group, &i,
+				    argc, argv, error, &parsed))
+	    goto fail;
+	  
+	  if (!parsed && (has_unknown || (*argv)[i][0] == '-'))
+	    separator_pos = 0;
+	}
     }
 
+  if (separator_pos > 0)
+    add_pending_null (context, &((*argv)[separator_pos]), NULL);
+
   /* Call post-parse hooks */
   list = context->groups;
   while (list)
@@ -1958,28 +1953,27 @@ g_option_context_parse (GOptionContext   *context,
 						     context->main_group->user_data, error))
 	goto fail;
     }
-  
-  if (argc && argv)
+
+  /* Remove parsed options from argv */
+  free_pending_nulls (context, TRUE);
+
+  /* Sanitize argv so that it doesn't contain NULLs */
+  for (i = 1; i < *argc; i++)
     {
-      free_pending_nulls (context, TRUE);
-      
-      for (i = 1; i < *argc; i++)
+      for (k = i; k < *argc; k++)
+	if ((*argv)[k] != NULL)
+	  break;
+
+      if (k > i)
 	{
-	  for (k = i; k < *argc; k++)
-	    if ((*argv)[k] != NULL)
-	      break;
-	  
-	  if (k > i)
+	  k -= i;
+	  for (j = i + k; j < *argc; j++)
 	    {
-	      k -= i;
-	      for (j = i + k; j < *argc; j++)
-		{
-		  (*argv)[j-k] = (*argv)[j];
-		  (*argv)[j] = NULL;
-		}
-	      *argc -= k;
+	      (*argv)[j-k] = (*argv)[j];
+	      (*argv)[j] = NULL;
 	    }
-	}      
+	  *argc -= k;
+	}
     }
 
   return TRUE;
@@ -2008,7 +2002,59 @@ g_option_context_parse (GOptionContext   *context,
 
   return FALSE;
 }
-				   
+
+/**
+ * g_option_context_parse:
+ * @context: a #GOptionContext
+ * @argc: a pointer to the number of command line arguments
+ * @argv: a pointer to the array of command line arguments
+ * @error: a return location for errors 
+ * 
+ * Works like g_option_context_parse_command_line.
+ * The main difference is that it directly accepts pointers
+ * to the arguments of main().
+ *
+ * This function does not work correctly on Windows. Specifically,
+ * it cannot handle filenames with characters not representable
+ * in the system codepage. To get the correct behavior on all
+ * platforms, call g_option_context_parse_command_line()
+ * with a command line created from g_command_line_new().
+ *
+ * Deprecated: 2.24: Use g_option_context_parse_command_line() instead.
+ * Since: 2.6
+ **/
+gboolean
+g_option_context_parse (GOptionContext   *context,
+			gint             *argc,
+			gchar          ***argv,
+			GError          **error)
+{
+  GCommandLine *command_line = NULL;
+  gboolean ret = TRUE;
+
+  if (argc && argv && *argc && *argv)
+    {
+      command_line = g_command_line_new_from_locale (*argc, (const gchar **) *argv);
+      ret = g_option_context_parse_command_line (context, command_line, error);
+
+      if (ret)
+        {
+          gint i;
+          for (i = 0; i < command_line->argc; i++)
+            (*argv)[i] = g_locale_from_utf8 (command_line->argv[i], -1, NULL, NULL, NULL);
+	  for (i = command_line->argc; i < *argc; i++)
+	    (*argv)[i] = NULL;
+
+	  *argc = command_line->argc;
+        }
+      g_command_line_free (command_line);
+    }
+  else
+    g_set_prgname (unknown_program_name);
+
+  return ret;
+}
+
 /**
  * g_option_group_new:
  * @name: the name for the option group, this is used to provide
@@ -2382,5 +2428,216 @@ g_option_context_get_description (GOptionContext *context)
 }
 
 
+/**
+ * g_command_line_new:
+ * @argc: Number of arguments
+ * @argv: Array of arguments
+ *
+ * Creates a new command line based on program arguments. On Windows,
+ * it inspects the global variables __argc and __wargv to access
+ * the Unicode command line. On all other systems, it creates
+ * the command line based on parameters given to it.
+ *
+ * If need to modify the command line before parsing with
+ * #GOptionContext, use g_command_line_get_arguments() combined
+ * with g_command_line_new_from_utf8().
+ *
+ * Returns: newly created command line
+ * Since: 2.24
+ */
+GCommandLine *
+g_command_line_new (gint          argc,
+                    const gchar **argv)
+{
+#ifdef G_OS_WIN32
+  (void) argc;
+  (void) argv;
+  return g_command_line_new_from_win32_wargv ();
+#else
+  return g_command_line_new_from_locale (argc, argv);
+#endif
+}
+
+
+/**
+ * g_command_line_new_from_locale:
+ * @argc: Number of arguments, or -1 if argv is NULL-terminated
+ * @argv: Array of arguments
+ *
+ * Creates a command line from an array of arguments in locale encoding.
+ *
+ * Returns: newly created command line
+ * Since: 2.24
+ */
+GCommandLine *
+g_command_line_new_from_locale (gint          argc,
+                                const gchar **argv)
+{
+  g_return_val_if_fail (argv != NULL, NULL);
+
+  GCommandLine *command_line;
+  gint i;
+  gint real_argc;
+
+  if (argc == -1)
+    real_argc = g_strv_length ((gchar **) argv);
+  else
+    real_argc = argc;
+
+  command_line = g_new0 (GCommandLine, 1);
+  command_line->argc = real_argc;
+  command_line->argv = g_new0 (gchar *, real_argc + 1);
+
+  for (i = 0; i < real_argc; i++)
+    command_line->argv[i] = g_locale_to_utf8 (argv[i], -1, NULL, NULL, NULL);
+
+  command_line->argv[real_argc] = NULL;
+
+  return command_line;
+}
+
+
+/**
+ * g_command_line_new_from_utf8:
+ * @argc: Number of arguments, or -1 if argv is NULL-terminated
+ * @argv: Array of arguments
+ *
+ * Creates a command line from an array of arguments in UTF-8 encoding.
+ *
+ * Returns: newly created command line
+ * Since: 2.24
+ */
+GCommandLine *
+g_command_line_new_from_utf8 (gint          argc,
+                              gchar const **argv)
+{
+  g_return_val_if_fail (argv != NULL, NULL);
+
+  GCommandLine *command_line;
+
+  command_line = g_new0 (GCommandLine, 1);
+  command_line->argc = argc;
+
+  if (argc == -1)
+    command_line->argv = g_strdupv ((gchar **) argv);
+  else
+    {
+      command_line->argv = g_new0 (gchar *, argc + 1);
+
+      gint i;
+      for (i = 0; i < argc; i++)
+	command_line->argv[i] = g_strdup (argv[i]);
+
+      command_line->argv[argc] = NULL;
+    }
+
+  return command_line;
+}
+
+
+/**
+ * g_command_line_copy:
+ * @command_line: The command line to be copied
+ *
+ * Copies the command line. Use this if you want to preserve the original
+ * command line after parsing.
+ *
+ * Returns: newly allocated copy of the command line
+ * Since: 2.24
+ */
+GCommandLine *
+g_command_line_copy (GCommandLine *command_line)
+{
+  g_return_val_if_fail (command_line != NULL, NULL);
+
+  GCommandLine *copy;
+
+  copy = g_new0 (GCommandLine, 1);
+  copy->argc = command_line->argc;
+  copy->argv = g_strdupv (command_line->argv);
+
+  return copy;
+}
+
+
+/**
+ * g_command_line_get_arguments:
+ * @command_line: The command line
+ * @argc: Place to store the argument count, or %NULL
+ * @argv: Place to store the array of arguments, or %NULL
+ *
+ * Creates an array of UTF-8 encoded strings that contain the unparsed
+ * command line arguments. The returned array is %NULL-terminated.
+ * It should be freed with g_strfreev when no longer needed.
+ *
+ * Since: 2.24
+ */
+void
+g_command_line_get_arguments (GCommandLine   *command_line,
+                              gint           *argc,
+                              gchar        ***argv)
+{
+  g_return_if_fail (command_line != NULL);
+
+  if (argc)
+    *argc = command_line->argc;
+  if (argv)
+    *argv = g_strdupv (command_line->argv);
+}
+
+
+/**
+ * g_command_line_free:
+ * @command_line: The command line to free
+ *
+ * Frees memory occupied by a command line.
+ * 
+ * Since: 2.24
+ */
+void
+g_command_line_free (GCommandLine *command_line)
+{
+  g_return_if_fail (command_line != NULL);
+
+  g_strfreev (command_line->argv);
+  g_free (command_line);
+}
+
+
+#ifdef G_OS_WIN32
+/**
+ * g_command_line_new_from_win32_wargv:
+ *
+ * Creates a new command line based on Windows Unicode command line
+ * stored in global variables __argc and __wargv.
+ *
+ * Unlike the arguments that the system passes to main and WinMain,
+ * the Unicode command line contains sufficient information
+ * to correctly open files with names that are not representable
+ * in the system codepage. This situation can arise when e.g. files
+ * with Chinese names are opened on an English version of Windows.
+ *
+ * Returns: newly created command line
+ * Since: 2.24
+ */
+GCommandLine *
+g_command_line_new_from_win32_wargv (void)
+{
+  GCommandLine *command_line;
+  int i;
+
+  command_line = g_new0 (GCommandLine, 1);
+  command_line->argc = __argc;
+  command_line->argv = g_new0 (gchar *, __argc + 1);
+
+  for (i = 0; i < __argc; i++)
+    command_line->argv[i] = g_utf16_to_utf8 ((gunichar2 *) __wargv[i], -1, NULL, NULL, NULL);
+
+  command_line->argv[__argc] = NULL;
+
+  return command_line;
+}
+#endif
+
 #define __G_OPTION_C__
 #include "galiasdef.c"
diff --git a/glib/goption.h b/glib/goption.h
index f096504..a7ad92e 100644
--- a/glib/goption.h
+++ b/glib/goption.h
@@ -54,6 +54,14 @@ typedef struct _GOptionGroup   GOptionGroup;
 typedef struct _GOptionEntry   GOptionEntry;
 
 /**
+ * GCommandLine:
+ *
+ * This structure represents an UTF-8 encoded command line. It can be created
+ * from various sources. All fields of this structure are private.
+ */
+typedef struct _GCommandLine GCommandLine;
+
+/**
  * GOptionFlags:
  * @G_OPTION_FLAG_HIDDEN: The option doesn't appear in <option>--help</option>
  *  output.
@@ -329,6 +337,9 @@ gboolean        g_option_context_parse            (GOptionContext      *context,
 						   gint                *argc,
 						   gchar             ***argv,
 						   GError             **error);
+gboolean        g_option_context_parse_command_line(GOptionContext *context,
+                                                    GCommandLine   *command_line,
+                                                    GError        **error);
 void            g_option_context_set_translate_func (GOptionContext     *context,
 						     GTranslateFunc      func,
 						     gpointer            data,
@@ -365,6 +376,22 @@ void          g_option_group_set_translate_func     (GOptionGroup       *group,
 void          g_option_group_set_translation_domain (GOptionGroup       *group,
 						     const gchar        *domain);
 
+GCommandLine *g_command_line_new		    (gint          argc,
+						     const gchar **argv);
+GCommandLine *g_command_line_new_from_utf8	    (gint          argc,
+						     const gchar **argv);
+GCommandLine *g_command_line_new_from_locale	    (gint argc,
+						     const gchar **argv);
+GCommandLine *g_command_line_copy		    (GCommandLine *command_line);
+void          g_command_line_get_arguments	    (GCommandLine *command_line,
+						     gint         *argc,
+						     gchar      ***argv);
+void          g_command_line_free		    (GCommandLine *command_line);
+
+#ifdef G_OS_WIN32
+GCommandLine *g_command_line_new_from_win32_wargv   (void);
+#endif
+
 G_END_DECLS
 
 #endif /* __G_OPTION_H__ */
