mirror of
https://gitlab.winehq.org/wine/fontforge.git
synced 2025-10-14 02:47:57 +08:00
425 lines
11 KiB
C
425 lines
11 KiB
C
/* Copyright (C) 2000-2012 by George Williams */
|
|
/*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
|
|
* Redistributions of source code must retain the above copyright notice, this
|
|
* list of conditions and the following disclaimer.
|
|
|
|
* Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
|
|
* The name of the author may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
|
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <ustring.h>
|
|
|
|
#include <gdraw.h>
|
|
#include <gresource.h>
|
|
#include <fileutil.h>
|
|
#include "charset.h"
|
|
#include "fontP.h"
|
|
#include <utype.h>
|
|
|
|
#include "gresourceP.h"
|
|
|
|
char *GResourceProgramName, *GResourceFullProgram, *GResourceProgramDir;
|
|
char *usercharset_names;
|
|
/* int local_encoding = e_iso8859_1;*/
|
|
|
|
static int rcur, rmax=0;
|
|
static int rbase = 0, rsummit=0, rskiplen=0; /* when restricting a search */
|
|
struct _GResource_Res *_GResource_Res;
|
|
|
|
static int rcompar(const void *_r1,const void *_r2) {
|
|
const struct _GResource_Res *r1 = _r1, *r2 = _r2;
|
|
return( strcmp(r1->res,r2->res));
|
|
}
|
|
|
|
int _GResource_FindResName(char *name) {
|
|
int top=rsummit, bottom = rbase;
|
|
int test, cmp;
|
|
|
|
if ( rcur==0 )
|
|
return( -1 );
|
|
|
|
forever {
|
|
if ( top==bottom )
|
|
return( -1 );
|
|
test = (top+bottom)/2;
|
|
cmp = strcmp(name,_GResource_Res[test].res+rskiplen);
|
|
if ( cmp==0 )
|
|
return( test );
|
|
if ( test==bottom )
|
|
return( -1 );
|
|
if ( cmp>0 )
|
|
bottom=test+1;
|
|
else
|
|
top = test;
|
|
}
|
|
}
|
|
|
|
static int GResourceRestrict(char *prefix) {
|
|
int top=rcur, bottom = 0;
|
|
int test, cmp;
|
|
int plen;
|
|
int oldtest, oldtop;
|
|
|
|
if ( prefix==NULL || *prefix=='\0' ) {
|
|
rbase = rskiplen = 0; rsummit = rcur;
|
|
return( rcur==0?-1:0 );
|
|
}
|
|
if ( rcur==0 )
|
|
return( -1 );
|
|
|
|
plen = strlen(prefix);
|
|
|
|
forever {
|
|
test = (top+bottom)/2;
|
|
cmp = strncmp(prefix,_GResource_Res[test].res,plen);
|
|
if ( cmp==0 )
|
|
break;
|
|
if ( test==bottom )
|
|
return( -1 );
|
|
if ( cmp>0 ) {
|
|
bottom=test+1;
|
|
if ( bottom==top )
|
|
return( -1 );
|
|
} else
|
|
top = test;
|
|
}
|
|
/* at this point the resource at test begins with the prefix */
|
|
/* we want to find the first and last resources that do */
|
|
oldtop = top; oldtest = top = test; /* find the first resource */
|
|
forever {
|
|
test = (top+bottom)/2;
|
|
cmp = strncmp(prefix,_GResource_Res[test].res,plen);
|
|
if ( cmp<0 ) {
|
|
GDrawIError("Resource list out of order");
|
|
return( -1 );
|
|
}
|
|
if ( test==bottom ) {
|
|
if ( cmp!=0 ) ++test;
|
|
break;
|
|
}
|
|
if ( cmp>0 ) {
|
|
bottom=++test;
|
|
if ( bottom==top )
|
|
break;
|
|
} else
|
|
top = test;
|
|
}
|
|
rbase = test;
|
|
|
|
top = oldtop; bottom = oldtest+1; /* find the last resource */
|
|
if ( bottom == top )
|
|
test = top;
|
|
else forever {
|
|
test = (top+bottom)/2;
|
|
cmp = strncmp(prefix,_GResource_Res[test].res,plen);
|
|
if ( cmp>0 ) {
|
|
GDrawIError("Resource list out of order");
|
|
return( -1 );
|
|
}
|
|
if ( test==bottom ) {
|
|
if ( cmp==0 ) ++test;
|
|
break;
|
|
}
|
|
if ( cmp==0 ) {
|
|
bottom=++test;
|
|
if ( bottom==top )
|
|
break;
|
|
} else
|
|
top = test;
|
|
}
|
|
rsummit = test;
|
|
rskiplen = plen;
|
|
return( 0 );
|
|
}
|
|
|
|
void GResourceSetProg(char *prog) {
|
|
char filename[1025], *pt;
|
|
extern char *_GFile_find_program_dir(char *prog);
|
|
|
|
if ( prog!=NULL ) {
|
|
if ( GResourceProgramName!=NULL && strcmp(prog,GResourceProgramName)==0 )
|
|
return;
|
|
gfree(GResourceProgramName);
|
|
if (( pt=strrchr(prog,'/'))!=NULL )
|
|
++pt;
|
|
else
|
|
pt = prog;
|
|
GResourceProgramName = copy(pt);
|
|
} else if ( GResourceProgramName==NULL )
|
|
GResourceProgramName = copy("gdraw");
|
|
else
|
|
return;
|
|
|
|
gfree(GResourceProgramDir);
|
|
GResourceProgramDir = _GFile_find_program_dir(prog);
|
|
if ( GResourceProgramDir==NULL ) {
|
|
GFileGetAbsoluteName(".",filename,sizeof(filename));
|
|
GResourceProgramDir = copy(filename);
|
|
}
|
|
gfree(GResourceFullProgram);
|
|
GResourceFullProgram = copy(
|
|
GFileBuildName(GResourceProgramDir,GResourceProgramName,filename,sizeof(filename)));
|
|
}
|
|
|
|
void GResourceAddResourceString(char *string,char *prog) {
|
|
char *pt, *ept, *next;
|
|
int cnt, plen;
|
|
struct _GResource_Res temp;
|
|
int i,j,k, off;
|
|
|
|
GResourceSetProg(prog);
|
|
plen = strlen(GResourceProgramName);
|
|
|
|
if ( string==NULL )
|
|
return;
|
|
|
|
cnt = 0;
|
|
pt = string;
|
|
while ( *pt!='\0' ) {
|
|
next = strchr(pt,'\n');
|
|
if ( next==NULL ) next = pt+strlen(pt);
|
|
else ++next;
|
|
if ( strncmp(pt,"Gdraw.",6)==0 ) ++cnt;
|
|
else if ( strncmp(pt,GResourceProgramName,plen)==0 && pt[plen]=='.' ) ++cnt;
|
|
else if ( strncmp(pt,"*",1)==0 ) ++cnt;
|
|
pt = next;
|
|
}
|
|
if ( cnt==0 )
|
|
return;
|
|
|
|
if ( rcur+cnt>=rmax ) {
|
|
if ( cnt<10 ) cnt = 10;
|
|
if ( rmax==0 )
|
|
_GResource_Res = galloc(cnt*sizeof(struct _GResource_Res));
|
|
else
|
|
_GResource_Res = grealloc(_GResource_Res,(rcur+cnt)*sizeof(struct _GResource_Res));
|
|
rmax += cnt;
|
|
}
|
|
|
|
pt = string;
|
|
while ( *pt!='\0' ) {
|
|
next = strchr(pt,'\n');
|
|
if ( next==NULL ) next = pt+strlen(pt);
|
|
if ( strncmp(pt,"Gdraw.",6)==0 || strncmp(pt,"*",1)==0 ||
|
|
(strncmp(pt,GResourceProgramName,plen)==0 && pt[plen]=='.' )) {
|
|
temp.generic = false;
|
|
if ( strncmp(pt,"Gdraw.",6)==0 ) {
|
|
temp.generic = true;
|
|
off = 6;
|
|
} else if ( strncmp(pt,"*",1)==0 ) {
|
|
temp.generic = true;
|
|
off = 1;
|
|
} else
|
|
off = plen+1;
|
|
ept = strchr(pt+off,':');
|
|
if ( ept==NULL )
|
|
goto bad;
|
|
temp.res = copyn(pt+off,ept-(pt+off));
|
|
pt = ept+1;
|
|
while ( isspace( *pt ) && pt<next ) ++pt;
|
|
temp.val = copyn(pt,next-pt);
|
|
temp.new = true;
|
|
_GResource_Res[rcur++] = temp;
|
|
}
|
|
bad:
|
|
if ( *next ) ++next;
|
|
pt = next;
|
|
}
|
|
|
|
if ( rcur!=0 )
|
|
qsort(_GResource_Res,rcur,sizeof(struct _GResource_Res),rcompar);
|
|
|
|
for ( i=j=0; i<rcur; ) {
|
|
if ( i!=j )
|
|
_GResource_Res[j] = _GResource_Res[i];
|
|
for ( k=i+1; k<rcur && strcmp(_GResource_Res[j].res,_GResource_Res[k].res)==0; ++k ) {
|
|
if (( !_GResource_Res[k].generic && (_GResource_Res[i].generic || _GResource_Res[i+1].new)) ||
|
|
(_GResource_Res[k].generic && _GResource_Res[i].generic && _GResource_Res[i+1].new)) {
|
|
gfree(_GResource_Res[j].res); gfree(_GResource_Res[j].val);
|
|
_GResource_Res[i].res=NULL;
|
|
_GResource_Res[j] = _GResource_Res[k];
|
|
} else {
|
|
gfree(_GResource_Res[k].res); gfree(_GResource_Res[k].val);
|
|
_GResource_Res[k].res=NULL;
|
|
}
|
|
}
|
|
i = k; ++j;
|
|
}
|
|
rcur = rsummit = j;
|
|
for ( i=0; i<j; ++i )
|
|
_GResource_Res[i].new = false;
|
|
|
|
if ( (i=_GResource_FindResName("LocalCharSet"))!=-1 ) {
|
|
local_encoding = _GDraw_ParseMapping(c_to_u(_GResource_Res[i].val));
|
|
if ( local_encoding==em_none )
|
|
local_encoding = em_iso8859_1;
|
|
local_encoding += e_iso8859_1-em_iso8859_1;
|
|
}
|
|
}
|
|
|
|
void GResourceAddResourceFile(char *filename,char *prog) {
|
|
FILE *file;
|
|
char buffer[1000];
|
|
|
|
file = fopen(filename,"r");
|
|
if ( file==NULL ) {
|
|
fprintf( stderr, "Failed to open resource file: %s\n", filename );
|
|
return;
|
|
}
|
|
while ( fgets(buffer,sizeof(buffer),file)!=NULL )
|
|
GResourceAddResourceString(buffer,prog);
|
|
fclose(file);
|
|
}
|
|
|
|
void GResourceFind( GResStruct *info,char *prefix) {
|
|
int pos;
|
|
|
|
if ( GResourceRestrict(prefix)== -1 ) {
|
|
rbase = rskiplen = 0; rsummit = rcur;
|
|
return;
|
|
}
|
|
while ( info->resname!=NULL ) {
|
|
pos = _GResource_FindResName(info->resname);
|
|
info->found = (pos!=-1);
|
|
if ( pos==-1 )
|
|
/* Do Nothing */;
|
|
else if ( info->type == rt_string ) {
|
|
if ( info->cvt!=NULL )
|
|
*(void **) (info->val) = (info->cvt)( _GResource_Res[pos].val, *(void **) (info->val) );
|
|
else
|
|
*(char **) (info->val) = copy( _GResource_Res[pos].val );
|
|
} else if ( info->type == rt_color ) {
|
|
Color temp = _GImage_ColourFName(_GResource_Res[pos].val );
|
|
if ( temp==-1 ) {
|
|
fprintf( stderr, "Can't convert %s to a Color for resource: %s\n",
|
|
_GResource_Res[pos].val, info->resname );
|
|
info->found = false;
|
|
} else
|
|
*(Color *) (info->val) = temp;
|
|
} else if ( info->type == rt_int ) {
|
|
char *end;
|
|
int val = strtol(_GResource_Res[pos].val,&end,0);
|
|
if ( *end!='\0' ) {
|
|
fprintf( stderr, "Can't convert %s to an int for resource: %s\n",
|
|
_GResource_Res[pos].val, info->resname );
|
|
info->found = false;
|
|
} else
|
|
*(int *) (info->val) = val;
|
|
} else if ( info->type == rt_bool ) {
|
|
int val = -1;
|
|
if ( strmatch(_GResource_Res[pos].val,"true")==0 ||
|
|
strmatch(_GResource_Res[pos].val,"on")==0 || strcmp(_GResource_Res[pos].val,"1")==0 )
|
|
val = 1;
|
|
else if ( strmatch(_GResource_Res[pos].val,"false")==0 ||
|
|
strmatch(_GResource_Res[pos].val,"off")==0 || strcmp(_GResource_Res[pos].val,"0")==0 )
|
|
val = 0;
|
|
if ( val==-1 ) {
|
|
fprintf( stderr, "Can't convert %s to a boolean for resource: %s\n",
|
|
_GResource_Res[pos].val, info->resname );
|
|
info->found = false;
|
|
} else
|
|
*(int *) (info->val) = val;
|
|
} else if ( info->type == rt_double ) {
|
|
char *end;
|
|
double val = strtod(_GResource_Res[pos].val,&end);
|
|
if ( *end=='.' || *end==',' ) {
|
|
*end = (*end==',')?'.':',';
|
|
val = strtod(_GResource_Res[pos].val,&end);
|
|
}
|
|
if ( *end!='\0' ) {
|
|
fprintf( stderr, "Can't convert %s to a double for resource: %s\n",
|
|
_GResource_Res[pos].val, info->resname );
|
|
info->found = false;
|
|
} else
|
|
*(double *) (info->val) = val;
|
|
} else {
|
|
fprintf( stderr, "Invalid resource type for: %s\n", info->resname );
|
|
info->found = false;
|
|
}
|
|
++info;
|
|
}
|
|
rbase = rskiplen = 0; rsummit = rcur;
|
|
}
|
|
|
|
char *GResourceFindString(char *name) {
|
|
int pos;
|
|
|
|
pos = _GResource_FindResName(name);
|
|
if ( pos==-1 )
|
|
return( NULL );
|
|
else
|
|
return( copy(_GResource_Res[pos].val));
|
|
}
|
|
|
|
int GResourceFindBool(char *name, int def) {
|
|
int pos;
|
|
int val = -1;
|
|
|
|
pos = _GResource_FindResName(name);
|
|
if ( pos==-1 )
|
|
return( def );
|
|
|
|
if ( strmatch(_GResource_Res[pos].val,"true")==0 ||
|
|
strmatch(_GResource_Res[pos].val,"on")==0 || strcmp(_GResource_Res[pos].val,"1")==0 )
|
|
val = 1;
|
|
else if ( strmatch(_GResource_Res[pos].val,"false")==0 ||
|
|
strmatch(_GResource_Res[pos].val,"off")==0 || strcmp(_GResource_Res[pos].val,"0")==0 )
|
|
val = 0;
|
|
|
|
if ( val==-1 )
|
|
return( def );
|
|
|
|
return( val );
|
|
}
|
|
|
|
long GResourceFindInt(char *name, long def) {
|
|
int pos;
|
|
char *end;
|
|
long ret;
|
|
|
|
pos = _GResource_FindResName(name);
|
|
if ( pos==-1 )
|
|
return( def );
|
|
|
|
ret = strtol(_GResource_Res[pos].val,&end,10);
|
|
if ( *end!='\0' )
|
|
return( def );
|
|
|
|
return( ret );
|
|
}
|
|
|
|
Color GResourceFindColor(char *name, Color def) {
|
|
int pos;
|
|
Color ret;
|
|
|
|
pos = _GResource_FindResName(name);
|
|
if ( pos==-1 )
|
|
return( def );
|
|
|
|
ret = _GImage_ColourFName(_GResource_Res[pos].val );
|
|
if ( ret==-1 )
|
|
return( def );
|
|
|
|
return( ret );
|
|
}
|