Revision: 4550 http://geany.svn.sourceforge.net/geany/?rev=4550&view=rev Author: statc Date: 2010-01-24 20:25:17 +0000 (Sun, 24 Jan 2010)
Log Message: ----------- Add "reverse parser" of GOptionEntry. Handle all command-line options.
Modified Paths: -------------- branches/sm/src/main.c branches/sm/src/main.h branches/sm/src/sm.c branches/sm/src/utils.c branches/sm/src/utils.h
Modified: branches/sm/src/main.c =================================================================== --- branches/sm/src/main.c 2010-01-24 20:24:52 UTC (rev 4549) +++ branches/sm/src/main.c 2010-01-24 20:25:17 UTC (rev 4550) @@ -118,8 +118,15 @@ static gboolean dummy = FALSE; static gchar * libsm_client_id = NULL;
+/* WARNING: Do not change values of variables where values of command-line options are stored! + * This is, they must remain unchanged after `g_option_context_parse' returns. + * Otherwise, "restart command" for X session management will be filled improperly. + * + * NOTE: Currently optentries of type G_OPTION_ARG_CALLBACK are not supported by + * X session management support implementation. + */ /* in alphabetical order of short options */ -static GOptionEntry entries[] = +GOptionEntry optentries[] = { { "column", 0, 0, G_OPTION_ARG_INT, &cl_options.goto_column, N_("Set initial column number for the first opened file (useful in conjunction with --line)"), NULL }, { "config", 'c', 0, G_OPTION_ARG_FILENAME, &alternate_config, N_("Use an alternate configuration directory"), NULL }, @@ -146,10 +153,39 @@ { "version", 'V', 0, G_OPTION_ARG_NONE, &show_version, N_("Show version and exit"), NULL }, { "dummy", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &dummy, NULL, NULL }, /* for +NNN line number arguments */ { "libsm-client-id", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &libsm_client_id, NULL, NULL }, + /* add new options here and in `optentries_aux' below */ { NULL, 0, 0, 0, NULL, NULL, NULL } };
+GeanyOptionEntryAux optentries_aux[] = { + {FALSE}, /* "column" */ + {TRUE}, /* "config" */ + {FALSE}, /* "ft-names */ + {FALSE}, /* "generate-tags" */ + {FALSE}, /* "no-preprocessing" */ +#ifdef HAVE_SOCKET + {TRUE}, /* "new-instance" */ + {TRUE}, /* "socket-file" */ +#endif + {FALSE}, /* "line" */ + {TRUE}, /* "no-msgwin" */ + {TRUE}, /* "no-ctags" */ +#ifdef HAVE_PLUGINS + {TRUE}, /* "no-plugins" */ +#endif + {FALSE}, /* "print-prefix" */ + {TRUE}, /* "no-session" */ +#ifdef HAVE_VTE + {TRUE}, /* "no-terminal" */ + {TRUE}, /* "vte-lib" */ +#endif + {TRUE}, /* "verbose" */ + {FALSE}, /* "version" */ + {FALSE}, /* "dummy" */ + {FALSE}, /* "libsm-client-id" option is handled separately */ +};
+ static void setup_window_position(void) { /* interprets the saved window geometry */ @@ -489,7 +525,7 @@ }
context = g_option_context_new(_("[FILES...]")); - g_option_context_add_main_entries(context, entries, GETTEXT_PACKAGE); + g_option_context_add_main_entries(context, optentries, GETTEXT_PACKAGE); g_option_group_set_translation_domain(g_option_context_get_main_group(context), GETTEXT_PACKAGE); g_option_context_add_group(context, gtk_get_option_group(FALSE)); g_option_context_parse(context, argc, argv, &error);
Modified: branches/sm/src/main.h =================================================================== --- branches/sm/src/main.h 2010-01-24 20:24:52 UTC (rev 4549) +++ branches/sm/src/main.h 2010-01-24 20:25:17 UTC (rev 4550) @@ -25,8 +25,22 @@ #ifndef GEANY_MAIN_H #define GEANY_MAIN_H
+/** Information about command line entries that can not be stored in GOptionEntry. */ typedef struct { + /** + * Indicates whether the value of a command-line option should go to "restart command". + * See X session management support implementation in sm.{c,h}. + */ + gboolean persist_upon_restart; +} +GeanyOptionEntryAux; + +extern GOptionEntry optentries[]; +extern GeanyOptionEntryAux optentries_aux[]; + +typedef struct +{ gboolean new_instance; gchar *socket_filename; gboolean load_session;
Modified: branches/sm/src/sm.c =================================================================== --- branches/sm/src/sm.c 2010-01-24 20:24:52 UTC (rev 4549) +++ branches/sm/src/sm.c 2010-01-24 20:25:17 UTC (rev 4550) @@ -390,54 +390,38 @@ */ static void sm_set_runtime_props(SmcConn smcon) { - const gint page_count = gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.notebook)); + GArray * arr = g_array_new(FALSE, FALSE, sizeof(SmPropValue)); + gint arr_filenames_begin = -1;
- GArray * arr; - gint arr_real_len, arr_filenames_begin; - - SmProp restart_command_prop, clone_command_prop; - SmPropValue * val; + GOptionEntry * optentry; + SmPropValue val; SmProp * prop; + SmProp restart_command_prop, clone_command_prop; gint i;
- /* - * Allocate space for `page_count+5' elements: - * * two elements for program name and client ID; - * * possibly one element for "--no-session" option; - * * possibly one element for "--new-instance" option; - * * possible one element for "--" to separate options and filenames; - * * max `page_count' elements for file paths. - * The number of actually used elements is saved in `arr_real_len'. - * Variable `arr_filenames_begin' stores the index in the array where - * the list of filenames begin. If there are no filenames in `arr', - * the value is -1. - */ - arr = g_array_sized_new(FALSE, FALSE, sizeof(SmPropValue), page_count + 5); - arr_real_len = 0; - arr_filenames_begin = -1; - - ((SmPropValue *)arr->data)[arr_real_len++] = sm_program_val; - ((SmPropValue *)arr->data)[arr_real_len++] = sm_client_id_arg_val; - - if (!cl_options.load_session) + g_array_append_val(arr, sm_program_val); + /* "libsm-client-id" option requires special handling */ + g_array_append_val(arr, sm_client_id_arg_val); + /* handle other command-line options */ + for (i = 0, optentry = optentries; optentry->long_name; i++, optentry++) { - val = ((SmPropValue *)arr->data) + arr_real_len++; - val->length = 2; /* length of "-s" */ - val->value = "-s"; + if (optentries_aux[i].persist_upon_restart) + { + GArray * arr2 = utils_option_entry_reverse_parse(optentry); + gchar ** ss = (gchar **)arr2->data; + for (; *ss; ss++) + { + val.length = strlen(*ss); + val.value = *ss; + g_array_append_val(arr, val); + } + /* elements are freed after `arr' is used */ + g_array_free(arr2, TRUE); + } }
-#ifdef HAVE_SOCKET - if (cl_options.new_instance) - { - val = ((SmPropValue *)arr->data) + arr_real_len++; - val->length = 2; /* length of "-i" */ - val->value = "-i"; - } -#endif
- /* TODO: handle other command-line options */ - if (cl_options.load_session && !cl_options.new_instance) { /* @@ -448,13 +432,13 @@ else { /* Specify file names in the command line */ + const gint page_count = gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.notebook));
- val = ((SmPropValue *)arr->data) + arr_real_len++; - val->length = 2; /* length of "--" */ - val->value = "--"; + val.length = 2; + val.value = "--"; + g_array_append_val(arr, val); + arr_filenames_begin = arr->len;
- arr_filenames_begin = arr_real_len; - /* * NOTE: compare this cycle with the one inside * configuration_save_session_files() function in keyfile.c. @@ -464,12 +448,12 @@ GeanyDocument * doc = document_get_from_page(i); if (doc && doc->real_path) { - /* this string will be freed when `arr' is no longer needed */ + /* freed after `arr' is used */ gchar * locale_filename = utils_get_locale_from_utf8(doc->file_name);
- val = ((SmPropValue *)arr->data) + arr_real_len++; - val->length = strlen(locale_filename); - val->value = locale_filename; + val.length = strlen(locale_filename); + val.value = locale_filename; + g_array_append_val(arr, val); } } } @@ -477,7 +461,7 @@
restart_command_prop.name = SmRestartCommand; restart_command_prop.type = SmLISTofARRAY8; - restart_command_prop.num_vals = arr_real_len; + restart_command_prop.num_vals = arr->len; restart_command_prop.vals = (SmPropValue *)arr->data; prop = &restart_command_prop; SmcSetProperties(smcon, 1, &prop); @@ -489,14 +473,15 @@ ((SmPropValue *)arr->data)[1] = sm_program_val; clone_command_prop.name = SmCloneCommand; clone_command_prop.type = SmLISTofARRAY8; - clone_command_prop.num_vals = arr_real_len - 1; + clone_command_prop.num_vals = arr->len - 1; clone_command_prop.vals = ((SmPropValue *)arr->data) + 1; prop = &clone_command_prop; SmcSetProperties(smcon, 1, &prop);
- if (arr_filenames_begin != -1) - for (i = arr_filenames_begin; i < arr_real_len; i++) + /* free allocated strings storing command-line options and file names */ + for (i = 2; i < arr->len; i++) + if (i != (arr_filenames_begin - 1)) g_free(((SmPropValue *)arr->data)[i].value); g_array_free(arr, TRUE); }
Modified: branches/sm/src/utils.c =================================================================== --- branches/sm/src/utils.c 2010-01-24 20:24:52 UTC (rev 4549) +++ branches/sm/src/utils.c 2010-01-24 20:25:17 UTC (rev 4550) @@ -1885,7 +1885,7 @@ g_free(uri); uri = g_strconcat(GEANY_HOMEPAGE, "manual/", VERSION, "/index.html", NULL); } - + if (suffix != NULL) { setptr(uri, g_strconcat(uri, suffix, NULL)); @@ -1894,3 +1894,69 @@ return uri; }
+ +GArray * utils_option_entry_reverse_parse(const GOptionEntry * optentry) +{ + GArray * ret = g_array_new(TRUE, TRUE, sizeof(gchar *)); + gchar * s; + gchar ** ss; + + switch (optentry->arg) + { + case G_OPTION_ARG_NONE: + { + gboolean val = *(gboolean *)optentry->arg_data; + gboolean reverse = (optentry->flags & G_OPTION_FLAG_REVERSE); + if ((val && !reverse) || (!val && reverse)) /* logical XOR */ + { + s = g_strdup_printf("--%s", optentry->long_name); + g_array_append_val(ret, s); + } + } + break; + + case G_OPTION_ARG_INT: + s = g_strdup_printf("--%s=%d", + optentry->long_name, *(gint *)optentry->arg_data); + g_array_append_val(ret, s); + break; +#if GLIB_MAJOR_VERSION >= 2 && GLIB_MINOR_VERSION >= 12 + case G_OPTION_ARG_INT64: + s = g_strdup_printf("--%s=%" G_GINT64_MODIFIER "d", + optentry->long_name, *(gint64 *)optentry->arg_data); + g_array_append_val(ret, s); + break; + case G_OPTION_ARG_DOUBLE: + s = g_strdup_printf("--%s=%f", + optentry->long_name, *(gdouble *)optentry->arg_data); + g_array_append_val(ret, s); + break; +#endif + + case G_OPTION_ARG_STRING: + case G_OPTION_ARG_FILENAME: + if (*(gchar **)optentry->arg_data) + { + s = g_strdup_printf("--%s=%s", optentry->long_name, *(gchar **)optentry->arg_data); + g_array_append_val(ret, s); + } + break; + case G_OPTION_ARG_STRING_ARRAY: + case G_OPTION_ARG_FILENAME_ARRAY: + for (ss = *(gchar ***)optentry->arg_data; *ss; ss++) + { + s = g_strdup_printf("--%s=%s", optentry->long_name, *ss); + g_array_append_val(ret, s); + } + break; + + case G_OPTION_ARG_CALLBACK: + g_warning("%s: %s\n", G_STRFUNC, + "Cannot reverse parse option entries of type G_OPTION_ARG_CALLBACK"); + break; + default: + g_warning("%s: %s: %d\n", G_STRFUNC, "Unknown option entry type", optentry->arg); + break; + } + return ret; +}
Modified: branches/sm/src/utils.h =================================================================== --- branches/sm/src/utils.h 2010-01-24 20:24:52 UTC (rev 4549) +++ branches/sm/src/utils.h 2010-01-24 20:25:17 UTC (rev 4550) @@ -229,4 +229,20 @@
gchar *utils_str_remove_chars(gchar *string, const gchar *chars);
+ +/** + * "Reverse parse" @c GOptionEntry + * + * @param optentry Object to parse. + * @return Null-terminated array of strings (@c gchar*). + * + * Function takes the information about the option entry stored in @c optentry + * and the option's value by the address stored in @c optentry. It returns an array + * of strings such that it specifies the option's value when used like @c argv. + * + * Elements of the resulting array must be freed with @c g_free(). The array + * itself must be freed with @c g_array_free(). + */ +GArray * utils_option_entry_reverse_parse(const GOptionEntry * optentry); + #endif
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.