Line data Source code
1 : /* Copyright (C) 2000-2012 by George Williams */
2 : /*
3 : * Redistribution and use in source and binary forms, with or without
4 : * modification, are permitted provided that the following conditions are met:
5 :
6 : * Redistributions of source code must retain the above copyright notice, this
7 : * list of conditions and the following disclaimer.
8 :
9 : * Redistributions in binary form must reproduce the above copyright notice,
10 : * this list of conditions and the following disclaimer in the documentation
11 : * and/or other materials provided with the distribution.
12 :
13 : * The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 :
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 : * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 : #include <stdio.h>
28 : #include <string.h>
29 : #include <stdlib.h>
30 : #include <ustring.h>
31 :
32 : #include <gdraw.h>
33 : #include <gresource.h>
34 : #include <fileutil.h>
35 : #include "charset.h"
36 : #include "fontP.h"
37 : #include <utype.h>
38 :
39 : #include "gresourceP.h"
40 :
41 : char *GResourceProgramName, *GResourceFullProgram, *GResourceProgramDir;
42 : char *usercharset_names;
43 : /* int local_encoding = e_iso8859_1;*/
44 :
45 : static int rcur, rmax=0;
46 : static int rbase = 0, rsummit=0, rskiplen=0; /* when restricting a search */
47 : struct _GResource_Res *_GResource_Res;
48 :
49 0 : static int rcompar(const void *_r1,const void *_r2) {
50 0 : const struct _GResource_Res *r1 = _r1, *r2 = _r2;
51 0 : return( strcmp(r1->res,r2->res));
52 : }
53 :
54 0 : int _GResource_FindResName(const char *name) {
55 0 : int top=rsummit, bottom = rbase;
56 : int test, cmp;
57 :
58 0 : if ( rcur==0 )
59 0 : return( -1 );
60 :
61 : for (;;) {
62 0 : if ( top==bottom )
63 0 : return( -1 );
64 0 : test = (top+bottom)/2;
65 0 : cmp = strcmp(name,_GResource_Res[test].res+rskiplen);
66 0 : if ( cmp==0 )
67 0 : return( test );
68 0 : if ( test==bottom )
69 0 : return( -1 );
70 0 : if ( cmp>0 )
71 0 : bottom=test+1;
72 : else
73 0 : top = test;
74 0 : }
75 : }
76 :
77 0 : static int GResourceRestrict(char *prefix) {
78 0 : int top=rcur, bottom = 0;
79 : int test, cmp;
80 : int plen;
81 : int oldtest, oldtop;
82 :
83 0 : if ( prefix==NULL || *prefix=='\0' ) {
84 0 : rbase = rskiplen = 0; rsummit = rcur;
85 0 : return( rcur==0?-1:0 );
86 : }
87 0 : if ( rcur==0 )
88 0 : return( -1 );
89 :
90 0 : plen = strlen(prefix);
91 :
92 : for (;;) {
93 0 : test = (top+bottom)/2;
94 0 : cmp = strncmp(prefix,_GResource_Res[test].res,plen);
95 0 : if ( cmp==0 )
96 0 : break;
97 0 : if ( test==bottom )
98 0 : return( -1 );
99 0 : if ( cmp>0 ) {
100 0 : bottom=test+1;
101 0 : if ( bottom==top )
102 0 : return( -1 );
103 : } else
104 0 : top = test;
105 0 : }
106 : /* at this point the resource at test begins with the prefix */
107 : /* we want to find the first and last resources that do */
108 0 : oldtop = top; oldtest = top = test; /* find the first resource */
109 : for (;;) {
110 0 : test = (top+bottom)/2;
111 0 : cmp = strncmp(prefix,_GResource_Res[test].res,plen);
112 0 : if ( cmp<0 ) {
113 0 : GDrawIError("Resource list out of order");
114 0 : return( -1 );
115 : }
116 0 : if ( test==bottom ) {
117 0 : if ( cmp!=0 ) ++test;
118 0 : break;
119 : }
120 0 : if ( cmp>0 ) {
121 0 : bottom=++test;
122 0 : if ( bottom==top )
123 0 : break;
124 : } else
125 0 : top = test;
126 0 : }
127 0 : rbase = test;
128 :
129 0 : top = oldtop; bottom = oldtest+1; /* find the last resource */
130 0 : if ( bottom == top )
131 0 : test = top;
132 : else for (;;) {
133 0 : test = (top+bottom)/2;
134 0 : cmp = strncmp(prefix,_GResource_Res[test].res,plen);
135 0 : if ( cmp>0 ) {
136 0 : GDrawIError("Resource list out of order");
137 0 : return( -1 );
138 : }
139 0 : if ( test==bottom ) {
140 0 : if ( cmp==0 ) ++test;
141 0 : break;
142 : }
143 0 : if ( cmp==0 ) {
144 0 : bottom=++test;
145 0 : if ( bottom==top )
146 0 : break;
147 : } else
148 0 : top = test;
149 0 : }
150 0 : rsummit = test;
151 0 : rskiplen = plen;
152 0 : return( 0 );
153 : }
154 :
155 40 : void GResourceSetProg(char *prog) {
156 : char filename[1025], *pt;
157 : extern char *_GFile_find_program_dir(char *prog);
158 :
159 40 : if ( prog!=NULL ) {
160 40 : if ( GResourceProgramName!=NULL && strcmp(prog,GResourceProgramName)==0 )
161 0 : return;
162 40 : free(GResourceProgramName);
163 40 : if (( pt=strrchr(prog,'/'))!=NULL )
164 40 : ++pt;
165 : else
166 0 : pt = prog;
167 40 : GResourceProgramName = copy(pt);
168 0 : } else if ( GResourceProgramName==NULL )
169 0 : GResourceProgramName = copy("gdraw");
170 : else
171 0 : return;
172 :
173 40 : free(GResourceProgramDir);
174 40 : GResourceProgramDir = _GFile_find_program_dir(prog);
175 40 : if ( GResourceProgramDir==NULL ) {
176 0 : GFileGetAbsoluteName(".",filename,sizeof(filename));
177 0 : GResourceProgramDir = copy(filename);
178 : }
179 40 : free(GResourceFullProgram);
180 80 : GResourceFullProgram = copy(
181 40 : GFileBuildName(GResourceProgramDir,GResourceProgramName,filename,sizeof(filename)));
182 : }
183 :
184 0 : void GResourceAddResourceString(char *string,char *prog) {
185 : char *pt, *ept, *next;
186 : int cnt, plen;
187 : struct _GResource_Res temp;
188 : int i,j,k, off;
189 :
190 0 : GResourceSetProg(prog);
191 0 : plen = strlen(GResourceProgramName);
192 :
193 0 : if ( string==NULL )
194 0 : return;
195 :
196 0 : cnt = 0;
197 0 : pt = string;
198 0 : while ( *pt!='\0' ) {
199 0 : next = strchr(pt,'\n');
200 0 : if ( next==NULL ) next = pt+strlen(pt);
201 0 : else ++next;
202 0 : if ( strncmp(pt,"Gdraw.",6)==0 ) ++cnt;
203 0 : else if ( strncmp(pt,GResourceProgramName,plen)==0 && pt[plen]=='.' ) ++cnt;
204 0 : else if ( strncmp(pt,"*",1)==0 ) ++cnt;
205 0 : pt = next;
206 : }
207 0 : if ( cnt==0 )
208 0 : return;
209 :
210 0 : if ( rcur+cnt>=rmax ) {
211 0 : if ( cnt<10 ) cnt = 10;
212 0 : if ( rmax==0 )
213 0 : _GResource_Res = malloc(cnt*sizeof(struct _GResource_Res));
214 : else
215 0 : _GResource_Res = realloc(_GResource_Res,(rcur+cnt)*sizeof(struct _GResource_Res));
216 0 : rmax += cnt;
217 : }
218 :
219 0 : pt = string;
220 0 : while ( *pt!='\0' ) {
221 0 : next = strchr(pt,'\n');
222 0 : if ( next==NULL ) next = pt+strlen(pt);
223 0 : if ( strncmp(pt,"Gdraw.",6)==0 || strncmp(pt,"*",1)==0 ||
224 0 : (strncmp(pt,GResourceProgramName,plen)==0 && pt[plen]=='.' )) {
225 0 : temp.generic = false;
226 0 : if ( strncmp(pt,"Gdraw.",6)==0 ) {
227 0 : temp.generic = true;
228 0 : off = 6;
229 0 : } else if ( strncmp(pt,"*",1)==0 ) {
230 0 : temp.generic = true;
231 0 : off = 1;
232 : } else
233 0 : off = plen+1;
234 0 : ept = strchr(pt+off,':');
235 0 : if ( ept==NULL )
236 0 : goto bad;
237 0 : temp.res = copyn(pt+off,ept-(pt+off));
238 0 : pt = ept+1;
239 0 : while ( isspace( *pt ) && pt<next ) ++pt;
240 0 : temp.val = copyn(pt,next-pt);
241 0 : temp.new = true;
242 0 : _GResource_Res[rcur++] = temp;
243 : }
244 : bad:
245 0 : if ( *next ) ++next;
246 0 : pt = next;
247 : }
248 :
249 0 : if ( rcur!=0 )
250 0 : qsort(_GResource_Res,rcur,sizeof(struct _GResource_Res),rcompar);
251 :
252 0 : for ( i=j=0; i<rcur; ) {
253 0 : if ( i!=j )
254 0 : _GResource_Res[j] = _GResource_Res[i];
255 0 : for ( k=i+1; k<rcur && strcmp(_GResource_Res[j].res,_GResource_Res[k].res)==0; ++k ) {
256 0 : if (( !_GResource_Res[k].generic && (_GResource_Res[i].generic || _GResource_Res[i+1].new)) ||
257 0 : (_GResource_Res[k].generic && _GResource_Res[i].generic && _GResource_Res[i+1].new)) {
258 0 : free(_GResource_Res[j].res); free(_GResource_Res[j].val);
259 0 : _GResource_Res[i].res=NULL;
260 0 : _GResource_Res[j] = _GResource_Res[k];
261 : } else {
262 0 : free(_GResource_Res[k].res); free(_GResource_Res[k].val);
263 0 : _GResource_Res[k].res=NULL;
264 : }
265 : }
266 0 : i = k; ++j;
267 : }
268 0 : rcur = rsummit = j;
269 0 : for ( i=0; i<j; ++i )
270 0 : _GResource_Res[i].new = false;
271 :
272 0 : if ( (i=_GResource_FindResName("LocalCharSet"))!=-1 ) {
273 0 : local_encoding = _GDraw_ParseMapping(c_to_u(_GResource_Res[i].val));
274 0 : if ( local_encoding==em_none )
275 0 : local_encoding = em_iso8859_1;
276 0 : local_encoding += e_iso8859_1-em_iso8859_1;
277 : }
278 : }
279 :
280 41 : void GResourceAddResourceFile(char *filename,char *prog,int warn) {
281 : FILE *file;
282 : char buffer[1000];
283 :
284 41 : file = fopen(filename,"r");
285 41 : if ( file==NULL ) {
286 41 : if ( warn )
287 1 : fprintf( stderr, "Failed to open resource file: %s\n", filename );
288 82 : return;
289 : }
290 0 : while ( fgets(buffer,sizeof(buffer),file)!=NULL )
291 0 : GResourceAddResourceString(buffer,prog);
292 0 : fclose(file);
293 : }
294 :
295 0 : void GResourceFind( GResStruct *info,char *prefix) {
296 : int pos;
297 :
298 0 : if ( GResourceRestrict(prefix)== -1 ) {
299 0 : rbase = rskiplen = 0; rsummit = rcur;
300 0 : return;
301 : }
302 0 : while ( info->resname!=NULL ) {
303 0 : pos = _GResource_FindResName(info->resname);
304 0 : info->found = (pos!=-1);
305 0 : if ( pos==-1 )
306 : /* Do Nothing */;
307 0 : else if ( info->type == rt_string ) {
308 0 : if ( info->cvt!=NULL )
309 0 : *(void **) (info->val) = (info->cvt)( _GResource_Res[pos].val, *(void **) (info->val) );
310 : else
311 0 : *(char **) (info->val) = copy( _GResource_Res[pos].val );
312 0 : } else if ( info->type == rt_color ) {
313 0 : Color temp = _GImage_ColourFName(_GResource_Res[pos].val );
314 0 : if ( temp==-1 ) {
315 0 : fprintf( stderr, "Can't convert %s to a Color for resource: %s\n",
316 0 : _GResource_Res[pos].val, info->resname );
317 0 : info->found = false;
318 : } else
319 0 : *(Color *) (info->val) = temp;
320 0 : } else if ( info->type == rt_int ) {
321 : char *end;
322 0 : int val = strtol(_GResource_Res[pos].val,&end,0);
323 0 : if ( *end!='\0' ) {
324 0 : fprintf( stderr, "Can't convert %s to an int for resource: %s\n",
325 0 : _GResource_Res[pos].val, info->resname );
326 0 : info->found = false;
327 : } else
328 0 : *(int *) (info->val) = val;
329 0 : } else if ( info->type == rt_bool ) {
330 0 : int val = -1;
331 0 : if ( strmatch(_GResource_Res[pos].val,"true")==0 ||
332 0 : strmatch(_GResource_Res[pos].val,"on")==0 || strcmp(_GResource_Res[pos].val,"1")==0 )
333 0 : val = 1;
334 0 : else if ( strmatch(_GResource_Res[pos].val,"false")==0 ||
335 0 : strmatch(_GResource_Res[pos].val,"off")==0 || strcmp(_GResource_Res[pos].val,"0")==0 )
336 0 : val = 0;
337 0 : if ( val==-1 ) {
338 0 : fprintf( stderr, "Can't convert %s to a boolean for resource: %s\n",
339 0 : _GResource_Res[pos].val, info->resname );
340 0 : info->found = false;
341 : } else
342 0 : *(int *) (info->val) = val;
343 0 : } else if ( info->type == rt_double ) {
344 : char *end;
345 0 : double val = strtod(_GResource_Res[pos].val,&end);
346 0 : if ( *end=='.' || *end==',' ) {
347 0 : *end = (*end==',')?'.':',';
348 0 : val = strtod(_GResource_Res[pos].val,&end);
349 : }
350 0 : if ( *end!='\0' ) {
351 0 : fprintf( stderr, "Can't convert %s to a double for resource: %s\n",
352 0 : _GResource_Res[pos].val, info->resname );
353 0 : info->found = false;
354 : } else
355 0 : *(double *) (info->val) = val;
356 : } else {
357 0 : fprintf( stderr, "Invalid resource type for: %s\n", info->resname );
358 0 : info->found = false;
359 : }
360 0 : ++info;
361 : }
362 0 : rbase = rskiplen = 0; rsummit = rcur;
363 : }
364 :
365 0 : char *GResourceFindString(char *name) {
366 : int pos;
367 :
368 0 : pos = _GResource_FindResName(name);
369 0 : if ( pos==-1 )
370 0 : return( NULL );
371 : else
372 0 : return( copy(_GResource_Res[pos].val));
373 : }
374 :
375 0 : int GResourceFindBool(char *name, int def) {
376 : int pos;
377 0 : int val = -1;
378 :
379 0 : pos = _GResource_FindResName(name);
380 0 : if ( pos==-1 )
381 0 : return( def );
382 :
383 0 : if ( strmatch(_GResource_Res[pos].val,"true")==0 ||
384 0 : strmatch(_GResource_Res[pos].val,"on")==0 || strcmp(_GResource_Res[pos].val,"1")==0 )
385 0 : val = 1;
386 0 : else if ( strmatch(_GResource_Res[pos].val,"false")==0 ||
387 0 : strmatch(_GResource_Res[pos].val,"off")==0 || strcmp(_GResource_Res[pos].val,"0")==0 )
388 0 : val = 0;
389 :
390 0 : if ( val==-1 )
391 0 : return( def );
392 :
393 0 : return( val );
394 : }
395 :
396 0 : long GResourceFindInt(char *name, long def) {
397 : int pos;
398 : char *end;
399 : long ret;
400 :
401 0 : pos = _GResource_FindResName(name);
402 0 : if ( pos==-1 )
403 0 : return( def );
404 :
405 0 : ret = strtol(_GResource_Res[pos].val,&end,10);
406 0 : if ( *end!='\0' )
407 0 : return( def );
408 :
409 0 : return( ret );
410 : }
411 :
412 0 : Color GResourceFindColor(char *name, Color def) {
413 : int pos;
414 : Color ret;
415 :
416 0 : pos = _GResource_FindResName(name);
417 0 : if ( pos==-1 )
418 0 : return( def );
419 :
420 0 : ret = _GImage_ColourFName(_GResource_Res[pos].val );
421 0 : if ( ret==-1 )
422 0 : return( def );
423 :
424 0 : return( ret );
425 : }
|