2025-04-27 07:49:33 -04:00

589 lines
12 KiB
C

/*
* udgtt - un-dump GTT file
*
* TODO:
*
* HISTORY:
*
* 4/28/99 yasuho Created.
*/
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdarg.h>
#include <windef.h>
#include <wingdi.h>
#include <winddi.h>
#include <prntfont.h>
FILE *infile, *outfile, *logfile;
UNI_GLYPHSETDATA Header;
UNI_CODEPAGEINFO *pCpCmdInfo;
MAPTABLE *pMapTable;
GLYPHRUN *pRuns;
typedef struct {
WORD wUc;
INT iCp;
BYTE jType;
BYTE *pCmd;
INT iCmdLen;
} GINFO;
typedef struct {
BYTE *pCmdSel;
INT iCmdSelLen;
BYTE *pCmdUnsel;
INT iCmdUnselLen;
} CINFO;
GINFO *pGInfo;
CINFO *pCInfo;
INT bVerbose;
BYTE buf[512];
BYTE Cmd[512];
INT iCmdLen;
char *namestr = "udgtt";
char *usagestr = "udgtt [-v] gttfile [txtfile]";
#include "utils.c"
VOID
LoadHeader()
{
DWORD dwTemp;
INT k;
k = 0;
while (1) {
if (NULL == fgets(buf, sizeof(buf), infile)) {
*buf = '\0';
return;
}
if (';' == *buf)
break;
switch (k++) {
case 0:
sscanf(buf, "%lx", &dwTemp);
Header.dwVersion = dwTemp;
break;
case 1:
sscanf(buf, "%lx", &dwTemp);
Header.dwFlags = dwTemp;
break;
case 2:
sscanf(buf, "%ld", &dwTemp);
Header.lPredefinedID = dwTemp;
break;
}
}
if (bVerbose) {
fprintf(logfile, "dwVersion=%lx\n", Header.dwVersion);
fprintf(logfile, "dwFlags=%lx\n", Header.dwFlags);
fprintf(logfile, "lPredefinedID=%ld\n", Header.lPredefinedID);
}
}
int
LoadNumValue(
BYTE **ppBuf)
{
BYTE *pTemp;
INT iRet;
pTemp = *ppBuf;
if (isspace(*pTemp)) {
while (isspace(*pTemp))
pTemp++;
}
if ('X' == *pTemp || 'x' == *pTemp || isdigit(*pTemp)) {
if ('X' == *pTemp || 'x' == *pTemp) {
pTemp++;
sscanf(pTemp, "%x", &iRet);
}
else {
sscanf(pTemp, "%d", &iRet);
}
while (isxdigit(*pTemp))
pTemp++;
}
*ppBuf = pTemp;
return iRet;
}
VOID
LoadCmdString(
BYTE *pTemp)
{
INT k;
INT iTemp;
k = 0;
while (*pTemp) {
if (isspace(*pTemp)) {
while (isspace(*pTemp))
pTemp++;
}
if (';' == *pTemp) {
break;
}
iTemp = LoadNumValue(&pTemp);
Cmd[k++] = (BYTE)iTemp;
}
iCmdLen = k;
}
VOID
LoadCpInfo()
{
DWORD dwTemp;
INT j, k, n;
fgets(buf, sizeof(buf), infile);
sscanf(buf, "%ld", &dwTemp);
Header.dwCodePageCount = dwTemp;
pCInfo = (CINFO *)calloc(1, sizeof (CINFO) * dwTemp);
pCpCmdInfo = (UNI_CODEPAGEINFO *)calloc(1,
sizeof (UNI_CODEPAGEINFO) * dwTemp);
k = 0;
j = 0;
while (1) {
if (NULL == fgets(buf, sizeof(buf), infile)) {
*buf = '\0';
return;
}
if (';' == *buf)
break;
switch ((k++) % 3) {
case 0:
sscanf(buf, "%ld", &dwTemp);
pCpCmdInfo[j].dwCodePage = dwTemp;
break;
case 1:
LoadCmdString(buf);
pCInfo[j].pCmdSel = calloc(1, iCmdLen);
memcpy(pCInfo[j].pCmdSel, Cmd, iCmdLen);
pCInfo[j].iCmdSelLen = iCmdLen;
break;
case 2:
LoadCmdString(buf);
pCInfo[j].pCmdUnsel = calloc(1, iCmdLen);
memcpy(pCInfo[j].pCmdUnsel, Cmd, iCmdLen);
pCInfo[j].iCmdUnselLen = iCmdLen;
j++;
break;
}
}
if (bVerbose) {
fprintf(logfile, "dwCodePageCount=%ld\n", Header.dwCodePageCount);
}
}
VOID
LoadGlyphInfoInternal(
GINFO *pGI,
BYTE *s)
{
INT iTemp;
BYTE *pTemp;
INT k;
pTemp = s;
sscanf(pTemp, "%04x", &iTemp);
pGI->wUc = iTemp;
pTemp += 4;
iTemp = LoadNumValue(&pTemp);
pGI->iCp = iTemp;
iTemp = LoadNumValue(&pTemp);
pGI->jType = iTemp;
LoadCmdString(pTemp);
pGI->pCmd = calloc(1, iCmdLen);
memcpy(pGI->pCmd, Cmd, iCmdLen);
pGI->iCmdLen = iCmdLen;
if (bVerbose) {
fprintf(logfile, "%04x %d", pGI->wUc, pGI->iCp);
fprintf(logfile, "\n");
}
}
VOID
LoadGlyphInfo()
{
DWORD dwTemp;
INT k;
fgets(buf, sizeof(buf), infile);
sscanf(buf, "%ld", &dwTemp);
Header.dwGlyphCount = dwTemp;
pGInfo = (GINFO *)calloc(1, (sizeof (GINFO) * dwTemp));
pMapTable = (MAPTABLE *)calloc(1,
(sizeof (MAPTABLE) + sizeof (TRANSDATA) * (dwTemp - 1)));
k = 0;
while (1) {
if (NULL == fgets(buf, sizeof(buf), infile)) {
*buf = '\0';
break;
}
if (';' == *buf) {
*buf = '\0';
continue;
}
if (!isxdigit(*buf))
break;
if (k >= (INT)dwTemp) {
fatal("too many glyph defs\n");
}
LoadGlyphInfoInternal(&(pGInfo[k++]), buf);
}
Header.dwGlyphCount = (DWORD)k;
if (bVerbose) {
fprintf(logfile, "dwGlyphCount=%ld\n", Header.dwGlyphCount);
}
}
VOID
CountRuns()
{
INT i, j;
WORD wUc;
j = 0;
wUc = 0x0000;
for (i = 0; i < (INT)Header.dwGlyphCount; i++) {
if (wUc > pGInfo[i].wUc) {
fatal("unicode value duplicated %x", pGInfo[i].wUc);
}
else if (wUc < pGInfo[i].wUc) {
j++;
wUc = pGInfo[i].wUc;
if (NULL != pRuns) {
pRuns[j - 1].wcLow = pGInfo[i].wUc;
}
}
wUc++;
if (NULL != pRuns) {
pRuns[j - 1].wGlyphCount++;
}
}
if (NULL == pRuns) {
Header.dwRunCount = (DWORD)j;
}
if (bVerbose) {
fprintf(logfile, "dwRunCount=%d\n", Header.dwRunCount);
}
}
int __cdecl
CompGInfo(
const void *p1, const void *p2)
{
GINFO *pGI1 = (GINFO *)p1;
GINFO *pGI2 = (GINFO *)p2;
return ((int)pGI1->wUc - (int)pGI2->wUc);
}
VOID
SortGlyphs()
{
qsort(pGInfo, Header.dwGlyphCount, sizeof (GINFO), CompGInfo);
CountRuns(); // just count # of runs
pRuns = (GLYPHRUN *)calloc(1, (sizeof (GLYPHRUN) * Header.dwRunCount));
CountRuns(); // load run info
}
VOID
WriteHeader(
BOOL bSeek)
{
if (0 != fseek(outfile, 0L, SEEK_SET))
fatal("fseek error");
if (1 != fwrite(&Header, sizeof (Header), 1, outfile))
fatal("fwrite error");
}
LONG
AdjustOffset(
FILE *fp)
{
LONG lTemp, lTemp2;
BYTE ajBuf[3];
if (0 > (lTemp = ftell(outfile)))
fatal("ftell");
if (0 != (lTemp2 = lTemp % 4)) {
lTemp2 = 4 - lTemp2;
memset(ajBuf, 0, 3);
if (1 != fwrite(pRuns, lTemp, 1, outfile))
fatal("fwrite");
}
return (lTemp + lTemp2);
}
VOID
WriteGlyphRuns()
{
LONG lTemp;
Header.loRunOffset = AdjustOffset(outfile);
lTemp = sizeof (GLYPHRUN) * Header.dwRunCount;
if (1 != fwrite(pRuns, lTemp, 1, outfile))
fatal("fwrite GLYPHRUN");
}
VOID
WriteCpInfo(
BOOL bSeek)
{
INT i;
LONG lTemp;
if (bSeek) {
if (0 != fseek(outfile, Header.loCodePageOffset, SEEK_SET))
fatal("fseek");
}
else {
Header.loCodePageOffset = AdjustOffset(outfile);
}
for (i = 0; i < (INT)Header.dwCodePageCount; i++) {
if (1 != fwrite(&(pCpCmdInfo[i]), sizeof(UNI_CODEPAGEINFO), 1, outfile))
fatal("fwrite CODEPAGEINFO");
}
}
VOID
WriteMapTable(
BOOL bSeek)
{
LONG lTemp;
pMapTable->dwGlyphNum = Header.dwGlyphCount;
if (bSeek) {
if (0 != fseek(outfile, Header.loMapTableOffset, SEEK_SET))
fatal("fseek");
}
else {
Header.loMapTableOffset = AdjustOffset(outfile);
}
lTemp = sizeof (MAPTABLE) + sizeof(TRANSDATA) * (Header.dwGlyphCount - 1);
if (1 != fwrite(pMapTable, lTemp, 1, outfile))
fatal("fwrite MAPTABLE");
}
VOID
WriteCommands()
{
INT iTemp;
LONG lTemp;
INT i;
WORD wTemp;
AdjustOffset(outfile);
for (i = 0; i < (INT)Header.dwCodePageCount; i++) {
if (0 < pCInfo[i].iCmdSelLen) {
if (0 > (lTemp = ftell(outfile)))
fatal("ftell");
if (1 != fwrite(pCInfo[i].pCmdSel, pCInfo[i].iCmdSelLen, 1, outfile))
fatal("fwrite");
pCpCmdInfo[i].SelectSymbolSet.dwCount = pCInfo[i].iCmdSelLen;
pCpCmdInfo[i].SelectSymbolSet.loOffset = lTemp;
}
if (0 < pCInfo[i].iCmdUnselLen) {
if (0 > (lTemp = ftell(outfile)))
fatal("ftell");
if (1 != fwrite(pCInfo[i].pCmdUnsel, pCInfo[i].iCmdUnselLen, 1, outfile))
fatal("fwrite");
pCpCmdInfo[i].UnSelectSymbolSet.dwCount = pCInfo[i].iCmdUnselLen;
pCpCmdInfo[i].UnSelectSymbolSet.loOffset = lTemp;
}
}
for (i = 0; i < (INT)Header.dwGlyphCount; i++) {
iTemp = pGInfo[i].iCmdLen;
pMapTable->Trans[i].ubType = pGInfo[i].jType;
pMapTable->Trans[i].ubType &= ~MTYPE_FORMAT_MASK;
// Currently we only support MTYPE_DIRECT and MTYPE_COMPOSE.
if (1 == iTemp) {
pMapTable->Trans[i].ubType |= MTYPE_DIRECT;
pMapTable->Trans[i].uCode.ubCode = pGInfo[i].pCmd[0];
}
else if (1 < iTemp) {
if (0 > (lTemp = ftell(outfile)))
fatal("ftell");
wTemp = pGInfo[i].iCmdLen;
if (1 != fwrite(&wTemp, sizeof (wTemp), 1, outfile))
fatal("fwrite");
if (1 != fwrite(pGInfo[i].pCmd, iTemp, 1, outfile))
fatal("fwrite");
pMapTable->Trans[i].ubType |= MTYPE_COMPOSE;
pMapTable->Trans[i].uCode.sCode =
(SHORT)(lTemp - Header.loMapTableOffset);
if (bVerbose) {
fprintf(logfile, "%d -> %0x (%0x)\n",
(i + 1), lTemp, (lTemp - Header.loMapTableOffset));
}
}
}
if (0 > (lTemp = ftell(outfile)))
fatal("ftell");
Header.dwSize = lTemp;
pMapTable->dwSize = (lTemp - Header.loMapTableOffset);
}
VOID
undumpgtt()
{
while (1) {
if ('\0' == *buf) {
if (NULL == fgets(buf, sizeof (buf), infile))
break;
}
switch(*buf) {
case ';':
// comment lines
*buf = '\0';
break;
case 'H':
LoadHeader();
break;
case 'C':
LoadCpInfo();
break;
case 'G':
LoadGlyphInfo();
break;
default:
fatal("unknown keyword '%c'\n", *buf);
}
}
// Generate glyh run
SortGlyphs();
// Write data into file
WriteHeader(TRUE);
WriteGlyphRuns();
WriteCpInfo(FALSE);
WriteMapTable(FALSE);
WriteCommands();
WriteHeader(TRUE); // w/ correct data
WriteCpInfo(TRUE); // w/ correct data
WriteMapTable(TRUE); // w/ correct data
}
/*
* main
*/
void __cdecl
main(int argc, char *argv[])
{
INT i, j;
argc--, argv++;
if (argc == 0)
usage();
infile = stdin;
logfile = stdout;
j = 0;
for (i = 0; i < argc; i++) {
if ('-' == argv[i][0]) {
switch(argv[i][1]) {
case 'v':
bVerbose = 1;
break;
}
}
else {
switch (j++) {
case 0:
if (NULL == (outfile = fopen(argv[i], "wb")))
fatal("can't open file \"%s\"", argv[i]);
break;
case 1:
if (NULL == (infile = fopen(argv[i], "r")))
fatal("can't open file \"%s\"", argv[i]);
break;
}
}
}
undumpgtt();
fclose(outfile);
}