nkeynes@1041: /** nkeynes@1041: * $Id$ nkeynes@1041: * nkeynes@1041: * GUI helper functions that aren't specific to any particular implementation. nkeynes@1041: * nkeynes@1041: * Copyright (c) 2009 Nathan Keynes. nkeynes@1041: * nkeynes@1041: * This program is free software; you can redistribute it and/or modify nkeynes@1041: * it under the terms of the GNU General Public License as published by nkeynes@1041: * the Free Software Foundation; either version 2 of the License, or nkeynes@1041: * (at your option) any later version. nkeynes@1041: * nkeynes@1041: * This program is distributed in the hope that it will be useful, nkeynes@1041: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@1041: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@1041: * GNU General Public License for more details. nkeynes@1041: */ nkeynes@1041: nkeynes@1041: #include nkeynes@1041: #include nkeynes@1205: #include nkeynes@1296: #include nkeynes@1041: nkeynes@1041: #include "gui.h" nkeynes@1041: #include "config.h" nkeynes@1041: nkeynes@1041: static gchar *gui_paths[CONFIG_KEY_MAX]; nkeynes@1041: nkeynes@1041: /** nkeynes@1041: * Test if we need to escape a path to prevent substitution mangling. nkeynes@1041: * @return TRUE if the input value contains any character that doesn't nkeynes@1041: * match [a-zA-Z0-9._@%/] (this will escape slightly more than it needs to, nkeynes@1041: * but is safe) nkeynes@1041: */ nkeynes@1041: static gboolean path_needs_escaping( const gchar *value ) nkeynes@1041: { nkeynes@1041: const gchar *p = value; nkeynes@1041: while( *p ) { nkeynes@1041: if( !isalnum(*p) && *p != '.' && *p != '_' && nkeynes@1041: *p != '@' && *p != '%' && *p != '/' ) { nkeynes@1041: return TRUE; nkeynes@1041: } nkeynes@1041: p++; nkeynes@1041: } nkeynes@1041: return FALSE; nkeynes@1041: } nkeynes@1041: nkeynes@1041: gchar *get_escaped_path( const gchar *value ) nkeynes@1041: { nkeynes@1041: if( value != NULL && path_needs_escaping(value) ) { nkeynes@1041: /* Escape with "", and backslash the remaining characters: nkeynes@1041: * \ " $ ` nkeynes@1041: */ nkeynes@1041: char buf[strlen(value)*2+3]; nkeynes@1041: const char *s = value; nkeynes@1041: char *p = buf; nkeynes@1041: *p++ = '\"'; nkeynes@1041: while( *s ) { nkeynes@1041: if( *s == '\\' || *s == '"' || *s == '$' || *s == '`' ) { nkeynes@1041: *p++ = '\\'; nkeynes@1041: } nkeynes@1041: *p++ = *s++; nkeynes@1041: } nkeynes@1041: *p++ = '\"'; nkeynes@1041: *p = '\0'; nkeynes@1041: return g_strdup(buf); nkeynes@1041: } else { nkeynes@1041: return g_strdup(value); nkeynes@1041: } nkeynes@1041: } nkeynes@1041: nkeynes@1041: gchar *get_expanded_path( const gchar *input ) nkeynes@1041: { nkeynes@1205: char result[PATH_MAX]; nkeynes@1205: nkeynes@1205: char *d, *e; nkeynes@1205: const char *s; nkeynes@1205: d = result; nkeynes@1205: e = result+sizeof(result)-1; nkeynes@1205: s = input; nkeynes@1283: gboolean inDQstring = FALSE; nkeynes@1205: nkeynes@1205: if( input == NULL ) nkeynes@1041: return NULL; nkeynes@1205: nkeynes@1205: while( *s ) { nkeynes@1205: if( d == e ) { nkeynes@1205: return g_strdup(input); /* expansion too long */ nkeynes@1205: } nkeynes@1205: char c = *s++; nkeynes@1205: if( c == '$' ) { nkeynes@1205: if( *s == '{' ) { nkeynes@1205: s++; nkeynes@1205: const char *q = s; nkeynes@1205: while( *q != '}' ) { nkeynes@1205: if( ! *q ) { nkeynes@1205: return g_strdup(input); /* unterminated variable */ nkeynes@1205: } nkeynes@1205: q++; nkeynes@1205: } nkeynes@1205: char *tmp = g_strndup(s, (q-s)); nkeynes@1205: s = q+1; nkeynes@1205: char *value = getenv(tmp); nkeynes@1205: g_free(tmp); nkeynes@1205: if( value != NULL ) { nkeynes@1205: int len = strlen(value); nkeynes@1205: if( d + len > e ) nkeynes@1205: return g_strdup(input); nkeynes@1205: strcpy(d, value); nkeynes@1205: d+=len; nkeynes@1205: } /* Else, empty string */ nkeynes@1205: } else { nkeynes@1205: const char *q = s; nkeynes@1205: while( isalnum(*q) || *q == '_' ) { nkeynes@1205: q++; nkeynes@1205: } nkeynes@1205: if( q == s ) { nkeynes@1205: *d++ = '$'; nkeynes@1205: } else { nkeynes@1205: char *tmp = g_strndup(s,q-s); nkeynes@1205: s = q; nkeynes@1205: char *value = getenv(tmp); nkeynes@1205: g_free(tmp); nkeynes@1205: if( value != NULL ) { nkeynes@1205: int len = strlen(value); nkeynes@1205: if( d + len > e ) nkeynes@1205: return g_strdup(input); nkeynes@1205: strcpy(d, value); nkeynes@1205: d += len; nkeynes@1205: } nkeynes@1205: } nkeynes@1205: } nkeynes@1205: } else if( c == '\\' ) { nkeynes@1205: c = *s++; nkeynes@1205: if( c ) { nkeynes@1205: *d++ = c; nkeynes@1205: } else { nkeynes@1205: *d++ = '\\'; nkeynes@1205: } nkeynes@1283: } else if( c == '\"' ) { nkeynes@1283: /* Unescaped double-quotes start a DQ string. Although we treat the nkeynes@1283: * string as if it were double-quoted for most purposes anyway, so nkeynes@1283: * this has little effect. nkeynes@1283: */ nkeynes@1283: inDQstring = !inDQstring; nkeynes@1205: } else { nkeynes@1205: *d++ = c; nkeynes@1205: } nkeynes@1041: } nkeynes@1205: *d = '\0'; nkeynes@1283: if( inDQstring ) { nkeynes@1283: WARN( "Unterminated double-quoted string '%s'", input ); nkeynes@1283: } nkeynes@1205: return g_strdup(result); nkeynes@1041: } nkeynes@1041: gchar *get_absolute_path( const gchar *in_path ) nkeynes@1041: { nkeynes@1041: char tmp[PATH_MAX]; nkeynes@1041: if( in_path == NULL ) { nkeynes@1041: return NULL; nkeynes@1041: } nkeynes@1041: if( in_path[0] == '/' || in_path[0] == 0 ) { nkeynes@1041: return g_strdup(in_path); nkeynes@1041: } else { nkeynes@1041: getcwd(tmp, sizeof(tmp)); nkeynes@1041: return g_strdup_printf("%s%c%s", tmp, G_DIR_SEPARATOR, in_path); nkeynes@1041: } nkeynes@1041: } nkeynes@1041: nkeynes@1041: gchar *get_filename_at( const gchar *at, const gchar *filename ) nkeynes@1041: { nkeynes@1056: char *p = strrchr( at, '/' ); nkeynes@1041: if( p == NULL ) { nkeynes@1041: /* No path at all, so just return filename */ nkeynes@1041: return g_strdup(filename); nkeynes@1041: } else { nkeynes@1056: int off = p-at; nkeynes@1041: return g_strdup_printf("%.*s%c%s", off, at, G_DIR_SEPARATOR, filename ); nkeynes@1041: } nkeynes@1041: } nkeynes@1041: nkeynes@1041: const gchar *get_gui_path( int key ) nkeynes@1041: { nkeynes@1041: if( gui_paths[key] == NULL ) { nkeynes@1041: gui_paths[key] = lxdream_get_global_config_path_value(key); nkeynes@1041: /* If no path defined, go with the current working directory */ nkeynes@1041: if( gui_paths[key] == NULL ) { nkeynes@1041: gui_paths[key] = get_absolute_path("."); nkeynes@1041: } nkeynes@1041: } nkeynes@1041: return gui_paths[key]; nkeynes@1041: } nkeynes@1041: nkeynes@1041: void set_gui_path( int key, const gchar *path ) nkeynes@1041: { nkeynes@1041: g_free(gui_paths[key]); nkeynes@1041: gui_paths[key] = g_strdup(path); nkeynes@1041: } nkeynes@1041: nkeynes@1041: void reset_gui_paths() nkeynes@1041: { nkeynes@1041: int i; nkeynes@1041: for( i=0; i < CONFIG_KEY_MAX; i++ ) { nkeynes@1041: g_free(gui_paths[i]); nkeynes@1041: gui_paths[i] = NULL; nkeynes@1041: } nkeynes@1041: }