scriptmgr.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. #include <precomp.h>
  2. #include <bfc/wasabi_std.h>
  3. #include <api/script/script.h>
  4. #include <api/script/scriptmgr.h>
  5. #include <api/script/objects/systemobj.h>
  6. #include <api/script/vcpu.h>
  7. #include <api/skin/skinparse.h>
  8. #include <api/script/objecttable.h>
  9. #ifdef WASABI_COMPILE_WND
  10. #include <api/wnd/wndtrack.h>
  11. #endif
  12. #ifdef WASABI_COMPILE_COMPONENTS
  13. PtrList<WACObject> comps;
  14. #endif
  15. extern GUID baseGUID;
  16. ScriptObjectManager::ScriptObjectManager() {
  17. ASSERTPR(!inited, "don't create 2 scriptobjectmanager, you dumbass");
  18. inited=1;
  19. #ifdef WASABI_COMPILE_COMPONENTS
  20. for (int i=0;i<api->getNumComponents();i++) {
  21. GUID g = api->getComponentGUID(i);
  22. WACObject *c = new WACObject();
  23. c->setGUID(g);
  24. comps.addItem(c);
  25. }
  26. WACObject *m = new WACObject();
  27. m->setGUID(baseGUID);
  28. comps.addItem(m);
  29. #endif
  30. }
  31. ScriptObjectManager::~ScriptObjectManager() {
  32. inited=0;
  33. #ifdef WASABI_COMPILE_COMPONENTS
  34. comps.deleteAll();
  35. #endif
  36. }
  37. // Create a variable of specified type
  38. scriptVar ScriptObjectManager::makeVar(int type)
  39. {
  40. scriptVar v;
  41. v.type = type;
  42. v.data.ddata = 0;
  43. return v;
  44. }
  45. // Create a variable of specified type and assigns an object to it
  46. scriptVar ScriptObjectManager::makeVar(int type, ScriptObject *o)
  47. {
  48. scriptVar v = makeVar(type);
  49. v.data.odata = o;
  50. return v;
  51. }
  52. // Assigns a char* to a String variable. Frees old value if necessary
  53. void ScriptObjectManager::assign(scriptVar *v, const wchar_t *str)
  54. {
  55. ASSERT(v != NULL);
  56. ASSERT(v->type == SCRIPT_STRING); // Compiler discarded
  57. if (v->data.sdata) FREE((wchar_t *)v->data.sdata);
  58. if ((int)str > 65536) {
  59. v->data.sdata = WCSDUP(str);
  60. VCPU::addStatementString(const_cast<wchar_t *>(v->data.sdata));
  61. } else
  62. v->data.sdata = NULL;
  63. }
  64. // Assigns an int to an int, float or double variable.
  65. void ScriptObjectManager::assign(scriptVar *v, int i) {
  66. ASSERT(v != NULL);
  67. switch (v->type) {
  68. case SCRIPT_FLOAT:
  69. assign(v, (float)i);
  70. return;
  71. case SCRIPT_DOUBLE:
  72. assign(v, (double)i);
  73. return;
  74. case SCRIPT_INT:
  75. case SCRIPT_BOOLEAN:
  76. v->data.idata = i;
  77. return;
  78. case SCRIPT_STRING:
  79. assign(v, StringPrintfW(L"%d", i));
  80. return;
  81. default:
  82. assign(v, (ScriptObject*)NULL);
  83. return;
  84. }
  85. }
  86. // Assigns a float to an int, float or double variable.
  87. void ScriptObjectManager::assign(scriptVar *v, float f) {
  88. ASSERT(v != NULL);
  89. switch (v->type) {
  90. case SCRIPT_INT:
  91. case SCRIPT_BOOLEAN:
  92. assign(v, (int)f);
  93. return;
  94. case SCRIPT_DOUBLE:
  95. assign(v, (double)f);
  96. return;
  97. case SCRIPT_FLOAT:
  98. v->data.fdata = f;
  99. return;
  100. case SCRIPT_STRING:
  101. {
  102. wchar_t t[96] = {0};
  103. WCSNPRINTF(t, 96, L"%f", f);
  104. assign(v, t);
  105. return;
  106. }
  107. default:
  108. assign(v, (ScriptObject*)NULL);
  109. return;
  110. }
  111. }
  112. // Assigns a double to an int, float or double variable.
  113. void ScriptObjectManager::assign(scriptVar *v, double d) {
  114. ASSERT(v != NULL);
  115. switch (v->type) {
  116. case SCRIPT_INT:
  117. case SCRIPT_BOOLEAN:
  118. assign(v, (int)d);
  119. return;
  120. case SCRIPT_FLOAT:
  121. assign(v, (float)d);
  122. return;
  123. case SCRIPT_DOUBLE:
  124. v->data.ddata = d;
  125. return;
  126. case SCRIPT_STRING:
  127. {
  128. wchar_t t[96] = {0};
  129. WCSNPRINTF(t, 96, L"%e", d);
  130. assign(v, t);
  131. return;
  132. }
  133. default:
  134. assign(v, (ScriptObject*)NULL);
  135. return;
  136. }
  137. }
  138. // Assigns a object to an object variable, handles hierarchy.
  139. void ScriptObjectManager::assign(scriptVar *v, ScriptObject *o) {
  140. ASSERT(v != NULL);
  141. // TODO: temporarily assert descendancy
  142. v->data.odata = o;
  143. }
  144. // Assigns a numerical scriptVar to another numerical scriptVar
  145. // or an object to another object
  146. // Autocasts
  147. void ScriptObjectManager::assign(scriptVar *v1, scriptVar *v2) {
  148. ASSERT(v1 != NULL);
  149. ASSERT(v2 != NULL);
  150. switch (v1->type) {
  151. case SCRIPT_INT:
  152. assign(v1, SOM::makeInt(v2));
  153. break;
  154. case SCRIPT_FLOAT:
  155. assign(v1, SOM::makeFloat(v2));
  156. break;
  157. case SCRIPT_DOUBLE:
  158. assign(v1, SOM::makeDouble(v2));
  159. break;
  160. case SCRIPT_STRING:
  161. assign(v1, v2->data.sdata);
  162. break;
  163. case SCRIPT_BOOLEAN:
  164. assign(v1, SOM::makeBoolean(v2));
  165. break;
  166. default:
  167. assign(v1, v2->data.odata);
  168. break;
  169. }
  170. }
  171. void ScriptObjectManager::assignPersistent(scriptVar *v1, scriptVar *v2) {
  172. ASSERT(v1 != NULL);
  173. ASSERT(v2 != NULL);
  174. switch (v1->type) {
  175. case SCRIPT_INT:
  176. assign(v1, SOM::makeInt(v2));
  177. break;
  178. case SCRIPT_FLOAT:
  179. assign(v1, SOM::makeFloat(v2));
  180. break;
  181. case SCRIPT_DOUBLE:
  182. assign(v1, SOM::makeDouble(v2));
  183. break;
  184. case SCRIPT_STRING:
  185. persistentstrassign(v1, v2->data.sdata);
  186. break;
  187. case SCRIPT_BOOLEAN:
  188. assign(v1, SOM::makeBoolean(v2));
  189. break;
  190. default:
  191. assign(v1, v2->data.odata);
  192. break;
  193. }
  194. }
  195. void ScriptObjectManager::strflatassign(scriptVar *v, const wchar_t *str)
  196. {
  197. ASSERT(v != NULL);
  198. ASSERT(v->type == SCRIPT_STRING); // Compiler discarded
  199. if (v->data.sdata) FREE((wchar_t *)v->data.sdata);
  200. if ((int)str > 65536)
  201. v->data.sdata = (wchar_t *)str;
  202. else
  203. v->data.sdata = NULL;
  204. }
  205. void ScriptObjectManager::persistentstrassign(scriptVar *v, const wchar_t *str) {
  206. ASSERT(v != NULL);
  207. ASSERT(v->type == SCRIPT_STRING); // Compiler discarded
  208. if (v->data.sdata) FREE((wchar_t *)v->data.sdata);
  209. if ((int)str > 65536)
  210. v->data.sdata = WCSDUP(str);
  211. else
  212. v->data.sdata = NULL;
  213. }
  214. // comparision functions
  215. int ScriptObjectManager::compEq(scriptVar *v1, scriptVar *v2) {
  216. int r;
  217. switch (v1->type) {
  218. case SCRIPT_INT:
  219. r = v1->data.idata == makeInt(v2);
  220. break;
  221. case SCRIPT_FLOAT:
  222. r = v1->data.fdata == makeFloat(v2);
  223. break;
  224. case SCRIPT_DOUBLE:
  225. r = v1->data.ddata == makeDouble(v2);
  226. break;
  227. case SCRIPT_BOOLEAN:
  228. r = ((v1->data.idata == 0) ? 0 : 1) == ((makeBoolean(v2) == 0) ? 0 : 1);
  229. break;
  230. case SCRIPT_STRING:
  231. if (v1->data.sdata && v2->data.sdata)
  232. {
  233. r = !wcscmp(v1->data.sdata, v2->data.sdata);
  234. break;
  235. }
  236. // pass through
  237. default: // any object, reference has to match
  238. r = v1->data.odata == v2->data.odata;
  239. break;
  240. }
  241. return r;
  242. }
  243. int ScriptObjectManager::compNeq(scriptVar *v1, scriptVar *v2) {
  244. int r;
  245. switch (v1->type) {
  246. case SCRIPT_INT:
  247. r = v1->data.idata != makeInt(v2);
  248. break;
  249. case SCRIPT_FLOAT:
  250. r = v1->data.fdata != makeFloat(v2);
  251. break;
  252. case SCRIPT_DOUBLE:
  253. r = v1->data.ddata != makeDouble(v2);
  254. break;
  255. case SCRIPT_BOOLEAN:
  256. r = ((v1->data.idata == 0) ? 0 : 1) != ((makeBoolean(v2) == 0) ? 0 : 1);
  257. break;
  258. case SCRIPT_STRING:
  259. if (v1->data.sdata && v2->data.sdata)
  260. r = (wcscmp(v1->data.sdata, v2->data.sdata) != 0) ? 1 : 0;
  261. else
  262. r = 0;
  263. break;
  264. default:
  265. r = v1->data.odata != v2->data.odata;
  266. break;
  267. }
  268. return r;
  269. }
  270. int ScriptObjectManager::compA(scriptVar *v1, scriptVar *v2) {
  271. int r;
  272. switch (v1->type) {
  273. case SCRIPT_BOOLEAN:
  274. r = ((v1->data.idata == 0) ? 0 : 1) > ((makeBoolean(v2) == 0) ? 0 : 1);
  275. break;
  276. case SCRIPT_INT:
  277. r = v1->data.idata > makeInt(v2);
  278. break;
  279. case SCRIPT_FLOAT:
  280. r = v1->data.fdata > makeFloat(v2);
  281. break;
  282. case SCRIPT_DOUBLE:
  283. r = v1->data.ddata > makeDouble(v2);
  284. break;
  285. case SCRIPT_STRING:
  286. r = (wcscmp(v1->data.sdata, v2->data.sdata) > 0) ? 1 : 0;
  287. break;
  288. default:
  289. r = 0;
  290. break;
  291. }
  292. return r;
  293. }
  294. int ScriptObjectManager::compAe(scriptVar *v1, scriptVar *v2) {
  295. int r;
  296. switch (v1->type) {
  297. case SCRIPT_BOOLEAN:
  298. r = ((v1->data.idata == 0) ? 0 : 1) >= ((makeBoolean(v2) == 0) ? 0 : 1);
  299. break;
  300. case SCRIPT_INT:
  301. r = v1->data.idata >= makeInt(v2);
  302. break;
  303. case SCRIPT_FLOAT:
  304. r = v1->data.fdata >= makeFloat(v2);
  305. break;
  306. case SCRIPT_DOUBLE:
  307. r = v1->data.ddata >= makeDouble(v2);
  308. break;
  309. case SCRIPT_STRING:
  310. r = (wcscmp(v1->data.sdata, v2->data.sdata) >= 0) ? 1 : 0;
  311. break;
  312. default:
  313. r = 0;
  314. break;
  315. }
  316. return r;
  317. }
  318. int ScriptObjectManager::compB(scriptVar *v1, scriptVar *v2) {
  319. int r;
  320. switch (v1->type) {
  321. case SCRIPT_BOOLEAN:
  322. r = ((v1->data.idata == 0) ? 0 : 1) < ((makeBoolean(v2) == 0) ? 0 : 1);
  323. break;
  324. case SCRIPT_INT:
  325. r = v1->data.idata < makeInt(v2);
  326. break;
  327. case SCRIPT_FLOAT:
  328. r = v1->data.fdata < makeFloat(v2);
  329. break;
  330. case SCRIPT_DOUBLE:
  331. r = v1->data.ddata < makeDouble(v2);
  332. break;
  333. case SCRIPT_STRING:
  334. r = (wcscmp(v1->data.sdata, v2->data.sdata) < 0) ? 1 : 0;
  335. break;
  336. default:
  337. r = 0;
  338. break;
  339. }
  340. return r;
  341. }
  342. int ScriptObjectManager::compBe(scriptVar *v1, scriptVar *v2) {
  343. int r;
  344. switch (v1->type) {
  345. case SCRIPT_BOOLEAN:
  346. r = ((v1->data.idata == 0) ? 0 : 1) <= ((makeBoolean(v2) == 0) ? 0 : 1);
  347. break;
  348. case SCRIPT_INT:
  349. r = v1->data.idata <= makeInt(v2);
  350. break;
  351. case SCRIPT_FLOAT:
  352. r = v1->data.fdata <= makeFloat(v2);
  353. break;
  354. case SCRIPT_DOUBLE:
  355. r = v1->data.ddata <= makeDouble(v2);
  356. break;
  357. case SCRIPT_STRING:
  358. r = (wcscmp(v1->data.sdata, v2->data.sdata) <= 0) ? 1 : 0;
  359. break;
  360. default:
  361. r = 0;
  362. break;
  363. }
  364. return r;
  365. }
  366. void ScriptObjectManager::mid(wchar_t *dest, const wchar_t *str, int s, int l) {
  367. if (str == NULL) return;
  368. int rl = wcslen(str);
  369. if (l == 0) return;
  370. if (s >= rl) return;
  371. if (s+l > rl || l == -1) l = rl-s;
  372. WCSCPYN(dest, str+s, l+1);
  373. }
  374. int ScriptObjectManager::makeInt(scriptVar *v) {
  375. switch (v->type) {
  376. case SCRIPT_INT:
  377. return v->data.idata;
  378. case SCRIPT_FLOAT:
  379. return (int)v->data.fdata;
  380. case SCRIPT_DOUBLE:
  381. return (int)v->data.ddata;
  382. case SCRIPT_BOOLEAN:
  383. return (v->data.idata == 0) ? 0 : 1;
  384. case SCRIPT_STRING:
  385. return WTOI(v->data.sdata);
  386. default:
  387. return 0;
  388. }
  389. }
  390. float ScriptObjectManager::makeFloat(scriptVar *v) {
  391. switch (v->type) {
  392. case SCRIPT_INT:
  393. return (float)v->data.idata;
  394. case SCRIPT_FLOAT:
  395. return v->data.fdata;
  396. case SCRIPT_DOUBLE:
  397. return (float)v->data.ddata;
  398. case SCRIPT_BOOLEAN:
  399. return (float)((v->data.idata == 0) ? 0 : 1);
  400. case SCRIPT_STRING:
  401. return (float)WTOF(v->data.sdata);
  402. default:
  403. return 0.0f;
  404. }
  405. }
  406. double ScriptObjectManager::makeDouble(scriptVar *v) {
  407. switch (v->type) {
  408. case SCRIPT_VOID:
  409. return 0;
  410. case SCRIPT_INT:
  411. return (double)v->data.idata;
  412. case SCRIPT_FLOAT:
  413. return (double)v->data.fdata;
  414. case SCRIPT_DOUBLE:
  415. return v->data.ddata;
  416. case SCRIPT_BOOLEAN:
  417. return (double)((v->data.idata == 0) ? 0 : 1);
  418. case SCRIPT_STRING:
  419. return WTOF(v->data.sdata);
  420. default:
  421. return 0.0;
  422. }
  423. }
  424. bool ScriptObjectManager::makeBoolean(scriptVar *v) {
  425. switch (v->type) {
  426. case SCRIPT_INT:
  427. case SCRIPT_BOOLEAN:
  428. return (v->data.idata == 0) ? 0 : 1;
  429. case SCRIPT_FLOAT:
  430. return (v->data.fdata == 0) ? 0 : 1;
  431. case SCRIPT_DOUBLE:
  432. return (v->data.ddata == 0) ? 0 : 1;
  433. case SCRIPT_STRING: {
  434. StringW s = v->data.sdata;
  435. if (s.iscaseequal(L"false") || s.iscaseequal(L"f"))
  436. return 0;
  437. if (s.iscaseequal(L"true") || s.iscaseequal(L"t"))
  438. return 1;
  439. return (WTOI(s.getValue()) != 0);
  440. }
  441. default:
  442. return (v->data.odata != NULL) ? 1 : 0;
  443. }
  444. }
  445. int ScriptObjectManager::isNumeric(scriptVar *s) {
  446. return isNumericType(s->type);
  447. }
  448. int ScriptObjectManager::isString(scriptVar *s) {
  449. return (s->type == SCRIPT_STRING);
  450. }
  451. int ScriptObjectManager::isVoid(scriptVar *s) {
  452. return (s->type == SCRIPT_VOID);
  453. }
  454. int ScriptObjectManager::isObject(scriptVar *s) {
  455. return (s->type == SCRIPT_OBJECT);
  456. }
  457. int ScriptObjectManager::isNumericType(int t) {
  458. return (t == SCRIPT_INT || t == SCRIPT_BOOLEAN || t == SCRIPT_FLOAT || t == SCRIPT_DOUBLE);
  459. }
  460. #ifdef WASABI_COMPILE_COMPONENTS
  461. WACObject *ScriptObjectManager::getWACObject(const char *guid) {
  462. GUID cg;
  463. //BU: let me use guid:avs please :)
  464. cg = *SkinParser::getComponentGuid(guid);
  465. return getWACObject(cg);
  466. }
  467. WACObject *ScriptObjectManager::getWACObject(GUID cg) {
  468. for (int i=0;i<comps.getNumItems();i++) {
  469. GUID dg = comps[i]->getGUID();
  470. if (!MEMCMP(&dg,&cg,sizeof(GUID)))
  471. return comps[i];
  472. }
  473. return NULL;
  474. }
  475. #endif
  476. SystemObject *ScriptObjectManager::getSystemObject(int n) {
  477. return syslist.enumItem(n);
  478. }
  479. SystemObject *ScriptObjectManager::getSystemObjectByScriptId(int id) {
  480. static int lasti = -1;
  481. static SystemObject *lasto = NULL;
  482. if (lasti == id && syslist.haveItem(lasto)) return lasto;
  483. for (int i=0;i<syslist.getNumItems();i++) {
  484. if (syslist.enumItem(i)->getScriptId() == id) {
  485. lasto = syslist.enumItem(i);
  486. lasti = id;
  487. return lasto;
  488. }
  489. }
  490. return NULL;
  491. }
  492. void ScriptObjectManager::registerSystemObject(SystemObject *o) {
  493. syslist.addItem(o);
  494. }
  495. void ScriptObjectManager::unregisterSystemObject(SystemObject *o) {
  496. syslist.removeItem(o);
  497. }
  498. int SOM::getNumSystemObjects() {
  499. return syslist.getNumItems();
  500. }
  501. SystemObject *SOM::enumSystemObject(int n) {
  502. return syslist.enumItem(n);
  503. }
  504. int ScriptObjectManager::typeCheck(VCPUscriptVar *v, int fail) {
  505. ASSERT(v);
  506. ASSERT(v->v.data.odata);
  507. int type = v->v.type;
  508. while (type >= 0x10000) {
  509. int id = VCPU::varBase(v->scriptId) + (type - 0x10000);
  510. VCPUscriptVar *vc = VCPU::variablesTable.enumItem(id);
  511. type = vc->v.type;
  512. }
  513. int otype = ObjectTable::getClassFromName(v->v.data.odata->vcpu_getClassName());
  514. ASSERT(otype >= 0);
  515. if (ObjectTable::isDescendant(type, otype)) return 1;
  516. if (fail)
  517. Script::guruMeditation(getSystemObject(v->scriptId), GURU_INCOMPATIBLEOBJECT, L"VAR/OBJECT CLASS MISMATCH", v->varId);
  518. return 0;
  519. }
  520. #ifdef WASABI_COMPILE_WNDMGR
  521. WindowHolder *ScriptObjectManager::getSuitableWindowHolderFromScript(GUID g) {
  522. for (int i=0;i<getNumSystemObjects();i++) {
  523. SystemObject *o = enumSystemObject(i);
  524. WindowHolder *so = o->getSuitableWindowHolderByGuid(g);
  525. if (so) return so;
  526. }
  527. return NULL;
  528. }
  529. int ScriptObjectManager::checkAbortShowHideWindow(GUID g, int visible) {
  530. for (int i=0;i<getNumSystemObjects();i++) {
  531. SystemObject *o = enumSystemObject(i);
  532. int r = o->onGetCancelComponent(g, visible);
  533. if (r)
  534. return r;
  535. }
  536. return 0;
  537. }
  538. #endif
  539. #ifdef WASABI_COMPILE_WND
  540. ScriptObject *ScriptObjectManager::findObject(const wchar_t *name)
  541. {
  542. for (int i=0;i<windowTracker->getNumAllWindows();i++)
  543. {
  544. ScriptObject *so = static_cast<ScriptObject *>(windowTracker->enumAllWindows(i)->getInterface(scriptObjectGuid));
  545. if (!so) continue;
  546. GuiObject *go = static_cast<GuiObject *>(so->vcpu_getInterface(guiObjectGuid));
  547. if (!go) continue;
  548. if (WCSCASEEQLSAFE(go->guiobject_getId(), name))
  549. return so;
  550. }
  551. return NULL;
  552. }
  553. #endif
  554. SystemObject * ScriptObjectManager::system;
  555. PtrList < SystemObject > ScriptObjectManager::syslist;
  556. int ScriptObjectManager::inited = 0;