/* 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 }