|
Packit |
2bba5f |
/*
|
|
Packit |
2bba5f |
Copyright (c) 1998-2001 by Juliusz Chroboczek
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
Packit |
2bba5f |
of this software and associated documentation files (the "Software"), to deal
|
|
Packit |
2bba5f |
in the Software without restriction, including without limitation the rights
|
|
Packit |
2bba5f |
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
Packit |
2bba5f |
copies of the Software, and to permit persons to whom the Software is
|
|
Packit |
2bba5f |
furnished to do so, subject to the following conditions:
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
The above copyright notice and this permission notice shall be included in
|
|
Packit |
2bba5f |
all copies or substantial portions of the Software.
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
Packit |
2bba5f |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
Packit |
2bba5f |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
Packit |
2bba5f |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
Packit |
2bba5f |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
Packit |
2bba5f |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
Packit |
2bba5f |
THE SOFTWARE.
|
|
Packit |
2bba5f |
*/
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* Parser for encoding files */
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* This code assumes that we are using ASCII. We don't use the ctype
|
|
Packit |
2bba5f |
functions, as they depend on the current locale. On the other
|
|
Packit |
2bba5f |
hand, we do use strcasecmp, but only on strings that we've checked
|
|
Packit |
2bba5f |
to be pure ASCII. Bloody ``Code Set Independence''. */
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
#include <string.h>
|
|
Packit |
2bba5f |
#include <strings.h>
|
|
Packit |
2bba5f |
#include <stdio.h>
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
#include <stdlib.h>
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
#include "zlib.h"
|
|
Packit |
2bba5f |
typedef gzFile FontFilePtr;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
#define FontFileGetc(f) gzgetc(f)
|
|
Packit |
2bba5f |
#define FontFileOpen(filename) gzopen(filename, "rb")
|
|
Packit |
2bba5f |
#define FontFileClose(f) gzclose(f)
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
#define MAXFONTFILENAMELEN 1024
|
|
Packit |
2bba5f |
#define MAXFONTNAMELEN 1024
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
#include <X11/fonts/fontenc.h>
|
|
Packit |
2bba5f |
#include "fontencI.h"
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
#define MAXALIASES 20
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
#define EOF_TOKEN -1
|
|
Packit |
2bba5f |
#define ERROR_TOKEN -2
|
|
Packit |
2bba5f |
#define EOL_TOKEN 0
|
|
Packit |
2bba5f |
#define NUMBER_TOKEN 1
|
|
Packit |
2bba5f |
#define KEYWORD_TOKEN 2
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
#define EOF_LINE -1
|
|
Packit |
2bba5f |
#define ERROR_LINE -2
|
|
Packit |
2bba5f |
#define STARTENCODING_LINE 1
|
|
Packit |
2bba5f |
#define STARTMAPPING_LINE 2
|
|
Packit |
2bba5f |
#define ENDMAPPING_LINE 3
|
|
Packit |
2bba5f |
#define CODE_LINE 4
|
|
Packit |
2bba5f |
#define CODE_RANGE_LINE 5
|
|
Packit |
2bba5f |
#define CODE_UNDEFINE_LINE 6
|
|
Packit |
2bba5f |
#define NAME_LINE 7
|
|
Packit |
2bba5f |
#define SIZE_LINE 8
|
|
Packit |
2bba5f |
#define ALIAS_LINE 9
|
|
Packit |
2bba5f |
#define FIRSTINDEX_LINE 10
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* Return from lexer */
|
|
Packit |
2bba5f |
#define MAXKEYWORDLEN 100
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
static long number_value;
|
|
Packit |
2bba5f |
static char keyword_value[MAXKEYWORDLEN + 1];
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
static long value1, value2, value3;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* Lexer code */
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* Skip to the beginning of new line */
|
|
Packit |
2bba5f |
static void
|
|
Packit |
2bba5f |
skipEndOfLine(FontFilePtr f, int c)
|
|
Packit |
2bba5f |
{
|
|
Packit |
2bba5f |
if (c == 0)
|
|
Packit |
2bba5f |
c = FontFileGetc(f);
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
for (;;)
|
|
Packit |
2bba5f |
if (c <= 0 || c == '\n')
|
|
Packit |
2bba5f |
return;
|
|
Packit |
2bba5f |
else
|
|
Packit |
2bba5f |
c = FontFileGetc(f);
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* Get a number; we're at the first digit. */
|
|
Packit |
2bba5f |
static unsigned
|
|
Packit |
2bba5f |
getnum(FontFilePtr f, int c, int *cp)
|
|
Packit |
2bba5f |
{
|
|
Packit |
2bba5f |
unsigned n = 0;
|
|
Packit |
2bba5f |
int base = 10;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* look for `0' or `0x' prefix */
|
|
Packit |
2bba5f |
if (c == '0') {
|
|
Packit |
2bba5f |
c = FontFileGetc(f);
|
|
Packit |
2bba5f |
base = 8;
|
|
Packit |
2bba5f |
if (c == 'x' || c == 'X') {
|
|
Packit |
2bba5f |
base = 16;
|
|
Packit |
2bba5f |
c = FontFileGetc(f);
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* accumulate digits */
|
|
Packit |
2bba5f |
for (;;) {
|
|
Packit |
2bba5f |
if ('0' <= c && c <= '9') {
|
|
Packit |
2bba5f |
n *= base;
|
|
Packit |
2bba5f |
n += c - '0';
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if ('a' <= c && c <= 'f') {
|
|
Packit |
2bba5f |
n *= base;
|
|
Packit |
2bba5f |
n += c - 'a' + 10;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if ('A' <= c && c <= 'F') {
|
|
Packit |
2bba5f |
n *= base;
|
|
Packit |
2bba5f |
n += c - 'A' + 10;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else
|
|
Packit |
2bba5f |
break;
|
|
Packit |
2bba5f |
c = FontFileGetc(f);
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
*cp = c;
|
|
Packit |
2bba5f |
return n;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* Skip to beginning of new line; return 1 if only whitespace was found. */
|
|
Packit |
2bba5f |
static int
|
|
Packit |
2bba5f |
endOfLine(FontFilePtr f, int c)
|
|
Packit |
2bba5f |
{
|
|
Packit |
2bba5f |
if (c == 0)
|
|
Packit |
2bba5f |
c = FontFileGetc(f);
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
for (;;) {
|
|
Packit |
2bba5f |
if (c <= 0 || c == '\n')
|
|
Packit |
2bba5f |
return 1;
|
|
Packit |
2bba5f |
else if (c == '#') {
|
|
Packit |
2bba5f |
skipEndOfLine(f, c);
|
|
Packit |
2bba5f |
return 1;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if (c == ' ' || c == '\t') {
|
|
Packit |
2bba5f |
skipEndOfLine(f, c);
|
|
Packit |
2bba5f |
return 0;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
c = FontFileGetc(f);
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* Get a token; we're at first char */
|
|
Packit |
2bba5f |
static int
|
|
Packit |
2bba5f |
gettoken(FontFilePtr f, int c, int *cp)
|
|
Packit |
2bba5f |
{
|
|
Packit |
2bba5f |
char *p;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
if (c <= 0)
|
|
Packit |
2bba5f |
c = FontFileGetc(f);
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
if (c <= 0) {
|
|
Packit |
2bba5f |
return EOF_TOKEN;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
while (c == ' ' || c == '\t')
|
|
Packit |
2bba5f |
c = FontFileGetc(f);
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
if (c == '\n') {
|
|
Packit |
2bba5f |
return EOL_TOKEN;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if (c == '#') {
|
|
Packit |
2bba5f |
skipEndOfLine(f, c);
|
|
Packit |
2bba5f |
return EOL_TOKEN;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if (c >= '0' && c <= '9') {
|
|
Packit |
2bba5f |
number_value = getnum(f, c, cp);
|
|
Packit |
2bba5f |
return NUMBER_TOKEN;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if ((c >= 'A' && c <= 'Z') ||
|
|
Packit |
2bba5f |
(c >= 'a' && c <= 'z') ||
|
|
Packit |
2bba5f |
c == '/' || c == '_' || c == '-' || c == '.') {
|
|
Packit |
2bba5f |
p = keyword_value;
|
|
Packit |
2bba5f |
*p++ = c;
|
|
Packit |
2bba5f |
while (p - keyword_value < MAXKEYWORDLEN) {
|
|
Packit |
2bba5f |
c = FontFileGetc(f);
|
|
Packit |
2bba5f |
if (c <= ' ' || c > '~' || c == '#')
|
|
Packit |
2bba5f |
break;
|
|
Packit |
2bba5f |
*p++ = c;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
*cp = c;
|
|
Packit |
2bba5f |
*p = '\0';
|
|
Packit |
2bba5f |
return KEYWORD_TOKEN;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else {
|
|
Packit |
2bba5f |
*cp = c;
|
|
Packit |
2bba5f |
return ERROR_TOKEN;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* Parse a line.
|
|
Packit |
2bba5f |
* Always skips to the beginning of a new line, even if an error occurs */
|
|
Packit |
2bba5f |
static int
|
|
Packit |
2bba5f |
getnextline(FontFilePtr f)
|
|
Packit |
2bba5f |
{
|
|
Packit |
2bba5f |
int c, token;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
c = FontFileGetc(f);
|
|
Packit |
2bba5f |
if (c <= 0)
|
|
Packit |
2bba5f |
return EOF_LINE;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
again:
|
|
Packit |
2bba5f |
token = gettoken(f, c, &c);
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
switch (token) {
|
|
Packit |
2bba5f |
case EOF_TOKEN:
|
|
Packit |
2bba5f |
return EOF_LINE;
|
|
Packit |
2bba5f |
case EOL_TOKEN:
|
|
Packit |
2bba5f |
/* empty line */
|
|
Packit |
2bba5f |
c = FontFileGetc(f);
|
|
Packit |
2bba5f |
goto again;
|
|
Packit |
2bba5f |
case NUMBER_TOKEN:
|
|
Packit |
2bba5f |
value1 = number_value;
|
|
Packit |
2bba5f |
token = gettoken(f, c, &c);
|
|
Packit |
2bba5f |
switch (token) {
|
|
Packit |
2bba5f |
case NUMBER_TOKEN:
|
|
Packit |
2bba5f |
value2 = number_value;
|
|
Packit |
2bba5f |
token = gettoken(f, c, &c);
|
|
Packit |
2bba5f |
switch (token) {
|
|
Packit |
2bba5f |
case NUMBER_TOKEN:
|
|
Packit |
2bba5f |
value3 = number_value;
|
|
Packit |
2bba5f |
return CODE_RANGE_LINE;
|
|
Packit |
2bba5f |
case EOL_TOKEN:
|
|
Packit |
2bba5f |
return CODE_LINE;
|
|
Packit |
2bba5f |
default:
|
|
Packit |
2bba5f |
skipEndOfLine(f, c);
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
case KEYWORD_TOKEN:
|
|
Packit |
2bba5f |
if (!endOfLine(f, c))
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
else
|
|
Packit |
2bba5f |
return NAME_LINE;
|
|
Packit |
2bba5f |
default:
|
|
Packit |
2bba5f |
skipEndOfLine(f, c);
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
case KEYWORD_TOKEN:
|
|
Packit |
2bba5f |
if (!strcasecmp(keyword_value, "STARTENCODING")) {
|
|
Packit |
2bba5f |
token = gettoken(f, c, &c);
|
|
Packit |
2bba5f |
if (token == KEYWORD_TOKEN) {
|
|
Packit |
2bba5f |
if (endOfLine(f, c))
|
|
Packit |
2bba5f |
return STARTENCODING_LINE;
|
|
Packit |
2bba5f |
else
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else {
|
|
Packit |
2bba5f |
skipEndOfLine(f, c);
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if (!strcasecmp(keyword_value, "ALIAS")) {
|
|
Packit |
2bba5f |
token = gettoken(f, c, &c);
|
|
Packit |
2bba5f |
if (token == KEYWORD_TOKEN) {
|
|
Packit |
2bba5f |
if (endOfLine(f, c))
|
|
Packit |
2bba5f |
return ALIAS_LINE;
|
|
Packit |
2bba5f |
else
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else {
|
|
Packit |
2bba5f |
skipEndOfLine(f, c);
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if (!strcasecmp(keyword_value, "SIZE")) {
|
|
Packit |
2bba5f |
token = gettoken(f, c, &c);
|
|
Packit |
2bba5f |
if (token == NUMBER_TOKEN) {
|
|
Packit |
2bba5f |
value1 = number_value;
|
|
Packit |
2bba5f |
token = gettoken(f, c, &c);
|
|
Packit |
2bba5f |
switch (token) {
|
|
Packit |
2bba5f |
case NUMBER_TOKEN:
|
|
Packit |
2bba5f |
value2 = number_value;
|
|
Packit |
2bba5f |
return SIZE_LINE;
|
|
Packit |
2bba5f |
case EOL_TOKEN:
|
|
Packit |
2bba5f |
value2 = 0;
|
|
Packit |
2bba5f |
return SIZE_LINE;
|
|
Packit |
2bba5f |
default:
|
|
Packit |
2bba5f |
skipEndOfLine(f, c);
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else {
|
|
Packit |
2bba5f |
skipEndOfLine(f, c);
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if (!strcasecmp(keyword_value, "FIRSTINDEX")) {
|
|
Packit |
2bba5f |
token = gettoken(f, c, &c);
|
|
Packit |
2bba5f |
if (token == NUMBER_TOKEN) {
|
|
Packit |
2bba5f |
value1 = number_value;
|
|
Packit |
2bba5f |
token = gettoken(f, c, &c);
|
|
Packit |
2bba5f |
switch (token) {
|
|
Packit |
2bba5f |
case NUMBER_TOKEN:
|
|
Packit |
2bba5f |
value2 = number_value;
|
|
Packit |
2bba5f |
return FIRSTINDEX_LINE;
|
|
Packit |
2bba5f |
case EOL_TOKEN:
|
|
Packit |
2bba5f |
value2 = 0;
|
|
Packit |
2bba5f |
return FIRSTINDEX_LINE;
|
|
Packit |
2bba5f |
default:
|
|
Packit |
2bba5f |
skipEndOfLine(f, c);
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else {
|
|
Packit |
2bba5f |
skipEndOfLine(f, c);
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if (!strcasecmp(keyword_value, "STARTMAPPING")) {
|
|
Packit |
2bba5f |
keyword_value[0] = 0;
|
|
Packit |
2bba5f |
value1 = 0;
|
|
Packit |
2bba5f |
value2 = 0;
|
|
Packit |
2bba5f |
/* first a keyword */
|
|
Packit |
2bba5f |
token = gettoken(f, c, &c);
|
|
Packit |
2bba5f |
if (token != KEYWORD_TOKEN) {
|
|
Packit |
2bba5f |
skipEndOfLine(f, c);
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* optional first integer */
|
|
Packit |
2bba5f |
token = gettoken(f, c, &c);
|
|
Packit |
2bba5f |
if (token == NUMBER_TOKEN) {
|
|
Packit |
2bba5f |
value1 = number_value;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if (token == EOL_TOKEN) {
|
|
Packit |
2bba5f |
return STARTMAPPING_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else {
|
|
Packit |
2bba5f |
skipEndOfLine(f, c);
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* optional second integer */
|
|
Packit |
2bba5f |
token = gettoken(f, c, &c);
|
|
Packit |
2bba5f |
if (token == NUMBER_TOKEN) {
|
|
Packit |
2bba5f |
value2 = number_value;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if (token == EOL_TOKEN) {
|
|
Packit |
2bba5f |
return STARTMAPPING_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else {
|
|
Packit |
2bba5f |
skipEndOfLine(f, c);
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
if (!endOfLine(f, c))
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
else {
|
|
Packit |
2bba5f |
return STARTMAPPING_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if (!strcasecmp(keyword_value, "UNDEFINE")) {
|
|
Packit |
2bba5f |
/* first integer */
|
|
Packit |
2bba5f |
token = gettoken(f, c, &c);
|
|
Packit |
2bba5f |
if (token != NUMBER_TOKEN) {
|
|
Packit |
2bba5f |
skipEndOfLine(f, c);
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
value1 = number_value;
|
|
Packit |
2bba5f |
/* optional second integer */
|
|
Packit |
2bba5f |
token = gettoken(f, c, &c);
|
|
Packit |
2bba5f |
if (token == EOL_TOKEN) {
|
|
Packit |
2bba5f |
value2 = value1;
|
|
Packit |
2bba5f |
return CODE_UNDEFINE_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if (token == NUMBER_TOKEN) {
|
|
Packit |
2bba5f |
value2 = number_value;
|
|
Packit |
2bba5f |
if (endOfLine(f, c)) {
|
|
Packit |
2bba5f |
return CODE_UNDEFINE_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else {
|
|
Packit |
2bba5f |
skipEndOfLine(f, c);
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if (!strcasecmp(keyword_value, "ENDENCODING")) {
|
|
Packit |
2bba5f |
if (endOfLine(f, c))
|
|
Packit |
2bba5f |
return EOF_LINE;
|
|
Packit |
2bba5f |
else
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if (!strcasecmp(keyword_value, "ENDMAPPING")) {
|
|
Packit |
2bba5f |
if (endOfLine(f, c))
|
|
Packit |
2bba5f |
return ENDMAPPING_LINE;
|
|
Packit |
2bba5f |
else
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else {
|
|
Packit |
2bba5f |
skipEndOfLine(f, c);
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
default:
|
|
Packit |
2bba5f |
return ERROR_LINE;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
static void
|
|
Packit |
2bba5f |
install_mapping(FontEncPtr encoding, FontMapPtr mapping)
|
|
Packit |
2bba5f |
{
|
|
Packit |
2bba5f |
FontMapPtr m;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
if (encoding->mappings == NULL)
|
|
Packit |
2bba5f |
encoding->mappings = mapping;
|
|
Packit |
2bba5f |
else {
|
|
Packit |
2bba5f |
m = encoding->mappings;
|
|
Packit |
2bba5f |
while (m->next != NULL)
|
|
Packit |
2bba5f |
m = m->next;
|
|
Packit |
2bba5f |
m->next = mapping;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
mapping->next = NULL;
|
|
Packit |
2bba5f |
mapping->encoding = encoding;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
static int
|
|
Packit |
2bba5f |
setCode(unsigned from, unsigned to, unsigned row_size,
|
|
Packit |
2bba5f |
unsigned *first, unsigned *last,
|
|
Packit |
2bba5f |
unsigned *encsize, unsigned short **enc)
|
|
Packit |
2bba5f |
{
|
|
Packit |
2bba5f |
unsigned index, i;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
unsigned short *newenc;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
if (from > 0xFFFF)
|
|
Packit |
2bba5f |
return 0; /* success */
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
if (row_size == 0)
|
|
Packit |
2bba5f |
index = from;
|
|
Packit |
2bba5f |
else {
|
|
Packit |
2bba5f |
if ((value1 & 0xFF) >= row_size)
|
|
Packit |
2bba5f |
return 0; /* ignore out of range mappings */
|
|
Packit |
2bba5f |
index = (from >> 8) * row_size + (from & 0xFF);
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* Optimize away useless identity mappings. This is only expected
|
|
Packit |
2bba5f |
to be useful with linear encodings. */
|
|
Packit |
2bba5f |
if (index == to && (index < *first || index > *last))
|
|
Packit |
2bba5f |
return 0;
|
|
Packit |
2bba5f |
if (*encsize == 0) {
|
|
Packit |
2bba5f |
*encsize = (index < 256) ? 256 : 0x10000;
|
|
Packit |
2bba5f |
*enc = malloc((*encsize) * sizeof(unsigned short));
|
|
Packit |
2bba5f |
if (*enc == NULL) {
|
|
Packit |
2bba5f |
*encsize = 0;
|
|
Packit |
2bba5f |
return 1;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if (*encsize <= index) {
|
|
Packit |
2bba5f |
*encsize = 0x10000;
|
|
Packit |
2bba5f |
if ((newenc =
|
|
Packit |
2bba5f |
realloc(*enc, (*encsize) * sizeof(unsigned short))) == NULL)
|
|
Packit |
2bba5f |
return 1;
|
|
Packit |
2bba5f |
*enc = newenc;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
if (*first > *last) {
|
|
Packit |
2bba5f |
*first = *last = index;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
if (index < *first) {
|
|
Packit |
2bba5f |
for (i = index; i < *first; i++)
|
|
Packit |
2bba5f |
(*enc)[i] = i;
|
|
Packit |
2bba5f |
*first = index;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
if (index > *last) {
|
|
Packit |
2bba5f |
for (i = *last + 1; i <= index; i++)
|
|
Packit |
2bba5f |
(*enc)[i] = i;
|
|
Packit |
2bba5f |
*last = index;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
(*enc)[index] = to;
|
|
Packit |
2bba5f |
return 0;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* Parser. If headerOnly is true, we're only interested in the
|
|
Packit |
2bba5f |
data contained in the encoding file's header. */
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* As font encodings are currently never freed, the allocations done
|
|
Packit |
2bba5f |
by this function are mostly its private business. Note, however,
|
|
Packit |
2bba5f |
that FontEncIdentify needs to free the header fields -- so if you
|
|
Packit |
2bba5f |
change this function, you may need to change FontEncIdentify. */
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* I want a garbage collector. */
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
static FontEncPtr
|
|
Packit |
2bba5f |
parseEncodingFile(FontFilePtr f, int headerOnly)
|
|
Packit |
2bba5f |
{
|
|
Packit |
2bba5f |
int line;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
unsigned short *enc = NULL;
|
|
Packit |
2bba5f |
char **nam = NULL, **newnam;
|
|
Packit |
2bba5f |
unsigned i, first = 0xFFFF, last = 0, encsize = 0, namsize = 0;
|
|
Packit |
2bba5f |
FontEncPtr encoding = NULL;
|
|
Packit |
2bba5f |
FontMapPtr mapping = NULL;
|
|
Packit |
2bba5f |
FontEncSimpleMapPtr sm;
|
|
Packit |
2bba5f |
FontEncSimpleNamePtr sn;
|
|
Packit |
2bba5f |
char *aliases[MAXALIASES] = { NULL };
|
|
Packit |
2bba5f |
int numaliases = 0;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
#if 0
|
|
Packit |
2bba5f |
/* GCC complains about unused labels. Please fix GCC rather than
|
|
Packit |
2bba5f |
obfuscating my code. */
|
|
Packit |
2bba5f |
no_encoding:
|
|
Packit |
2bba5f |
#endif
|
|
Packit |
2bba5f |
line = getnextline(f);
|
|
Packit |
2bba5f |
switch (line) {
|
|
Packit |
2bba5f |
case EOF_LINE:
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
case STARTENCODING_LINE:
|
|
Packit |
2bba5f |
encoding = malloc(sizeof(FontEncRec));
|
|
Packit |
2bba5f |
if (encoding == NULL)
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
encoding->name = strdup(keyword_value);
|
|
Packit |
2bba5f |
if (encoding->name == NULL)
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
encoding->size = 256;
|
|
Packit |
2bba5f |
encoding->row_size = 0;
|
|
Packit |
2bba5f |
encoding->mappings = NULL;
|
|
Packit |
2bba5f |
encoding->next = NULL;
|
|
Packit |
2bba5f |
encoding->first = encoding->first_col = 0;
|
|
Packit |
2bba5f |
goto no_mapping;
|
|
Packit |
2bba5f |
default:
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
no_mapping:
|
|
Packit |
2bba5f |
line = getnextline(f);
|
|
Packit |
2bba5f |
switch (line) {
|
|
Packit |
2bba5f |
case EOF_LINE:
|
|
Packit |
2bba5f |
goto done;
|
|
Packit |
2bba5f |
case ALIAS_LINE:
|
|
Packit |
2bba5f |
if (numaliases < MAXALIASES) {
|
|
Packit |
2bba5f |
aliases[numaliases] = strdup(keyword_value);
|
|
Packit |
2bba5f |
if (aliases[numaliases] == NULL)
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
numaliases++;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
goto no_mapping;
|
|
Packit |
2bba5f |
case SIZE_LINE:
|
|
Packit |
2bba5f |
encoding->size = value1;
|
|
Packit |
2bba5f |
encoding->row_size = value2;
|
|
Packit |
2bba5f |
goto no_mapping;
|
|
Packit |
2bba5f |
case FIRSTINDEX_LINE:
|
|
Packit |
2bba5f |
encoding->first = value1;
|
|
Packit |
2bba5f |
encoding->first_col = value2;
|
|
Packit |
2bba5f |
goto no_mapping;
|
|
Packit |
2bba5f |
case STARTMAPPING_LINE:
|
|
Packit |
2bba5f |
if (headerOnly)
|
|
Packit |
2bba5f |
goto done;
|
|
Packit |
2bba5f |
if (!strcasecmp(keyword_value, "unicode")) {
|
|
Packit |
2bba5f |
mapping = malloc(sizeof(FontMapRec));
|
|
Packit |
2bba5f |
if (mapping == NULL)
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
mapping->type = FONT_ENCODING_UNICODE;
|
|
Packit |
2bba5f |
mapping->pid = 0;
|
|
Packit |
2bba5f |
mapping->eid = 0;
|
|
Packit |
2bba5f |
mapping->recode = NULL;
|
|
Packit |
2bba5f |
mapping->name = NULL;
|
|
Packit |
2bba5f |
mapping->client_data = NULL;
|
|
Packit |
2bba5f |
mapping->next = NULL;
|
|
Packit |
2bba5f |
goto mapping;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if (!strcasecmp(keyword_value, "cmap")) {
|
|
Packit |
2bba5f |
mapping = malloc(sizeof(FontMapRec));
|
|
Packit |
2bba5f |
if (mapping == NULL)
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
mapping->type = FONT_ENCODING_TRUETYPE;
|
|
Packit |
2bba5f |
mapping->pid = value1;
|
|
Packit |
2bba5f |
mapping->eid = value2;
|
|
Packit |
2bba5f |
mapping->recode = NULL;
|
|
Packit |
2bba5f |
mapping->name = NULL;
|
|
Packit |
2bba5f |
mapping->client_data = NULL;
|
|
Packit |
2bba5f |
mapping->next = NULL;
|
|
Packit |
2bba5f |
goto mapping;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if (!strcasecmp(keyword_value, "postscript")) {
|
|
Packit |
2bba5f |
mapping = malloc(sizeof(FontMapRec));
|
|
Packit |
2bba5f |
if (mapping == NULL)
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
mapping->type = FONT_ENCODING_POSTSCRIPT;
|
|
Packit |
2bba5f |
mapping->pid = 0;
|
|
Packit |
2bba5f |
mapping->eid = 0;
|
|
Packit |
2bba5f |
mapping->recode = NULL;
|
|
Packit |
2bba5f |
mapping->name = NULL;
|
|
Packit |
2bba5f |
mapping->client_data = NULL;
|
|
Packit |
2bba5f |
mapping->next = NULL;
|
|
Packit |
2bba5f |
goto string_mapping;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else { /* unknown mapping type -- ignore */
|
|
Packit |
2bba5f |
goto skipmapping;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
/* NOTREACHED */
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
default:
|
|
Packit |
2bba5f |
goto no_mapping; /* ignore unknown lines */
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
skipmapping:
|
|
Packit |
2bba5f |
line = getnextline(f);
|
|
Packit |
2bba5f |
switch (line) {
|
|
Packit |
2bba5f |
case ENDMAPPING_LINE:
|
|
Packit |
2bba5f |
goto no_mapping;
|
|
Packit |
2bba5f |
case EOF_LINE:
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
default:
|
|
Packit |
2bba5f |
goto skipmapping;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
mapping:
|
|
Packit |
2bba5f |
line = getnextline(f);
|
|
Packit |
2bba5f |
switch (line) {
|
|
Packit |
2bba5f |
case EOF_LINE:
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
case ENDMAPPING_LINE:
|
|
Packit |
2bba5f |
mapping->recode = FontEncSimpleRecode;
|
|
Packit |
2bba5f |
mapping->name = FontEncUndefinedName;
|
|
Packit |
2bba5f |
mapping->client_data = sm = malloc(sizeof(FontEncSimpleMapRec));
|
|
Packit |
2bba5f |
if (sm == NULL)
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
sm->row_size = encoding->row_size;
|
|
Packit |
2bba5f |
if (first <= last) {
|
|
Packit |
2bba5f |
unsigned short *newmap;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
sm->first = first;
|
|
Packit |
2bba5f |
sm->len = last - first + 1;
|
|
Packit |
2bba5f |
newmap = malloc(sm->len * sizeof(unsigned short));
|
|
Packit |
2bba5f |
if (newmap == NULL) {
|
|
Packit |
2bba5f |
free(sm);
|
|
Packit |
2bba5f |
mapping->client_data = sm = NULL;
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
for (i = 0; i < sm->len; i++)
|
|
Packit |
2bba5f |
newmap[i] = enc[first + i];
|
|
Packit |
2bba5f |
sm->map = newmap;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else {
|
|
Packit |
2bba5f |
sm->first = 0;
|
|
Packit |
2bba5f |
sm->len = 0;
|
|
Packit |
2bba5f |
sm->map = NULL;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
install_mapping(encoding, mapping);
|
|
Packit |
2bba5f |
mapping = NULL;
|
|
Packit |
2bba5f |
first = 0xFFFF;
|
|
Packit |
2bba5f |
last = 0;
|
|
Packit |
2bba5f |
goto no_mapping;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
case CODE_LINE:
|
|
Packit |
2bba5f |
if (setCode(value1, value2, encoding->row_size,
|
|
Packit |
2bba5f |
&first, &last, &encsize, &enc))
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
goto mapping;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
case CODE_RANGE_LINE:
|
|
Packit |
2bba5f |
if (value1 > 0x10000)
|
|
Packit |
2bba5f |
value1 = 0x10000;
|
|
Packit |
2bba5f |
if (value2 > 0x10000)
|
|
Packit |
2bba5f |
value2 = 0x10000;
|
|
Packit |
2bba5f |
if (value2 < value1)
|
|
Packit |
2bba5f |
goto mapping;
|
|
Packit |
2bba5f |
/* Do the last value first to avoid having to realloc() */
|
|
Packit |
2bba5f |
if (setCode(value2, value3 + (value2 - value1), encoding->row_size,
|
|
Packit |
2bba5f |
&first, &last, &encsize, &enc))
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
for (i = value1; i < value2; i++) {
|
|
Packit |
2bba5f |
if (setCode(i, value3 + (i - value1), encoding->row_size,
|
|
Packit |
2bba5f |
&first, &last, &encsize, &enc))
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
goto mapping;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
case CODE_UNDEFINE_LINE:
|
|
Packit |
2bba5f |
if (value1 > 0x10000)
|
|
Packit |
2bba5f |
value1 = 0x10000;
|
|
Packit |
2bba5f |
if (value2 > 0x10000)
|
|
Packit |
2bba5f |
value2 = 0x10000;
|
|
Packit |
2bba5f |
if (value2 < value1)
|
|
Packit |
2bba5f |
goto mapping;
|
|
Packit |
2bba5f |
/* Do the last value first to avoid having to realloc() */
|
|
Packit |
2bba5f |
if (setCode(value2, 0, encoding->row_size,
|
|
Packit |
2bba5f |
&first, &last, &encsize, &enc))
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
for (i = value1; i < value2; i++) {
|
|
Packit |
2bba5f |
if (setCode(i, 0, encoding->row_size,
|
|
Packit |
2bba5f |
&first, &last, &encsize, &enc))
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
goto mapping;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
default:
|
|
Packit |
2bba5f |
goto mapping; /* ignore unknown lines */
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
string_mapping:
|
|
Packit |
2bba5f |
line = getnextline(f);
|
|
Packit |
2bba5f |
switch (line) {
|
|
Packit |
2bba5f |
case EOF_LINE:
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
case ENDMAPPING_LINE:
|
|
Packit |
2bba5f |
mapping->recode = FontEncUndefinedRecode;
|
|
Packit |
2bba5f |
mapping->name = FontEncSimpleName;
|
|
Packit |
2bba5f |
mapping->client_data = sn = malloc(sizeof(FontEncSimpleNameRec));
|
|
Packit |
2bba5f |
if (sn == NULL)
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
if (first > last) {
|
|
Packit |
2bba5f |
free(sn);
|
|
Packit |
2bba5f |
mapping->client_data = sn = NULL;
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
sn->first = first;
|
|
Packit |
2bba5f |
sn->len = last - first + 1;
|
|
Packit |
2bba5f |
sn->map = malloc(sn->len * sizeof(char *));
|
|
Packit |
2bba5f |
if (sn->map == NULL) {
|
|
Packit |
2bba5f |
free(sn);
|
|
Packit |
2bba5f |
mapping->client_data = sn = NULL;
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
for (i = 0; i < sn->len; i++)
|
|
Packit |
2bba5f |
sn->map[i] = nam[first + i];
|
|
Packit |
2bba5f |
install_mapping(encoding, mapping);
|
|
Packit |
2bba5f |
mapping = NULL;
|
|
Packit |
2bba5f |
first = 0xFFFF;
|
|
Packit |
2bba5f |
last = 0;
|
|
Packit |
2bba5f |
goto no_mapping;
|
|
Packit |
2bba5f |
case NAME_LINE:
|
|
Packit |
2bba5f |
if (value1 >= 0x10000)
|
|
Packit |
2bba5f |
goto string_mapping;
|
|
Packit |
2bba5f |
if (namsize == 0) {
|
|
Packit |
2bba5f |
namsize = (value1) < 256 ? 256 : 0x10000;
|
|
Packit |
2bba5f |
nam = malloc(namsize * sizeof(char *));
|
|
Packit |
2bba5f |
if (nam == NULL) {
|
|
Packit |
2bba5f |
namsize = 0;
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else if (namsize <= value1) {
|
|
Packit |
2bba5f |
namsize = 0x10000;
|
|
Packit |
2bba5f |
if ((newnam = (char **) realloc(nam, namsize)) == NULL)
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
nam = newnam;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
if (first > last) {
|
|
Packit |
2bba5f |
first = last = value1;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
if (value1 < first) {
|
|
Packit |
2bba5f |
for (i = value1; i < first; i++)
|
|
Packit |
2bba5f |
nam[i] = NULL;
|
|
Packit |
2bba5f |
first = value1;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
if (value1 > last) {
|
|
Packit |
2bba5f |
for (i = last + 1; i <= value1; i++)
|
|
Packit |
2bba5f |
nam[i] = NULL;
|
|
Packit |
2bba5f |
last = value1;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
nam[value1] = strdup(keyword_value);
|
|
Packit |
2bba5f |
if (nam[value1] == NULL) {
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
goto string_mapping;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
default:
|
|
Packit |
2bba5f |
goto string_mapping; /* ignore unknown lines */
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
done:
|
|
Packit |
2bba5f |
if (encsize) {
|
|
Packit |
2bba5f |
free(enc);
|
|
Packit |
2bba5f |
encsize = 0;
|
|
Packit |
2bba5f |
enc = NULL;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
if (namsize) {
|
|
Packit |
2bba5f |
free(nam); /* don't free entries! */
|
|
Packit |
2bba5f |
namsize = 0;
|
|
Packit |
2bba5f |
nam = NULL;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
encoding->aliases = NULL;
|
|
Packit |
2bba5f |
if (numaliases) {
|
|
Packit |
2bba5f |
encoding->aliases = malloc((numaliases + 1) * sizeof(char *));
|
|
Packit |
2bba5f |
if (encoding->aliases == NULL)
|
|
Packit |
2bba5f |
goto error;
|
|
Packit |
2bba5f |
for (i = 0; i < numaliases; i++)
|
|
Packit |
2bba5f |
encoding->aliases[i] = aliases[i];
|
|
Packit |
2bba5f |
encoding->aliases[numaliases] = NULL;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
return encoding;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
error:
|
|
Packit |
2bba5f |
if (encsize) {
|
|
Packit |
2bba5f |
free(enc);
|
|
Packit |
2bba5f |
encsize = 0;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
if (namsize) {
|
|
Packit |
2bba5f |
for (i = first; i <= last; i++)
|
|
Packit |
2bba5f |
free(nam[i]);
|
|
Packit |
2bba5f |
free(nam);
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
if (mapping) {
|
|
Packit |
2bba5f |
free(mapping->client_data);
|
|
Packit |
2bba5f |
free(mapping);
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
if (encoding) {
|
|
Packit |
2bba5f |
FontMapPtr nextmap;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
free(encoding->name);
|
|
Packit |
2bba5f |
for (mapping = encoding->mappings; mapping; mapping = nextmap) {
|
|
Packit |
2bba5f |
free(mapping->client_data);
|
|
Packit |
2bba5f |
nextmap = mapping->next;
|
|
Packit |
2bba5f |
free(mapping);
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
free(encoding);
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
for (i = 0; i < numaliases; i++)
|
|
Packit |
2bba5f |
free(aliases[i]);
|
|
Packit |
2bba5f |
/* We don't need to free sn and sm as they handled locally in the body. */
|
|
Packit |
2bba5f |
return NULL;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
char *
|
|
Packit |
2bba5f |
FontEncDirectory(void)
|
|
Packit |
2bba5f |
{
|
|
Packit |
2bba5f |
static char *dir = NULL;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
if (dir == NULL) {
|
|
Packit |
2bba5f |
char *c = getenv("FONT_ENCODINGS_DIRECTORY");
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
if (c) {
|
|
Packit |
2bba5f |
dir = strdup(c);
|
|
Packit |
2bba5f |
if (!dir)
|
|
Packit |
2bba5f |
return NULL;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else {
|
|
Packit |
2bba5f |
dir = FONT_ENCODINGS_DIRECTORY;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
return dir;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
static void
|
|
Packit |
2bba5f |
parseFontFileName(const char *fontFileName, char *buf, char *dir)
|
|
Packit |
2bba5f |
{
|
|
Packit |
2bba5f |
const char *p;
|
|
Packit |
2bba5f |
char *q, *lastslash;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
for (p = fontFileName, q = dir, lastslash = NULL; *p; p++, q++) {
|
|
Packit |
2bba5f |
*q = *p;
|
|
Packit |
2bba5f |
if (*p == '/')
|
|
Packit |
2bba5f |
lastslash = q + 1;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
if (!lastslash)
|
|
Packit |
2bba5f |
lastslash = dir;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
*lastslash = '\0';
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
if (buf && strlen(dir) + 14 < MAXFONTFILENAMELEN) {
|
|
Packit |
2bba5f |
snprintf(buf, MAXFONTFILENAMELEN, "%s%s", dir, "encodings.dir");
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
static FontEncPtr
|
|
Packit |
2bba5f |
FontEncReallyReallyLoad(const char *charset,
|
|
Packit |
2bba5f |
const char *dirname, const char *dir)
|
|
Packit |
2bba5f |
{
|
|
Packit |
2bba5f |
FontFilePtr f;
|
|
Packit |
2bba5f |
FILE *file;
|
|
Packit |
2bba5f |
FontEncPtr encoding;
|
|
Packit |
2bba5f |
char file_name[MAXFONTFILENAMELEN], encoding_name[MAXFONTNAMELEN],
|
|
Packit |
2bba5f |
buf[MAXFONTFILENAMELEN];
|
|
Packit |
2bba5f |
int count, n;
|
|
Packit |
2bba5f |
static char format[24] = "";
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* As we don't really expect to open encodings that often, we don't
|
|
Packit |
2bba5f |
take the trouble of caching encodings directories. */
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
if ((file = fopen(dirname, "r")) == NULL) {
|
|
Packit |
2bba5f |
return NULL;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
count = fscanf(file, "%d\n", &n);
|
|
Packit |
2bba5f |
if (count == EOF || count != 1) {
|
|
Packit |
2bba5f |
fclose(file);
|
|
Packit |
2bba5f |
return NULL;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
encoding = NULL;
|
|
Packit |
2bba5f |
if (!format[0]) {
|
|
Packit |
2bba5f |
snprintf(format, sizeof(format), "%%%ds %%%d[^\n]\n",
|
|
Packit |
2bba5f |
(int) sizeof(encoding_name) - 1, (int) sizeof(file_name) - 1);
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
for (;;) {
|
|
Packit |
2bba5f |
count = fscanf(file, format, encoding_name, file_name);
|
|
Packit |
2bba5f |
if (count == EOF)
|
|
Packit |
2bba5f |
break;
|
|
Packit |
2bba5f |
if (count != 2)
|
|
Packit |
2bba5f |
break;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
if (!strcasecmp(encoding_name, charset)) {
|
|
Packit |
2bba5f |
/* Found it */
|
|
Packit |
2bba5f |
if (file_name[0] != '/') {
|
|
Packit |
2bba5f |
if (strlen(dir) + strlen(file_name) >= MAXFONTFILENAMELEN) {
|
|
Packit |
2bba5f |
fclose(file);
|
|
Packit |
2bba5f |
return NULL;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
snprintf(buf, MAXFONTFILENAMELEN, "%s%s", dir, file_name);
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
else {
|
|
Packit |
2bba5f |
snprintf(buf, MAXFONTFILENAMELEN, "%s", file_name);
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
f = FontFileOpen(buf);
|
|
Packit |
2bba5f |
if (f == NULL) {
|
|
Packit |
2bba5f |
fclose(file);
|
|
Packit |
2bba5f |
return NULL;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
encoding = parseEncodingFile(f, 0);
|
|
Packit |
2bba5f |
FontFileClose(f);
|
|
Packit |
2bba5f |
break;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
fclose(file);
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
return encoding;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* Parser ntrypoint -- used by FontEncLoad */
|
|
Packit |
2bba5f |
FontEncPtr
|
|
Packit |
2bba5f |
FontEncReallyLoad(const char *charset, const char *fontFileName)
|
|
Packit |
2bba5f |
{
|
|
Packit |
2bba5f |
FontEncPtr encoding;
|
|
Packit |
2bba5f |
char dir[MAXFONTFILENAMELEN], dirname[MAXFONTFILENAMELEN];
|
|
Packit |
2bba5f |
char *d;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
if (fontFileName) {
|
|
Packit |
2bba5f |
parseFontFileName(fontFileName, dirname, dir);
|
|
Packit |
2bba5f |
encoding = FontEncReallyReallyLoad(charset, dirname, dir);
|
|
Packit |
2bba5f |
if (encoding)
|
|
Packit |
2bba5f |
return (encoding);
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
d = FontEncDirectory();
|
|
Packit |
2bba5f |
if (d) {
|
|
Packit |
2bba5f |
parseFontFileName(d, NULL, dir);
|
|
Packit |
2bba5f |
encoding = FontEncReallyReallyLoad(charset, d, dir);
|
|
Packit |
2bba5f |
return encoding;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
return NULL;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
/* Return a NULL-terminated array of encoding names. Note that this
|
|
Packit |
2bba5f |
* function has incestuous knowledge of the allocations done by
|
|
Packit |
2bba5f |
* parseEncodingFile. */
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
char **
|
|
Packit |
2bba5f |
FontEncIdentify(const char *fileName)
|
|
Packit |
2bba5f |
{
|
|
Packit |
2bba5f |
FontFilePtr f;
|
|
Packit |
2bba5f |
FontEncPtr encoding;
|
|
Packit |
2bba5f |
char **names, **name, **alias;
|
|
Packit |
2bba5f |
int numaliases;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
if ((f = FontFileOpen(fileName)) == NULL) {
|
|
Packit |
2bba5f |
return NULL;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
encoding = parseEncodingFile(f, 1);
|
|
Packit |
2bba5f |
FontFileClose(f);
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
if (!encoding)
|
|
Packit |
2bba5f |
return NULL;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
numaliases = 0;
|
|
Packit |
2bba5f |
if (encoding->aliases)
|
|
Packit |
2bba5f |
for (alias = encoding->aliases; *alias; alias++)
|
|
Packit |
2bba5f |
numaliases++;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
names = malloc((numaliases + 2) * sizeof(char *));
|
|
Packit |
2bba5f |
if (names == NULL) {
|
|
Packit |
2bba5f |
free(encoding->aliases);
|
|
Packit |
2bba5f |
free(encoding);
|
|
Packit |
2bba5f |
return NULL;
|
|
Packit |
2bba5f |
}
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
name = names;
|
|
Packit |
2bba5f |
*(name++) = encoding->name;
|
|
Packit |
2bba5f |
if (numaliases > 0)
|
|
Packit |
2bba5f |
for (alias = encoding->aliases; *alias; alias++, name++)
|
|
Packit |
2bba5f |
*name = *alias;
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
*name = NULL;
|
|
Packit |
2bba5f |
free(encoding->aliases);
|
|
Packit |
2bba5f |
free(encoding);
|
|
Packit |
2bba5f |
|
|
Packit |
2bba5f |
return names;
|
|
Packit |
2bba5f |
}
|