1 /*
2 * This file is part of XForms.
3 *
4 * XForms is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as
6 * published by the Free Software Foundation; either version 2.1, or
7 * (at your option) any later version.
8 *
9 * XForms is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with XForms. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include <ctype.h>
24
25 #include "fd_main.h"
26 #include "fd_iconinfo.h"
27
28
29 /***************************************
30 ***************************************/
31
32 static int
is_blank(char c)33 is_blank( char c )
34 {
35 return c == ' ' || c == '\t';
36 }
37
38
39 /***************************************
40 ***************************************/
41
42 IconInfo *
get_iconinfo(FL_OBJECT * obj)43 get_iconinfo( FL_OBJECT * obj )
44 {
45 IconInfo *info = obj->c_vdata;
46
47 if ( obj->objclass != FL_PIXMAPBUTTON
48 && obj->objclass != FL_BITMAPBUTTON
49 && obj->objclass != FL_PIXMAP
50 && obj->objclass != FL_BITMAP )
51 return NULL;
52
53 if ( ! info )
54 {
55 info = obj->c_vdata = fl_malloc( sizeof *info );
56
57 info->use_data = 0;
58 info->show_focus = 1;
59 info->dx = 0;
60 info->dy = 0;
61 info->align = FL_ALIGN_CENTER;
62 info->fullpath = 1;
63 *info->filename = '\0';
64 *info->focus_filename = '\0';
65 *info->data = '\0';
66 *info->focus_data = '\0';
67 *info->width = '\0';
68 *info->height = '\0';
69 }
70
71 return info;
72 }
73
74
75 /***************************************
76 ***************************************/
77
78 void
copy_iconinfo(FL_OBJECT * target,FL_OBJECT * src)79 copy_iconinfo( FL_OBJECT * target,
80 FL_OBJECT * src )
81 {
82 IconInfo *si = get_iconinfo( src ),
83 *ti;
84
85 fli_safe_free( target->c_vdata );
86
87 if ( ! si )
88 return;
89
90 ti = get_iconinfo( target );
91 *ti = *si;
92 }
93
94
95 /***************************************
96 ***************************************/
97
98 void
free_iconinfo(FL_OBJECT * obj)99 free_iconinfo( FL_OBJECT * obj )
100 {
101 fli_safe_free( obj->c_vdata );
102 }
103
104
105 /***************************************
106 * Function tries to read a line (of arbirary length) from a file
107 * On failure (either due to read error or missing memory) NULL is
108 * returned, otherwise a pointer to an allocated buffer that must
109 * be freed by the caller.
110 ***************************************/
111
112 #define STRING_TRY_LENGTH 128
113
114 static char *
read_line(FILE * fp)115 read_line( FILE * fp )
116 {
117 char *line = NULL;
118 char *old_line = NULL;
119 size_t len = STRING_TRY_LENGTH;
120 size_t old_len = 0;
121
122 while ( 1 )
123 {
124 if ( ( line = fl_realloc( line, len ) ) == NULL )
125 {
126 fli_safe_free( old_line );
127 return NULL;
128 }
129
130 if ( ! fgets( line + old_len, len - old_len, fp ) )
131 {
132 if ( ferror( fp ) )
133 {
134 fl_free( line );
135 return NULL;
136 }
137
138 if ( old_len == 0 )
139 {
140 fl_free( line );
141 return NULL;
142 }
143
144 break;
145 }
146
147 if ( strchr( line + old_len, '\n' ) )
148 break;
149
150 old_line = line;
151 old_len = len - 1;
152 len *= 2;
153 }
154
155 old_line = line;
156 if ( ( line = fl_realloc( line, strlen( line ) + 1 ) ) == NULL )
157 return old_line;
158 return line;
159 }
160
161
162 /***************************************
163 ***************************************/
164
165 static const char *
check_for_define(const char * line)166 check_for_define( const char * line )
167 {
168 while ( *line && is_blank( *line ) )
169 line++;
170
171 if ( ! *line || *line != '#' )
172 return NULL;
173
174 while ( *++line && is_blank( *line ) )
175 /* empty */ ;
176
177 if ( ! *line )
178 return NULL;
179
180 if ( strncmp( line, "define", 6 ) )
181 return NULL;
182
183 line += 6;
184
185 while ( *line && is_blank( *line ) )
186 line++;
187
188 if ( ! ( isupper( *line ) || islower( *line ) || *line == '_' ) )
189 return NULL;
190
191 return line;
192 }
193
194
195 /***************************************
196 ***************************************/
197
198 static char *
check_for_end(const char * line,const char * what)199 check_for_end( const char * line,
200 const char * what )
201 {
202 static char name[ MAX_VAR_LEN ];
203 const char *start;
204 size_t len;
205
206 if ( ( ! ( start = check_for_define( line ) ) ) )
207 return NULL;
208
209 line = start;
210
211 while ( *line
212 && ( isupper( *line )
213 || islower( *line )
214 || isdigit( *line )
215 || *line == '_' ) )
216 line++;
217
218 if ( ! is_blank( *line ) )
219 return NULL;
220
221 len = line - start;
222 if ( len > MAX_VAR_LEN - 1 || len <= strlen( what ) )
223 return NULL;
224
225 strncpy( name, start, len );
226 name[ len ] = '\0';
227
228 if ( strcmp( name + len - strlen( what ), what ) )
229 return NULL;
230
231 return name;
232 }
233
234
235 /***************************************
236 ***************************************/
237
238 static char *
check_for_data(const char * line,const char * what)239 check_for_data( const char * line,
240 const char * what )
241 {
242 static char name[ MAX_VAR_LEN ];
243 const char *start;
244 size_t len;
245
246 /* Skip leading blanks */
247
248 while ( *line && is_blank( *line ) )
249 line++;
250
251 /* First word must be 'static', followed by a blank */
252
253 if ( ! *line || strncmp( line, "static", 6 ) )
254 return NULL;
255
256 line += 6;
257
258 if ( ! *line || ! is_blank( *line ) )
259 return NULL;
260
261 while ( *++line && is_blank( *line ) )
262 /* empty */ ;
263
264 /* Skip optional 'const', followed by a blank */
265
266 if ( ! strncmp( line, "const", 5 ) )
267 {
268 line += 5;
269
270 if ( ! *line || ! is_blank( *line ) )
271 return NULL;
272
273 while ( *++line && is_blank( *line ) )
274 /* empty */ ;
275 }
276
277 /* Skip optional 'unsigned', followed by a blank */
278
279 if ( ! strncmp( line, "unsigned", 8 ) )
280 {
281 line += 8;
282
283 if ( ! *line || ! is_blank( *line ) )
284 return NULL;
285
286 while ( *++line && is_blank( *line ) )
287 /* empty */ ;
288 }
289
290 /* Now 'char', followed by at least one blank must follow */
291
292 if ( ! *line || strncmp( line, "char", 4 ) )
293 return NULL;
294
295 line += 4;
296
297 if ( ! *line || ! ( is_blank( *line ) || *line == '*' ) )
298 return NULL;
299
300 while ( *++line && is_blank( *line ) )
301 /* empty */ ;
302
303 /* Skip optional 'const', followed by a blank */
304
305 if ( ! strncmp( line, "const", 5 ) )
306 {
307 line += 5;
308
309 while ( *line && is_blank( *line ) )
310 line++;
311 }
312
313 /* When reading an xpm file a '*' must come next */
314
315 if ( ! strcmp( what, "_pixels" ) )
316 {
317 if ( ! *line || *line != '*' )
318 return NULL;
319
320 while ( ++line && is_blank( *line ) )
321 /* empty */ ;
322 }
323
324 /* Now we should have arrived at the variable name */
325
326 start = line;
327
328 while ( *line
329 && ( isupper( *line )
330 || islower( *line )
331 || isdigit( *line )
332 || *line == '_' ) )
333 line++;
334
335 /* Check that the variable name is ok */
336
337 len = line - start;
338 if ( len > MAX_VAR_LEN - 1 || ( ! strcmp( what, "_bits" ) && len < 6 ) )
339 return NULL;
340
341 strncpy( name, start, len );
342 name[ len ] = '\0';
343
344 /* A blank or a '[' must immediately followe the variable name */
345
346 if ( ! *line || ! ( is_blank( *line ) || *line == '[' ) )
347 return NULL;
348
349 /* Make sure that the next non-blank char is a '[' */
350
351 while ( *line && is_blank( *line ) )
352 line++;
353
354 return *line == '[' ? name : NULL;
355 }
356
357
358 /***************************************
359 * Tries to guess the names of the variables used for width, height
360 * and data in a xbm file from the file name.
361 ***************************************/
362
363 void
get_xbm_stuff(IconInfo * info,FILE * fp)364 get_xbm_stuff( IconInfo * info,
365 FILE * fp )
366 {
367 char *line;
368 char *res;
369 int found = 0;
370
371 *info->width = *info->height = *info->data = '\0';
372
373 while ( found < 3 && ( line = read_line( fp ) ) )
374 {
375 if ( ( res = check_for_end( line, "_width" ) ) )
376 {
377 strcpy( info->width, res );
378 found++;
379 }
380 else if ( ( res = check_for_end( line, "_height" ) ) )
381 {
382 strcpy( info->height, res );
383 found++;
384 }
385 else if ( ( res = check_for_data( line, "_bits" ) ) )
386 {
387 strcpy( info->data, res );
388 found++;
389 }
390
391 fl_free( line );
392 }
393
394 if ( found < 3 )
395 {
396 fprintf( stderr, "Failed to parse xbm file\n" );
397 *info->width = *info->height = *info->data = '\0';
398 }
399 }
400
401
402 /***************************************
403 * Read in an (already opened) xpm file and return via 'in'
404 * the name of the variable for the data.
405 ***************************************/
406
407 void
get_xpm_stuff(char * in,FILE * fp)408 get_xpm_stuff( char * in,
409 FILE * fp )
410 {
411 char *line;
412 char *res;
413
414 *in = '\0';
415
416 while ( ( line = read_line( fp ) ) )
417 {
418 if ( ( res = check_for_data( line, "_pixels" ) ) )
419 {
420 strcpy( in, res );
421 fl_free( line );
422 return;
423 }
424
425 fl_free( line );
426 }
427 }
428
429
430 /*
431 * Local variables:
432 * tab-width: 4
433 * indent-tabs-mode: nil
434 * End:
435 */
436