diff options
Diffstat (limited to 'Src/Wasabi/api/script/scriptmgr.cpp')
-rw-r--r-- | Src/Wasabi/api/script/scriptmgr.cpp | 602 |
1 files changed, 602 insertions, 0 deletions
diff --git a/Src/Wasabi/api/script/scriptmgr.cpp b/Src/Wasabi/api/script/scriptmgr.cpp new file mode 100644 index 00000000..2ae3f0ec --- /dev/null +++ b/Src/Wasabi/api/script/scriptmgr.cpp @@ -0,0 +1,602 @@ +#include <precomp.h> +#include <bfc/wasabi_std.h> +#include <api/script/script.h> +#include <api/script/scriptmgr.h> +#include <api/script/objects/systemobj.h> +#include <api/script/vcpu.h> +#include <api/skin/skinparse.h> +#include <api/script/objecttable.h> +#ifdef WASABI_COMPILE_WND +#include <api/wnd/wndtrack.h> +#endif + +#ifdef WASABI_COMPILE_COMPONENTS +PtrList<WACObject> comps; +#endif + +extern GUID baseGUID; + +ScriptObjectManager::ScriptObjectManager() { + ASSERTPR(!inited, "don't create 2 scriptobjectmanager, you dumbass"); + inited=1; +#ifdef WASABI_COMPILE_COMPONENTS + for (int i=0;i<api->getNumComponents();i++) { + GUID g = api->getComponentGUID(i); + WACObject *c = new WACObject(); + c->setGUID(g); + comps.addItem(c); + } + WACObject *m = new WACObject(); + m->setGUID(baseGUID); + comps.addItem(m); +#endif +} + +ScriptObjectManager::~ScriptObjectManager() { + inited=0; +#ifdef WASABI_COMPILE_COMPONENTS + comps.deleteAll(); +#endif +} + +// Create a variable of specified type +scriptVar ScriptObjectManager::makeVar(int type) +{ + scriptVar v; + v.type = type; + v.data.ddata = 0; + return v; +} + +// Create a variable of specified type and assigns an object to it +scriptVar ScriptObjectManager::makeVar(int type, ScriptObject *o) +{ + scriptVar v = makeVar(type); + v.data.odata = o; + return v; +} + +// Assigns a char* to a String variable. Frees old value if necessary +void ScriptObjectManager::assign(scriptVar *v, const wchar_t *str) +{ + ASSERT(v != NULL); + ASSERT(v->type == SCRIPT_STRING); // Compiler discarded + if (v->data.sdata) FREE((wchar_t *)v->data.sdata); + if ((int)str > 65536) { + v->data.sdata = WCSDUP(str); + VCPU::addStatementString(const_cast<wchar_t *>(v->data.sdata)); + } else + v->data.sdata = NULL; +} + +// Assigns an int to an int, float or double variable. +void ScriptObjectManager::assign(scriptVar *v, int i) { + ASSERT(v != NULL); + switch (v->type) { + case SCRIPT_FLOAT: + assign(v, (float)i); + return; + case SCRIPT_DOUBLE: + assign(v, (double)i); + return; + case SCRIPT_INT: + case SCRIPT_BOOLEAN: + v->data.idata = i; + return; + case SCRIPT_STRING: + assign(v, StringPrintfW(L"%d", i)); + return; + default: + assign(v, (ScriptObject*)NULL); + return; + } +} + +// Assigns a float to an int, float or double variable. +void ScriptObjectManager::assign(scriptVar *v, float f) { + ASSERT(v != NULL); + switch (v->type) { + case SCRIPT_INT: + case SCRIPT_BOOLEAN: + assign(v, (int)f); + return; + case SCRIPT_DOUBLE: + assign(v, (double)f); + return; + case SCRIPT_FLOAT: + v->data.fdata = f; + return; + case SCRIPT_STRING: + { + wchar_t t[96] = {0}; + WCSNPRINTF(t, 96, L"%f", f); + assign(v, t); + return; + } + default: + assign(v, (ScriptObject*)NULL); + return; + } +} + +// Assigns a double to an int, float or double variable. +void ScriptObjectManager::assign(scriptVar *v, double d) { + ASSERT(v != NULL); + switch (v->type) { + case SCRIPT_INT: + case SCRIPT_BOOLEAN: + assign(v, (int)d); + return; + case SCRIPT_FLOAT: + assign(v, (float)d); + return; + case SCRIPT_DOUBLE: + v->data.ddata = d; + return; + case SCRIPT_STRING: + { + wchar_t t[96] = {0}; + WCSNPRINTF(t, 96, L"%e", d); + assign(v, t); + return; + } + default: + assign(v, (ScriptObject*)NULL); + return; + } +} + +// Assigns a object to an object variable, handles hierarchy. +void ScriptObjectManager::assign(scriptVar *v, ScriptObject *o) { + ASSERT(v != NULL); + // TODO: temporarily assert descendancy + v->data.odata = o; +} + + +// Assigns a numerical scriptVar to another numerical scriptVar +// or an object to another object +// Autocasts +void ScriptObjectManager::assign(scriptVar *v1, scriptVar *v2) { + ASSERT(v1 != NULL); + ASSERT(v2 != NULL); + switch (v1->type) { + case SCRIPT_INT: + assign(v1, SOM::makeInt(v2)); + break; + case SCRIPT_FLOAT: + assign(v1, SOM::makeFloat(v2)); + break; + case SCRIPT_DOUBLE: + assign(v1, SOM::makeDouble(v2)); + break; + case SCRIPT_STRING: + assign(v1, v2->data.sdata); + break; + case SCRIPT_BOOLEAN: + assign(v1, SOM::makeBoolean(v2)); + break; + default: + assign(v1, v2->data.odata); + break; + } +} + +void ScriptObjectManager::assignPersistent(scriptVar *v1, scriptVar *v2) { + ASSERT(v1 != NULL); + ASSERT(v2 != NULL); + switch (v1->type) { + case SCRIPT_INT: + assign(v1, SOM::makeInt(v2)); + break; + case SCRIPT_FLOAT: + assign(v1, SOM::makeFloat(v2)); + break; + case SCRIPT_DOUBLE: + assign(v1, SOM::makeDouble(v2)); + break; + case SCRIPT_STRING: + persistentstrassign(v1, v2->data.sdata); + break; + case SCRIPT_BOOLEAN: + assign(v1, SOM::makeBoolean(v2)); + break; + default: + assign(v1, v2->data.odata); + break; + } +} + +void ScriptObjectManager::strflatassign(scriptVar *v, const wchar_t *str) +{ + ASSERT(v != NULL); + ASSERT(v->type == SCRIPT_STRING); // Compiler discarded + if (v->data.sdata) FREE((wchar_t *)v->data.sdata); + if ((int)str > 65536) + v->data.sdata = (wchar_t *)str; + else + v->data.sdata = NULL; +} + +void ScriptObjectManager::persistentstrassign(scriptVar *v, const wchar_t *str) { + ASSERT(v != NULL); + ASSERT(v->type == SCRIPT_STRING); // Compiler discarded + if (v->data.sdata) FREE((wchar_t *)v->data.sdata); + if ((int)str > 65536) + v->data.sdata = WCSDUP(str); + else + v->data.sdata = NULL; +} + +// comparision functions +int ScriptObjectManager::compEq(scriptVar *v1, scriptVar *v2) { + int r; + switch (v1->type) { + case SCRIPT_INT: + r = v1->data.idata == makeInt(v2); + break; + case SCRIPT_FLOAT: + r = v1->data.fdata == makeFloat(v2); + break; + case SCRIPT_DOUBLE: + r = v1->data.ddata == makeDouble(v2); + break; + case SCRIPT_BOOLEAN: + r = ((v1->data.idata == 0) ? 0 : 1) == ((makeBoolean(v2) == 0) ? 0 : 1); + break; + case SCRIPT_STRING: + if (v1->data.sdata && v2->data.sdata) + { + r = !wcscmp(v1->data.sdata, v2->data.sdata); + break; + } + // pass through + default: // any object, reference has to match + r = v1->data.odata == v2->data.odata; + break; + } + return r; +} + +int ScriptObjectManager::compNeq(scriptVar *v1, scriptVar *v2) { + int r; + switch (v1->type) { + case SCRIPT_INT: + r = v1->data.idata != makeInt(v2); + break; + case SCRIPT_FLOAT: + r = v1->data.fdata != makeFloat(v2); + break; + case SCRIPT_DOUBLE: + r = v1->data.ddata != makeDouble(v2); + break; + case SCRIPT_BOOLEAN: + r = ((v1->data.idata == 0) ? 0 : 1) != ((makeBoolean(v2) == 0) ? 0 : 1); + break; + case SCRIPT_STRING: + if (v1->data.sdata && v2->data.sdata) + r = (wcscmp(v1->data.sdata, v2->data.sdata) != 0) ? 1 : 0; + else + r = 0; + break; + default: + r = v1->data.odata != v2->data.odata; + break; + } + return r; +} + +int ScriptObjectManager::compA(scriptVar *v1, scriptVar *v2) { + int r; + switch (v1->type) { + case SCRIPT_BOOLEAN: + r = ((v1->data.idata == 0) ? 0 : 1) > ((makeBoolean(v2) == 0) ? 0 : 1); + break; + case SCRIPT_INT: + r = v1->data.idata > makeInt(v2); + break; + case SCRIPT_FLOAT: + r = v1->data.fdata > makeFloat(v2); + break; + case SCRIPT_DOUBLE: + r = v1->data.ddata > makeDouble(v2); + break; + case SCRIPT_STRING: + r = (wcscmp(v1->data.sdata, v2->data.sdata) > 0) ? 1 : 0; + break; + default: + r = 0; + break; + } + return r; +} + +int ScriptObjectManager::compAe(scriptVar *v1, scriptVar *v2) { + int r; + switch (v1->type) { + case SCRIPT_BOOLEAN: + r = ((v1->data.idata == 0) ? 0 : 1) >= ((makeBoolean(v2) == 0) ? 0 : 1); + break; + case SCRIPT_INT: + r = v1->data.idata >= makeInt(v2); + break; + case SCRIPT_FLOAT: + r = v1->data.fdata >= makeFloat(v2); + break; + case SCRIPT_DOUBLE: + r = v1->data.ddata >= makeDouble(v2); + break; + case SCRIPT_STRING: + r = (wcscmp(v1->data.sdata, v2->data.sdata) >= 0) ? 1 : 0; + break; + default: + r = 0; + break; + } + return r; +} + +int ScriptObjectManager::compB(scriptVar *v1, scriptVar *v2) { + int r; + switch (v1->type) { + case SCRIPT_BOOLEAN: + r = ((v1->data.idata == 0) ? 0 : 1) < ((makeBoolean(v2) == 0) ? 0 : 1); + break; + case SCRIPT_INT: + r = v1->data.idata < makeInt(v2); + break; + case SCRIPT_FLOAT: + r = v1->data.fdata < makeFloat(v2); + break; + case SCRIPT_DOUBLE: + r = v1->data.ddata < makeDouble(v2); + break; + case SCRIPT_STRING: + r = (wcscmp(v1->data.sdata, v2->data.sdata) < 0) ? 1 : 0; + break; + default: + r = 0; + break; + } + return r; +} + +int ScriptObjectManager::compBe(scriptVar *v1, scriptVar *v2) { + int r; + switch (v1->type) { + case SCRIPT_BOOLEAN: + r = ((v1->data.idata == 0) ? 0 : 1) <= ((makeBoolean(v2) == 0) ? 0 : 1); + break; + case SCRIPT_INT: + r = v1->data.idata <= makeInt(v2); + break; + case SCRIPT_FLOAT: + r = v1->data.fdata <= makeFloat(v2); + break; + case SCRIPT_DOUBLE: + r = v1->data.ddata <= makeDouble(v2); + break; + case SCRIPT_STRING: + r = (wcscmp(v1->data.sdata, v2->data.sdata) <= 0) ? 1 : 0; + break; + default: + r = 0; + break; + } + return r; +} + +void ScriptObjectManager::mid(wchar_t *dest, const wchar_t *str, int s, int l) { + if (str == NULL) return; + int rl = wcslen(str); + if (l == 0) return; + if (s >= rl) return; + if (s+l > rl || l == -1) l = rl-s; + WCSCPYN(dest, str+s, l+1); +} + +int ScriptObjectManager::makeInt(scriptVar *v) { + switch (v->type) { + case SCRIPT_INT: + return v->data.idata; + case SCRIPT_FLOAT: + return (int)v->data.fdata; + case SCRIPT_DOUBLE: + return (int)v->data.ddata; + case SCRIPT_BOOLEAN: + return (v->data.idata == 0) ? 0 : 1; + case SCRIPT_STRING: + return WTOI(v->data.sdata); + default: + return 0; + } +} + +float ScriptObjectManager::makeFloat(scriptVar *v) { + switch (v->type) { + case SCRIPT_INT: + return (float)v->data.idata; + case SCRIPT_FLOAT: + return v->data.fdata; + case SCRIPT_DOUBLE: + return (float)v->data.ddata; + case SCRIPT_BOOLEAN: + return (float)((v->data.idata == 0) ? 0 : 1); + case SCRIPT_STRING: + return (float)WTOF(v->data.sdata); + default: + return 0.0f; + } +} + +double ScriptObjectManager::makeDouble(scriptVar *v) { + switch (v->type) { + case SCRIPT_VOID: + return 0; + case SCRIPT_INT: + return (double)v->data.idata; + case SCRIPT_FLOAT: + return (double)v->data.fdata; + case SCRIPT_DOUBLE: + return v->data.ddata; + case SCRIPT_BOOLEAN: + return (double)((v->data.idata == 0) ? 0 : 1); + case SCRIPT_STRING: + return WTOF(v->data.sdata); + default: + return 0.0; + } +} + +bool ScriptObjectManager::makeBoolean(scriptVar *v) { + switch (v->type) { + case SCRIPT_INT: + case SCRIPT_BOOLEAN: + return (v->data.idata == 0) ? 0 : 1; + case SCRIPT_FLOAT: + return (v->data.fdata == 0) ? 0 : 1; + case SCRIPT_DOUBLE: + return (v->data.ddata == 0) ? 0 : 1; + case SCRIPT_STRING: { + StringW s = v->data.sdata; + if (s.iscaseequal(L"false") || s.iscaseequal(L"f")) + return 0; + if (s.iscaseequal(L"true") || s.iscaseequal(L"t")) + return 1; + return (WTOI(s.getValue()) != 0); + } + default: + return (v->data.odata != NULL) ? 1 : 0; + } +} + +int ScriptObjectManager::isNumeric(scriptVar *s) { + return isNumericType(s->type); +} + +int ScriptObjectManager::isString(scriptVar *s) { + return (s->type == SCRIPT_STRING); +} + +int ScriptObjectManager::isVoid(scriptVar *s) { + return (s->type == SCRIPT_VOID); +} + +int ScriptObjectManager::isObject(scriptVar *s) { + return (s->type == SCRIPT_OBJECT); +} + +int ScriptObjectManager::isNumericType(int t) { + return (t == SCRIPT_INT || t == SCRIPT_BOOLEAN || t == SCRIPT_FLOAT || t == SCRIPT_DOUBLE); +} + +#ifdef WASABI_COMPILE_COMPONENTS +WACObject *ScriptObjectManager::getWACObject(const char *guid) { + GUID cg; + //BU: let me use guid:avs please :) + cg = *SkinParser::getComponentGuid(guid); + return getWACObject(cg); +} + +WACObject *ScriptObjectManager::getWACObject(GUID cg) { + for (int i=0;i<comps.getNumItems();i++) { + GUID dg = comps[i]->getGUID(); + if (!MEMCMP(&dg,&cg,sizeof(GUID))) + return comps[i]; + } + return NULL; +} +#endif + +SystemObject *ScriptObjectManager::getSystemObject(int n) { + return syslist.enumItem(n); +} + +SystemObject *ScriptObjectManager::getSystemObjectByScriptId(int id) { + static int lasti = -1; + static SystemObject *lasto = NULL; + if (lasti == id && syslist.haveItem(lasto)) return lasto; + for (int i=0;i<syslist.getNumItems();i++) { + if (syslist.enumItem(i)->getScriptId() == id) { + lasto = syslist.enumItem(i); + lasti = id; + return lasto; + } + } + return NULL; +} + +void ScriptObjectManager::registerSystemObject(SystemObject *o) { + syslist.addItem(o); +} + +void ScriptObjectManager::unregisterSystemObject(SystemObject *o) { + syslist.removeItem(o); +} + +int SOM::getNumSystemObjects() { + return syslist.getNumItems(); +} + +SystemObject *SOM::enumSystemObject(int n) { + return syslist.enumItem(n); +} + +int ScriptObjectManager::typeCheck(VCPUscriptVar *v, int fail) { + ASSERT(v); + ASSERT(v->v.data.odata); + int type = v->v.type; + while (type >= 0x10000) { + int id = VCPU::varBase(v->scriptId) + (type - 0x10000); + VCPUscriptVar *vc = VCPU::variablesTable.enumItem(id); + type = vc->v.type; + } + int otype = ObjectTable::getClassFromName(v->v.data.odata->vcpu_getClassName()); + ASSERT(otype >= 0); + if (ObjectTable::isDescendant(type, otype)) return 1; + if (fail) + Script::guruMeditation(getSystemObject(v->scriptId), GURU_INCOMPATIBLEOBJECT, L"VAR/OBJECT CLASS MISMATCH", v->varId); + return 0; +} + +#ifdef WASABI_COMPILE_WNDMGR +WindowHolder *ScriptObjectManager::getSuitableWindowHolderFromScript(GUID g) { + for (int i=0;i<getNumSystemObjects();i++) { + SystemObject *o = enumSystemObject(i); + WindowHolder *so = o->getSuitableWindowHolderByGuid(g); + if (so) return so; + } + return NULL; +} + +int ScriptObjectManager::checkAbortShowHideWindow(GUID g, int visible) { + for (int i=0;i<getNumSystemObjects();i++) { + SystemObject *o = enumSystemObject(i); + int r = o->onGetCancelComponent(g, visible); + if (r) + return r; + } + return 0; +} +#endif + +#ifdef WASABI_COMPILE_WND +ScriptObject *ScriptObjectManager::findObject(const wchar_t *name) +{ + for (int i=0;i<windowTracker->getNumAllWindows();i++) + { + ScriptObject *so = static_cast<ScriptObject *>(windowTracker->enumAllWindows(i)->getInterface(scriptObjectGuid)); + if (!so) continue; + GuiObject *go = static_cast<GuiObject *>(so->vcpu_getInterface(guiObjectGuid)); + if (!go) continue; + if (WCSCASEEQLSAFE(go->guiobject_getId(), name)) + return so; + } + return NULL; +} +#endif + +SystemObject * ScriptObjectManager::system; +PtrList < SystemObject > ScriptObjectManager::syslist; + +int ScriptObjectManager::inited = 0; |