2014-10-14 13:11:37 +00:00
|
|
|
|
/*
|
|
|
|
|
* This file is part of the Colobot: Gold Edition source code
|
|
|
|
|
* Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
|
|
|
|
|
* http://epsiteс.ch; http://colobot.info; http://github.com/colobot
|
|
|
|
|
*
|
|
|
|
|
* 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://gnu.org/licenses
|
|
|
|
|
*/
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
#include "script/script.h"
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
2014-12-20 17:45:46 +00:00
|
|
|
|
#include "app/pausemanager.h"
|
2014-12-20 17:03:49 +00:00
|
|
|
|
|
2014-12-20 17:45:46 +00:00
|
|
|
|
#include "common/restext.h"
|
|
|
|
|
#include "common/stringutils.h"
|
2014-12-20 17:03:49 +00:00
|
|
|
|
|
2015-08-02 11:09:48 +00:00
|
|
|
|
#include "common/resources/inputstream.h"
|
|
|
|
|
#include "common/resources/outputstream.h"
|
|
|
|
|
#include "common/resources/resourcemanager.h"
|
|
|
|
|
|
2014-12-20 17:45:46 +00:00
|
|
|
|
#include "graphics/engine/engine.h"
|
|
|
|
|
#include "graphics/engine/text.h"
|
2014-12-20 17:03:49 +00:00
|
|
|
|
|
2015-08-13 09:47:32 +00:00
|
|
|
|
#include "level/robotmain.h"
|
|
|
|
|
|
2015-07-12 11:46:25 +00:00
|
|
|
|
#include "object/old_object.h"
|
2014-12-20 17:03:49 +00:00
|
|
|
|
|
2014-12-20 17:45:46 +00:00
|
|
|
|
#include "script/cbottoken.h"
|
2014-12-20 17:03:49 +00:00
|
|
|
|
|
2015-08-02 11:09:48 +00:00
|
|
|
|
#include "ui/displaytext.h"
|
2015-08-10 11:46:39 +00:00
|
|
|
|
|
2015-08-06 11:25:24 +00:00
|
|
|
|
#include "ui/controls/edit.h"
|
|
|
|
|
#include "ui/controls/interface.h"
|
|
|
|
|
#include "ui/controls/list.h"
|
2014-12-20 17:03:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-12-20 17:45:46 +00:00
|
|
|
|
const int CBOT_IPF = 100; // CBOT: default number of instructions / frame
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Object's constructor.
|
|
|
|
|
|
2015-08-10 11:46:39 +00:00
|
|
|
|
CScript::CScript(COldObject* object)
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2015-08-11 15:51:39 +00:00
|
|
|
|
assert(object->Implements(ObjectInterfaceType::Programmable));
|
|
|
|
|
|
2015-08-10 11:46:39 +00:00
|
|
|
|
m_object = object;
|
|
|
|
|
assert(m_object->Implements(ObjectInterfaceType::TaskExecutor));
|
|
|
|
|
m_taskExecutor = dynamic_cast<CTaskExecutorObject*>(m_object);
|
|
|
|
|
|
2013-02-16 21:37:43 +00:00
|
|
|
|
m_engine = Gfx::CEngine::GetInstancePointer();
|
|
|
|
|
m_main = CRobotMain::GetInstancePointer();
|
|
|
|
|
m_terrain = m_main->GetTerrain();
|
|
|
|
|
m_water = m_engine->GetWater();
|
2015-08-10 11:46:39 +00:00
|
|
|
|
m_interface = m_main->GetInterface();
|
|
|
|
|
m_pause = CPauseManager::GetInstancePointer();
|
2015-07-12 11:46:25 +00:00
|
|
|
|
|
2015-08-10 11:46:39 +00:00
|
|
|
|
m_botProg = nullptr;
|
2015-07-12 11:46:25 +00:00
|
|
|
|
|
2012-06-26 20:23:05 +00:00
|
|
|
|
m_ipf = CBOT_IPF;
|
|
|
|
|
m_errMode = ERM_STOP;
|
|
|
|
|
m_len = 0;
|
2012-12-26 19:58:02 +00:00
|
|
|
|
m_script = nullptr;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
m_bRun = false;
|
|
|
|
|
m_bStepMode = false;
|
|
|
|
|
m_bCompile = false;
|
|
|
|
|
m_title[0] = 0;
|
2014-11-10 21:42:05 +00:00
|
|
|
|
m_mainFunction[0] = 0;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
m_cursor1 = 0;
|
|
|
|
|
m_cursor2 = 0;
|
|
|
|
|
m_filename[0] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Object's destructor.
|
|
|
|
|
|
|
|
|
|
CScript::~CScript()
|
|
|
|
|
{
|
|
|
|
|
delete m_botProg;
|
2012-12-28 12:37:08 +00:00
|
|
|
|
m_botProg = nullptr;
|
|
|
|
|
|
|
|
|
|
delete[] m_script;
|
|
|
|
|
m_script = nullptr;
|
2012-12-26 19:58:02 +00:00
|
|
|
|
|
2012-06-26 20:23:05 +00:00
|
|
|
|
m_len = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Gives the script editable block of text.
|
|
|
|
|
|
2012-09-18 20:33:28 +00:00
|
|
|
|
void CScript::PutScript(Ui::CEdit* edit, const char* name)
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2012-12-28 12:37:08 +00:00
|
|
|
|
if ( m_script == nullptr )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
New(edit, name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
edit->SetText(m_script);
|
|
|
|
|
edit->SetCursor(m_cursor2, m_cursor1);
|
|
|
|
|
edit->ShowSelect();
|
|
|
|
|
}
|
2015-07-15 17:08:45 +00:00
|
|
|
|
m_interface->SetFocus(edit);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The script takes a paved text.
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
bool CScript::GetScript(Ui::CEdit* edit)
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
int len;
|
|
|
|
|
|
2012-12-28 12:37:08 +00:00
|
|
|
|
delete[] m_script;
|
|
|
|
|
m_script = nullptr;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
len = edit->GetTextLength();
|
2012-12-28 12:37:08 +00:00
|
|
|
|
m_script = new char[len+1];
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
edit->GetText(m_script, len+1);
|
|
|
|
|
edit->GetCursor(m_cursor2, m_cursor1);
|
|
|
|
|
m_len = strlen(m_script);
|
|
|
|
|
|
|
|
|
|
if ( !CheckToken() )
|
|
|
|
|
{
|
|
|
|
|
edit->SetCursor(m_cursor2, m_cursor1);
|
|
|
|
|
edit->ShowSelect();
|
2015-07-15 17:08:45 +00:00
|
|
|
|
m_interface->SetFocus(edit);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( !Compile() )
|
|
|
|
|
{
|
|
|
|
|
edit->SetCursor(m_cursor2, m_cursor1);
|
|
|
|
|
edit->ShowSelect();
|
2015-07-15 17:08:45 +00:00
|
|
|
|
m_interface->SetFocus(edit);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Indicates whether a program is compiled correctly.
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
bool CScript::GetCompile()
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
return m_bCompile;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Indicates whether the program is empty.
|
|
|
|
|
|
|
|
|
|
bool CScript::IsEmpty()
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for ( i=0 ; i<m_len ; i++ )
|
|
|
|
|
{
|
|
|
|
|
if ( m_script[i] != ' ' &&
|
|
|
|
|
m_script[i] != '\n' ) return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Checks if a program does not contain the prohibited instructions
|
|
|
|
|
// and if it contains well at least once every mandatory instructions.
|
|
|
|
|
|
|
|
|
|
bool CScript::CheckToken()
|
|
|
|
|
{
|
|
|
|
|
CBotToken* bt;
|
2013-10-12 16:48:28 +00:00
|
|
|
|
CBotToken* allBt;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
CBotString bs;
|
|
|
|
|
const char* token;
|
2012-09-10 21:29:38 +00:00
|
|
|
|
int error, cursor1, cursor2, i;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
char used[100];
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
if ( !m_object->GetCheckToken() ) return true;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
m_error = 0;
|
|
|
|
|
m_title[0] = 0;
|
2014-11-10 21:42:05 +00:00
|
|
|
|
m_mainFunction[0] = 0;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
m_token[0] = 0;
|
|
|
|
|
m_bCompile = false;
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
for ( i=0 ; i<m_main->GetObligatoryToken() ; i++ )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
used[i] = 0; // token not used
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-12 16:48:28 +00:00
|
|
|
|
allBt = CBotToken::CompileTokens(m_script, error);
|
|
|
|
|
bt = allBt;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
while ( bt != 0 )
|
|
|
|
|
{
|
2012-09-10 21:29:38 +00:00
|
|
|
|
bs = bt->GetString();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
token = bs;
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
cursor1 = bt->GetStart();
|
|
|
|
|
cursor2 = bt->GetEnd();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
i = m_main->IsObligatoryToken(token);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( i != -1 )
|
|
|
|
|
{
|
|
|
|
|
used[i] = 1; // token used
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
if ( !m_main->IsProhibitedToken(token) )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
m_error = ERR_PROHIBITEDTOKEN;
|
|
|
|
|
m_cursor1 = cursor1;
|
|
|
|
|
m_cursor2 = cursor2;
|
2014-11-10 21:42:05 +00:00
|
|
|
|
strcpy(m_title, "<prohibited>");
|
|
|
|
|
m_mainFunction[0] = 0;
|
2013-10-12 16:48:28 +00:00
|
|
|
|
CBotToken::Delete(allBt);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
bt = bt->GetNext();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// At least once every obligatory instruction?
|
2012-09-10 21:29:38 +00:00
|
|
|
|
for ( i=0 ; i<m_main->GetObligatoryToken() ; i++ )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
if ( used[i] == 0 ) // token not used?
|
|
|
|
|
{
|
2012-09-10 21:29:38 +00:00
|
|
|
|
strcpy(m_token, m_main->GetObligatoryToken(i));
|
2012-06-26 20:23:05 +00:00
|
|
|
|
m_error = ERR_OBLIGATORYTOKEN;
|
2014-11-10 21:42:05 +00:00
|
|
|
|
strcpy(m_title, "<obligatory>");
|
|
|
|
|
m_mainFunction[0] = 0;
|
2013-10-12 16:48:28 +00:00
|
|
|
|
CBotToken::Delete(allBt);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-12 16:48:28 +00:00
|
|
|
|
CBotToken::Delete(allBt);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Compile the script of a paved text.
|
|
|
|
|
|
|
|
|
|
bool CScript::Compile()
|
|
|
|
|
{
|
|
|
|
|
CBotStringArray liste;
|
|
|
|
|
int i;
|
|
|
|
|
const char* p;
|
|
|
|
|
|
|
|
|
|
m_error = 0;
|
|
|
|
|
m_cursor1 = 0;
|
|
|
|
|
m_cursor2 = 0;
|
|
|
|
|
m_title[0] = 0;
|
2014-11-10 21:42:05 +00:00
|
|
|
|
m_mainFunction[0] = 0;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
m_bCompile = false;
|
|
|
|
|
|
|
|
|
|
if ( IsEmpty() ) // program exist?
|
|
|
|
|
{
|
|
|
|
|
delete m_botProg;
|
|
|
|
|
m_botProg = 0;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( m_botProg == 0 )
|
|
|
|
|
{
|
2012-09-10 21:29:38 +00:00
|
|
|
|
m_botProg = new CBotProgram(m_object->GetBotVar());
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( m_botProg->Compile(m_script, liste, this) )
|
|
|
|
|
{
|
2012-09-10 21:29:38 +00:00
|
|
|
|
if ( liste.GetSize() == 0 )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2013-05-19 15:03:55 +00:00
|
|
|
|
strcpy(m_title, "<extern missing>");
|
2014-11-10 21:42:05 +00:00
|
|
|
|
m_mainFunction[0] = 0;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
p = liste[0];
|
|
|
|
|
i = 0;
|
2014-11-10 21:42:05 +00:00
|
|
|
|
bool titleDone = false;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
while ( true )
|
|
|
|
|
{
|
|
|
|
|
if ( p[i] == 0 || p[i] == '(' ) break;
|
2014-11-10 21:42:05 +00:00
|
|
|
|
if ( i >= 20 && !titleDone )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2014-11-10 21:42:05 +00:00
|
|
|
|
m_title[i+0] = '.';
|
|
|
|
|
m_title[i+1] = '.';
|
|
|
|
|
m_title[i+2] = '.';
|
|
|
|
|
m_title[i+3] = 0;
|
|
|
|
|
titleDone = true;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
2014-11-10 21:42:05 +00:00
|
|
|
|
if(!titleDone)
|
|
|
|
|
m_title[i] = p[i];
|
|
|
|
|
m_mainFunction[i] = p[i];
|
2012-06-26 20:23:05 +00:00
|
|
|
|
i ++;
|
|
|
|
|
}
|
2014-11-10 21:42:05 +00:00
|
|
|
|
if(!titleDone)
|
|
|
|
|
m_title[i] = 0;
|
|
|
|
|
m_mainFunction[i] = p[i];
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
m_bCompile = true;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_botProg->GetError(m_error, m_cursor1, m_cursor2);
|
|
|
|
|
if ( m_cursor1 < 0 || m_cursor1 > m_len ||
|
|
|
|
|
m_cursor2 < 0 || m_cursor2 > m_len )
|
|
|
|
|
{
|
|
|
|
|
m_cursor1 = 0;
|
|
|
|
|
m_cursor2 = 0;
|
|
|
|
|
}
|
|
|
|
|
if ( m_error == 0 )
|
|
|
|
|
{
|
|
|
|
|
m_cursor1 = m_cursor2 = 0;
|
|
|
|
|
}
|
2013-05-19 15:03:55 +00:00
|
|
|
|
strcpy(m_title, "<error>");
|
2014-11-10 21:42:05 +00:00
|
|
|
|
m_mainFunction[0] = 0;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Returns the title of the script.
|
|
|
|
|
|
|
|
|
|
void CScript::GetTitle(char* buffer)
|
|
|
|
|
{
|
|
|
|
|
strcpy(buffer, m_title);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Choice of mode of execution.
|
|
|
|
|
|
|
|
|
|
void CScript::SetStepMode(bool bStep)
|
|
|
|
|
{
|
|
|
|
|
m_bStepMode = bStep;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Runs the program from the beginning.
|
|
|
|
|
|
|
|
|
|
bool CScript::Run()
|
|
|
|
|
{
|
|
|
|
|
if( m_botProg == 0 ) return false;
|
2012-12-28 12:37:08 +00:00
|
|
|
|
if ( m_script == nullptr || m_len == 0 ) return false;
|
2014-11-10 21:42:05 +00:00
|
|
|
|
if ( m_mainFunction[0] == 0 ) return false;
|
2015-07-12 11:46:25 +00:00
|
|
|
|
|
2014-11-10 21:42:05 +00:00
|
|
|
|
if ( !m_botProg->Start(m_mainFunction) ) return false;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
m_bRun = true;
|
|
|
|
|
m_bContinue = false;
|
|
|
|
|
m_ipf = CBOT_IPF;
|
|
|
|
|
m_errMode = ERM_STOP;
|
|
|
|
|
|
|
|
|
|
if ( m_bStepMode ) // step by step mode?
|
|
|
|
|
{
|
2015-08-10 11:46:39 +00:00
|
|
|
|
Step();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Continues the execution of current program.
|
|
|
|
|
// Returns true when execution is finished.
|
|
|
|
|
|
2015-08-10 11:46:39 +00:00
|
|
|
|
bool CScript::Continue()
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
if( m_botProg == 0 ) return true;
|
|
|
|
|
if ( !m_bRun ) return true;
|
|
|
|
|
|
|
|
|
|
if ( m_bStepMode ) // step by step mode?
|
|
|
|
|
{
|
|
|
|
|
if ( m_bContinue ) // instuction "move", "goto", etc. ?
|
|
|
|
|
{
|
2015-08-11 15:51:39 +00:00
|
|
|
|
if ( m_botProg->Run(this, 0) )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
m_botProg->GetError(m_error, m_cursor1, m_cursor2);
|
|
|
|
|
if ( m_cursor1 < 0 || m_cursor1 > m_len ||
|
|
|
|
|
m_cursor2 < 0 || m_cursor2 > m_len )
|
|
|
|
|
{
|
|
|
|
|
m_cursor1 = 0;
|
|
|
|
|
m_cursor2 = 0;
|
|
|
|
|
}
|
|
|
|
|
if ( m_error == 0 )
|
|
|
|
|
{
|
|
|
|
|
m_cursor1 = m_cursor2 = 0;
|
|
|
|
|
}
|
|
|
|
|
m_bRun = false;
|
|
|
|
|
|
|
|
|
|
if ( m_error != 0 && m_errMode == ERM_STOP )
|
|
|
|
|
{
|
2013-12-02 23:11:26 +00:00
|
|
|
|
std::string s;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
GetError(s);
|
2013-12-02 23:11:26 +00:00
|
|
|
|
m_main->GetDisplayText()->DisplayText(s.c_str(), m_object, 10.0f, Ui::TT_ERROR);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
2013-12-31 11:58:45 +00:00
|
|
|
|
m_pause->SetPause(PAUSE_EDITOR); // gives pause
|
2012-06-26 20:23:05 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if ( !m_bContinue )
|
|
|
|
|
{
|
2013-12-31 11:58:45 +00:00
|
|
|
|
m_pause->SetPause(PAUSE_EDITOR); // gives pause
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-11 15:51:39 +00:00
|
|
|
|
if ( m_botProg->Run(this, m_ipf) )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
m_botProg->GetError(m_error, m_cursor1, m_cursor2);
|
|
|
|
|
if ( m_cursor1 < 0 || m_cursor1 > m_len ||
|
|
|
|
|
m_cursor2 < 0 || m_cursor2 > m_len )
|
|
|
|
|
{
|
|
|
|
|
m_cursor1 = 0;
|
|
|
|
|
m_cursor2 = 0;
|
|
|
|
|
}
|
|
|
|
|
if ( m_error == 0 )
|
|
|
|
|
{
|
|
|
|
|
m_cursor1 = m_cursor2 = 0;
|
|
|
|
|
}
|
|
|
|
|
m_bRun = false;
|
|
|
|
|
|
|
|
|
|
if ( m_error != 0 && m_errMode == ERM_STOP )
|
|
|
|
|
{
|
2013-12-02 23:11:26 +00:00
|
|
|
|
std::string s;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
GetError(s);
|
2013-12-02 23:11:26 +00:00
|
|
|
|
m_main->GetDisplayText()->DisplayText(s.c_str(), m_object, 10.0f, Ui::TT_ERROR);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Continues the execution of current program.
|
|
|
|
|
// Returns true when execution is finished.
|
|
|
|
|
|
2015-08-10 11:46:39 +00:00
|
|
|
|
bool CScript::Step()
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
if( m_botProg == 0 ) return true;
|
|
|
|
|
if ( !m_bRun ) return true;
|
|
|
|
|
if ( !m_bStepMode ) return false;
|
|
|
|
|
|
2013-12-31 11:58:45 +00:00
|
|
|
|
// ??? m_engine->SetPause(false);
|
2012-09-15 16:50:51 +00:00
|
|
|
|
// TODO: m_app StepSimulation??? m_engine->StepSimulation(0.01f); // advance of 10ms
|
2013-12-31 11:58:45 +00:00
|
|
|
|
// ??? m_engine->SetPause(true);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
2015-08-11 15:51:39 +00:00
|
|
|
|
if ( m_botProg->Run(this, 0) ) // step mode
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
m_botProg->GetError(m_error, m_cursor1, m_cursor2);
|
|
|
|
|
if ( m_cursor1 < 0 || m_cursor1 > m_len ||
|
|
|
|
|
m_cursor2 < 0 || m_cursor2 > m_len )
|
|
|
|
|
{
|
|
|
|
|
m_cursor1 = 0;
|
|
|
|
|
m_cursor2 = 0;
|
|
|
|
|
}
|
|
|
|
|
if ( m_error == 0 )
|
|
|
|
|
{
|
|
|
|
|
m_cursor1 = m_cursor2 = 0;
|
|
|
|
|
}
|
|
|
|
|
m_bRun = false;
|
|
|
|
|
|
|
|
|
|
if ( m_error != 0 && m_errMode == ERM_STOP )
|
|
|
|
|
{
|
2013-12-02 23:11:26 +00:00
|
|
|
|
std::string s;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
GetError(s);
|
2013-12-02 23:11:26 +00:00
|
|
|
|
m_main->GetDisplayText()->DisplayText(s.c_str(), m_object, 10.0f, Ui::TT_ERROR);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( m_bContinue ) // instuction "move", "goto", etc. ?
|
|
|
|
|
{
|
2015-07-22 16:01:24 +00:00
|
|
|
|
if (m_pause->GetPauseType() == PAUSE_EDITOR)
|
|
|
|
|
{
|
|
|
|
|
m_pause->ClearPause(); // removes the pause
|
|
|
|
|
}
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Stops the program.
|
|
|
|
|
|
|
|
|
|
void CScript::Stop()
|
|
|
|
|
{
|
|
|
|
|
if ( !m_bRun ) return;
|
|
|
|
|
|
2015-08-12 14:54:44 +00:00
|
|
|
|
m_taskExecutor->StopForegroundTask();
|
|
|
|
|
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if( m_botProg != 0 )
|
|
|
|
|
{
|
|
|
|
|
m_botProg->Stop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_bRun = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Indicates whether the program runs.
|
|
|
|
|
|
|
|
|
|
bool CScript::IsRunning()
|
|
|
|
|
{
|
|
|
|
|
return m_bRun;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Indicates whether the program continues a step.
|
|
|
|
|
|
|
|
|
|
bool CScript::IsContinue()
|
|
|
|
|
{
|
|
|
|
|
return m_bContinue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Gives the position of the cursor during the execution.
|
|
|
|
|
|
|
|
|
|
bool CScript::GetCursor(int &cursor1, int &cursor2)
|
|
|
|
|
{
|
|
|
|
|
const char* funcName;
|
|
|
|
|
|
|
|
|
|
cursor1 = cursor2 = 0;
|
|
|
|
|
|
|
|
|
|
if( m_botProg == 0 ) return false;
|
|
|
|
|
if ( !m_bRun ) return false;
|
|
|
|
|
|
|
|
|
|
m_botProg->GetRunPos(funcName, cursor1, cursor2);
|
|
|
|
|
if ( cursor1 < 0 || cursor1 > m_len ||
|
|
|
|
|
cursor2 < 0 || cursor2 > m_len )
|
|
|
|
|
{
|
|
|
|
|
cursor1 = 0;
|
|
|
|
|
cursor2 = 0;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Put of the variables in a list.
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
void PutList(const char *baseName, bool bArray, CBotVar *var, Ui::CList *list, int &rankList)
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
CBotString bs;
|
|
|
|
|
CBotVar *svar, *pStatic;
|
|
|
|
|
char varName[100];
|
|
|
|
|
char buffer[100];
|
|
|
|
|
const char *p;
|
|
|
|
|
int index, type;
|
|
|
|
|
|
|
|
|
|
if ( var == 0 && baseName[0] != 0 )
|
|
|
|
|
{
|
|
|
|
|
sprintf(buffer, "%s = null;", baseName);
|
2013-05-26 15:45:15 +00:00
|
|
|
|
list->SetItemName(rankList++, buffer);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
index = 0;
|
|
|
|
|
while ( var != 0 )
|
|
|
|
|
{
|
|
|
|
|
var->Maj(NULL, false);
|
2012-09-10 21:29:38 +00:00
|
|
|
|
pStatic = var->GetStaticVar(); // finds the static element
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
bs = pStatic->GetName(); // variable name
|
2012-06-26 20:23:05 +00:00
|
|
|
|
p = bs;
|
|
|
|
|
//? if ( strcmp(p, "this") == 0 )
|
|
|
|
|
//? {
|
2012-09-10 21:29:38 +00:00
|
|
|
|
//? var = var->GetNext();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
//? continue;
|
|
|
|
|
//? }
|
|
|
|
|
|
|
|
|
|
if ( baseName[0] == 0 )
|
|
|
|
|
{
|
|
|
|
|
sprintf(varName, "%s", p);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ( bArray )
|
|
|
|
|
{
|
|
|
|
|
sprintf(varName, "%s[%d]", baseName, index);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
sprintf(varName, "%s.%s", baseName, p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
type = pStatic->GetType();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
if ( type < CBotTypBoolean )
|
|
|
|
|
{
|
|
|
|
|
CBotString value;
|
2012-09-10 21:29:38 +00:00
|
|
|
|
value = pStatic->GetValString();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
p = value;
|
|
|
|
|
sprintf(buffer, "%s = %s;", varName, p);
|
2013-05-26 15:45:15 +00:00
|
|
|
|
list->SetItemName(rankList++, buffer);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
else if ( type == CBotTypString )
|
|
|
|
|
{
|
|
|
|
|
CBotString value;
|
2012-09-10 21:29:38 +00:00
|
|
|
|
value = pStatic->GetValString();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
p = value;
|
|
|
|
|
sprintf(buffer, "%s = \"%s\";", varName, p);
|
2013-05-26 15:45:15 +00:00
|
|
|
|
list->SetItemName(rankList++, buffer);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
else if ( type == CBotTypArrayPointer )
|
|
|
|
|
{
|
2012-09-10 21:29:38 +00:00
|
|
|
|
svar = pStatic->GetItemList();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
PutList(varName, true, svar, list, rankList);
|
|
|
|
|
}
|
|
|
|
|
else if ( type == CBotTypClass ||
|
|
|
|
|
type == CBotTypPointer )
|
|
|
|
|
{
|
2012-09-10 21:29:38 +00:00
|
|
|
|
svar = pStatic->GetItemList();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
PutList(varName, false, svar, list, rankList);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
sprintf(buffer, "%s = ?;", varName);
|
2013-05-26 15:45:15 +00:00
|
|
|
|
list->SetItemName(rankList++, buffer);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
index ++;
|
2012-09-10 21:29:38 +00:00
|
|
|
|
var = var->GetNext();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fills a list with variables.
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
void CScript::UpdateList(Ui::CList* list)
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
CBotVar *var;
|
|
|
|
|
const char *progName, *funcName;
|
|
|
|
|
int total, select, level, cursor1, cursor2, rank;
|
|
|
|
|
|
|
|
|
|
if( m_botProg == 0 ) return;
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
total = list->GetTotal();
|
|
|
|
|
select = list->GetSelect();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
list->Flush(); // empty list
|
|
|
|
|
m_botProg->GetRunPos(progName, cursor1, cursor2);
|
|
|
|
|
if ( progName == 0 ) return;
|
|
|
|
|
|
|
|
|
|
level = 0;
|
|
|
|
|
rank = 0;
|
|
|
|
|
while ( true )
|
|
|
|
|
{
|
2012-09-10 21:29:38 +00:00
|
|
|
|
var = m_botProg->GetStackVars(funcName, level--);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( funcName != progName ) break;
|
|
|
|
|
|
|
|
|
|
PutList("", false, var, list, rank);
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
if ( total == list->GetTotal() ) // same total?
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
list->SetSelect(select);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
list->SetTooltip("");
|
2012-09-10 21:29:38 +00:00
|
|
|
|
list->SetState(Ui::STATE_ENABLE);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Colorize the text according to syntax.
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
void CScript::ColorizeScript(Ui::CEdit* edit)
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
CBotToken* bt;
|
|
|
|
|
CBotString bs;
|
|
|
|
|
const char* token;
|
2012-09-10 21:29:38 +00:00
|
|
|
|
int error, type, cursor1, cursor2;
|
|
|
|
|
Gfx::FontHighlight color;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
edit->ClearFormat();
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
bt = CBotToken::CompileTokens(edit->GetText(), error);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
while ( bt != 0 )
|
|
|
|
|
{
|
2012-09-10 21:29:38 +00:00
|
|
|
|
bs = bt->GetString();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
token = bs;
|
2012-09-10 21:29:38 +00:00
|
|
|
|
type = bt->GetType();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
cursor1 = bt->GetStart();
|
|
|
|
|
cursor2 = bt->GetEnd();
|
|
|
|
|
color = Gfx::FONT_HIGHLIGHT_NONE;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( type >= TokenKeyWord && type < TokenKeyWord+100 )
|
|
|
|
|
{
|
2012-09-10 21:29:38 +00:00
|
|
|
|
color = Gfx::FONT_HIGHLIGHT_TOKEN;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
if ( type >= TokenKeyDeclare && type < TokenKeyDeclare+100 )
|
|
|
|
|
{
|
2012-09-10 21:29:38 +00:00
|
|
|
|
color = Gfx::FONT_HIGHLIGHT_TYPE;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
if ( type >= TokenKeyVal && type < TokenKeyVal+100 )
|
|
|
|
|
{
|
2012-09-10 21:29:38 +00:00
|
|
|
|
color = Gfx::FONT_HIGHLIGHT_CONST;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
2015-08-03 17:56:35 +00:00
|
|
|
|
if ( type == TokenTypVar || ( type >= TokenKeyWord && type < TokenKeyWord+100 ) || strcmp(token, "this") == 0 )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
if ( IsType(token) )
|
|
|
|
|
{
|
2012-09-10 21:29:38 +00:00
|
|
|
|
color = Gfx::FONT_HIGHLIGHT_TYPE;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
2015-08-03 17:56:35 +00:00
|
|
|
|
else if ( IsFunction(token) || strcmp(token, "this") == 0 )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2012-09-10 21:29:38 +00:00
|
|
|
|
color = Gfx::FONT_HIGHLIGHT_TOKEN;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( type == TokenTypDef )
|
|
|
|
|
{
|
2012-09-10 21:29:38 +00:00
|
|
|
|
color =Gfx::FONT_HIGHLIGHT_CONST;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-02-09 20:00:07 +00:00
|
|
|
|
if ( cursor1 < cursor2 && color != Gfx::FONT_HIGHLIGHT_NONE )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
edit->SetFormat(cursor1, cursor2, color);
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
bt = bt->GetNext();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotToken::Delete(bt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Seeks a token at random in a script.
|
|
|
|
|
// Returns the index of the start of the token found, or -1.
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
|
|
|
|
|
int SearchToken(char* script, const char* token)
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
int lScript, lToken, i, iFound;
|
|
|
|
|
int found[100];
|
|
|
|
|
char* p;
|
|
|
|
|
|
|
|
|
|
lScript = strlen(script);
|
|
|
|
|
lToken = strlen(token);
|
|
|
|
|
iFound = 0;
|
|
|
|
|
for ( i=0 ; i<lScript-lToken ; i++ )
|
|
|
|
|
{
|
|
|
|
|
p = strstr(script+i, token);
|
|
|
|
|
if ( p != 0 )
|
|
|
|
|
{
|
|
|
|
|
found[iFound++] = p-script;
|
|
|
|
|
if ( iFound >= 100 ) break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( iFound == 0 ) return -1;
|
|
|
|
|
return found[rand()%iFound];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Removes a token in a script.
|
|
|
|
|
|
|
|
|
|
void DeleteToken(char* script, int pos, int len)
|
|
|
|
|
{
|
|
|
|
|
while ( true )
|
|
|
|
|
{
|
|
|
|
|
script[pos] = script[pos+len];
|
|
|
|
|
if ( script[pos++] == 0 ) break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Inserts a token in a script.
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
void InsertToken(char* script, int pos, const char* token)
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
int lScript, lToken, i;
|
|
|
|
|
|
|
|
|
|
lScript = strlen(script);
|
|
|
|
|
lToken = strlen(token);
|
|
|
|
|
for ( i=lScript ; i>=pos ; i-- )
|
|
|
|
|
{
|
|
|
|
|
script[i+lToken] = script[i];
|
|
|
|
|
}
|
|
|
|
|
memcpy(script+pos, token, lToken);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Introduces a virus into a program.
|
|
|
|
|
|
|
|
|
|
bool CScript::IntroduceVirus()
|
|
|
|
|
{
|
2015-08-06 20:50:22 +00:00
|
|
|
|
if (m_script == nullptr) return false;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
const char* names[11*2] =
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
"==", "!=",
|
|
|
|
|
"!=", "==",
|
|
|
|
|
">", "<",
|
|
|
|
|
"<", ">",
|
|
|
|
|
"true", "false",
|
|
|
|
|
"false", "true",
|
|
|
|
|
"grab", "drop",
|
|
|
|
|
"drop", "grab",
|
|
|
|
|
"InFront", "Behind",
|
|
|
|
|
"Behind", "EnergyCell",
|
|
|
|
|
"EnergyCell", "InFront",
|
|
|
|
|
};
|
|
|
|
|
|
2015-08-06 20:50:22 +00:00
|
|
|
|
int iFound = 0;
|
|
|
|
|
int found[11*2];
|
|
|
|
|
for ( int i=0 ; i<11 ; i++ )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2015-08-06 20:50:22 +00:00
|
|
|
|
int start = SearchToken(m_script, names[i*2]);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( start != -1 )
|
|
|
|
|
{
|
|
|
|
|
found[iFound++] = i*2;
|
|
|
|
|
found[iFound++] = start;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( iFound == 0 ) return false;
|
|
|
|
|
|
2015-08-06 20:50:22 +00:00
|
|
|
|
int i = (rand()%(iFound/2))*2;
|
|
|
|
|
int start = found[i+1];
|
2012-06-26 20:23:05 +00:00
|
|
|
|
i = found[i+0];
|
|
|
|
|
|
2015-08-06 20:50:22 +00:00
|
|
|
|
char* newScript = new char[m_len+strlen(names[i+1])+1];
|
2012-06-26 20:23:05 +00:00
|
|
|
|
strcpy(newScript, m_script);
|
2012-12-28 12:37:08 +00:00
|
|
|
|
delete[] m_script;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
m_script = newScript;
|
|
|
|
|
|
|
|
|
|
DeleteToken(m_script, start, strlen(names[i]));
|
|
|
|
|
InsertToken(m_script, start, names[i+1]);
|
|
|
|
|
m_len = strlen(m_script);
|
|
|
|
|
Compile(); // recompile with the virus
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Returns the number of the error.
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
int CScript::GetError()
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
return m_error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Returns the text of the error.
|
|
|
|
|
|
2013-12-02 23:11:26 +00:00
|
|
|
|
void CScript::GetError(std::string& error)
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
if ( m_error == 0 )
|
|
|
|
|
{
|
2013-12-02 23:11:26 +00:00
|
|
|
|
error.clear();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ( m_error == ERR_OBLIGATORYTOKEN )
|
|
|
|
|
{
|
2013-12-02 23:11:26 +00:00
|
|
|
|
std::string s;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
GetResource(RES_ERR, m_error, s);
|
2013-12-02 23:11:26 +00:00
|
|
|
|
error = StrUtils::Format(s.c_str(), m_token);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
else if ( m_error < 1000 )
|
|
|
|
|
{
|
2013-12-02 23:11:26 +00:00
|
|
|
|
GetResource(RES_ERR, m_error, error);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2013-12-02 23:11:26 +00:00
|
|
|
|
GetResource(RES_CBOT, m_error, error);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// New program.
|
|
|
|
|
|
2012-09-18 20:33:28 +00:00
|
|
|
|
void CScript::New(Ui::CEdit* edit, const char* name)
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
char res[100];
|
|
|
|
|
char text[100];
|
|
|
|
|
char script[500];
|
|
|
|
|
char buffer[500];
|
|
|
|
|
char *sf;
|
|
|
|
|
int cursor1, cursor2, len, i, j;
|
|
|
|
|
|
2013-12-02 23:11:26 +00:00
|
|
|
|
std::string resStr;
|
|
|
|
|
GetResource(RES_TEXT, RT_SCRIPT_NEW, resStr);
|
|
|
|
|
strcpy(res, resStr.c_str());
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( name[0] == 0 ) strcpy(text, res);
|
|
|
|
|
else strcpy(text, name);
|
|
|
|
|
|
|
|
|
|
sprintf(script, "extern void object::%s()\n{\n\t\n\t\n\t\n}\n", text);
|
|
|
|
|
edit->SetText(script, false);
|
|
|
|
|
|
|
|
|
|
if ( strcmp(text, res) == 0 )
|
|
|
|
|
{
|
|
|
|
|
cursor1 = 20;
|
|
|
|
|
cursor2 = 20+strlen(text); // update "New"
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2012-09-10 21:29:38 +00:00
|
|
|
|
if ( edit->GetAutoIndent() )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
cursor1 = 20+strlen(text)+6;
|
|
|
|
|
cursor2 = cursor1; // cursor in { }
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cursor1 = 20+strlen(text)+8;
|
|
|
|
|
cursor2 = cursor1; // cursor in { }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
edit->SetCursor(cursor2, cursor1);
|
|
|
|
|
edit->ShowSelect();
|
2015-07-15 17:08:45 +00:00
|
|
|
|
m_interface->SetFocus(edit);
|
2012-06-26 21:01:17 +00:00
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
sf = m_main->GetScriptFile();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( sf[0] != 0 ) // Load an empty program specific?
|
|
|
|
|
{
|
2014-06-20 21:41:38 +00:00
|
|
|
|
std::string filename = sf;
|
2014-06-22 19:30:23 +00:00
|
|
|
|
CInputStream stream;
|
|
|
|
|
stream.open(filename);
|
|
|
|
|
|
|
|
|
|
if (stream.is_open())
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2014-06-22 19:30:23 +00:00
|
|
|
|
len = stream.size();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
if ( len > 500-1 ) len = 500-1;
|
2014-06-22 19:30:23 +00:00
|
|
|
|
stream.read(buffer, len);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
buffer[len] = 0;
|
2014-06-22 19:30:23 +00:00
|
|
|
|
stream.close();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
cursor1 = 0;
|
|
|
|
|
i = 0;
|
|
|
|
|
j = 0;
|
|
|
|
|
while ( true )
|
|
|
|
|
{
|
|
|
|
|
if ( buffer[i] == 0 ) break;
|
|
|
|
|
|
|
|
|
|
if ( buffer[i] == '\r' )
|
|
|
|
|
{
|
|
|
|
|
i ++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
if ( buffer[i] == '\t' && edit->GetAutoIndent() )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
i ++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( buffer[i+0] == '%' &&
|
|
|
|
|
buffer[i+1] == 's' )
|
|
|
|
|
{
|
|
|
|
|
strcpy(script+j, text);
|
|
|
|
|
j += strlen(text);
|
|
|
|
|
i += 2;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( buffer[i] == '#' )
|
|
|
|
|
{
|
|
|
|
|
cursor1 = j;
|
|
|
|
|
i ++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
script[j++] = buffer[i++];
|
|
|
|
|
}
|
|
|
|
|
script[j] = 0;
|
|
|
|
|
edit->SetText(script, false);
|
|
|
|
|
|
|
|
|
|
cursor2 = cursor1;
|
|
|
|
|
edit->SetCursor(cursor2, cursor1);
|
|
|
|
|
edit->ShowSelect();
|
2015-07-15 17:08:45 +00:00
|
|
|
|
m_interface->SetFocus(edit);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ColorizeScript(edit);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Provided a script for all parts.
|
|
|
|
|
|
2013-05-19 14:25:53 +00:00
|
|
|
|
bool CScript::SendScript(const char* text)
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2013-05-19 14:25:53 +00:00
|
|
|
|
/*m_len = strlen(text);
|
2012-12-28 12:37:08 +00:00
|
|
|
|
m_script = new char[m_len+1];
|
2012-06-26 20:23:05 +00:00
|
|
|
|
strcpy(m_script, text);
|
|
|
|
|
if ( !CheckToken() ) return false;
|
2013-05-19 14:25:53 +00:00
|
|
|
|
if ( !Compile() ) return false;*/
|
|
|
|
|
|
|
|
|
|
Ui::CEdit* edit = m_interface->CreateEdit(Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f), 0, EVENT_EDIT9);
|
|
|
|
|
edit->SetMaxChar(Ui::EDITSTUDIOMAX);
|
|
|
|
|
edit->SetAutoIndent(m_engine->GetEditIndentMode());
|
|
|
|
|
edit->SetText(text, true);
|
|
|
|
|
GetScript(edit);
|
|
|
|
|
m_interface->DeleteControl(EVENT_EDIT9);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reads a script as a text file.
|
|
|
|
|
|
2012-09-15 16:50:51 +00:00
|
|
|
|
bool CScript::ReadScript(const char* filename)
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2012-09-10 21:29:38 +00:00
|
|
|
|
Ui::CEdit* edit;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
2014-06-22 19:30:23 +00:00
|
|
|
|
if (!CResourceManager::Exists(filename)) return false;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
2012-12-28 12:37:08 +00:00
|
|
|
|
delete[] m_script;
|
|
|
|
|
m_script = nullptr;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
edit = m_interface->CreateEdit(Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f), 0, EVENT_EDIT9);
|
2012-09-10 21:29:38 +00:00
|
|
|
|
edit->SetMaxChar(Ui::EDITSTUDIOMAX);
|
|
|
|
|
edit->SetAutoIndent(m_engine->GetEditIndentMode());
|
2014-06-20 21:41:38 +00:00
|
|
|
|
edit->ReadText(filename);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
GetScript(edit);
|
|
|
|
|
m_interface->DeleteControl(EVENT_EDIT9);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Writes a script as a text file.
|
|
|
|
|
|
2012-09-15 16:50:51 +00:00
|
|
|
|
bool CScript::WriteScript(const char* filename)
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2012-09-10 21:29:38 +00:00
|
|
|
|
Ui::CEdit* edit;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
2012-12-28 12:37:08 +00:00
|
|
|
|
if ( m_script == nullptr )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2015-03-29 12:21:02 +00:00
|
|
|
|
CResourceManager::Remove(filename);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
edit = m_interface->CreateEdit(Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f), 0, EVENT_EDIT9);
|
2012-09-10 21:29:38 +00:00
|
|
|
|
edit->SetMaxChar(Ui::EDITSTUDIOMAX);
|
|
|
|
|
edit->SetAutoIndent(m_engine->GetEditIndentMode());
|
2012-06-26 20:23:05 +00:00
|
|
|
|
edit->SetText(m_script);
|
2014-06-20 21:41:38 +00:00
|
|
|
|
edit->WriteText(filename);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
m_interface->DeleteControl(EVENT_EDIT9);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Reads a stack of script by execution as a file.
|
|
|
|
|
|
|
|
|
|
bool CScript::ReadStack(FILE *file)
|
|
|
|
|
{
|
|
|
|
|
int nb;
|
|
|
|
|
|
|
|
|
|
fRead(&nb, sizeof(int), 1, file);
|
|
|
|
|
fRead(&m_ipf, sizeof(int), 1, file);
|
|
|
|
|
fRead(&m_errMode, sizeof(int), 1, file);
|
|
|
|
|
|
|
|
|
|
if ( m_botProg == 0 ) return false;
|
|
|
|
|
if ( !m_botProg->RestoreState(file) ) return false;
|
2012-06-26 21:01:17 +00:00
|
|
|
|
|
2012-06-26 20:23:05 +00:00
|
|
|
|
m_bRun = true;
|
|
|
|
|
m_bContinue = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Writes a stack of script by execution as a file.
|
|
|
|
|
|
|
|
|
|
bool CScript::WriteStack(FILE *file)
|
|
|
|
|
{
|
|
|
|
|
int nb;
|
|
|
|
|
|
|
|
|
|
nb = 2;
|
|
|
|
|
fWrite(&nb, sizeof(int), 1, file);
|
|
|
|
|
fWrite(&m_ipf, sizeof(int), 1, file);
|
|
|
|
|
fWrite(&m_errMode, sizeof(int), 1, file);
|
|
|
|
|
|
|
|
|
|
return m_botProg->SaveState(file);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Compares two scripts.
|
|
|
|
|
|
|
|
|
|
bool CScript::Compare(CScript* other)
|
|
|
|
|
{
|
|
|
|
|
if ( m_len != other->m_len ) return false;
|
|
|
|
|
|
|
|
|
|
return ( strcmp(m_script, other->m_script) == 0 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Management of the file name when the script is saved.
|
|
|
|
|
|
|
|
|
|
void CScript::SetFilename(char *filename)
|
|
|
|
|
{
|
|
|
|
|
strcpy(m_filename, filename);
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-10 21:29:38 +00:00
|
|
|
|
char* CScript::GetFilename()
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
return m_filename;
|
|
|
|
|
}
|