#include "libtexpdf.h"
static int is_similar_charset (char **encoding, const char **encoding2);
static pdf_obj *make_encoding_differences (char **encoding, char **baseenc,
const char *is_used);
static unsigned char verbose = 0;
static const char *MacRomanEncoding[256];
static const char *MacExpertEncoding[256];
static const char *WinAnsiEncoding[256];
#if 0#endif
void
pdf_encoding_set_verbose (void)
{
verbose++;
}
#define FLAG_IS_PREDEFINED (1 << 0)
#define FLAG_USED_BY_TYPE3 (1 << 1)
typedef struct pdf_encoding
{
char *ident;
char *enc_name;
int flags;
char *glyphs[256];
char is_used[256];
struct pdf_encoding *baseenc;
pdf_obj *tounicode;
pdf_obj *resource;
} pdf_encoding;
static int pdf_encoding_new_encoding (const char *enc_name,
const char *ident,
const char **encoding_vec,
const char *baseenc_name,
int flags);
static void
texpdf_init_encoding_struct (pdf_encoding *encoding)
{
ASSERT(encoding);
encoding->ident = NULL;
encoding->enc_name = NULL;
memset(encoding->glyphs, 0, 256*sizeof(char *));
memset(encoding->is_used, 0, 256);
encoding->tounicode = NULL;
encoding->baseenc = NULL;
encoding->resource = NULL;
encoding->flags = 0;
return;
}
static pdf_obj *
create_encoding_resource (pdf_encoding *encoding, pdf_encoding *baseenc)
{
pdf_obj *differences;
ASSERT(encoding);
ASSERT(!encoding->resource);
differences = make_encoding_differences(encoding->glyphs,
baseenc ? baseenc->glyphs : NULL,
encoding->is_used);
if (differences) {
pdf_obj *resource = texpdf_new_dict();
if (baseenc)
texpdf_add_dict(resource, texpdf_new_name("BaseEncoding"),
texpdf_link_obj(baseenc->resource));
texpdf_add_dict(resource, texpdf_new_name("Differences"), differences);
return resource;
} else {
return baseenc ? texpdf_link_obj(baseenc->resource) : NULL;
}
}
static void
pdf_flush_encoding (pdf_encoding *encoding)
{
ASSERT(encoding);
if (encoding->resource) {
texpdf_release_obj(encoding->resource);
encoding->resource = NULL;
}
if (encoding->tounicode) {
texpdf_release_obj(encoding->tounicode);
encoding->tounicode = NULL;
}
return;
}
static void
pdf_clean_encoding_struct (pdf_encoding *encoding)
{
int code;
ASSERT(encoding);
if (encoding->resource)
ERROR("Object not flushed.");
if (encoding->tounicode)
texpdf_release_obj(encoding->tounicode);
if (encoding->ident)
RELEASE(encoding->ident);
if (encoding->enc_name)
RELEASE(encoding->enc_name);
encoding->ident = NULL;
encoding->enc_name = NULL;
for (code = 0; code < 256; code++) {
if (encoding->glyphs[code])
RELEASE(encoding->glyphs[code]);
encoding->glyphs[code] = NULL;
}
encoding->ident = NULL;
encoding->enc_name = NULL;
return;
}
#if 0#endif
static int
is_similar_charset (char **enc_vec, const char **enc_vec2)
{
int code, same = 0;
for (code = 0; code < 256; code++)
if (!(enc_vec[code] && strcmp(enc_vec[code], enc_vec2[code]))
&& ++same >= 64)
return 1;
return 0;
}
static pdf_obj *
make_encoding_differences (char **enc_vec, char **baseenc, const char *is_used)
{
pdf_obj *differences = NULL;
int code, count = 0;
int skipping = 1;
ASSERT(enc_vec);
differences = texpdf_new_array();
for (code = 0; code < 256; code++) {
if ((is_used && !is_used[code]) || !enc_vec[code])
skipping = 1;
else if (!baseenc || !baseenc[code] ||
strcmp(baseenc[code], enc_vec[code]) != 0) {
if (skipping)
texpdf_add_array(differences, texpdf_new_number(code));
texpdf_add_array(differences, texpdf_new_name(enc_vec[code]));
skipping = 0;
count++;
} else
skipping = 1;
}
if (count == 0) {
texpdf_release_obj(differences);
differences = NULL;
}
return differences;
}
static int
load_encoding_file (const char *filename)
{
FILE *fp;
pdf_obj *enc_name = NULL;
pdf_obj *encoding_array = NULL;
char *wbuf;
const char *p, *endptr;
const char *enc_vec[256];
int code, fsize, enc_id;
if (!filename)
return -1;
if (verbose) {
MESG("(Encoding:%s", filename);
}
fp = DPXFOPEN(filename, DPX_RES_TYPE_ENC);
if (!fp)
return -1;
fsize = file_size(fp);
wbuf = NEW(fsize + 1, char);
wbuf[fsize] = '\0';
fread(wbuf, sizeof(char), fsize, fp);
DPXFCLOSE(fp);
p = wbuf;
endptr = wbuf + fsize;
texpdf_skip_white(&p, endptr);
while (p < endptr && p[0] == '%') {
skip_line (&p, endptr);
texpdf_skip_white(&p, endptr);
}
if (p[0] == '/')
enc_name = texpdf_parse_pdf_name(&p, endptr);
texpdf_skip_white(&p, endptr);
encoding_array = texpdf_parse_pdf_array(&p, endptr, NULL);
RELEASE(wbuf);
if (!encoding_array) {
if (enc_name)
texpdf_release_obj(enc_name);
return -1;
}
for (code = 0; code < 256; code++) {
enc_vec[code] = texpdf_name_value(texpdf_get_array(encoding_array, code));
}
enc_id = pdf_encoding_new_encoding(enc_name ? texpdf_name_value(enc_name) : NULL,
filename, enc_vec, NULL, 0);
if (enc_name) {
if (verbose > 1)
MESG("[%s]", texpdf_name_value(enc_name));
texpdf_release_obj(enc_name);
}
texpdf_release_obj(encoding_array);
if (verbose) MESG(")");
return enc_id;
}
#define CHECK_ID(n) do { \
if ((n) < 0 || (n) >= enc_cache.count) { \
ERROR("Invalid encoding id: %d", (n)); \
} \
} while (0)
#define CACHE_ALLOC_SIZE 16u
struct {
int count;
int capacity;
pdf_encoding *encodings;
} enc_cache = {
0, 0, NULL
};
void
texpdf_init_encodings (void)
{
enc_cache.count = 0;
enc_cache.capacity = 3;
enc_cache.encodings = NEW(enc_cache.capacity, pdf_encoding);
pdf_encoding_new_encoding("WinAnsiEncoding", "WinAnsiEncoding",
WinAnsiEncoding, NULL, FLAG_IS_PREDEFINED);
pdf_encoding_new_encoding("MacRomanEncoding", "MacRomanEncoding",
MacRomanEncoding, NULL, FLAG_IS_PREDEFINED);
pdf_encoding_new_encoding("MacExpertEncoding", "MacExpertEncoding",
MacExpertEncoding, NULL, FLAG_IS_PREDEFINED);
return;
}
static int
pdf_encoding_new_encoding (const char *enc_name, const char *ident,
const char **encoding_vec,
const char *baseenc_name, int flags)
{
int enc_id, code;
pdf_encoding *encoding;
enc_id = enc_cache.count;
if (enc_cache.count++ >= enc_cache.capacity) {
enc_cache.capacity += 16;
enc_cache.encodings = RENEW(enc_cache.encodings,
enc_cache.capacity, pdf_encoding);
}
encoding = &enc_cache.encodings[enc_id];
texpdf_init_encoding_struct(encoding);
encoding->ident = NEW(strlen(ident)+1, char);
strcpy(encoding->ident, ident);
encoding->enc_name = NEW(strlen(enc_name)+1, char);
strcpy(encoding->enc_name, enc_name);
encoding->flags = flags;
for (code = 0; code < 256; code++)
if (encoding_vec[code] && strcmp(encoding_vec[code], ".notdef")) {
encoding->glyphs[code] = NEW(strlen(encoding_vec[code])+1, char);
strcpy(encoding->glyphs[code], encoding_vec[code]);
}
if (!baseenc_name && !(flags & FLAG_IS_PREDEFINED)
&& is_similar_charset(encoding->glyphs, WinAnsiEncoding)) {
baseenc_name = "WinAnsiEncoding";
}
if (baseenc_name) {
int baseenc_id = pdf_encoding_findresource(baseenc_name);
if (baseenc_id < 0 || !pdf_encoding_is_predefined(baseenc_id))
ERROR("Illegal base encoding %s for encoding %s\n",
baseenc_name, encoding->enc_name);
encoding->baseenc = &enc_cache.encodings[baseenc_id];
}
if (flags & FLAG_IS_PREDEFINED)
encoding->resource = texpdf_new_name(encoding->enc_name);
return enc_id;
}
void pdf_encoding_complete (void)
{
int enc_id;
for (enc_id = 0; enc_id < enc_cache.count; enc_id++) {
if (!pdf_encoding_is_predefined(enc_id)) {
pdf_encoding *encoding = &enc_cache.encodings[enc_id];
int with_base = !(encoding->flags & FLAG_USED_BY_TYPE3)
|| texpdf_get_version() >= 4;
ASSERT(!encoding->resource);
encoding->resource = create_encoding_resource(encoding,
with_base ? encoding->baseenc : NULL);
ASSERT(!encoding->tounicode);
encoding->tounicode = pdf_create_ToUnicode_CMap(encoding->enc_name,
encoding->glyphs,
encoding->is_used);
}
}
}
void
texpdf_close_encodings (void)
{
int enc_id;
if (enc_cache.encodings) {
for (enc_id = 0; enc_id < enc_cache.count; enc_id++) {
pdf_encoding *encoding;
encoding = &enc_cache.encodings[enc_id];
if (encoding) {
pdf_flush_encoding(encoding);
pdf_clean_encoding_struct(encoding);
}
}
RELEASE(enc_cache.encodings);
}
enc_cache.encodings = NULL;
enc_cache.count = 0;
enc_cache.capacity = 0;
}
int
pdf_encoding_findresource (const char *enc_name)
{
int enc_id;
pdf_encoding *encoding;
ASSERT(enc_name);
for (enc_id = 0; enc_id < enc_cache.count; enc_id++) {
encoding = &enc_cache.encodings[enc_id];
if (encoding->ident &&
!strcmp(enc_name, encoding->ident))
return enc_id;
else if (encoding->enc_name &&
!strcmp(enc_name, encoding->enc_name))
return enc_id;
}
return load_encoding_file(enc_name);
}
char **
pdf_encoding_get_encoding (int enc_id)
{
pdf_encoding *encoding;
CHECK_ID(enc_id);
encoding = &enc_cache.encodings[enc_id];
return encoding->glyphs;
}
pdf_obj *
texpdf_get_encoding_obj (int enc_id)
{
pdf_encoding *encoding;
CHECK_ID(enc_id);
encoding = &enc_cache.encodings[enc_id];
return encoding->resource;
}
int
pdf_encoding_is_predefined (int enc_id)
{
pdf_encoding *encoding;
CHECK_ID(enc_id);
encoding = &enc_cache.encodings[enc_id];
return (encoding->flags & FLAG_IS_PREDEFINED) ? 1 : 0;
}
void
pdf_encoding_used_by_type3 (int enc_id)
{
pdf_encoding *encoding;
CHECK_ID(enc_id);
encoding = &enc_cache.encodings[enc_id];
encoding->flags |= FLAG_USED_BY_TYPE3;
}
char *
pdf_encoding_get_name (int enc_id)
{
pdf_encoding *encoding;
CHECK_ID(enc_id);
encoding = &enc_cache.encodings[enc_id];
return encoding->enc_name;
}
#include "cid.h"
#include "cmap.h"
#include "cmap_read.h"
#include "cmap_write.h"
#include "agl.h"
#define WBUF_SIZE 1024
static unsigned char wbuf[WBUF_SIZE];
static unsigned char range_min[1] = {0x00u};
static unsigned char range_max[1] = {0xFFu};
void
pdf_encoding_add_usedchars (int encoding_id, const char *is_used)
{
pdf_encoding *encoding;
int code;
CHECK_ID(encoding_id);
if (!is_used || pdf_encoding_is_predefined(encoding_id))
return;
encoding = &enc_cache.encodings[encoding_id];
for (code = 0; code <= 0xff; code++)
encoding->is_used[code] |= is_used[code];
}
pdf_obj *
pdf_encoding_get_tounicode (int encoding_id)
{
CHECK_ID(encoding_id);
return enc_cache.encodings[encoding_id].tounicode;
}
pdf_obj *
pdf_create_ToUnicode_CMap (const char *enc_name,
char **enc_vec, const char *is_used)
{
pdf_obj *stream;
CMap *cmap;
int code, all_predef;
char *cmap_name;
unsigned char *p, *endptr;
ASSERT(enc_name && enc_vec);
cmap_name = NEW(strlen(enc_name)+strlen("-UTF16")+1, char);
sprintf(cmap_name, "%s-UTF16", enc_name);
cmap = CMap_new();
CMap_set_name (cmap, cmap_name);
CMap_set_type (cmap, CMAP_TYPE_TO_UNICODE);
CMap_set_wmode(cmap, 0);
CMap_set_CIDSysInfo(cmap, &CSI_UNICODE);
CMap_add_codespacerange(cmap, range_min, range_max, 1);
all_predef = 1;
for (code = 0; code <= 0xff; code++) {
if (is_used && !is_used[code])
continue;
if (enc_vec[code]) {
long len;
int fail_count = 0;
agl_name *agln = agl_lookup_list(enc_vec[code]);
if (texpdf_get_version() < 5 || !agln || !agln->is_predef) {
wbuf[0] = (code & 0xff);
p = wbuf + 1;
endptr = wbuf + WBUF_SIZE;
len = agl_sput_UTF16BE(enc_vec[code], &p, endptr, &fail_count);
if (len >= 1 && !fail_count) {
CMap_add_bfchar(cmap, wbuf, 1, wbuf + 1, len);
all_predef &= agln && agln->is_predef;
}
}
}
}
stream = all_predef ? NULL : CMap_create_stream(cmap);
CMap_release(cmap);
RELEASE(cmap_name);
return stream;
}
pdf_obj *
pdf_load_ToUnicode_stream (const char *ident)
{
pdf_obj *stream = NULL;
CMap *cmap;
FILE *fp;
if (!ident)
return NULL;
fp = DPXFOPEN(ident, DPX_RES_TYPE_CMAP);
if (!fp)
return NULL;
else if (CMap_parse_check_sig(fp) < 0) {
DPXFCLOSE(fp);
return NULL;
}
cmap = CMap_new();
if (CMap_parse(cmap, fp) < 0) {
WARN("Reading CMap file \"%s\" failed.", ident);
} else {
if (verbose) {
MESG("(CMap:%s)", ident);
}
stream = CMap_create_stream(cmap);
if (!stream) {
WARN("Failed to creat ToUnicode CMap stream for \"%s\".", ident);
}
}
CMap_release(cmap);
DPXFCLOSE(fp);
return stream;
}
static const char *
MacRomanEncoding[256] = {
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
"space", "exclam", "quotedbl", "numbersign",
"dollar", "percent", "ampersand", "quotesingle",
"parenleft", "parenright", "asterisk", "plus",
"comma", "hyphen", "period", "slash",
"zero", "one", "two", "three",
"four", "five", "six", "seven",
"eight", "nine", "colon", "semicolon",
"less", "equal", "greater", "question",
"at", "A", "B", "C",
"D", "E", "F", "G", "H",
"I", "J", "K", "L",
"M", "N", "O", "P",
"Q", "R", "S", "T",
"U", "V", "W", "X",
"Y", "Z", "bracketleft", "backslash",
"bracketright", "asciicircum", "underscore",
"grave", "a", "b", "c",
"d", "e", "f", "g",
"h", "i", "j", "k",
"l", "m", "n", "o",
"p", "q", "r", "s",
"t", "u", "v", "w",
"x", "y", "z", "braceleft",
"bar", "braceright", "asciitilde", ".notdef",
"Adieresis", "Aring", "Ccedilla", "Eacute",
"Ntilde", "Odieresis", "Udieresis", "aacute",
"agrave", "acircumflex", "adieresis", "atilde",
"aring", "ccedilla", "eacute", "egrave",
"ecircumflex", "edieresis", "iacute", "igrave",
"icircumflex", "idieresis", "ntilde", "oacute",
"ograve", "ocircumflex", "odieresis", "otilde",
"uacute", "ugrave", "ucircumflex", "udieresis",
"dagger", "degree", "cent", "sterling",
"section", "bullet", "paragraph", "germandbls",
"registered", "copyright", "trademark", "acute",
"dieresis", "notequal", "AE", "Oslash",
"infinity", "plusminus", "lessequal", "greaterequal",
"yen", "mu", "partialdiff", "summation",
"product", "pi", "integral", "ordfeminine",
"ordmasculine", "Omega", "ae", "oslash",
"questiondown", "exclamdown", "logicalnot", "radical",
"florin", "approxequal", "Delta", "guillemotleft",
"guillemotright", "ellipsis", "space", "Agrave",
"Atilde", "Otilde", "OE", "oe",
"endash", "emdash", "quotedblleft", "quotedblright",
"quoteleft", "quoteright", "divide", "lozenge",
"ydieresis", "Ydieresis", "fraction", "currency",
"guilsinglleft", "guilsinglright", "fi", "fl",
"daggerdbl", "periodcentered", "quotesinglbase", "quotedblbase",
"perthousand", "Acircumflex", "Ecircumflex", "Aacute",
"Edieresis", "Egrave", "Iacute", "Icircumflex",
"Idieresis", "Igrave", "Oacute", "Ocircumflex",
"apple", "Ograve", "Uacute", "Ucircumflex",
"Ugrave", "dotlessi", "circumflex", "tilde",
"macron", "breve", "dotaccent", "ring",
"cedilla", "hungarumlaut", "ogonek", "caron"
};
static const char *
MacExpertEncoding[256] = {
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
"space", "exclamsmall", "Hungarumlautsmall", "centoldstyle",
"dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall",
"parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader",
"comma", "hyphen", "period", "fraction",
"zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle",
"fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle",
"eightoldstyle", "nineoldstyle", "colon", "semicolon",
".notdef", "threequartersemdash", ".notdef", "questionsmall",
".notdef", ".notdef", ".notdef", ".notdef",
"Ethsmall", ".notdef", ".notdef", "onequarter",
"onehalf", "threequarters", "oneeighth", "threeeighths",
"fiveeighths", "seveneighths", "onethird", "twothirds",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", "ff", "fi",
"fl", "ffi", "ffl", "parenleftinferior",
".notdef", "parenrightinferior", "Circumflexsmall", "hypheninferior",
"Gravesmall", "Asmall", "Bsmall", "Csmall",
"Dsmall", "Esmall", "Fsmall", "Gsmall",
"Hsmall", "Ismall", "Jsmall", "Ksmall",
"Lsmall", "Msmall", "Nsmall", "Osmall",
"Psmall", "Qsmall", "Rsmall", "Ssmall",
"Tsmall", "Usmall", "Vsmall", "Wsmall",
"Xsmall", "Ysmall", "Zsmall", "colonmonetary",
"onefitted", "rupiah", "Tildesmall", ".notdef",
".notdef", "asuperior", "centsuperior", ".notdef",
".notdef", ".notdef", ".notdef", "Aacutesmall",
"Agravesmall", "Acircumflexsmall", "Adieresissmall", "Atildesmall",
"Aringsmall", "Ccedillasmall", "Eacutesmall", "Egravesmall",
"Ecircumflexsmall", "Edieresissmall", "Iacutesmall", "Igravesmall",
"Icircumflexsmall", "Idieresissmall", "Ntildesmall", "Oacutesmall",
"Ogravesmall", "Ocircumflexsmall", "Odieresissmall", "Otildesmall",
"Uacutesmall", "Ugravesmall", "Ucircumflexsmall", "Udieresissmall",
".notdef", "eightsuperior", "fourinferior", "threeinferior",
"sixinferior", "eightinferior", "seveninferior", "Scaronsmall",
".notdef", "centinferior", "twoinferior", ".notdef",
"Dieresissmall", ".notdef", "Caronsmall", "osuperior",
"fiveinferior", ".notdef", "commainferior", "periodinferior",
"Yacutesmall", ".notdef", "dollarinferior", ".notdef",
".notdef", "Thornsmall", ".notdef", "nineinferior",
"zeroinferior", "Zcaronsmall", "AEsmall", "Oslashsmall",
"questiondownsmall", "oneinferior", "Lslashsmall", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", "Cedillasmall", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", "OEsmall",
"figuredash", "hyphensuperior", ".notdef", ".notdef",
".notdef", ".notdef", "exclamdownsmall", ".notdef",
"Ydieresissmall", ".notdef", "onesuperior", "twosuperior",
"threesuperior", "foursuperior", "fivesuperior", "sixsuperior",
"sevensuperior", "ninesuperior", "zerosuperior", ".notdef",
"esuperior", "rsuperior", "tsuperior", ".notdef",
".notdef", "isuperior", "ssuperior", "dsuperior",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", "lsuperior", "Ogoneksmall", "Brevesmall",
"Macronsmall", "bsuperior", "nsuperior", "msuperior",
"commasuperior", "periodsuperior", "Dotaccentsmall", "Ringsmall",
".notdef", ".notdef", ".notdef", ".notdef"
};
static const char *
WinAnsiEncoding[256] = {
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
".notdef", ".notdef", ".notdef", ".notdef",
"space", "exclam", "quotedbl", "numbersign",
"dollar", "percent", "ampersand", "quotesingle",
"parenleft", "parenright", "asterisk", "plus",
"comma", "hyphen", "period", "slash",
"zero", "one", "two", "three",
"four", "five", "six", "seven",
"eight", "nine", "colon", "semicolon",
"less", "equal", "greater", "question",
"at", "A", "B", "C",
"D", "E", "F", "G",
"H", "I", "J", "K",
"L", "M", "N", "O",
"P", "Q", "R", "S",
"T", "U", "V", "W",
"X", "Y", "Z", "bracketleft",
"backslash", "bracketright", "asciicircum", "underscore",
"grave", "a", "b", "c",
"d", "e", "f", "g",
"h", "i", "j", "k",
"l", "m", "n", "o",
"p", "q", "r", "s",
"t", "u", "v", "w",
"x", "y", "z", "braceleft",
"bar", "braceright", "asciitilde", "bullet",
"Euro", "bullet", "quotesinglbase", "florin",
"quotedblbase", "ellipsis", "dagger", "daggerdbl",
"circumflex", "perthousand", "Scaron", "guilsinglleft",
"OE", "bullet", "Zcaron", "bullet",
"bullet", "quoteleft", "quoteright", "quotedblleft",
"quotedblright", "bullet", "endash", "emdash",
"tilde", "trademark", "scaron", "guilsinglright",
"oe", "bullet", "zcaron", "Ydieresis",
"space", "exclamdown", "cent", "sterling",
"currency", "yen", "brokenbar", "section",
"dieresis", "copyright", "ordfeminine", "guillemotleft",
"logicalnot", "hyphen", "registered", "macron",
"degree", "plusminus", "twosuperior", "threesuperior",
"acute", "mu", "paragraph", "periodcentered",
"cedilla", "onesuperior", "ordmasculine", "guillemotright",
"onequarter", "onehalf", "threequarters", "questiondown",
"Agrave", "Aacute", "Acircumflex", "Atilde",
"Adieresis", "Aring", "AE", "Ccedilla",
"Egrave", "Eacute", "Ecircumflex", "Edieresis",
"Igrave", "Iacute", "Icircumflex", "Idieresis",
"Eth", "Ntilde", "Ograve", "Oacute",
"Ocircumflex", "Otilde", "Odieresis", "multiply",
"Oslash", "Ugrave", "Uacute", "Ucircumflex",
"Udieresis", "Yacute", "Thorn", "germandbls",
"agrave", "aacute", "acircumflex", "atilde",
"adieresis", "aring", "ae", "ccedilla",
"egrave", "eacute", "ecircumflex", "edieresis",
"igrave", "iacute", "icircumflex", "idieresis",
"eth", "ntilde", "ograve", "oacute",
"ocircumflex", "otilde", "odieresis", "divide",
"oslash", "ugrave", "uacute", "ucircumflex",
"udieresis", "yacute", "thorn", "ydieresis"
};
#if 0#endif