filename | src/lxpaths.c |
changeset | 1286:8376a612a79d |
prev | 1283:2cbafe321d6f |
next | 1296:30ecee61f811 |
author | nkeynes |
date | Fri Aug 24 08:53:50 2012 +1000 (11 years ago) |
permissions | -rw-r--r-- |
last change | Move the generated prologue/epilogue code out into a common entry stub (reduces space requirements) and pre-save all saved registers. Change FASTCALL to use 3 regs instead of 2 since we can now keep everything in regs. |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
3 *
4 * GUI helper functions that aren't specific to any particular implementation.
5 *
6 * Copyright (c) 2009 Nathan Keynes.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
19 #include <ctype.h>
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <glib/gfileutils.h>
23 #include <glib/gstrfuncs.h>
24 #include <glib/gutils.h>
26 #include "gui.h"
27 #include "config.h"
29 static gchar *gui_paths[CONFIG_KEY_MAX];
31 /**
32 * Test if we need to escape a path to prevent substitution mangling.
33 * @return TRUE if the input value contains any character that doesn't
34 * match [a-zA-Z0-9._@%/] (this will escape slightly more than it needs to,
35 * but is safe)
36 */
37 static gboolean path_needs_escaping( const gchar *value )
38 {
39 const gchar *p = value;
40 while( *p ) {
41 if( !isalnum(*p) && *p != '.' && *p != '_' &&
42 *p != '@' && *p != '%' && *p != '/' ) {
43 return TRUE;
44 }
45 p++;
46 }
47 return FALSE;
48 }
50 gchar *get_escaped_path( const gchar *value )
51 {
52 if( value != NULL && path_needs_escaping(value) ) {
53 /* Escape with "", and backslash the remaining characters:
54 * \ " $ `
55 */
56 char buf[strlen(value)*2+3];
57 const char *s = value;
58 char *p = buf;
59 *p++ = '\"';
60 while( *s ) {
61 if( *s == '\\' || *s == '"' || *s == '$' || *s == '`' ) {
62 *p++ = '\\';
63 }
64 *p++ = *s++;
65 }
66 *p++ = '\"';
67 *p = '\0';
68 return g_strdup(buf);
69 } else {
70 return g_strdup(value);
71 }
72 }
74 gchar *get_expanded_path( const gchar *input )
75 {
76 char result[PATH_MAX];
78 char *d, *e;
79 const char *s;
80 d = result;
81 e = result+sizeof(result)-1;
82 s = input;
83 gboolean inDQstring = FALSE;
85 if( input == NULL )
86 return NULL;
88 while( *s ) {
89 if( d == e ) {
90 return g_strdup(input); /* expansion too long */
91 }
92 char c = *s++;
93 if( c == '$' ) {
94 if( *s == '{' ) {
95 s++;
96 const char *q = s;
97 while( *q != '}' ) {
98 if( ! *q ) {
99 return g_strdup(input); /* unterminated variable */
100 }
101 q++;
102 }
103 char *tmp = g_strndup(s, (q-s));
104 s = q+1;
105 char *value = getenv(tmp);
106 g_free(tmp);
107 if( value != NULL ) {
108 int len = strlen(value);
109 if( d + len > e )
110 return g_strdup(input);
111 strcpy(d, value);
112 d+=len;
113 } /* Else, empty string */
114 } else {
115 const char *q = s;
116 while( isalnum(*q) || *q == '_' ) {
117 q++;
118 }
119 if( q == s ) {
120 *d++ = '$';
121 } else {
122 char *tmp = g_strndup(s,q-s);
123 s = q;
124 char *value = getenv(tmp);
125 g_free(tmp);
126 if( value != NULL ) {
127 int len = strlen(value);
128 if( d + len > e )
129 return g_strdup(input);
130 strcpy(d, value);
131 d += len;
132 }
133 }
134 }
135 } else if( c == '\\' ) {
136 c = *s++;
137 if( c ) {
138 *d++ = c;
139 } else {
140 *d++ = '\\';
141 }
142 } else if( c == '\"' ) {
143 /* Unescaped double-quotes start a DQ string. Although we treat the
144 * string as if it were double-quoted for most purposes anyway, so
145 * this has little effect.
146 */
147 inDQstring = !inDQstring;
148 } else {
149 *d++ = c;
150 }
151 }
152 *d = '\0';
153 if( inDQstring ) {
154 WARN( "Unterminated double-quoted string '%s'", input );
155 }
156 return g_strdup(result);
157 }
158 gchar *get_absolute_path( const gchar *in_path )
159 {
160 char tmp[PATH_MAX];
161 if( in_path == NULL ) {
162 return NULL;
163 }
164 if( in_path[0] == '/' || in_path[0] == 0 ) {
165 return g_strdup(in_path);
166 } else {
167 getcwd(tmp, sizeof(tmp));
168 return g_strdup_printf("%s%c%s", tmp, G_DIR_SEPARATOR, in_path);
169 }
170 }
172 gchar *get_filename_at( const gchar *at, const gchar *filename )
173 {
174 char tmp[PATH_MAX];
175 char *p = strrchr( at, '/' );
176 if( p == NULL ) {
177 /* No path at all, so just return filename */
178 return g_strdup(filename);
179 } else {
180 int off = p-at;
181 return g_strdup_printf("%.*s%c%s", off, at, G_DIR_SEPARATOR, filename );
182 }
183 }
185 const gchar *get_gui_path( int key )
186 {
187 if( gui_paths[key] == NULL ) {
188 gui_paths[key] = lxdream_get_global_config_path_value(key);
189 /* If no path defined, go with the current working directory */
190 if( gui_paths[key] == NULL ) {
191 gui_paths[key] = get_absolute_path(".");
192 }
193 }
194 return gui_paths[key];
195 }
197 void set_gui_path( int key, const gchar *path )
198 {
199 g_free(gui_paths[key]);
200 gui_paths[key] = g_strdup(path);
201 }
203 void reset_gui_paths()
204 {
205 int i;
206 for( i=0; i < CONFIG_KEY_MAX; i++ ) {
207 g_free(gui_paths[i]);
208 gui_paths[i] = NULL;
209 }
210 }
.