PageRenderTime 61ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 1ms

/CS/migrated/branches/R0_18/apps/walktest/command.cpp

#
C++ | 610 lines | 523 code | 26 blank | 61 comment | 201 complexity | 8b43e47ebfacabf6b90ccc1acacac6a2 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0
  1. /*
  2. Copyright (C) 1998 by Jorrit Tyberghein
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public
  5. License as published by the Free Software Foundation; either
  6. version 2 of the License, or (at your option) any later version.
  7. This library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Library General Public License for more details.
  11. You should have received a copy of the GNU Library General Public
  12. License along with this library; if not, write to the Free
  13. Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. /*
  16. * Command processor. There are now several sources of commands:
  17. * the console and the keyboard. This class ignores the sources but
  18. * just executes the commands. The respective source handlers should
  19. * then do whatever they need to recognize the command and send the
  20. * command to this class.
  21. */
  22. #include <string.h>
  23. #include "cssysdef.h"
  24. #include "version.h"
  25. #include "csengine/engine.h"
  26. #include "csengine/lghtmap.h"
  27. #include "csengine/sector.h"
  28. #include "csengine/polygon.h"
  29. #include "csengine/polytext.h"
  30. #include "csengine/meshobj.h"
  31. #include "csengine/dumper.h"
  32. #include "command.h"
  33. #include "csutil/scanstr.h"
  34. #include "walktest.h"
  35. #include "qint.h"
  36. #include "igraph3d.h"
  37. #include "igraph2d.h"
  38. #include "iconsole.h"
  39. #include "ievent.h"
  40. #include "imeshobj.h"
  41. extern WalkTest* Sys;
  42. // Static csCommandProcessor variables
  43. csEngine* csCommandProcessor::engine = NULL;
  44. csCamera* csCommandProcessor::camera = NULL;
  45. iGraphics3D* csCommandProcessor::g3d = NULL;
  46. iConsole* csCommandProcessor::console = NULL;
  47. iSystem* csCommandProcessor::system = NULL;
  48. iFile* csCommandProcessor::script = NULL;
  49. // Additional command handler
  50. csCommandProcessor::CmdHandler csCommandProcessor::ExtraHandler = NULL;
  51. void csCommandProcessor::Initialize (csEngine* engine, csCamera* camera, iGraphics3D* g3d, iConsole* console, iSystem* system)
  52. {
  53. csCommandProcessor::engine = engine;
  54. csCommandProcessor::camera = camera;
  55. csCommandProcessor::g3d = g3d;
  56. csCommandProcessor::console = console;
  57. csCommandProcessor::system = system;
  58. }
  59. bool csCommandProcessor::PerformLine (const char* line)
  60. {
  61. return perform_line (line);
  62. }
  63. void csCommandProcessor::perform_callback (void *, const char *command)
  64. {
  65. perform_line (command);
  66. }
  67. static int value_choice (const char* arg, int old_value, const char* const* choices, int num)
  68. {
  69. if (!arg) return -1;
  70. int i = 0;
  71. if (!strcasecmp (arg, "next")) return (old_value+1)%num;
  72. if (!strcasecmp (arg, "prev")) return (old_value-1+num)%num;
  73. while (choices[i])
  74. {
  75. if (!strcasecmp (choices[i], arg)) return i;
  76. i++;
  77. }
  78. CsPrintf (MSG_CONSOLE, "Expected one of the following:\n");
  79. i = 0;
  80. while (choices[i])
  81. {
  82. CsPrintf (MSG_CONSOLE, " %s%s\n", choices[i], i == old_value ? " (current)" : "");
  83. i++;
  84. }
  85. CsPrintf (MSG_CONSOLE, " or 'next' or 'prev'\n");
  86. return -1;
  87. }
  88. static bool yes_or_no (const char* arg, bool old_value)
  89. {
  90. if (!arg) return false;
  91. if (*arg == '0' && *(arg+1) == 0) return false;
  92. if (*arg == '1' && *(arg+1) == 0) return true;
  93. if (!strcasecmp (arg, "yes") || !strcasecmp (arg, "true") || !strcasecmp (arg, "on")) return true;
  94. if (!strcasecmp (arg, "no") || !strcasecmp (arg, "false") || !strcasecmp (arg, "off")) return false;
  95. if (!strcasecmp (arg, "toggle")) return !old_value;
  96. CsPrintf (MSG_CONSOLE, "Expected: yes, true, on, 1, no, false, off, 0, or toggle!\n");
  97. return false;
  98. }
  99. static const char* say_on_or_off (int arg)
  100. {
  101. if (arg) return "on";
  102. return "off";
  103. }
  104. /*
  105. * Standard processing to change/display a boolean value setting.
  106. */
  107. void csCommandProcessor::change_boolean (const char* arg, bool* value, const char* what)
  108. {
  109. if (arg)
  110. {
  111. // Change value
  112. int v = yes_or_no (arg, *value);
  113. if (v != -1)
  114. {
  115. *value = v;
  116. CsPrintf (MSG_CONSOLE, "Set %s %s\n", what, say_on_or_off (*value));
  117. }
  118. }
  119. else
  120. {
  121. // Show value
  122. CsPrintf (MSG_CONSOLE, "Current %s is %s\n", what, say_on_or_off (*value));
  123. }
  124. }
  125. bool csCommandProcessor::change_boolean_gfx3d (const char* arg, G3D_RENDERSTATEOPTION op, const char* what)
  126. {
  127. bool bValue;
  128. long val = g3d->GetRenderState (op);
  129. bValue = (bool)val;
  130. change_boolean (arg, &bValue, what);
  131. return (g3d->SetRenderState (op, bValue));
  132. }
  133. /*
  134. * Standard processing to change/display a multi-value setting.
  135. */
  136. void csCommandProcessor::change_choice (const char* arg, int* value, const char* what, const char* const* choices, int num)
  137. {
  138. if (arg)
  139. {
  140. // Change value
  141. int v = value_choice (arg, *value, choices, num);
  142. if (v != -1)
  143. {
  144. *value = v;
  145. CsPrintf (MSG_CONSOLE, "Set %s %s\n", what, choices[*value]);
  146. }
  147. }
  148. else
  149. {
  150. // Show value
  151. CsPrintf (MSG_CONSOLE, "Current %s is %s\n", what, choices[*value]);
  152. }
  153. }
  154. /*
  155. * Standard processing to change/display a floating point setting.
  156. * Return true if value changed.
  157. */
  158. bool csCommandProcessor::change_float (const char* arg, float* value, const char* what, float min, float max)
  159. {
  160. if (arg)
  161. {
  162. // Change value.
  163. float g;
  164. if ((*arg == '+' || *arg == '-') && *(arg+1) == *arg)
  165. {
  166. float dv;
  167. sscanf (arg+1, "%f", &dv);
  168. g = *value+dv;
  169. }
  170. else sscanf (arg, "%f", &g);
  171. if (g < min || g > max) CsPrintf (MSG_CONSOLE, "Bad value for %s (%f <= value <= %f)!\n", what, min, max);
  172. else
  173. {
  174. *value = g;
  175. CsPrintf (MSG_CONSOLE, "Set %s to %f\n", what, *value);
  176. return true;
  177. }
  178. }
  179. else
  180. {
  181. // Show value.
  182. CsPrintf (MSG_CONSOLE, "Current %s is %f\n", what, *value);
  183. }
  184. return false;
  185. }
  186. /*
  187. * Standard processing to change/display an integer setting.
  188. * Return true if value changed.
  189. */
  190. bool csCommandProcessor::change_int (const char* arg, int* value, const char* what, int min, int max)
  191. {
  192. if (arg)
  193. {
  194. // Change value.
  195. int g;
  196. if ((*arg == '+' || *arg == '-') && *(arg+1) == *arg)
  197. {
  198. int dv;
  199. sscanf (arg+1, "%d", &dv);
  200. g = *value+dv;
  201. }
  202. else sscanf (arg, "%d", &g);
  203. if (g < min || g > max) CsPrintf (MSG_CONSOLE, "Bad value for %s (%d <= value <= %d)!\n", what, min, max);
  204. else
  205. {
  206. *value = g;
  207. CsPrintf (MSG_CONSOLE, "Set %s to %d\n", what, *value);
  208. return true;
  209. }
  210. }
  211. else
  212. {
  213. // Show value.
  214. CsPrintf (MSG_CONSOLE, "Current %s is %d\n", what, *value);
  215. }
  216. return false;
  217. }
  218. /*
  219. * Standard processing to change/display a long setting.
  220. * Return true if value changed.
  221. */
  222. bool csCommandProcessor::change_long (const char* arg, long* value, const char* what, long min, long max)
  223. {
  224. if (arg)
  225. {
  226. // Change value.
  227. long g;
  228. if ((*arg == '+' || *arg == '-') && *(arg+1) == *arg)
  229. {
  230. long dv;
  231. sscanf (arg+1, "%ld", &dv);
  232. g = *value+dv;
  233. }
  234. else sscanf (arg, "%ld", &g);
  235. if (g < min || g > max) CsPrintf (MSG_CONSOLE, "Bad value for %s (%ld <= value <= %ld)!\n", what, min, max);
  236. else
  237. {
  238. *value = g;
  239. CsPrintf (MSG_CONSOLE, "Set %s to %ld\n", what, *value);
  240. return true;
  241. }
  242. }
  243. else
  244. {
  245. // Show value.
  246. CsPrintf (MSG_CONSOLE, "Current %s is %ld\n", what, *value);
  247. }
  248. return false;
  249. }
  250. bool csCommandProcessor::perform_line (const char* line)
  251. {
  252. char cmd[512], arg[255];
  253. if (*line == ';') return true; // Comment
  254. if (*line == 0) return true; // Empty line
  255. strcpy (cmd, line);
  256. char* space = strchr (cmd, ' ');
  257. if (space) { *space = 0; strcpy (arg, space+1); }
  258. else *arg = 0;
  259. return perform (cmd, *arg ? arg : (char*)NULL);
  260. }
  261. extern bool GetConfigOption (iBase* plugin, const char* optName, csVariant& optValue);
  262. extern void SetConfigOption (iBase* plugin, const char* optName, const char* optValue);
  263. extern void SetConfigOption (iBase* plugin, const char* optName, csVariant& optValue);
  264. bool csCommandProcessor::perform (const char* cmd, const char* arg)
  265. {
  266. if (ExtraHandler)
  267. {
  268. static bool inside = false;
  269. if (!inside)
  270. {
  271. inside = true;
  272. bool ret = ExtraHandler (cmd, arg);
  273. inside = false;
  274. if (ret) return true;
  275. }
  276. }
  277. if (!strcasecmp (cmd, "quit"))
  278. csEngine::System->GetSystemEventOutlet ()->Broadcast (cscmdQuit);
  279. else if (!strcasecmp (cmd, "help"))
  280. {
  281. CsPrintf (MSG_CONSOLE, "-*- General commands -*-\n");
  282. CsPrintf (MSG_CONSOLE, " about, version, quit, help\n");
  283. CsPrintf (MSG_CONSOLE, " dblbuff, debug, db_maxpol, cachedump, cacheclr\n");
  284. // CsPrintf (MSG_CONSOLE, " coorddump, coordsave, coordload, coordset\n");
  285. CsPrintf (MSG_CONSOLE, " console, facenorth, facesouth, faceeast\n");
  286. CsPrintf (MSG_CONSOLE, " facewest, faceup, facedown, turn, activate\n");
  287. CsPrintf (MSG_CONSOLE, " cls, exec, dnl, dump, cmessage, dmessage\n");
  288. CsPrintf (MSG_CONSOLE, " lighting, texture, portals, transp, mipmap\n");
  289. CsPrintf (MSG_CONSOLE, " gamma, fov, fovangle, gouraud, ilace, mmx, inter\n");
  290. CsPrintf (MSG_CONSOLE, " bilinear, trilinear, lm_grid, lm_only, cosfact\n");
  291. CsPrintf (MSG_CONSOLE, " extension, lod, sprlight, coorddump, coordset\n");
  292. CsPrintf (MSG_CONSOLE, " db_procpol\n");
  293. }
  294. else if (!strcasecmp (cmd, "about"))
  295. {
  296. CsPrintf (MSG_CONSOLE, "Crystal Space version %s (%s).\n", CS_VERSION, CS_RELEASE_DATE);
  297. }
  298. else if (!strcasecmp (cmd, "version"))
  299. CsPrintf (MSG_CONSOLE, "%s\n", CS_VERSION);
  300. else if (!strcasecmp (cmd, "extension"))
  301. {
  302. iGraphics2D* g2d = g3d->GetDriver2D ();
  303. if (!g2d->PerformExtension (arg))
  304. CsPrintf (MSG_CONSOLE, "Extension '%s' not supported!\n", arg);
  305. }
  306. else if (!strcasecmp (cmd, "db_maxpol"))
  307. {
  308. long val = g3d->GetRenderState (G3DRENDERSTATE_MAXPOLYGONSTODRAW);
  309. int ival = (int)val;
  310. change_int (arg, &ival, "maximum polygons", 0, 2000000000);
  311. g3d->SetRenderState (G3DRENDERSTATE_MAXPOLYGONSTODRAW, (long)ival);
  312. }
  313. else if (!strcasecmp (cmd, "db_procpol"))
  314. {
  315. int val = csEngine::GetMaxProcessPolygons ();
  316. change_int (arg, &val, "maximum process polygons", 0, 2000000000);
  317. csEngine::SetMaxProcessPolygons (val);
  318. }
  319. else if (!strcasecmp (cmd, "cmessage"))
  320. {
  321. if (arg) CsPrintf (MSG_CONSOLE, arg);
  322. else CsPrintf (MSG_CONSOLE, "Argument expected!\n");
  323. }
  324. else if (!strcasecmp (cmd, "dmessage"))
  325. {
  326. if (arg) CsPrintf (MSG_DEBUG_0, arg);
  327. else CsPrintf (MSG_CONSOLE, "Argument expected!\n");
  328. }
  329. else if (!strcasecmp (cmd, "cosfact"))
  330. change_float (arg, &csPolyTexture::cfg_cosinus_factor, "cosinus factor", -1, 1);
  331. else if (!strcasecmp (cmd, "lod"))
  332. {
  333. iMeshObjectType* type = QUERY_PLUGIN_CLASS (Sys, "crystalspace.mesh.object.sprite.3d",
  334. "MeshObj", iMeshObjectType);
  335. csVariant lod_level;
  336. GetConfigOption (type, "sprlod", lod_level);
  337. change_float (arg, &lod_level.v.f, "LOD detail", -1, 1000000);
  338. SetConfigOption (type, "sprlod", lod_level);
  339. }
  340. else if (!strcasecmp (cmd, "sprlight"))
  341. {
  342. iMeshObjectType* type = QUERY_PLUGIN_CLASS (Sys, "crystalspace.mesh.object.sprite.3d",
  343. "MeshObj", iMeshObjectType);
  344. csVariant lqual;
  345. GetConfigOption (type, "sprlq", lqual);
  346. change_long (arg, &lqual.v.l, "sprite lighting quality", 0, 3);
  347. SetConfigOption (type, "sprlq", lqual);
  348. }
  349. else if (!strcasecmp (cmd, "dnl"))
  350. CsPrintf (MSG_DEBUG_0, "\n");
  351. else if (!strcasecmp (cmd, "exec"))
  352. {
  353. if (arg)
  354. {
  355. if (start_script (arg) && console)
  356. console->SetVisible (true);
  357. }
  358. else CsPrintf (MSG_CONSOLE, "Please specify the name of the script!\n");
  359. }
  360. else if (!strcasecmp (cmd, "dump"))
  361. {
  362. Dumper::dump (camera);
  363. Dumper::dump (engine);
  364. }
  365. else if (!strcasecmp (cmd, "transp"))
  366. change_boolean_gfx3d (arg, G3DRENDERSTATE_TRANSPARENCYENABLE, "transp");
  367. else if (!strcasecmp (cmd, "portals"))
  368. change_boolean (arg, &csSector::do_portals, "portals");
  369. //@@@
  370. //else if (!strcasecmp (cmd, "lm_grid"))
  371. //change_boolean (arg, &Textures::do_lightmapgrid, "lightmap grid");
  372. //else if (!strcasecmp (cmd, "lm_only"))
  373. //change_boolean (arg, &Textures::do_lightmaponly, "lightmap only");
  374. else if (!strcasecmp (cmd, "texture"))
  375. change_boolean_gfx3d (arg, G3DRENDERSTATE_TEXTUREMAPPINGENABLE, "texture mapping");
  376. else if (!strcasecmp (cmd, "bilinear"))
  377. change_boolean_gfx3d (arg, G3DRENDERSTATE_BILINEARMAPPINGENABLE, "bi-linear filtering");
  378. else if (!strcasecmp (cmd, "trilinear"))
  379. change_boolean_gfx3d (arg, G3DRENDERSTATE_TRILINEARMAPPINGENABLE, "tri-linear filtering");
  380. else if (!strcasecmp (cmd, "things"))
  381. change_boolean (arg, &csSector::do_things, "things");
  382. else if (!strcasecmp (cmd, "lighting"))
  383. change_boolean_gfx3d (arg, G3DRENDERSTATE_LIGHTINGENABLE, "lighting");
  384. else if (!strcasecmp (cmd, "gouraud"))
  385. {
  386. if (!change_boolean_gfx3d (arg, G3DRENDERSTATE_GOURAUDENABLE, "Gouraud shading"))
  387. CsPrintf (MSG_CONSOLE, "Gouraud shading toggling is not supported by 3D driver\n");
  388. }
  389. else if (!strcasecmp (cmd, "ilace"))
  390. {
  391. if (!change_boolean_gfx3d (arg, G3DRENDERSTATE_INTERLACINGENABLE, "interlaced mode"))
  392. CsPrintf (MSG_CONSOLE, "Interlaced mode not supported by 3D driver\n");
  393. }
  394. else if (!strcasecmp (cmd, "mmx"))
  395. {
  396. if (!change_boolean_gfx3d (arg, G3DRENDERSTATE_MMXENABLE, "mmx usage"))
  397. CsPrintf (MSG_CONSOLE, "MMX support is not present in this version\n");
  398. }
  399. else if (!strcasecmp (cmd, "cls"))
  400. {
  401. if (console)
  402. console->Clear ();
  403. }
  404. else if (!strcasecmp (cmd, "console"))
  405. {
  406. if (console)
  407. {
  408. bool active = console->GetVisible ();
  409. change_boolean (arg, &active, "console");
  410. if (active != console->GetVisible ())
  411. console->SetVisible (active);
  412. }
  413. }
  414. else if (!strcasecmp (cmd, "mipmap"))
  415. {
  416. int nValue;
  417. char* choices[6] = { "on", "off", "1", "2", "3", NULL };
  418. long old = g3d->GetRenderState( G3DRENDERSTATE_MIPMAPENABLE);
  419. nValue = old;
  420. change_choice (arg, &nValue, "mipmapping", choices, 5);
  421. g3d->SetRenderState( G3DRENDERSTATE_MIPMAPENABLE, (long)nValue );
  422. }
  423. else if (!strcasecmp (cmd, "inter"))
  424. {
  425. int nValue;
  426. char* choices[5] = { "smart", "step32", "step16", "step8", NULL };
  427. long old = g3d->GetRenderState (G3DRENDERSTATE_INTERPOLATIONSTEP);
  428. nValue = old;
  429. change_choice (arg, &nValue, "interpolation steps", choices, 4);
  430. g3d->SetRenderState (G3DRENDERSTATE_INTERPOLATIONSTEP, (long)nValue);
  431. }
  432. else if (!strcasecmp (cmd, "cachedump"))
  433. g3d->DumpCache ();
  434. else if (!strcasecmp (cmd, "cacheclr"))
  435. {
  436. CsPrintf (MSG_CONSOLE, "Refresh (clear) the texture cache.\n");
  437. g3d->ClearCache ();
  438. }
  439. else if (!strcasecmp (cmd, "turn"))
  440. camera->Rotate (VEC_ROT_RIGHT, M_PI);
  441. else if (!strcasecmp (cmd, "activate"))
  442. {
  443. CsPrintf (MSG_CONSOLE, "OBSOLETE\n");
  444. }
  445. else if (!strcasecmp (cmd, "coordset"))
  446. {
  447. if (!arg)
  448. {
  449. CsPrintf (MSG_CONSOLE, "Expected argument!\n");
  450. return false;
  451. }
  452. char sect[100];
  453. float x, y, z;
  454. if (ScanStr (arg, "%s,%f,%f,%f", sect, &x, &y, &z) != 4)
  455. {
  456. CsPrintf (MSG_CONSOLE, "Expected sector,x,y,z. Got something else!\n");
  457. return false;
  458. }
  459. csSector* s = (csSector*)engine->sectors.FindByName (sect);
  460. if (!s)
  461. {
  462. CsPrintf (MSG_CONSOLE, "Can't find this sector!\n");
  463. return false;
  464. }
  465. camera->SetSector (s);
  466. camera->SetPosition (csVector3(x,y,z));
  467. }
  468. else if (!strcasecmp (cmd, "facenorth"))
  469. camera->SetO2T (csMatrix3() /* identity */ );
  470. else if (!strcasecmp (cmd, "facesouth"))
  471. camera->SetO2T ( csMatrix3 ( -1, 0, 0,
  472. 0, 1, 0,
  473. 0, 0, -1 ) );
  474. else if (!strcasecmp (cmd, "facewest"))
  475. camera->SetO2T ( csMatrix3 ( 0, 0, 1,
  476. 0, 1, 0,
  477. -1, 0, 0 ) );
  478. else if (!strcasecmp (cmd, "faceeast"))
  479. camera->SetO2T ( csMatrix3 ( 0, 0, -1,
  480. 0, 1, 0,
  481. 1, 0, 0 ) );
  482. else if (!strcasecmp (cmd, "facedown"))
  483. camera->SetO2T ( csMatrix3 ( 1, 0, 0,
  484. 0, 0, 1,
  485. 1, -1, 0 ) );
  486. else if (!strcasecmp (cmd, "faceup"))
  487. camera->SetO2T ( csMatrix3 ( 1, 0, 0,
  488. 0, 0, -1,
  489. 1, 1, 0 ) );
  490. else if (!strcasecmp (cmd, "coorddump"))
  491. Dumper::dump (camera);
  492. else if (!strcasecmp (cmd, "gamma"))
  493. {
  494. float val = g3d->GetRenderState (G3DRENDERSTATE_GAMMACORRECTION) / 65536.;
  495. change_float (arg, &val, "gamma correction", 0, 10);
  496. g3d->SetRenderState (G3DRENDERSTATE_GAMMACORRECTION, QRound (val * 65536));
  497. }
  498. else if (!strcasecmp (cmd, "fov"))
  499. {
  500. float fov = (float)(camera->GetFOV ());
  501. if (change_float (arg, &fov, "fov", 0.01, 2000.0))
  502. camera->SetFOV ((int)fov, g3d->GetWidth ());
  503. }
  504. else if (!strcasecmp (cmd, "fovangle"))
  505. {
  506. float fov = (float)(camera->GetFOVAngle ());
  507. if (change_float (arg, &fov, "fovangle", 0.01, 360.0))
  508. camera->SetFOVAngle ((int)fov, g3d->GetWidth ());
  509. }
  510. else if (!strcasecmp (cmd, "dblbuff"))
  511. {
  512. iGraphics2D* g2d = g3d->GetDriver2D ();
  513. bool state = g2d->GetDoubleBufferState ();
  514. if (arg)
  515. {
  516. bool newstate = yes_or_no (arg, state);
  517. if (newstate != (bool)state)
  518. if (!g2d->DoubleBuffer (newstate))
  519. CsPrintf (MSG_CONSOLE, "Switching double buffering is not supported in current video mode!\n");
  520. }
  521. else
  522. CsPrintf (MSG_CONSOLE, "Current dblbuff is %s\n", say_on_or_off (state));
  523. }
  524. else
  525. {
  526. CsPrintf (MSG_CONSOLE, "Unknown command: `%s'\n", cmd);
  527. return false;
  528. }
  529. return true;
  530. }
  531. bool csCommandProcessor::start_script (const char* scr)
  532. {
  533. bool ok = false;
  534. iVFS* v = QUERY_PLUGIN_ID (system, CS_FUNCID_VFS, iVFS);
  535. if (v)
  536. {
  537. if (v->Exists (scr))
  538. {
  539. iFile* f = v->Open (scr, VFS_FILE_READ);
  540. if (!f)
  541. CsPrintf (MSG_CONSOLE, "Could not open script file '%s'!\n", scr);
  542. else
  543. {
  544. // Replace possible running script with this one.
  545. if (script)
  546. script->DecRef();
  547. script = f;
  548. ok = true;
  549. }
  550. }
  551. v->DecRef();
  552. }
  553. return ok;
  554. }
  555. bool csCommandProcessor::get_script_line (char* buf, int nbytes)
  556. {
  557. if (!script)
  558. return false;
  559. char c = '\n';
  560. while (c == '\n' || c == '\r')
  561. if (!script->Read(&c, 1))
  562. break;
  563. if (script->AtEOF())
  564. {
  565. script->DecRef();
  566. script = NULL;
  567. return false;
  568. }
  569. char* p = buf;
  570. const char* plim = p + nbytes - 1;
  571. while (p < plim)
  572. {
  573. if (c == '\n' || c == '\r')
  574. break;
  575. *p++ = c;
  576. if (!script->Read(&c, 1))
  577. break;
  578. }
  579. *p = '\0';
  580. return true;
  581. }