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
28 #include <fontforge-config.h>
29
30 #include "charset.h"
31 #include "fontP.h"
32 #include "gdraw.h"
33 #include "gfile.h"
34 #include "gresource.h"
35 #include "gresourceP.h"
36 #include "ustring.h"
37 #include "utype.h"
38
39 char *GResourceProgramName;
40 char *usercharset_names;
41 /* int local_encoding = e_iso8859_1;*/
42
43 static int rcur, rmax=0;
44 static int rbase = 0, rsummit=0, rskiplen=0; /* when restricting a search */
45 struct _GResource_Res *_GResource_Res;
46
rcompar(const void * _r1,const void * _r2)47 static int rcompar(const void *_r1,const void *_r2) {
48 const struct _GResource_Res *r1 = _r1, *r2 = _r2;
49 return( strcmp(r1->res,r2->res));
50 }
51
_GResource_FindResName(const char * name)52 int _GResource_FindResName(const char *name) {
53 int top=rsummit, bottom = rbase;
54 int test, cmp;
55
56 if ( rcur==0 )
57 return( -1 );
58
59 for (;;) {
60 if ( top==bottom )
61 return( -1 );
62 test = (top+bottom)/2;
63 cmp = strcmp(name,_GResource_Res[test].res+rskiplen);
64 if ( cmp==0 )
65 return( test );
66 if ( test==bottom )
67 return( -1 );
68 if ( cmp>0 )
69 bottom=test+1;
70 else
71 top = test;
72 }
73 }
74
GResourceRestrict(char * prefix)75 static int GResourceRestrict(char *prefix) {
76 int top=rcur, bottom = 0;
77 int test, cmp;
78 int plen;
79 int oldtest, oldtop;
80
81 if ( prefix==NULL || *prefix=='\0' ) {
82 rbase = rskiplen = 0; rsummit = rcur;
83 return( rcur==0?-1:0 );
84 }
85 if ( rcur==0 )
86 return( -1 );
87
88 plen = strlen(prefix);
89
90 for (;;) {
91 test = (top+bottom)/2;
92 cmp = strncmp(prefix,_GResource_Res[test].res,plen);
93 if ( cmp==0 )
94 break;
95 if ( test==bottom )
96 return( -1 );
97 if ( cmp>0 ) {
98 bottom=test+1;
99 if ( bottom==top )
100 return( -1 );
101 } else
102 top = test;
103 }
104 /* at this point the resource at test begins with the prefix */
105 /* we want to find the first and last resources that do */
106 oldtop = top; oldtest = top = test; /* find the first resource */
107 for (;;) {
108 test = (top+bottom)/2;
109 cmp = strncmp(prefix,_GResource_Res[test].res,plen);
110 if ( cmp<0 ) {
111 GDrawIError("Resource list out of order");
112 return( -1 );
113 }
114 if ( test==bottom ) {
115 if ( cmp!=0 ) ++test;
116 break;
117 }
118 if ( cmp>0 ) {
119 bottom=++test;
120 if ( bottom==top )
121 break;
122 } else
123 top = test;
124 }
125 rbase = test;
126
127 top = oldtop; bottom = oldtest+1; /* find the last resource */
128 if ( bottom == top )
129 test = top;
130 else for (;;) {
131 test = (top+bottom)/2;
132 cmp = strncmp(prefix,_GResource_Res[test].res,plen);
133 if ( cmp>0 ) {
134 GDrawIError("Resource list out of order");
135 return( -1 );
136 }
137 if ( test==bottom ) {
138 if ( cmp==0 ) ++test;
139 break;
140 }
141 if ( cmp==0 ) {
142 bottom=++test;
143 if ( bottom==top )
144 break;
145 } else
146 top = test;
147 }
148 rsummit = test;
149 rskiplen = plen;
150 return( 0 );
151 }
152
GResourceSetProg(char * prog)153 void GResourceSetProg(char *prog) {
154 char filename[1025], *pt;
155 extern char *_GFile_find_program_dir(char *prog);
156
157 if ( prog!=NULL ) {
158 if ( GResourceProgramName!=NULL && strcmp(prog,GResourceProgramName)==0 )
159 return;
160 free(GResourceProgramName);
161 if (( pt=strrchr(prog,'/'))!=NULL )
162 ++pt;
163 else
164 pt = prog;
165 GResourceProgramName = copy(pt);
166 } else if ( GResourceProgramName==NULL )
167 GResourceProgramName = copy("gdraw");
168 else
169 return;
170 }
171
GResourceAddResourceString(char * string,char * prog)172 void GResourceAddResourceString(char *string,char *prog) {
173 char *pt, *ept, *next;
174 int cnt, plen;
175 struct _GResource_Res temp;
176 int i,j,k, off;
177
178 GResourceSetProg(prog);
179 plen = strlen(GResourceProgramName);
180
181 if ( string==NULL )
182 return;
183
184 cnt = 0;
185 pt = string;
186 while ( *pt!='\0' ) {
187 next = strchr(pt,'\n');
188 if ( next==NULL ) next = pt+strlen(pt);
189 else ++next;
190 if ( strncmp(pt,"Gdraw.",6)==0 ) ++cnt;
191 else if ( strncmp(pt,GResourceProgramName,plen)==0 && pt[plen]=='.' ) ++cnt;
192 else if ( strncmp(pt,"*",1)==0 ) ++cnt;
193 pt = next;
194 }
195 if ( cnt==0 )
196 return;
197
198 if ( rcur+cnt>=rmax ) {
199 if ( cnt<10 ) cnt = 10;
200 if ( rmax==0 )
201 _GResource_Res = malloc(cnt*sizeof(struct _GResource_Res));
202 else
203 _GResource_Res = realloc(_GResource_Res,(rcur+cnt)*sizeof(struct _GResource_Res));
204 rmax += cnt;
205 }
206
207 pt = string;
208 while ( *pt!='\0' ) {
209 next = strchr(pt,'\n');
210 if ( next==NULL ) next = pt+strlen(pt);
211 if ( strncmp(pt,"Gdraw.",6)==0 || strncmp(pt,"*",1)==0 ||
212 (strncmp(pt,GResourceProgramName,plen)==0 && pt[plen]=='.' )) {
213 temp.generic = false;
214 if ( strncmp(pt,"Gdraw.",6)==0 ) {
215 temp.generic = true;
216 off = 6;
217 } else if ( strncmp(pt,"*",1)==0 ) {
218 temp.generic = true;
219 off = 1;
220 } else
221 off = plen+1;
222 ept = strchr(pt+off,':');
223 if ( ept==NULL )
224 goto bad;
225 temp.res = copyn(pt+off,ept-(pt+off));
226 pt = ept+1;
227 while ( isspace( *pt ) && pt<next ) ++pt;
228 temp.val = copyn(pt,next-pt);
229 temp.new = true;
230 _GResource_Res[rcur++] = temp;
231 }
232 bad:
233 if ( *next ) ++next;
234 pt = next;
235 }
236
237 if ( rcur!=0 )
238 qsort(_GResource_Res,rcur,sizeof(struct _GResource_Res),rcompar);
239
240 for ( i=j=0; i<rcur; ) {
241 if ( i!=j )
242 _GResource_Res[j] = _GResource_Res[i];
243 for ( k=i+1; k<rcur && strcmp(_GResource_Res[j].res,_GResource_Res[k].res)==0; ++k ) {
244 if (( !_GResource_Res[k].generic && (_GResource_Res[i].generic || _GResource_Res[i+1].new)) ||
245 (_GResource_Res[k].generic && _GResource_Res[i].generic && _GResource_Res[i+1].new)) {
246 free(_GResource_Res[j].res); free(_GResource_Res[j].val);
247 _GResource_Res[i].res=NULL;
248 _GResource_Res[j] = _GResource_Res[k];
249 } else {
250 free(_GResource_Res[k].res); free(_GResource_Res[k].val);
251 _GResource_Res[k].res=NULL;
252 }
253 }
254 i = k; ++j;
255 }
256 rcur = rsummit = j;
257 for ( i=0; i<j; ++i )
258 _GResource_Res[i].new = false;
259
260 if ( (i=_GResource_FindResName("LocalCharSet"))!=-1 ) {
261 local_encoding = _GDraw_ParseMapping(c_to_u(_GResource_Res[i].val));
262 if ( local_encoding==em_none )
263 local_encoding = em_iso8859_1;
264 local_encoding += e_iso8859_1-em_iso8859_1;
265 }
266 }
267
GResourceAddResourceFile(char * filename,char * prog,int warn)268 void GResourceAddResourceFile(char *filename,char *prog,int warn) {
269 FILE *file;
270 char buffer[1000];
271
272 file = fopen(filename,"r");
273 if ( file==NULL ) {
274 if ( warn )
275 fprintf( stderr, "Failed to open resource file: %s\n", filename );
276 return;
277 }
278 while ( fgets(buffer,sizeof(buffer),file)!=NULL )
279 GResourceAddResourceString(buffer,prog);
280 fclose(file);
281 }
282
GResourceFind(GResStruct * info,char * prefix)283 void GResourceFind( GResStruct *info,char *prefix) {
284 int pos;
285
286 if ( GResourceRestrict(prefix)== -1 ) {
287 rbase = rskiplen = 0; rsummit = rcur;
288 return;
289 }
290 while ( info->resname!=NULL ) {
291 pos = _GResource_FindResName(info->resname);
292 info->found = (pos!=-1);
293 if ( pos==-1 )
294 /* Do Nothing */;
295 else if ( info->type == rt_string ) {
296 if ( info->cvt!=NULL )
297 *(void **) (info->val) = (info->cvt)( _GResource_Res[pos].val, *(void **) (info->val) );
298 else
299 *(char **) (info->val) = copy( _GResource_Res[pos].val );
300 } else if ( info->type == rt_color ) {
301 Color temp = _GImage_ColourFName(_GResource_Res[pos].val );
302 if ( temp==-1 ) {
303 fprintf( stderr, "Can't convert %s to a Color for resource: %s\n",
304 _GResource_Res[pos].val, info->resname );
305 info->found = false;
306 } else
307 *(Color *) (info->val) = temp;
308 } else if ( info->type == rt_int ) {
309 char *end;
310 int val = strtol(_GResource_Res[pos].val,&end,0);
311 if ( *end!='\0' ) {
312 fprintf( stderr, "Can't convert %s to an int for resource: %s\n",
313 _GResource_Res[pos].val, info->resname );
314 info->found = false;
315 } else
316 *(int *) (info->val) = val;
317 } else if ( info->type == rt_bool ) {
318 int val = -1;
319 if ( strmatch(_GResource_Res[pos].val,"true")==0 ||
320 strmatch(_GResource_Res[pos].val,"on")==0 || strcmp(_GResource_Res[pos].val,"1")==0 )
321 val = 1;
322 else if ( strmatch(_GResource_Res[pos].val,"false")==0 ||
323 strmatch(_GResource_Res[pos].val,"off")==0 || strcmp(_GResource_Res[pos].val,"0")==0 )
324 val = 0;
325 if ( val==-1 ) {
326 fprintf( stderr, "Can't convert %s to a boolean for resource: %s\n",
327 _GResource_Res[pos].val, info->resname );
328 info->found = false;
329 } else
330 *(int *) (info->val) = val;
331 } else if ( info->type == rt_double ) {
332 char *end;
333 double val = strtod(_GResource_Res[pos].val,&end);
334 if ( *end=='.' || *end==',' ) {
335 *end = (*end==',')?'.':',';
336 val = strtod(_GResource_Res[pos].val,&end);
337 }
338 if ( *end!='\0' ) {
339 fprintf( stderr, "Can't convert %s to a double for resource: %s\n",
340 _GResource_Res[pos].val, info->resname );
341 info->found = false;
342 } else
343 *(double *) (info->val) = val;
344 } else {
345 fprintf( stderr, "Invalid resource type for: %s\n", info->resname );
346 info->found = false;
347 }
348 ++info;
349 }
350 rbase = rskiplen = 0; rsummit = rcur;
351 }
352
GResourceFindString(char * name)353 char *GResourceFindString(char *name) {
354 int pos;
355
356 pos = _GResource_FindResName(name);
357 if ( pos==-1 )
358 return( NULL );
359 else
360 return( copy(_GResource_Res[pos].val));
361 }
362
GResourceFindBool(char * name,int def)363 int GResourceFindBool(char *name, int def) {
364 int pos;
365 int val = -1;
366
367 pos = _GResource_FindResName(name);
368 if ( pos==-1 )
369 return( def );
370
371 if ( strmatch(_GResource_Res[pos].val,"true")==0 ||
372 strmatch(_GResource_Res[pos].val,"on")==0 || strcmp(_GResource_Res[pos].val,"1")==0 )
373 val = 1;
374 else if ( strmatch(_GResource_Res[pos].val,"false")==0 ||
375 strmatch(_GResource_Res[pos].val,"off")==0 || strcmp(_GResource_Res[pos].val,"0")==0 )
376 val = 0;
377
378 if ( val==-1 )
379 return( def );
380
381 return( val );
382 }
383
GResourceFindInt(char * name,long def)384 long GResourceFindInt(char *name, long def) {
385 int pos;
386 char *end;
387 long ret;
388
389 pos = _GResource_FindResName(name);
390 if ( pos==-1 )
391 return( def );
392
393 ret = strtol(_GResource_Res[pos].val,&end,10);
394 if ( *end!='\0' )
395 return( def );
396
397 return( ret );
398 }
399
GResourceFindColor(char * name,Color def)400 Color GResourceFindColor(char *name, Color def) {
401 int pos;
402 Color ret;
403
404 pos = _GResource_FindResName(name);
405 if ( pos==-1 )
406 return( def );
407
408 ret = _GImage_ColourFName(_GResource_Res[pos].val );
409 if ( ret==-1 )
410 return( def );
411
412 return( ret );
413 }
414