mirror of
https://github.com/scummvm/scummvm.git
synced 2025-04-02 10:52:32 -04:00
1655 lines
42 KiB
C++
1655 lines
42 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "bagel/baglib/rp_object.h"
|
|
#include "bagel/baglib/master_win.h"
|
|
#include "bagel/baglib/base_pda.h"
|
|
#include "bagel/baglib/log_msg.h"
|
|
#include "bagel/baglib/pda.h"
|
|
#include "bagel/baglib/zoom_pda.h"
|
|
#include "bagel/boflib/log.h"
|
|
|
|
namespace Bagel {
|
|
|
|
// constants for save/restore
|
|
#define NUM_RP_FIELDS 9
|
|
#define mRPCurDossierShift 28
|
|
|
|
#define mRPReported 0x00010000
|
|
#define mResPrinted 0x00020000
|
|
#define mTouched 0x00040000
|
|
#define mRPRead 0x00080000
|
|
#define mRPMoviePlayed 0x00100000
|
|
#define mRPTDos1Eval 0x00200000
|
|
#define mRPTDos2Eval 0x00400000
|
|
#define mRPTDos3Eval 0x00800000
|
|
#define mRPUDos1Eval 0x01000000
|
|
#define mRPUDos2Eval 0x02000000
|
|
#define mRPUDos3Eval 0x04000000
|
|
#define mRPCurVisible 0x08000000
|
|
#define mRPTimeSet 0x10000000
|
|
#define mRPCurDossier 0x60000000
|
|
#define mRPTime 0x0000FFFF
|
|
|
|
// Initialize statics
|
|
CBofList<CBagRPObject *> *CBagRPObject::_pRPList = nullptr;
|
|
CBagVar *CBagRPObject::_turnCount = nullptr;
|
|
CBagVar *CBagRPObject::_pLogStateVar = nullptr;
|
|
CBagVar *CBagRPObject::_pPrevLogStateVar = nullptr;
|
|
CBagVar *CBagRPObject::_pBarLogPages = nullptr;
|
|
CBagVar *CBagRPObject::_pPrevBarPage = nullptr;
|
|
CBagVar *CBagRPObject::_pCurBarPage = nullptr;
|
|
int32 CBagRPObject::_nLastRPQCheck = 0;
|
|
CBagRPObject *CBagRPObject::_pCurRPObject = nullptr;
|
|
RPStates CBagRPObject::_eRPMode = RP_NO_MODE;
|
|
CBagRPObject *CBagRPObject::_pActivateThisGuy = nullptr;
|
|
|
|
// Local globals
|
|
//
|
|
// CBagRPObject -
|
|
// CBagRPObject is an object that can be accessed through script to handle residue
|
|
// printing.
|
|
//
|
|
CBagRPObject::CBagRPObject() {
|
|
_xObjType = RESPRNT_OBJ;
|
|
|
|
// Dossier list
|
|
_pTouchedList = nullptr;
|
|
_pUntouchedList = nullptr;
|
|
|
|
// Touched var, not required.
|
|
_pTouchedVar = nullptr;
|
|
|
|
_pDescObj = nullptr;
|
|
|
|
_nRPTime = 0;
|
|
_bRPReported = false;
|
|
_bResPrinted = false;
|
|
_bTouched = false;
|
|
_bRPRead = false;
|
|
_bRPTimeSet = false;
|
|
_bCurVisible = false;
|
|
_bInitialized = false;
|
|
_bMoviePlayed = false;
|
|
|
|
// Have to save the original rectangle since we'll be messing with it later
|
|
// on.
|
|
_cOrigRect.setRect(0, 0, 0, 0);
|
|
_bOrigRectInit = false;
|
|
|
|
// the object's name, we pull this out of the wld sdev.
|
|
_pObjectName = nullptr;
|
|
|
|
// Initialize movie land
|
|
_sMovieObj = "";
|
|
_pMovieObj = nullptr;
|
|
|
|
// Save variable
|
|
_pSaveVar = nullptr;
|
|
|
|
// Current dossier
|
|
_nCurDossier = 0;
|
|
|
|
_pVarObj = nullptr;
|
|
}
|
|
|
|
CBagRPObject::~CBagRPObject() {
|
|
// If still attached, then detach
|
|
if (CBagParseObject::isAttached()) {
|
|
CBagRPObject::detach();
|
|
}
|
|
|
|
// Explicitly delete everything in the list
|
|
bool bSame = (_pTouchedList == _pUntouchedList);
|
|
DossierObj *pDObj;
|
|
|
|
// Trash the expression list
|
|
if (_pTouchedList != nullptr) {
|
|
int nCount = _pTouchedList->getCount();
|
|
for (int i = 0; i < nCount; i++) {
|
|
pDObj = _pTouchedList->remove(0);
|
|
if (pDObj) {
|
|
delete pDObj;
|
|
}
|
|
}
|
|
|
|
delete _pTouchedList;
|
|
_pTouchedList = nullptr;
|
|
}
|
|
|
|
// Explicitly delete everything in the list
|
|
// Only trash them if they are not the same list.
|
|
if ((bSame == false) && (_pUntouchedList != nullptr)) {
|
|
int nCount = _pUntouchedList->getCount();
|
|
for (int i = 0; i < nCount; i++) {
|
|
pDObj = _pUntouchedList->remove(0);
|
|
if (pDObj) {
|
|
delete pDObj;
|
|
}
|
|
}
|
|
delete _pUntouchedList;
|
|
_pUntouchedList = nullptr;
|
|
}
|
|
|
|
// Delete the description object
|
|
delete _pDescObj;
|
|
_pDescObj = nullptr;
|
|
|
|
// We got these vars from the var manager, so just null it out, don't delete it!
|
|
_pVarObj = nullptr;
|
|
_turnCount = nullptr;
|
|
_pTouchedVar = nullptr;
|
|
_pMovieObj = nullptr;
|
|
_pSaveVar = nullptr;
|
|
|
|
// Clear our statics, yes, I mean to do that here.
|
|
_pLogStateVar = nullptr;
|
|
_pPrevLogStateVar = nullptr;
|
|
_pBarLogPages = nullptr;
|
|
_pPrevBarPage = nullptr;
|
|
_pCurBarPage = nullptr;
|
|
}
|
|
|
|
ParseCodes CBagRPObject::setInfo(CBagIfstream &istr) {
|
|
bool nObjectUpdated = false;
|
|
char szLocalStr[256];
|
|
CBofString sStr(szLocalStr, 256);
|
|
|
|
while (!istr.eof()) {
|
|
istr.eatWhite();
|
|
|
|
char ch = (char)istr.peek();
|
|
switch (ch) {
|
|
//
|
|
// This will be the list of results that are to be used if the
|
|
// object is found to have been touched.
|
|
//
|
|
// Touched var can also be in this stream.
|
|
//
|
|
case 'U':
|
|
case 'T': {
|
|
getAlphaNumFromStream(istr, sStr);
|
|
if (sStr.find("TOUCHEDVAR") == 0) {
|
|
getAlphaNumFromStream(istr, sStr);
|
|
|
|
nObjectUpdated = true;
|
|
istr.eatWhite();
|
|
|
|
// Get the variable name from the definition line, then find it
|
|
// in the global list.
|
|
_pTouchedVar = g_VarManager->getVariable(sStr);
|
|
|
|
break;
|
|
}
|
|
|
|
bool bTouched = (ch == 'T');
|
|
|
|
if ((bTouched && !sStr.find("TOUCHED")) || (bTouched == false && !sStr.find("UNTOUCHED"))) {
|
|
|
|
nObjectUpdated = true;
|
|
|
|
bool bContinue;
|
|
do {
|
|
CBagExpression *px = nullptr;
|
|
|
|
getAlphaNumFromStream(istr, sStr);
|
|
bContinue = false;
|
|
|
|
// If the next non-whitespace char is a paren, then we're going
|
|
// to have an expression.
|
|
istr.eatWhite();
|
|
if ((char)istr.peek() == '(') {
|
|
px = new CBagExpression();
|
|
px->setInfo(istr);
|
|
}
|
|
|
|
// add this to the correct list.
|
|
if (bTouched) {
|
|
setTouchedDos(sStr, px);
|
|
} else {
|
|
setUntouchedDos(sStr, px);
|
|
}
|
|
|
|
if ((char)istr.peek() == ',') {
|
|
istr.getCh();
|
|
istr.eatWhite();
|
|
bContinue = true;
|
|
}
|
|
} while (bContinue);
|
|
} else {
|
|
putbackStringOnStream(istr, sStr);
|
|
}
|
|
}
|
|
break;
|
|
|
|
//
|
|
// We can hit a continuation character, a plus sign tells us that there
|
|
// is more on the next line.
|
|
case '+': {
|
|
// Skip over this character
|
|
istr.getCh();
|
|
istr.eatWhite();
|
|
|
|
// Now keep going until we get our next alpha num.
|
|
while (!Common::isAlnum((char)istr.peek())) {
|
|
istr.getCh();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'N': {
|
|
getAlphaNumFromStream(istr, sStr);
|
|
if (!sStr.find("NAME")) {
|
|
nObjectUpdated = true;
|
|
|
|
istr.eatWhite();
|
|
getAlphaNumFromStream(istr, sStr);
|
|
|
|
_sObjectName = sStr;
|
|
|
|
} else {
|
|
putbackStringOnStream(istr, sStr);
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Same and Save can be in the stream.
|
|
case 'S': {
|
|
getAlphaNumFromStream(istr, sStr);
|
|
|
|
if (!sStr.find("SAVE")) {
|
|
nObjectUpdated = true;
|
|
istr.eatWhite();
|
|
|
|
// Get the variable name from the definition line, then find it
|
|
// in the global list.
|
|
getAlphaNumFromStream(istr, sStr);
|
|
_pSaveVar = g_VarManager->getVariable(sStr);
|
|
|
|
// the variable must have been found, if it wasn't, then
|
|
// complain violently.
|
|
if (_pSaveVar == nullptr) {
|
|
reportError(ERR_UNKNOWN, "Invalid Residue Print SAVE Variable=%s",
|
|
sStr.getBuffer());
|
|
return UNKNOWN_TOKEN;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (!sStr.find("SAME")) {
|
|
nObjectUpdated = true;
|
|
|
|
_pUntouchedList = _pTouchedList;
|
|
} else {
|
|
putbackStringOnStream(istr, sStr);
|
|
}
|
|
}
|
|
break;
|
|
|
|
//
|
|
// Might have an associated movie
|
|
//
|
|
case 'M': {
|
|
getAlphaNumFromStream(istr, sStr);
|
|
if (!sStr.find("MOVIE")) {
|
|
nObjectUpdated = true;
|
|
|
|
getAlphaNumFromStream(istr, sStr);
|
|
_sMovieObj = sStr;
|
|
} else {
|
|
putbackStringOnStream(istr, sStr);
|
|
}
|
|
}
|
|
break;
|
|
|
|
//
|
|
// Must have a description file, this contains the description of the object
|
|
// that is being residue printed.
|
|
//
|
|
case 'D': {
|
|
getAlphaNumFromStream(istr, sStr);
|
|
if (!sStr.find("DESC")) {
|
|
nObjectUpdated = true;
|
|
|
|
_pDescObj = new CBagTextObject();
|
|
if (_pDescObj->setInfo(istr) == PARSING_DONE) {
|
|
return PARSING_DONE;
|
|
}
|
|
} else {
|
|
putbackStringOnStream(istr, sStr);
|
|
}
|
|
}
|
|
break;
|
|
|
|
// The variable, which is required, will be the var that is set when
|
|
// residue printing of that object has occurred.
|
|
case 'V': {
|
|
getAlphaNumFromStream(istr, sStr);
|
|
if (!sStr.find("VAR")) {
|
|
nObjectUpdated = true;
|
|
istr.eatWhite();
|
|
|
|
// Get the variable name from the definition line, then find it
|
|
// in the global list.
|
|
getAlphaNumFromStream(istr, sStr);
|
|
_pVarObj = g_VarManager->getVariable(sStr);
|
|
|
|
// the variable must have been found, if it wasn't, then
|
|
// complain violently.
|
|
if (_pVarObj == nullptr) {
|
|
reportError(ERR_UNKNOWN, "Invalid Residue Print Variable=%s",
|
|
sStr.getBuffer());
|
|
return UNKNOWN_TOKEN;
|
|
}
|
|
} else {
|
|
putbackStringOnStream(istr, sStr);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default: {
|
|
ParseCodes parseCode = CBagObject::setInfo(istr);
|
|
if (parseCode == PARSING_DONE) {
|
|
return PARSING_DONE;
|
|
}
|
|
|
|
if (parseCode == UPDATED_OBJECT) {
|
|
nObjectUpdated = true;
|
|
} else { // rc==UNKNOWN_TOKEN
|
|
if (nObjectUpdated)
|
|
return UPDATED_OBJECT;
|
|
|
|
return UNKNOWN_TOKEN;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return PARSING_DONE;
|
|
}
|
|
|
|
ErrorCode CBagRPObject::attach() {
|
|
// Add this object to the list of objects in the RPO queue.
|
|
|
|
if (_pRPList == nullptr) {
|
|
_pRPList = new CBofList<CBagRPObject *>;
|
|
}
|
|
|
|
assert(_pRPList != nullptr);
|
|
|
|
_pRPList->addToTail(this);
|
|
|
|
ErrorCode errorCode = CBagObject::attach();
|
|
|
|
// If we haven't initialized this guys original rectangle, then do it
|
|
// here.
|
|
if (_bOrigRectInit == false) {
|
|
_cOrigRect = getRect();
|
|
}
|
|
|
|
// Start this object off as invisible (so that we don't receive update events).
|
|
setVisible(false);
|
|
|
|
restoreResiduePrintedVars();
|
|
|
|
if (_bInitialized == false) {
|
|
_bInitialized = initialize();
|
|
}
|
|
|
|
RPStates rpState = getLogState();
|
|
switch (rpState) {
|
|
case RP_NO_MODE:
|
|
break;
|
|
case RP_RESULTS:
|
|
case RP_READ_DOSSIER:
|
|
// If this guy was being shown before, bring it up now.
|
|
if (_bCurVisible) {
|
|
_pActivateThisGuy = this;
|
|
}
|
|
break;
|
|
case RP_REVIEW:
|
|
if (_bRPRead) {
|
|
activateResiduePrintedReview();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return errorCode;
|
|
}
|
|
|
|
ErrorCode CBagRPObject::detach() {
|
|
// Turn off our current object
|
|
if (_pCurRPObject == this) {
|
|
_pCurRPObject = nullptr;
|
|
}
|
|
|
|
// If we're in the current list, then remove us!
|
|
if (_pRPList) {
|
|
int nCount = _pRPList->getCount();
|
|
for (int i = 0; i < nCount; i++) {
|
|
CBagObject *pObj = _pRPList->getNodeItem(i);
|
|
|
|
if (pObj == this) {
|
|
_pRPList->remove(i);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (_pRPList->getCount() == 0) {
|
|
delete _pRPList;
|
|
_pRPList = nullptr;
|
|
}
|
|
}
|
|
|
|
_bInitialized = false;
|
|
|
|
// Don't really need to do anything here since the destructor will trash the
|
|
// entire list.
|
|
return CBagObject::detach();
|
|
}
|
|
|
|
// Have a dossier name and expression for a touched object
|
|
void CBagRPObject::setTouchedDos(CBofString &s, CBagExpression *x) {
|
|
// Make sure the list has been allocated
|
|
if (_pTouchedList == nullptr) {
|
|
_pTouchedList = new CBofList<DossierObj *>;
|
|
}
|
|
|
|
DossierObj *pDosObj = new DossierObj();
|
|
|
|
// Just store the name for now, we'll get the pointer to the dossier in
|
|
// the attach code.
|
|
pDosObj->_sDossier = s;
|
|
pDosObj->_xDosExp = x;
|
|
|
|
_pTouchedList->addToTail(pDosObj);
|
|
}
|
|
|
|
// Store a dossier name and associated expression for an untouched object
|
|
void CBagRPObject::setUntouchedDos(CBofString &s, CBagExpression *x) {
|
|
// Make sure the list has been allocated
|
|
if (_pUntouchedList == nullptr) {
|
|
_pUntouchedList = new CBofList<DossierObj *>;
|
|
}
|
|
|
|
DossierObj *pDosObj = new DossierObj();
|
|
|
|
// Store the expression and the dossier string.
|
|
pDosObj->_sDossier = s;
|
|
pDosObj->_xDosExp = x;
|
|
|
|
_pUntouchedList->addToTail(pDosObj);
|
|
}
|
|
|
|
// This static is the tough guy that is in charge of checking the rp queue for
|
|
// any objects that have results that should be returned.
|
|
int CBagRPObject::runResiduePrintedQueue() {
|
|
// Might get called with no residue printing list
|
|
if (_pRPList == nullptr) {
|
|
return 0;
|
|
}
|
|
|
|
// The first part of this static should only run if the log is frontmost.
|
|
if (SBBasePda::getPdaMode() == PDA_LOG_MODE) {
|
|
// If our script switched us to the main menu, then make sure that we
|
|
// have a chance to deactivate anything that we have active.
|
|
RPStates prevRPState = _eRPMode;
|
|
RPStates curRPState = getLogState();
|
|
if (prevRPState != curRPState && curRPState == RP_MAIN_MENU) {
|
|
if (_pCurRPObject) {
|
|
_pCurRPObject->deactivateRPObject();
|
|
_pCurRPObject->_bCurVisible = false;
|
|
_pCurRPObject->saveResiduePrintedVars();
|
|
}
|
|
}
|
|
|
|
// Check the first guy in the queue to see if he's been initialized, if not,
|
|
// then cruise the whole thing.
|
|
int nCount = _pRPList->getCount();
|
|
if (nCount == 0) {
|
|
return 0;
|
|
}
|
|
|
|
for (int i = 0; i < nCount; i++) {
|
|
CBagRPObject *pRPObj = _pRPList->getNodeItem(i);
|
|
|
|
// This could fail if we are not initialized properly
|
|
if (pRPObj->_bInitialized == false) {
|
|
pRPObj->_bInitialized = pRPObj->initialize();
|
|
}
|
|
}
|
|
|
|
// If we have an activate set, then we want to get this guy up as soon as possible,
|
|
// he has been completely constructed and attached and all that cool stuff, this was
|
|
// the object that was frontmost when we went into a flashback, saved a game, etc...
|
|
//
|
|
// Don't activate until we've been properly initialized.
|
|
if (_pActivateThisGuy) {
|
|
if (_pActivateThisGuy->_bInitialized) {
|
|
RPStates rpState = getLogState();
|
|
switch (rpState) {
|
|
case RP_REVIEW:
|
|
if (_pActivateThisGuy->_bRPRead) {
|
|
_pActivateThisGuy->activateResiduePrintedReview();
|
|
}
|
|
break;
|
|
|
|
case RP_RESULTS:
|
|
_pActivateThisGuy->activateRPObject();
|
|
break;
|
|
|
|
case RP_READ_DOSSIER: {
|
|
CBagDossierObject *pDObj = _pActivateThisGuy->getActiveDossier();
|
|
if (pDObj) {
|
|
pDObj->showDossierText();
|
|
// Special case, make sure the trail back to the rp obj is clearly marked
|
|
pDObj->setResiduePrintedObject(_pActivateThisGuy);
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
_pActivateThisGuy = nullptr;
|
|
}
|
|
}
|
|
|
|
// If our last update is zero, then we have to parouse our list and fill in all the
|
|
// missing vars. This is considered our initialization trigger.
|
|
if (_nLastRPQCheck == 0) {
|
|
deactivateResiduePrintedReview();
|
|
}
|
|
}
|
|
|
|
// Be semi-efficient about this and only execute every 5 seconds or so.
|
|
|
|
int32 nCurTime = getTimer();
|
|
if (nCurTime > _nLastRPQCheck + 5000) {
|
|
|
|
// Get the turncount variable.
|
|
if (_turnCount == nullptr) {
|
|
_turnCount = g_VarManager->getVariable("TURNCOUNT");
|
|
}
|
|
//
|
|
assert(_turnCount != nullptr);
|
|
|
|
// Get the current time
|
|
int nCurSBTime = _turnCount->getNumValue();
|
|
int nCount = _pRPList->getCount();
|
|
|
|
for (int i = 0; i < nCount; i++) {
|
|
CBagRPObject *pRPObj = _pRPList->getNodeItem(i);
|
|
|
|
// Find out if there are any events worth reporting.
|
|
//
|
|
// Remove the addition of 20, that's already been added in the script.
|
|
if (pRPObj->_bRPReported == false && pRPObj->_nRPTime != 0 && nCurSBTime >= pRPObj->_nRPTime) {
|
|
addToMsgQueue(pRPObj);
|
|
}
|
|
}
|
|
|
|
if (getLogState() == RP_REVIEW) {
|
|
setLogPages(99);
|
|
}
|
|
|
|
_nLastRPQCheck = nCurTime;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// This static will cruise through the whole queue, check the value of each
|
|
// associated variable, find a non-null one and activate the return time associated
|
|
// with that residue print request.
|
|
int CBagRPObject::updateResiduePrintedQueue() {
|
|
assert(_pRPList != nullptr);
|
|
|
|
int nCount = _pRPList->getCount();
|
|
char szLocalBuff[256];
|
|
CBofString cStr(szLocalBuff, 256);
|
|
|
|
// Cruise through and find if we have one that has had it's value changed.
|
|
for (int i = 0; i < nCount; i++) {
|
|
CBagRPObject *pRPObj = _pRPList->getNodeItem(i);
|
|
if (pRPObj) {
|
|
cStr = pRPObj->_pVarObj->getValue();
|
|
|
|
// If it's value is NOT 3000, then store its value in the associative
|
|
// rp object.
|
|
if (cStr.find("3000") == -1) {
|
|
int nTimecount = atoi(szLocalBuff);
|
|
pRPObj->_nRPTime = nTimecount;
|
|
pRPObj->_bRPReported = false;
|
|
pRPObj->_bResPrinted = true;
|
|
|
|
// Evaluate the expression as we submit it for printing, this will
|
|
// guarantee that the expressions are reported as a function of the
|
|
// time that they were submitted. Trust me, this statement makes
|
|
// perfect sense.
|
|
pRPObj->evaluateDossiers();
|
|
pRPObj->saveResiduePrintedVars();
|
|
// Reset back to "3000"
|
|
|
|
cStr = "3000";
|
|
pRPObj->_pVarObj->setValue(cStr);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// This static runs through the entire chain and makes sure that everything
|
|
// has been deactivated and is not displayed to the PDA. Called from
|
|
// script.
|
|
void CBagRPObject::deactivateResiduePrintedQueue() {
|
|
assert(_pRPList != nullptr);
|
|
|
|
int nCount = _pRPList->getCount();
|
|
|
|
// Cruise through and find if we have one that has had it's value changed.
|
|
for (int i = 0; i < nCount; i++) {
|
|
CBagRPObject *pRPObj = _pRPList->getNodeItem(i);
|
|
if (pRPObj) {
|
|
pRPObj->deactivateRPObject();
|
|
}
|
|
}
|
|
|
|
deactivateResiduePrintedReview();
|
|
}
|
|
|
|
// Add this guy to the message queue and make that little message
|
|
// light blink away!
|
|
bool CBagRPObject::addToMsgQueue(CBagRPObject *pRPObj) {
|
|
bool bAddedToQueue = false;
|
|
|
|
// If zoomed, then don't add to the message queue!!!!
|
|
if (zoomed()) {
|
|
return false;
|
|
}
|
|
|
|
CBagLog *pLogWld = (CBagLog *)g_SDevManager->getStorageDevice(LOG_WLD);
|
|
|
|
if (pLogWld) {
|
|
pRPObj->setMsgWaiting(true); // mark this guy as waiting
|
|
pLogWld->activateLocalObject(pRPObj);
|
|
|
|
pRPObj->setVisible(true); // make sure it gets updated.
|
|
pRPObj->_bRPRead = false; // hasn't been read yet
|
|
pRPObj->_bRPReported = true; // been reported though
|
|
pRPObj->saveResiduePrintedVars(); // Update the variable store
|
|
bAddedToQueue = true;
|
|
}
|
|
|
|
return bAddedToQueue;
|
|
}
|
|
|
|
// If we get called to run this guy, then run the movie and post the results,
|
|
// if any.
|
|
bool CBagRPObject::runObject() {
|
|
bool bMoviePlayed = false;
|
|
|
|
// If we have a movie, which we should, run it!
|
|
//only play the movie the first time through!
|
|
bool bLocalMoviePlayed = false;
|
|
if (_pMovieObj && _bMoviePlayed == false) {
|
|
bMoviePlayed = _pMovieObj->runObject();
|
|
_bMoviePlayed = true;
|
|
bLocalMoviePlayed = true;
|
|
}
|
|
|
|
// Order is important here, if we end up activating the RP review, then
|
|
// we're going to need this guy marked as read.
|
|
|
|
_bRPRead = true;
|
|
saveResiduePrintedVars(); // Update the variable store
|
|
|
|
// Make sure that nothing from a previous res print is showing
|
|
if (_pCurRPObject) {
|
|
_pCurRPObject->deactivateRPObject();
|
|
_pCurRPObject->_bCurVisible = false;
|
|
_pCurRPObject->saveResiduePrintedVars();
|
|
_pCurRPObject = nullptr;
|
|
}
|
|
|
|
// Parouse the rp list, if we have more than one waiting for the
|
|
// user, then go to the residue print results. Be a good guy and
|
|
// go to the page that this guy will show up on.
|
|
//
|
|
// results waiting will only return 1 if there are two in
|
|
// the queue (because this one has already been marked as read).
|
|
//
|
|
// only want to remove everything waiting if this movie
|
|
// was actually played.
|
|
if (bLocalMoviePlayed == true && !zoomed() && residuePrintedResultsWaiting() >= 1) {
|
|
|
|
// Remove all these from the message waiting queue.
|
|
removeAllFromMsgQueue(this);
|
|
|
|
activateResiduePrintedReview();
|
|
} else {
|
|
activateRPObject();
|
|
}
|
|
|
|
return bMoviePlayed;
|
|
}
|
|
|
|
// This routine just displays results for a single object. We still need to
|
|
// implement cascading RP results.
|
|
#define REVIEWDOSZ "REVIEWDOSZ"
|
|
#define REVIEWDOS "REVIEWDOS"
|
|
|
|
ErrorCode CBagRPObject::update(CBofBitmap *pBmp, CBofPoint /*pt*/, CBofRect * /*pSrcRect*/, int) {
|
|
if (getLogState() == RP_RESULTS) {
|
|
if (_pDescObj) {
|
|
CBofRect txRect = _pDescObj->getRect();
|
|
CBofPoint txPt = txRect.topLeft();
|
|
_pDescObj->update(pBmp, txPt, &txRect, 0);
|
|
}
|
|
}
|
|
|
|
return ERR_NONE;
|
|
}
|
|
|
|
bool CBagRPObject::activateRPObject() {
|
|
// If there's one already activated, then deactivate it. Don't want
|
|
// two of these drawn on top of each other.
|
|
if (_pCurRPObject && _pCurRPObject != this) {
|
|
_pCurRPObject->deactivateRPObject();
|
|
_pCurRPObject->_bCurVisible = false;
|
|
_pCurRPObject->saveResiduePrintedVars();
|
|
}
|
|
|
|
// Set current and make sure our variable knows that this one is being shown,
|
|
// this is important for snapping from zoom to regular and vice-versa.
|
|
_pCurRPObject = this;
|
|
_bCurVisible = true;
|
|
saveResiduePrintedVars();
|
|
|
|
// Make sure this guy is active and ready to get drawn.
|
|
setVisible(); // show this guy
|
|
setActive(); // accept mouse downs
|
|
|
|
CBagLog *pLogWld;
|
|
if (zoomed()) {
|
|
pLogWld = (CBagLog *)g_SDevManager->getStorageDevice(LOGZ_WLD);
|
|
} else {
|
|
pLogWld = (CBagLog *)g_SDevManager->getStorageDevice(LOG_WLD);
|
|
}
|
|
|
|
if (pLogWld == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
// If we're coming from residue print review, make sure none of those objects
|
|
// are visible.
|
|
if (getLogState() == RP_REVIEW) {
|
|
hideResiduePrintedReview();
|
|
}
|
|
|
|
// We're ready to display a RP result, so switch to results mode
|
|
if (getLogState() != RP_RESULTS) {
|
|
setLogState(RP_RESULTS);
|
|
}
|
|
setLogPages(1);
|
|
|
|
// Now go through each one and make sure we have the backp
|
|
CBofList<DossierObj *> *pDosList = (_bTouched ? _pTouchedList : _pUntouchedList);
|
|
int nCount = pDosList->getCount();
|
|
|
|
for (int i = 0; i < nCount; i++) {
|
|
DossierObj *pDosObj = pDosList->getNodeItem(i);
|
|
|
|
// By default, include the dossier in the list
|
|
if (pDosObj->_bDisplayDossier) {
|
|
pDosObj->_pDossier->activateDossierObject(pLogWld);
|
|
}
|
|
|
|
// Give it a back pointer so that it can find the parent res print object
|
|
//
|
|
// We must do this here as this will point to the object that just got
|
|
// residue printed.
|
|
pDosObj->_pDossier->setResiduePrintedObject(this);
|
|
}
|
|
|
|
showPdaLog();
|
|
|
|
// Attach the description object.
|
|
assert(_pDescObj != nullptr);
|
|
|
|
// This object might not be attached since it is not a local object in the
|
|
// log storage device
|
|
if (!_pDescObj->isAttached()) {
|
|
_pDescObj->attach();
|
|
}
|
|
_pDescObj->setVisible(); // Show this guy
|
|
|
|
return true;
|
|
}
|
|
|
|
void CBagRPObject::deactivateRPObject() {
|
|
CBagLog *pLogWld;
|
|
|
|
// Get the appropriate storage device
|
|
if (zoomed()) {
|
|
pLogWld = (CBagLog *)g_SDevManager->getStorageDevice(LOGZ_WLD);
|
|
} else {
|
|
pLogWld = (CBagLog *)g_SDevManager->getStorageDevice(LOG_WLD);
|
|
}
|
|
|
|
// Can't bloody well do much without our storage device
|
|
if (pLogWld == nullptr) {
|
|
return;
|
|
}
|
|
|
|
// Make sure that all our objects that we care about are no longer active
|
|
int nCount = _pTouchedList->getCount();
|
|
DossierObj *pDosLObj;
|
|
|
|
for (int i = 0; i < nCount; i++) {
|
|
pDosLObj = _pTouchedList->getNodeItem(i);
|
|
pDosLObj->_pDossier->deactivateDossierObject(pLogWld);
|
|
}
|
|
|
|
if (_pTouchedList != _pUntouchedList) {
|
|
nCount = _pUntouchedList->getCount();
|
|
|
|
for (int i = 0; i < nCount; i++) {
|
|
pDosLObj = _pUntouchedList->getNodeItem(i);
|
|
pDosLObj->_pDossier->deactivateDossierObject(pLogWld);
|
|
}
|
|
}
|
|
|
|
// Attach the description object.
|
|
assert(_pDescObj != nullptr);
|
|
|
|
if (_pDescObj) {
|
|
_pDescObj->setVisible(false); // Hide this guy
|
|
_pDescObj->setActive(false); // Don't take mousedowns
|
|
_pDescObj->setFloating(false); // Don't calculate floating rects
|
|
}
|
|
setVisible(false); // Hide this guy
|
|
|
|
return;
|
|
}
|
|
|
|
// This static will cruise the entire rpo object list, mark each one that has
|
|
// had a result returned as active and floater. also, update the mode var
|
|
void CBagRPObject::activateResiduePrintedReview() {
|
|
// Make sure the log is frontmost
|
|
if (getLogState() != RP_REVIEW) {
|
|
showPdaLog();
|
|
|
|
// Now in review mode, this is used in our update code to determine what to
|
|
// show.
|
|
setLogState(RP_REVIEW);
|
|
}
|
|
|
|
setLogPages(99);
|
|
showResiduePrintedReview();
|
|
}
|
|
|
|
void CBagRPObject::deactivateResiduePrintedReview() {
|
|
CBagLog *pLogWld;
|
|
|
|
// Get the appropriate storage device
|
|
if (zoomed()) {
|
|
pLogWld = (CBagLog *)g_SDevManager->getStorageDevice(LOGZ_WLD);
|
|
} else {
|
|
pLogWld = (CBagLog *)g_SDevManager->getStorageDevice(LOG_WLD);
|
|
}
|
|
|
|
// can't bloody well get anywhere without this info.
|
|
assert(pLogWld != nullptr);
|
|
if (pLogWld == nullptr) {
|
|
return;
|
|
}
|
|
|
|
// Now in review mode, this is used in our update code to determine what to show.
|
|
CBagRPObject *pRPObj = _pRPList->getNodeItem(0);
|
|
if (pRPObj == nullptr) {
|
|
return;
|
|
}
|
|
|
|
// Cruise the whole list, fill in missing vars, set all our text
|
|
// objects to inactive so they don't get drawn.
|
|
int nCount = _pRPList->getCount();
|
|
|
|
for (int i = 0; i < nCount; i++) {
|
|
pRPObj = _pRPList->getNodeItem(i);
|
|
|
|
// We know this object is attached, but it might not be visible.
|
|
if (pRPObj->_pObjectName) {
|
|
pRPObj->_pObjectName->setFloating(false);
|
|
pRPObj->_pObjectName->setVisible(false);
|
|
pRPObj->_pObjectName->setActive(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CBagRPObject::onLButtonUp(uint32 /*nFlags*/, CBofPoint * /*xPoint*/, void * /*pv*/) {
|
|
// Deactivate everything in the rp list
|
|
hideResiduePrintedReview();
|
|
|
|
// We're ready to display a RP result, so switch to results mode
|
|
setLogState(RP_RESULTS);
|
|
setLogPages(1);
|
|
|
|
runObject();
|
|
}
|
|
|
|
void CBagRPObject::evaluateDossiers() {
|
|
|
|
// If we have a touched variable, then evaluate and if it is not 3000, then
|
|
// we know it's been touched.
|
|
if (_pTouchedVar) {
|
|
if (_pTouchedVar->getValue() != "3000") {
|
|
_bTouched = true;
|
|
}
|
|
}
|
|
|
|
// Just cruise through each of our dossier's and decide which ones
|
|
// to include in our list, this is based on the expression objects
|
|
// that are in the script.
|
|
//
|
|
// A note on expression objects in script. Note that all the expressions
|
|
// in the script that have mathematical expressions in them take place
|
|
// on the left of the >/=/< sign. This is because the eval left to
|
|
// right routine used below has been specifically tweaked to handle
|
|
// left to right evaluation.
|
|
CBofList<DossierObj *> *pDosList = (_bTouched ? _pTouchedList : _pUntouchedList);
|
|
assert(pDosList != nullptr);
|
|
|
|
int nCount = pDosList->getCount();
|
|
CBagLog *pLogZWld = nullptr;
|
|
|
|
for (int i = 0; i < nCount; i++) {
|
|
DossierObj *pDosLObj = pDosList->getNodeItem(i);
|
|
|
|
// By default, include the dossier in the list
|
|
pDosLObj->_bDisplayDossier = true;
|
|
if (pDosLObj->_xDosExp != nullptr) {
|
|
pDosLObj->_bDisplayDossier = pDosLObj->_xDosExp->evalLeftToRight(false);
|
|
}
|
|
|
|
// If we are displaying this dossier and the suspect var is
|
|
// there, then lookup the suspect var and let the voice printing code know
|
|
// that this guy's DNA has shown up on some object.
|
|
if (pDosLObj->_bDisplayDossier &&
|
|
pDosLObj->_pDossier &&
|
|
pDosLObj->_pDossier->_sSuspectVar.isEmpty() == false) {
|
|
|
|
if (pLogZWld == nullptr) {
|
|
pLogZWld = (CBagLog *)g_SDevManager->getStorageDevice(LOGZ_WLD);
|
|
}
|
|
|
|
if (pLogZWld != nullptr) {
|
|
CBagLogSuspect *pSusObj = (CBagLogSuspect *)pLogZWld->getObject(pDosLObj->_pDossier->_sSuspectVar);
|
|
|
|
if (pSusObj != nullptr) {
|
|
pSusObj->setSusResiduePrinted(true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
saveResiduePrintedVars(); // Update the variable store
|
|
}
|
|
|
|
// This is really ugly, so put it all in the same place
|
|
void CBagRPObject::setLogState(RPStates eLogMode) {
|
|
// This is very, very, very hacky, but make sure that our script has
|
|
// no power over what is going on, so set our log state to "CODE_RP_RESULTS".
|
|
// Also, so we know where to return to, make sure we set the previous log
|
|
// state to whatever LOG_STATE is right now.
|
|
if (_pLogStateVar == nullptr) {
|
|
_pLogStateVar = g_VarManager->getVariable("LOG_STATE");
|
|
}
|
|
|
|
if (_pPrevLogStateVar == nullptr) {
|
|
_pPrevLogStateVar = g_VarManager->getVariable("PREV_LOG_STATE");
|
|
}
|
|
|
|
assert(_pLogStateVar != nullptr && _pPrevLogStateVar != nullptr);
|
|
|
|
if (_pLogStateVar != nullptr && _pPrevLogStateVar != nullptr) {
|
|
char szLocalBuff[256];
|
|
CBofString cStr(szLocalBuff, 256);
|
|
bool bRemember = false;
|
|
bool bSavePage = false;
|
|
bool bRestorePage = false;
|
|
|
|
switch (eLogMode) {
|
|
case RP_RESULTS:
|
|
cStr = "CODE_RP_RESULTS";
|
|
bSavePage = true;
|
|
bRemember = true;
|
|
break;
|
|
|
|
case RP_READ_DOSSIER:
|
|
cStr = "CODE_RP_DOSSIER";
|
|
break;
|
|
|
|
case RP_REVIEW:
|
|
bRemember = true;
|
|
bRestorePage = true;
|
|
cStr = "RES_PRINT_REVIEW";
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (_eRPMode != RP_READ_DOSSIER) {
|
|
if (bRemember) {
|
|
_pPrevLogStateVar->setValue(_pLogStateVar->getValue());
|
|
}
|
|
}
|
|
_pLogStateVar->setValue(cStr);
|
|
|
|
if (bSavePage || bRestorePage) {
|
|
if (_pPrevBarPage == nullptr) {
|
|
_pPrevBarPage = g_VarManager->getVariable("PREV_BAR_LOG_PAGE");
|
|
}
|
|
|
|
if (_pCurBarPage == nullptr) {
|
|
_pCurBarPage = g_VarManager->getVariable("CUR_BAR_LOG_PAGE");
|
|
}
|
|
|
|
if (_pPrevBarPage && _pCurBarPage) {
|
|
if (bSavePage) {
|
|
_pPrevBarPage->setValue(_pCurBarPage->getValue());
|
|
}
|
|
|
|
if (bRestorePage) {
|
|
_pCurBarPage->setValue(_pPrevBarPage->getValue());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
_eRPMode = eLogMode;
|
|
}
|
|
|
|
// Return the current log state
|
|
RPStates CBagRPObject::getLogState() {
|
|
if (_pLogStateVar == nullptr) {
|
|
_pLogStateVar = g_VarManager->getVariable("LOG_STATE");
|
|
}
|
|
|
|
_eRPMode = RP_NO_MODE;
|
|
|
|
assert(_pLogStateVar != nullptr);
|
|
if (_pLogStateVar) {
|
|
char szLocalBuff[256];
|
|
CBofString cStr(szLocalBuff, 256);
|
|
|
|
cStr = _pLogStateVar->getValue();
|
|
if (cStr == "CODE_RP_RESULTS") {
|
|
_eRPMode = RP_RESULTS;
|
|
} else if (cStr == "CODE_RP_DOSSIER") {
|
|
_eRPMode = RP_READ_DOSSIER;
|
|
} else if (cStr == "RES_PRINT_REVIEW") {
|
|
_eRPMode = RP_REVIEW;
|
|
} else if (cStr == "MAINMENU") {
|
|
_eRPMode = RP_MAIN_MENU;
|
|
}
|
|
}
|
|
|
|
return _eRPMode;
|
|
}
|
|
|
|
// Set the current number of pages in both script and code.
|
|
void CBagRPObject::setLogPages(int nPages) {
|
|
if (_pBarLogPages == nullptr) {
|
|
_pBarLogPages = g_VarManager->getVariable("CODE_TOTAL_LOG_PAGES");
|
|
}
|
|
|
|
assert(_pBarLogPages != nullptr);
|
|
|
|
if (_pBarLogPages) {
|
|
_pBarLogPages->setValue(nPages);
|
|
}
|
|
|
|
// Let the float code know how many pages we have.
|
|
CBagLog *pLogWld;
|
|
if (zoomed()) {
|
|
pLogWld = (CBagLog *)g_SDevManager->getStorageDevice(LOGZ_WLD);
|
|
} else {
|
|
pLogWld = (CBagLog *)g_SDevManager->getStorageDevice(LOG_WLD);
|
|
}
|
|
|
|
assert(pLogWld != nullptr);
|
|
if (pLogWld) {
|
|
// Let the float code know how many pages we have.
|
|
pLogWld->setNumFloatPages(nPages);
|
|
if (nPages == 1) {
|
|
pLogWld->setCurFltPage(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Save the residue print variables
|
|
|
|
void CBagRPObject::saveResiduePrintedVars() {
|
|
if (_pSaveVar == nullptr) {
|
|
return;
|
|
}
|
|
|
|
uint32 nVars = 0;
|
|
|
|
for (int i = 0; i < NUM_RP_FIELDS; i++) {
|
|
switch (i) {
|
|
case 0:
|
|
nVars = _nRPTime & mRPTime;
|
|
break;
|
|
case 1:
|
|
nVars |= (_bRPReported ? mRPReported : 0);
|
|
break;
|
|
case 2:
|
|
nVars |= (_bResPrinted ? mResPrinted : 0);
|
|
break;
|
|
case 3:
|
|
nVars |= (_bTouched ? mTouched : 0);
|
|
break;
|
|
case 4:
|
|
nVars |= (_bRPRead ? mRPRead : 0);
|
|
break;
|
|
case 5:
|
|
nVars |= (_bCurVisible ? mRPCurVisible : 0);
|
|
break;
|
|
case 6:
|
|
nVars |= ((_nCurDossier & 0x3) << mRPCurDossierShift);
|
|
break;
|
|
case 7:
|
|
nVars |= (_bMoviePlayed ? mRPMoviePlayed : 0);
|
|
break;
|
|
case 8:
|
|
nVars |= (_bRPTimeSet ? mRPTimeSet : 0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
DossierObj *pDosObj;
|
|
|
|
if (_pTouchedList) {
|
|
// Now handle touched dossier's
|
|
int nCount = _pTouchedList->getCount();
|
|
assert(nCount <= 3);
|
|
|
|
for (int i = 0; i < nCount; i++) {
|
|
pDosObj = _pTouchedList->getNodeItem(i);
|
|
switch (i) {
|
|
case 0:
|
|
nVars |= (pDosObj->_bDisplayDossier ? mRPTDos1Eval : 0);
|
|
break;
|
|
case 1:
|
|
nVars |= (pDosObj->_bDisplayDossier ? mRPTDos2Eval : 0);
|
|
break;
|
|
case 2:
|
|
nVars |= (pDosObj->_bDisplayDossier ? mRPTDos3Eval : 0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_pUntouchedList) {
|
|
// Now handle untouched dossier's
|
|
int nCount = _pUntouchedList->getCount();
|
|
assert(nCount <= 3);
|
|
|
|
for (int i = 0; i < nCount; i++) {
|
|
pDosObj = _pUntouchedList->getNodeItem(i);
|
|
switch (i) {
|
|
case 0:
|
|
nVars |= (pDosObj->_bDisplayDossier ? mRPUDos1Eval : 0);
|
|
break;
|
|
case 1:
|
|
nVars |= (pDosObj->_bDisplayDossier ? mRPUDos2Eval : 0);
|
|
break;
|
|
case 2:
|
|
nVars |= (pDosObj->_bDisplayDossier ? mRPUDos3Eval : 0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
_pSaveVar->setValue(nVars);
|
|
}
|
|
|
|
// Restore the residue print variable from memory
|
|
void CBagRPObject::restoreResiduePrintedVars() {
|
|
if (_pSaveVar == nullptr) {
|
|
return;
|
|
}
|
|
|
|
uint32 nVars = _pSaveVar->getNumValue();
|
|
|
|
for (int i = 0; i < NUM_RP_FIELDS; i++) {
|
|
switch (i) {
|
|
case 0:
|
|
_nRPTime = nVars & mRPTime;
|
|
break;
|
|
case 1:
|
|
_bRPReported = (nVars & mRPReported ? true : false);
|
|
break;
|
|
case 2:
|
|
_bResPrinted = (nVars & mResPrinted ? true : false);
|
|
break;
|
|
case 3:
|
|
_bTouched = (nVars & mTouched ? true : false);
|
|
break;
|
|
case 4:
|
|
_bRPRead = (nVars & mRPRead ? true : false);
|
|
break;
|
|
case 5:
|
|
_bCurVisible = (nVars & mRPCurVisible ? true : false);
|
|
break;
|
|
case 6:
|
|
(_nCurDossier = (nVars & mRPCurDossier) >> mRPCurDossierShift);
|
|
break;
|
|
case 7:
|
|
_bMoviePlayed = (nVars & mRPMoviePlayed ? true : false);
|
|
break;
|
|
case 8:
|
|
_bRPTimeSet = (nVars & mRPTimeSet ? true : false);
|
|
break;
|
|
}
|
|
}
|
|
|
|
DossierObj *pDosObj;
|
|
|
|
if (_pTouchedList) {
|
|
// Now handle touched dossier's
|
|
int nCount = _pTouchedList->getCount();
|
|
assert(nCount <= 3);
|
|
|
|
for (int i = 0; i < nCount; i++) {
|
|
pDosObj = _pTouchedList->getNodeItem(i);
|
|
switch (i) {
|
|
case 0:
|
|
pDosObj->_bDisplayDossier = (nVars & mRPTDos1Eval ? true : false);
|
|
break;
|
|
case 1:
|
|
pDosObj->_bDisplayDossier = (nVars & mRPTDos2Eval ? true : false);
|
|
break;
|
|
case 2:
|
|
pDosObj->_bDisplayDossier = (nVars & mRPTDos3Eval ? true : false);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_pUntouchedList) {
|
|
// Now handle untouched dossier's
|
|
int nCount = _pUntouchedList->getCount();
|
|
assert(nCount <= 3);
|
|
|
|
for (int i = 0; i < nCount; i++) {
|
|
pDosObj = _pUntouchedList->getNodeItem(i);
|
|
switch (i) {
|
|
case 0:
|
|
pDosObj->_bDisplayDossier = (nVars & mRPUDos1Eval ? true : false);
|
|
break;
|
|
case 1:
|
|
pDosObj->_bDisplayDossier = (nVars & mRPUDos2Eval ? true : false);
|
|
break;
|
|
case 2:
|
|
pDosObj->_bDisplayDossier = (nVars & mRPUDos3Eval ? true : false);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Hide the list of rp results, don't purge them from memory, just set to not visible.
|
|
void CBagRPObject::hideResiduePrintedReview() {
|
|
CBagLog *pLogWld;
|
|
|
|
if (zoomed()) {
|
|
pLogWld = (CBagLog *)g_SDevManager->getStorageDevice(LOGZ_WLD);
|
|
} else {
|
|
pLogWld = (CBagLog *)g_SDevManager->getStorageDevice(LOG_WLD);
|
|
}
|
|
|
|
CBagRPObject *pRPObj = _pRPList->getNodeItem(0);
|
|
if (pRPObj == nullptr) {
|
|
return;
|
|
}
|
|
|
|
// Count items in this queue.
|
|
int nCount = _pRPList->getCount();
|
|
|
|
for (int i = 0; i < nCount; i++) {
|
|
pRPObj = _pRPList->getNodeItem(i);
|
|
|
|
if (!pRPObj)
|
|
error("hideResiduePrintedReview() - Unexpected null pRPObj");
|
|
|
|
// If the object txt var is not found yet, then get it.
|
|
if (pRPObj->_pObjectName == nullptr) {
|
|
if (!pLogWld)
|
|
error("hideResiduePrintedReview() - Unexpected null pLogWld");
|
|
|
|
pRPObj->_pObjectName = (CBagTextObject *)pLogWld->getObject(pRPObj->_sObjectName);
|
|
}
|
|
|
|
// We know this object is attached, but it might not be visible.
|
|
if (pRPObj->_pObjectName) {
|
|
pRPObj->_pObjectName->setVisible(false); // hide this guy
|
|
pRPObj->_pObjectName->setFloating(false); // don't arrange floating pages
|
|
pRPObj->_pObjectName->setActive(false); // don't accept mouse downs
|
|
}
|
|
}
|
|
}
|
|
|
|
void CBagRPObject::showResiduePrintedReview() {
|
|
CBagLog *pLogWld;
|
|
|
|
if (zoomed()) {
|
|
pLogWld = (CBagLog *)g_SDevManager->getStorageDevice(LOGZ_WLD);
|
|
} else {
|
|
pLogWld = (CBagLog *)g_SDevManager->getStorageDevice(LOG_WLD);
|
|
}
|
|
|
|
if (!pLogWld) {
|
|
warning("showResiduePrintedReview() - Unexpected null logWld");
|
|
return;
|
|
}
|
|
|
|
// Count items in this queue.
|
|
int nCount = pLogWld->getObjectCount();
|
|
|
|
// Check the first guy in the queue to see if he's been initialized, if not,
|
|
// then cruise the whole thing.
|
|
for (int i = 0; i < nCount; i++) {
|
|
CBagObject *pObj = pLogWld->getObjectByPos(i);
|
|
if (pObj && pObj->getType() == RESPRNT_OBJ) {
|
|
|
|
CBagRPObject *pRPObj = (CBagRPObject *)pObj;
|
|
// Find out if there are any events worth reporting.
|
|
if (pRPObj->_bResPrinted && pRPObj->_bRPRead) {
|
|
|
|
// We know this object is attached, but it might not be visible.
|
|
if (pRPObj->_pObjectName) {
|
|
|
|
bool bIsAttached = pRPObj->_pObjectName->isAttached();
|
|
if (bIsAttached == false) {
|
|
pLogWld->activateLocalObject(pRPObj->_pObjectName);
|
|
}
|
|
pRPObj->_pObjectName->setVisible();
|
|
pRPObj->_pObjectName->setFloating();
|
|
pRPObj->_pObjectName->setActive();
|
|
|
|
// If the time on this object has not yet been set, then force it to
|
|
// be re-read into memory and append the current time to it.
|
|
if (pRPObj->_bRPTimeSet == false) {
|
|
CBofString s = pRPObj->_pObjectName->getText();
|
|
|
|
int nHr = pRPObj->_nRPTime / 100;
|
|
int nMn = pRPObj->_nRPTime - (nHr * 100);
|
|
|
|
s += buildString("%02d:%02d", nHr, nMn);
|
|
|
|
pRPObj->_pObjectName->setText(s);
|
|
pRPObj->_bRPTimeSet = true;
|
|
pRPObj->saveResiduePrintedVars();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Count the number of residue print objects waiting to be reported;
|
|
int CBagRPObject::residuePrintedResultsWaiting() {
|
|
int nCount = _pRPList->getCount();
|
|
int nWaiting = 0;
|
|
|
|
for (int i = 0; i < nCount; i++) {
|
|
CBagRPObject *pRPObj = _pRPList->getNodeItem(i);
|
|
if (pRPObj->_bRPReported && pRPObj->_bRPRead == false) {
|
|
nWaiting++;
|
|
}
|
|
}
|
|
|
|
return nWaiting;
|
|
}
|
|
|
|
// Remove all residue print results from the message queue
|
|
void CBagRPObject::removeAllFromMsgQueue(CBagRPObject *pCurRPObj) {
|
|
// we really only care about the log world, not the logz.
|
|
CBagLog *pLogWld = (CBagLog *)g_SDevManager->getStorageDevice(LOG_WLD);
|
|
assert(pLogWld != nullptr);
|
|
int nCount = _pRPList->getCount();
|
|
|
|
for (int i = 0; i < nCount; i++) {
|
|
CBagRPObject *pRPObj = _pRPList->getNodeItem(i);
|
|
|
|
if (pRPObj->_bRPReported && pRPObj->_bRPRead == false && pRPObj != pCurRPObj) {
|
|
pLogWld->removeFromMsgQueue(pRPObj);
|
|
|
|
pRPObj->_bRPRead = true;
|
|
pRPObj->_bMoviePlayed = true; // Don't want this guys movie again
|
|
pRPObj->saveResiduePrintedVars(); // Update the variable store
|
|
}
|
|
}
|
|
}
|
|
|
|
// We're going to need to switch the PDA to log mode.
|
|
void CBagRPObject::showPdaLog() {
|
|
if (zoomed()) {
|
|
SBZoomPda *pZoomPDA = (SBZoomPda *)g_SDevManager->getStorageDevice(PDAZ_WLD);
|
|
if (pZoomPDA) {
|
|
pZoomPDA->showLog();
|
|
}
|
|
} else {
|
|
CBagPDA *pPDA = (CBagPDA *)g_SDevManager->getStorageDevice(PDA_WLD);
|
|
if (pPDA) {
|
|
pPDA->showLog();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CBagRPObject::zoomed() {
|
|
SBZoomPda *pPDA = (SBZoomPda *)g_SDevManager->getStorageDevice(PDAZ_WLD);
|
|
if (pPDA == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
return pPDA->getZoomed();
|
|
}
|
|
|
|
bool CBagRPObject::initialize() {
|
|
// Cruise the dossier's for both lists and get pointers to the actual bagdoobj's.
|
|
// Search the current storage device for this object.
|
|
CBagStorageDev *pSDev;
|
|
|
|
if (zoomed()) {
|
|
pSDev = g_SDevManager->getStorageDevice(LOGZ_WLD);
|
|
} else {
|
|
pSDev = g_SDevManager->getStorageDevice(LOG_WLD);
|
|
}
|
|
assert(pSDev != nullptr);
|
|
|
|
// Scoff the dossier out of the LOG_WLD SDEV. If it's not there then hurl.
|
|
bool bDoUntouched = (_pTouchedList != _pUntouchedList);
|
|
int nCount = _pTouchedList->getCount();
|
|
|
|
for (int i = 0; i < nCount; i++) {
|
|
DossierObj *pDosObj = _pTouchedList->getNodeItem(i);
|
|
pDosObj->_pDossier = (CBagDossierObject *)pSDev->getObject(pDosObj->_sDossier);
|
|
if (pDosObj->_pDossier == nullptr) {
|
|
return false;
|
|
}
|
|
// Give it a back pointer so that it can find the parent res print object
|
|
//
|
|
// We must do this here as this will point to the object that just got
|
|
// residue printed.
|
|
pDosObj->_pDossier->setResiduePrintedObject(this);
|
|
}
|
|
|
|
if (bDoUntouched) {
|
|
nCount = _pUntouchedList->getCount();
|
|
for (int i = 0; i < nCount; i++) {
|
|
DossierObj *pDosObj = _pUntouchedList->getNodeItem(i);
|
|
pDosObj->_pDossier = (CBagDossierObject *)pSDev->getObject(pDosObj->_sDossier);
|
|
if (pDosObj->_pDossier == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
// Give it a back pointer so that it can find the parent res print object
|
|
//
|
|
// We must do this here as this will point to the object that just got
|
|
// residue printed.
|
|
pDosObj->_pDossier->setResiduePrintedObject(this);
|
|
}
|
|
}
|
|
|
|
// Fill in the movie object if we have one.
|
|
if (!_sMovieObj.isEmpty()) {
|
|
_pMovieObj = (CBagMovieObject *)pSDev->getObject(_sMovieObj);
|
|
if (_pMovieObj == nullptr) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Fill in the object name if we have one.
|
|
if (_pObjectName == nullptr) {
|
|
_pObjectName = (CBagTextObject *)pSDev->getObject(_sObjectName);
|
|
if (_pObjectName == nullptr) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Make sure the object is not active. Object name is the
|
|
// line that shows up in the RP Review screen (such as "Voice Printer")
|
|
|
|
// Give the dossier a back pointer so that it can respond to
|
|
// mouse down events
|
|
_pObjectName->setRPObject(this);
|
|
|
|
_pObjectName->setVisible(false);
|
|
_pObjectName->setActive(false);
|
|
_pObjectName->setFloating(false);
|
|
|
|
return true;
|
|
}
|
|
|
|
// This hack is used to make sure that any variable values that were altered by
|
|
// the zoom pda are propagated down to the regular PDA.
|
|
void CBagRPObject::synchronizeResiduePrintedObjects(bool bLogFrontmost) {
|
|
// only synchronize in the bar
|
|
CBagVar *pVar = g_VarManager->getVariable("INBAR");
|
|
if (pVar == nullptr) {
|
|
return;
|
|
}
|
|
|
|
CBagLog *pLogWld = (CBagLog *)g_SDevManager->getStorageDevice(LOG_WLD);
|
|
if (pLogWld == nullptr) {
|
|
return;
|
|
}
|
|
|
|
RPStates rpState = getLogState();
|
|
int nCount = pLogWld->getObjectCount();
|
|
|
|
// Check the first guy in the queue to see if he's been initialized, if not,
|
|
// then cruise the whole thing.
|
|
for (int i = 0; i < nCount; i++) {
|
|
CBagObject *pObj = pLogWld->getObjectByPos(i);
|
|
if (pObj->getType() == RESPRNT_OBJ) {
|
|
CBagRPObject *pRPObj = (CBagRPObject *)pObj;
|
|
pRPObj->restoreResiduePrintedVars();
|
|
|
|
if (bLogFrontmost) {
|
|
switch (rpState) {
|
|
case RP_NO_MODE:
|
|
break;
|
|
case RP_RESULTS:
|
|
// If this guy was being shown before, bring it up now.
|
|
if (pRPObj->_bCurVisible) {
|
|
_pActivateThisGuy = pRPObj;
|
|
}
|
|
break;
|
|
case RP_READ_DOSSIER:
|
|
if (pRPObj->_bCurVisible) {
|
|
_pActivateThisGuy = pRPObj;
|
|
}
|
|
break;
|
|
case RP_REVIEW:
|
|
if (pRPObj->_bRPRead) {
|
|
pRPObj->activateResiduePrintedReview();
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Used to fetch the currently active dossier, good for coming out of save/
|
|
// restore, flashbacks and zoom/unzoom.
|
|
CBagDossierObject *CBagRPObject::getActiveDossier() {
|
|
CBofList<DossierObj *> *pDosList = (_bTouched ? _pTouchedList : _pUntouchedList);
|
|
|
|
return pDosList->getNodeItem(_nCurDossier)->_pDossier;
|
|
}
|
|
|
|
// Used to set the currently active dossier when one is displayed to the user.
|
|
void CBagRPObject::setActiveDossier(CBagDossierObject *pDosObj) {
|
|
CBofList<DossierObj *> *pDosList = (_bTouched ? _pTouchedList : _pUntouchedList);
|
|
|
|
int nCount = pDosList->getCount();
|
|
for (int i = 0; i < nCount; i++) {
|
|
DossierObj *p = pDosList->getNodeItem(i);
|
|
if (p->_pDossier == pDosObj) {
|
|
_nCurDossier = i;
|
|
saveResiduePrintedVars();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Initialize all dossier fields
|
|
DossierObj::DossierObj() {
|
|
_pDossier = nullptr;
|
|
_sDossier = "";
|
|
_xDosExp = nullptr;
|
|
_bDisplayDossier = false;
|
|
}
|
|
|
|
// Remove all allocated dossier objects
|
|
DossierObj::~DossierObj() {
|
|
// Don't delete dossier's, we got those from the storage dev manager.
|
|
_pDossier = nullptr;
|
|
|
|
// Expressions, however, we do own
|
|
delete _xDosExp;
|
|
_xDosExp = nullptr;
|
|
}
|
|
|
|
} // namespace Bagel
|