2011-12-19 22:05:57 +01:00
/*
* This file is part of OpenTTD .
* OpenTTD 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 , version 2.
* OpenTTD 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 OpenTTD . If not , see < http : //www.gnu.org/licenses/>.
*/
/** @file script_text.cpp Implementation of ScriptText. */
# include "../../stdafx.h"
# include "../../string_func.h"
2013-06-27 21:57:41 +02:00
# include "../../strings_func.h"
2023-02-18 03:21:25 +01:00
# include "../../game/game_text.hpp"
2011-12-19 22:05:57 +01:00
# include "script_text.hpp"
2023-02-16 01:17:53 +01:00
# include "../script_fatalerror.hpp"
2011-12-19 22:05:57 +01:00
# include "../../table/control_codes.h"
2013-06-27 21:57:41 +02:00
# include "table/strings.h"
2014-04-23 22:13:33 +02:00
# include "../../safeguards.h"
2023-02-16 02:05:54 +01:00
RawText : : RawText ( const char * text ) : text ( text )
2014-04-25 17:40:32 +02:00
{
}
2011-12-21 15:55:28 +01:00
ScriptText : : ScriptText ( HSQUIRRELVM vm ) :
ZeroedMemoryAllocator ( )
2011-12-19 22:05:57 +01:00
{
2011-12-21 15:55:28 +01:00
int nparam = sq_gettop ( vm ) - 1 ;
if ( nparam < 1 ) {
2014-09-06 19:46:56 +02:00
throw sq_throwerror ( vm , " You need to pass at least a StringID to the constructor " ) ;
2011-12-21 15:55:28 +01:00
}
/* First resolve the StringID. */
SQInteger sqstring ;
if ( SQ_FAILED ( sq_getinteger ( vm , 2 , & sqstring ) ) ) {
2014-09-06 19:46:56 +02:00
throw sq_throwerror ( vm , " First argument must be a valid StringID " ) ;
2011-12-21 15:55:28 +01:00
}
this - > string = sqstring ;
/* The rest of the parameters must be arguments. */
for ( int i = 0 ; i < nparam - 1 ; i + + ) {
/* Push the parameter to the top of the stack. */
sq_push ( vm , i + 3 ) ;
if ( SQ_FAILED ( this - > _SetParam ( i , vm ) ) ) {
this - > ~ ScriptText ( ) ;
2014-09-06 19:46:56 +02:00
throw sq_throwerror ( vm , " Invalid parameter " ) ;
2011-12-21 15:55:28 +01:00
}
/* Pop the parameter again. */
sq_pop ( vm , 1 ) ;
}
2011-12-19 22:05:57 +01:00
}
SQInteger ScriptText : : _SetParam ( int parameter , HSQUIRRELVM vm )
{
if ( parameter > = SCRIPT_TEXT_MAX_PARAMETERS ) return SQ_ERROR ;
switch ( sq_gettype ( vm , - 1 ) ) {
case OT_STRING : {
const SQChar * value ;
sq_getstring ( vm , - 1 , & value ) ;
2023-02-18 02:29:50 +01:00
this - > param [ parameter ] = StrMakeValid ( value ) ;
2011-12-19 22:05:57 +01:00
break ;
}
case OT_INTEGER : {
SQInteger value ;
sq_getinteger ( vm , - 1 , & value ) ;
2023-02-18 02:29:50 +01:00
this - > param [ parameter ] = value ;
2011-12-19 22:05:57 +01:00
break ;
}
case OT_INSTANCE : {
2019-04-10 23:07:06 +02:00
SQUserPointer real_instance = nullptr ;
2011-12-19 22:05:57 +01:00
HSQOBJECT instance ;
sq_getstackobj ( vm , - 1 , & instance ) ;
/* Validate if it is a GSText instance */
sq_pushroottable ( vm ) ;
2014-09-06 19:46:56 +02:00
sq_pushstring ( vm , " GSText " , - 1 ) ;
2011-12-19 22:05:57 +01:00
sq_get ( vm , - 2 ) ;
sq_pushobject ( vm , instance ) ;
if ( sq_instanceof ( vm ) ! = SQTrue ) return SQ_ERROR ;
sq_pop ( vm , 3 ) ;
/* Get the 'real' instance of this class */
2021-06-16 21:10:41 +02:00
sq_getinstanceup ( vm , - 1 , & real_instance , nullptr ) ;
2019-04-10 23:07:06 +02:00
if ( real_instance = = nullptr ) return SQ_ERROR ;
2011-12-19 22:05:57 +01:00
ScriptText * value = static_cast < ScriptText * > ( real_instance ) ;
2023-02-28 17:13:38 +01:00
this - > param [ parameter ] = ScriptTextRef ( value ) ;
2011-12-19 22:05:57 +01:00
break ;
}
default : return SQ_ERROR ;
}
if ( this - > paramc < = parameter ) this - > paramc = parameter + 1 ;
return 0 ;
}
SQInteger ScriptText : : SetParam ( HSQUIRRELVM vm )
{
if ( sq_gettype ( vm , 2 ) ! = OT_INTEGER ) return SQ_ERROR ;
SQInteger k ;
sq_getinteger ( vm , 2 , & k ) ;
if ( k > SCRIPT_TEXT_MAX_PARAMETERS ) return SQ_ERROR ;
if ( k < 1 ) return SQ_ERROR ;
k - - ;
return this - > _SetParam ( k , vm ) ;
}
SQInteger ScriptText : : AddParam ( HSQUIRRELVM vm )
{
SQInteger res ;
res = this - > _SetParam ( this - > paramc , vm ) ;
if ( res ! = 0 ) return res ;
/* Push our own instance back on top of the stack */
sq_push ( vm , 1 ) ;
return 1 ;
}
SQInteger ScriptText : : _set ( HSQUIRRELVM vm )
{
int32 k ;
if ( sq_gettype ( vm , 2 ) = = OT_STRING ) {
2014-09-06 19:30:33 +02:00
const SQChar * key_string ;
sq_getstring ( vm , 2 , & key_string ) ;
2021-05-29 15:18:51 +02:00
StrMakeValidInPlace ( const_cast < char * > ( key_string ) ) ;
2011-12-19 22:05:57 +01:00
if ( strncmp ( key_string , " param_ " , 6 ) ! = 0 | | strlen ( key_string ) > 8 ) return SQ_ERROR ;
k = atoi ( key_string + 6 ) ;
} else if ( sq_gettype ( vm , 2 ) = = OT_INTEGER ) {
SQInteger key ;
sq_getinteger ( vm , 2 , & key ) ;
k = ( int32 ) key ;
} else {
return SQ_ERROR ;
}
if ( k > SCRIPT_TEXT_MAX_PARAMETERS ) return SQ_ERROR ;
if ( k < 1 ) return SQ_ERROR ;
k - - ;
return this - > _SetParam ( k , vm ) ;
}
2023-02-16 02:05:54 +01:00
const std : : string ScriptText : : GetEncodedText ( )
2011-12-19 22:05:57 +01:00
{
static char buf [ 1024 ] ;
2013-02-08 21:34:27 +01:00
int param_count = 0 ;
this - > _GetEncodedText ( buf , lastof ( buf ) , param_count ) ;
2023-03-05 17:00:16 +01:00
if ( param_count > SCRIPT_TEXT_MAX_PARAMETERS ) throw Script_FatalError ( fmt : : format ( " {}: Too many parameters " , GetGameStringName ( this - > string ) ) ) ;
2023-02-16 01:17:53 +01:00
return buf ;
2011-12-19 22:05:57 +01:00
}
2013-02-08 21:34:27 +01:00
char * ScriptText : : _GetEncodedText ( char * p , char * lastofp , int & param_count )
2011-12-19 22:05:57 +01:00
{
p + = Utf8Encode ( p , SCC_ENCODED ) ;
p + = seprintf ( p , lastofp , " %X " , this - > string ) ;
2023-02-18 03:21:25 +01:00
const StringParams & params = GetGameStringParams ( this - > string ) ;
2023-03-05 17:00:16 +01:00
const std : : string & name = GetGameStringName ( this - > string ) ;
2023-02-18 03:21:25 +01:00
int cur_idx = 0 ;
for ( const StringParam & cur_param : params ) {
2023-03-05 17:00:16 +01:00
if ( cur_idx > = this - > paramc ) throw Script_FatalError ( fmt : : format ( " {}: Not enough parameters " , name ) ) ;
2023-02-18 03:21:25 +01:00
switch ( cur_param . type ) {
case StringParam : : RAW_STRING :
2023-03-05 17:00:16 +01:00
if ( ! std : : holds_alternative < std : : string > ( this - > param [ cur_idx ] ) ) throw Script_FatalError ( fmt : : format ( " {}: Parameter {} expects a raw string " , name , cur_idx ) ) ;
2023-02-18 03:21:25 +01:00
p + = seprintf ( p , lastofp , " : \" %s \" " , std : : get < std : : string > ( this - > param [ cur_idx + + ] ) . c_str ( ) ) ;
break ;
case StringParam : : STRING : {
2023-03-05 17:00:16 +01:00
if ( ! std : : holds_alternative < ScriptTextRef > ( this - > param [ cur_idx ] ) ) throw Script_FatalError ( fmt : : format ( " {}: Parameter {} expects a substring " , name , cur_idx ) ) ;
2023-02-18 03:21:25 +01:00
int count = 1 ; // 1 because the string id is included in consumed parameters
p + = seprintf ( p , lastofp , " : " ) ;
p = std : : get < ScriptTextRef > ( this - > param [ cur_idx + + ] ) - > _GetEncodedText ( p , lastofp , count ) ;
2023-03-05 17:00:16 +01:00
if ( count ! = cur_param . consumes ) throw Script_FatalError ( fmt : : format ( " {}: Parameter {} substring consumes {}, but expected {} to be consumed " , name , cur_idx , count - 1 , cur_param . consumes - 1 ) ) ;
2023-02-18 03:21:25 +01:00
break ;
}
default :
2023-03-05 17:00:16 +01:00
if ( cur_idx + cur_param . consumes > this - > paramc ) throw Script_FatalError ( fmt : : format ( " {}: Not enough parameters " , name ) ) ;
2023-02-18 03:21:25 +01:00
for ( int i = 0 ; i < cur_param . consumes ; i + + ) {
2023-03-05 17:00:16 +01:00
if ( ! std : : holds_alternative < SQInteger > ( this - > param [ cur_idx ] ) ) throw Script_FatalError ( fmt : : format ( " {}: Parameter {} expects an integer " , name , cur_idx ) ) ;
2023-02-18 03:21:25 +01:00
p + = seprintf ( p , lastofp , " : " OTTD_PRINTFHEX64 , std : : get < SQInteger > ( this - > param [ cur_idx + + ] ) ) ;
}
2011-12-19 22:05:57 +01:00
}
2023-02-18 03:21:25 +01:00
param_count + = cur_param . consumes ;
2011-12-19 22:05:57 +01:00
}
return p ;
}
2013-06-27 21:57:41 +02:00
2023-02-16 02:05:54 +01:00
const std : : string Text : : GetDecodedText ( )
2013-06-27 21:57:41 +02:00
{
2023-02-16 01:17:53 +01:00
const std : : string & encoded_text = this - > GetEncodedText ( ) ;
2013-06-27 21:57:41 +02:00
static char buf [ 1024 ] ;
: : SetDParamStr ( 0 , encoded_text ) ;
2013-06-27 22:07:09 +02:00
: : GetString ( buf , STR_JUST_RAW_STRING , lastof ( buf ) ) ;
return buf ;
2013-06-27 21:57:41 +02:00
}