summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Kew <jfkthame@googlemail.com>2008-04-17 14:26:29 +0000
committerJonathan Kew <jfkthame@googlemail.com>2008-04-17 14:26:29 +0000
commit5510e0bf8ad6881494129b795d1ad7286fd70b7a (patch)
tree371f9e59e0823936d4b03f28bbc9890386514eec
parente6d9f6ddf842b1486cc26a69c777ca93011fb090 (diff)
xetex 0.996-patch2: backported fixes from svn r.414, 449, 460, 466, 467, 468-9, 510, 436, 518, 526, 510, 557, 572, 580, 579, 634, 541-3, 589
git-svn-id: svn://tug.org/texlive/branches/branch2007@7473 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Build/source/texk/web2c/etexdir/etex.ch22
-rw-r--r--Build/source/texk/web2c/lib/texmfmp.c57
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp144
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeXFontMgr.h8
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp7
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.h19
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp2
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeX_ext.c85
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeX_ext.h1
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeX_mac.c25
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeX_pic.c16
-rw-r--r--Build/source/texk/web2c/xetexdir/appleGlyphNames.c2
-rw-r--r--Build/source/texk/web2c/xetexdir/pdfimage.cpp22
-rw-r--r--Build/source/texk/web2c/xetexdir/pdfimage.h2
-rw-r--r--Build/source/texk/web2c/xetexdir/pool2c.pl74
-rw-r--r--Build/source/texk/web2c/xetexdir/xetex-new.ch327
-rw-r--r--Build/source/texk/web2c/xetexdir/xetex.defines2
-rw-r--r--Build/source/texk/web2c/xetexdir/xetex.mk24
-rw-r--r--Build/source/texk/web2c/xetexdir/xetexextra.in2
19 files changed, 615 insertions, 226 deletions
diff --git a/Build/source/texk/web2c/etexdir/etex.ch b/Build/source/texk/web2c/etexdir/etex.ch
index 74c19e79057..d887bf00288 100644
--- a/Build/source/texk/web2c/etexdir/etex.ch
+++ b/Build/source/texk/web2c/etexdir/etex.ch
@@ -29,7 +29,7 @@
% (pdftexdir/pdftex.ch). Consequently, changes in these files have to be
% coordinated.
-% e-TeX is copyright (C) 1999-2004 by P. Breitenlohner (1994,98 by the NTS
+% e-TeX is copyright (C) 1999-2008 by P. Breitenlohner (1994,98 by the NTS
% team); all rights are reserved. Copying of this file is authorized only if
% (1) you are P. Breitenlohner, or if (2) you make absolutely no changes to
% your copy. (Programs such as TIE allow the application of several change
@@ -116,6 +116,9 @@
% direction typesetting;
% fixed a bug in the revised glue rounding code, detected by
% Tigran Aivazian <tigran@@aivazian.fsnet.co.uk>, Oct 2004.
+% Version 2.3 development was started in Feb 2008; released in Mon Year.
+% fixed a bug in hyph_code handling (\savinghyphcodes)
+% reported by Vladimir Volovich <vvv@@vsu.ru>, Feb 2008.
% Although considerable effort has been expended to make the e-TeX program
% correct and reliable, no warranty is implied; the author disclaims any
@@ -3020,13 +3023,12 @@ if (format_ident=0)or(buffer[loc]="&") then
if eTeX_ex then wterm_ln('entering extended mode');
@z
%---------------------------------------
-@x [53] m.1363 l.24757 - e-TeX hyph_codes
-adv_past(s)
+@x [53] m.1362 l.24751 adv_past - e-TeX hyph_codes
+ begin cur_lang:=what_lang(#); l_hyf:=what_lhm(#); r_hyf:=what_rhm(#);@+end
@y
-if subtype(s)=language_node then
- begin cur_lang:=what_lang(s); l_hyf:=what_lhm(s); r_hyf:=what_rhm(s);
- set_hyph_index;
- end
+ begin cur_lang:=what_lang(#); l_hyf:=what_lhm(#); r_hyf:=what_rhm(#);
+ set_hyph_index;
+ end
@z
%---------------------------------------
@x [54] m.1379 l.24945 - e-TeX additions
@@ -5915,7 +5917,7 @@ fields in the active nodes.
@!best_pl_glue:array[very_loose_fit..tight_fit] of scaled; {corresponding
glue stretch or shrink}
-@ The new algorithm for the last line requires that the stretchability
+@ The new algorithm for the last line requires that the stretchability of
|par_fill_skip| is infinite and the stretchability of |left_skip| plus
|right_skip| is finite.
@@ -5966,10 +5968,10 @@ if arith_error then
if active_short(r)>0 then g:=max_dimen@+else g:=-max_dimen;
if g>0 then
@<Set the value of |b| to the badness of the last line for stretching,
- compute the corresponding |fit_class, and |goto found||@>
+ compute the corresponding |fit_class|, and |goto found|@>
else if g<0 then
@<Set the value of |b| to the badness of the last line for shrinking,
- compute the corresponding |fit_class, and |goto found||@>;
+ compute the corresponding |fit_class|, and |goto found|@>;
not_found:end
@ These badness computations are rather similar to those of the standard
diff --git a/Build/source/texk/web2c/lib/texmfmp.c b/Build/source/texk/web2c/lib/texmfmp.c
index 12307761463..494b353c08c 100644
--- a/Build/source/texk/web2c/lib/texmfmp.c
+++ b/Build/source/texk/web2c/lib/texmfmp.c
@@ -1953,22 +1953,65 @@ compare_paths P2C(const_string, p1, const_string, p2)
return ret;
}
-#ifdef XeTeX
-#define strstartar strstart
-#endif
+#ifdef XeTeX /* the string pool is UTF-16 but we want a UTF-8 string */
+
+string
+gettexstring P1C(strnumber, s)
+{
+ unsigned bytesToWrite = 0;
+ poolpointer len, i, j;
+ string name;
+ len = strstart[s + 1 - 65536L] - strstart[s - 65536L];
+ name = (string)xmalloc(len * 3 + 1); /* max UTF16->UTF8 expansion (code units, not bytes) */
+ for (i = 0, j = 0; i < len; i++) {
+ unsigned c = strpool[i + strstart[s - 65536L]];
+ if (c >= 0xD800 && c <= 0xDBFF) {
+ unsigned lo = strpool[++i + strstart[s - 65536L]];
+ if (lo >= 0xDC00 && lo <= 0xDFFF)
+ c = (c - 0xD800) * 0x0400 + lo - 0xDC00;
+ else
+ c = 0xFFFD;
+ }
+ if (c < 0x80)
+ bytesToWrite = 1;
+ else if (c < 0x800)
+ bytesToWrite = 2;
+ else if (c < 0x10000)
+ bytesToWrite = 3;
+ else if (c < 0x110000)
+ bytesToWrite = 4;
+ else {
+ bytesToWrite = 3;
+ c = 0xFFFD;
+ }
+
+ j += bytesToWrite;
+ switch (bytesToWrite) { /* note: everything falls through. */
+ case 4: name[--j] = ((c | 0x80) & 0xBF); c >>= 6;
+ case 3: name[--j] = ((c | 0x80) & 0xBF); c >>= 6;
+ case 2: name[--j] = ((c | 0x80) & 0xBF); c >>= 6;
+ case 1: name[--j] = (c | firstByteMark[bytesToWrite]);
+ }
+ j += bytesToWrite;
+ }
+ name[j] = 0;
+ return name;
+}
+
+#else
string
gettexstring P1C(strnumber, s)
{
poolpointer len;
string name;
-#if !defined(Omega) && !defined(eOmega) && !defined(Aleph) && !defined(XeTeX)
+#if !defined(Omega) && !defined(eOmega) && !defined(Aleph)
len = strstart[s + 1] - strstart[s];
#else
len = strstartar[s + 1 - 65536L] - strstartar[s - 65536L];
#endif
name = (string)xmalloc (len + 1);
-#if !defined(Omega) && !defined(eOmega) && !defined(Aleph) && !defined(XeTeX)
+#if !defined(Omega) && !defined(eOmega) && !defined(Aleph)
strncpy (name, (string)&strpool[strstart[s]], len);
#else
{
@@ -1981,9 +2024,7 @@ gettexstring P1C(strnumber, s)
return name;
}
-#ifdef XeTeX
-#undef strstartar
-#endif
+#endif /* not XeTeX */
boolean
isnewsource P2C(strnumber, srcfilename, int, lineno)
diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp
index 62c787da5bb..dde4f26a80a 100644
--- a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp
+++ b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.cpp
@@ -34,7 +34,6 @@ authorization from SIL International.
#include "XeTeXFontMgr_FC.h"
#endif
-#include "XeTeXLayoutInterface.h"
#include "XeTeXswap.h"
#include "Features.h"
@@ -44,6 +43,8 @@ authorization from SIL International.
#include <math.h>
+extern Fixed loadedfontdesignsize;
+
XeTeXFontMgr* XeTeXFontMgr::sFontManager = NULL;
char XeTeXFontMgr::sReqEngine = 0;
@@ -83,17 +84,22 @@ XeTeXFontMgr::Terminate()
PlatformFontRef
XeTeXFontMgr::findFont(const char* name, char* variant, double ptSize)
- // ptSize is in TeX points
+ // ptSize is in TeX points, or negative for 'scaled' factor
// "variant" string will be shortened (in-place) by removal of /B and /I if present
{
std::string nameStr(name);
Font* font = NULL;
+ int dsize = 100;
+ loadedfontdesignsize = 655360L;
+
for (int pass = 0; pass < 2; ++pass) {
// try full name as given
std::map<std::string,Font*>::iterator i = nameToFont.find(nameStr);
if (i != nameToFont.end()) {
font = i->second;
+ if (font->opSizeInfo.designSize != 0)
+ dsize = font->opSizeInfo.designSize;
break;
}
@@ -107,6 +113,8 @@ XeTeXFontMgr::findFont(const char* name, char* variant, double ptSize)
i = f->second->styles->find(style);
if (i != f->second->styles->end()) {
font = i->second;
+ if (font->opSizeInfo.designSize != 0)
+ dsize = font->opSizeInfo.designSize;
break;
}
}
@@ -116,6 +124,8 @@ XeTeXFontMgr::findFont(const char* name, char* variant, double ptSize)
i = psNameToFont.find(nameStr);
if (i != psNameToFont.end()) {
font = i->second;
+ if (font->opSizeInfo.designSize != 0)
+ dsize = font->opSizeInfo.designSize;
break;
}
@@ -179,7 +189,7 @@ XeTeXFontMgr::findFont(const char* name, char* variant, double ptSize)
Family* parent = font->parent;
// if there are variant requests, try to apply them
- // and delete B or I codes from the string
+ // and delete B, I, and S=... codes from the string, just retain /engine option
sReqEngine = 0;
bool reqBold = false;
bool reqItal = false;
@@ -248,9 +258,6 @@ XeTeXFontMgr::findFont(const char* name, char* variant, double ptSize)
++cp;
}
}
- if (varString.length() > 0 && *(varString.end() - 1) != '/')
- varString.append("/");
- varString.append(start, cp);
goto skip_to_slash;
}
@@ -359,8 +366,10 @@ XeTeXFontMgr::findFont(const char* name, char* variant, double ptSize)
}
// if there's optical size info, try to apply it
- if (font != NULL && font->opSizeInfo.subFamilyID != 0 && ptSize != 0.0) {
- ptSize = ptSize * 720 / 72.27; // convert TeX points to PS decipoints for comparison with the opSize values
+ if (ptSize < 0.0)
+ ptSize = dsize / 10.0;
+ if (font != NULL && font->opSizeInfo.subFamilyID != 0 && ptSize > 0.0) {
+ ptSize = ptSize * 10.0; // convert to decipoints for comparison with the opSize values
double bestMismatch = my_fmax(font->opSizeInfo.minSize - ptSize, ptSize - font->opSizeInfo.maxSize);
if (bestMismatch > 0.0) {
Font* bestMatch = font;
@@ -378,6 +387,9 @@ XeTeXFontMgr::findFont(const char* name, char* variant, double ptSize)
font = bestMatch;
}
}
+
+ if (font != NULL && font->opSizeInfo.designSize != 0)
+ loadedfontdesignsize = (font->opSizeInfo.designSize << 16L) / 10;
return font->fontRef;
}
@@ -450,58 +462,82 @@ XeTeXFontMgr::bestMatchFromFamily(const Family* fam, int wt, int wd, int slant)
return bestMatch;
}
+const XeTeXFontMgr::OpSizeRec*
+XeTeXFontMgr::getOpSizePtr(XeTeXFont font)
+{
+ const GlyphPositioningTableHeader* gposTable = (const GlyphPositioningTableHeader*)getFontTablePtr(font, LE_GPOS_TABLE_TAG);
+ if (gposTable != NULL) {
+ const FeatureListTable* featureListTable = (const FeatureListTable*)((const char*)gposTable + SWAP(gposTable->featureListOffset));
+ for (int i = 0; i < SWAP(featureListTable->featureCount); ++i) {
+ UInt32 tag = SWAPT(featureListTable->featureRecordArray[i].featureTag);
+ if (tag == LE_SIZE_FEATURE_TAG) {
+ const FeatureTable* feature = (const FeatureTable*)((const char*)featureListTable
+ + SWAP(featureListTable->featureRecordArray[i].featureTableOffset));
+ UInt16 offset = SWAP(feature->featureParamsOffset);
+ const OpSizeRec* pSizeRec;
+ /* if featureParamsOffset < (offset of feature from featureListTable),
+ then we have a correct size table;
+ otherwise we (presumably) have a "broken" one from the old FDK */
+ for (int i = 0; i < 2; ++i) {
+ if (i == 0)
+ pSizeRec = (const OpSizeRec*)((char*)feature + offset);
+ else
+ pSizeRec = (const OpSizeRec*)((char*)featureListTable + offset);
+ if (SWAP(pSizeRec->designSize) == 0)
+ continue; // incorrect 'size' feature format
+ if (SWAP(pSizeRec->subFamilyID) == 0
+ && SWAP(pSizeRec->nameCode) == 0
+ && SWAP(pSizeRec->minSize) == 0
+ && SWAP(pSizeRec->maxSize) == 0)
+ return pSizeRec; // feature is valid, but no 'size' range
+ if (SWAP(pSizeRec->designSize) < SWAP(pSizeRec->minSize)) // check values are valid
+ continue; // else try different interpretation
+ if (SWAP(pSizeRec->designSize) > SWAP(pSizeRec->maxSize))
+ continue;
+ if (SWAP(pSizeRec->maxSize) < SWAP(pSizeRec->minSize))
+ continue;
+ if (SWAP(pSizeRec->nameCode) < 256)
+ continue;
+ if (SWAP(pSizeRec->nameCode) > 32767)
+ continue;
+ return pSizeRec;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+double
+XeTeXFontMgr::getDesignSize(XeTeXFont font)
+{
+ const OpSizeRec* pSizeRec = getOpSizePtr(font);
+ if (pSizeRec != NULL)
+ return SWAP(pSizeRec->designSize) / 10.0;
+ else
+ return 10.0;
+}
+
void
XeTeXFontMgr::getOpSizeRecAndStyleFlags(Font* theFont)
{
XeTeXFont font = createFont(theFont->fontRef, 655360);
if (font != 0) {
- const GlyphPositioningTableHeader* gposTable = (const GlyphPositioningTableHeader*)getFontTablePtr(font, LE_GPOS_TABLE_TAG);
- if (gposTable != NULL) {
- const FeatureListTable* featureListTable = (const FeatureListTable*)((const char*)gposTable + SWAP(gposTable->featureListOffset));
- for (int i = 0; i < SWAP(featureListTable->featureCount); ++i) {
- UInt32 tag = SWAPT(featureListTable->featureRecordArray[i].featureTag);
- if (tag == LE_SIZE_FEATURE_TAG) {
- const FeatureTable* feature = (const FeatureTable*)((const char*)featureListTable
- + SWAP(featureListTable->featureRecordArray[i].featureTableOffset));
- UInt16 offset = SWAP(feature->featureParamsOffset);
- const OpSizeRec* pSizeRec;
- /* if featureParamsOffset < (offset of feature from featureListTable),
- then we have a correct size table;
- otherwise we (presumably) have a "broken" one from the old FDK */
- for (int i = 0; i < 2; ++i) {
- if (i == 0)
- pSizeRec = (const OpSizeRec*)((char*)feature + offset);
- else
- pSizeRec = (const OpSizeRec*)((char*)featureListTable + offset);
- if (SWAP(pSizeRec->designSize) == 0)
- continue; // incorrect 'size' feature format
- if (SWAP(pSizeRec->subFamilyID) == 0
- && SWAP(pSizeRec->nameCode) == 0
- && SWAP(pSizeRec->minSize) == 0
- && SWAP(pSizeRec->maxSize) == 0)
- break; // feature is valid, but no 'size' range
- if (SWAP(pSizeRec->designSize) < SWAP(pSizeRec->minSize))
- continue;
- if (SWAP(pSizeRec->designSize) > SWAP(pSizeRec->maxSize))
- continue;
- if (SWAP(pSizeRec->maxSize) <= SWAP(pSizeRec->minSize))
- continue;
- if (SWAP(pSizeRec->nameCode) < 256)
- continue;
- if (SWAP(pSizeRec->nameCode) > 32767)
- continue;
- // looks like we've found a usable feature!
- theFont->opSizeInfo.designSize = SWAP(pSizeRec->designSize);
- theFont->opSizeInfo.subFamilyID = SWAP(pSizeRec->subFamilyID);
- theFont->opSizeInfo.nameCode = SWAP(pSizeRec->nameCode);
- theFont->opSizeInfo.minSize = SWAP(pSizeRec->minSize);
- theFont->opSizeInfo.maxSize = SWAP(pSizeRec->maxSize);
- break;
- }
- break;
- }
- }
+ const OpSizeRec* pSizeRec = getOpSizePtr(font);
+ if (pSizeRec != NULL) {
+ theFont->opSizeInfo.designSize = SWAP(pSizeRec->designSize);
+ if (SWAP(pSizeRec->subFamilyID) == 0
+ && SWAP(pSizeRec->nameCode) == 0
+ && SWAP(pSizeRec->minSize) == 0
+ && SWAP(pSizeRec->maxSize) == 0)
+ goto done_size; // feature is valid, but no 'size' range
+ theFont->opSizeInfo.subFamilyID = SWAP(pSizeRec->subFamilyID);
+ theFont->opSizeInfo.nameCode = SWAP(pSizeRec->nameCode);
+ theFont->opSizeInfo.minSize = SWAP(pSizeRec->minSize);
+ theFont->opSizeInfo.maxSize = SWAP(pSizeRec->maxSize);
}
+ done_size:
const OS2TableHeader* os2Table = (const OS2TableHeader*)getFontTablePtr(font, LE_OS_2_TABLE_TAG);
if (os2Table != NULL) {
diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.h b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.h
index b82194afb07..44e2bcade75 100644
--- a/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.h
+++ b/Build/source/texk/web2c/xetexdir/XeTeXFontMgr.h
@@ -43,6 +43,8 @@ typedef ATSFontRef PlatformFontRef;
typedef FcPattern* PlatformFontRef;
#endif
+#include "XeTeXLayoutInterface.h"
+
#ifdef __cplusplus /* allow inclusion in plain C files just to get the typedefs above */
#include <string>
@@ -83,6 +85,7 @@ public:
const char** famName, const char** styName) const;
// return Postscript, family, and style names, for use in .xdv
+ double getDesignSize(XeTeXFont font);
char getReqEngine() const;
// return the requested rendering technology for the most recent findFont
@@ -118,7 +121,8 @@ protected:
, parent(NULL)
, fontRef(ref), weight(0), width(0), slant(0)
, isReg(false), isBold(false), isItalic(false)
- { opSizeInfo.subFamilyID = 0; }
+ { opSizeInfo.subFamilyID = 0;
+ opSizeInfo.designSize = 100; } /* default to 10bp */
~Font()
{ delete fullName; delete psName; }
@@ -181,6 +185,8 @@ protected:
void prependToList(std::list<std::string>* list, const char* str);
void addToMaps(PlatformFontRef platformFont, const NameCollection* names);
+ const OpSizeRec* getOpSizePtr(XeTeXFont font);
+
virtual void getOpSizeRecAndStyleFlags(Font* theFont);
virtual void searchForHostPlatformFonts(const std::string& name) = 0;
diff --git a/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp b/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp
index a591d7a05a4..b5d179dd5fe 100644
--- a/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp
+++ b/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.cpp
@@ -144,6 +144,11 @@ const char* getFullName(PlatformFontRef fontRef)
return XeTeXFontMgr::GetFontManager()->getFullName(fontRef);
}
+double getDesignSize(XeTeXFont font)
+{
+ return XeTeXFontMgr::GetFontManager()->getDesignSize(font);
+}
+
const char* getFontFilename(XeTeXLayoutEngine engine)
{
return engine->font->getFilename();
@@ -479,7 +484,7 @@ findGlyphInPostTable(const char* buffer, int tableSize, const char* glyphName)
switch (SWAP(p->format)) {
case 0x00010000:
{
- char* cp;
+ const char* cp;
while ((cp = appleGlyphNames[g]) != 0) {
if (strcmp(glyphName, cp) == 0)
return g;
diff --git a/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.h b/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.h
index d92cca16d91..620eb050773 100644
--- a/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.h
+++ b/Build/source/texk/web2c/xetexdir/XeTeXLayoutInterface.h
@@ -28,10 +28,22 @@ use or other dealings in this Software without prior written
authorization from SIL International.
\****************************************************************************/
+#ifndef XETEX_LAYOUT_INTERFACE_H
+#define XETEX_LAYOUT_INTERFACE_H 1
+
#ifdef XETEX_MAC
#include <Carbon/Carbon.h>
#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+typedef struct XeTeXFont_rec* XeTeXFont;
+typedef struct XeTeXLayoutEngine_rec* XeTeXLayoutEngine;
+#ifdef __cplusplus
+};
+#endif
+
#include "XeTeX_ext.h"
#include "XeTeXFontMgr.h"
@@ -39,9 +51,6 @@ authorization from SIL International.
extern "C" {
#endif
-typedef struct XeTeXFont_rec* XeTeXFont;
-typedef struct XeTeXLayoutEngine_rec* XeTeXLayoutEngine;
-
extern char gPrefEngine;
int getCachedGlyphBBox(UInt16 fontID, UInt16 glyphID, GlyphBBox* bbox);
@@ -67,6 +76,7 @@ const char* getFullName(PlatformFontRef fontRef);
const char* getFontFilename(XeTeXLayoutEngine engine);
void getNames(PlatformFontRef fontRef, const char** psName, const char** famName, const char** styName);
+double getDesignSize(XeTeXFont font);
void deleteFont(XeTeXFont font);
@@ -139,3 +149,6 @@ int getFontCharRange(XeTeXLayoutEngine engine, int reqFirst);
#ifdef __cplusplus
};
#endif
+
+#endif /* XETEX_LAYOUT_INTERFACE_H */
+
diff --git a/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp b/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp
index d8ef3ed3a04..5583b31c337 100644
--- a/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp
+++ b/Build/source/texk/web2c/xetexdir/XeTeXOTLayoutEngine.cpp
@@ -129,7 +129,7 @@ LayoutEngine* XeTeXOTLayoutEngine::LayoutEngineFactory
break;
case arabScriptCode:
- case hebrScriptCode:
+// case hebrScriptCode:
result = new UnicodeArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
break;
diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_ext.c b/Build/source/texk/web2c/xetexdir/XeTeX_ext.c
index a4b467bb10c..24d5bd93bb8 100644
--- a/Build/source/texk/web2c/xetexdir/XeTeX_ext.c
+++ b/Build/source/texk/web2c/xetexdir/XeTeX_ext.c
@@ -710,9 +710,9 @@ loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const cha
if (strncmp(cp1, "vertical", 8) == 0) {
cp3 = cp2;
- if (*cp3 == ';' || *cp3 == ':')
+ if (*cp3 == ';' || *cp3 == ':' || *cp3 == ',')
--cp3;
- while (*cp3 == ' ' || *cp3 == '\t')
+ while (*cp3 == '\0' || *cp3 == ' ' || *cp3 == '\t')
--cp3;
if (*cp3)
++cp3;
@@ -763,10 +763,11 @@ loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const cha
}
static void
-splitFontName(char* name, char** var, char** feat, char** end)
+splitFontName(char* name, char** var, char** feat, char** end, int* index)
{
*var = NULL;
*feat = NULL;
+ *index = 0;
if (*name == '[') {
int withinFileName = 1;
#ifdef WIN32
@@ -784,8 +785,12 @@ splitFontName(char* name, char** var, char** feat, char** end)
#ifdef WIN32
&& !((name - start == 1) && isalpha(*start))
#endif
- )
- *var = name;
+ ) {
+ ++name;
+ while (*name >= '0' && *name <= '9')
+ *index = *index * 10 + *name++ - '0';
+ --name;
+ }
else if (!withinFileName && *feat == NULL)
*feat = name;
}
@@ -811,9 +816,9 @@ splitFontName(char* name, char** var, char** feat, char** end)
void*
findnativefont(unsigned char* uname, integer scaled_size)
- /* scaled_size here is in TeX points */
+ /* scaled_size here is in TeX points, or is a negative integer for 'scaled' */
{
- void* rval = 0;
+ void* rval = NULL;
char* nameString;
char* var;
char* feat;
@@ -823,13 +828,13 @@ findnativefont(unsigned char* uname, integer scaled_size)
char* featString = NULL;
PlatformFontRef fontRef;
XeTeXFont font;
+ int index = 0;
loadedfontmapping = NULL;
loadedfontflags = 0;
loadedfontletterspace = 0;
- splitFontName(name, &var, &feat, &end);
-
+ splitFontName(name, &var, &feat, &end, &index);
nameString = xmalloc(var - name + 1);
strncpy(nameString, name, var - name);
nameString[var - name] = 0;
@@ -854,16 +859,22 @@ findnativefont(unsigned char* uname, integer scaled_size)
if (path == NULL)
path = kpse_find_file(nameString + 1, kpse_type1_format, 0);
if (path != NULL) {
- int index = 0;
- if (varString != NULL) {
- char* cp;
- for (cp = varString; *cp && isdigit(*cp); ++cp)
- index = index * 10 + *cp - '0';
+ if (scaled_size < 0) {
+ font = createFontFromFile(path, index, 655360L);
+ if (font != NULL) {
+ Fixed dsize = X2Fix(getDesignSize(font));
+ if (scaled_size == -1000)
+ scaled_size = dsize;
+ else
+ scaled_size = zxnoverd(dsize, -scaled_size, 1000);
+ deleteFont(font);
+ }
}
font = createFontFromFile(path, index, scaled_size);
if (font != NULL) {
+ loadedfontdesignsize = X2Fix(getDesignSize(font));
rval = loadOTfont(0, font, scaled_size, featString);
- if (rval == 0)
+ if (rval == NULL)
deleteFont(font);
}
}
@@ -883,6 +894,18 @@ findnativefont(unsigned char* uname, integer scaled_size)
nameoffile = xmalloc(namelength + 4); /* +2 would be correct: initial space, final NUL */
nameoffile[0] = ' ';
strcpy((char*)nameoffile + 1, fullName);
+
+ if (scaled_size < 0) {
+ font = createFont(fontRef, scaled_size);
+ if (font != NULL) {
+ Fixed dsize = X2Fix(getDesignSize(font));
+ if (scaled_size == -1000)
+ scaled_size = dsize;
+ else
+ scaled_size = zxnoverd(dsize, -scaled_size, 1000);
+ deleteFont(font);
+ }
+ }
#ifdef XETEX_MAC
/* decide whether to use AAT or OpenType rendering with this font */
@@ -1568,7 +1591,7 @@ measure_native_node(void* pNode, int use_glyph_metrics)
for (runIndex = 0; runIndex < nRuns; ++runIndex) {
dir = ubidi_getVisualRun(pBiDi, runIndex, &logicalStart, &length);
nGlyphs = layoutChars(engine, (UniChar*)txtPtr, logicalStart, length, txtLen,
- (dir == UBIDI_RTL), x, y, &status);
+ (dir == UBIDI_RTL), 0, 0, &status);
getGlyphs(engine, glyphs, &status);
getGlyphPositions(engine, positions, &status);
@@ -1576,13 +1599,13 @@ measure_native_node(void* pNode, int use_glyph_metrics)
for (i = 0; i < nGlyphs; ++i) {
if (glyphs[i] < 0xfffe) {
glyphIDs[realGlyphCount] = glyphs[i];
- locations[realGlyphCount].x = X2Fix(positions[2*i]);
- locations[realGlyphCount].y = X2Fix(positions[2*i+1]);
+ locations[realGlyphCount].x = X2Fix(positions[2*i] + x);
+ locations[realGlyphCount].y = X2Fix(positions[2*i+1] + y);
++realGlyphCount;
}
}
- x = positions[2*i];
- y = positions[2*i+1];
+ x += positions[2*i];
+ y += positions[2*i+1];
}
wid = x;
}
@@ -2299,10 +2322,22 @@ open_dvi_output(FILE** fptr)
if (*p++ == '\"')
++len;
len += strlen(outputdriver);
- len += 8; /* space for -o flag, quotes, NUL */
+ if (output_directory)
+ len += strlen(output_directory);
+ len += 10; /* space for -o flag, quotes, NUL */
+ for (p = (const char*)nameoffile+1; *p; p++)
+ if (*p == '\"')
+ ++len; /* allow extra space to escape quotes in filename */
cmd = xmalloc(len);
strcpy(cmd, outputdriver);
strcat(cmd, " -o \"");
+ if (output_directory) {
+ len = strlen(output_directory);
+ if (IS_DIR_SEP(output_directory[len-1]))
+ output_directory[len-1] = '\0';
+ strcat(cmd, output_directory);
+ strcat(cmd, "/");
+ }
q = cmd + strlen(cmd);
for (p = (const char*)nameoffile+1; *p; p++) {
if (*p == '\"')
@@ -2316,6 +2351,14 @@ open_dvi_output(FILE** fptr)
free(cmd);
cmd = cmd2;
}
+ if (output_directory) {
+ char *fullname = concat3(output_directory, "/", nameoffile+1);
+ free(nameoffile);
+ namelength = strlen(fullname);
+ nameoffile = (char*)xmalloc(namelength+2);
+ strcpy(nameoffile+1, fullname);
+ free(fullname);
+ }
*fptr = popen(cmd, "w");
free(cmd);
return (*fptr != 0);
diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_ext.h b/Build/source/texk/web2c/xetexdir/XeTeX_ext.h
index 9e37b3ca63e..65b1db3a0e9 100644
--- a/Build/source/texk/web2c/xetexdir/XeTeX_ext.h
+++ b/Build/source/texk/web2c/xetexdir/XeTeX_ext.h
@@ -260,6 +260,7 @@ extern "C" {
const char* getGlyphNamePtr(const char* buffer, int tableSize, UInt16 gid, int* len);
+ int countpdffilepages();
int find_pic_file(char** path, realrect* bounds, int pdfBoxType, int page);
int u_open_in(unicodefile* f, integer filefmt, const char* fopen_mode, integer mode, integer encodingData);
int open_dvi_output(FILE** fptr);
diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_mac.c b/Build/source/texk/web2c/xetexdir/XeTeX_mac.c
index 4c64a65feb4..5228c669ab9 100644
--- a/Build/source/texk/web2c/xetexdir/XeTeX_mac.c
+++ b/Build/source/texk/web2c/xetexdir/XeTeX_mac.c
@@ -961,6 +961,31 @@ loadAATfont(ATSFontRef fontRef, long scaled_size, const char* cp1)
}
int
+countpdffilepages()
+{
+ int rval = 0;
+
+ char* pic_path = kpse_find_file((char*)nameoffile + 1, kpse_pict_format, 1);
+ CFURLRef picFileURL = NULL;
+ if (pic_path) {
+ picFileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8*)pic_path, strlen(pic_path), false);
+ if (picFileURL != NULL) {
+ FSRef picFileRef;
+ CFURLGetFSRef(picFileURL, &picFileRef);
+ CGPDFDocumentRef document = CGPDFDocumentCreateWithURL(picFileURL);
+ if (document != NULL) {
+ rval = CGPDFDocumentGetNumberOfPages(document);
+ CGPDFDocumentRelease(document);
+ }
+ CFRelease(picFileURL);
+ }
+ free(pic_path);
+ }
+
+ return rval;
+}
+
+int
find_pic_file(char** path, realrect* bounds, int pdfBoxType, int page)
{
*path = NULL;
diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_pic.c b/Build/source/texk/web2c/xetexdir/XeTeX_pic.c
index a511b848038..9491e9d1a8a 100644
--- a/Build/source/texk/web2c/xetexdir/XeTeX_pic.c
+++ b/Build/source/texk/web2c/xetexdir/XeTeX_pic.c
@@ -32,6 +32,22 @@ XeTeX_pic.c
#include "jpegimage.h"
#include "bmpimage.h"
+
+int
+countpdffilepages()
+{
+ int rval = 0;
+
+ char* pic_path = kpse_find_file((char*)nameoffile + 1, kpse_pict_format, 1);
+ if (pic_path) {
+ rval = pdf_count_pages(pic_path);
+ free(pic_path);
+ }
+
+ return rval;
+}
+
+
/*
locate picture file from /nameoffile+1/ using kpathsearch
pdfBoxType indicates which pdf bounding box to use (0 for \XeTeXpicfile)
diff --git a/Build/source/texk/web2c/xetexdir/appleGlyphNames.c b/Build/source/texk/web2c/xetexdir/appleGlyphNames.c
index 21fe6cc6719..a036fb9c393 100644
--- a/Build/source/texk/web2c/xetexdir/appleGlyphNames.c
+++ b/Build/source/texk/web2c/xetexdir/appleGlyphNames.c
@@ -28,7 +28,7 @@ use or other dealings in this Software without prior written
authorization from SIL International.
\****************************************************************************/
-char* appleGlyphNames[] = {
+const char* appleGlyphNames[] = {
".notdef",
".null",
"nonmarkingreturn",
diff --git a/Build/source/texk/web2c/xetexdir/pdfimage.cpp b/Build/source/texk/web2c/xetexdir/pdfimage.cpp
index 21af77c6572..2c60d09c790 100644
--- a/Build/source/texk/web2c/xetexdir/pdfimage.cpp
+++ b/Build/source/texk/web2c/xetexdir/pdfimage.cpp
@@ -82,3 +82,25 @@ pdf_get_rect(char* filename, int page_num, int pdf_box, realrect* box)
return 0;
}
+
+int
+pdf_count_pages(char* filename)
+{
+ int pages = 0;
+ GString* name = new GString(filename);
+ PDFDoc* doc = new PDFDoc(name);
+
+ if (!doc) {
+ delete name;
+ return 0;
+ }
+
+ /* if the doc got created, it now owns name, so we mustn't delete it! */
+
+ if (doc->isOk())
+ pages = doc->getNumPages();
+
+ delete doc;
+
+ return pages;
+}
diff --git a/Build/source/texk/web2c/xetexdir/pdfimage.h b/Build/source/texk/web2c/xetexdir/pdfimage.h
index 0869c03aa1e..b2a77d9f311 100644
--- a/Build/source/texk/web2c/xetexdir/pdfimage.h
+++ b/Build/source/texk/web2c/xetexdir/pdfimage.h
@@ -20,6 +20,8 @@ extern "C" {
extern int pdf_get_rect(char* filename, int page_num, int pdf_box, realrect* box);
+extern int pdf_count_pages(char* filename);
+
#ifdef __cplusplus
};
#endif
diff --git a/Build/source/texk/web2c/xetexdir/pool2c.pl b/Build/source/texk/web2c/xetexdir/pool2c.pl
new file mode 100644
index 00000000000..c2628deab46
--- /dev/null
+++ b/Build/source/texk/web2c/xetexdir/pool2c.pl
@@ -0,0 +1,74 @@
+#! /usr/bin/perl
+
+# Convert web .pool file into C source
+# Result is an array of chars (bytes) containing the strings,
+# each prefixed by a length byte.
+# The function initpool() loads this data into TeX's pool.
+
+# usage: perl pool2c.pl NAME.pool
+# writes output to ${NAME}_pool.c if only one arg provided
+
+die "expected pool name as argument" unless $#ARGV >= 0;
+die "too many arguments" if $#ARGV > 1;
+
+$prog = `basename $ARGV[0] .pool`;
+chomp($prog);
+
+$outfile = ($#ARGV == 1) ? $ARGV[1] : "${prog}_pool.c";
+
+open IN, "< $ARGV[0]" or die "can't open input $ARGV[0]";
+open OUT, "> $outfile" or die "can't open output $outfile";
+
+print OUT <<__EOT__;
+/* This file is auto-generated from $ARGV[0] by pool2c.pl */
+#define EXTERN extern
+#include "${prog}d.h"
+
+#include <stdio.h>
+
+static unsigned char POOL[] =
+__EOT__
+$pool_len = 0;
+while (<IN>) {
+ chomp;
+ if (m/^([0-9]{2})(.*)$/) {
+ ($len, $str) = ($1, $2);
+ if (length($str) != $len) {
+ die "*** pool string length error:\n$_\n";
+ }
+ $str =~ s/(["\\])/\\$1/g;
+ $str =~ s/\?\?\?/\\?\\?\\?/g;
+ printf OUT "\t\"\\x%02X\" \"%s\"\n", $len, $str;
+ $pool_len += $len + 1;
+ }
+ elsif (m/^\*[0-9]+$/) {
+ last;
+ }
+ else {
+ die "*** unexpected line in pool file:\n$_\n";
+ }
+}
+
+close IN;
+
+print OUT <<__EOT__;
+ ;
+
+#define POOL_LEN $pool_len
+
+int initpool(int limit) {
+ int g = 0;
+ unsigned char *s = POOL;
+ while (s < POOL + POOL_LEN) {
+ int len = *s++;
+ if (poolptr + len >= limit)
+ return 0;
+ while (len-- > 0)
+ strpool[poolptr++] = *s++;
+ g = makestring();
+ }
+ return g;
+}
+__EOT__
+
+close OUT;
diff --git a/Build/source/texk/web2c/xetexdir/xetex-new.ch b/Build/source/texk/web2c/xetexdir/xetex-new.ch
index 5340b3fe061..07adba9e228 100644
--- a/Build/source/texk/web2c/xetexdir/xetex-new.ch
+++ b/Build/source/texk/web2c/xetexdir/xetex-new.ch
@@ -1,6 +1,6 @@
% /****************************************************************************\
% Part of the XeTeX typesetting system
-% copyright (c) 1994-2006 by SIL International
+% copyright (c) 1994-2008 by SIL International
% written by Jonathan Kew
%
% Permission is hereby granted, free of charge, to any person obtaining
@@ -55,8 +55,8 @@
@d eTeX_version_string=='-2.2' {current \eTeX\ version}
@d XeTeX_version=0
-@d XeTeX_revision==".996"
-@d XeTeX_version_string=='-0.996-patch1' {current \XeTeX\ version}
+@d XeTeX_revision==".996-patch2"
+@d XeTeX_version_string=='-0.996-patch2' {current \XeTeX\ version}
@z
@x
@@ -346,41 +346,80 @@ end
@z
@x
-name_of_file := xmalloc_array (ASCII_code, name_length + 1);
-@y
-name_of_file := xmalloc_array (UTF8_code, name_length + 1);
-@z
+@ When the \.{WEB} system program called \.{TANGLE} processes the \.{TEX.WEB}
+description that you are now reading, it outputs the \PASCAL\ program
+\.{TEX.PAS} and also a string pool file called \.{TEX.POOL}. The \.{INITEX}
+@.WEB@>@.INITEX@>
+program reads the latter file, where each string appears as a two-digit decimal
+length followed by the string itself, and the information is recorded in
+\TeX's string memory.
-@x
+@<Glob...@>=
+@!init @!pool_file:alpha_file; {the string-pool file output by \.{TANGLE}}
+tini
+
+@ @d bad_pool(#)==begin wake_up_terminal; write_ln(term_out,#);
+ a_close(pool_file); get_strings_started:=false; return;
+ end
+@<Read the other strings...@>=
+name_length := strlen (pool_name);
+name_of_file := xmalloc_array (ASCII_code, name_length + 1);
+strcpy (stringcast(name_of_file+1), pool_name); {copy the string}
+if a_open_in (pool_file, kpse_texpool_format) then
+ begin c:=false;
+ repeat @<Read one string, but return |false| if the
+ string memory space is getting too tight for comfort@>;
+ until c;
+ a_close(pool_file); get_strings_started:=true;
+ end
+else bad_pool('! I can''t read ', pool_name, '; bad path?')
+@.I can't read TEX.POOL@>
+
+@ @<Read one string...@>=
+begin if eof(pool_file) then bad_pool('! ', pool_name, ' has no check sum.');
+@.TEX.POOL has no check sum@>
+read(pool_file,m); read(pool_file,n); {read two digits of string length}
+if m='*' then @<Check the pool check sum@>
else begin if (xord[m]<"0")or(xord[m]>"9")or@|
(xord[n]<"0")or(xord[n]>"9") then
-@y
-else begin if (m<"0")or(m>"9")or@|
- (n<"0")or(n>"9") then
-@z
-
-@x
+ bad_pool('! ', pool_name, ' line doesn''t begin with two digits.');
+@.TEX.POOL line doesn't...@>
l:=xord[m]*10+xord[n]-"0"*11; {compute the length}
-@y
- l:=m*10+n-"0"*11; {compute the length}
-@z
-
-@x
+ if pool_ptr+l+string_vacancies>pool_size then
+ bad_pool('! You have to increase POOLSIZE.');
+@.You have to increase POOLSIZE@>
+ for k:=1 to l do
+ begin if eoln(pool_file) then m:=' '@+else read(pool_file,m);
append_char(xord[m]);
-@y
- append_char(m);
-@z
+ end;
+ read_ln(pool_file); g:=make_string;
+ end;
+end
-@x
-loop@+ begin if (xord[n]<"0")or(xord[n]>"9") then
-@y
-loop@+ begin if (n<"0")or(n>"9") then
-@z
+@ The \.{WEB} operation \.{@@\$} denotes the value that should be at the
+end of this \.{TEX.POOL} file; any other value means that the wrong pool
+file has been loaded.
+@^check sum@>
-@x
+@<Check the pool check sum@>=
+begin a:=0; k:=1;
+loop@+ begin if (xord[n]<"0")or(xord[n]>"9") then
+ bad_pool('! ', pool_name, ' check sum doesn''t have nine digits.');
+@.TEX.POOL check sum...@>
a:=10*a+xord[n]-"0";
+ if k=9 then goto done;
+ incr(k); read(pool_file,n);
+ end;
+done: if a<>@$ then
+ bad_pool('! ', pool_name, ' doesn''t match; tangle me again (or fix the path).');
+@.TEX.POOL doesn't match@>
+c:=true;
+end
@y
- a:=10*a+n-"0";
+@ @<Read the other strings...@>=
+if init_pool(pool_size-string_vacancies) = 0 then
+ get_strings_started:=false;
+get_strings_started:=true;
@z
@x
@@ -501,11 +540,23 @@ end else begin
end;
exit:end;
+@ @d native_room(#)==while native_text_size <= native_len+# do begin
+ native_text_size:=native_text_size+128;
+ native_text:=xrealloc(native_text, native_text_size * sizeof(UTF16_code));
+ end
+@d append_native(#)==begin native_text[native_len]:=#; incr(native_len); end
+
@ @<Glob...@>=
-doing_special: boolean;
+@!doing_special: boolean;
+@!native_text: ^UTF16_code; { buffer for collecting native-font strings }
+@!native_text_size: integer; { size of buffer }
+@!native_len: integer;
+@!save_native_len: integer;
@ @<Set init...@>=
doing_special:=false;
+native_text_size:=128;
+native_text:=xmalloc(native_text_size * sizeof(UTF16_code));
@z
@x
@@ -710,8 +761,7 @@ and then a word containing a size field for the node, a font number, a length, a
Then there is a field containing a C pointer to a glyph info array;
this and the glyph count are set by |set_native_metrics|.
Copying and freeing of these nodes needs to take account of this!
-This is followed by |length| bytes, for the actual characters of the string.
-(Yes, we count in bytes, even though what we store there is UTF-16.)
+This is followed by |2*length| bytes, for the actual characters of the string (in UTF-16).
So |native_node_size|, which does not include any space for the actual text, is 6.}
@@ -1142,9 +1192,10 @@ else begin print_esc("scriptscriptfont");
@d eTeX_state_code=etex_int_base+9 {\eTeX\ state variables}
@d etex_int_pars=eTeX_state_code+eTeX_states {total number of \eTeX's integer parameters}
@y
-@d XeTeX_linebreak_locale_code=etex_int_base+9 {string number of locale to use for linebreak locations}
-@d XeTeX_linebreak_penalty_code=etex_int_base+10 {penalty to use at locale-dependent linebreak locations}
-@d eTeX_state_code=etex_int_base+11 {\eTeX\ state variables}
+@d suppress_fontnotfound_error_code=etex_int_base+9 {suppress errors for missing fonts}
+@d XeTeX_linebreak_locale_code=etex_int_base+10 {string number of locale to use for linebreak locations}
+@d XeTeX_linebreak_penalty_code=etex_int_base+11 {penalty to use at locale-dependent linebreak locations}
+@d eTeX_state_code=etex_int_base+12 {\eTeX\ state variables}
@d etex_int_pars=eTeX_state_code+eTeX_states {total number of \eTeX's integer parameters}
@z
@@ -1162,6 +1213,7 @@ else begin print_esc("scriptscriptfont");
@d saving_hyph_codes==int_par(saving_hyph_codes_code)
@y
@d saving_hyph_codes==int_par(saving_hyph_codes_code)
+@d suppress_fontnotfound_error==int_par(suppress_fontnotfound_error_code)
@d XeTeX_linebreak_locale==int_par(XeTeX_linebreak_locale_code)
@d XeTeX_linebreak_penalty==int_par(XeTeX_linebreak_penalty_code)
@z
@@ -1805,7 +1857,7 @@ end
@#
@d XeTeX_int=eTeX_int+8 {first of \XeTeX\ codes for integers}
@#
-@d eTeX_dim=XeTeX_int+29 {first of \eTeX\ codes for dimensions}
+@d eTeX_dim=XeTeX_int+30 {first of \eTeX\ codes for dimensions}
{changed for \XeTeX\ to make room for \XeTeX\ integers}
@z
@@ -2536,6 +2588,7 @@ loop@+begin if (cur_cmd>other_char)or(cur_chr>biggest_char) then
@!loaded_font_mapping: void_pointer; { used by load_native_font to return mapping, if any }
@!loaded_font_flags: char; { used by load_native_font to return flags }
@!loaded_font_letter_space: scaled;
+@!loaded_font_design_size: scaled;
@!mapped_text: ^UTF16_code; { scratch buffer used while applying font mappings }
@!xdv_buffer: ^char; { scratch buffer used in generating XDV output }
@z
@@ -2548,9 +2601,9 @@ pack_file_name(nom,aire,cur_ext);
if quoted_filename then begin
{ quoted name, so try for a native font }
g:=load_native_font(u,nom,aire,s);
- if g=null_font then goto bad_tfm else goto done;
+ if g<>null_font then goto done;
end;
-{ it was an unquoted name, so try for a TFM file }
+{ it was an unquoted name, or not found as an installed font, so try for a TFM file }
@<Read and check the font data if file exists;
|abort| if the \.{TFM} file is
@z
@@ -2559,16 +2612,15 @@ end;
bad_tfm: @<Report that the font won't be loaded@>;
@y
if g<>null_font then goto done;
-if file_name_quote_char=0 then begin
+if not quoted_filename then begin
{ we failed to find a TFM file, so try for a native font }
g:=load_native_font(u,nom,aire,s);
if g<>null_font then goto done
end;
bad_tfm:
-if (not file_opened) and (file_name_quote_char<>0) then begin
- @<Report that native font couldn't be found, and |goto done|@>;
-end;
-@<Report that the font won't be loaded@>;
+if suppress_fontnotfound_error=0 then begin
+ @<Report that the font won't be loaded@>;
+ end;
@z
@x
@@ -2593,17 +2645,6 @@ else print(" not loadable: Metric (TFM) file or installed font not found");
@ @<Read and check...@>=
@<Open |tfm_file| for input@>;
@y
-@ @<Report that native font couldn't be found, and |goto done|@>=
-start_font_error_message;
-@.Font x=xx not loadable...@>
-print(" not loadable: installed font not found");
-help4("I wasn't able to find this font in the Mac OS,")@/
-("so I will ignore the font specification.")@/
-("You might try inserting a different font spec;")@/
-("e.g., type `I\font<same font id>=<substitute font name>'.");
-error;
-goto done
-
@ @<Read and check...@>=
@<Open |tfm_file| for input and |begin|@>;
@z
@@ -2945,21 +2986,22 @@ while (q <> null) and (not is_char_node(q)) and (type(q) = disc_node) do
dvi_four(last_bop); last_bop:=page_loc;
@y
dvi_four(last_bop); last_bop:=page_loc;
+{ generate a pagesize \special at start of page }
+old_setting:=selector; selector:=new_string;
+print("pdf:pagesize ");
if (pdf_page_width > 0) and (pdf_page_height > 0) then begin
- { generate a papersize \special at start of page }
- old_setting:=selector; selector:=new_string;
- print("papersize ");
- if mag=1000 then print_scaled(pdf_page_width)
- else print_scaled(xn_over_d(pdf_page_width,mag,1000));
- print("pt"); print(",");
- if mag=1000 then print_scaled(pdf_page_height)
- else print_scaled(xn_over_d(pdf_page_height,mag,1000));
+ print("width"); print(" ");
+ print_scaled(pdf_page_width);
+ print("pt"); print(" ");
+ print("height"); print(" ");
+ print_scaled(pdf_page_height);
print("pt");
- selector:=old_setting;
- dvi_out(xxx1); dvi_out(cur_length);
- for s:=str_start_macro(str_ptr) to pool_ptr-1 do dvi_out(so(str_pool[s]));
- pool_ptr:=str_start_macro(str_ptr); {erase the string}
-end;
+end else
+ print("default");
+selector:=old_setting;
+dvi_out(xxx1); dvi_out(cur_length);
+for s:=str_start_macro(str_ptr) to pool_ptr-1 do dvi_out(so(str_pool[s]));
+pool_ptr:=str_start_macro(str_ptr); {erase the string}
@z
@x
@@ -3786,27 +3828,27 @@ hmode+char_num: begin scan_usv_num; cur_chr:=cur_val; goto main_loop;@+end;
@x
adjust_space_factor;@/
@y
-
{ added code for native font support }
if is_native_font(cur_font) then begin
if mode>0 then if language<>clang then fix_language;
main_h := 0;
main_f := cur_font;
-
+ native_len := 0;
+
collect_native:
adjust_space_factor;
if (cur_chr > @"FFFF) then begin
- str_room(2);
- append_char((cur_chr - @"10000) div 1024 + @"D800);
- append_char((cur_chr - @"10000) mod 1024 + @"DC00);
+ native_room(2);
+ append_native((cur_chr - @"10000) div 1024 + @"D800);
+ append_native((cur_chr - @"10000) mod 1024 + @"DC00);
end else begin
- str_room(1);
- append_char(cur_chr);
+ native_room(1);
+ append_native(cur_chr);
end;
is_hyph := (cur_chr = hyphen_char[main_f])
or (XeTeX_dash_break_en and (cur_chr = @"2014) or (cur_chr = @"2013));
- if (main_h = 0) and is_hyph then main_h := cur_length;
+ if (main_h = 0) and is_hyph then main_h := native_len;
{try to collect as many chars as possible in the same font}
get_next;
@@ -3820,27 +3862,26 @@ collect_native:
end;
if (font_mapping[main_f] <> 0) then begin
- main_k := apply_mapping(font_mapping[main_f], address_of(str_pool[str_start_macro(str_ptr)]), cur_length);
- pool_ptr := str_start_macro(str_ptr); { flush the string, as we'll be using the mapped text instead }
- str_room(main_k);
+ main_k := apply_mapping(font_mapping[main_f], native_text, native_len);
+ native_len := 0;
+ native_room(main_k);
main_h := 0;
for main_p := 0 to main_k - 1 do begin
- append_char(mapped_text[main_p]);
+ append_native(mapped_text[main_p]);
if (main_h = 0) and ((mapped_text[main_p] = hyphen_char[main_f])
or (XeTeX_dash_break_en and ((mapped_text[main_p] = @"2014) or (mapped_text[main_p] = @"2013)) ) )
- then main_h := cur_length;
+ then main_h := native_len;
end
end;
if tracing_lost_chars > 0 then begin
- temp_ptr := str_start_macro(str_ptr);
- main_p := temp_ptr + cur_length;
- while (temp_ptr < main_p) do begin
- main_k := str_pool[temp_ptr];
+ temp_ptr := 0;
+ while (temp_ptr < native_len) do begin
+ main_k := native_text[temp_ptr];
incr(temp_ptr);
if (main_k >= @"D800) and (main_k < @"DC00) then begin
main_k := @"10000 + (main_k - @"D800) * 1024;
- main_k := main_k + str_pool[temp_ptr] - @"DC00;
+ main_k := main_k + native_text[temp_ptr] - @"DC00;
incr(temp_ptr);
end;
if map_char_to_glyph(main_f, main_k) = 0 then
@@ -3848,48 +3889,54 @@ collect_native:
end
end;
- main_k := cur_length;
+ main_k := native_len;
main_pp := tail;
if mode=hmode then begin
main_ppp := head;
- if main_ppp<>main_pp then
- while (link(main_ppp)<>main_pp) do
- main_ppp:=link(main_ppp); { find node preceding tail }
+ if main_ppp<>main_pp then { find node preceding tail, skipping discretionaries }
+ while (link(main_ppp)<>main_pp) do begin
+ if (not is_char_node(main_ppp)) and (type(main_ppp=disc_node)) then begin
+ temp_ptr:=main_ppp;
+ for main_p:=1 to replace_count(temp_ptr) do main_ppp:=link(main_ppp);
+ end;
+ if main_ppp<>main_pp then main_ppp:=link(main_ppp);
+ end;
- temp_ptr := str_start_macro(str_ptr);
+ temp_ptr := 0;
repeat
if main_h = 0 then main_h := main_k;
- if (not is_char_node(main_pp))
+ if (not is_char_node(main_pp))
and (type(main_pp)=whatsit_node)
and (subtype(main_pp)=native_word_node)
and (native_font(main_pp)=main_f)
and (main_ppp<>main_pp)
- and type(main_ppp)<>disc_node
+ and (not is_char_node(main_ppp))
+ and (type(main_ppp)<>disc_node)
then begin
{ make a new temp string that contains the concatenated text of |tail| + the current word/fragment }
main_k := main_h + native_length(main_pp);
- str_room(main_k);
+ native_room(main_k);
- temp_ptr := pool_ptr;
+ save_native_len := native_len;
for main_p := 0 to native_length(main_pp) - 1 do
- append_char(get_native_char(main_pp, main_p));
- for main_p := str_start_macro(str_ptr) to temp_ptr - 1 do
- append_char(str_pool[main_p]);
+ append_native(get_native_char(main_pp, main_p));
+ for main_p := 0 to main_h - 1 do
+ append_native(native_text[temp_ptr + main_p]);
- do_locale_linebreaks(temp_ptr, main_k);
+ do_locale_linebreaks(save_native_len, main_k);
- pool_ptr := temp_ptr; { discard the temp string }
- main_k := cur_length - main_h; { and set main_k to remaining length of new word }
- temp_ptr := str_start_macro(str_ptr) + main_h; { pointer to remaining fragment }
+ native_len := save_native_len; { discard the temp string }
+ main_k := native_len - main_h - temp_ptr; { and set main_k to remaining length of new word }
+ temp_ptr := main_h; { pointer to remaining fragment }
main_h := 0;
- while (main_h < main_k) and (str_pool[temp_ptr + main_h] <> hyphen_char[main_f])
+ while (main_h < main_k) and (native_text[temp_ptr + main_h] <> hyphen_char[main_f])
and ( (not XeTeX_dash_break_en)
- or ((str_pool[temp_ptr + main_h] <> @"2014) and (str_pool[temp_ptr + main_h] <> @"2013)) )
+ or ((native_text[temp_ptr + main_h] <> @"2014) and (native_text[temp_ptr + main_h] <> @"2013)) )
do incr(main_h); { look for next hyphen or end of text }
if (main_h < main_k) then incr(main_h);
@@ -3909,9 +3956,9 @@ collect_native:
main_k := main_k - main_h; { decrement remaining length }
main_h := 0;
- while (main_h < main_k) and (str_pool[temp_ptr + main_h] <> hyphen_char[main_f])
+ while (main_h < main_k) and (native_text[temp_ptr + main_h] <> hyphen_char[main_f])
and ( (not XeTeX_dash_break_en)
- or ((str_pool[temp_ptr + main_h] <> @"2014) and (str_pool[temp_ptr + main_h] <> @"2013)) )
+ or ((native_text[temp_ptr + main_h] <> @"2014) and (native_text[temp_ptr + main_h] <> @"2013)) )
do incr(main_h); { look for next hyphen or end of text }
if (main_h < main_k) then incr(main_h);
@@ -3920,6 +3967,7 @@ collect_native:
if (main_k > 0) or is_hyph then begin
tail_append(new_disc); { add a break if we aren't at end of text (must be a hyphen),
or if last char in original text was a hyphen }
+ main_pp:=tail;
end;
until main_k = 0;
@@ -3935,7 +3983,7 @@ collect_native:
set_native_char(tail, main_p, get_native_char(main_pp, main_p));
{ append the new text }
for main_p := 0 to main_k - 1 do
- set_native_char(tail, main_p + native_length(main_pp), str_pool[str_start_macro(str_ptr) + main_p]);
+ set_native_char(tail, main_p + native_length(main_pp), native_text[main_p]);
set_native_metrics(tail, XeTeX_use_glyph_metrics);
{ remove the preceding node from the list }
@@ -3951,12 +3999,11 @@ collect_native:
link(main_pp) := new_native_word_node(main_f, main_k);
tail := link(main_pp);
for main_p := 0 to main_k - 1 do
- set_native_char(tail, main_p, str_pool[str_start_macro(str_ptr) + main_p]);
+ set_native_char(tail, main_p, native_text[main_p]);
set_native_metrics(tail, XeTeX_use_glyph_metrics);
end
end;
- pool_ptr := str_start_macro(str_ptr);
goto reswitch;
end;
{ End of added code for native fonts }
@@ -5004,16 +5051,39 @@ end else
@x
@ @d adv_past(#)==@+if subtype(#)=language_node then
- begin cur_lang:=what_lang(#); l_hyf:=what_lhm(#); r_hyf:=what_rhm(#);@+end
+ begin cur_lang:=what_lang(#); l_hyf:=what_lhm(#); r_hyf:=what_rhm(#);
+ set_hyph_index;
+ end
+
+@<Advance \(p)past a whatsit node in the \(l)|line_break| loop@>=@+
+adv_past(cur_p)
@y
-@ @d adv_past(#)==@+if subtype(#)=language_node then
- begin cur_lang:=what_lang(#); l_hyf:=what_lhm(#); r_hyf:=what_rhm(#);@+end
+@ @d adv_past_linebreak(#)==@+if subtype(#)=language_node then
+ begin cur_lang:=what_lang(#); l_hyf:=what_lhm(#); r_hyf:=what_rhm(#);
+ set_hyph_index;
+ end
else if (subtype(#)=native_word_node)
or (subtype(#)=glyph_node)
or (subtype(#)=pic_node)
or (subtype(#)=pdf_node)
then
begin act_width:=act_width+width(#); end
+
+@<Advance \(p)past a whatsit node in the \(l)|line_break| loop@>=@+
+adv_past_linebreak(cur_p)
+@z
+
+@x
+@ @<Advance \(p)past a whatsit node in the \(p)pre-hyphenation loop@>=@+
+adv_past(s)
+@y
+@ @d adv_past_prehyph(#)==@+if subtype(#)=language_node then
+ begin cur_lang:=what_lang(#); l_hyf:=what_lhm(#); r_hyf:=what_rhm(#);
+ set_hyph_index;
+ end
+
+@<Advance \(p)past a whatsit node in the \(p)pre-hyphenation loop@>=@+
+adv_past_prehyph(s)
@z
@x
@@ -5565,6 +5635,8 @@ end
@d pdf_last_x_pos_code = XeTeX_int+27
@d pdf_last_y_pos_code = XeTeX_int+28
+@d XeTeX_pdf_page_count_code = XeTeX_int+29
+
{ NB: must update eTeX_dim when items are added here! }
@z
@@ -5619,6 +5691,8 @@ primitive("XeTeXlastfontchar", last_item, XeTeX_last_char_code);
primitive("pdflastxpos",last_item,pdf_last_x_pos_code);
primitive("pdflastypos",last_item,pdf_last_y_pos_code);
+
+primitive("XeTeXpdfpagecount",last_item,XeTeX_pdf_page_count_code);
@z
@x
@@ -5662,6 +5736,8 @@ XeTeX_last_char_code: print_esc("XeTeXlastfontchar");
pdf_last_x_pos_code: print_esc("pdflastxpos");
pdf_last_y_pos_code: print_esc("pdflastypos");
+
+XeTeX_pdf_page_count_code: print_esc("XeTeXpdfpagecount");
@z
@x
@@ -5835,6 +5911,12 @@ XeTeX_first_char_code,XeTeX_last_char_code:
pdf_last_x_pos_code: cur_val := pdf_last_x_pos;
pdf_last_y_pos_code: cur_val := pdf_last_y_pos;
+XeTeX_pdf_page_count_code:
+ begin
+ scan_and_pack_name;
+ cur_val:=count_pdf_file_pages;
+ end;
+
@ Slip in an extra procedure here and there....
@<Error hand...@>=
@@ -5984,6 +6066,7 @@ font_char_ic_code: begin scan_font_ident; q:=cur_val; scan_usv_num;
@x
eTeX_state_code+TeXXeT_code:print_esc("TeXXeTstate");
@y
+suppress_fontnotfound_error_code:print_esc("suppressfontnotfounderror");
eTeX_state_code+TeXXeT_code:print_esc("TeXXeTstate");
eTeX_state_code+XeTeX_dash_break_code:print_esc("XeTeXdashbreakstate");
@z
@@ -6255,10 +6338,18 @@ begin
load_native_font := null_font;
- if (s < 0) then actual_size := -s * unity div 100 else actual_size := s;
- font_engine := find_native_font(name_of_file + 1, actual_size);
+ font_engine := find_native_font(name_of_file + 1, s);
if font_engine = 0 then goto done;
+ if s>=0 then
+ actual_size := s
+ else begin
+ if (s <> -1000) then
+ actual_size := xn_over_d(loaded_font_design_size,-s,1000)
+ else
+ actual_size := loaded_font_design_size;
+ end;
+
{ look again to see if the font is already loaded, now that we know its canonical name }
str_room(name_length);
for k := 1 to name_length do
@@ -6289,7 +6380,7 @@ begin
font_check[font_ptr].b2 := 0;
font_check[font_ptr].b3 := 0;
font_glue[font_ptr] := null;
- font_dsize[font_ptr] := 10 * unity;
+ font_dsize[font_ptr] := loaded_font_design_size;
font_size[font_ptr] := actual_size;
if (native_font_type_flag = aat_font_flag) then begin
@@ -6344,7 +6435,7 @@ begin
done:
end;
-procedure do_locale_linebreaks(s: pointer; len: integer);
+procedure do_locale_linebreaks(s: integer; len: integer);
var
offs, prevOffs, i: integer;
use_penalty, use_skip: boolean;
@@ -6353,12 +6444,12 @@ begin
link(tail) := new_native_word_node(main_f, len);
tail := link(tail);
for i := 0 to len - 1 do
- set_native_char(tail, i, str_pool[s + i]);
+ set_native_char(tail, i, native_text[s + i]);
set_native_metrics(tail, XeTeX_use_glyph_metrics);
end else begin
use_skip := XeTeX_linebreak_skip <> zero_glue;
use_penalty := XeTeX_linebreak_penalty <> 0 or not use_skip;
- linebreak_start(XeTeX_linebreak_locale, address_of(str_pool[s]), len);
+ linebreak_start(XeTeX_linebreak_locale, native_text + s, len);
offs := 0;
repeat
prevOffs := offs;
@@ -6373,7 +6464,7 @@ begin
link(tail) := new_native_word_node(main_f, offs - prevOffs);
tail := link(tail);
for i := prevOffs to offs - 1 do
- set_native_char(tail, i - prevOffs, str_pool[s + i]);
+ set_native_char(tail, i - prevOffs, native_text[s + i]);
set_native_metrics(tail, XeTeX_use_glyph_metrics);
end;
until offs < 0;
diff --git a/Build/source/texk/web2c/xetexdir/xetex.defines b/Build/source/texk/web2c/xetexdir/xetex.defines
index 218d8228c97..11d03e5ecd2 100644
--- a/Build/source/texk/web2c/xetexdir/xetex.defines
+++ b/Build/source/texk/web2c/xetexdir/xetex.defines
@@ -61,6 +61,7 @@ authorization from SIL International.
@define procedure printutf8str();
@define procedure setinputfileencoding();
@define procedure terminatefontmanager;
+@define function initpool();
@define procedure memcpy();
@define function casttoptr();
@@ -133,6 +134,7 @@ authorization from SIL International.
@define function findpicfile();
@define function picpathbyte();
+@define function countpdffilepages;
@define procedure makeidentity();
@define procedure makescale();
diff --git a/Build/source/texk/web2c/xetexdir/xetex.mk b/Build/source/texk/web2c/xetexdir/xetex.mk
index 0c54f08a093..621bd99a629 100644
--- a/Build/source/texk/web2c/xetexdir/xetex.mk
+++ b/Build/source/texk/web2c/xetexdir/xetex.mk
@@ -108,10 +108,16 @@ xetexdir/xetex.version: $(srcdir)/xetexdir/xetex-new.ch
grep '^@d XeTeX_version_string==' $(srcdir)/xetexdir/xetex-new.ch \
| sed "s/^.*'-//;s/'.*$$//" >xetexdir/xetex.version
+# Extract etex version
+xetexdir/etex.version: $(srcdir)/etexdir/etex.ch
+ test -d xetexdir || mkdir xetexdir
+ grep '^@d eTeX_version_string==' $(srcdir)/etexdir/etex.ch \
+ | sed "s/^.*'-//;s/'.*$$//" >xetexdir/etex.version
+
# The C sources.
xetex_c = xetexini.c xetex0.c xetex1.c xetex2.c
xetex_o = xetexini.o xetex0.o xetex1.o xetex2.o xetexextra.o
-xetex_add_o = trans.o XeTeX_ext.o $(xetex_platform_o)
+xetex_add_o = trans.o XeTeX_ext.o xetex_pool.o $(xetex_platform_o)
# these compilations require the path to TECkit headers;
# just setting it in XCFLAGS doesn't seem to work when we're called
@@ -126,6 +132,8 @@ xetex2.o: xetex2.c $(srcdir)/xetexdir/XeTeX_ext.h
$(compile) $(TECKITFLAGS) $(ALL_CFLAGS) $(XETEX_DEFINES) -c $< -o $@
xetexextra.o: xetexextra.c $(srcdir)/xetexdir/XeTeX_ext.h
$(compile) $(TECKITFLAGS) $(ALL_CFLAGS) $(XETEX_DEFINES) -c $< -o $@
+xetex_pool.o: xetex_pool.c $(srcdir)/xetexdir/XeTeX_ext.h
+ $(compile) $(TECKITFLAGS) $(ALL_CFLAGS) $(XETEX_DEFINES) -c $< -o $@
# image support
mfileio.o: $(srcdir)/xetexdir/mfileio.c $(srcdir)/xetexdir/mfileio.h
@@ -205,11 +213,15 @@ $(xetex_c) xetexcoerce.h xetexd.h: xetex.p $(web2c_texmf)
$(web2c) xetex
xetexextra.c: lib/texmfmp.c xetexdir/xetexextra.h
sed s/TEX-OR-MF-OR-MP/xetex/ $(srcdir)/lib/texmfmp.c >$@
-xetexdir/xetexextra.h: xetexdir/xetexextra.in xetexdir/xetex.version
+xetexdir/xetexextra.h: xetexdir/xetexextra.in xetexdir/xetex.version xetexdir/etex.version
test -d xetexdir || mkdir xetexdir
- sed s/XETEX-VERSION/`cat xetexdir/xetex.version`/ \
+ sed -e s/XETEX-VERSION/`cat xetexdir/xetex.version`/ \
+ -e s/ETEX-VERSION/`cat xetexdir/etex.version`/ \
$(srcdir)/xetexdir/xetexextra.in >$@
+xetex_pool.c: xetex.pool
+ perl $(srcdir)/xetexdir/pool2c.pl $< $@
+
# Tangling
xetex.p xetex.pool: ./otangle xetex.web # xetex.ch
./otangle xetex.web # xetex.ch
@@ -258,7 +270,7 @@ xetex.web: tie xetexdir/xetex.mk $(xetex_web_srcs)
clean:: xetex-clean
xetex-clean: # etrip-clean
$(LIBTOOL) --mode=clean $(RM) xetex
- rm -f $(xetex_o) $(xetex_c) xetexextra.c xetexcoerce.h xetexd.h
+ rm -f $(xetex_o) $(xetex_c) xetexextra.c xetex_pool.c xetexcoerce.h xetexd.h
rm -f xetexdir/xetexextra.h xetexdir/xetex.version
rm -f xetex.p xetex.pool xetex.web xetex.ch
rm -f xetex.fmt xetex.log
@@ -289,7 +301,7 @@ xelatex.fmt: xetex
# Install
install-xetex: install-xetex-exec install-xetex-data
install-xetex-exec: install-xetex-programs install-xetex-links
-install-xetex-data: install-xetex-pool @FMU@ install-xetex-dumps
+install-xetex-data: @FMU@ install-xetex-dumps
install-xetex-dumps: install-xetex-fmts
install-programs: @XETEX@ install-xetex-programs
@@ -310,7 +322,5 @@ install-xetex-fmts: xefmts $(xefmtdir)
(cd ${DESTDIR}$(bindir) && (rm -f $$base; $(LN) xetex $$base)); done
install-data:: @XETEX@ install-xetex-data
-install-xetex-pool: xetex.pool $(texpooldir)
- $(INSTALL_DATA) xetex.pool ${DESTDIR}$(texpooldir)/xetex.pool
# end of xetex.mk
diff --git a/Build/source/texk/web2c/xetexdir/xetexextra.in b/Build/source/texk/web2c/xetexdir/xetexextra.in
index 9286d98fe37..e9e883ab3b7 100644
--- a/Build/source/texk/web2c/xetexdir/xetexextra.in
+++ b/Build/source/texk/web2c/xetexdir/xetexextra.in
@@ -51,7 +51,7 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define BANNER "This is XeTeX, Version 3.141592-XETEX-VERSION"
+#define BANNER "This is XeTeX, Version 3.141592-ETEX-VERSION-XETEX-VERSION"
#define COPYRIGHT_HOLDER "SIL International"
#define AUTHOR "Jonathan Kew"
#define PROGRAM_HELP XETEXHELP