Microsoft-3D-Movie-Maker/kauai/SRC/SCREXEG.CPP
2022-05-03 16:31:19 -07:00

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
}