Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

10604 lines (9655 sloc) 330.64 kB
/* Copyright (C) 2002-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.
*/
/* Yet another interpreter */
#include "fontforge.h"
#include <gfile.h>
#include <utype.h>
#include <ustring.h>
#include <ffglib.h>
#include <chardata.h>
#include <unistd.h>
#include <math.h>
#include <setjmp.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include <locale.h>
#ifdef HAVE_IEEEFP_H
# include <ieeefp.h> /* Solaris defines isnan in ieeefp rather than math.h */
#endif
#ifndef _NO_LIBREADLINE
# include <readline/readline.h>
# include <readline/history.h>
#endif
#include "ttf.h"
#include "plugins.h"
#include "scripting.h"
#include "scriptfuncs.h"
#include "flaglist.h"
#include "gutils/prefs.h"
#include "gutils/unicodelibinfo.h"
#include "xvasprintf.h"
int no_windowing_ui = false;
int running_script = false;
int use_utf8_in_script = true;
extern int prefRevisionsToRetain; /* sfd.c */
#ifndef _NO_FFSCRIPT
static int verbose = -1;
static struct dictionary globals;
struct keywords { enum token_type tok; const char *name; } keywords[] = {
{ tt_if, "if" },
{ tt_else, "else" },
{ tt_elseif, "elseif" },
{ tt_endif, "endif" },
{ tt_while, "while" },
{ tt_foreach, "foreach" },
{ tt_endloop, "endloop" },
{ tt_shift, "shift" },
{ tt_return, "return" },
{ tt_break, "break" },
{ 0, NULL }
};
static const char *toknames[] = {
"name", "string", "number", "unicode id", "real number",
"lparen", "rparen", "comma", "end of ff_statement",
"lbracket", "rbracket",
"minus", "plus", "logical not", "bitwise not", "colon",
"multiply", "divide", "mod", "logical and", "logical or", "bitwise and", "bitwise or", "bitwise xor",
"equal to", "not equal to", "greater than", "less than", "greater than or equal to", "less than or equal to",
"assignment", "plus equals", "minus equals", "mul equals", "div equals", "mod equals",
"increment", "decrement",
"if", "else", "elseif", "endif", "while", "foreach", "endloop",
"shift", "return",
"End Of File",
NULL };
char *utf82script_copy(const char *ustr) {
return( use_utf8_in_script ? copy(ustr) : utf8_2_latin1_copy(ustr));
}
char *script2utf8_copy(const char *str) {
return( use_utf8_in_script ? copy(str) : latin1_2_utf8_copy(str));
}
static char *script2latin1_copy(const char *str) {
if ( !use_utf8_in_script )
return( copy(str));
else {
unichar_t *t = utf82u_copy(str);
char *ret = cu_copy(t);
free(t);
return( ret );
}
}
#endif /* _NO_FFSCRIPT */
void arrayfree(Array *a) {
int i;
for ( i=0; i<a->argc; ++i ) {
if ( a->vals[i].type==v_str )
free(a->vals[i].u.sval);
else if ( a->vals[i].type==v_arr )
arrayfree(a->vals[i].u.aval);
}
free(a->vals);
free(a);
}
static Array *arraycopy(Array *a) {
int i;
Array *c;
c = malloc(sizeof(Array));
c->argc = a->argc;
c->vals = malloc(c->argc*sizeof(Val));
memcpy(c->vals,a->vals,c->argc*sizeof(Val));
for ( i=0; i<a->argc; ++i ) {
if ( a->vals[i].type==v_str )
c->vals[i].u.sval = copy(a->vals[i].u.sval);
else if ( a->vals[i].type==v_arr )
c->vals[i].u.aval = arraycopy(a->vals[i].u.aval);
}
return( c );
}
#ifndef _NO_FFSCRIPT
static void array_copy_into(Array *dest,int offset,Array *src) {
int i;
memcpy(dest->vals+offset,src->vals,src->argc*sizeof(Val));
for ( i=0; i<src->argc; ++i ) {
if ( src->vals[i].type==v_str )
dest->vals[i+offset].u.sval = copy(src->vals[i].u.sval);
else if ( src->vals[i].type==v_arr )
dest->vals[i+offset].u.aval = arraycopy(src->vals[i].u.aval);
}
}
void DictionaryFree(struct dictionary *dica) {
int i;
if ( dica==NULL )
return;
for ( i=0; i<dica->cnt; ++i ) {
free(dica->entries[i].name );
if ( dica->entries[i].val.type == v_str )
free( dica->entries[i].val.u.sval );
if ( dica->entries[i].val.type == v_arr )
arrayfree( dica->entries[i].val.u.aval );
}
free( dica->entries );
dica->entries = NULL;
}
static int DicaLookup(struct dictionary *dica,char *name,Val *val) {
int i;
if ( dica!=NULL && dica->entries!=NULL ) {
for ( i=0; i<dica->cnt; ++i )
if ( strcmp(dica->entries[i].name,name)==0 ) {
val->type = v_lval;
val->u.lval = &dica->entries[i].val;
return( true );
}
}
return( false );
}
static void DicaNewEntry(struct dictionary *dica,char *name,Val *val) {
if ( dica->entries==NULL ) {
dica->max = 10;
dica->entries = malloc(dica->max*sizeof(struct dictentry));
} else if ( dica->cnt>=dica->max ) {
dica->max += 10;
dica->entries = realloc(dica->entries,dica->max*sizeof(struct dictentry));
}
dica->entries[dica->cnt].name = copy(name);
dica->entries[dica->cnt].val.type = v_void;
val->type = v_lval;
val->u.lval = &dica->entries[dica->cnt].val;
++dica->cnt;
}
static void calldatafree(Context *c) {
int i;
/* child may have freed some args itself by shifting,
but argc will reflect the proper values none the less */
for ( i=1; i<c->a.argc; ++i ) {
if ( c->a.vals[i].type == v_str ) {
free( c->a.vals[i].u.sval );
c->a.vals[i].u.sval = NULL;
}
if ( c->a.vals[i].type == v_arrfree || (c->a.vals[i].type == v_arr && c->dontfree[i]!=c->a.vals[i].u.aval )) {
arrayfree( c->a.vals[i].u.aval );
c->a.vals[i].u.aval = NULL;
}
c->a.vals[i].type = v_void;
}
DictionaryFree(&c->locals);
if ( c->script!=NULL ) {
fclose(c->script);
c->script = NULL;
}
}
/* coverity[+kill] */
static void traceback(Context *c) {
int cnt = 0;
while ( c!=NULL ) {
if (c->interactive) {
if ( c->err_env!=NULL ) {
longjmp(*c->err_env,1);
}
c->error = true;
return;
}
if ( cnt==1 ) LogError( _("Called from...\n") );
if ( cnt>0 ) LogError( _(" %s: line %d\n"), c->filename, c->lineno );
calldatafree(c);
if ( c->err_env!=NULL )
longjmp(*c->err_env,1);
c = c->caller;
++cnt;
}
exit(1);
}
static void showtoken(Context *c,enum token_type got) {
if ( got==tt_name || got==tt_string )
LogError( " \"%s\"\n", c->tok_text );
else if ( got==tt_number )
LogError( " %d (0x%x)\n", c->tok_val.u.ival, c->tok_val.u.ival );
else if ( got==tt_unicode )
LogError( " 0u%x\n", c->tok_val.u.ival );
else if ( got==tt_real )
LogError( " %g\n", c->tok_val.u.fval );
else
LogError( "\n" );
traceback(c);
}
static void expect(Context *c,enum token_type expected, enum token_type got) {
if ( got!=expected ) {
if ( verbose>0 )
fflush(stdout);
if (c->interactive)
LogError( _("Error: Expected %s, got %s"),
toknames[expected], toknames[got] );
else
LogError( _("%s: %d Expected %s, got %s"),
c->filename, c->lineno, toknames[expected], toknames[got] );
if ( !no_windowing_ui ) {
ff_post_error(NULL,_("%1$s: %2$d. Expected %3$s got %4$s"),
c->filename, c->lineno, toknames[expected], toknames[got] );
}
showtoken(c,got);
}
}
static void unexpected(Context *c,enum token_type got) {
if ( verbose>0 )
fflush(stdout);
if (c->interactive)
LogError( _("Error: Unexpected %s found"), toknames[got] );
else
LogError( _("%s: %d Unexpected %s found"),
c->filename, c->lineno, toknames[got] );
if ( !no_windowing_ui ) {
ff_post_error(NULL,"%1$s: %2$d Unexpected %3$",
c->filename, c->lineno, toknames[got] );
}
showtoken(c,got);
}
void ScriptError( Context *c, const char *msg ) {
char *t1 = script2utf8_copy(msg);
char *ufile = def2utf8_copy(c->filename);
/* All of fontforge's internal errors are in ASCII where there is */
/* no difference between latin1 and utf8. User errors are a different */
/* matter */
if ( verbose>0 )
fflush(stdout);
if ( c->interactive )
LogError( "Error: %s\n", t1 );
else if ( c->lineno!=0 )
LogError( _("%s line: %d %s\n"), ufile, c->lineno, t1 );
else
LogError( "%s: %s\n", ufile, t1 );
if ( !no_windowing_ui ) {
ff_post_error(NULL,"%s: %d %s",ufile, c->lineno, t1 );
}
free(ufile); free(t1);
traceback(c);
}
void ScriptErrorString( Context *c, const char *msg, const char *name) {
char *t1 = script2utf8_copy(msg);
char *t2 = script2utf8_copy(name);
char *ufile = def2utf8_copy(c->filename);
if ( verbose>0 )
fflush(stdout);
if ( c->interactive )
LogError( "Error: %s: %s\n", t1, t2 );
else if ( c->lineno!=0 )
LogError( _("%s line: %d %s: %s\n"), ufile, c->lineno, t1, t2 );
else
LogError( "%s: %s: %s\n", ufile, t1, t2 );
if ( !no_windowing_ui ) {
ff_post_error(NULL,"%s: %d %s: %s",ufile, c->lineno, t1, t2 );
}
free(ufile); free(t1); free(t2);
traceback(c);
}
void ScriptErrorF( Context *c, const char *format, ... ) {
char *ufile = def2utf8_copy(c->filename);
/* All string arguments here assumed to be utf8 */
char errbuf[400];
va_list ap;
va_start(ap,format);
vsnprintf(errbuf,sizeof(errbuf),format,ap);
va_end(ap);
if ( verbose>0 )
fflush(stdout);
if (c->interactive)
LogError( _("Error: %s\n"), errbuf );
else if ( c->lineno!=0 )
LogError( _("%s line: %d %s\n"), ufile, c->lineno, errbuf );
else
LogError( "%s: %s\n", ufile, errbuf );
if ( !no_windowing_ui ) {
ff_post_error(NULL,"%s: %d %s",ufile, c->lineno, errbuf );
}
free(ufile);
traceback(c);
}
static char *forcePSName_copy(Context *c,char *str) {
char *pt;
for ( pt=str; *pt; ++pt ) {
if ( *pt<=' ' || *pt>=0x7f ||
*pt=='(' || *pt==')' ||
*pt=='[' || *pt==']' ||
*pt=='{' || *pt=='}' ||
*pt=='<' || *pt=='>' ||
*pt=='%' || *pt=='/' )
ScriptErrorString(c,"Invalid character in PostScript name token (probably fontname): ", str );
}
return( copy( str ));
}
static char *forceASCIIcopy(Context *c,char *str) {
char *pt;
for ( pt=str; *pt; ++pt ) {
if ( *pt<' ' || *pt>=0x7f )
ScriptErrorString(c,"Invalid ASCII character in: ", str );
}
return( copy( str ));
}
static void dereflvalif(Val *val) {
if ( val->type == v_lval ) {
*val = *val->u.lval;
if ( val->type==v_str )
val->u.sval = copy(val->u.sval);
}
}
/* *************************** Built in Functions *************************** */
static void PrintVal(Val *val) {
int j;
if ( val->type==v_str ) {
char *t1 = script2utf8_copy(val->u.sval);
char *loc = utf82def_copy(t1);
printf( "%s", loc );
free(loc); free(t1);
} else if ( val->type==v_arr || val->type==v_arrfree ) {
putchar( '[' );
if ( val->u.aval->argc>0 ) {
PrintVal(&val->u.aval->vals[0]);
for ( j=1; j<val->u.aval->argc; ++j ) {
putchar(',');
if ( val->u.aval->vals[j-1].type==v_arr || val->u.aval->vals[j-1].type==v_arrfree )
putchar('\n');
PrintVal(&val->u.aval->vals[j]);
}
}
putchar( ']' );
} else if ( val->type==v_int )
printf( "%d", val->u.ival );
else if ( val->type==v_unicode )
printf( "0u%04X", val->u.ival );
else if ( val->type==v_real )
printf( "%g", (double) val->u.fval );
else if ( val->type==v_void )
printf( "<void>");
else
printf( "<" "???" ">");
}
static void bPrint(Context *c) {
int i;
for ( i=1; i<c->a.argc; ++i )
PrintVal(&c->a.vals[i] );
printf( "\n" );
fflush(stdout);
}
static void bError(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str )
ScriptError( c, "Expected string argument" );
ScriptError( c, c->a.vals[1].u.sval );
}
static void bPostNotice(Context *c) {
char *t1;
char *loc;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str )
ScriptError( c, "Expected string argument" );
loc = c->a.vals[1].u.sval;
if ( !no_windowing_ui ) {
if ( !use_utf8_in_script ) {
unichar_t *t1 = uc_copy(loc);
loc = u2utf8_copy(t1);
free(t1);
}
ff_post_notice(_("Attention"), "%.200s", loc );
if ( loc != c->a.vals[1].u.sval )
free(loc);
} else
{
t1 = script2utf8_copy(loc);
loc = utf82def_copy(t1);
fprintf(stderr,"%s\n", loc );
free(loc); free(t1);
}
}
static void bAskUser(Context *c) {
char *quest;
const char *def="";
if ( c->a.argc!=2 && c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str || ( c->a.argc==3 && c->a.vals[2].type!=v_str) )
ScriptError( c, "Expected string argument" );
quest = c->a.vals[1].u.sval;
if ( c->a.argc==3 )
def = c->a.vals[2].u.sval;
if ( no_windowing_ui ) {
char buffer[300];
char *t1 = script2utf8_copy(quest);
char *loc = utf82def_copy(t1);
printf( "%s", loc );
free(t1); free(loc);
buffer[0] = '\0';
c->return_val.type = v_str;
if ( fgets(buffer,sizeof(buffer),stdin)==NULL ) {
clearerr(stdin);
c->return_val.u.sval = copy("");
} else if ( buffer[0]=='\0' || buffer[0]=='\n' || buffer[0]=='\r' )
c->return_val.u.sval = copy(def);
else {
t1 = def2utf8_copy(buffer);
c->return_val.u.sval = utf82script_copy(t1);
free(t1);
}
} else {
char *t1, *t2, *ret;
if ( use_utf8_in_script ) {
ret = ff_ask_string(quest,def,"%s", quest);
} else {
t1 = latin1_2_utf8_copy(quest);
ret = ff_ask_string(t1,t2=latin1_2_utf8_copy(def),"%s", t1);
free(t1); free(t2);
}
c->return_val.type = v_str;
c->return_val.u.sval = utf82script_copy(ret);
if ( ret==NULL )
c->return_val.u.sval = copy("");
else
free(ret);
}
}
static void bArray(Context *c) {
int i;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_int )
ScriptError( c, "Expected integer argument" );
else if ( c->a.vals[1].u.ival<=0 )
ScriptError( c, "Argument must be positive" );
c->return_val.type = v_arrfree;
c->return_val.u.aval = malloc(sizeof(Array));
c->return_val.u.aval->argc = c->a.vals[1].u.ival;
c->return_val.u.aval->vals = malloc(c->a.vals[1].u.ival*sizeof(Val));
for ( i=0; i<c->a.vals[1].u.ival; ++i )
c->return_val.u.aval->vals[i].type = v_void;
}
static void bSizeOf(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
if ( c->a.vals[1].type!=v_arr && c->a.vals[1].type!=v_arrfree )
ScriptError( c, "Expected array argument" );
c->return_val.type = v_int;
c->return_val.u.ival = c->a.vals[1].u.aval->argc;
}
static void bTypeOf(Context *c) {
static const char *typenames[] = { "Integer", "Real", "String", "Unicode", "LValue",
"Array", "Array", "LValue", "LValue", "LValue", "Void" };
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
c->return_val.type = v_str;
c->return_val.u.sval = copy( typenames[c->a.vals[1].type] );
}
static void bStrlen(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str )
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_int;
c->return_val.u.ival = strlen( c->a.vals[1].u.sval );
}
static void bStrstr(Context *c) {
char *pt;
if ( c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str || c->a.vals[2].type!=v_str )
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_int;
pt = strstr(c->a.vals[1].u.sval,c->a.vals[2].u.sval);
c->return_val.u.ival = pt==NULL ? -1 : pt-c->a.vals[1].u.sval;
}
static void bStrSplit(Context *c) {
char *pt, *pt2, *str1, *str2;
int max=-1, len2, cnt, k;
if ( c->a.argc!=3 && c->a.argc!=4 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str || c->a.vals[2].type!=v_str )
ScriptError( c, "Bad type for argument" );
else if ( c->a.argc==4 && c->a.vals[3].type!=v_int )
ScriptError( c, "Bad type for argument" );
else if ( c->a.argc==4 )
max = c->a.vals[3].u.ival;
str1 = c->a.vals[1].u.sval;
str2 = c->a.vals[2].u.sval;
len2 = strlen( str2 );
for ( k=0; k<2; ++k ) {
cnt = 0;
pt = str1;
while ( (pt2 = strstr(pt,str2))!=NULL ) {
if ( k ) {
if ( max!=-1 && cnt>=max )
break;
c->return_val.u.aval->vals[cnt].type = v_str;
c->return_val.u.aval->vals[cnt].u.sval = copyn(pt,pt2-pt);
}
++cnt;
pt = pt2+len2;
}
if ( !k ) {
if ( *pt!='\0' )
++cnt;
if ( max!=-1 && cnt>max )
cnt = max;
c->return_val.type = v_arrfree;
c->return_val.u.aval = malloc(sizeof(Array));
c->return_val.u.aval->argc = cnt;
c->return_val.u.aval->vals = malloc(cnt*sizeof(Val));
} else {
if ( *pt!='\0' && cnt < max ) {
c->return_val.u.aval->vals[cnt].type = v_str;
c->return_val.u.aval->vals[cnt].u.sval = copy(pt);
}
}
}
}
static void bStrJoin(Context *c) {
char *str2;
int len, len2, k, i;
Array *arr;
if ( c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments" );
else if ( (c->a.vals[1].type!=v_arr && c->a.vals[1].type!=v_arrfree) ||
c->a.vals[2].type!=v_str )
ScriptError( c, "Bad type for argument" );
arr = c->a.vals[1].u.aval;
str2 = c->a.vals[2].u.sval;
len2 = strlen( str2 );
for ( k=0; k<2; ++k ) {
len = 0;
for ( i=0; i<arr->argc; ++i ) {
if ( arr->vals[i].type!=v_str )
ScriptError( c, "Bad type for array element" );
if ( k ) {
strcpy(c->return_val.u.sval+len,arr->vals[i].u.sval);
strcat(c->return_val.u.sval+len,str2);
}
len += strlen(arr->vals[i].u.sval) + len2;
}
if ( !k ) {
c->return_val.type = v_str;
c->return_val.u.sval = malloc(len+1);
}
}
}
static void bStrcasestr(Context *c) {
char *pt;
if ( c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str || c->a.vals[2].type!=v_str )
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_int;
pt = strstrmatch(c->a.vals[1].u.sval,c->a.vals[2].u.sval);
c->return_val.u.ival = pt==NULL ? -1 : pt-c->a.vals[1].u.sval;
}
static void bStrrstr(Context *c) {
char *pt;
char *haystack, *needle;
int nlen;
if ( c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str || c->a.vals[2].type!=v_str )
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_int;
haystack = c->a.vals[1].u.sval; needle = c->a.vals[2].u.sval;
nlen = strlen( needle );
for ( pt=haystack+strlen(haystack)-nlen; pt>=haystack; --pt )
if ( strncmp(pt,needle,nlen)==0 )
break;
c->return_val.u.ival = pt-haystack;
}
static void bStrsub(Context *c) {
int start, end;
char *str;
if ( c->a.argc!=3 && c->a.argc!=4 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str || c->a.vals[2].type!=v_int ||
(c->a.argc==4 && c->a.vals[3].type!=v_int))
ScriptError( c, "Bad type for argument" );
str = c->a.vals[1].u.sval;
start = c->a.vals[2].u.ival;
end = c->a.argc==4? c->a.vals[3].u.ival : (int)strlen(str);
if ( start<0 || start>(int)strlen(str) || end<start || end>(int)strlen(str) )
ScriptError( c, "Arguments out of bounds" );
c->return_val.type = v_str;
c->return_val.u.sval = copyn(str+start,end-start);
}
static void bStrcasecmp(Context *c) {
if ( c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str || c->a.vals[2].type!=v_str )
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_int;
c->return_val.u.ival = strmatch(c->a.vals[1].u.sval,c->a.vals[2].u.sval);
}
static void bStrtol(Context *c) {
int base = 10;
if ( c->a.argc!=2 && c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str || (c->a.argc==3 && c->a.vals[2].type!=v_int) )
ScriptError( c, "Bad type for argument" );
else if ( c->a.argc==3 ) {
base = c->a.vals[2].u.ival;
if ( base<0 || base==1 || base>36 )
ScriptError( c, "Argument out of bounds" );
}
c->return_val.type = v_int;
c->return_val.u.ival = strtol(c->a.vals[1].u.sval,NULL,base);
}
static void bStrtod(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str )
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_real;
c->return_val.u.fval = (float)strtod(c->a.vals[1].u.sval,NULL);
}
static void bStrskipint(Context *c) {
int base = 10;
char *end;
if ( c->a.argc!=2 && c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str || (c->a.argc==3 && c->a.vals[2].type!=v_int) )
ScriptError( c, "Bad type for argument" );
else if ( c->a.argc==3 ) {
base = c->a.vals[2].u.ival;
if ( base<0 || base==1 || base>36 )
ScriptError( c, "Argument out of bounds" );
}
c->return_val.type = v_int;
strtol(c->a.vals[1].u.sval,&end,base);
c->return_val.u.ival = end-c->a.vals[1].u.sval;
}
static void bStrftime(Context *c) {
int isgmt=1;
char *oldloc = NULL;
char buffer[300];
struct tm *tm;
time_t now;
if ( c->a.argc!=2 && c->a.argc!=3 && c->a.argc!=4 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str ||
(c->a.argc>=3 && c->a.vals[2].type!=v_int) ||
(c->a.argc>=4 && c->a.vals[3].type!=v_str) )
ScriptError( c, "Bad type for argument" );
if ( c->a.argc>=3 )
isgmt = c->a.vals[2].u.ival;
if ( c->a.argc>=4 )
oldloc = setlocale(LC_TIME, c->a.vals[3].u.sval); // TODO
time(&now);
if ( isgmt )
tm = gmtime(&now);
else
tm = localtime(&now);
strftime(buffer,sizeof(buffer),c->a.vals[1].u.sval,tm);
if ( oldloc!=NULL )
(void) setlocale(LC_TIME, oldloc);
c->return_val.type = v_str;
c->return_val.u.sval = copy(buffer);
}
static void bisupper(Context *c) {
const char *pt;
long ch;
c->return_val.type = v_int;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_str ) {
pt = c->a.vals[1].u.sval;
ch = utf8_ildb(&pt);
c->return_val.u.ival = ch>=0 && ch<0x10000?isupper(ch):0;
} else if ( c->a.vals[1].type==v_int || c->a.vals[1].type==v_unicode )
c->return_val.u.ival = isupper(c->a.vals[1].u.ival);
else
ScriptError( c, "Bad type for argument" );
}
static void bislower(Context *c) {
const char *pt;
long ch;
c->return_val.type = v_int;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_str ) {
pt = c->a.vals[1].u.sval;
ch = utf8_ildb(&pt);
c->return_val.u.ival = ch>=0 && ch<0x10000?islower(ch):0;
} else if ( c->a.vals[1].type==v_int || c->a.vals[1].type==v_unicode )
c->return_val.u.ival = islower(c->a.vals[1].u.ival);
else
ScriptError( c, "Bad type for argument" );
}
static void bisdigit(Context *c) {
const char *pt;
long ch;
c->return_val.type = v_int;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_str ) {
pt = c->a.vals[1].u.sval;
ch = utf8_ildb(&pt);
c->return_val.u.ival = ch>=0 && ch<0x10000?isdigit(ch):0;
} else if ( c->a.vals[1].type==v_int || c->a.vals[1].type==v_unicode )
c->return_val.u.ival = isdigit(c->a.vals[1].u.ival);
else
ScriptError( c, "Bad type for argument" );
}
static void bishexdigit(Context *c) {
const char *pt;
long ch;
c->return_val.type = v_int;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_str ) {
pt = c->a.vals[1].u.sval;
ch = utf8_ildb(&pt);
c->return_val.u.ival = ch>=0 && ch<0x10000?ishexdigit(ch):0;
} else if ( c->a.vals[1].type==v_int || c->a.vals[1].type==v_unicode )
c->return_val.u.ival = ishexdigit(c->a.vals[1].u.ival);
else
ScriptError( c, "Bad type for argument" );
}
static void bisalpha(Context *c) {
const char *pt;
long ch;
c->return_val.type = v_int;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_str ) {
pt = c->a.vals[1].u.sval;
ch = utf8_ildb(&pt);
c->return_val.u.ival = ch>=0 && ch<0x10000?isalpha(ch):0;
} else if ( c->a.vals[1].type==v_int || c->a.vals[1].type==v_unicode )
c->return_val.u.ival = isalpha(c->a.vals[1].u.ival);
else
ScriptError( c, "Bad type for argument" );
}
static void bisalnum(Context *c) {
const char *pt;
long ch;
c->return_val.type = v_int;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_str ) {
pt = c->a.vals[1].u.sval;
ch = utf8_ildb(&pt);
c->return_val.u.ival = ch>=0 && ch<0x10000?isalnum(ch):0;
} else if ( c->a.vals[1].type==v_int || c->a.vals[1].type==v_unicode )
c->return_val.u.ival = isalnum(c->a.vals[1].u.ival);
else
ScriptError( c, "Bad type for argument" );
}
static void bisspace(Context *c) {
const char *pt;
long ch;
c->return_val.type = v_int;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_str ) {
pt = c->a.vals[1].u.sval;
ch = utf8_ildb(&pt);
c->return_val.u.ival = ch>=0 && ch<0x10000?isspace(ch):0;
} else if ( c->a.vals[1].type==v_int || c->a.vals[1].type==v_unicode )
c->return_val.u.ival = isspace(c->a.vals[1].u.ival);
else
ScriptError( c, "Bad type for argument" );
}
static void btoupper(Context *c) {
char *pt; const char *ipt;
long ch;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_str ) {
c->return_val.type = v_str;
c->return_val.u.sval = pt = copy(ipt = c->a.vals[1].u.sval);
while ( *ipt ) {
ch = utf8_ildb(&ipt);
if ( ch==-1 )
break;
if ( ch<0x10000 ) ch = toupper(ch);
pt = utf8_idpb(pt,ch,UTF8IDPB_NOZERO);
}
*pt = '\0';
} else if ( c->a.vals[1].type==v_int || c->a.vals[1].type==v_unicode ) {
c->return_val.type = v_int;
c->return_val.u.ival = c->a.vals[1].u.ival<0x10000?toupper(c->a.vals[1].u.ival): c->a.vals[1].u.ival;
} else
ScriptError( c, "Bad type for argument" );
}
static void btolower(Context *c) {
char *pt; const char *ipt;
long ch;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_str ) {
c->return_val.type = v_str;
c->return_val.u.sval = pt = copy(ipt = c->a.vals[1].u.sval);
while ( *ipt ) {
ch = utf8_ildb(&ipt);
if ( ch==-1 )
break;
if ( ch<0x10000 ) ch = tolower(ch);
pt = utf8_idpb(pt,ch,UTF8IDPB_NOZERO);
}
*pt = '\0';
} else if ( c->a.vals[1].type==v_int || c->a.vals[1].type==v_unicode ) {
c->return_val.type = v_int;
c->return_val.u.ival = c->a.vals[1].u.ival<0x10000?tolower(c->a.vals[1].u.ival): c->a.vals[1].u.ival;
} else
ScriptError( c, "Bad type for argument" );
}
static void btomirror(Context *c) {
char *pt; const char *ipt;
long ch;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_str ) {
c->return_val.type = v_str;
c->return_val.u.sval = pt = copy(ipt = c->a.vals[1].u.sval);
while ( *ipt ) {
ch = utf8_ildb(&ipt);
if ( ch==-1 )
break;
if ( ch<0x10000 ) ch = tomirror(ch);
pt = utf8_idpb(pt,ch,UTF8IDPB_NOZERO);
}
*pt = '\0';
} else if ( c->a.vals[1].type==v_int || c->a.vals[1].type==v_unicode ) {
c->return_val.type = v_int;
c->return_val.u.ival = c->a.vals[1].u.ival<0x10000?tomirror(c->a.vals[1].u.ival): c->a.vals[1].u.ival;
} else
ScriptError( c, "Bad type for argument" );
}
static void bLoadPrefs(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments" );
LoadPrefs();
}
static void bSavePrefs(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments" );
SavePrefs(false);
DumpPfaEditEncodings();
}
static void bGetPrefs(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str )
ScriptError( c, "Bad type for argument" );
if ( !GetPrefs(c->a.vals[1].u.sval,&c->return_val) )
ScriptErrorString( c, "Unknown Preference variable", c->a.vals[1].u.sval );
}
static void bSetPrefs(Context *c) {
int ret;
if ( c->a.argc!=3 && c->a.argc!=4 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str && (c->a.argc==4 && c->a.vals[3].type!=v_int) )
ScriptError( c, "Bad type for argument" );
if ( (ret=SetPrefs(c->a.vals[1].u.sval,&c->a.vals[2],c->a.argc==4?&c->a.vals[3]:NULL))==0 )
ScriptErrorString( c, "Unknown Preference variable", c->a.vals[1].u.sval );
else if ( ret==-1 )
ScriptErrorString( c, "Bad type for preference variable", c->a.vals[1].u.sval);
}
static void bDefaultOtherSubrs(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments" );
DefaultOtherSubrs();
}
static void bReadOtherSubrsFile(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str )
ScriptError( c, "Bad type for argument" );
if ( ReadOtherSubrsFile(c->a.vals[1].u.sval)<=0 )
ScriptErrorString( c,"Failed to read OtherSubrs from %s", c->a.vals[1].u.sval );
}
static void bGetEnv(Context *c) {
char *env;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str )
ScriptError( c, "Bad type for argument" );
if ( (env = getenv(c->a.vals[1].u.sval))==NULL )
ScriptErrorString( c, "Unknown Preference variable", c->a.vals[1].u.sval );
c->return_val.type = v_str;
c->return_val.u.sval = strdup(env);
}
static void bUnicodeFromName(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str )
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_int;
c->return_val.u.ival = UniFromName(c->a.vals[1].u.sval,ui_none,&custom);
}
static void bNameFromUnicode(Context *c) {
char buffer[400];
int uniinterp;
NameList *for_new_glyphs;
if ( c->a.argc!=2 && c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_int && c->a.vals[1].type!=v_unicode )
ScriptError( c, "Bad type for argument" );
else if ( c->a.argc==3 && c->a.vals[2].type!=v_str )
ScriptError( c, "Bad type for argument" );
if ( c->a.argc==3 ) {
uniinterp = ui_none;
for_new_glyphs = NameListByName(c->a.vals[2].u.sval);
if ( for_new_glyphs == NULL )
ScriptErrorString( c, "Could not find namelist", c->a.vals[2].u.sval);
} else if (c->curfv == NULL) {
uniinterp = ui_none;
for_new_glyphs = NameListByName("AGL with PUA");
} else {
uniinterp = c->curfv->sf->uni_interp;
for_new_glyphs = c->curfv->sf->for_new_glyphs;
}
c->return_val.type = v_str;
c->return_val.u.sval = copy(StdGlyphName(buffer,c->a.vals[1].u.ival,uniinterp,for_new_glyphs));
}
static void bUnicodeBlockCountFromLib(Context *c) {
/* If the library is available, then return the number of name blocks */
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments" );
c->return_val.type=v_int;
c->return_val.u.ival=unicode_block_count();
}
static void bUnicodeBlockEndFromLib(Context *c) {
/* If the library is available, then get the official Nth block end */
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_int && c->a.vals[1].type!=v_unicode )
ScriptError( c, "Bad type for argument" );
c->return_val.type=v_int;
c->return_val.u.ival=unicode_block_end(c->a.vals[1].u.ival);
}
static void bUnicodeBlockNameFromLib(Context *c) {
/* If the library is available, then get the official Nth block name */
char *temp;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_int && c->a.vals[1].type!=v_unicode )
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_str;
if ( (temp=unicode_block_name(c->a.vals[1].u.ival))==NULL ) {
temp=malloc(1*sizeof(char)); *temp='\0';
}
c->return_val.u.sval=temp;
}
static void bUnicodeBlockStartFromLib(Context *c) {
/* If the library is available, then get the official Nth block start */
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_int && c->a.vals[1].type!=v_unicode )
ScriptError( c, "Bad type for argument" );
c->return_val.type=v_int;
c->return_val.u.ival=unicode_block_start(c->a.vals[1].u.ival);
}
static void bUnicodeNameFromLib(Context *c) {
/* If the library is available, then get the official name for this unicode value */
char *temp;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_int && c->a.vals[1].type!=v_unicode )
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_str;
if ( (temp=unicode_name(c->a.vals[1].u.ival))==NULL ) {
temp=malloc(1*sizeof(char)); *temp='\0';
}
c->return_val.u.sval = temp;
}
static void bUnicodeAnnotationFromLib(Context *c) {
char *temp;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_int && c->a.vals[1].type!=v_unicode )
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_str;
if ( (temp=unicode_annot(c->a.vals[1].u.ival))==NULL ) {
temp=malloc(1*sizeof(char)); *temp='\0';
}
c->return_val.u.sval = temp;
}
static void bUnicodeNamesListVersion(Context *c) {
/* If the library is available, then return the Nameslist Version */
char *temp;
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments" );
if ( (temp=unicode_library_version())==NULL ) {
temp=malloc(1*sizeof(char)); *temp='\0';
}
c->return_val.type = v_str;
c->return_val.u.sval = temp;
}
static void bChr(Context *c) {
char buf[2];
char *temp;
int i;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_int ) {
if ( c->a.vals[1].u.ival<-128 || c->a.vals[1].u.ival>255 )
ScriptError( c, "Bad value for argument" );
buf[0] = c->a.vals[1].u.ival; buf[1] = 0;
c->return_val.type = v_str;
c->return_val.u.sval = copy(buf);
} else if ( c->a.vals[1].type==v_arr || c->a.vals[1].type==v_arrfree ) {
Array *arr = c->a.vals[1].u.aval;
temp = malloc((arr->argc+1)*sizeof(char));
for ( i=0; i<arr->argc; ++i ) {
if ( arr->vals[i].type!=v_int )
ScriptError( c, "Bad type for argument" );
else if ( c->a.vals[1].u.ival<-128 || c->a.vals[1].u.ival>255 )
ScriptError( c, "Bad value for argument" );
temp[i] = arr->vals[i].u.ival;
}
temp[i] = 0;
c->return_val.type = v_str;
c->return_val.u.sval = temp;
} else
ScriptError( c, "Bad type for argument" );
}
static void bUtf8(Context *c) {
uint32 buf[2];
int i;
uint32 *temp;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_int ) {
if ( c->a.vals[1].u.ival<0 || c->a.vals[1].u.ival>0x10ffff )
ScriptError( c, "Bad value for argument" );
buf[0] = c->a.vals[1].u.ival; buf[1] = 0;
c->return_val.type = v_str;
c->return_val.u.sval = u2utf8_copy(buf);
} else if ( c->a.vals[1].type==v_arr || c->a.vals[1].type==v_arrfree ) {
Array *arr = c->a.vals[1].u.aval;
temp = malloc((arr->argc+1)*sizeof(int32));
for ( i=0; i<arr->argc; ++i ) {
if ( arr->vals[i].type!=v_int )
ScriptError( c, "Bad type for argument" );
else if ( arr->vals[i].u.ival<0 || arr->vals[i].u.ival>0x10ffff )
ScriptError( c, "Bad value for argument" );
temp[i] = arr->vals[i].u.ival;
}
temp[i] = 0;
c->return_val.type = v_str;
c->return_val.u.sval = u2utf8_copy(temp);
free(temp);
} else
ScriptError( c, "Bad type for argument" );
}
static void bUCS4(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_str ) {
const char *pt = c->a.vals[1].u.sval;
int i, len = g_utf8_strlen( pt, -1 );
c->return_val.type = v_arrfree;
c->return_val.u.aval = malloc(sizeof(Array));
c->return_val.u.aval->argc = len;
c->return_val.u.aval->vals = malloc(len*sizeof(Val));
for ( i=0; i<len; ++i ) {
c->return_val.u.aval->vals[i].type = v_int;
c->return_val.u.aval->vals[i].u.ival = utf8_ildb(&pt);
}
} else
ScriptError( c, "Bad type for argument" );
}
static void bOrd(Context *c) {
if ( c->a.argc!=2 && c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str || ( c->a.argc==3 && c->a.vals[2].type!=v_int ))
ScriptError( c, "Bad type for argument" );
if ( c->a.argc==3 ) {
if ( c->a.vals[2].u.ival<0 || c->a.vals[2].u.ival>(int)strlen( c->a.vals[1].u.sval ))
ScriptError( c, "Bad value for argument" );
c->return_val.type = v_int;
c->return_val.u.ival = (uint8) c->a.vals[1].u.sval[c->a.vals[2].u.ival];
} else {
int i, len = strlen(c->a.vals[1].u.sval);
c->return_val.type = v_arrfree;
c->return_val.u.aval = malloc(sizeof(Array));
c->return_val.u.aval->argc = len;
c->return_val.u.aval->vals = malloc(len*sizeof(Val));
for ( i=0; i<len; ++i ) {
c->return_val.u.aval->vals[i].type = v_int;
c->return_val.u.aval->vals[i].u.ival = (uint8) c->a.vals[1].u.sval[i];
}
}
}
static void bReal(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_int && c->a.vals[1].type!=v_unicode )
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_real;
c->return_val.u.fval = (float) c->a.vals[1].u.ival;
}
static void bUCodePoint(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_real )
c->return_val.u.ival = c->a.vals[1].u.fval;
else if ( c->a.vals[1].type==v_unicode || c->a.vals[1].type==v_int )
c->return_val.u.ival = c->a.vals[1].u.ival;
else
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_unicode;
}
static void bInt(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_real )
c->return_val.u.ival = c->a.vals[1].u.fval;
else if ( c->a.vals[1].type==v_unicode || c->a.vals[1].type==v_int )
c->return_val.u.ival = c->a.vals[1].u.ival;
else
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_int;
}
static void bFloor(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_real )
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_int;
c->return_val.u.ival = floor( c->a.vals[1].u.fval );
}
static void bCeil(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_real )
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_int;
c->return_val.u.ival = ceil( c->a.vals[1].u.fval );
}
static void bRound(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_real )
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_int;
c->return_val.u.ival = rint( c->a.vals[1].u.fval );
}
static void bIsNan(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_real )
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_int;
c->return_val.u.ival = isnan( c->a.vals[1].u.fval );
}
static void bIsFinite(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_real )
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_int;
c->return_val.u.ival = finite( c->a.vals[1].u.fval );
}
static char *ToString(Val *val) {
int j;
char buffer[40];
if ( val->type==v_str ) {
return( copy(val->u.sval) );
} else if ( val->type==v_arr || val->type==v_arrfree ) {
char **results, *ret, *pt;
int len;
results = malloc(val->u.aval->argc*sizeof(char *));
len = 0;
for ( j=0; j<val->u.aval->argc; ++j ) {
results[j] = ToString(&val->u.aval->vals[j]);
len += strlen(results[j])+2;
}
ret = pt = malloc(len+20);
*pt++ = '[';
if ( val->u.aval->argc>0 ) {
strcpy(pt,results[0]); pt += strlen(pt);
free(results[0]);
for ( j=1; j<val->u.aval->argc; ++j ) {
*pt++ = ',';
if ( val->u.aval->vals[j-1].type==v_arr || val->u.aval->vals[j-1].type==v_arrfree )
*pt++ = '\n';
strcpy(pt,results[j]); pt += strlen(pt);
free(results[j]);
}
}
*pt++ = ']'; *pt = '\0';
free(results);
return( ret );
} else if ( val->type==v_int )
sprintf( buffer, "%d", val->u.ival );
else if ( val->type==v_unicode )
sprintf( buffer, "0u%04X", val->u.ival );
else if ( val->type==v_real )
sprintf( buffer, "%g", (double) val->u.fval );
else if ( val->type==v_void )
sprintf( buffer, "<void>");
else
sprintf( buffer, "<" "???" ">");
return( copy( buffer ));
}
static void bToString(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
c->return_val.type = v_str;
c->return_val.u.sval = ToString( &c->a.vals[1] );
}
static void bSqrt(Context *c) {
double val;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_real )
val = c->a.vals[1].u.fval;
else if ( c->a.vals[1].type==v_int )
val = c->a.vals[1].u.ival;
else
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_real;
c->return_val.u.fval = sqrt( val );
}
static void bExp(Context *c) {
double val;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_real )
val = c->a.vals[1].u.fval;
else if ( c->a.vals[1].type==v_int )
val = c->a.vals[1].u.ival;
else
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_real;
c->return_val.u.fval = exp( val );
}
static void bLog(Context *c) {
double val;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_real )
val = c->a.vals[1].u.fval;
else if ( c->a.vals[1].type==v_int )
val = c->a.vals[1].u.ival;
else
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_real;
c->return_val.u.fval = log( val );
}
static void bPow(Context *c) {
double val1, val2;
if ( c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_real )
val1 = c->a.vals[1].u.fval;
else if ( c->a.vals[1].type==v_int )
val1 = c->a.vals[1].u.ival;
else
ScriptError( c, "Bad type for argument" );
if ( c->a.vals[2].type==v_real )
val2 = c->a.vals[2].u.fval;
else if ( c->a.vals[2].type==v_int )
val2 = c->a.vals[2].u.ival;
else
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_real;
c->return_val.u.fval = pow( val1, val2 );
}
static void bSin(Context *c) {
double val;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_real )
val = c->a.vals[1].u.fval;
else if ( c->a.vals[1].type==v_int )
val = c->a.vals[1].u.ival;
else
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_real;
c->return_val.u.fval = sin( val );
}
static void bCos(Context *c) {
double val;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_real )
val = c->a.vals[1].u.fval;
else if ( c->a.vals[1].type==v_int )
val = c->a.vals[1].u.ival;
else
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_real;
c->return_val.u.fval = cos( val );
}
static void bTan(Context *c) {
double val;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_real )
val = c->a.vals[1].u.fval;
else if ( c->a.vals[1].type==v_int )
val = c->a.vals[1].u.ival;
else
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_real;
c->return_val.u.fval = tan( val );
}
static void bATan2(Context *c) {
double val1, val2;
if ( c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type==v_real )
val1 = c->a.vals[1].u.fval;
else if ( c->a.vals[1].type==v_int )
val1 = c->a.vals[1].u.ival;
else
ScriptError( c, "Bad type for argument" );
if ( c->a.vals[2].type==v_real )
val2 = c->a.vals[2].u.fval;
else if ( c->a.vals[2].type==v_int )
val2 = c->a.vals[2].u.ival;
else
ScriptError( c, "Bad type for argument" );
c->return_val.type = v_real;
c->return_val.u.fval = atan2( val1, val2 );
}
static void bRand(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments" );
c->return_val.type = v_int;
c->return_val.u.ival = rand();
}
static void bFileAccess(Context *c) {
if ( c->a.argc!=3 && c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str || (c->a.argc==3 && c->a.vals[2].type!=v_int ))
ScriptError( c, "Bad type of argument" );
c->return_val.type = v_int;
c->return_val.u.ival = access(c->a.vals[1].u.sval,c->a.argc==3 ? c->a.vals[2].u.ival : R_OK );
}
static void bLoadFileToString(Context *c) {
FILE *f;
int len;
char *name, *_name;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str )
ScriptError( c, "Bad type of argument" );
c->return_val.type = v_str;
_name = script2utf8_copy(c->a.vals[1].u.sval);
name = utf82def_copy(_name); free(_name);
f = fopen(name,"rb");
free(name);
if ( f==NULL )
c->return_val.u.sval = copy("");
else {
fseek(f,0,SEEK_END);
len = ftell(f);
rewind(f);
c->return_val.u.sval = malloc(len+1);
len = fread(c->return_val.u.sval,1,len,f);
c->return_val.u.sval[len]='\0';
fclose(f);
}
}
static void bWriteStringToFile(Context *c) {
FILE *f;
int append = 0;
char *name, *_name;
if ( c->a.argc!=3 && c->a.argc!=4 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str && c->a.vals[2].type!=v_str )
ScriptError( c, "Bad type of argument" );
else if ( c->a.argc==4 ) {
if ( c->a.vals[3].type!=v_int )
ScriptError( c, "Bad type of argument" );
append = c->a.vals[3].u.ival;
}
_name = script2utf8_copy(c->a.vals[2].u.sval);
name = utf82def_copy(_name); free(_name);
f = fopen(name,append?"ab":"wb");
free(name);
c->return_val.type = v_int;
if ( f==NULL )
c->return_val.u.ival = -1;
else {
c->return_val.u.ival = fwrite(c->a.vals[1].u.sval,1,strlen(c->a.vals[1].u.sval),f);
fclose(f);
}
}
static void bLoadPlugin(Context *c) {
char *name, *_name;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str )
ScriptError( c, "Bad type of argument" );
_name = script2utf8_copy(c->a.vals[1].u.sval);
name = utf82def_copy(_name); free(_name);
LoadPlugin(name);
free(name);
}
static void bLoadPluginDir(Context *c) {
char *dir=NULL, *_dir;
if ( c->a.argc>2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.argc==2 ) {
if ( c->a.vals[1].type!=v_str )
ScriptError( c, "Bad type of argument" );
_dir = script2utf8_copy(c->a.vals[1].u.sval);
dir = utf82def_copy(_dir); free(_dir);
}
LoadPluginDir(dir);
free(dir);
}
static void bLoadNamelist(Context *c) {
char *name, *_name;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.vals[1].type!=v_str )
ScriptError( c, "Bad type of argument" );
_name = script2utf8_copy(c->a.vals[1].u.sval);
name = utf82def_copy(_name); free(_name);
LoadNamelist(name);
free(name);
}
static void bLoadNamelistDir(Context *c) {
char *dir=NULL, *_dir;
if ( c->a.argc>2 )
ScriptError( c, "Wrong number of arguments" );
else if ( c->a.argc==2 ) {
if ( c->a.vals[1].type!=v_str )
ScriptError( c, "Bad type of argument" );
_dir = script2utf8_copy(c->a.vals[1].u.sval);
dir = utf82def_copy(_dir); free(_dir);
}
LoadNamelistDir(dir);
free(dir);
}
/* **** File menu **** */
static void bQuit(Context *c) {
if ( verbose>0 ) putchar('\n');
if ( c->a.argc==1 )
exit(0);
if ( c->a.argc>2 )
ScriptError( c, "Too many arguments" );
else if ( c->a.vals[1].type!=v_int )
ScriptError( c, "Expected integer argument" );
else
exit(c->a.vals[1].u.ival );
exit(1);
}
#endif /* _NO_FFSCRIPT */
char **GetFontNames(char *filename, int do_slow) {
FILE *foo;
char **ret = NULL;
if ( GFileIsDir(filename)) {
char *temp = malloc(strlen(filename)+strlen("/glyphs/contents.plist")+1);
strcpy(temp,filename);
strcat(temp,"/glyphs/contents.plist");
if ( GFileExists(temp))
ret = NamesReadUFO(filename);
else {
strcpy(temp,filename);
strcat(temp,"/font.props");
if ( GFileExists(temp))
ret = NamesReadSFD(temp);
/* The fonts.prop file will look just like an sfd file as far */
/* as fontnames are concerned, we don't need a separate routine*/
}
free(temp);
} else {
foo = fopen(filename,"rb");
if ( foo!=NULL ) {
/* Try to guess the file type from the first few characters... */
int ch1 = getc(foo);
int ch2 = getc(foo);
int ch3 = getc(foo);
int ch4 = getc(foo);
fseek(foo, 98, SEEK_SET);
/* ch5 */ (void)getc(foo);
/* ch6 */ (void)getc(foo);
fclose(foo);
if (( ch1==0 && ch2==1 && ch3==0 && ch4==0 ) ||
(ch1=='O' && ch2=='T' && ch3=='T' && ch4=='O') ||
(ch1=='t' && ch2=='r' && ch3=='u' && ch4=='e') ||
(ch1=='t' && ch2=='t' && ch3=='c' && ch4=='f') ) {
ret = NamesReadTTF(filename);
} else if (( ch1=='%' && ch2=='!' ) ||
( ch1==0x80 && ch2=='\01' ) ) { /* PFB header */
ret = NamesReadPostScript(filename);
} else if ( ch1=='%' && ch2=='P' && ch3=='D' && ch4=='F' && do_slow ) {
// We are disabling scanning for P. D. F. until we can address the performance issues.
ret = NamesReadPDF(filename);
} else if ( ch1=='<' && ch2=='?' && (ch3=='x'||ch3=='X') && (ch4=='m'||ch4=='M') ) {
ret = NamesReadSVG(filename);
} else if ( ch1=='S' && ch2=='p' && ch3=='l' && ch4=='i' ) {
ret = NamesReadSFD(filename);
} else if ( ch1==1 && ch2==0 && ch3==4 ) {
ret = NamesReadCFF(filename);
} else /* Too hard to figure out a valid mark for a mac resource file */
ret = NamesReadMacBinary(filename);
}
}
return( ret );
}
#ifndef _NO_FFSCRIPT
static void bFontsInFile(Context *c) {
char **ret;
int cnt;
char *t;
char *locfilename;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments");
else if ( c->a.vals[1].type!=v_str )
ScriptError( c, "FontsInFile expects a filename" );
t = script2utf8_copy(c->a.vals[1].u.sval);
locfilename = utf82def_copy(t);
ret = GetFontNames(locfilename, 1);
free(t); free(locfilename);
cnt = 0;
if ( ret!=NULL ) for ( cnt=0; ret[cnt]!=NULL; ++cnt );
c->return_val.type = v_arrfree;
c->return_val.u.aval = malloc(sizeof(Array));
c->return_val.u.aval->argc = cnt;
c->return_val.u.aval->vals = malloc((cnt==0?1:cnt)*sizeof(Val));
if ( ret!=NULL ) for ( cnt=0; ret[cnt]!=NULL; ++cnt ) {
c->return_val.u.aval->vals[cnt].type = v_str;
c->return_val.u.aval->vals[cnt].u.sval = ret[cnt];
}
free(ret);
}
static void bOpen(Context *c) {
SplineFont *sf;
int openflags=0;
char *t;
char *locfilename;
if ( c->a.argc!=2 && c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments");
else if ( c->a.vals[1].type!=v_str )
ScriptError( c, "Open expects a filename" );
else if ( c->a.argc==3 ) {
if ( c->a.vals[2].type!=v_int )
ScriptError( c, "Open expects an integer for second argument" );
openflags = c->a.vals[2].u.ival;
}
t = script2utf8_copy(c->a.vals[1].u.sval);
locfilename = utf82def_copy(t);
sf = LoadSplineFont(locfilename,openflags);
free(t); free(locfilename);
if ( sf==NULL )
ScriptErrorString(c, "Failed to open", c->a.vals[1].u.sval);
else {
if ( sf->fv!=NULL )
/* All done */;
else if ( !no_windowing_ui )
FontViewCreate(sf,openflags&of_hidewindow);
else
FVAppend(_FontViewCreate(sf));
c->curfv = sf->fv;
}
}
static void bSelectBitmap(Context *c) {
BDFFont *bdf;
int depth, size;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments");
else if ( c->a.vals[1].type!=v_int )
ScriptError( c, "Bad type for argument" );
size = c->a.vals[2].u.ival;
if ( size==-1 )
c->curfv->active_bitmap = NULL;
else {
depth = size>>16;
if ( depth==0 ) depth = 1;
size = size&0xffff;
for ( bdf = c->curfv->sf->bitmaps; bdf!=NULL; bdf=bdf->next )
if ( size==bdf->pixelsize && depth==BDFDepth(bdf))
break;
ScriptError(c,"No matching bitmap");
c->curfv->active_bitmap = bdf;
}
}
static void bNew(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
if ( !no_windowing_ui )
c->curfv = FontViewCreate(SplineFontNew(),false);
else
c->curfv = FVAppend(_FontViewCreate(SplineFontNew()));
}
static void bClose(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
FontViewClose(c->curfv);
c->curfv = NULL;
}
static void bRevert(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
FVRevert(c->curfv);
}
static void bRevertToBackup(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
FVRevertBackup(c->curfv);
}
static void bSave(Context *c) {
SplineFont *sf = c->curfv->sf;
char *t, *pt;
char *locfilename;
int s2d = false;
int localRevisionsToRetain = -1;
if ( c->a.argc>3 )
ScriptError( c, "Wrong number of arguments");
// Grab the optional number of backups that are desired argument
if ( c->a.argc==3 ) {
/**
* A call Save( wheretosave, revisioncount )
*/
if ( c->a.vals[2].type!=v_int )
ScriptError(c,"The second argument to Save() must be a number of revisions to keep (integer)");
localRevisionsToRetain = c->a.vals[2].u.ival;
}
if ( c->a.argc>=2 )
{
if ( c->a.vals[1].type!=v_str )
ScriptError(c,"If an argument is given to Save it must be a filename");
t = script2utf8_copy(c->a.vals[1].u.sval);
locfilename = utf82def_copy(t);
pt = strrchr(locfilename,'.');
if ( pt!=NULL && strmatch(pt,".sfdir")==0 )
s2d = true;
int rc = SFDWriteBakExtended( locfilename,
sf,c->curfv->map,c->curfv->normal,s2d,
localRevisionsToRetain );
if ( !rc )
ScriptError(c,"Save failed" );
/* Hmmm. We don't set the filename, nor the save_to_dir bit */
free(t); free(locfilename);
}
else
{
if ( sf->filename==NULL )
ScriptError(c,"This font has no associated sfd file yet, you must specify a filename" );
/**
* If there are no existing backup files, don't start creating them here.
* Otherwise, save as many as the user wants.
*/
int s2d = false;
int rc = SFDWriteBakExtended( sf->filename,
sf,c->curfv->map,c->curfv->normal,s2d,
localRevisionsToRetain );
if ( !rc )
ScriptError(c,"Save failed" );
}
}
static void bGenerate(Context *c) {
SplineFont *sf = c->curfv->sf;
const char *bitmaptype = "";
int fmflags = -1;
int res = -1;
char *subfontdirectory = NULL;
char *t;
char *locfilename;
NameList *rename_to = NULL;
if ( c->a.argc!=2 && c->a.argc!=3 && c->a.argc!=4 && c->a.argc!=5 && c->a.argc!=6 && c->a.argc!=7 )
ScriptError( c, "Wrong number of arguments");
if ( c->a.vals[1].type!=v_str ||
(c->a.argc>=3 && c->a.vals[2].type!=v_str ) ||
(c->a.argc>=4 && c->a.vals[3].type!=v_int ) ||
(c->a.argc>=5 && c->a.vals[4].type!=v_int ) ||
(c->a.argc>=6 && c->a.vals[5].type!=v_str ) ||
(c->a.argc>=7 && c->a.vals[5].type!=v_str ))
ScriptError( c, "Bad type of argument");
if ( c->a.argc>=3 )
bitmaptype = c->a.vals[2].u.sval;
if ( c->a.argc>=4 )
fmflags = c->a.vals[3].u.ival;
if ( c->a.argc>=5 )
res = c->a.vals[4].u.ival;
if ( c->a.argc>=6 )
subfontdirectory = c->a.vals[5].u.sval;
if ( c->a.argc>=7 ) {
rename_to = NameListByName(c->a.vals[6].u.sval);
if ( rename_to==NULL )
ScriptErrorString( c, "Could not find namelist: ", c->a.vals[6].u.sval);
}
t = script2utf8_copy(c->a.vals[1].u.sval);
locfilename = utf82def_copy(t);
if ( !GenerateScript(sf,locfilename,bitmaptype,fmflags,res,subfontdirectory,
NULL,c->curfv->normal==NULL?c->curfv->map:c->curfv->normal,rename_to,
ly_fore) )
ScriptError(c,"Save failed");
free(t); free(locfilename);
}
static int strtailcmp(char *needle, char *haystack) {
int nlen = strlen(needle), hlen = strlen(haystack);
if ( nlen>hlen )
return( -1 );
if ( *needle=='/' )
return( strcmp(needle,haystack));
return( strcmp(needle,haystack+hlen-nlen));
}
typedef SplineFont *SFArray[48];
static void bGenerateFamily(Context *c) {
SplineFont *sf = NULL;
const char *bitmaptype = "";
int fmflags = -1;
struct sflist *sfs, *cur, *lastsfs;
Array *fonts;
FontViewBase *fv;
int i, j, fc, added;
uint16 psstyle;
int fondcnt = 0, fondmax = 10;
SFArray *familysfs=NULL;
char *t;
char *locfilename;
familysfs = malloc((fondmax=10)*sizeof(SFArray));
if ( c->a.argc!=5 )
ScriptError( c, "Wrong number of arguments");
if ( c->a.vals[1].type!=v_str || c->a.vals[2].type!=v_str ||
c->a.vals[3].type!=v_int ||
c->a.vals[4].type!=v_arr )
ScriptError( c, "Bad type of argument");
bitmaptype = c->a.vals[2].u.sval;
fmflags = c->a.vals[3].u.ival;
fonts = c->a.vals[4].u.aval;
for ( i=0; i<fonts->argc; ++i ) {
if ( fonts->vals[i].type!=v_str )
ScriptError(c,"Values in the fontname array must be strings");
for ( fv=FontViewFirst(); fv!=NULL; fv=fv->next ) if ( fv->sf!=sf )
if ( strtailcmp(fonts->vals[i].u.sval,fv->sf->origname)==0 ||
(fv->sf->filename!=NULL && strtailcmp(fonts->vals[i].u.sval,fv->sf->origname)==0 ))
break;
if ( fv==NULL )
for ( fv=FontViewFirst(); fv!=NULL; fv=fv->next ) if ( fv->sf!=sf )
if ( strcmp(fonts->vals[i].u.sval,fv->sf->fontname)==0 )
break;
if ( fv==NULL ) {
LogError( "%s\n", fonts->vals[i].u.sval );
ScriptError( c, "The above font is not loaded" );
}
if ( sf==NULL )
sf = fv->sf;
if ( strcmp(fv->sf->familyname,sf->familyname)!=0 )
LogError( _("Warning: %s has a different family name than does %s (GenerateFamily)\n"),
fv->sf->fontname, sf->fontname );
MacStyleCode(fv->sf,&psstyle);
if ( psstyle>=48 ) {
LogError( "%s(%s)\n", fv->sf->origname, fv->sf->fontname );
ScriptError( c, "A font can't be both Condensed and Expanded" );
}
added = false;
if ( fv->sf->fondname==NULL ) {
if ( fondcnt>0 ) {
for ( j=0; j<48; ++j )
if ( familysfs[0][j]!=NULL )
break;
if ( familysfs[0][j]->fondname==NULL ) {
if ( familysfs[0][psstyle]==NULL || familysfs[0][psstyle]==fv->sf ) {
familysfs[0][psstyle] = fv->sf;
fv->sf->map = fv->map;
added = true;
}
}
}
} else {
for ( fc=0; fc<fondcnt; ++fc ) {
for ( j=0; j<48; ++j )
if ( familysfs[fc][j]!=NULL )
break;
if ( familysfs[fc][j]->fondname!=NULL &&
strcmp(familysfs[fc][j]->fondname,fv->sf->fondname)==0 ) {
if ( familysfs[fc][psstyle]==NULL || familysfs[fc][psstyle]==fv->sf ) {
familysfs[fc][psstyle] = fv->sf;
added = true;
} else {
LogError( _("%s(%s) and %s(%s) 0x%x in FOND %s\n"),
familysfs[fc][psstyle]->origname, familysfs[fc][psstyle]->fontname,
fv->sf->origname, fv->sf->fontname,
psstyle, fv->sf->fondname );
ScriptError( c, "Two array entries given with the same style (in the Mac's postscript style set)" );
}
}
}
}
if ( !added ) {
if ( fondcnt>=fondmax )
familysfs = realloc(familysfs,(fondmax+=10)*sizeof(SFArray));
memset(familysfs[fondcnt],0,sizeof(SFArray));
familysfs[fondcnt++][psstyle] = fv->sf;
}
}
if ( familysfs[0][0]==NULL ) {
if ( MacStyleCode(c->curfv->sf,NULL)==0 && strcmp(c->curfv->sf->familyname,sf->familyname)!=0 )
familysfs[0][0] = c->curfv->sf;
if ( familysfs[0][0]==NULL )
ScriptError(c,"At least one of the specified fonts must have a plain style");
}
sfs = lastsfs = NULL;
for ( fc=0; fc<fondcnt; ++fc ) {
for ( j=0; j<48; ++j ) if ( familysfs[fc][j]!=NULL ) {
cur = chunkalloc(sizeof(struct sflist));
if ( sfs==NULL ) sfs = cur;
else lastsfs->next = cur;
lastsfs = cur;
cur->sf = familysfs[fc][j];
cur->map = cur->sf->map;
}
}
free(familysfs);
t = script2utf8_copy(c->a.vals[1].u.sval);
locfilename = utf82def_copy(t);
if ( !GenerateScript(sf,locfilename,bitmaptype,fmflags,-1,NULL,sfs,
c->curfv->normal==NULL?c->curfv->map:c->curfv->normal,NULL,
ly_fore) )
ScriptError(c,"Save failed");
free(t); free(locfilename);
for ( cur=sfs; cur!=NULL; cur=sfs ) {
sfs = cur->next;
/* free(cur->sizes); */ /* Done inside GenerateScript */
chunkfree(cur,sizeof(struct sflist));
}
}
static void bGenerateFeatureFile(Context *c) {
SplineFont *sf = c->curfv->sf;
char *t;
char *locfilename;
OTLookup *otl = NULL;
FILE *out;
int err;
if ( c->a.argc!=2 && c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments");
if ( c->a.vals[1].type!=v_str || (c->a.argc==3 && c->a.vals[2].type!=v_str ))
ScriptError( c, "Bad type of argument");
if ( c->a.argc==3 ) {
otl = SFFindLookup(sf,c->a.vals[2].u.sval);
if ( otl==NULL )
ScriptError(c,"Unknown lookup");
}
t = script2utf8_copy(c->a.vals[1].u.sval);
locfilename = utf82def_copy(t);
out = fopen(locfilename,"w");
if ( out==NULL )
ScriptError(c,"Failed to open output file");
if ( otl!=NULL )
FeatDumpOneLookup(out,sf,otl);
else
FeatDumpFontLookups(out,sf);
err = ferror(out);
if ( fclose(out)!=0 || err )
ScriptError(c,"IO Error");
free(t); free(locfilename);
}
static void bControlAfmLigatureOutput(Context *c) {
ScriptError(c,"This scripting function no longer works.");
}
static void Bitmapper(Context *c,int isavail) {
int32 *sizes;
int i;
int rasterize = true;
if ( c->a.argc!=2 && (!isavail || c->a.argc!=3))
ScriptError( c, "Wrong number of arguments");
if ( c->a.vals[1].type!=v_arr )
ScriptError( c, "Bad type of argument");
for ( i=0; i<c->a.vals[1].u.aval->argc; ++i )
if ( c->a.vals[1].u.aval->vals[i].type!=v_int ||
c->a.vals[1].u.aval->vals[i].u.ival<=2 )
ScriptError( c, "Bad type of array component");
if ( c->a.argc==3 ) {
if ( c->a.vals[2].type!=v_int )
ScriptError( c, "Bad type of argument");
rasterize = c->a.vals[2].u.ival;
}
sizes = malloc((c->a.vals[1].u.aval->argc+1)*sizeof(int32));
for ( i=0; i<c->a.vals[1].u.aval->argc; ++i ) {
sizes[i] = c->a.vals[1].u.aval->vals[i].u.ival;
if ( (sizes[i]>>16)==0 )
sizes[i] |= 0x10000;
}
sizes[i] = 0;
if ( !BitmapControl(c->curfv,sizes,isavail,rasterize) )
ScriptError(c,"Bitmap operation failed"); /* Storage leak here longjmp avoids free */
free(sizes);
}
static void bBitmapsAvail(Context *c) {
int shows_bitmap = false;
BDFFont *bdf;
if ( c->curfv->active_bitmap!=NULL ) {
for ( bdf=c->curfv->sf->bitmaps; bdf!=NULL; bdf = bdf->next )
if ( bdf==c->curfv->active_bitmap )
break;
shows_bitmap = bdf!=NULL;
}
Bitmapper(c,true);
if ( shows_bitmap && c->curfv->active_bitmap!=NULL ) {
BDFFont *bdf;
for ( bdf=c->curfv->sf->bitmaps; bdf!=NULL; bdf = bdf->next )
if ( bdf==c->curfv->active_bitmap )
break;
if ( bdf==NULL )
c->curfv->active_bitmap = c->curfv->sf->bitmaps;
}
}
static void bBitmapsRegen(Context *c) {
Bitmapper(c,false);
}
static void bImport(Context *c) {
char *ext, *filename;
int format, back, ok, flags;
char *t; char *locfilename;
if ( c->a.argc!=2 && c->a.argc!=3 && c->a.argc!=4 )
ScriptError( c, "Wrong number of arguments");
if ( c->a.vals[1].type!=v_str ||
(c->a.argc>=3 && c->a.vals[2].type!=v_int ) ||
(c->a.argc==4 && c->a.vals[3].type!=v_int ))
ScriptError( c, "Bad type of argument");
t = script2utf8_copy(c->a.vals[1].u.sval);
locfilename = utf82def_copy(t);
filename = GFileMakeAbsoluteName(locfilename);
free(locfilename); free(t);
ext = strrchr(filename,'.');
if ( ext==NULL ) {
int len = strlen(filename);
ext = filename+len-2;
if ( ext[0]!='p' || ext[1]!='k' )
ScriptErrorString( c, "No extension in", filename);
}
back = 0; flags = -1;
if ( strmatch(ext,".bdf")==0 || strmatch(ext-4,".bdf.gz")==0 )
format = fv_bdf;
else if ( strmatch(ext,".pcf")==0 || strmatch(ext-4,".pcf.gz")==0 )
format = fv_pcf;
else if ( strmatch(ext,".ttf")==0 || strmatch(ext,".otf")==0 || strmatch(ext,".otb")==0 )
format = fv_ttf;
else if ( strmatch(ext,"pk")==0 || strmatch(ext,".pk")==0 ) {
format = fv_pk;
back = true;
} else if ( strmatch(ext,".eps")==0 || strmatch(ext,".ps")==0 ||
strmatch(ext,".art")==0 ) {
if ( strchr(filename,'*')!=NULL )
format = fv_epstemplate;
else
format = fv_eps;
} else if ( strmatch(ext,".pdf")==0 ) {
if ( strchr(filename,'*')!=NULL )
format = fv_pdftemplate;
else
format = fv_pdf;
} else if ( strmatch(ext,".svg")==0 ) {
if ( strchr(filename,'*')!=NULL )
format = fv_svgtemplate;
else
format = fv_svg;
} else {
if ( strchr(filename,'*')!=NULL )
format = fv_imgtemplate;
else
format = fv_image;
back = true;
}
if ( c->a.argc>=3 )
back = c->a.vals[2].u.ival;
if ( c->a.argc>=4 )
flags = c->a.vals[3].u.ival;
if ( format==fv_bdf )
ok = FVImportBDF(c->curfv,filename,false, back);
else if ( format==fv_pcf )
ok = FVImportBDF(c->curfv,filename,2, back);
else if ( format==fv_ttf )
ok = FVImportMult(c->curfv,filename, back, bf_ttf);
else if ( format==fv_pk )
ok = FVImportBDF(c->curfv,filename,true, back);
else if ( format==fv_image || format==fv_eps || format==fv_svg || format==fv_pdf )
ok = FVImportImages(c->curfv,filename,format,back,flags);
else
ok = FVImportImageTemplate(c->curfv,filename,format,back,flags);
free(filename);
if ( !ok )
ScriptError(c,"Import failed" );
}
#ifdef FONTFORGE_CONFIG_WRITE_PFM
static void bWritePfm(Context *c) {
SplineFont *sf = c->curfv->sf;
char *t; char *locfilename;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments");
if ( c->a.vals[1].type!=v_str )
ScriptError( c, "Bad type of argument");
t = script2utf8_copy(c->a.vals[1].u.sval);
locfilename = utf82def_copy(t);
if ( !WritePfmFile(c->a.vals[1].u.sval,sf,0,c->curfv->map) )
ScriptError(c,"Save failed");
free(locfilename); free(t);
}
#endif
static void bExport(Context *c) {
int format,i, gid ;
BDFFont *bdf;
char *pt, *format_spec;
char buffer[20];
char *t;
if ( c->a.argc!=2 && c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments");
if ( c->a.vals[1].type!=v_str || (c->a.argc==3 && c->a.vals[2].type!=v_int ))
ScriptError( c, "Bad type of arguments");
t = script2utf8_copy(c->a.vals[1].u.sval);
pt = utf82def_copy(t); free(t);
sprintf( buffer, "%%n_%%f.%.4s", pt);
format_spec = buffer;
if ( strrchr(pt,'.')!=NULL ) {
format_spec = pt;
pt = strrchr(pt,'.')+1;
}
if ( strmatch(pt,"eps")==0 )
format = 0;
else if ( strmatch(pt,"fig")==0 )
format = 1;
else if ( strmatch(pt,"svg")==0 )
format = 2;
else if ( strmatch(pt,"glif")==0 )
format = 3;
else if ( strmatch(pt,"pdf")==0 )
format = 4;
else if ( strmatch(pt,"plate")==0 )
format = 5;
else if ( strmatch(pt,"xbm")==0 )
format = 6;
else if ( strmatch(pt,"bmp")==0 )
format = 7;
#ifndef _NO_LIBPNG
else if ( strmatch(pt,"png")==0 )
format = 8;
else
ScriptError( c, "Bad format (first arg must be eps/fig/xbm/bmp/png)");
#else
else
ScriptError( c, "Bad format (first arg must be eps/fig/xbm/bmp)");
#endif
if (( format>=4 && c->a.argc!=3 ) || (format<4 && c->a.argc==3 ))
ScriptError( c, "Wrong number of arguments");
bdf=NULL;
if ( format>4 ) {
for ( bdf = c->curfv->sf->bitmaps; bdf!=NULL; bdf=bdf->next )
if (( BDFDepth(bdf)==1 && bdf->pixelsize==c->a.vals[2].u.ival) ||
(bdf->pixelsize!=(c->a.vals[2].u.ival&0xffff) &&
BDFDepth(bdf)==(c->a.vals[2].u.ival>>16)) )
break;
if ( bdf==NULL )
ScriptError(c, "No bitmap font matches the specified size");
}
for ( i=0; i<c->curfv->map->enccount; ++i )
if ( c->curfv->selected[i] && (gid=c->curfv->map->map[i])!=-1 &&
SCWorthOutputting(c->curfv->sf->glyphs[gid]) )
ScriptExport(c->curfv->sf,bdf,format,gid,format_spec,c->curfv->map);
if ( format_spec!=buffer )
free(format_spec);
}
/* FontImage("Outputfilename",array of [pointsize,string][,width[,height]]) */
static void bFontImage(Context *c) {
int i ;
char *pt, *t;
int width = -1, height = -1;
Array *arr;
if ( c->a.argc<3 || c->a.argc>5 )
ScriptError( c, "Wrong number of arguments");
if ( c->a.vals[1].type!=v_str ||
(c->a.vals[2].type!=v_arr && c->a.vals[2].type!=v_arrfree) ||
(c->a.argc>=4 && c->a.vals[3].type!=v_int ) ||
(c->a.argc>=5 && c->a.vals[4].type!=v_int ) )
ScriptError( c, "Bad type of arguments");
t = script2utf8_copy(c->a.vals[1].u.sval);
pt = strrchr(t,'.');
if ( pt==NULL || (strmatch(pt,".bmp")!=0
#ifndef _NO_LIBPNG
&& strmatch(pt,".png")!=0
#endif
))
ScriptError( c, "Unsupported image format");
if ( c->a.argc>=4 )
width = c->a.vals[3].u.ival;
if ( c->a.argc>=5 )
height = c->a.vals[4].u.ival;
arr = c->a.vals[2].u.aval;
if ( (arr->argc&1) && arr->argc>=2 )
ScriptError(c, "Second argument must be an array with an even number of entries");
if ( arr->argc==1 ) {
if ( arr->vals[0].type != v_int )
ScriptError( c, "Second argument must be an array where each even numbered entry is an integer pixelsize" );
} else for ( i=0; i<arr->argc; i+=2 ) {
if ( arr->vals[i].type != v_int )
ScriptError( c, "Second argument must be an array where each even numbered entry is an integer pixelsize" );
if ( arr->vals[i+1].type != v_str )
ScriptError( c, "Second argument must be an array where each odd numbered entry is a string" );
}
FontImage(c->curfv->sf,t,arr,width,height);
free(t);
}
static void bMergeKern(Context *c) {
char *t; char *locfilename;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments");
if ( c->a.vals[1].type!=v_str )
ScriptError( c, "Bad type of arguments");
t = script2utf8_copy(c->a.vals[1].u.sval);
locfilename = utf82def_copy(t);
if ( !LoadKerningDataFromMetricsFile(c->curfv->sf,locfilename,c->curfv->map))
ScriptError( c, "Failed to find kern info in file" );
free(locfilename); free(t);
}
static void bPrintSetup(Context *c) {
if ( c->a.argc!=2 && c->a.argc!=3 && c->a.argc!=5 )
ScriptError( c, "Wrong number of arguments");
if ( c->a.vals[1].type!=v_int )
ScriptError( c, "Bad type for first argument");
if ( c->a.argc>=3 && c->a.vals[2].type!=v_str )
ScriptError( c, "Bad type for second argument");
if ( c->a.argc==5 ) {
if ( c->a.vals[3].type!=v_int )
ScriptError( c, "Bad type for third argument");
if ( c->a.vals[4].type!=v_int )
ScriptError( c, "Bad type for fourth argument");
pagewidth = c->a.vals[3].u.ival;
pageheight = c->a.vals[4].u.ival;
}
if ( c->a.vals[1].u.ival<0 || c->a.vals[1].u.ival>5 )
ScriptError( c, "First argument out of range [0,5]");
printtype = c->a.vals[1].u.ival;
if ( c->a.argc>=3 && printtype==4 )
printcommand = copy(c->a.vals[2].u.sval);
else if ( c->a.argc>=3 && (printtype==0 || printtype==1) )
printlazyprinter = copy(c->a.vals[2].u.sval);
}
static void bPrintFont(Context *c) {
int type, i, inlinesample = false;
int32 *pointsizes=NULL;
char *samplefile=NULL, *output=NULL;
unichar_t *sample=NULL;
char *t; char *locfilename=NULL;
if ( c->a.argc!=2 && c->a.argc!=3 && c->a.argc!=4 && c->a.argc!=5 )
ScriptError( c, "Wrong number of arguments");
type = c->a.vals[1].u.ival;
if ( c->a.vals[1].type!=v_int || type<0 || type>4 )
ScriptError( c, "Bad type for first argument");
if ( type==4 ) {
type=3;
inlinesample = true;
}
if ( c->a.argc>=3 ) {
if ( c->a.vals[2].type==v_int ) {
if ( c->a.vals[2].u.ival>0 ) {
pointsizes = calloc(2,sizeof(int32));
pointsizes[0] = c->a.vals[2].u.ival;
}
} else if ( c->a.vals[2].type==v_arr ) {
Array *a = c->a.vals[2].u.aval;
pointsizes = malloc((a->argc+1)*sizeof(int32));
for ( i=0; i<a->argc; ++i ) {
if ( a->vals[i].type!=v_int )
ScriptError( c, "Bad type for array contents");
pointsizes[i] = a->vals[i].u.ival;
}
pointsizes[i] = 0;
} else
ScriptError( c, "Bad type for second argument");
}
if ( c->a.argc>=4 ) {
if ( c->a.vals[3].type!=v_str )
ScriptError( c, "Bad type for third argument");
else if ( *c->a.vals[3].u.sval!='\0' ) {
samplefile = c->a.vals[3].u.sval;
if ( inlinesample ) {
sample = utf82u_copy(samplefile);
samplefile = NULL;
} else {
t = script2utf8_copy(samplefile);
samplefile = locfilename = utf82def_copy(t); free(t);
}
}
}
if ( c->a.argc>=5 ) {
if ( c->a.vals[4].type!=v_str )
ScriptError( c, "Bad type for fourth argument");
else if ( *c->a.vals[4].u.sval!='\0' )
output = c->a.vals[4].u.sval;
}
ScriptPrint(c->curfv,type,pointsizes,samplefile,sample,output);
free(pointsizes);
free(locfilename);
/* ScriptPrint frees sample for us */
}
/* **** Edit menu **** */
static void bCut(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
FVCopy(c->curfv,ct_fullcopy);
FVClear(c->curfv);
}
static void bCopy(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
FVCopy(c->curfv,ct_fullcopy);
}
static void bCopyReference(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
FVCopy(c->curfv,ct_reference);
}
static void bCopyUnlinked(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
FVCopy(c->curfv,ct_unlinkrefs);
}
static void bCopyWidth(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
FVCopy(c->curfv,ut_width);
}
static void bCopyVWidth(Context *c) {
if ( c->curfv!=NULL && !c->curfv->sf->hasvmetrics )
ScriptError(c,"Vertical metrics not enabled in this font");
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
FVCopy(c->curfv,ut_vwidth);
}
static void bCopyLBearing(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
FVCopy(c->curfv,ut_lbearing);
}
static void bCopyRBearing(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
FVCopy(c->curfv,ut_rbearing);
}
static void bCopyAnchors(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
FVCopyAnchors(c->curfv);
}
static int GetOneSelCharIndex(Context *c) {
FontViewBase *fv = c->curfv;
EncMap *map = fv->map;
int i, found = -1;
for ( i=0; i<map->enccount; ++i ) if ( fv->selected[i] ) {
if ( found==-1 )
found = i;
else
ScriptError(c,"More than one character selected" );
}
if ( found==-1 )
ScriptError(c,"No characters selected" );
return( found );
}
static SplineChar *GetOneSelChar(Context *c) {
int found = GetOneSelCharIndex(c);
return( SFMakeChar(c->curfv->sf,c->curfv->map,found));
}
static void bCopyGlyphFeatures(Context *c) {
ScriptError(c,"This scripting function no longer works.");
}
static void bPaste(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
PasteIntoFV(c->curfv,false,NULL);
}
static void bPasteInto(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
PasteIntoFV(c->curfv,true,NULL);
}
static void bPasteWithOffset(Context *c) {
real trans[6];
memset(trans,0,sizeof(trans));
trans[0] = trans[3] = 1;
if ( c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments");
if ( c->a.vals[1].type==v_int )
trans[4] = c->a.vals[1].u.ival;
else if ( c->a.vals[1].type==v_real )
trans[4] = c->a.vals[1].u.fval;
else
ScriptError( c, "Bad type for argument");
if ( c->a.vals[2].type==v_int )
trans[5] = c->a.vals[2].u.ival;
else if ( c->a.vals[2].type==v_real )
trans[5] = c->a.vals[2].u.fval;
else
ScriptError( c, "Bad type for argument");
PasteIntoFV(c->curfv,3,trans);
}
static void bClear(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
FVClear( c->curfv );
}
static void bClearBackground(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
FVClearBackground( c->curfv );
}
static void bCopyFgToBg(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
FVCopyFgtoBg(c->curfv);
}
static void bUnlinkReference(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
FVUnlinkRef(c->curfv);
}
static void bJoin(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
FVJoin(c->curfv);
}
static void bSameGlyphAs(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
FVSameGlyphAs(c->curfv);
}
static void bMultipleEncodingsToReferences(Context *c) {
int i, gid;
FontViewBase *fv = c->curfv;
SplineFont *sf = fv->sf;
EncMap *map = fv->map;
SplineChar *sc, *orig;
struct altuni *alt, *next, *prev;
int uni, enc;
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
for ( i=0; i<map->enccount; ++i ) {
if ( (gid=map->map[i])!=-1 && fv->selected[i] &&
(orig = sf->glyphs[gid])!=NULL && orig->altuni!=NULL ) {
prev = NULL;
for ( alt = orig->altuni; alt!=NULL; alt=next ) {
if ( alt->vs==-1 ) {
next = alt->next;
uni = alt->unienc;
orig->altuni = next;
AltUniFree(alt);
if ( prev==NULL )
orig->altuni = next;
else
prev->next = next;
enc = EncFromUni(uni,map->enc);
if ( enc!=-1 ) {
map->map[enc] = -1;
sc = SFMakeChar(sf,map,enc);
SCAddRef(sc,orig,ly_fore,0,0);
}
} else
prev = alt;
}
}
}
/* Now suppose we had a duplicate encoding of a glyph with no unicode */
/* so there will be no altuni to mark it */
for ( gid=0; gid<sf->glyphcnt; ++gid ) {
for ( i=0; i<map->enccount; ++i ) {
if ( map->map[i]==gid && map->backmap[gid]!=i &&
(fv->selected[i] || (map->backmap[gid]!=-1 && fv->selected[map->backmap[gid]]))) {
map->map[i] = -1;
sc = SFMakeChar(sf,map,i);
SCAddRef(sc,orig,ly_fore,0,0);
sc->width = orig->width;
sc->vwidth = orig->vwidth;
}
}
}
}
static void bSelectAll(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
memset(c->curfv->selected,1,c->curfv->map->enccount);
}
static void bSelectNone(Context *c) {
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
memset(c->curfv->selected,0,c->curfv->map->enccount);
}
static void bSelectInvert(Context *c) {
int i;
if ( c->a.argc!=1 )
ScriptError( c, "Wrong number of arguments");
for ( i=0; i<c->curfv->map->enccount; ++i )
c->curfv->selected[i] = !c->curfv->selected[i];
}
static int ParseCharIdent(Context *c, Val *val, int signal_error) {
SplineFont *sf = c->curfv->sf;
EncMap *map = c->curfv->map;
int bottom = -1;
if ( val->type==v_int )
bottom = val->u.ival;
else if ( val->type==v_unicode || val->type==v_str ) {
if ( val->type==v_unicode )
bottom = SFFindSlot(sf,map,val->u.ival,NULL);
else {
bottom = SFFindSlot(sf,map,-1,val->u.sval);
}
} else {
if ( signal_error )
ScriptError( c, "Bad type for argument");
else
return( -1 );
}
if ( bottom<0 || bottom>=map->enccount ) {
if ( signal_error ) {
char buffer[40], *name = buffer;
if ( val->type==v_int )
sprintf( buffer, "%d", val->u.ival );
else if ( val->type == v_unicode )
sprintf( buffer, "U+%04X", val->u.ival );
else
name = val->u.sval;
if ( bottom==-1 )
ScriptErrorString( c, "Character not found", name );
else
ScriptErrorString( c, "Character is not in font", name );
}
return( -1 );
}
return( bottom );
}
static int bDoSelect(Context *c, int signal_error, int select, int by_ranges) {
int top, bottom, i,j;
int any = false;
if ( c->a.argc==2 && (c->a.vals[1].type==v_arr || c->a.vals[1].type==v_arrfree)) {
struct array *arr = c->a.vals[1].u.aval;
for ( i=0; i<arr->argc && i<c->curfv->map->enccount; ++i ) {
if ( arr->vals[i].type!=v_int ) {
if ( signal_error )
ScriptError(c,"Bad type within selection array");
else
return( any ? -1 : -2 );
} else {
c->curfv->selected[i] = (arr->vals[i].u.ival!=0);
++any;
}
}
return( any );
}
for ( i=1; i<c->a.argc; i+=1+by_ranges ) {
bottom = ParseCharIdent(c,&c->a.vals[i],signal_error);
if ( i+1==c->a.argc || !by_ranges )
top = bottom;
else {
top = ParseCharIdent(c,&c->a.vals[i+1],signal_error);
}
if ( bottom==-1 || top==-1 ) /* an error occurred in parsing */
return( any ? -1 : -2 );
if ( top<bottom ) { j=top; top=bottom; bottom = j; }
for ( j=bottom; j<=top; ++j ) {
c->curfv->selected[j] = select;
++any;
}
}
return( any );
}
static void bSelectMore(Context *c) {
if ( c->a.argc==1 )
ScriptError( c, "SelectMore needs at least one argument");
bDoSelect(c,true,true,true);
}
static void bSelectFewer(Context *c) {
if ( c->a.argc==1 )
ScriptError( c, "SelectFewer needs at least one argument");
bDoSelect(c,true,false,true);
}
static void bSelect(Context *c) {
memset(c->curfv->selected,0,c->curfv->map->enccount);
bDoSelect(c,true,true,true);
}
static void bSelectMoreIf(Context *c) {
if ( c->a.argc==1 )
ScriptError( c, "SelectMore needs at least one argument");
c->return_val.type = v_int;
c->return_val.u.ival = bDoSelect(c,false,true,true);
}
static void bSelectMoreSingletons(Context *c) {
if ( c->a.argc==1 )
ScriptError( c, "SelectMore needs at least one argument");
bDoSelect(c,true,true,false);
}
static void bSelectMoreSingletonsIf(Context *c) {
if ( c->a.argc==1 )
ScriptError( c, "SelectMore needs at least one argument");
c->return_val.type = v_int;
c->return_val.u.ival = bDoSelect(c,false,true,false);
}
static void bSelectFewerSingletons(Context *c) {
if ( c->a.argc==1 )
ScriptError( c, "SelectFewer needs at least one argument");
bDoSelect(c,true,false,false);
}
static void bSelectSingletons(Context *c) {
memset(c->curfv->selected,0,c->curfv->map->enccount);
bDoSelect(c,true,true,false);
}
static void bSelectSingletonsIf(Context *c) {
memset(c->curfv->selected,0,c->curfv->map->enccount);
c->return_val.type = v_int;
c->return_val.u.ival = bDoSelect(c,false,true,false);
}
static void bSelectAllInstancesOf(Context *c) {
int i,j,gid;
SplineChar *sc;
FontViewBase *fv = c->curfv;
EncMap *map = fv->map;
SplineFont *sf = fv->sf;
struct altuni *alt;
memset(fv->selected,0,map->enccount);
for ( i=1; i<c->a.argc; ++i ) {
if ( c->a.vals[i].type==v_unicode ) {
int uni = c->a.vals[i].u.ival;
for ( j=0; j<map->enccount; ++j ) if ( (gid=map->map[j])!=-1 && (sc=sf->glyphs[gid])!=NULL ) {
for ( alt=sc->altuni; alt!=NULL && alt->unienc!=uni; alt=alt->next );
if ( sc->unicodeenc == uni || alt!=NULL )
fv->selected[j] = true;
}
} else if ( c->a.vals[i].type==v_str ) {
char *name = c->a.vals[i].u.sval;
for ( j=0; j<map->enccount; ++j ) if ( (gid=map->map[j])!=-1 && (sc=sf->glyphs[gid])!=NULL ) {
if ( strcmp(sc->name,name)==0 )
fv->selected[j] = true;
}
} else
ScriptError( c, "Bad type for argument");
}
}
static void bSelectIf(Context *c) {
memset(c->curfv->selected,0,c->curfv->map->enccount);
c->return_val.type = v_int;
c->return_val.u.ival = bDoSelect(c,false,true,true);
}
static void bSelectChanged(Context *c) {
int i, gid;
FontViewBase *fv = c->curfv;
EncMap *map = fv->map;
SplineFont *sf = fv->sf;
int add = 0;
if ( c->a.argc!=1 && c->a.argc!=2 )
ScriptError( c, "Too many arguments");
if ( c->a.argc==2 ) {
if ( c->a.vals[1].type!=v_int )
ScriptError( c, "Bad type for argument" );
add = c->a.vals[1].u.ival;
}
if ( add ) {
for ( i=0; i< map->enccount; ++i )
fv->selected[i] |= ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL && sf->glyphs[gid]->changed );
} else {
for ( i=0; i< map->enccount; ++i )
fv->selected[i] = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL && sf->glyphs[gid]->changed );
}
}
static void bSelectHintingNeeded(Context *c) {
int i, gid;
FontViewBase *fv = c->curfv;
EncMap *map = fv->map;
SplineFont *sf = fv->sf;
int add = 0;
int order2 = sf->layers[ly_fore].order2;
if ( c->a.argc!=1 && c->a.argc!=2 )
ScriptError( c, "Too many arguments");
if ( c->a.argc==2 ) {
if ( c->a.vals[1].type!=v_int )
ScriptError( c, "Bad type for argument" );
add = c->a.vals[1].u.ival;
}
if ( add ) {
for ( i=0; i< map->enccount; ++i )
fv->selected[i] |= ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
((!order2 && sf->glyphs[gid]->changedsincelasthinted ) ||
( order2 && sf->glyphs[gid]->layers[ly_fore].splines!=NULL &&
sf->glyphs[gid]->ttf_instrs_len<=0 )) );
} else {
for ( i=0; i< map->enccount; ++i )
fv->selected[i] = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
((!order2 && sf->glyphs[gid]->changedsincelasthinted ) ||
( order2 && sf->glyphs[gid]->layers[ly_fore].splines!=NULL &&
sf->glyphs[gid]->ttf_instrs_len<=0 )) );
}
}
static void bSelectWorthOutputting(Context *c) {
int i, gid;
FontViewBase *fv = c->curfv;
EncMap *map = fv->map;
SplineFont *sf = fv->sf;
int add = 0;
if ( c->a.argc!=1 && c->a.argc!=2 )
ScriptError( c, "Too many arguments");
if ( c->a.argc==2 ) {
if ( c->a.vals[1].type!=v_int )
ScriptError( c, "Bad type for argument" );
add = c->a.vals[1].u.ival;
}
if ( add ) {
for ( i=0; i< map->enccount; ++i )
fv->selected[i] |= ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
SCWorthOutputting(sf->glyphs[gid]) );
} else {
for ( i=0; i< map->enccount; ++i )
fv->selected[i] = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
SCWorthOutputting(sf->glyphs[gid]) );
}
}
static void bSelectGlyphsSplines(Context *c) {
FontViewBase *fv = c->curfv;
int i, gid;
EncMap *map = fv->map;
SplineFont *sf = fv->sf;
int layer = fv->active_layer;
int add = 0;
if ( c->a.argc!=1 && c->a.argc!=2 )
ScriptError( c, "Too many arguments");
if ( c->a.argc==2 ) {
if ( c->a.vals[1].type!=v_int )
ScriptError( c, "Bad type for argument" );
add = c->a.vals[1].u.ival;
}
if ( add ) {
for ( i=0; i< map->enccount; ++i )
fv->selected[i] |= ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
sf->glyphs[gid]->layers[layer].splines!=NULL );
} else {
for ( i=0; i< map->enccount; ++i )
fv->selected[i] = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
sf->glyphs[gid]->layers[layer].splines!=NULL );
}
}
static void bSelectGlyphsReferences(Context *c) {
FontViewBase *fv = c->curfv;
int i, gid;
EncMap *map = fv->map;
SplineFont *sf = fv->sf;
int layer = fv->active_layer;
int add = 0;
if ( c->a.argc!=1 && c->a.argc!=2 )
ScriptError( c, "Too many arguments");
if ( c->a.argc==2 ) {
if ( c->a.vals[1].type!=v_int )
ScriptError( c, "Bad type for argument" );
add = c->a.vals[1].u.ival;
}
if ( add ) {
for ( i=0; i< map->enccount; ++i )
fv->selected[i] |= ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
sf->glyphs[gid]->layers[layer].refs!=NULL );
} else {
for ( i=0; i< map->enccount; ++i )
fv->selected[i] = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
sf->glyphs[gid]->layers[layer].refs!=NULL);
}
}
static void bSelectGlyphsBoth(Context *c) {
FontViewBase *fv = c->curfv;
int i, gid;
EncMap *map = fv->map;
SplineFont *sf = fv->sf;
int layer = fv->active_layer;
int add = 0;
if ( c->a.argc!=1 && c->a.argc!=2 )
ScriptError( c, "Too many arguments");
if ( c->a.argc==2 ) {
if ( c->a.vals[1].type!=v_int )
ScriptError( c, "Bad type for argument" );
add = c->a.vals[1].u.ival;
}
if ( add ) {
for ( i=0; i< map->enccount; ++i )
fv->selected[i] |= ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
sf->glyphs[gid]->layers[layer].refs!=NULL &&
sf->glyphs[gid]->layers[layer].splines!=NULL );
} else {
for ( i=0; i< map->enccount; ++i )
fv->selected[i] = ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
sf->glyphs[gid]->layers[layer].refs!=NULL &&
sf->glyphs[gid]->layers[layer].splines!=NULL );
}
}
static void bSelectByATT(Context *c) {
ScriptError(c,"This scripting function no longer works. It has been replace by SelectByPosSub");
}
static void bSelectByPosSub(Context *c) {
struct lookup_subtable *sub;
if ( c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments");
else if ( c->a.vals[1].type!=v_str ||
c->a.vals[2].type!=v_int )
ScriptError(c,"Bad argument type");
else if ( c->a.vals[2].u.ival<1 || c->a.vals[2].u.ival>3 )
ScriptError(c,"Bad argument value");
sub = SFFindLookupSubtable(c->curfv->sf,c->a.vals[1].u.sval);
if ( sub==NULL )
ScriptErrorString(c,"Unknown lookup subtable",c->a.vals[1].u.sval);
c->return_val.type = v_int;
c->return_val.u.ival = FVBParseSelectByPST(c->curfv,sub,c->a.vals[2].u.ival);
}
static void bSelectByColor(Context *c) {
int col, sccol;
int i;
EncMap *map = c->curfv->map;
SplineFont *sf = c->curfv->sf;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments");
else if ( c->a.vals[1].type!=v_str && c->a.vals[1].type!=v_int )
ScriptError(c,"Bad argument type");
if ( c->a.vals[1].type==v_int )
col = c->a.vals[1].u.ival;
else {
if ( strmatch(c->a.vals[1].u.sval,"Red")==0 )
col = 0xff0000;
else if ( strmatch(c->a.vals[1].u.sval,"Green")==0 )
col = 0x00ff00;
else if ( strmatch(c->a.vals[1].u.sval,"Blue")==0 )
col = 0x0000ff;
else if ( strmatch(c->a.vals[1].u.sval,"Magenta")==0 )
col = 0xff00ff;
else if ( strmatch(c->a.vals[1].u.sval,"Cyan")==0 )
col = 0x00ffff;
else if ( strmatch(c->a.vals[1].u.sval,"Yellow")==0 )
col = 0xffff00;
else if ( strmatch(c->a.vals[1].u.sval,"White")==0 )
col = 0xffffff;
else if ( strmatch(c->a.vals[1].u.sval,"none")==0 ||
strmatch(c->a.vals[1].u.sval,"Default")==0 )
col = COLOR_DEFAULT;
else
ScriptErrorString(c,"Unknown color", c->a.vals[1].u.sval);
}
for ( i=0; i<map->enccount; ++i ) {
int gid = map->map[i];
if ( gid!=-1 ) {
sccol = ( sf->glyphs[gid]==NULL ) ? COLOR_DEFAULT : sf->glyphs[gid]->color;
if ( c->curfv->selected[i]!=(sccol==col) )
c->curfv->selected[i] = !c->curfv->selected[i];
}
}
}
/* **** Element Menu **** */
static void bReencode(Context *c) {
Encoding *new_enc;
int force = 0;
int ret;
if ( c->a.argc!=2 && c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments");
else if ( c->a.vals[1].type!=v_str || ( c->a.argc==3 && c->a.vals[2].type!=v_int ))
ScriptError(c,"Bad argument type");
if ( c->a.argc==3 )
force = c->a.vals[2].u.ival;
ret = SFReencode(c->curfv->sf, c->a.vals[1].u.sval, force);
if ( ret==-1 )
ScriptErrorString(c,"Unknown encoding", c->a.vals[1].u.sval);
}
static void bRenameGlyphs(Context *c) {
NameList *nl;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments");
else if ( c->a.vals[1].type!=v_str )
ScriptError(c,"Bad argument type");
nl = NameListByName(c->a.vals[1].u.sval);
if ( nl==NULL )
ScriptErrorString(c,"Unknown namelist", c->a.vals[1].u.sval);
SFRenameGlyphsToNamelist(c->curfv->sf,nl);
}
static void bSetCharCnt(Context *c) {
EncMap *map = c->curfv->map;
int newcnt;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments");
else if ( c->a.vals[1].type!=v_int )
ScriptError(c,"Bad argument type");
else if ( c->a.vals[1].u.ival<=0 || c->a.vals[1].u.ival>10*65536 )
ScriptError(c,"Argument out of bounds");
newcnt = c->a.vals[1].u.ival;
if ( map->enccount==newcnt )
return;
if ( newcnt<map->enc->char_cnt ) {
map->enc = &custom;
if ( !no_windowing_ui )
FVSetTitles(c->curfv->sf);
} else {
c->curfv->selected = realloc(c->curfv->selected,newcnt);
if ( newcnt>map->encmax ) {
memset(c->curfv->selected+map->enccount,0,newcnt-map->enccount);
map->map = realloc(map->map,(map->encmax=newcnt+10)*sizeof(int32));
memset(map->map+map->enccount,-1,(newcnt-map->enccount)*sizeof(int32));
}
}
map->enccount = newcnt;
if ( !no_windowing_ui )
FontViewReformatOne(c->curfv);
c->curfv->sf->changed = true;
c->curfv->sf->changed_since_autosave = true;
c->curfv->sf->changed_since_xuidchanged = true;
}
static void bDetachGlyphs(Context *c) {
FontViewBase *fv = c->curfv;
FVDetachGlyphs(fv);
}
static void bDetachAndRemoveGlyphs(Context *c) {
FontViewBase *fv = c->curfv;
FVDetachAndRemoveGlyphs( fv);
}
static void bRemoveDetachedGlyphs(Context *c) {
FontViewBase *fv = c->curfv;
int i, gid;
EncMap *map = fv->map;
SplineFont *sf = fv->sf;
SplineChar *sc;
int changed = false;
for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( sf->glyphs[gid]!=NULL )
sf->glyphs[gid]->ticked = false;
for ( i=0; i<map->enccount; ++i ) if ( (gid=map->map[i])!=-1 )
sf->glyphs[gid]->ticked = true;
for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( (sc=sf->glyphs[gid])!=NULL && !sc->ticked ) {
SFRemoveGlyph(sf,sc);
changed = true;
}
if ( changed && !sf->changed ) {
fv->sf->changed = true;
}
}
static void bLoadTableFromFile(Context *c) {
SplineFont *sf = c->curfv->sf;
uint32 tag;
char *tstr, *end;
struct ttf_table *tab;
FILE *file;
struct stat statb;
char *t; char *locfilename;
if ( c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments");
else if ( c->a.vals[1].type!=v_str && c->a.vals[2].type!=v_str )
ScriptError(c,"Bad argument type");
tstr = c->a.vals[1].u.sval;
end = tstr+strlen(tstr);
if ( *tstr=='\0' || end-tstr>4 )
ScriptError(c, "Bad tag");
tag = *tstr<<24;
tag |= (tstr+1<end ? tstr[1] : ' ')<<16;
tag |= (tstr+2<end ? tstr[2] : ' ')<<8 ;
tag |= (tstr+3<end ? tstr[3] : ' ') ;
t = script2utf8_copy(c->a.vals[2].u.sval);
locfilename = utf82def_copy(t);
file = fopen(locfilename,"rb");
free(locfilename); free(t);
if ( file==NULL )
ScriptErrorString(c,"Could not open file: ", c->a.vals[2].u.sval );
if ( fstat(fileno(file),&statb)==-1 )
ScriptErrorString(c,"fstat() failed on: ", c->a.vals[2].u.sval );
for ( tab=sf->ttf_tab_saved; tab!=NULL && tab->tag!=tag; tab=tab->next );
if ( tab==NULL ) {
tab = chunkalloc(sizeof(struct ttf_table));
tab->tag = tag;
tab->next = sf->ttf_tab_saved;
sf->ttf_tab_saved = tab;
} else
free(tab->data);
tab->data = malloc(statb.st_size);
tab->len = fread(tab->data,1,statb.st_size,file);
fclose(file);
}
static void bSaveTableToFile(Context *c) {
SplineFont *sf = c->curfv->sf;
uint32 tag;
char *tstr, *end;
struct ttf_table *tab;
FILE *file;
char *t; char *locfilename;
if ( c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments");
else if ( c->a.vals[1].type!=v_str && c->a.vals[2].type!=v_str )
ScriptError(c,"Bad argument type");
tstr = c->a.vals[1].u.sval;
end = tstr+strlen(tstr);
if ( *tstr=='\0' || end-tstr>4 )
ScriptError(c, "Bad tag");
tag = *tstr<<24;
tag |= (tstr+1<end ? tstr[1] : ' ')<<16;
tag |= (tstr+2<end ? tstr[2] : ' ')<<8 ;
tag |= (tstr+3<end ? tstr[3] : ' ') ;
t = script2utf8_copy(c->a.vals[2].u.sval);
locfilename = utf82def_copy(t);
file = fopen(locfilename,"wb");
free(locfilename); free(t);
if ( file==NULL )
ScriptErrorString(c,"Could not open file: ", c->a.vals[2].u.sval );
for ( tab=sf->ttf_tab_saved; tab!=NULL && tab->tag!=tag; tab=tab->next );
if ( tab==NULL )
ScriptErrorString(c,"No preserved table matches tag: ", tstr );
fwrite(tab->data,1,tab->len,file);
fclose(file);
}
static void bRemovePreservedTable(Context *c) {
SplineFont *sf = c->curfv->sf;
uint32 tag;
char *tstr, *end;
struct ttf_table *tab, *prev;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments");
else if ( c->a.vals[1].type!=v_str )
ScriptError(c,"Bad argument type");
tstr = c->a.vals[1].u.sval;
end = tstr+strlen(tstr);
if ( *tstr=='\0' || end-tstr>4 )
ScriptError(c, "Bad tag");
tag = *tstr<<24;
tag |= (tstr+1<end ? tstr[1] : ' ')<<16;
tag |= (tstr+2<end ? tstr[2] : ' ')<<8 ;
tag |= (tstr+3<end ? tstr[3] : ' ') ;
for ( tab=sf->ttf_tab_saved, prev=NULL; tab!=NULL && tab->tag!=tag; prev=tab, tab=tab->next );
if ( tab==NULL )
ScriptErrorString(c,"No preserved table matches tag: ", tstr );
if ( prev==NULL )
sf->ttf_tab_saved = tab->next;
else
prev->next = tab->next;
free(tab->data);
chunkfree(tab,sizeof(*tab));
}
static void bHasPreservedTable(Context *c) {
SplineFont *sf = c->curfv->sf;
uint32 tag;
char *tstr, *end;
struct ttf_table *tab;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments");
else if ( c->a.vals[1].type!=v_str )
ScriptError(c,"Bad argument type");
tstr = c->a.vals[1].u.sval;
end = tstr+strlen(tstr);
if ( *tstr=='\0' || end-tstr>4 )
ScriptError(c, "Bad tag");
tag = *tstr<<24;
tag |= (tstr+1<end ? tstr[1] : ' ')<<16;
tag |= (tstr+2<end ? tstr[2] : ' ')<<8 ;
tag |= (tstr+3<end ? tstr[3] : ' ') ;
for ( tab=sf->ttf_tab_saved; tab!=NULL && tab->tag!=tag; tab=tab->next );
c->return_val.type = v_int;
c->return_val.u.ival = (tab!=NULL);
}
static void bLoadEncodingFile(Context *c) {
char *t; char *locfilename;
if ( c->a.argc != 2 && c->a.argc != 3 )
ScriptError( c, "Wrong number of arguments");
else if ((c->a.vals[1].type!=v_str ) ||
(c->a.argc >= 3 && c->a.vals[2].type !=v_str))
ScriptError(c,"Bad argument type");
t = script2utf8_copy(c->a.vals[1].u.sval);
locfilename = utf82def_copy(t);
ParseEncodingFile(locfilename, (c->a.argc>=3 ? c->a.vals[2].u.sval : NULL));
free(locfilename); free(t);
/*DumpPfaEditEncodings();*/
}
static void bSetFontOrder(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments");
else if ( c->a.vals[1].type!=v_int )
ScriptError(c,"Bad argument type");
else if ( c->a.vals[1].u.ival!=2 && c->a.vals[1].u.ival!=3 )
ScriptError(c,"Order must be 2 or 3");
c->return_val.type = v_int;
c->return_val.u.ival = c->curfv->sf->layers[ly_fore].order2?2:3;
if ( c->a.vals[1].u.ival==(c->curfv->sf->layers[ly_fore].order2?2:3))
/* No Op */;
else {
if ( c->a.vals[1].u.ival==2 ) {
SFCloseAllInstrs(c->curfv->sf);
SFConvertToOrder2(c->curfv->sf);
} else
SFConvertToOrder3(c->curfv->sf);
}
}
static void bSetFontHasVerticalMetrics(Context *c) {
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments");
else if ( c->a.vals[1].type!=v_int )
ScriptError(c,"Bad argument type");
c->return_val.type = v_int;
c->return_val.u.ival = c->curfv->sf->hasvmetrics;
c->curfv->sf->hasvmetrics = (c->a.vals[1].u.ival!=0);
}
static void bSetGasp(Context *c) {
int i, base;
struct array *arr;
SplineFont *sf = c->curfv->sf;
if ( c->a.argc==2 && (c->a.vals[1].type==v_arr || c->a.vals[1].type==v_arrfree)) {
arr = c->a.vals[1].u.aval;
if ( arr->argc&1 )
ScriptError( c, "Bad array size");
base = 0;
} else if ( (c->a.argc&1)==0 )
ScriptError( c, "Wrong number of arguments");
else {
arr = &c->a;
base = 1;
}
for ( i=base; i<arr->argc; i += 2 ) {
if ( arr->vals[i].type!=v_int || arr->vals[i+1].type!=v_int )
ScriptError(c,"Bad argument type");
if ( arr->vals[i].u.ival<=0 || arr->vals[i].u.ival>65535 )
ScriptError(c,"'gasp' Pixel size out of range");
if ( i!=base && arr->vals[i].u.ival<=arr->vals[i-2].u.ival )
ScriptError(c,"'gasp' Pixel size out of order");
if ( arr->vals[i+1].u.ival<0 || arr->vals[i+1].u.ival>15 )
ScriptError(c,"'gasp' flag out of range");
if ( arr->vals[i+1].u.ival>3 )
sf->gasp_version=1;
}
if ( arr->argc>=2 && arr->vals[arr->argc-2].u.ival!=65535 )
ScriptError(c,"'gasp' Final pixel size must be 65535");
free(sf->gasp);
sf->gasp_cnt = (arr->argc-base)/2;
if ( sf->gasp_cnt!=0 ) {
sf->gasp = calloc(sf->gasp_cnt,sizeof(struct gasp));
for ( i=base; i<arr->argc; i += 2 ) {
int g = (i-base)/2;
sf->gasp[g].ppem = arr->vals[i].u.ival;
sf->gasp[g].flags = arr->vals[i+1].u.ival;
}
} else
sf->gasp = NULL;
}
static void _SetFontNames(Context *c,SplineFont *sf) {
int i;
if ( c->a.argc==1 || c->a.argc>7 )
ScriptError( c, "Wrong number of arguments");
for ( i=1; i<c->a.argc; ++i )
if ( c->a.vals[i].type!=v_str )
ScriptError(c,"Bad argument type");
if ( *c->a.vals[1].u.sval!='\0' ) {
free(sf->fontname);
sf->fontname = forcePSName_copy(c,c->a.vals[1].u.sval);
}
if ( c->a.argc>2 && *c->a.vals[2].u.sval!='\0' ) {
free(sf->familyname);
sf->familyname = script2latin1_copy(c->a.vals[2].u.sval);
}
if ( c->a.argc>3 && *c->a.vals[3].u.sval!='\0' ) {
free(sf->fullname);
sf->fullname = script2latin1_copy(c->a.vals[3].u.sval);
}
if ( c->a.argc>4 && *c->a.vals[4].u.sval!='\0' ) {
free(sf->weight);
sf->weight = script2latin1_copy(c->a.vals[4].u.sval);
}
if ( c->a.argc>5 && *c->a.vals[5].u.sval!='\0' ) {
free(sf->copyright);
sf->copyright = script2latin1_copy(c->a.vals[5].u.sval);
}
if ( c->a.argc>6 && *c->a.vals[6].u.sval!='\0' ) {
free(sf->version);
sf->version = script2latin1_copy(c->a.vals[6].u.sval);
}
SFReplaceFontnameBDFProps(c->curfv->sf);
}
static void bSetFontNames(Context *c) {
SplineFont *sf = c->curfv->sf;
_SetFontNames(c,sf);
}
static void bSetFondName(Context *c) {
SplineFont *sf = c->curfv->sf;
if ( c->a.argc!=2 )
ScriptError( c, "Wrong number of arguments");
if ( c->a.vals[1].type!=v_str )
ScriptError(c,"Bad argument type");
if ( *c->a.vals[1].u.sval!='\0' ) {
free(sf->fondname);
sf->fondname = forceASCIIcopy(c,c->a.vals[1].u.sval);
}
}
static void bSetTTFName(Context *c) {
SplineFont *sf = c->curfv->sf;
char *u;
int lang, strid;
struct ttflangname *prev, *ln;
if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
if ( c->a.argc!=4 )
ScriptError( c, "Wrong number of arguments");
else if ( c->a.vals[1].type!=v_int || c->a.vals[2].type!=v_int ||
c->a.vals[3].type!=v_str )
ScriptError(c,"Bad argument type");
lang = c->a.vals[1].u.ival;
strid = c->a.vals[2].u.ival;
if ( lang<0 || lang>0xffff )
ScriptError(c,"Bad value for language");
else if ( strid<0 || strid>=ttf_namemax )
ScriptError(c,"Bad value for string id");
u = copy(c->a.vals[3].u.sval);
if ( *u=='\0' ) {
free(u);
u = NULL;
}
for ( ln = sf->names; ln!=NULL && ln->lang!=lang; ln = ln->next );
if ( ln==NULL ) {
if ( u==NULL )
return;
for ( prev = NULL, ln = sf->names; ln!=NULL && ln->lang<lang; prev = ln, ln = ln->next );
ln = chunkalloc(sizeof(struct ttflangname));
ln->lang = lang;
if ( prev==NULL ) { ln->next = sf->names; sf->names = ln; }
else { ln->next = prev->next; prev->next = ln; }
}
free(ln->names[strid]);
ln->names[strid] = u;
}
static void bGetTTFName(Context *c) {
SplineFont *sf = c->curfv->sf;
int lang, strid;
struct ttflangname *ln;
if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
if ( c->a.argc!=3 )
ScriptError( c, "Wrong number of arguments");