/* Giram: a simple 3D modeller * Copyright (C) 2001 DindinX * * The GIMP -- an image manipulation program * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * 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 2 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #ifdef HAVE_SYS_PARAM_H #include #endif #include /* #include "libgimpcolor/gimpcolor.h" #include "apptypes.h" #include "tools/gimptoolinfo.h" #include "tools/tool.h" #include "app_procs.h" #include "appenv.h" #include "color_notebook.h" #include "cursorutil.h" #include "devices.h" #include "errors.h" #include "fileops.h"*/ #include "general.h" /*#include "gimphelp.h" #include "gimpparasite.h"*/ #include "giramrc.h" /*#include "menus.h" #include "plug_in.h" #include "gimage.h" #include "session.h"*/ #include "giramenv.h" #include "giramutils.h" /*#include "libgimp/gimpparasite.h" */ #include "giramintl.h" #define ERROR 0 #define DONE 1 #define OK 2 #define LOCALE_DEF 3 #define HELP_DEF 4 typedef enum { TT_STRING, TT_PATH, TT_DOUBLE, TT_FLOAT, TT_INT, TT_BOOLEAN, TT_XMENUPATH, /* TT_XHELPBROWSER,*/ TT_XCOMMENT } TokenType; typedef struct _ParseFunc ParseFunc; struct _ParseFunc { gchar *name; TokenType type; gpointer val1p; gpointer val2p; }; typedef struct _UnknownToken UnknownToken; struct _UnknownToken { gchar *token; gchar *value; }; static gint get_next_token (void); static gint peek_next_token (void); static gint parse_statement (void); static gint parse_string (gpointer val1p, gpointer val2p); static gint parse_path (gpointer val1p, gpointer val2p); static gint parse_double (gpointer val1p, gpointer val2p); static gint parse_float (gpointer val1p, gpointer val2p); static gint parse_int (gpointer val1p, gpointer val2p); static gint parse_boolean (gpointer val1p, gpointer val2p); static gint parse_menu_path (gpointer val1p, gpointer val2p); static gint parse_unknown (gchar *token_sym); gchar * giramrc_value_to_str (gchar *name); static gchar * value_to_str (gchar *name); static gchar * string_to_str (gpointer val1p, gpointer val2p); static gchar * path_to_str (gpointer val1p, gpointer val2p); static gchar * double_to_str (gpointer val1p, gpointer val2p); static gchar * float_to_str (gpointer val1p, gpointer val2p); static gchar * int_to_str (gpointer val1p, gpointer val2p); static gchar * boolean_to_str (gpointer val1p, gpointer val2p); static gchar * comment_to_str (gpointer val1p, gpointer val2p); static gchar * transform_path (gchar *path, gboolean destroy); static void giramrc_set_token (gchar *token, gchar *value); static void add_giram_directory_token (const gchar *giram_dir); static gchar * open_backup_file (gchar *filename, gchar *secondary_filename, gchar **name_used, FILE **fp_new, FILE **fp_old); extern gboolean be_verbose; /* global giramrc variables */ gchar *temp_path = NULL; gchar *plugins_path = NULL; gchar *pov_include_path = NULL; gchar *renderer_modules_path = NULL; gchar *help_path = NULL; gchar *color_path = NULL; gchar *color_map_path = NULL; gchar *finish_path = NULL; gchar *normal_path = NULL; gchar *pigment_path = NULL; gchar *shape_path = NULL; gchar *texture_path = NULL; gboolean show_xy_view = TRUE; gboolean show_xz_view = TRUE; gboolean show_zy_view = TRUE; gboolean show_camera_view = TRUE; gint toolbox_style = 0; gint dynamic_toolbox_shape = 0; gboolean show_rulers = TRUE; gboolean show_statusbar = TRUE; gboolean show_tips = TRUE; gint last_tip = -1; gboolean show_tool_tips = TRUE; gboolean use_help = TRUE; gchar *view_title_format = NULL; /*gint help_browser = HELP_BROWSER_GIRAM;*/ gboolean remove_trivial_transform = TRUE; gboolean merge_successive_translation = TRUE; static ParseFunc funcs[] = { { "temp-path", TT_PATH, &temp_path, NULL }, { "plugins-path", TT_PATH, &plugins_path, NULL }, { "pov-include-path", TT_PATH, &pov_include_path, NULL }, { "renderer-modules-path", TT_PATH, &renderer_modules_path, NULL }, { "help-path", TT_PATH, &help_path, NULL }, { "color-path", TT_PATH, &color_path, NULL }, { "color-map-path", TT_PATH, &color_map_path, NULL }, { "finish-path", TT_PATH, &finish_path, NULL }, { "normal-path", TT_PATH, &normal_path, NULL }, { "pigment-path", TT_PATH, &pigment_path, NULL }, { "shape-path", TT_PATH, &shape_path, NULL }, { "texture-path", TT_PATH, &texture_path, NULL }, { "show-xy-view", TT_BOOLEAN, &show_xy_view, NULL }, { "dont-show-xy-view", TT_BOOLEAN, NULL, &show_xy_view }, { "show-xz-view", TT_BOOLEAN, &show_xz_view, NULL }, { "dont-show-xz-view", TT_BOOLEAN, NULL, &show_xz_view }, { "show-zy-view", TT_BOOLEAN, &show_zy_view, NULL }, { "dont-show-zy-view", TT_BOOLEAN, NULL, &show_zy_view }, { "show-camera-view", TT_BOOLEAN, &show_camera_view, NULL }, { "dont-show-camera-view", TT_BOOLEAN, NULL, &show_camera_view }, { "toolbox-style", TT_INT, &toolbox_style, NULL }, { "dynamic-toolbox-shape", TT_INT, &dynamic_toolbox_shape, NULL }, { "show-rulers", TT_BOOLEAN, &show_rulers, NULL }, { "dont-show-rulers", TT_BOOLEAN, NULL, &show_rulers }, { "show-statusbar", TT_BOOLEAN, &show_statusbar, NULL }, { "dont-show-statusbar", TT_BOOLEAN, NULL, &show_statusbar }, { "show-tips", TT_BOOLEAN, &show_tips, NULL }, { "dont-show-tips", TT_BOOLEAN, NULL, &show_tips }, { "last-tip-shown", TT_INT, &last_tip, NULL }, { "show-tool-tips", TT_BOOLEAN, &show_tool_tips, NULL }, { "dont-show-tool-tips", TT_BOOLEAN, NULL, &show_tool_tips }, { "use-help", TT_BOOLEAN, &use_help, NULL }, { "dont-use-help", TT_BOOLEAN, NULL, &use_help }, { "view-title-format", TT_STRING, &view_title_format, NULL }, { "remove-trivial-transform", TT_BOOLEAN, &remove_trivial_transform, NULL }, { "dont-remove-trivial-transform", TT_BOOLEAN, NULL, &remove_trivial_transform }, { "merge-successive-translation", TT_BOOLEAN, &merge_successive_translation, NULL }, { "dont-merge-successive-translation", TT_BOOLEAN, NULL, &merge_successive_translation }, /* { "help-browser", TT_XHELPBROWSER, &help_browser, NULL },*/ }; static gint n_funcs = (sizeof(funcs) / sizeof(funcs[0])); static ParseInfo parse_info = { NULL }; static GList *unknown_tokens = NULL; static gint cur_token; static gint next_token; /* extern variables */ extern gchar *alternate_giramrc; extern gchar *alternate_system_giramrc; static gchar *giram_system_rc_file(void) { static gchar *value = NULL; if (! value) { value = g_strconcat(giram_sysconf_directory(), G_DIR_SEPARATOR_S, "giramrc", NULL); } return value; } gboolean parse_buffers_init(void) { if (!parse_info.buffer) { parse_info.buffer = g_new(gchar, 4096); parse_info.tokenbuf = parse_info.buffer + 2048; parse_info.buffer_size = 2048; parse_info.tokenbuf_size = 2048; return TRUE; } return FALSE; } static GList *parse_add_directory_tokens(void) { const gchar *giram_dir; giram_dir = giram_directory(); add_giram_directory_token(giram_dir); /* the real output is unknown_tokens list ! */ return unknown_tokens; } void parse_giramrc(void) { gchar *libfilename; gchar *filename; parse_add_directory_tokens(); if (alternate_system_giramrc != NULL) libfilename = g_strdup(alternate_system_giramrc); else libfilename = g_strdup(giram_system_rc_file()); if (!parse_giramrc_file(libfilename)) g_message("Can't open '%s' for reading.", libfilename); if (alternate_giramrc != NULL) filename = g_strdup(alternate_giramrc); else filename = giram_personal_rc_file("giramrc"); if (g_strcasecmp(filename, libfilename) != 0) parse_giramrc_file(filename); if (!view_title_format) view_title_format = g_strdup("(%t) - %s"); g_free(filename); g_free(libfilename); } gboolean parse_absolute_giramrc_file(char *filename) { gint status; parse_info.fp = fopen(filename, "rt"); if (!parse_info.fp) return FALSE; if (be_verbose) g_print(_("parsing \"%s\"\n"), filename); cur_token = -1; next_token = -1; parse_info.position = -1; parse_info.linenum = 1; parse_info.charnum = 1; parse_info.inc_linenum = FALSE; parse_info.inc_charnum = FALSE; while ((status = parse_statement()) == OK); fclose (parse_info.fp); if (status == ERROR) { g_print(_("error parsing: \"%s\"\n"), filename); g_print(_(" at line %d column %d\n"), parse_info.linenum, parse_info.charnum); g_print(_(" unexpected token: %s\n"), token_sym); return FALSE; } return TRUE; } gboolean parse_giramrc_file(gchar *filename) { gchar *rfilename; gboolean parsed; if (!g_path_is_absolute(filename)) { gchar *home_dir = (gchar *)g_get_home_dir(); gchar *home_dir_sep; if (home_dir != NULL) { if (home_dir[strlen(home_dir) -1] != G_DIR_SEPARATOR) home_dir_sep = G_DIR_SEPARATOR_S; else home_dir_sep = ""; rfilename = g_strdup_printf("%s%s%s", home_dir, home_dir_sep, filename); parsed = parse_absolute_giramrc_file(rfilename); g_free(rfilename); return parsed; } } parsed = parse_absolute_giramrc_file(filename); return parsed; } static GList *g_list_findstr(GList *list, gchar *str) { for (; list; list = g_list_next(list)) { if (!strcmp((char *)list->data, str)) break; } return list; } void save_giramrc_strings(gchar *token, gchar *value) { gchar timestamp[40]; /* variables for parsing and updating gimprc */ gchar *name; gchar tokname[51]; FILE *fp_new; FILE *fp_old; gchar *cur_line; gchar *prev_line; gchar *error_msg; gboolean found = FALSE; gchar *personal_giramrc; gchar *str; UnknownToken *ut; /* variables to modify unknown_tokens */ UnknownToken *tmp; GList *list; g_assert(token != NULL); g_assert(value != NULL); /* get the name of the backup file, and the file pointers. 'name' * is reused in another context later, disregard it here */ personal_giramrc = giram_personal_rc_file("giramrc"); error_msg = open_backup_file(personal_giramrc, giram_system_rc_file(), &name, &fp_new, &fp_old); g_free(personal_giramrc); if (error_msg != NULL) { g_message(error_msg); g_free(error_msg); return; } strcpy(timestamp, "by GIRAM on "); iso_8601_date_format(timestamp + strlen(timestamp), FALSE); /* copy the old .giramrc into the new one, modifying it as needed */ prev_line = NULL; cur_line = g_new(char, 1024); while (!feof(fp_old)) { if (!fgets(cur_line, 1024, fp_old)) continue; /* special case: save lines starting with '#-' (added by GIRAM) */ if ((cur_line[0] == '#') && (cur_line[1] == '-')) { if (prev_line != NULL) { fputs(prev_line, fp_new); g_free(prev_line); } prev_line = g_strdup(cur_line); continue; } /* see if the line contains something that we can use * and place that into 'name' if its found */ if (find_token(cur_line, tokname, 50)) { /* check if that entry should be updated */ if (!g_strcasecmp(token, tokname)) /* if they match */ { if (prev_line == NULL) { fprintf(fp_new, "#- Next line commented out %s\n", timestamp); fprintf(fp_new, "# %s\n", cur_line); fprintf(fp_new, "#- Next line added %s\n",timestamp); } else { g_free(prev_line); prev_line = NULL; fprintf(fp_new, "#- Next line modified %s\n", timestamp); } str = giram_strescape(value, NULL); if (!found) { fprintf(fp_new, "(%s \"%s\")\n", token, str); } else fprintf(fp_new, "#- (%s \"%s\")\n", token, str); g_free(str); found = TRUE; continue; } /* end if token and name match */ } /* end if token is found */ /* all lines that did not match the tests above are simply copied */ if (prev_line != NULL) { fputs(prev_line, fp_new); g_free(prev_line); prev_line = NULL; } fputs(cur_line, fp_new); } /* end of while(!feof) */ g_free(cur_line); if (prev_line != NULL) g_free(prev_line); fclose(fp_old); /* append the options that were not in the old .gimprc */ if (!found) { fprintf(fp_new, "#- Next line added %s\n", timestamp); str = giram_strescape(value, NULL); fprintf(fp_new, "(%s \"%s\")\n\n", token, str); g_free(str); } /* update unknown_tokens to reflect new token value */ ut = g_new(UnknownToken, 1); ut->token = g_strdup(token); ut->value = g_strdup(value); list = unknown_tokens; while (list) { tmp = (UnknownToken *)list->data; list = list->next; if (strcmp(tmp->token, ut->token) == 0) { unknown_tokens = g_list_remove(unknown_tokens, tmp); g_free(tmp->token); g_free(tmp->value); g_free(tmp); } } unknown_tokens = g_list_append(unknown_tokens, ut); fclose(fp_new); } void save_giramrc(GList **updated_options, GList **conflicting_options) { gchar timestamp[40]; gchar *name; gchar tokname[51]; FILE *fp_new; FILE *fp_old; GList *option; gchar *cur_line; gchar *prev_line; gchar *str; gchar *error_msg; gchar *personal_giramrc; g_assert(updated_options != NULL); g_assert(conflicting_options != NULL); personal_giramrc = giram_personal_rc_file("giramrc"); error_msg = open_backup_file(personal_giramrc, giram_system_rc_file(), &name, &fp_new, &fp_old); g_free(personal_giramrc); if (error_msg != NULL) { g_message(error_msg); g_free(error_msg); return; } strcpy(timestamp, "by GIRAM on "); iso_8601_date_format(timestamp + strlen(timestamp), FALSE); /* copy the old .giramrc into the new one, modifying it as needed */ prev_line = NULL; cur_line = g_new(char, 1024); while (!feof(fp_old)) { if (!fgets(cur_line, 1024, fp_old)) continue; /* special case: save lines starting with '#-' (added by GIRAM) */ if ((cur_line[0] == '#') && (cur_line[1] == '-')) { if (prev_line != NULL) { fputs(prev_line, fp_new); g_free(prev_line); } prev_line = g_strdup(cur_line); continue; } /* see if the line contains something that we can use */ if (find_token(cur_line, tokname, 50)) { /* check if that entry should be updated */ option = g_list_findstr(*updated_options, tokname); if (option != NULL) { if (prev_line == NULL) { fprintf(fp_new, "#- Next line commented out %s\n", timestamp); fprintf(fp_new, "# %s\n", cur_line); fprintf(fp_new, "#- Next line added %s\n", timestamp); } else { g_free(prev_line); prev_line = NULL; fprintf(fp_new, "#- Next line modified %s\n", timestamp); } str = value_to_str(tokname); fprintf(fp_new, "(%s %s)\n", tokname, str); g_free(str); *updated_options = g_list_remove_link(*updated_options, option); *conflicting_options = g_list_concat(*conflicting_options, option); continue; } /* check if that entry should be commented out */ option = g_list_findstr(*conflicting_options, tokname); if (option != NULL) { if (prev_line != NULL) { g_free(prev_line); prev_line = NULL; } fprintf(fp_new, "#- Next line commented out %s\n", timestamp); fprintf(fp_new, "# %s\n", cur_line); continue; } } /* all lines that did not match the tests above are simply copied */ if (prev_line != NULL) { fputs(prev_line, fp_new); g_free(prev_line); prev_line = NULL; } fputs(cur_line, fp_new); } g_free(cur_line); if (prev_line != NULL) g_free(prev_line); fclose(fp_old); /* append the options that were not in the old .giramrc */ option = *updated_options; while (option) { fprintf(fp_new, "#- Next line added %s\n", timestamp); str = value_to_str((char *)option->data); fprintf(fp_new, "(%s %s)\n\n", (char *)option->data, str); g_free(str); option = option->next; } fclose(fp_new); } static gint get_next_token(void) { if (next_token != -1) { cur_token = next_token; next_token = -1; } else { cur_token = get_rctoken(&parse_info); } return cur_token; } static gint peek_next_token(void) { if (next_token == -1) next_token = get_rctoken(&parse_info); return next_token; } static gint parse_statement(void) { gint token; gint i; token = peek_next_token(); if (!token) return DONE; if (token != TOKEN_LEFT_PAREN) return ERROR; token = get_next_token(); token = peek_next_token(); if (!token || (token != TOKEN_SYMBOL)) return ERROR; token = get_next_token(); for (i = 0; i < n_funcs; i++) if (strcmp(funcs[i].name, token_sym) == 0) switch (funcs[i].type) { case TT_STRING: return parse_string(funcs[i].val1p, funcs[i].val2p); case TT_PATH: return parse_path(funcs[i].val1p, funcs[i].val2p); case TT_DOUBLE: return parse_double(funcs[i].val1p, funcs[i].val2p); case TT_FLOAT: return parse_float(funcs[i].val1p, funcs[i].val2p); case TT_INT: return parse_int(funcs[i].val1p, funcs[i].val2p); case TT_BOOLEAN: return parse_boolean(funcs[i].val1p, funcs[i].val2p); case TT_XMENUPATH: return parse_menu_path(funcs[i].val1p, funcs[i].val2p); /* case TT_XHELPBROWSER: return parse_help_browser(funcs[i].val1p, funcs[i].val2p);*/ case TT_XCOMMENT: return parse_string(funcs[i].val1p, funcs[i].val2p); } return parse_unknown (token_sym); } static gint parse_path(gpointer val1p, gpointer val2p) { gint token; gchar **pathp; g_assert(val1p != NULL); pathp = (char **)val1p; token = peek_next_token(); if (!token || (token != TOKEN_STRING)) return ERROR; token = get_next_token(); if (*pathp) g_free(*pathp); *pathp = g_strdup(token_str); token = peek_next_token(); if (!token || (token != TOKEN_RIGHT_PAREN)) { g_free(*pathp); *pathp = NULL; return ERROR; } token = get_next_token(); *pathp = transform_path(*pathp, TRUE); return OK; } static gint parse_string(gpointer val1p, gpointer val2p) { gint token; gchar **strp; g_assert(val1p != NULL); strp = (gchar **)val1p; token = peek_next_token(); if (!token || (token != TOKEN_STRING)) return ERROR; token = get_next_token(); if (*strp) g_free(*strp); *strp = g_strdup(token_str); token = peek_next_token(); if (!token || (token != TOKEN_RIGHT_PAREN)) { g_free(*strp); *strp = NULL; return ERROR; } token = get_next_token(); return OK; } static gint parse_double(gpointer val1p, gpointer val2p) { gint token; gdouble *nump; g_assert(val1p != NULL); nump = (gdouble *)val1p; token = peek_next_token(); if (!token || (token != TOKEN_NUMBER)) return ERROR; token = get_next_token(); *nump = token_num; token = peek_next_token(); if (!token || (token != TOKEN_RIGHT_PAREN)) return ERROR; token = get_next_token(); return OK; } static gint parse_float(gpointer val1p, gpointer val2p) { gint token; gfloat *nump; g_assert(val1p != NULL); nump = (gfloat *)val1p; token = peek_next_token(); if (!token || (token != TOKEN_NUMBER)) return ERROR; token = get_next_token(); *nump = token_num; token = peek_next_token(); if (!token || (token != TOKEN_RIGHT_PAREN)) return ERROR; token = get_next_token(); return OK; } static gint parse_int(gpointer val1p, gpointer val2p) { gint token; gint *nump; g_assert(val1p != NULL); nump = (gint *)val1p; token = peek_next_token(); if (!token || (token != TOKEN_NUMBER)) return ERROR; token = get_next_token(); *nump = token_num; token = peek_next_token(); if (!token || (token != TOKEN_RIGHT_PAREN)) return ERROR; token = get_next_token(); return OK; } static gint parse_boolean(gpointer val1p, gpointer val2p) { gint token; gint *boolp; /* The variable to be set should be passed in the first or second * pointer. If the pointer is in val2p, then the opposite value is * stored in the pointer. This is useful for "dont-xxx" or "no-xxx" * type of options. * If the expression to be parsed is written as "(option)" instead * of "(option yes)" or "(option no)", then the default value is * TRUE if the variable is passed in val1p, or FALSE if in val2p. */ g_assert(val1p != NULL || val2p != NULL); if (val1p != NULL) boolp = (gint *)val1p; else boolp = (gint *)val2p; token = peek_next_token(); if (!token) return ERROR; switch (token) { case TOKEN_RIGHT_PAREN: *boolp = TRUE; break; case TOKEN_NUMBER: token = get_next_token(); *boolp = token_num; token = peek_next_token(); if (!token || (token != TOKEN_RIGHT_PAREN)) return ERROR; break; case TOKEN_SYMBOL: token = get_next_token(); if (!strcmp(token_sym, "true") || !strcmp(token_sym, "on") || !strcmp(token_sym, "yes")) *boolp = TRUE; else if (!strcmp(token_sym, "false") || !strcmp(token_sym, "off") || !strcmp (token_sym, "no")) *boolp = FALSE; else return ERROR; token = peek_next_token(); if (!token || (token != TOKEN_RIGHT_PAREN)) return ERROR; break; default: return ERROR; } if (val1p == NULL) *boolp = !*boolp; token = get_next_token(); return OK; } static gint parse_menu_path(gpointer val1p, gpointer val2p) { gchar *menu_path = NULL; gchar *accelerator = NULL; gint token; token = peek_next_token(); if (!token || (token != TOKEN_STRING)) goto error; token = get_next_token(); menu_path = g_strdup(token_str); token = peek_next_token(); if (!token || (token != TOKEN_STRING)) goto error; token = get_next_token(); accelerator = g_strdup(token_str); token = peek_next_token(); if (!token || (token != TOKEN_RIGHT_PAREN)) goto error; token = get_next_token(); return OK; error: g_free(menu_path); g_free(accelerator); return ERROR; } static gchar *transform_path(gchar *path, gboolean destroy) { guint length = 0; gchar *new_path; gchar *home; gchar *token; gchar *tmp; gchar *tmp2; gboolean substituted = FALSE; gboolean is_env = FALSE; UnknownToken *ut; home = (gchar *)g_get_home_dir (); tmp = path; while (*tmp) { if (*tmp == '~') { length += strlen(home); tmp += 1; } else if (*tmp == '$') { tmp += 1; if (!*tmp || (*tmp != '{')) return path; tmp += 1; token = tmp; while (*tmp && (*tmp != '}')) tmp += 1; if (!*tmp) return path; *tmp = '\0'; tmp2 = giramrc_find_token(token); if (tmp2 == NULL) { /* maybe token is an environment variable */ tmp2 = (gchar *)g_getenv(token); if (tmp2 != NULL) { is_env = TRUE; } else { /* giram_terminate("transform_path(): giramrc token referenced but not defined: %s", token);*/ g_print("transform_path(): giramrc token referenced but not defined: %s", token); exit(-1); } } tmp2 = transform_path(tmp2, FALSE); if (is_env) { /* then add to list of unknown tokens */ /* but only if it isn't already in list */ if (giramrc_find_token(token) == NULL) { ut = g_new(UnknownToken, 1); ut->token = g_strdup(token); ut->value = g_strdup(tmp2); unknown_tokens = g_list_append(unknown_tokens, ut); } } else { giramrc_set_token(token, tmp2); } length += strlen(tmp2); *tmp = '}'; tmp += 1; substituted = TRUE; } else { length += 1; tmp += 1; } } if ((length == strlen(path)) && !substituted) return path; new_path = g_new(char, length + 1); tmp = path; tmp2 = new_path; while (*tmp) { if (*tmp == '~') { *tmp2 = '\0'; strcat(tmp2, home); tmp2 += strlen(home); tmp += 1; } else if (*tmp == '$') { tmp += 1; if (!*tmp || (*tmp != '{')) { g_free(new_path); return path; } tmp += 1; token = tmp; while (*tmp && (*tmp != '}')) tmp += 1; if (!*tmp) { g_free(new_path); return path; } *tmp = '\0'; token = giramrc_find_token(token); *tmp = '}'; *tmp2 = '\0'; strcat(tmp2, token); tmp2 += strlen(token); tmp += 1; } else { *tmp2++ = *tmp++; } } *tmp2 = '\0'; if (destroy) g_free(path); return new_path; } /* Copied from gtk_menu_factory_parse_accelerator() */ #if 0 static void parse_device_accelerator(const gchar *accelerator, GdkDeviceKey *key) { gboolean done = FALSE; g_return_if_fail(accelerator != NULL); g_return_if_fail(key != NULL); key->modifiers = 0; while (!done) { if (strncmp(accelerator, "", 7) == 0) { accelerator += 7; key->modifiers |= GDK_SHIFT_MASK; } else if (strncmp(accelerator, "", 5) == 0) { accelerator += 5; key->modifiers |= GDK_MOD1_MASK; } else if (strncmp(accelerator, "", 9) == 0) { accelerator += 9; key->modifiers |= GDK_CONTROL_MASK; } else { done = TRUE; /* Tricky, but works... ("" => keyval = 0, or no translation) */ key->keyval = accelerator[0]; } } } #endif #if 0 static gint parse_help_browser(gpointer val1p, gpointer val2p) { gint token; token = peek_next_token(); if (!token || token != TOKEN_SYMBOL) return ERROR; token = get_next_token(); if (strcmp(token_sym, "giram") == 0) help_browser = HELP_BROWSER_GIRAM; else if (strcmp(token_sym, "netscape") == 0) help_browser = HELP_BROWSER_NETSCAPE; token = peek_next_token(); if (!token || (token != TOKEN_RIGHT_PAREN)) return ERROR; token = get_next_token(); return OK; } #endif static gint parse_unknown(gchar *token_sym) { gint token; UnknownToken *ut; UnknownToken *tmp; GList *list; ut = g_new(UnknownToken, 1); ut->token = g_strdup(token_sym); token = peek_next_token(); if (!token || (token != TOKEN_STRING)) { g_free(ut->token); g_free(ut); return ERROR; } token = get_next_token(); ut->value = g_strdup(token_str); token = peek_next_token(); if (!token || (token != TOKEN_RIGHT_PAREN)) { g_free(ut->token); g_free(ut->value); g_free(ut); return ERROR; } token = get_next_token(); /* search through the list of unknown tokens and replace an existing entry */ list = unknown_tokens; while (list) { tmp = (UnknownToken *)list->data; list = list->next; if (strcmp(tmp->token, ut->token) == 0) { unknown_tokens = g_list_remove(unknown_tokens, tmp); g_free(tmp->token); g_free(tmp->value); g_free(tmp); } } ut->value = transform_path(ut->value, TRUE); unknown_tokens = g_list_append(unknown_tokens, ut); return OK; } gchar *gimprc_value_to_str(gchar *name) { return value_to_str(name); /* had a namespace collision */ } static gchar *value_to_str(gchar *name) { gint i; for (i = 0; i < n_funcs; i++) if (! strcmp(funcs[i].name, name)) switch (funcs[i].type) { case TT_STRING: return string_to_str(funcs[i].val1p, funcs[i].val2p); case TT_PATH: return path_to_str(funcs[i].val1p, funcs[i].val2p); case TT_DOUBLE: return double_to_str(funcs[i].val1p, funcs[i].val2p); case TT_FLOAT: return float_to_str(funcs[i].val1p, funcs[i].val2p); case TT_INT: return int_to_str(funcs[i].val1p, funcs[i].val2p); case TT_BOOLEAN: return boolean_to_str(funcs[i].val1p, funcs[i].val2p); /* case TT_XHELPBROWSER: return help_browser_to_str(funcs[i].val1p, funcs[i].val2p);*/ case TT_XCOMMENT: return comment_to_str(funcs[i].val1p, funcs[i].val2p); case TT_XMENUPATH: return NULL; } return NULL; } static gchar *string_to_str(gpointer val1p, gpointer val2p) { gchar *str = giram_strescape(*((char **)val1p), NULL); gchar *retval; retval = g_strdup_printf("%c%s%c", '"', str, '"'); g_free (str); return retval; } static gchar *path_to_str(gpointer val1p, gpointer val2p) { return string_to_str (val1p, val2p); } static gchar *double_to_str(gpointer val1p, gpointer val2p) { return g_strdup_printf("%f", *((gdouble *)val1p)); } static gchar *float_to_str(gpointer val1p, gpointer val2p) { return g_strdup_printf("%f", (gdouble)(*((float *)val1p))); } static gchar *int_to_str(gpointer val1p, gpointer val2p) { return g_strdup_printf("%d", *((gint *)val1p)); } static gchar *boolean_to_str(gpointer val1p, gpointer val2p) { int v; if (val1p != NULL) v = *((int *)val1p); else v = !*((int *)val2p); if (v) return g_strdup("yes"); else return g_strdup("no"); } /*static gchar *help_browser_to_str(gpointer val1p, gpointer val2p) { if (help_browser == HELP_BROWSER_NETSCAPE) return g_strdup("netscape"); else return g_strdup("gimp"); }*/ static gchar *comment_to_str(gpointer val1p, gpointer val2p) { gchar **str_array; gchar *retval; gchar *str = giram_strescape(*((gchar **) val1p), NULL); str_array = g_strsplit(str, "\n", 0); g_free(str); str = g_strjoinv("\\n", str_array); g_strfreev(str_array); retval = g_strdup_printf("%c%s%c", '"', str, '"'); g_free(str); return retval; } static void add_giram_directory_token(const gchar *giram_dir) { UnknownToken *ut; /* * The token holds data from a static buffer which is initialized * once. There should be no need to change an already-existing * value. */ if (NULL != giramrc_find_token("giram_dir")) return; ut = g_new(UnknownToken, 1); ut->token = g_strdup("giram_dir"); ut->value = g_strdup(giram_dir); /* Similarly, transforming the path should be silly. */ unknown_tokens = g_list_append(unknown_tokens, ut); /* While we're at it, also add the token gimp_install_dir */ ut = g_new(UnknownToken, 1); ut->token = g_strdup("gimp_install_dir"); ut->value = (gchar *)giram_data_directory(); unknown_tokens = g_list_append(unknown_tokens, ut); } /* Try to: * * 1. Open the personal file for reading. * * 1b. If that fails, try to open the system (overriding) file * * 2. If we could open the personal file, rename it to file.old. * * 3. Open personal file for writing. * * On success, return NULL. On failure, return a string in English * explaining the problem. * */ static gchar *open_backup_file(gchar *filename, gchar *secondary_filename, gchar **name_used, FILE **fp_new, FILE **fp_old) { gchar *oldfilename = NULL; /* Rename the file to *.old, open it for reading and create the new file. */ if ((*fp_old = fopen(filename, "rt")) == NULL) { if ((*fp_old = fopen(secondary_filename, "rt")) == NULL) { return g_strdup_printf(_("Can't open %s; %s"), secondary_filename, g_strerror(errno)); } else *name_used = secondary_filename; } else { *name_used = filename; oldfilename = g_strdup_printf("%s.old", filename); if (rename(filename, oldfilename) < 0) { g_free(oldfilename); return g_strdup_printf(_("Can't rename %s to %s.old; %s"), filename, filename, g_strerror (errno)); } } if ((*fp_new = fopen(filename, "w")) == NULL) { if (oldfilename != NULL) { /* Undo the renaming... */ (void)rename(oldfilename, filename); g_free(oldfilename); } return g_strdup_printf(_("Can't write to %s; %s"), filename, g_strerror(errno)); } if (oldfilename != NULL) g_free(oldfilename); return NULL; } gchar *giramrc_find_token(gchar *token) { GList *list; UnknownToken *ut; for (list = unknown_tokens; list; list = g_list_next(list)) { ut = (UnknownToken *)list->data; if (strcmp(ut->token, token) == 0) return ut->value; } return NULL; } static void giramrc_set_token(gchar *token, gchar *value) { GList *list; UnknownToken *ut; for (list = unknown_tokens; list; list = g_list_next(list)) { ut = (UnknownToken *)list->data; if (strcmp(ut->token, token) == 0) { if (ut->value != value) { if (ut->value) g_free(ut->value); ut->value = value; } break; } } }