summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/wee-config-file.c539
-rw-r--r--src/core/wee-config-file.h43
-rw-r--r--src/core/wee-config-option.c568
-rw-r--r--src/core/wee-config-option.h68
4 files changed, 1218 insertions, 0 deletions
diff --git a/src/core/wee-config-file.c b/src/core/wee-config-file.c
new file mode 100644
index 000000000..5cabd5a07
--- /dev/null
+++ b/src/core/wee-config-file.c
@@ -0,0 +1,539 @@
+/*
+ * Copyright (c) 2003-2007 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * 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
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* wee-config-file.c: I/O functions to read/write options in a config file */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <time.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "weechat.h"
+#include "wee-config-file.h"
+#include "wee-config-option.h"
+#include "wee-log.h"
+#include "wee-string.h"
+#include "wee-utf8.h"
+#include "../gui/gui-chat.h"
+#include "../gui/gui-color.h"
+
+
+/*
+ * config_file_read_option: read an option for a section in config file
+ * This function is called when a new section begins
+ * or for an option of a section
+ * if options == NULL, then option is out of section
+ * if option_name == NULL, it's beginning of section
+ * otherwise it's an option for a section
+ * Return: 0 = successful
+ * -1 = option not found
+ * -2 = bad format/value
+ */
+
+int
+config_file_read_option (struct t_config_option *options,
+ char *option_name, char *value)
+{
+ struct t_config_option *ptr_option;
+
+ if (option_name)
+ {
+ /* no option allowed outside a section by default */
+ if (!options)
+ return -1;
+
+ /* search option in list of options for section */
+ ptr_option = config_option_search (options, option_name);
+ if (!ptr_option)
+ return -1;
+
+ /* set value for option found */
+ if (config_option_set (ptr_option, value) < 0)
+ return -2;
+ }
+ else
+ {
+ /* by default, does nothing for a new section */
+ }
+
+ /* all ok */
+ return 0;
+}
+
+/*
+ * config_file_read: read a configuration file
+ * return: 0 = successful
+ * -1 = config file file not found
+ * -2 = error in config file
+ */
+
+int
+config_file_read (char **config_sections, struct t_config_option **options,
+ t_config_func_read_option **read_functions,
+ t_config_func_read_option *read_function_default,
+ t_config_func_write_options **write_default_functions,
+ char *config_filename)
+{
+ int filename_length;
+ char *filename;
+ FILE *file;
+ int section, line_number, rc;
+ char line[1024], *ptr_line, *ptr_line2, *pos, *pos2;
+
+ filename_length = strlen (weechat_home) + strlen (config_filename) + 2;
+ filename = (char *) malloc (filename_length * sizeof (char));
+ if (!filename)
+ return -2;
+ snprintf (filename, filename_length, "%s%s%s",
+ weechat_home, DIR_SEPARATOR, config_filename);
+ if ((file = fopen (filename, "r")) == NULL)
+ {
+ /* if no default write functions provided and that config file
+ is not here, then return without doing anything */
+ if (!write_default_functions)
+ return 0;
+
+ /* create default config, then go on with reading */
+ config_file_write_default (config_sections, options,
+ write_default_functions,
+ config_filename);
+ if ((file = fopen (filename, "r")) == NULL)
+ {
+ gui_chat_printf (NULL, _("%s config file \"%s\" not found.\n"),
+ WEECHAT_WARNING, filename);
+ free (filename);
+ return -1;
+ }
+ }
+
+ config_option_section_option_set_default_values (config_sections, options);
+
+ section = -1;
+ line_number = 0;
+ while (!feof (file))
+ {
+ ptr_line = fgets (line, sizeof (line) - 1, file);
+ line_number++;
+ if (ptr_line)
+ {
+ /* encode line to internal charset */
+ ptr_line2 = string_iconv_to_internal (NULL, ptr_line);
+ if (ptr_line2)
+ {
+ snprintf (line, sizeof (line) - 1, "%s", ptr_line2);
+ free (ptr_line2);
+ }
+
+ /* skip spaces */
+ while (ptr_line[0] == ' ')
+ ptr_line++;
+ /* not a comment and not an empty line */
+ if ((ptr_line[0] != '#') && (ptr_line[0] != '\r')
+ && (ptr_line[0] != '\n'))
+ {
+ /* beginning of section */
+ if (ptr_line[0] == '[')
+ {
+ pos = strchr (line, ']');
+ if (pos == NULL)
+ gui_chat_printf (NULL,
+ _("%s %s, line %d: invalid syntax, "
+ "missing \"]\"\n"),
+ WEECHAT_WARNING, filename,
+ line_number);
+ else
+ {
+ pos[0] = '\0';
+ pos = ptr_line + 1;
+ section = config_option_section_get_index (config_sections, pos);
+ if (section < 0)
+ gui_chat_printf (NULL,
+ _("%s %s, line %d: unknown section "
+ "identifier (\"%s\")\n"),
+ WEECHAT_WARNING, filename,
+ line_number, pos);
+ else
+ {
+ rc = ((int) (read_functions[section]) (options[section],
+ NULL, NULL));
+ if (rc < 0)
+ gui_chat_printf (NULL,
+ _("%s %s, line %d: error "
+ "reading new section \"%s\"\n"),
+ WEECHAT_WARNING, filename,
+ line_number, pos);
+ }
+ }
+ }
+ else
+ {
+ pos = strchr (line, '=');
+ if (pos == NULL)
+ gui_chat_printf (NULL,
+ _("%s %s, line %d: invalid syntax, "
+ "missing \"=\"\n"),
+ WEECHAT_WARNING, filename,
+ line_number);
+ else
+ {
+ pos[0] = '\0';
+ pos++;
+
+ /* remove spaces before '=' */
+ pos2 = pos - 2;
+ while ((pos2 > line) && (pos2[0] == ' '))
+ {
+ pos2[0] = '\0';
+ pos2--;
+ }
+
+ /* skip spaces after '=' */
+ while (pos[0] && (pos[0] == ' '))
+ {
+ pos++;
+ }
+
+ /* remove CR/LF */
+ pos2 = strchr (pos, '\r');
+ if (pos2 != NULL)
+ pos2[0] = '\0';
+ pos2 = strchr (pos, '\n');
+ if (pos2 != NULL)
+ pos2[0] = '\0';
+
+ /* remove simple or double quotes
+ and spaces at the end */
+ if (strlen(pos) > 1)
+ {
+ pos2 = pos + strlen (pos) - 1;
+ while ((pos2 > pos) && (pos2[0] == ' '))
+ {
+ pos2[0] = '\0';
+ pos2--;
+ }
+ pos2 = pos + strlen (pos) - 1;
+ if (((pos[0] == '\'') &&
+ (pos2[0] == '\'')) ||
+ ((pos[0] == '"') &&
+ (pos2[0] == '"')))
+ {
+ pos2[0] = '\0';
+ pos++;
+ }
+ }
+
+ if (section < 0)
+ rc = ((int) (read_function_default) (NULL, line, pos));
+ else
+ rc = ((int) (read_functions[section]) (options[section],
+ line, pos));
+ if (rc < 0)
+ {
+ switch (rc)
+ {
+ case -1:
+ if (section < 0)
+ gui_chat_printf (NULL,
+ _("%s %s, line %d: unknown "
+ "option \"%s\" "
+ "(outside a section)\n"),
+ WEECHAT_WARNING,
+ filename,
+ line_number, line);
+ else
+ gui_chat_printf (NULL,
+ _("%s %s, line %d: option "
+ "\"%s\" unknown for "
+ "section \"%s\"\n"),
+ WEECHAT_WARNING, filename,
+ line_number, line,
+ config_sections[section]);
+ break;
+ case -2:
+ gui_chat_printf (NULL,
+ _("%s %s, line %d: invalid "
+ "value for option \"%s\"\n"),
+ WEECHAT_WARNING, filename,
+ line_number, line);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ fclose (file);
+ free (filename);
+
+ return 0;
+}
+
+/*
+ * config_file_write_options: write a section with options in a config file
+ * This function is called when config is saved,
+ * for a section with standard options
+ * Return: 0 = successful
+ * -1 = write error
+ */
+
+int
+config_file_write_options (FILE *file, char *section_name,
+ struct t_config_option *options)
+{
+ int i;
+
+ string_iconv_fprintf (file, "\n[%s]\n", section_name);
+
+ for (i = 0; options[i].name; i++)
+ {
+ switch (options[i].type)
+ {
+ case OPTION_TYPE_BOOLEAN:
+ string_iconv_fprintf (file, "%s = %s\n",
+ options[i].name,
+ (options[i].ptr_int &&
+ *options[i].ptr_int) ?
+ "on" : "off");
+ break;
+ case OPTION_TYPE_INT:
+ string_iconv_fprintf (file, "%s = %d\n",
+ options[i].name,
+ (options[i].ptr_int) ?
+ *options[i].ptr_int :
+ options[i].default_int);
+ break;
+ case OPTION_TYPE_INT_WITH_STRING:
+ string_iconv_fprintf (file, "%s = %s\n",
+ options[i].name,
+ (options[i].ptr_int) ?
+ options[i].array_values[*options[i].ptr_int] :
+ options[i].array_values[options[i].default_int]);
+ break;
+ case OPTION_TYPE_COLOR:
+ string_iconv_fprintf (file, "%s = %s\n",
+ options[i].name,
+ (options[i].ptr_int) ?
+ gui_color_get_name (*options[i].ptr_int) :
+ options[i].default_string);
+ break;
+ case OPTION_TYPE_STRING:
+ string_iconv_fprintf (file, "%s = \"%s\"\n",
+ options[i].name,
+ (options[i].ptr_string) ?
+ *options[i].ptr_string :
+ options[i].default_string);
+ break;
+ }
+ }
+
+ /* all ok */
+ return 0;
+}
+
+/*
+ * config_file_write_options_default_values: write a section with options in a config file
+ * This function is called when new config file
+ * is created, with default values, for a
+ * section with standard options
+ * Return: 0 = successful
+ * -1 = write error
+ */
+
+int
+config_file_write_options_default_values (FILE *file, char *section_name,
+ struct t_config_option *options)
+{
+ int i;
+
+ string_iconv_fprintf (file, "\n[%s]\n", section_name);
+
+ for (i = 0; options[i].name; i++)
+ {
+ switch (options[i].type)
+ {
+ case OPTION_TYPE_BOOLEAN:
+ string_iconv_fprintf (file, "%s = %s\n",
+ options[i].name,
+ (options[i].default_int) ?
+ "on" : "off");
+ break;
+ case OPTION_TYPE_INT:
+ string_iconv_fprintf (file, "%s = %d\n",
+ options[i].name,
+ options[i].default_int);
+ break;
+ case OPTION_TYPE_INT_WITH_STRING:
+ case OPTION_TYPE_COLOR:
+ string_iconv_fprintf (file, "%s = %s\n",
+ options[i].name,
+ options[i].default_string);
+ break;
+ case OPTION_TYPE_STRING:
+ string_iconv_fprintf (file, "%s = \"%s\"\n",
+ options[i].name,
+ options[i].default_string);
+ break;
+ }
+ }
+
+ /* all ok */
+ return 0;
+}
+
+/*
+ * config_file_write_header: write header in a config file
+ */
+
+void
+config_file_write_header (FILE *file)
+{
+ time_t current_time;
+
+ current_time = time (NULL);
+ string_iconv_fprintf (file, _("#\n# %s configuration file, created by "
+ "%s v%s on %s"),
+ PACKAGE_NAME, PACKAGE_NAME, PACKAGE_VERSION,
+ ctime (&current_time));
+ string_iconv_fprintf (file, _("# WARNING! Be careful when editing this file, "
+ "WeeChat may write it at any time.\n#\n"));
+}
+
+/*
+ * config_file_write_default: create a default configuration file
+ * return: 0 if ok
+ * < 0 if error
+ */
+
+int
+config_file_write_default (char **config_sections, struct t_config_option **options,
+ t_config_func_write_options **write_functions,
+ char *config_filename)
+{
+ int filename_length, i, rc;
+ char *filename;
+ FILE *file;
+
+ filename_length = strlen (weechat_home) +
+ strlen (config_filename) + 2;
+ filename =
+ (char *) malloc (filename_length * sizeof (char));
+ if (!filename)
+ return -2;
+ snprintf (filename, filename_length, "%s%s%s",
+ weechat_home, DIR_SEPARATOR, config_filename);
+ if ((file = fopen (filename, "w")) == NULL)
+ {
+ gui_chat_printf (NULL, _("%s cannot create file \"%s\"\n"),
+ WEECHAT_ERROR, filename);
+ free (filename);
+ return -1;
+ }
+
+ string_iconv_fprintf (stdout,
+ _("%s: creating default config file \"%s\"...\n"),
+ PACKAGE_NAME,
+ config_filename);
+ weechat_log_printf (_("Creating default config file \"%s\"\n"),
+ config_filename);
+
+ config_file_write_header (file);
+
+ for (i = 0; config_sections[i]; i++)
+ {
+ rc = ((int) (write_functions[i]) (file, config_sections[i],
+ options[i]));
+ }
+
+ fclose (file);
+ chmod (filename, 0600);
+ free (filename);
+ return 0;
+}
+
+/*
+ * config_file_write: write a configurtion file
+ * return: 0 if ok
+ * < 0 if error
+ */
+
+int
+config_file_write (char **config_sections, struct t_config_option **options,
+ t_config_func_write_options **write_functions,
+ char *config_filename)
+{
+ int filename_length, i, rc;
+ char *filename, *filename2;
+ FILE *file;
+
+ filename_length = strlen (weechat_home) +
+ strlen (config_filename) + 2;
+ filename =
+ (char *) malloc (filename_length * sizeof (char));
+ if (!filename)
+ return -2;
+ snprintf (filename, filename_length, "%s%s%s",
+ weechat_home, DIR_SEPARATOR, config_filename);
+
+ filename2 = (char *) malloc ((filename_length + 32) * sizeof (char));
+ if (!filename2)
+ {
+ free (filename);
+ return -2;
+ }
+ snprintf (filename2, filename_length + 32, "%s.weechattmp", filename);
+
+ if ((file = fopen (filename2, "w")) == NULL)
+ {
+ gui_chat_printf (NULL, _("%s cannot create file \"%s\"\n"),
+ WEECHAT_ERROR, filename2);
+ free (filename);
+ free (filename2);
+ return -1;
+ }
+
+ config_file_write_header (file);
+
+ for (i = 0; config_sections[i]; i++)
+ {
+ rc = ((int) (write_functions[i]) (file, config_sections[i],
+ options[i]));
+ }
+
+ fclose (file);
+ chmod (filename2, 0600);
+ unlink (filename);
+ rc = rename (filename2, filename);
+ free (filename);
+ free (filename2);
+ if (rc != 0)
+ return -1;
+ return 0;
+}
diff --git a/src/core/wee-config-file.h b/src/core/wee-config-file.h
new file mode 100644
index 000000000..cde80def3
--- /dev/null
+++ b/src/core/wee-config-file.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2003-2007 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * 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
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __WEECHAT_CONFIG_FILE_H
+#define __WEECHAT_CONFIG_FILE_H 1
+
+#include "wee-config-option.h"
+
+typedef int (t_config_func_read_option) (struct t_config_option *, char *, char *);
+typedef int (t_config_func_write_options) (FILE *, char *, struct t_config_option *);
+
+extern int config_file_read_option (struct t_config_option *, char *, char *);
+extern int config_file_read (char **, struct t_config_option **,
+ t_config_func_read_option **,
+ t_config_func_read_option *,
+ t_config_func_write_options **,
+ char *);
+
+extern int config_file_write_options (FILE *, char *, struct t_config_option *);
+extern int config_file_write_options_default_values (FILE *, char *,
+ struct t_config_option *);
+extern int config_file_write_default (char **, struct t_config_option **,
+ t_config_func_write_options **, char *);
+extern int config_file_write (char **, struct t_config_option **,
+ t_config_func_write_options **, char *);
+
+#endif /* wee-config-file.h */
diff --git a/src/core/wee-config-option.c b/src/core/wee-config-option.c
new file mode 100644
index 000000000..9d8decb43
--- /dev/null
+++ b/src/core/wee-config-option.c
@@ -0,0 +1,568 @@
+/*
+ * Copyright (c) 2003-2007 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * 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
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* wee-config-option.c: manages WeeChat/protocols options */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <time.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "weechat.h"
+#include "wee-config-option.h"
+#include "wee-hook.h"
+#include "wee-string.h"
+#include "wee-utf8.h"
+#include "../gui/gui-chat.h"
+#include "../gui/gui-color.h"
+
+
+/*
+ * config_option_get_pos_array_values: return position of a string in an array of values
+ * return -1 if not found, otherwise position
+ */
+
+int
+config_option_get_pos_array_values (char **array, char *string)
+{
+ int i;
+
+ i = 0;
+ while (array[i])
+ {
+ if (string_strcasecmp (array[i], string) == 0)
+ return i;
+ i++;
+ }
+
+ /* string not found in array */
+ return -1;
+}
+
+/*
+ * config_option_list_remove: remove an item from a list for an option
+ * (for options with value like: "abc:1,def:blabla")
+ */
+
+void
+config_option_list_remove (char **string, char *item)
+{
+ char *name, *pos, *pos2;
+
+ if (!string || !(*string))
+ return;
+
+ name = (char *) malloc (strlen (item) + 2);
+ strcpy (name, item);
+ strcat (name, ":");
+ pos = string_strcasestr (*string, name);
+ free (name);
+ if (pos)
+ {
+ pos2 = pos + strlen (item);
+ if (pos2[0] == ':')
+ {
+ pos2++;
+ if (pos2[0])
+ {
+ while (pos2[0] && (pos2[0] != ','))
+ pos2++;
+ if (pos2[0] == ',')
+ pos2++;
+ if (!pos2[0] && (pos != (*string)))
+ pos--;
+ strcpy (pos, pos2);
+ if (!(*string)[0])
+ {
+ free (*string);
+ *string = NULL;
+ }
+ else
+ (*string) = (char *) realloc (*string, strlen (*string) + 1);
+ }
+ }
+ }
+}
+
+/*
+ * config_option_list_set: set an item from a list for an option
+ * (for options with value like: "abc:1,def:blabla")
+ */
+
+void
+config_option_list_set (char **string, char *item, char *value)
+{
+ config_option_list_remove (string, item);
+
+ if (!(*string))
+ {
+ (*string) = (char *) malloc (strlen (item) + 1 + strlen (value) + 1);
+ (*string)[0] = '\0';
+ }
+ else
+ (*string) = (char *) realloc (*string,
+ strlen (*string) + 1 +
+ strlen (item) + 1 + strlen (value) + 1);
+
+ if ((*string)[0])
+ strcat (*string, ",");
+ strcat (*string, item);
+ strcat (*string, ":");
+ strcat (*string, value);
+}
+
+/*
+ * config_option_list_get_value: return position of item value in the list
+ * (for options with value like: "abc:1,def:blabla")
+ */
+
+void
+config_option_list_get_value (char **string, char *item,
+ char **pos_found, int *length)
+{
+ char *name, *pos, *pos2, *pos_comma;
+
+ *pos_found = NULL;
+ *length = 0;
+
+ if (!string || !(*string))
+ return;
+
+ name = (char *) malloc (strlen (item) + 2);
+ strcpy (name, item);
+ strcat (name, ":");
+ pos = string_strcasestr (*string, name);
+ free (name);
+ if (pos)
+ {
+ pos2 = pos + strlen (item);
+ if (pos2[0] == ':')
+ {
+ pos2++;
+ *pos_found = pos2;
+ pos_comma = strchr (pos2, ',');
+ if (pos_comma)
+ *length = pos_comma - pos2;
+ else
+ *length = strlen (pos2);
+ }
+ }
+}
+
+/*
+ * config_option_option_get_boolean_value: get boolean value with user text
+ * return: BOOL_FALSE or BOOL_TRUE
+ */
+
+int
+config_option_option_get_boolean_value (char *text)
+{
+ if ((string_strcasecmp (text, "on") == 0)
+ || (string_strcasecmp (text, "yes") == 0)
+ || (string_strcasecmp (text, "y") == 0)
+ || (string_strcasecmp (text, "true") == 0)
+ || (string_strcasecmp (text, "t") == 0)
+ || (string_strcasecmp (text, "1") == 0))
+ return BOOL_TRUE;
+
+ if ((string_strcasecmp (text, "off") == 0)
+ || (string_strcasecmp (text, "no") == 0)
+ || (string_strcasecmp (text, "n") == 0)
+ || (string_strcasecmp (text, "false") == 0)
+ || (string_strcasecmp (text, "f") == 0)
+ || (string_strcasecmp (text, "0") == 0))
+ return BOOL_FALSE;
+
+ /* invalid text */
+ return -1;
+}
+
+/*
+ * config_option_set: set new value for an option
+ * return: 0 if success
+ * -1 if error (bad value)
+ */
+
+int
+config_option_set (struct t_config_option *option, char *value)
+{
+ int int_value;
+
+ switch (option->type)
+ {
+ case OPTION_TYPE_BOOLEAN:
+ int_value = config_option_option_get_boolean_value (value);
+ switch (int_value)
+ {
+ case BOOL_TRUE:
+ *(option->ptr_int) = BOOL_TRUE;
+ break;
+ case BOOL_FALSE:
+ *(option->ptr_int) = BOOL_FALSE;
+ break;
+ default:
+ return -1;
+ }
+ break;
+ case OPTION_TYPE_INT:
+ int_value = atoi (value);
+ if ((int_value < option->min) || (int_value > option->max))
+ return -1;
+ *(option->ptr_int) = int_value;
+ break;
+ case OPTION_TYPE_INT_WITH_STRING:
+ int_value = config_option_get_pos_array_values (option->array_values,
+ value);
+ if (int_value < 0)
+ return -1;
+ *(option->ptr_int) = int_value;
+ break;
+ case OPTION_TYPE_STRING:
+ if ((option->max > 0) && (utf8_strlen (value) > option->max))
+ return -1;
+ if (*(option->ptr_string))
+ free (*(option->ptr_string));
+ *(option->ptr_string) = strdup (value);
+ break;
+ case OPTION_TYPE_COLOR:
+ if (!gui_color_assign (option->ptr_int, value))
+ return -1;
+ break;
+ }
+
+ hook_config_exec ("weechat", option->name, value);
+
+ return 0;
+}
+
+/*
+ * config_option_search: look for an option in a section and
+ * return pointer to this option
+ * If option is not found, NULL is returned
+ */
+
+struct t_config_option *
+config_option_search (struct t_config_option *config_options, char *option_name)
+{
+ int i;
+
+ for (i = 0; config_options[i].name; i++)
+ {
+ /* if option found, return pointer */
+ if (string_strcasecmp (config_options[i].name, option_name) == 0)
+ return &config_options[i];
+ }
+
+ /* option not found */
+ return NULL;
+}
+
+/*
+ * config_option_section_option_search: look for an option and return pointer to this option
+ * if option is not found, NULL is returned
+ */
+
+struct t_config_option *
+config_option_section_option_search (char **config_sections,
+ struct t_config_option **config_options,
+ char *option_name)
+{
+ int i;
+ struct t_config_option *ptr_option;
+
+ for (i = 0; config_sections[i]; i++)
+ {
+ ptr_option = config_option_search (config_options[i],
+ option_name);
+ if (ptr_option)
+ return ptr_option;
+ }
+
+ /* option not found */
+ return NULL;
+}
+
+/*
+ * config_option_section_option_search_get_value: look for type and value of an option
+ * if option is not found, NULL is returned
+ */
+
+void
+config_option_section_option_search_get_value (char **config_sections,
+ struct t_config_option **config_options,
+ char *option_name,
+ struct t_config_option **output_option,
+ void **output_option_value)
+{
+ struct t_config_option *ptr_option;
+ void *ptr_value;
+
+ ptr_option = NULL;
+ ptr_value = NULL;
+
+ ptr_option = config_option_section_option_search (config_sections,
+ config_options,
+ option_name);
+ if (ptr_option)
+ {
+ switch (ptr_option->type)
+ {
+ case OPTION_TYPE_BOOLEAN:
+ case OPTION_TYPE_INT:
+ case OPTION_TYPE_INT_WITH_STRING:
+ case OPTION_TYPE_COLOR:
+ ptr_value = (void *)(ptr_option->ptr_int);
+ break;
+ case OPTION_TYPE_STRING:
+ ptr_value = (void *)(ptr_option->ptr_string);
+ break;
+ }
+ if (ptr_option)
+ {
+ *output_option = ptr_option;
+ *output_option_value = ptr_value;
+ }
+ }
+}
+
+/*
+ * config_option_section_option_set_value_by_name: set new value for an option (found by name)
+ * return: 0 if success
+ * -1 if bad value for option
+ * -2 if option is not found
+ */
+
+int
+config_option_section_option_set_value_by_name (char **config_sections,
+ struct t_config_option **config_options,
+ char *option_name, char *value)
+{
+ struct t_config_option *ptr_option;
+
+ ptr_option = config_option_section_option_search (config_sections,
+ config_options,
+ option_name);
+ if (ptr_option)
+ return config_option_set (ptr_option, value);
+ else
+ return -2;
+}
+
+/*
+ * config_option_section_get_index: get section index by name
+ * return -1 if section is not found
+ */
+
+int
+config_option_section_get_index (char **config_sections, char *section_name)
+{
+ int i;
+
+ for (i = 0; config_sections[i]; i++)
+ {
+ if (string_strcasecmp (config_sections[i], section_name) == 0)
+ return i;
+ }
+
+ /* option not found */
+ return -1;
+}
+
+/*
+ * config_option_section_get_name: get section name by option pointer
+ */
+
+char *
+config_option_section_get_name (char **config_sections,
+ struct t_config_option **config_options,
+ struct t_config_option *ptr_option)
+{
+ int i, j;
+
+ for (i = 0; config_sections[i]; i++)
+ {
+ for (j = 0; config_options[i][j].name; j++)
+ {
+ /* if option found, return pointer to section name */
+ if (ptr_option == &config_options[i][j])
+ return config_sections[i];
+ }
+ }
+
+ /* option not found */
+ return NULL;
+}
+
+/*
+ * config_option_section_option_set_default_values: initialize config options
+ * with default values
+ */
+
+void
+config_option_section_option_set_default_values (char **config_sections,
+ struct t_config_option **config_options)
+{
+ int i, j, int_value;
+
+ for (i = 0; config_sections[i]; i++)
+ {
+ if (config_options[i])
+ {
+ for (j = 0; config_options[i][j].name; j++)
+ {
+ switch (config_options[i][j].type)
+ {
+ case OPTION_TYPE_BOOLEAN:
+ case OPTION_TYPE_INT:
+ *config_options[i][j].ptr_int =
+ config_options[i][j].default_int;
+ break;
+ case OPTION_TYPE_INT_WITH_STRING:
+ int_value = config_option_get_pos_array_values (
+ config_options[i][j].array_values,
+ config_options[i][j].default_string);
+ if (int_value < 0)
+ gui_chat_printf (NULL,
+ _("%s unable to assign default int with "
+ "string (\"%s\")\n"),
+ WEECHAT_WARNING,
+ config_options[i][j].default_string);
+ else
+ *config_options[i][j].ptr_int = int_value;
+ break;
+ case OPTION_TYPE_STRING:
+ *config_options[i][j].ptr_string =
+ strdup (config_options[i][j].default_string);
+ break;
+ case OPTION_TYPE_COLOR:
+ if (!gui_color_assign (config_options[i][j].ptr_int,
+ config_options[i][j].default_string))
+ gui_chat_printf (NULL,
+ _("%s unable to assign default color "
+ "(\"%s\")\n"),
+ WEECHAT_WARNING,
+ config_options[i][j].default_string);
+ break;
+ }
+ }
+ }
+ }
+}
+
+/*
+ * config_option_print_stdout: print options on standard output
+ */
+
+void
+config_option_print_stdout (char **config_sections,
+ struct t_config_option **config_options)
+{
+ int i, j, k;
+
+ for (i = 0; config_sections[i]; i++)
+ {
+ if (config_options[i])
+ {
+ j = 0;
+ while (config_options[i][j].name)
+ {
+ string_iconv_fprintf (stdout,
+ "* %s:\n",
+ config_options[i][j].name);
+ switch (config_options[i][j].type)
+ {
+ case OPTION_TYPE_BOOLEAN:
+ string_iconv_fprintf (stdout, _(" . type: boolean\n"));
+ string_iconv_fprintf (stdout, _(" . values: 'on' or 'off'\n"));
+ string_iconv_fprintf (stdout, _(" . default value: '%s'\n"),
+ (config_options[i][j].default_int == BOOL_TRUE) ?
+ "on" : "off");
+ break;
+ case OPTION_TYPE_INT:
+ string_iconv_fprintf (stdout, _(" . type: integer\n"));
+ string_iconv_fprintf (stdout, _(" . values: between %d and %d\n"),
+ config_options[i][j].min,
+ config_options[i][j].max);
+ string_iconv_fprintf (stdout, _(" . default value: %d\n"),
+ config_options[i][j].default_int);
+ break;
+ case OPTION_TYPE_INT_WITH_STRING:
+ string_iconv_fprintf (stdout, _(" . type: string\n"));
+ string_iconv_fprintf (stdout, _(" . values: "));
+ k = 0;
+ while (config_options[i][j].array_values[k])
+ {
+ string_iconv_fprintf (stdout, "'%s'",
+ config_options[i][j].array_values[k]);
+ if (config_options[i][j].array_values[k + 1])
+ string_iconv_fprintf (stdout, ", ");
+ k++;
+ }
+ string_iconv_fprintf (stdout, "\n");
+ string_iconv_fprintf (stdout, _(" . default value: '%s'\n"),
+ (config_options[i][j].default_string) ?
+ config_options[i][j].default_string : _("empty"));
+ break;
+ case OPTION_TYPE_STRING:
+ switch (config_options[i][j].max)
+ {
+ case 0:
+ string_iconv_fprintf (stdout, _(" . type: string\n"));
+ string_iconv_fprintf (stdout, _(" . values: any string\n"));
+ break;
+ case 1:
+ string_iconv_fprintf (stdout, _(" . type: char\n"));
+ string_iconv_fprintf (stdout, _(" . values: any char\n"));
+ break;
+ default:
+ string_iconv_fprintf (stdout, _(" . type: string\n"));
+ string_iconv_fprintf (stdout, _(" . values: any string (limit: %d chars)\n"),
+ config_options[i][j].max);
+ break;
+ }
+ string_iconv_fprintf (stdout, _(" . default value: '%s'\n"),
+ (config_options[i][j].default_string) ?
+ config_options[i][j].default_string : _("empty"));
+ break;
+ case OPTION_TYPE_COLOR:
+ string_iconv_fprintf (stdout, _(" . type: color\n"));
+ string_iconv_fprintf (stdout, _(" . values: color (depends on GUI used)\n"));
+ string_iconv_fprintf (stdout, _(" . default value: '%s'\n"),
+ (config_options[i][j].default_string) ?
+ config_options[i][j].default_string : _("empty"));
+ break;
+ }
+ string_iconv_fprintf (stdout, _(" . description: %s\n"),
+ _(config_options[i][j].description));
+ string_iconv_fprintf (stdout, "\n");
+ j++;
+ }
+ }
+ }
+}
diff --git a/src/core/wee-config-option.h b/src/core/wee-config-option.h
new file mode 100644
index 000000000..652c7d916
--- /dev/null
+++ b/src/core/wee-config-option.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2003-2007 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * 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
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __WEECHAT_CONFIG_OPTION_H
+#define __WEECHAT_CONFIG_OPTION_H 1
+
+#define OPTION_TYPE_BOOLEAN 1 /* values: on/off */
+#define OPTION_TYPE_INT 2 /* values: from min to max */
+#define OPTION_TYPE_INT_WITH_STRING 3 /* values: one from **array_values */
+#define OPTION_TYPE_STRING 4 /* values: any string, may be empty */
+#define OPTION_TYPE_COLOR 5 /* values: a color struct */
+
+
+#define BOOL_FALSE 0
+#define BOOL_TRUE 1
+
+struct t_config_option
+{
+ char *name;
+ char *description;
+ int type;
+ int min, max;
+ int default_int;
+ char *default_string;
+ char **array_values;
+ int *ptr_int;
+ char **ptr_string;
+ void (*handler_change)();
+};
+
+extern int config_option_get_pos_array_values (char **, char *);
+extern void config_option_list_remove (char **, char *);
+extern void config_option_list_set (char **, char *, char *);
+extern void config_option_list_get_value (char **, char *, char **, int *);
+extern int config_option_option_get_boolean_value (char *);
+extern int config_option_set (struct t_config_option *, char *);
+extern struct t_config_option *config_option_search (struct t_config_option *, char *);
+extern struct t_config_option *config_option_section_option_search (char **,
+ struct t_config_option **,
+ char *);
+extern void config_option_section_option_search_get_value (char **, struct t_config_option **,
+ char *, struct t_config_option **,
+ void **);
+extern int config_option_section_option_set_value_by_name (char **,
+ struct t_config_option **,
+ char *, char *);
+extern int config_option_section_get_index (char **, char *);
+extern void config_option_section_option_set_default_values (char **,
+ struct t_config_option **);
+extern void config_option_print_stdout (char **, struct t_config_option **);
+
+#endif /* wee-config-option.h */