mirror of
https://github.com/microsoft/Microsoft-3D-Movie-Maker.git
synced 2024-11-22 02:12:33 +01:00
1361 lines
28 KiB
C++
1361 lines
28 KiB
C++
/* Copyright (c) Microsoft Corporation.
|
|
Licensed under the MIT License. */
|
|
|
|
/***************************************************************************
|
|
Author: ShonK
|
|
Project: Kauai
|
|
Reviewed:
|
|
Copyright (c) Microsoft Corporation
|
|
|
|
Script interpreter for GOB based scripts.
|
|
|
|
***************************************************************************/
|
|
#include "kidframe.h"
|
|
ASSERTNAME
|
|
|
|
|
|
RTCLASS(SCEG)
|
|
|
|
|
|
#ifdef DEBUG
|
|
// these strings are for debug only error messages
|
|
static STN _stn;
|
|
#endif //DEBUG
|
|
|
|
|
|
/***************************************************************************
|
|
Constructor for a GOB based script interpreter. We don't just keep
|
|
the pgob in case the GOB goes away while the script is running.
|
|
***************************************************************************/
|
|
SCEG::SCEG(PWOKS pwoks, PRCA prca, PGOB pgob) : SCEG_PAR(prca, pwoks->Pstrg())
|
|
{
|
|
AssertPo(pwoks, 0);
|
|
AssertPo(prca, 0);
|
|
AssertPo(pgob, 0);
|
|
|
|
_pwoks = pwoks;
|
|
_hid = pgob->Hid();
|
|
_grid = pgob->Grid();
|
|
_pgob = pvNil;
|
|
|
|
AssertThis(0);
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
/***************************************************************************
|
|
Assert the validity of a SCEG.
|
|
***************************************************************************/
|
|
void SCEG::AssertValid(ulong grf)
|
|
{
|
|
SCEG_PAR::AssertValid(0);
|
|
Assert(hidNil != _hid, 0);
|
|
AssertPo(_pwoks, 0);
|
|
Assert(_prca != pvNil, 0);
|
|
}
|
|
#endif //DEBUG
|
|
|
|
|
|
/***************************************************************************
|
|
The script is being resumed, so set _pgob to nil (don't know whether
|
|
it exists).
|
|
***************************************************************************/
|
|
bool SCEG::FResume(long *plwReturn, bool *pfPaused)
|
|
{
|
|
GobMayDie();
|
|
return SCEG_PAR::FResume(plwReturn, pfPaused);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Return the gob that corresponds to this script interpreter.
|
|
***************************************************************************/
|
|
PGOB SCEG::_PgobThis(void)
|
|
{
|
|
AssertThis(0);
|
|
|
|
if (pvNil != _pgob)
|
|
{
|
|
AssertPo(_pgob, 0);
|
|
Assert(_pgob->Grid() == _grid, "bad value of _pgob");
|
|
return _pgob;
|
|
}
|
|
|
|
_pgob = _pwoks->PgobFromGrid(_grid);
|
|
return _pgob;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Return the gob that is accessible to this script interpreter and has
|
|
the given hid.
|
|
***************************************************************************/
|
|
PGOB SCEG::_PgobFromHid(long hid)
|
|
{
|
|
AssertThis(0);
|
|
|
|
if (hid == _hid)
|
|
return _PgobThis();
|
|
|
|
return _pwoks->PgobFromHid(hid);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Return the address of the variable table for the GOB associated with
|
|
this script interpreter.
|
|
***************************************************************************/
|
|
PGL *SCEG::_PpglrtvmThis(void)
|
|
{
|
|
PGOB pgob = _PgobThis();
|
|
|
|
if (pvNil == pgob)
|
|
return pvNil;
|
|
return pgob->Ppglrtvm();
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Return the address of the variable table for the WOKS associated with
|
|
this script interpreter.
|
|
***************************************************************************/
|
|
PGL *SCEG::_PpglrtvmGlobal(void)
|
|
{
|
|
AssertThis(0);
|
|
|
|
return _pwoks->Ppglrtvm();
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Return the address of the variable table for the GOB with given hid.
|
|
***************************************************************************/
|
|
PGL *SCEG::_PpglrtvmRemote(long lw)
|
|
{
|
|
PGOB pgob = _PgobFromHid(lw);
|
|
|
|
if (pvNil == pgob)
|
|
return pvNil;
|
|
return pgob->Ppglrtvm();
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Return the current version number of the script compiler.
|
|
***************************************************************************/
|
|
short SCEG::_SwCur(void)
|
|
{
|
|
return kswCurSccg;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Return the min version number of the script compiler. Read can read
|
|
scripts back to this version.
|
|
***************************************************************************/
|
|
short SCEG::_SwMin(void)
|
|
{
|
|
return kswMinSccg;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Execute a script command.
|
|
***************************************************************************/
|
|
bool SCEG::_FExecOp(long op)
|
|
{
|
|
CMD cmd;
|
|
PGOB pgob;
|
|
PCLOK pclok;
|
|
long hid;
|
|
long dtim;
|
|
long dxp, dyp;
|
|
long lw1, lw2, lw3, lw4, clw;
|
|
long *qrglw;
|
|
void *pv;
|
|
|
|
hid = _hid; //for "this" operations
|
|
switch (op)
|
|
{
|
|
case kopDestroyGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopDestroyThis:
|
|
if (!_fError && pvNil != (pgob = _PgobFromHid(hid)))
|
|
{
|
|
GobMayDie();
|
|
if (pgob == _pwoks)
|
|
{
|
|
Debug(_WarnSz(PszLit(
|
|
"Can't Destroy WOKS - destroying all its children")));
|
|
PGOB pgobT;
|
|
|
|
while (pvNil != (pgobT = pgob->PgobFirstChild()))
|
|
ReleasePpo(&pgobT);
|
|
}
|
|
else
|
|
ReleasePpo(&pgob);
|
|
}
|
|
break;
|
|
|
|
case kopCreateChildGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopCreateChildThis:
|
|
lw1 = _LwPop();
|
|
lw2 = _LwPop();
|
|
pgob = pvNil;
|
|
if (!_fError && pvNil != (pgob = _PgobFromHid(hid)))
|
|
{
|
|
GobMayDie();
|
|
pgob = _pwoks->PgokNew(pgob, lw1, lw2, _prca);
|
|
}
|
|
else
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing parent GOB for CreateChild(Gob|This) (gid = %d)"),
|
|
hid));
|
|
}
|
|
_Push(pvNil == pgob ? hidNil : pgob->Hid());
|
|
break;
|
|
|
|
case kopCreateHelpGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopCreateHelpThis:
|
|
lw1 = _LwPop();
|
|
pgob = pvNil;
|
|
if (!_fError && pvNil != (pgob = _PgobFromHid(hid)))
|
|
{
|
|
GobMayDie();
|
|
pgob = _pwoks->PhbalNew(pgob, _prca, lw1);
|
|
}
|
|
else
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing parent GOB for CreateHelp(Gob|This) (gid = %d)"),
|
|
hid));
|
|
}
|
|
_Push(pvNil == pgob ? hidNil : pgob->Hid());
|
|
break;
|
|
|
|
case kopResizeGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopResizeThis:
|
|
dxp = _LwPop();
|
|
dyp = _LwPop();
|
|
//REVIEW shonk: should we handle hwnd based gob's?
|
|
if (!_fError && pvNil != (pgob = _PgobFromHid(hid)) &&
|
|
hNil == pgob->Hwnd())
|
|
{
|
|
RC rc;
|
|
|
|
pgob->GetRc(&rc, cooParent);
|
|
rc.xpRight = rc.xpLeft + LwMax(0, dxp);
|
|
rc.ypBottom = rc.ypTop + LwMax(0, dyp);
|
|
pgob->SetPos(&rc, pvNil);
|
|
}
|
|
else
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for Resize(Gob|This) (gid = %d)"), hid));
|
|
}
|
|
break;
|
|
|
|
case kopMoveRelGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopMoveRelThis:
|
|
dxp = _LwPop();
|
|
dyp = _LwPop();
|
|
//REVIEW shonk: should we handle hwnd based gob's?
|
|
if (!_fError && pvNil != (pgob = _PgobFromHid(hid)) &&
|
|
hNil == pgob->Hwnd())
|
|
{
|
|
RC rc;
|
|
|
|
pgob->GetRc(&rc, cooParent);
|
|
rc.Offset(dxp, dyp);
|
|
pgob->SetPos(&rc, pvNil);
|
|
}
|
|
else
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for MoveRel(Gob|This) (gid = %d)"), hid));
|
|
}
|
|
break;
|
|
|
|
case kopMoveAbsGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopMoveAbsThis:
|
|
dxp = _LwPop();
|
|
dyp = _LwPop();
|
|
//REVIEW shonk: should we handle hwnd based gob's?
|
|
if (!_fError && pvNil != (pgob = _PgobFromHid(hid)) &&
|
|
hNil == pgob->Hwnd())
|
|
{
|
|
RC rc;
|
|
|
|
pgob->GetRc(&rc, cooParent);
|
|
if (pgob->FIs(kclsGOK))
|
|
{
|
|
PT pt;
|
|
((PGOK)pgob)->GetPtReg(&pt, cooLocal);
|
|
dxp -= pt.xp;
|
|
dyp -= pt.yp;
|
|
}
|
|
rc.Offset(dxp - rc.xpLeft, dyp - rc.ypTop);
|
|
pgob->SetPos(&rc, pvNil);
|
|
}
|
|
else
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for MoveAbs(Gob|This) (gid = %d)"), hid));
|
|
}
|
|
break;
|
|
|
|
case kopRunScriptGob:
|
|
case kopRunScriptThis:
|
|
case kopRunScriptCnoGob:
|
|
case kopRunScriptCnoThis:
|
|
clw = _LwPop(); //the number of parameters
|
|
if (kopRunScriptGob == op || kopRunScriptCnoGob == op)
|
|
hid = _LwPop();
|
|
lw1 = _LwPop(); //the chid of the script
|
|
if (_fError)
|
|
break;
|
|
|
|
if (clw > 0)
|
|
{
|
|
if (pvNil == _QlwGet(clw))
|
|
break;
|
|
if (!FAllocPv(&pv, LwMul(size(long), clw), fmemNil, mprNormal))
|
|
{
|
|
Debug(_WarnSz(PszLit("OOM attempting to run script")));
|
|
_PopList(clw);
|
|
clw = 0;
|
|
pv = pvNil;
|
|
}
|
|
else
|
|
{
|
|
CopyPb(_QlwGet(clw), pv, LwMul(size(long), clw));
|
|
ReverseRglw(pv, clw);
|
|
_PopList(clw);
|
|
}
|
|
}
|
|
else
|
|
pv = pvNil;
|
|
|
|
if (pvNil == (pgob = _PgobFromHid(hid)) || !pgob->FIs(kclsGOK))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for RunScript[Cno](Gob|This) (gid = %d)"),
|
|
hid));
|
|
lw2 = 0;
|
|
}
|
|
else
|
|
{
|
|
bool tRet;
|
|
|
|
GobMayDie();
|
|
if (kopRunScriptCnoGob == op || kopRunScriptCnoThis == op)
|
|
((PGOK)pgob)->FRunScriptCno(lw1, (long *)pv, clw, &lw2, &tRet);
|
|
else
|
|
((PGOK)pgob)->FRunScript(lw1, (long *)pv, clw, &lw2, &tRet);
|
|
if (tYes != tRet)
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Running script failed (chid = 0x%x, gid = %d)"),
|
|
lw1, hid));
|
|
lw2 = 0;
|
|
}
|
|
}
|
|
FreePpv(&pv);
|
|
_Push(lw2);
|
|
break;
|
|
|
|
case kopChangeStateGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopChangeStateThis:
|
|
lw1 = _LwPop();
|
|
if (_fError || pvNil == (pgob = _PgobFromHid(hid)) ||
|
|
!pgob->FIs(kclsGOK) || !FIn(lw1, 0, kswMax))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB or state out of range for ")
|
|
PszLit("ChangeState(Gob|This) (gid = %d, sno = %d)"), hid, lw1));
|
|
}
|
|
else
|
|
{
|
|
GobMayDie();
|
|
((PGOK)pgob)->FChangeState(lw1);
|
|
}
|
|
break;
|
|
|
|
case kopAnimateGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopAnimateThis:
|
|
lw1 = _LwPop();
|
|
if (_fError || pvNil == (pgob = _PgobFromHid(hid)) || !pgob->FIs(kclsGOK))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for Animate(Gob|This) (gid = %d)"), hid));
|
|
}
|
|
else
|
|
{
|
|
GobMayDie();
|
|
((PGOK)pgob)->FSetRep(lw1, fgokNil, kctgAnimation);
|
|
}
|
|
break;
|
|
|
|
case kopSetPictureGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopSetPictureThis:
|
|
lw1 = _LwPop();
|
|
if (_fError || pvNil == (pgob = _PgobFromHid(hid)) || !pgob->FIs(kclsGOK))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for SetPicture(Gob|This) (gid = %d)"), hid));
|
|
}
|
|
else
|
|
{
|
|
GobMayDie();
|
|
((PGOK)pgob)->FSetRep(lw1, fgokKillAnim, kctgMbmp);
|
|
}
|
|
break;
|
|
|
|
case kopSetRepGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopSetRepThis:
|
|
lw1 = _LwPop();
|
|
if (_fError || pvNil == (pgob = _PgobFromHid(hid)) || !pgob->FIs(kclsGOK))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for SetRep(Gob|This) (gid = %d)"), hid));
|
|
}
|
|
else
|
|
{
|
|
GobMayDie();
|
|
((PGOK)pgob)->FSetRep(lw1);
|
|
}
|
|
break;
|
|
|
|
case kopStateGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopStateThis:
|
|
if (_fError || pvNil == (pgob = _PgobFromHid(hid)) || !pgob->FIs(kclsGOK))
|
|
{
|
|
lw1 = 0;
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for State(Gob|This) (gid = %d)"), hid));
|
|
}
|
|
else
|
|
lw1 = ((PGOK)pgob)->Sno();
|
|
_Push(lw1);
|
|
break;
|
|
|
|
case kopGidThis:
|
|
_Push(_hid);
|
|
break;
|
|
|
|
case kopGidParGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopGidParThis:
|
|
if (pvNil != (pgob = _PgobFromHid(hid)))
|
|
pgob = _pwoks->PgobParGob(pgob);
|
|
_Push(pvNil == pgob ? hidNil : pgob->Hid());
|
|
break;
|
|
|
|
case kopGidNextSib:
|
|
if (pvNil != (pgob = _PgobFromHid(_LwPop())))
|
|
pgob = pgob->PgobNextSib();
|
|
_Push(pvNil == pgob ? hidNil : pgob->Hid());
|
|
break;
|
|
|
|
case kopGidPrevSib:
|
|
if (pvNil != (pgob = _PgobFromHid(_LwPop())))
|
|
pgob = pgob->PgobPrevSib();
|
|
_Push(pvNil == pgob ? hidNil : pgob->Hid());
|
|
break;
|
|
|
|
case kopGidChild:
|
|
if (pvNil != (pgob = _PgobFromHid(_LwPop())))
|
|
pgob = pgob->PgobFirstChild();
|
|
_Push(pvNil == pgob ? hidNil : pgob->Hid());
|
|
break;
|
|
|
|
case kopFGobExists:
|
|
pgob = _PgobFromHid(_LwPop());
|
|
_Push(pvNil != pgob);
|
|
break;
|
|
|
|
case kopEnqueueCid:
|
|
cmd.cid = _LwPop();
|
|
cmd.pgg = pvNil;
|
|
hid = _LwPop();
|
|
if (hidNil == hid)
|
|
cmd.pcmh = pvNil;
|
|
else
|
|
cmd.pcmh = _pwoks->PcmhFromHid(hid);
|
|
cmd.rglw[0] = _LwPop();
|
|
cmd.rglw[1] = _LwPop();
|
|
cmd.rglw[2] = _LwPop();
|
|
cmd.rglw[3] = _LwPop();
|
|
if (!_fError)
|
|
vpcex->EnqueueCmd(&cmd);
|
|
break;
|
|
|
|
case kopAlert:
|
|
case kopPrint:
|
|
case kopPrintStat:
|
|
case kopAlertStr:
|
|
case kopPrintStr:
|
|
case kopPrintStrStat:
|
|
GobMayDie();
|
|
_DoAlert(op);
|
|
break;
|
|
|
|
case kopCreateClock:
|
|
hid = _LwPop();
|
|
if (hidNil != hid && pvNil != (pclok = _pwoks->PclokFromHid(hid)))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Clock already exists - incrementing ref count (hid = %d)"),
|
|
hid));
|
|
pclok->AddRef();
|
|
}
|
|
else
|
|
{
|
|
if (hidNil == hid)
|
|
hid = CMH::HidUnique();
|
|
if (pvNil == NewObj CLOK(hid))
|
|
hid = hidNil;
|
|
}
|
|
_Push(hid);
|
|
break;
|
|
|
|
case kopDestroyClock:
|
|
if (pvNil != (pclok = _pwoks->PclokFromHid(_LwPop())))
|
|
ReleasePpo(&pclok);
|
|
break;
|
|
|
|
case kopStartClock:
|
|
hid = _LwPop();
|
|
lw1 = _LwPop();
|
|
if (!_fError && pvNil != (pclok = _pwoks->PclokFromHid(hid)))
|
|
pclok->Start(lw1);
|
|
else
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing clock for StartClock (hid = %d)"), hid));
|
|
}
|
|
break;
|
|
|
|
case kopStopClock:
|
|
if (pvNil != (pclok = _pwoks->PclokFromHid(_LwPop())))
|
|
pclok->Stop();
|
|
else
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing clock for StopClock (hid = %d)"), hid));
|
|
}
|
|
break;
|
|
|
|
case kopTimeCur:
|
|
if (pvNil != (pclok = _pwoks->PclokFromHid(_LwPop())))
|
|
_Push(pclok->TimCur());
|
|
else
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing clock for TimeCur (hid = %d)"), hid));
|
|
_Push(0);
|
|
}
|
|
break;
|
|
|
|
case kopSetAlarmGob:
|
|
hid = _LwPop();
|
|
case kopSetAlarmThis:
|
|
case kopSetAlarm:
|
|
lw1 = _LwPop();
|
|
dtim = _LwPop();
|
|
if (kopSetAlarm == op)
|
|
lw2 = chidNil;
|
|
else
|
|
lw2 = _LwPop();
|
|
if (_fError || pvNil == (pgob = _PgobFromHid(hid)) ||
|
|
pvNil == (pclok = _pwoks->PclokFromHid(lw1)) ||
|
|
!pclok->FSetAlarm(dtim, pgob, lw2))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Setting Alarm failed (hid = %d)"), lw1));
|
|
}
|
|
break;
|
|
|
|
case kopXMouseGob:
|
|
case kopYMouseGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopXMouseThis:
|
|
case kopYMouseThis:
|
|
if (_fError || pvNil == (pgob = _PgobFromHid(hid)))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for (X|Y)Mouse(Gob|This) (gid = %d)"), hid));
|
|
_Push(0);
|
|
}
|
|
else
|
|
{
|
|
PT pt;
|
|
bool fDown;
|
|
pgob->GetPtMouse(&pt, &fDown);
|
|
_Push(op == kopXMouseThis || op == kopXMouseGob ? pt.xp : pt.yp);
|
|
}
|
|
break;
|
|
|
|
case kopGidUnique:
|
|
_Push(CMH::HidUnique());
|
|
break;
|
|
|
|
case kopXGob:
|
|
case kopYGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopXThis:
|
|
case kopYThis:
|
|
if (_fError || pvNil == (pgob = _PgobFromHid(hid)))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for (X|Y)(Gob|This) (gid = %d)"), hid));
|
|
_Push(0);
|
|
}
|
|
else if (pgob->FIs(kclsGOK))
|
|
{
|
|
PT pt;
|
|
((PGOK)pgob)->GetPtReg(&pt);
|
|
_Push(op == kopXThis || op == kopXGob ? pt.xp : pt.yp);
|
|
}
|
|
else
|
|
{
|
|
RC rc;
|
|
pgob->GetRc(&rc, cooParent);
|
|
_Push(op == kopXThis || op == kopXGob ? rc.xpLeft : rc.ypTop);
|
|
}
|
|
break;
|
|
|
|
case kopZGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopZThis:
|
|
if (_fError || pvNil == (pgob = _PgobFromHid(hid)) || !pgob->FIs(kclsGOK))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for Z(Gob|This) (gid = %d)"), hid));
|
|
_Push(0);
|
|
}
|
|
else
|
|
_Push(((PGOK)pgob)->ZPlane());
|
|
break;
|
|
|
|
case kopSetZGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopSetZThis:
|
|
lw1 = _LwPop();
|
|
if (_fError || pvNil == (pgob = _PgobFromHid(hid)) || !pgob->FIs(kclsGOK))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for SetZ(Gob|This) (gid = %d)"), hid));
|
|
}
|
|
else
|
|
((PGOK)pgob)->SetZPlane(lw1);
|
|
break;
|
|
|
|
case kopSetColorTable:
|
|
_SetColorTable(_LwPop());
|
|
break;
|
|
|
|
case kopCell:
|
|
_fPaused = fTrue;
|
|
//fall through
|
|
case kopCellNoPause:
|
|
lw1 = _LwPop();
|
|
dxp = _LwPop();
|
|
dyp = _LwPop();
|
|
dtim = _LwPop();
|
|
if (_fError || pvNil == (pgob = _PgobThis()))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for Cell[NoPause] (gid = %d)"), hid));
|
|
}
|
|
else
|
|
{
|
|
GobMayDie();
|
|
((PGOK)pgob)->FSetRep(lw1, fgokNoAnim, ctgNil, dxp, dyp, dtim);
|
|
}
|
|
break;
|
|
|
|
case kopGetModifierState:
|
|
_Push(_pwoks->GrfcustCur());
|
|
break;
|
|
|
|
case kopChangeModifierState:
|
|
lw1 = _LwPop();
|
|
lw2 = _LwPop();
|
|
if (!_fError)
|
|
_pwoks->ModifyGrfcust(lw1, lw2);
|
|
break;
|
|
|
|
case kopTransition:
|
|
lw1 = _LwPop();
|
|
lw2 = _LwPop();
|
|
dtim = _LwPop();
|
|
lw3 = _LwPop();
|
|
lw4 = _LwPop();
|
|
if (!_fError)
|
|
{
|
|
ACR acr;
|
|
PGL pglclr = _PglclrGet((CNO)lw4);
|
|
acr.SetFromLw(lw3);
|
|
vpappb->SetGft(lw1, lw2, LuMulDiv(dtim, kdtsSecond, kdtimSecond),
|
|
pglclr, acr);
|
|
ReleasePpo(&pglclr);
|
|
}
|
|
break;
|
|
|
|
case kopGetEdit:
|
|
lw1 = _LwPop();
|
|
_DoEditControl(lw1, _LwPop(), fTrue);
|
|
break;
|
|
|
|
case kopSetEdit:
|
|
lw1 = _LwPop();
|
|
_DoEditControl(lw1, _LwPop(), fFalse);
|
|
break;
|
|
|
|
case kopGetProp:
|
|
lw1 = _LwPop();
|
|
if (!_fError)
|
|
{
|
|
GobMayDie();
|
|
if (!vpappb->FGetProp(lw1, &lw2))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("GetProp failed (prid = %d)"), lw1));
|
|
lw2 = 0;
|
|
}
|
|
_Push(lw2);
|
|
}
|
|
break;
|
|
|
|
case kopSetProp:
|
|
lw1 = _LwPop();
|
|
lw2 = _LwPop();
|
|
GobMayDie();
|
|
if (!_fError && !vpappb->FSetProp(lw1, lw2))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("SetProp failed (prid = %d, val = %d)"), lw1, lw2));
|
|
}
|
|
break;
|
|
|
|
case kopLaunch:
|
|
lw1 = _LwPop();
|
|
GobMayDie();
|
|
if (!_fError)
|
|
_Push(_FLaunch(lw1));
|
|
break;
|
|
|
|
case kopPlayGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopPlayThis:
|
|
if (_fError || pvNil == (pgob = _PgobFromHid(hid)) || !pgob->FIs(kclsGOK))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for Play(Gob|This) (gid = %d)"), hid));
|
|
}
|
|
else
|
|
((PGOK)pgob)->FPlay();
|
|
break;
|
|
|
|
case kopPlayingGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopPlayingThis:
|
|
if (_fError || pvNil == (pgob = _PgobFromHid(hid)) || !pgob->FIs(kclsGOK))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for Playing(Gob|This) (gid = %d)"), hid));
|
|
_Push(fFalse);
|
|
}
|
|
else
|
|
_Push(((PGOK)pgob)->FPlaying());
|
|
break;
|
|
|
|
case kopStopGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopStopThis:
|
|
if (_fError || pvNil == (pgob = _PgobFromHid(hid)) || !pgob->FIs(kclsGOK))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for Stop(Gob|This) (gid = %d)"), hid));
|
|
}
|
|
else
|
|
((PGOK)pgob)->Stop();
|
|
break;
|
|
|
|
case kopCurFrameGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopCurFrameThis:
|
|
if (_fError || pvNil == (pgob = _PgobFromHid(hid)) || !pgob->FIs(kclsGOK))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for (CurFrame(Gob|This) (gid = %d)"), hid));
|
|
_Push(0);
|
|
}
|
|
else
|
|
_Push(((PGOK)pgob)->NfrCur());
|
|
break;
|
|
|
|
case kopCountFramesGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopCountFramesThis:
|
|
if (_fError || pvNil == (pgob = _PgobFromHid(hid)) || !pgob->FIs(kclsGOK))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for CountFrames(Gob|This) (gid = %d)"), hid));
|
|
_Push(0);
|
|
}
|
|
else
|
|
_Push(((PGOK)pgob)->NfrMac());
|
|
break;
|
|
|
|
case kopGotoFrameGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopGotoFrameThis:
|
|
lw1 = _LwPop();
|
|
if (_fError || pvNil == (pgob = _PgobFromHid(hid)) || !pgob->FIs(kclsGOK))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for GotoFrame(Gob|This) (gid = %d)"), hid));
|
|
}
|
|
else
|
|
((PGOK)pgob)->GotoNfr(lw1);
|
|
break;
|
|
|
|
case kopFilterCmdsGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopFilterCmdsThis:
|
|
lw1 = _LwPop();
|
|
lw2 = _LwPop();
|
|
lw3 = _LwPop();
|
|
if (_fError || pvNil == (pgob = _PgobFromHid(hid)) || !pgob->FIs(kclsGOK))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for FilterCmds(Gob|This) (gid = %d)"), hid));
|
|
}
|
|
else if (!((PGOK)pgob)->FFilterCidHid(lw1, lw2, lw3))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Filtering failed (gid = %d)"), hid));
|
|
}
|
|
break;
|
|
|
|
case kopDestroyChildrenGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopDestroyChildrenThis:
|
|
if (!_fError && pvNil != (pgob = _PgobFromHid(hid)))
|
|
{
|
|
PGOB pgobT;
|
|
|
|
GobMayDie();
|
|
while (pvNil != (pgobT = pgob->PgobFirstChild()))
|
|
ReleasePpo(&pgobT);
|
|
}
|
|
break;
|
|
|
|
case kopPlaySoundGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopPlaySoundThis:
|
|
lw1 = siiNil;
|
|
if (!_fError)
|
|
{
|
|
pgob = (hidNil == hid) ? pvNil : _PgobFromHid(hid);
|
|
|
|
if (pvNil != pgob && pgob->FIs(kclsGOK))
|
|
{
|
|
if (pvNil != (qrglw = _QlwGet(7)))
|
|
{
|
|
lw1 = ((PGOK)pgob)->SiiPlaySound(qrglw[6], qrglw[5], qrglw[4],
|
|
qrglw[3], qrglw[2], 0, qrglw[1], qrglw[0]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG
|
|
if (hidNil != hid)
|
|
{
|
|
_WarnSz(
|
|
PszLit("No GOK for PlaySound(Gob|This) (gid = %d)"),
|
|
hid);
|
|
}
|
|
#endif //DEBUG
|
|
|
|
if (pvNil != vpsndm && pvNil != (qrglw = _QlwGet(7)))
|
|
{
|
|
lw1 = vpsndm->SiiPlay(_prca, qrglw[6], qrglw[5], qrglw[4],
|
|
qrglw[3], qrglw[2], 0, qrglw[1], qrglw[0]);
|
|
}
|
|
}
|
|
_PopList(7);
|
|
}
|
|
_Push(lw1);
|
|
break;
|
|
|
|
case kopStopSound:
|
|
lw1 = _LwPop();
|
|
if (!_fError && pvNil != vpsndm)
|
|
vpsndm->Stop(lw1);
|
|
break;
|
|
|
|
case kopStopSoundClass:
|
|
lw1 = _LwPop();
|
|
lw2 = _LwPop();
|
|
if (!_fError && pvNil != vpsndm)
|
|
vpsndm->StopAll(lw1, lw2);
|
|
break;
|
|
|
|
case kopPlayingSound:
|
|
lw1 = _LwPop();
|
|
if (!_fError && pvNil != vpsndm)
|
|
_Push(vpsndm->FPlaying(lw1));
|
|
break;
|
|
|
|
case kopPlayingSoundClass:
|
|
lw1 = _LwPop();
|
|
lw2 = _LwPop();
|
|
if (!_fError && pvNil != vpsndm)
|
|
_Push(vpsndm->FPlayingAll(lw1, lw2));
|
|
break;
|
|
|
|
case kopPauseSound:
|
|
lw1 = _LwPop();
|
|
if (!_fError && pvNil != vpsndm)
|
|
vpsndm->Pause(lw1);
|
|
break;
|
|
|
|
case kopPauseSoundClass:
|
|
lw1 = _LwPop();
|
|
lw2 = _LwPop();
|
|
if (!_fError && pvNil != vpsndm)
|
|
vpsndm->PauseAll(lw1, lw2);
|
|
break;
|
|
|
|
case kopResumeSound:
|
|
lw1 = _LwPop();
|
|
if (!_fError && pvNil != vpsndm)
|
|
vpsndm->Resume(lw1);
|
|
break;
|
|
|
|
case kopResumeSoundClass:
|
|
lw1 = _LwPop();
|
|
lw2 = _LwPop();
|
|
if (!_fError && pvNil != vpsndm)
|
|
vpsndm->ResumeAll(lw1, lw2);
|
|
break;
|
|
|
|
case kopPlayMouseSoundGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopPlayMouseSoundThis:
|
|
lw1 = _LwPop();
|
|
lw2 = _LwPop();
|
|
if (!_fError && pvNil != (pgob = _PgobFromHid(hid)) &&
|
|
pgob->FIs(kclsGOK))
|
|
{
|
|
_Push(((PGOK)pgob)->SiiPlayMouseSound(lw1, lw2));
|
|
}
|
|
else
|
|
_Push(siiNil);
|
|
break;
|
|
|
|
case kopWidthGob:
|
|
case kopHeightGob:
|
|
hid = _LwPop();
|
|
//fall thru
|
|
case kopWidthThis:
|
|
case kopHeightThis:
|
|
if (!_fError && pvNil != (pgob = _PgobFromHid(hid)))
|
|
{
|
|
RC rc;
|
|
|
|
pgob->GetRc(&rc, cooLocal);
|
|
if (kopWidthGob == op || kopWidthThis == op)
|
|
_Push(rc.Dxp());
|
|
else
|
|
_Push(rc.Dyp());
|
|
}
|
|
else
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for (Width|Height)(Gob|This) (gid = %d)"), hid));
|
|
_Push(0);
|
|
}
|
|
break;
|
|
|
|
case kopSetNoSlipGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopSetNoSlipThis:
|
|
lw1 = _LwPop();
|
|
if (!_fError && pvNil != (pgob = _PgobFromHid(hid)) &&
|
|
pgob->FIs(kclsGOK))
|
|
{
|
|
((PGOK)pgob)->SetNoSlip(lw1);
|
|
}
|
|
else
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for SetNoSlip(Gob|This) (gid = %d)"), hid));
|
|
}
|
|
break;
|
|
|
|
case kopFIsDescendent:
|
|
lw1 = _LwPop();
|
|
lw2 = _LwPop();
|
|
if (!_fError)
|
|
{
|
|
PGOB pgobPar = _PgobFromHid(lw2);
|
|
|
|
if (pvNil == pgobPar || pvNil == (pgob = _PgobFromHid(lw1)))
|
|
_Push(0);
|
|
else
|
|
{
|
|
while (pgob != pvNil && pgob != pgobPar)
|
|
pgob = _pwoks->PgobParGob(pgob);
|
|
_Push(pgob == pgobPar);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case kopSetMasterVolume:
|
|
lw1 = _LwPop();
|
|
if (!_fError && pvNil != vpsndm)
|
|
vpsndm->SetVlm(lw1);
|
|
break;
|
|
|
|
case kopGetMasterVolume:
|
|
if (pvNil != vpsndm)
|
|
_Push(vpsndm->VlmCur());
|
|
else
|
|
_Push(0);
|
|
break;
|
|
|
|
case kopStartLongOp:
|
|
vpappb->BeginLongOp();
|
|
break;
|
|
|
|
case kopEndLongOp:
|
|
vpappb->EndLongOp(_LwPop());
|
|
break;
|
|
|
|
case kopSetToolTipSourceGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopSetToolTipSourceThis:
|
|
lw1 = _LwPop();
|
|
if (!_fError && pvNil != (pgob = _PgobFromHid(hid)) &&
|
|
pgob->FIs(kclsGOK))
|
|
{
|
|
((PGOK)pgob)->SetHidToolTip(lw1);
|
|
}
|
|
else
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for SetToolTipSource(Gob|This) (gid = %d)"),
|
|
hid));
|
|
}
|
|
break;
|
|
|
|
case kopModalHelp:
|
|
lw1 = _LwPop();
|
|
lw2 = _LwPop();
|
|
if (!_fError)
|
|
{
|
|
GobMayDie();
|
|
if (_pwoks->FModalTopic(_prca, lw1, &lw3))
|
|
lw2 = lw3;
|
|
_Push(lw2);
|
|
}
|
|
break;
|
|
|
|
case kopFlushUserEvents:
|
|
vpappb->FlushUserEvents(_LwPop());
|
|
break;
|
|
|
|
case kopStreamGob:
|
|
hid = _LwPop();
|
|
//fall through
|
|
case kopStreamThis:
|
|
lw1 = _LwPop();
|
|
if (_fError || pvNil == (pgob = _PgobFromHid(hid)) ||
|
|
!pgob->FIs(kclsGOK))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing GOB for Stream(Gob|This) (gid = %d)"), hid));
|
|
}
|
|
else
|
|
((PGOK)pgob)->Stream(FPure(lw1));
|
|
break;
|
|
|
|
default:
|
|
return SCEG_PAR::_FExecOp(op);
|
|
}
|
|
|
|
return !_fError;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Put up an alert containing a list of numbers.
|
|
***************************************************************************/
|
|
void SCEG::_DoAlert(long op)
|
|
{
|
|
STN stn1;
|
|
STN stn2;
|
|
long lw;
|
|
bool fStrings;
|
|
long clw = _LwPop();
|
|
|
|
switch (op)
|
|
{
|
|
default:
|
|
return;
|
|
|
|
#ifdef CHUNK_STATS
|
|
case kopPrintStat:
|
|
#endif //CHUNK_STATS
|
|
case kopAlert:
|
|
case kopPrint:
|
|
fStrings = fFalse;
|
|
break;
|
|
|
|
#ifdef CHUNK_STATS
|
|
case kopPrintStrStat:
|
|
#endif //CHUNK_STATS
|
|
case kopAlertStr:
|
|
case kopPrintStr:
|
|
fStrings = fTrue;
|
|
break;
|
|
}
|
|
|
|
if (fStrings && pvNil == _pstrg)
|
|
{
|
|
_Error(fTrue);
|
|
return;
|
|
}
|
|
|
|
stn1.FFormatSz(PszLit("Script Message ('%f', 0x%x, %d): "),
|
|
_pscpt->Ctg(), _pscpt->Cno(), _ilwCur);
|
|
|
|
while (clw-- > 0)
|
|
{
|
|
lw = _LwPop();
|
|
if (fStrings)
|
|
_pstrg->FGet(lw, &stn2);
|
|
else
|
|
stn2.FFormatSz(PszLit("%d (0x%x) "), lw, lw);
|
|
stn1.FAppendStn(&stn2);
|
|
}
|
|
|
|
|
|
switch (op)
|
|
{
|
|
#ifdef CHUNK_STATS
|
|
case kopPrintStat:
|
|
case kopPrintStrStat:
|
|
CFL::DumpStn(&stn1);
|
|
break;
|
|
#endif //CHUNK_STATS
|
|
|
|
case kopAlert:
|
|
case kopAlertStr:
|
|
_pwoks->TGiveAlert(&stn1, bkOk, cokInformation);
|
|
break;
|
|
|
|
case kopPrint:
|
|
case kopPrintStr:
|
|
_pwoks->Print(&stn1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Get or set the string in an edit control.
|
|
***************************************************************************/
|
|
void SCEG::_DoEditControl(long hid, long stid, bool fGet)
|
|
{
|
|
PEDCB pedcb;
|
|
long cch;
|
|
achar rgch[kcchMaxStn];
|
|
STN stn;
|
|
|
|
if (_fError || pvNil == (pedcb = (PEDCB)_PgobFromHid(hid)) ||
|
|
!pedcb->FIs(kclsEDCB))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("Missing edit control for (Get|Set)Edit (gid = %d)"), hid));
|
|
return;
|
|
}
|
|
|
|
if (pvNil == _pstrg)
|
|
{
|
|
_Error(fTrue);
|
|
return;
|
|
}
|
|
|
|
cch = pedcb->IchMac();
|
|
if (fGet)
|
|
{
|
|
cch = pedcb->CchFetch(rgch, 0, LwMin(kcchMaxStn, cch));
|
|
stn.SetRgch(rgch, cch);
|
|
_pstrg->FPut(stid, &stn);
|
|
}
|
|
else
|
|
{
|
|
_pstrg->FGet(stid, &stn);
|
|
pedcb->FReplace(stn.Psz(), stn.Cch(), 0, cch);
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Set the current color table.
|
|
***************************************************************************/
|
|
void SCEG::_SetColorTable(CNO cno)
|
|
{
|
|
PGL pglclr;
|
|
|
|
if (pvNil == (pglclr = _PglclrGet(cno)))
|
|
return;
|
|
|
|
GPT::SetActiveColors(pglclr, fpalIdentity);
|
|
ReleasePpo(&pglclr);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Read the indicated color table and return a reference to it.
|
|
***************************************************************************/
|
|
PGL SCEG::_PglclrGet(CNO cno)
|
|
{
|
|
PCABO pcabo;
|
|
PGL pglclr;
|
|
|
|
if (cnoNil == cno)
|
|
return pvNil;
|
|
|
|
pcabo = (PCABO)_prca->PbacoFetch(kctgColorTable, cno, FReadColorTable);
|
|
if (pvNil == pcabo)
|
|
return pvNil;
|
|
|
|
pglclr = (PGL)pcabo->po;
|
|
AssertPo(pglclr, 0);
|
|
pglclr->AddRef();
|
|
pcabo->SetCrep(crepTossFirst);
|
|
ReleasePpo(&pcabo);
|
|
|
|
return pglclr;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
A chunky resource reader to read a color table. Wraps the color table in
|
|
a CABO.
|
|
***************************************************************************/
|
|
bool FReadColorTable(PCRF pcrf, CTG ctg, CNO cno, PBLCK pblck,
|
|
PBACO *ppbaco, long *pcb)
|
|
{
|
|
PCABO pcabo;
|
|
PGL pglclr = pvNil;
|
|
|
|
*pcb = pblck->Cb(fTrue);
|
|
if (pvNil == ppbaco)
|
|
return fTrue;
|
|
|
|
if (!pblck->FUnpackData())
|
|
goto LFail;
|
|
*pcb = pblck->Cb();
|
|
|
|
if (pvNil == (pglclr = GL::PglRead(pblck)) || pglclr->CbEntry() != size(CLR))
|
|
goto LFail;
|
|
|
|
if (pvNil == (pcabo = NewObj CABO(pglclr)))
|
|
{
|
|
LFail:
|
|
ReleasePpo(&pglclr);
|
|
TrashVar(pcb);
|
|
TrashVar(ppbaco);
|
|
return fFalse;
|
|
}
|
|
|
|
*ppbaco = pcabo;
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
Launch an app with the given command line. Return true iff the launch
|
|
was successful.
|
|
***************************************************************************/
|
|
bool SCEG::_FLaunch(long stid)
|
|
{
|
|
AssertThis(0);
|
|
STN stn;
|
|
|
|
if (pvNil == _pstrg)
|
|
{
|
|
_Error(fTrue);
|
|
return fFalse;
|
|
}
|
|
|
|
if (!_pstrg->FGet(stid, &stn))
|
|
{
|
|
Debug(_WarnSz(
|
|
PszLit("String missing for Launch (stid = %d)"), stid));
|
|
Warn("string missing");
|
|
return fFalse;
|
|
}
|
|
|
|
#ifdef WIN
|
|
STARTUPINFO sui;
|
|
PROCESS_INFORMATION pi;
|
|
|
|
ClearPb(&sui, size(sui));
|
|
sui.cb = size(sui);
|
|
|
|
return CreateProcess(pvNil, stn.Psz(), pvNil, pvNil, fFalse,
|
|
DETACHED_PROCESS, pvNil, pvNil, &sui, &pi );
|
|
#else //!WIN
|
|
RawRtn(); //REVIEW shonk: Mac: implement SCEG::_FLaunch
|
|
return fFalse;
|
|
#endif //!WIN
|
|
}
|
|
|