Microsoft-3D-Movie-Maker/kauai/TOOLS/CHELPEXP.CPP

484 lines
12 KiB
C++

/* Copyright (c) Microsoft Corporation.
Licensed under the MIT License. */
/***************************************************************************
Author: ShonK
Project: Kauai
Copyright (c) Microsoft Corporation
Routines to export help topics to chomp input format.
***************************************************************************/
#include "kidframe.h"
#include "chelpexp.h"
ASSERTNAME
static bool _FWriteHelpChunk(PCFL pcfl, PCHSE pchse, KID *pkid, CKI *pckiPar);
static bool _FWriteHelpPropAg(PCFL pcfl, PCHSE pchse, KID *pkid, CKI *pckiPar);
static void _AppendHelpStnLw(PSTN pstn, PGST pgst, long istn, long lw);
/***************************************************************************
Export the help topics in their textual representation for compilation
by chomp.
REVIEW shonk: this code is a major hack and very fragile.
***************************************************************************/
bool FExportHelpText(PCFL pcfl, PMSNK pmsnk)
{
AssertPo(pcfl, 0);
BLCK blck;
PGST pgst;
long icki;
CKI cki, ckiPar;
KID kid;
CGE cge;
ulong grfcge;
HTOPF htopf;
CHSE chse;
STN stn, stnT;
bool fRet = fFalse;
chse.Init(pmsnk);
chse.DumpSz(PszLit("#undef __HELP_NAME"));
chse.DumpSz(PszLit("#undef __HELP_SYMBOL"));
chse.DumpSz(PszLit("#undef __HELP_PACK"));
chse.DumpSz(PszLit("#undef __HELP_PACK2"));
chse.DumpSz(PszLit("#ifdef NO_HELP_NAMES"));
chse.DumpSz(PszLit("#define __HELP_NAME(name) \"\""));
chse.DumpSz(PszLit("#else"));
chse.DumpSz(PszLit("#define __HELP_NAME(name) name"));
chse.DumpSz(PszLit("#endif"));
chse.DumpSz(PszLit("#ifdef NO_HELP_SYMBOLS"));
chse.DumpSz(PszLit("#define __HELP_SYMBOL(stuff)"));
chse.DumpSz(PszLit("#else"));
chse.DumpSz(PszLit("#define __HELP_SYMBOL(stuff) stuff"));
chse.DumpSz(PszLit("#endif"));
chse.DumpSz(PszLit("#ifdef PACK_HELP"));
chse.DumpSz(PszLit("#define __HELP_PACK PACK"));
chse.DumpSz(PszLit("#else"));
chse.DumpSz(PszLit("#define __HELP_PACK"));
chse.DumpSz(PszLit("#endif"));
chse.DumpSz(PszLit("#ifdef HELP_SINGLE_CHUNK"));
chse.DumpSz(PszLit("#define __HELP_PACK2"));
chse.DumpSz(PszLit("#else"));
chse.DumpSz(PszLit("#define __HELP_PACK2 __HELP_PACK"));
chse.DumpSz(PszLit("#endif"));
pgst = pvNil;
for (icki = 0; pcfl->FGetCkiCtg(kctgHelpTopic, icki, &cki); icki++)
{
// read the string table if it's there
if (pcfl->FGetKidChidCtg(cki.ctg, cki.cno, 0, kctgGst, &kid) &&
(!pcfl->FFind(kid.cki.ctg, kid.cki.cno, &blck) ||
pvNil == (pgst = GST::PgstRead(&blck)) ||
pgst->IvMac() != 6 && (pgst->IvMac() != 5 ||
!pgst->FAddRgch(PszLit(""), 0))))
{
goto LFail;
}
// read the topic
if (!pcfl->FFind(cki.ctg, cki.cno, &blck) || !blck.FUnpackData() ||
blck.Cb() != size(HTOPF) || !blck.FRead(&htopf))
{
goto LFail;
}
if (htopf.bo == kboOther)
SwapBytesBom(&htopf.htop, kbomHtop);
else if (htopf.bo != kboCur)
goto LFail;
// dump the htop's cno definition
chse.DumpSz(PszLit(""));
stn.FFormatSz(PszLit("SET _help_%x_%x="), cki.ctg, cki.cno);
_AppendHelpStnLw(&stn, pgst, 1, cki.cno);
chse.DumpSz(stn.Psz());
// dump the single chunk prefix
pcfl->FGetName(cki.ctg, cki.cno, &stnT);
stnT.FExpandControls();
chse.DumpSz(PszLit(""));
chse.DumpSz(PszLit("#ifdef HELP_SINGLE_CHUNK"));
stn.FFormatSz(
PszLit("CHUNK('%f', _help_%x_%x, __HELP_NAME(\"%s\")) __HELP_PACK"),
cki.ctg, cki.ctg, cki.cno, &stnT);
chse.DumpSz(stn.Psz());
chse.DumpSz(PszLit("SUBFILE"));
chse.DumpSz(PszLit("#endif //HELP_SINGLE_CHUNK"));
stn.FAppendCh(ChLit('2'));
// dump the HTOPF
chse.DumpSz(PszLit(""));
chse.DumpSz(stn.Psz());
stn = PszLit("\tBO OSK LONG");
_AppendHelpStnLw(&stn, pgst, 0, htopf.htop.cnoBalloon);
_AppendHelpStnLw(&stn, pgst, 2, htopf.htop.hidThis);
_AppendHelpStnLw(&stn, pgst, 3, htopf.htop.hidTarget);
_AppendHelpStnLw(&stn, pgst, 4, htopf.htop.cnoScript);
stnT.FFormatSz(PszLit(" 0x%x 0x%x 0x%x"),
htopf.htop.dxp, htopf.htop.dyp, htopf.htop.ckiSnd.ctg);
stn.FAppendStn(&stnT);
_AppendHelpStnLw(&stn, pgst, 5, htopf.htop.ckiSnd.cno);
chse.DumpSz(stn.Psz());
ReleasePpo(&pgst);
chse.DumpSz(PszLit("ENDCHUNK"));
// dump child chunks
cge.Init(pcfl, cki.ctg, cki.cno);
while (cge.FNextKid(&kid, &ckiPar, &grfcge, fcgeNil))
{
if (fcgeError & grfcge)
goto LFail;
if ((fcgeRoot & grfcge) || !(fcgePre & grfcge))
continue;
chse.DumpSz(PszLit(""));
if (kid.cki.ctg == kctgTxtPropArgs)
{
// special handling of argument AG
if (!_FWriteHelpPropAg(pcfl, &chse, &kid, &ckiPar))
goto LFail;
}
else
{
if (kid.cki.ctg == kctgGst)
{
// put "#ifndef NO_HELP_SYMBOLS" before it
chse.DumpSz(PszLit("#ifndef NO_HELP_SYMBOLS"));
}
if (!_FWriteHelpChunk(pcfl, &chse, &kid, &ckiPar))
goto LFail;
if (kid.cki.ctg == kctgGst)
{
// put "#endif //!NO_HELP_SYMBOLS" after it
chse.DumpSz(PszLit("#endif //!NO_HELP_SYMBOLS"));
}
}
}
chse.DumpSz(PszLit(""));
chse.DumpSz(PszLit("#ifdef HELP_SINGLE_CHUNK"));
chse.DumpSz(PszLit("ENDCHUNK"));
chse.DumpSz(PszLit("#endif //HELP_SINGLE_CHUNK"));
chse.DumpSz(PszLit(""));
}
fRet = fTrue;
LFail:
chse.Uninit();
ReleasePpo(&pgst);
return fRet;
}
/***************************************************************************
Dump a chunk as text to the given chse.
***************************************************************************/
bool _FWriteHelpChunk(PCFL pcfl, PCHSE pchse, KID *pkid, CKI *pckiPar)
{
AssertPo(pcfl, 0);
AssertPo(pchse, 0);
AssertVarMem(pkid);
AssertVarMem(pckiPar);
STN stn;
STN stnT;
BLCK blck;
if (!pcfl->FFind(pkid->cki.ctg, pkid->cki.cno, &blck))
return fFalse;
// dump the CHUNK declaration
pchse->DumpSz(PszLit("SET _help_cno++"));
stn.FFormatSz(PszLit("SET _help_%x_%x=_help_cno"),
pkid->cki.ctg, pkid->cki.cno);
pchse->DumpSz(stn.Psz());
pcfl->FGetName(pkid->cki.ctg, pkid->cki.cno, &stnT);
stnT.FExpandControls();
stn.FFormatSz(
PszLit("CHUNK('%f', _help_cno, __HELP_NAME(\"%s\")) __HELP_PACK2"),
pkid->cki.ctg, &stnT);
pchse->DumpSz(stn.Psz());
// dump the PARENT declaration
stn.FFormatSz(PszLit("PARENT('%f', _help_%x_%x, 0x%x)"),
pckiPar->ctg, pckiPar->ctg, pckiPar->cno, pkid->chid);
pchse->DumpSz(stn.Psz());
if (pkid->cki.ctg == kctgGst)
{
PGST pgst;
short bo, osk;
bool fPacked = blck.FPacked();
bool fRet;
pgst = GST::PgstRead(&blck, &bo, &osk);
if (pvNil == pgst)
return fFalse;
if (fPacked)
pchse->DumpSz(PszLit("PACK"));
if (bo != kboCur)
pchse->DumpSz(MacWin(PszLit("WINBO"), PszLit("MACBO")));
fRet = pchse->FDumpStringTable(pgst);
ReleasePpo(&pgst);
if (bo != kboCur)
pchse->DumpSz(MacWin(PszLit("MACBO"), PszLit("WINBO")));
if (!fRet)
return fFalse;
}
else
{
// dump the data
pchse->DumpBlck(&blck);
}
// dump the ENDCHUNK
pchse->DumpSz(PszLit("ENDCHUNK"));
return fTrue;
}
/***************************************************************************
Write the property AG. This requires special processing
***************************************************************************/
bool _FWriteHelpPropAg(PCFL pcfl, PCHSE pchse, KID *pkid, CKI *pckiPar)
{
AssertPo(pcfl, 0);
AssertPo(pchse, 0);
AssertVarMem(pkid);
AssertVarMem(pckiPar);
PAG pag;
short bo, osk;
STN stn, stnT, stnT2;
byte rgb[2 * kcbMaxDataStn];
BLCK blck;
long iv, lw, cb, ib, cbRead;
CKI cki;
pag = pvNil;
if (!pcfl->FFind(pkid->cki.ctg, pkid->cki.cno, &blck) ||
pvNil == (pag = AG::PagRead(&blck, &bo, &osk)) ||
bo != kboCur || osk != koskCur || size(long) != pag->CbFixed())
{
ReleasePpo(&pag);
return fFalse;
}
// dump the CHUNK declaration
pchse->DumpSz(PszLit("SET _help_cno++"));
stn.FFormatSz(PszLit("SET _help_%x_%x=_help_cno"),
pkid->cki.ctg, pkid->cki.cno);
pchse->DumpSz(stn.Psz());
pcfl->FGetName(pkid->cki.ctg, pkid->cki.cno, &stnT);
stnT.FExpandControls();
stn.FFormatSz(
PszLit("CHUNK('%f', _help_cno, __HELP_NAME(\"%s\")) __HELP_PACK2"),
pkid->cki.ctg, &stnT);
pchse->DumpSz(stn.Psz());
// dump the PARENT declaration
stn.FFormatSz(PszLit("PARENT('%f', _help_%x_%x, 0x%x)"),
pckiPar->ctg, pckiPar->ctg, pckiPar->cno, pkid->chid);
pchse->DumpSz(stn.Psz());
// dump the AG declaration
pchse->DumpSz(PszLit("AG(4)"));
// dump the items
for (iv = 0; iv < pag->IvMac(); iv++)
{
if (pag->FFree(iv))
{
pchse->DumpSz(PszLit("\tFREE"));
continue;
}
pag->GetFixed(iv, &lw);
stn.FFormatSz(PszLit("\tITEM LONG 0x%x"), lw);
pchse->DumpSz(stn.Psz());
cb = pag->Cb(iv);
if (0 == cb)
continue;
switch (B3Lw(lw))
{
case 64: //sprmGroup
if (cb <= size(byte) + size(CNO))
goto LWriteCore;
if (cb > size(rgb))
{
Bug("bad group data");
goto LWriteCore;
}
pag->GetRgb(iv, 0, cb, rgb);
ib = size(byte) + size(CNO);
if (!stnT.FSetData(rgb + ib, cb - ib) || stnT.Cch() == 0)
{
Bug("bad group data");
goto LWriteCore;
}
stn.FFormatSz(
PszLit("\t\tVAR BYTE %d LONG %s __HELP_SYMBOL( STN \""),
(long)rgb[0], &stnT);
stnT.FExpandControls();
stn.FAppendStn(&stnT);
stn.FAppendSz(PszLit("\" )"));
pchse->DumpSz(stn.Psz());
break;
case 192: //sprmObject
if (cb <= size(CKI))
goto LWriteCore;
// an object
pag->GetRgb(iv, 0, size(CKI), &cki);
switch (cki.ctg)
{
default:
goto LWriteCore;
case kctgMbmp:
ib = size(CKI);
if (ib >= cb)
goto LWriteCore;
if ((cb -= ib) > kcbMaxDataStn)
{
Bug("bad picture data");
goto LWriteCore;
}
pag->GetRgb(iv, ib, cb, rgb);
if (!stnT.FSetData(rgb, cb) || stnT.Cch() == 0)
{
Bug("bad picture data 2");
goto LWriteCore;
}
stn.FFormatSz(
PszLit("\t\tVAR LONG '%f' %s __HELP_SYMBOL( STN \""),
cki.ctg, &stnT);
stnT.FExpandControls();
stn.FAppendStn(&stnT);
stn.FAppendSz(PszLit("\" )"));
pchse->DumpSz(stn.Psz());
break;
case kctgGokd:
ib = size(CKI) + size(long);
if (ib >= cb)
goto LWriteCore;
if ((cb -= ib) > size(rgb))
{
Bug("bad button data");
goto LWriteCore;
}
pag->GetRgb(iv, ib, cb, rgb);
if (!stnT.FSetData(rgb, cb, &cbRead) || cbRead >= cb ||
!stnT2.FSetData(rgb + cbRead, cb - cbRead))
{
Bug("bad picture data 2");
goto LWriteCore;
}
stn.FFormatSz(PszLit("\t\tVAR LONG '%f' "), cki.ctg);
if (stnT.Cch() > 0)
{
stn.FAppendStn(&stnT);
stnT.FExpandControls();
}
else
{
stnT.FFormatSz(PszLit("0x%x"), cki.cno);
stn.FAppendStn(&stnT);
stnT.SetNil();
}
stn.FAppendCh(kchSpace);
if (stnT2.Cch() > 0)
{
stn.FAppendStn(&stnT2);
stnT2.FExpandControls();
}
else
{
pag->GetRgb(iv, size(CKI), size(long), &lw);
stnT2.FFormatSz(PszLit("0x%x"), lw);
stn.FAppendStn(&stnT2);
stnT2.SetNil();
}
stn.FAppendSz(PszLit(" __HELP_SYMBOL( STN "));
if (stnT.Cch() > 0)
{
stn.FAppendCh(ChLit('"'));
stn.FAppendStn(&stnT);
stn.FAppendSz(PszLit("\" "));
}
if (stnT2.Cch() > 0)
{
if (stnT.Cch() > 0)
stn.FAppendSz(PszLit("; "));
stn.FAppendCh(ChLit('"'));
stn.FAppendStn(&stnT2);
stn.FAppendSz(PszLit("\" "));
}
stn.FAppendCh(ChLit(')'));
pchse->DumpSz(stn.Psz());
break;
}
break;
default:
LWriteCore:
// just write the data
pchse->DumpSz(PszLit("\t\tVAR"));
pchse->DumpRgb(pag->PvLock(iv), cb, 3);
pag->Unlock();
break;
}
}
// dump the ENDCHUNK
ReleasePpo(&pag);
pchse->DumpSz(PszLit("ENDCHUNK"));
return fTrue;
}
/***************************************************************************
Append a string or number.
***************************************************************************/
void _AppendHelpStnLw(PSTN pstn, PGST pgst, long istn, long lw)
{
AssertPo(pstn, 0);
AssertNilOrPo(pgst, 0);
STN stn;
stn.SetNil();
if (pvNil != pgst)
pgst->GetStn(istn, &stn);
if (stn.Cch() == 0)
stn.FFormatSz(PszLit(" 0x%x"), lw);
else
pstn->FAppendCh(kchSpace);
pstn->FAppendStn(&stn);
}