//This file was generated by the LASAL2 CodeGenerator  -- 
//Please, do not edit this file (it might be overwritten by the next generator run)
//{{LSL_DECLARATION

(*!
<Class
	Name               = "StringInternal"
	Revision           = "1.85"
	GUID               = "{2C12408A-7CCA-458A-912B-98C634EE4BD9}"
	RealtimeTask       = "false"
	CyclicTask         = "false"
	BackgroundTask     = "false"
	Sigmatek           = "true"
	OSInterface        = "false"
	HighPriority       = "false"
	Automatic          = "false"
	UpdateMode         = "Prescan"
	IconPath           = ".\Class\StringInternal\StringInternal.ico"
	SharedCommandTable = "true"
	Objectsize         = "(284,120)"
	Comment            = "handels character strings">
	<Channels>
		<Server Name="Data" WriteProtected="false">
		</Server>
		<Client Name="DataBuffer" Required="true" Internal="false" Comment="some extern storage mechanism (retentive or not)"/>
		<Client Name="SingleRealloc" Required="false" Internal="false" DefValue="1" Comment="This client is used for optimized memory handling!&#13;&#10;1..Optimized memory handling -&gt; realloc only if string grows (default)&#13;&#10;0..Normal memory handling -&gt; the needed memory is allocated"/>
	</Channels>
	<Dependencies>
		<Files>
			<File Path=".\Class\StringInternal\StringDefs.h" Include="false"/>
		</Files>
	</Dependencies>
	<RevDoku>
		<Owner Company="Sigmatek GmbH &amp; Co KG"/>
		<Dokumentation Revision="1.85" Date="2021-09-01" Author="kolott" Company="Sigmatek" Description="8D-3289: Bugfix in method TxtToUni()"/>
		<Dokumentation Revision="1.84" Date="2020-05-28" Author="kolott" Company="Sigmatek" Description="DEVVIS-37, sa57324: Support of utf8-encoded strings added"/>
		<Dokumentation Revision="1.83" Date="2020-01-30" Author="kolott" Company="Sigmatek" Description="New method added: TxtGetAscii().&#13;&#10;Better icon added."/>
		<Dokumentation Revision="1.82" Date="2016-11-16" Author="kolott" Company="Sigmatek" Description="Bugfix: Fix of possible bug when using StrCmp, StrICmp and StrCat (sa36002)&#13;&#10;Betterment: New methods, beginning with &quot;Obj&quot; und &quot;Txt&quot; are added."/>
		<Dokumentation Revision="1.81" Date="2016-01-25" Author="hubchr" Company="Sigmatek GmbH &amp; Co KG" Description="Bugfix:&#13;&#10;It is now possible to write a single CHAR character with the Method WriteDataOffUni();"/>
		<Dokumentation Revision="1.80" Date="2015-09-25" Author="Fimluc" Company="Sigmatek GmbH &amp; Co KG" Description="All global functions virtual"/>
		<Dokumentation Revision="1.71" Date="2014-07-30" Author="HlaWol" Company="Sigmatek GmbH &amp; Co KG" Description="SA28794: AddTermination() returned pointer of GetData() has to be validated&#13;&#10;"/>
		<Dokumentation Revision="1.70" Date="2014-02-20" Author="spimar" Company="Sigmatek GmbH &amp; Co KG" Description="Check for valid pointer"/>
		<Dokumentation Revision="1.60" Date="2013-11-06" Author="feshar" Company="Sigmatek GmbH &amp; Co KG" Description="Set the init value. (Set a new RamEx object to length 0.)"/>
		<Dokumentation Revision="1.50" Date="2013-09-23" Author="spimar" Company="Sigmatek GmbH &amp; Co KG" Description="Check valid pointer after alloc;"/>
		<Dokumentation Revision="1.40" Date="2013-07-12" Author="spimar&#13;&#10;kolott" Company="Sigmatek" Description="Check if there is already data stored in object;&#13;&#10;ARM-Ready"/>
		<Dokumentation Revision="1.30" Date="2013-01-07" Author="spimar&#13;&#10;fesgue" Company="Sigmatek" Description="Improvement: &#13;&#10;-added comments in code;&#13;&#10;-added a check if the pointer is valid (WriteDataOffUni);&#13;&#10;Bugfix: Memory fault in WriteDataOffUni();"/>
		<Dokumentation Revision="1.20" Date="2012-11-21" Author="spimar" Company="Sigmatek" Description="Bugfix with client SingleRealloc;&#13;&#10;- The termination of the string was set on the wrong place in case of client is set to 1;&#13;&#10;- Added comments in code;"/>
		<Dokumentation Revision="1.10" Date="2012-11-05" Author="spimar" Company="Sigmatek" Description="New client (SingleRealloc) which is used for an optimized memory handling!"/>
		<Dokumentation Revision="1.7" Date="2012-09-24" Author="feshar" Company="Sigmatek" Description="String Initvalue was not set for RamEx objects with file storage."/>
		<Dokumentation Revision="1.6" Date="2012-08-02" Author="spimar" Company="Sigmatek" Description="Added a new method named WriteDataOffUni with which one it is possible, to hand over the size (Ascii or Uni), without set the identifier in front of the string!"/>
		<Dokumentation Revision="1.5" Date="2012-05-03" Author="feshar" Company="Sigmatek" Description="Changes for RamEx file storage."/>
		<Dokumentation Revision="1.4" Date="2011-09-28" Author="SpiMar" Company="Sigmatek" Description="Corrected a comment;"/>
		<Dokumentation Revision="1.3" Date="2011-09-28" Author="SpiMar" Company="Sigmatek" Description="The input and output parameters of the server write methods  are now fitted to the datatype of the server;"/>
	</RevDoku>
	<Network Name="StringInternal">
		<!-- List of Components in this network -->
		<Components>
			<Object
				Name       = "_base"
				GUID       = "{6CBDDE57-D222-420A-BC45-D2266096244E}"
				Class      = "VirtualBaseInit"
				Position   = "(570,330)"
				Visualized = "true">
				<Channels>
					<Server Name="Data"/>
				</Channels>
			</Object>
		</Components>
		<Comments>
		</Comments>
		<!-- List of Connections in this network -->
		<Connections>
			<Connection Source="this.Data" Destination="_base.Data" Vertices="(1042,210),(870,420),"/>
		</Connections>
		<!-- Headerfiles -->
		<Options>
		</Options>
	</Network>
</Class>
*)
#pragma using VirtualBaseInit

StringInternal : CLASS
: VirtualBaseInit
  //Servers:
  //Clients:
	DataBuffer 	: CltChCmd_MerkerEx;
	SingleRealloc 	: CltCh_DINT;
  //Variables:
		m_udCRC 	: UDINT;			//! <Variable Comment="for faster detection of changes" Name="m_udCRC"/>
		m_usSize 	: USINT;			//! <Variable Comment="size of one character" Name="m_usSize"/>
		m_udlen 	: UDINT;
  //Functions:
				//! <Function Comment=" to have a defined state after configuration&#13;&#10; calculate the CRC&#13;&#10;Die CRC wird am Anfang berechnet, um diesen Wert zu initialisieren&#13;&#10;" Name="Init"/>
	FUNCTION VIRTUAL GLOBAL Init;
				//! <Function Comment=" returns the length of the raw data (without termination-0)&#13;&#10;liefert die Länge der Strings-Rohdaten ohne Abschluß-Null&#13;&#10;" Name="GetLength"/>
	FUNCTION VIRTUAL GLOBAL GetLength
		VAR_OUTPUT
			udLen 	: UDINT;			//! <Variable Comment="number of characters" Name="GetLength.udLen"/>
		END_VAR;
				//! <Function Comment="The function extracts the given amount of bytes from a string-buffer.&#13;&#10;udAt specifies the starting position. pData is a pointer to a destination&#13;&#10;buffer, which has to be big enough to contain the extracted part.&#13;&#10;Die Funktion kopiert die angegebene Anzahl von Bytes ab dem Offset udAt&#13;&#10;aus dem String in einen zur Verfügung gestellten Ziel-Puffer. Dieser&#13;&#10;Puffer muß ausreichend groß sein, um den extrahierten Teil aufnehmen&#13;&#10;zu können.&#13;&#10;[&gt;udSize] Anzahl der Bytes, die kopiert werden sollen&#13;&#10;" Name="GetDataAt"/>
	FUNCTION VIRTUAL GLOBAL GetDataAt
		VAR_INPUT
			pData 	: ^USINT;			//! <Variable Comment="Zeigt auf die Quelldaten" Name="GetDataAt.pData"/>
			udSize 	: UDINT;			//! <Variable Comment=" number of bytes to extract" Name="GetDataAt.udSize"/>
			udAt 	: UDINT;			//! <Variable Comment="offset within the string-buffer" Name="GetDataAt.udAt"/>
		END_VAR;
				//! <Function Comment="Initialisiert den String mit konstanten Daten, z.B. aus einer Tabelle&#13;&#10;Der String wird als ASCII-String interpretiert.&#13;&#10;Initializes a string object with constant data (i.e. from a table)&#13;&#10;The string is assumed to be an ASCII-string&#13;&#10;" Name="InitFromTable"/>
	FUNCTION VIRTUAL GLOBAL InitFromTable
		VAR_INPUT
			udLen 	: UDINT;			//! <Variable Comment="Länge der Initialisierungsdaten in Bytes" Name="InitFromTable.udLen"/>
			pData 	: ^USINT;			//! <Variable Comment="pointer to source" Name="InitFromTable.pData"/>
		END_VAR;
				//! <Function Comment=" The function doesn&apos;t provide default functionality&#13;&#10; Please overwrite it for derived classes.&#13;&#10; Die Funktion stellt keine Standard-Implementierung dar. Sie muß für abgeleitete&#13;&#10; Klassen überschrieben werden.&#13;&#10;[&gt;udOff] Offset innerhalb des internen Datenpuffers, auf den die Daten kopiert werden sollen&#13;&#10;" Name="WriteDataOff"/>
	FUNCTION VIRTUAL GLOBAL WriteDataOff
		VAR_INPUT
			udLen 	: UDINT;			//! <Variable Comment=" Length of initialization data block" Name="WriteDataOff.udLen"/>
			udOff 	: UDINT;			//! <Variable Comment=" form this offset the data is read" Name="WriteDataOff.udOff"/>
			pData 	: ^USINT;
		END_VAR;
				//! <Function Comment=" The function returns a CRC of the string&apos;s data buffer&#13;&#10; This CRC is recalculated everytime the contents are changed&#13;&#10;Die Funktion liefert eine Prüfsumme über den Stringinhalt. Diese CRC&#13;&#10;wird bei jeder String-Änderung angepaßt.&#13;&#10;[&lt;udCRC]32-bit-CRC&#13;&#10;" Name="GetCRC"/>
	FUNCTION VIRTUAL GLOBAL GetCRC
		VAR_OUTPUT
			udCRC 	: UDINT;			//! <Variable Comment="32-bit-CRC" Name="GetCRC.udCRC"/>
		END_VAR;
				//! <Function Comment="Kopiert den Inhalt des übergebenen Strings in das eigene String-Objekt.&#13;&#10;Die Inhalte beider Strings sind danach ident.&#13;&#10; Copies the raw data from the passed string to the current one.&#13;&#10; The contents of the data blocks of both strings are the same&#13;&#10; afterwards.&#13;&#10;" Name="StrCpy"/>
	FUNCTION VIRTUAL GLOBAL StrCpy
		VAR_INPUT
			pSrc 	: ^StringInternal;			//! <Variable Comment="pointer to string to append" Name="StrCpy.pSrc"/>
		END_VAR;
				//! <Function Comment="The passed string is appended to the current string&#13;&#10;If the strings styles differ (ASCII/UNICODE), then the passed string&#13;&#10;will be converted to the current string&apos;s style prior to appending it.&#13;&#10;Der übergebene String wird an den eigenen String hinten angehängt.&#13;&#10;Wenn die Strings unterschiedliche Typen haben (ASCII/UNICODE), dann&#13;&#10;wird der übergebene String zuerst angepaßt, und dann erst angehängt.&#13;&#10;" Name="StrCat"/>
	FUNCTION VIRTUAL GLOBAL StrCat
		VAR_INPUT
			pSrc 	: ^StringInternal;			//! <Variable Comment="Zeiger auf den anzuhängenden String" Name="StrCat.pSrc"/>
		END_VAR;
				//! <Function Comment="Der String wird auf einen Leerstring gesetzt.&#13;&#10; the string contents of the string are set to an empty string&#13;&#10;" Name="Clear"/>
	FUNCTION VIRTUAL GLOBAL Clear;
				//! <Function Comment=" Every time the string contents are changed, this function&#13;&#10; should be called to recalculate the check sum.&#13;&#10;Diese Funktion muß nach jeder String-Änderung aufgerufen werden,&#13;&#10;um die Prüfsumme über den Stringinhalt zu aktualisieren.&#13;&#10;" Name="CalcCRC"/>
	FUNCTION CalcCRC;
				//! <Function Comment="The two strings are compared case sensitive. The function returns 0&#13;&#10;if the strings are exactly the same, otherwise it returns &lt;&gt;0.&#13;&#10;If one of the two strings is in UNICODE, then the other is converted&#13;&#10;to UNICODE, too, before the comparison.&#13;&#10;None of the strings is changed!&#13;&#10;Die beiden Strings werden mit Unterscheidung von Groß/Kleinschreibung&#13;&#10;verglichen. Die Funktion liefert 0, wenn die beiden Strings exakt&#13;&#10;gleich sind, sonst &lt;&gt;0.&#13;&#10;Wenn einer der beiden Strings UNICODE-Zeichen enthält, dann wird auch&#13;&#10;der andere String auf UNICODE transformiert, bevor der Vergleich&#13;&#10;durchgeführt wird.&#13;&#10;Keiner der beiden Strings wird dadurch verändert!&#13;&#10;" Name="StrCmp"/>
	FUNCTION VIRTUAL GLOBAL StrCmp
		VAR_INPUT
			pStr 	: ^StringInternal;			//! <Variable Comment="Zeiger auf den Zielstring" Name="StrCmp.pStr"/>
		END_VAR
		VAR_OUTPUT
			udNotEqual 	: UDINT;			//! <Variable Comment="0 .. equal, &lt;&gt; 0 .. not equal" Name="StrCmp.udNotEqual"/>
		END_VAR;
				//! <Function Comment="The two strings are compared case insensitive. The function will return 0 if the&#13;&#10;strings are the same, otherwise it returns &lt;&gt;0.&#13;&#10;Comparing &quot;Abc&quot; with &quot;Abc&quot; or &quot;Abc&quot; with &quot;ABC&quot; will result in 0,&#13;&#10;comparing &quot;PLC&quot; with &quot;SPS&quot; will result in a value different from 0&#13;&#10;Die beiden Strings werden ohne Berücksichtigung der Groß/Kleinschreibung&#13;&#10;miteinander verglichen. Die Funktion liefert für gleiche Strings 0,&#13;&#10;ansonsten einen Wert &lt;&gt; 0.&#13;&#10;Der Vergleich von &quot;Abc&quot; mit &quot;Abc&quot; oder von &quot;Abc&quot; mit &quot;ABC&quot; liefert 0,&#13;&#10;der Vergleich &quot;PLC&quot; mit &quot;SPS&quot; liefert einen Wert ungleich 0.&#13;&#10;" Name="StriCmp"/>
	FUNCTION VIRTUAL GLOBAL StriCmp
		VAR_INPUT
			pStr 	: ^StringInternal;			//! <Variable Comment="pointer to the destination string" Name="StriCmp.pStr"/>
		END_VAR
		VAR_OUTPUT
			udNotEqual 	: UDINT;			//! <Variable Comment="0 .. gleich, &lt;&gt; 0 .. ungleich" Name="StriCmp.udNotEqual"/>
		END_VAR;
				//! <Function Comment="Der linke Teil des Strings wird in den Zielstring kopiert. Wenn&#13;&#10;die angegebene Zeichenzahl größer als die Stringlänge ist, wird&#13;&#10;nur der ursprüngliche String kopiert.&#13;&#10;The left part of the string is copied to the specified string object. If udCnt exceeds&#13;&#10;the string length, only the string contents are copied&#13;&#10;" Name="Left"/>
	FUNCTION VIRTUAL GLOBAL Left
		VAR_INPUT
			udCnt 	: UDINT;			//! <Variable Comment="Anzahl der zu kopierenden Zeichen" Name="Left.udCnt"/>
			pStr 	: ^StringInternal;
		END_VAR;
				//! <Function Comment="Die Funktion kopiert die letzten udCnt Zeichen des Strings in den&#13;&#10;Zielstring. Wenn die angegebene Zeichenzahl größer als die String-&#13;&#10;länge ist, wird nur der ursprüngliche String kopiert.&#13;&#10;The function copies the specified number of characters to the destination string. If&#13;&#10;the specified number exceeds the string length, only the string contents are copied.&#13;&#10;" Name="Right"/>
	FUNCTION VIRTUAL GLOBAL Right
		VAR_INPUT
			udCnt 	: UDINT;			//! <Variable Comment="number of characters to extract" Name="Right.udCnt"/>
			pStr 	: ^StringInternal;
		END_VAR;
				//! <Function Comment="All lower case letters are converted to upper case letters. The&#13;&#10;string object itself will be changed.&#13;&#10;Alle Kleinbuchstaben werden in Großbuchstaben konvertiert. Durch diese&#13;&#10;Funktion wird der String selbst geändert.&#13;&#10;" Name="StrUpr"/>
	FUNCTION VIRTUAL GLOBAL StrUpr;
				//! <Function Comment="All characters of a UNICODE-string are converted to ASCII-characters.&#13;&#10;If a character can not be transformed to ASCII-code, it will be replaced&#13;&#10;by a SPACE-character (0x20).&#13;&#10;Die Zeichen eines UNICODE-STrings werden in ASCII-Code gewandelt. Wenn&#13;&#10;sich ein Zeichen nicht auf ASCII-Code abbilden läßt, dann wird es durch&#13;&#10;ein Leerzeichen (0x20) ersetzt.&#13;&#10;" Name="ToAscii"/>
	FUNCTION VIRTUAL GLOBAL ToAscii;
				//! <Function Comment="All characters of an ASCII-string are converted to UNICODE.&#13;&#10;Alle Zeichen eines ASCII-Strings werden auf UNICODE übersetzt.&#13;&#10;" Name="ToUniCode"/>
	FUNCTION VIRTUAL GLOBAL ToUniCode;
				//! <Function Comment="All upper case letters are converted to lower case letters. The&#13;&#10;string object itself will be changed.&#13;&#10;Alle Großbuchstaben werden in Kleinbuchstaben konvertiert. Durch diese&#13;&#10;Funktion wird der String selbst geändert.&#13;&#10;" Name="StrLwr"/>
	FUNCTION VIRTUAL GLOBAL StrLwr;
				//! <Function Comment="The function searches for the given character in its string-buffer.&#13;&#10;It returns -1 if the character was not found, otherwise the index&#13;&#10;of the 1st matching character.&#13;&#10;Die Funktion sucht im String-Puffer nach dem angegebenen Zeichen.&#13;&#10;Sie liefert -1, wenn das Zeichen nicht gefunden wurde, ansonsten&#13;&#10;den Index des ersten übereinstimmenden Zeichens.&#13;&#10;[&gt;uiChar] Zeichen, nach dem gesucht werden soll&#13;&#10;" Name="StrChr"/>
	FUNCTION VIRTUAL GLOBAL StrChr
		VAR_INPUT
			uiChar 	: UINT;			//! <Variable Comment=" character to search for" Name="StrChr.uiChar"/>
		END_VAR
		VAR_OUTPUT
			udPosition 	: UDINT;
		END_VAR;
				//! <Function Comment="Checks, if the string is terminated with a 0-character. If not, &#13;&#10;a 0-character is appended. The string length is not changed by&#13;&#10;this function.&#13;&#10;Prüft, ob ein String mit 0 abgeschlossen ist. Wenn nicht, dann&#13;&#10;wird hier ein &apos;\0&apos;-Zeichen angehängt. Die Stringlänge ändert sich dadurch &#13;&#10;nicht.&#13;&#10;" Name="AddTermination"/>
	FUNCTION AddTermination;
				//! <Function Comment="Returns the number of characters in the string.&#13;&#10;For ASCII - strings this is equal to the number of bytes, for&#13;&#10;Unicode - strings it&apos;s just the half of it.&#13;&#10;The string length does not include the terminating zero.&#13;&#10;Liefert die Anzahl der Zeichen in einem String.&#13;&#10;Bei ASCII - Strings entspricht das genau der Anzahl an Daten - Bytes,&#13;&#10;bei Unicode - Strings ist es die Hälfte davon.&#13;&#10;Die Abschluß - Null ist nicht inkludiert.&#13;&#10;" Name="StrLen"/>
	FUNCTION VIRTUAL GLOBAL StrLen
		VAR_OUTPUT
			udLen 	: UDINT;			//! <Variable Comment="Anzahl der Zeichen" Name="StrLen.udLen"/>
		END_VAR;
				//! <Function Comment="Set a character to the String at a given position&#13;&#10;Setzt ein Zeichen an einer bestimmten Position des Strings&#13;&#10;" Name="SetDataAt"/>
	FUNCTION VIRTUAL GLOBAL SetDataAt
		VAR_INPUT
			pData 	: ^UINT;
			udAt 	: UDINT;			//! <Variable Comment="Position im String an der das Zeichen gesetzt wird" Name="SetDataAt.udAt"/>
		END_VAR
		VAR_OUTPUT
			ret_code 	: ConfStates;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;returns 1 for ASCII strings and 2 for Unicode strings&#13;&#10;" Name="GetCharSize"/>
	FUNCTION VIRTUAL GLOBAL GetCharSize
		VAR_OUTPUT
			usSize 	: USINT;			//! <Variable Comment="size of one character in the string (ASCII vs. Unicode)" Name="GetCharSize.usSize"/>
		END_VAR;
				//! <Function Comment=" The function doesn&apos;t provide default functionality&#13;&#10; Please overwrite it for derived classes.&#13;&#10; Die Funktion stellt keine Standard-Implementierung dar. Sie muß für abgeleitete&#13;&#10; Klassen überschrieben werden.&#13;&#10;[&gt;udOff] Offset innerhalb des internen Datenpuffers, auf den die Daten kopiert werden sollen&#13;&#10;" Name="WriteDataOffUni"/>
	FUNCTION VIRTUAL GLOBAL WriteDataOffUni
		VAR_INPUT
			udlen 	: UDINT;			//! <Variable Comment="length of initialization data in bytes" Name="WriteDataOffUni.udlen"/>
			udOff 	: UDINT;			//! <Variable Comment=" offset where data should be copied to" Name="WriteDataOffUni.udOff"/>
			pData 	: ^UINT;			//! <Variable Comment="contains the stringdata" Name="WriteDataOffUni.pData"/>
			usSize 	: USINT;			//! <Variable Comment="hand over the size of one character!&#13;&#10;1 = ASCII, 2 = Unicode" Name="WriteDataOffUni.usSize"/>
		END_VAR;
	
	FUNCTION TmpFree
		VAR_INPUT
			ppd 	: ^pVoid;
			phelp 	: ^void;
		END_VAR;
	
	FUNCTION TmpAlloc
		VAR_INPUT
			ppd 	: ^pVoid;
			bytesize 	: UDINT;
			phelp 	: ^void;
			helpsize 	: UDINT;
		END_VAR
		VAR_OUTPUT
			retcode 	: UDINT;
		END_VAR;
	
	FUNCTION AddDataIntern
		VAR_INPUT
			pData 	: ^USINT;
			udLen 	: UDINT;
			udOff 	: UDINT;
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;
		END_VAR;
	
	FUNCTION ToUniSequence
		VAR_INPUT
			pu 	: ^UINT;
			pa 	: ^USINT;
			length 	: UDINT;
			zerotermination 	: BOOL;
		END_VAR;
	
	FUNCTION ToAsciiSequence
		VAR_INPUT
			pa 	: ^USINT;
			pu 	: ^UINT;
			length 	: UDINT;
			zerotermination 	: BOOL;
		END_VAR;
	
	FUNCTION CmpUniAscii
		VAR_INPUT
			pu 	: ^UINT;
			pa 	: ^USINT;
			len 	: UDINT;
		END_VAR
		VAR_OUTPUT
			retcode 	: UDINT;
		END_VAR;
	
	FUNCTION ICmpUniUni
		VAR_INPUT
			pu1 	: ^UINT;
			pu2 	: ^UINT;
			len 	: UDINT;
		END_VAR
		VAR_OUTPUT
			retcode 	: UDINT;
		END_VAR;
	
	FUNCTION ICmpUniAscii
		VAR_INPUT
			pu 	: ^UINT;
			pa 	: ^USINT;
			len 	: UDINT;
		END_VAR
		VAR_OUTPUT
			retcode 	: UDINT;
		END_VAR;
	
	FUNCTION CatAtIntern
		VAR_INPUT
			isuni 	: UDINT;
			chroffset 	: UDINT;
			psrc 	: ^void;
			chrsize 	: UDINT;
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;
		END_VAR;
				//! <Function Comment="Concatenate string by using ASCII- or UNI-0-string. Given string will always be added at the given position in target string. At the end of given string target will end afterwards. Format (UNI, ASCII) of target will not change.&#13;&#10;Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;.&#13;&#10;chroffset .... offset where given string will be added.&#13;&#10;psrc .... ASCII- or UNI-0-string to add&#13;&#10;chrsize .... size of single character at given string (1=ASCII, 2=UNI)" Name="TxtCatAt"/>
	FUNCTION VIRTUAL GLOBAL TxtCatAt
		VAR_INPUT
			chroffset 	: UDINT;			//! <Variable Comment="offset where given string will be added." Name="TxtCatAt.chroffset"/>
			psrc 	: ^void;			//! <Variable Comment=" ASCII- or UNI-0-string to add" Name="TxtCatAt.psrc"/>
			chrsize 	: UDINT;			//! <Variable Comment="size of single character at given string (1=ASCII, 2=UNI)" Name="TxtCatAt.chrsize"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;			//! <Variable Comment="Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;." Name="TxtCatAt.retcode"/>
		END_VAR;
				//! <Function Comment="Concatenate string by using ASCII- or UNI-0-string. Given string will always be added at the end of target string. Format (UNI, ASCII) of target will not change.&#13;&#10;Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;.&#13;&#10;psrc .... ASCII- or UNI-0-string to add&#13;&#10;chrsize .... size of single character at given string (1=ASCII, 2=UNI)&#13;&#10;" Name="TxtCat"/>
	FUNCTION VIRTUAL GLOBAL TxtCat
		VAR_INPUT
			psrc 	: ^void;			//! <Variable Comment="ASCII- or UNI-0-string to add" Name="TxtCat.psrc"/>
			chrsize 	: UDINT;			//! <Variable Comment="size of single character at given string (1=ASCII, 2=UNI)" Name="TxtCat.chrsize"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;			//! <Variable Comment="Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;." Name="TxtCat.retcode"/>
		END_VAR;
				//! <Function Comment="Perform compare (case sensitive) between given string and content of object. Functionality is independent on style of object- and string-content (UNI, ASCII).&#13;&#10;Method will return 0 when given string and content of object are the same, on the other hand &lt;&gt;0&#13;&#10;psrc .... ASCII- or UNI-0-string to compare&#13;&#10;chrsize .... size of single character at given string (1=ASCII, 2=UNI)" Name="TxtCmp"/>
	FUNCTION VIRTUAL GLOBAL TxtCmp
		VAR_INPUT
			psrc 	: ^void;			//! <Variable Comment="ASCII- or UNI-0-string used for comparison" Name="TxtCmp.psrc"/>
			chrsize 	: UDINT;			//! <Variable Comment="size of single character at given string (1=ASCII, 2=UNI)" Name="TxtCmp.chrsize"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: UDINT;			//! <Variable Comment="Method will return 0 when given string and content of object are the same, on the other hand &lt;&gt;0" Name="TxtCmp.retcode"/>
		END_VAR;
				//! <Function Comment="Perform case insensitive comparison between given string and content of object. Functionality is independent on style of object- and string-content (UNI, ASCII).&#13;&#10;Method will return 0 when given string and content of object are the same, on the other hand &lt;&gt;0&#13;&#10;psrc .... ASCII- or UNI-0-string to compare&#13;&#10;chrsize .... size of single character at given string (1=ASCII, 2=UNI)" Name="TxtICmp"/>
	FUNCTION VIRTUAL GLOBAL TxtICmp
		VAR_INPUT
			psrc 	: ^void;			//! <Variable Comment="ASCII- or UNI-0-string to compare" Name="TxtICmp.psrc"/>
			chrsize 	: UDINT;			//! <Variable Comment="size of single character at given string (1=ASCII, 2=UNI)" Name="TxtICmp.chrsize"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: UDINT;			//! <Variable Comment="Method will return 0 when given string and content of object are the same, on the other hand &lt;&gt;0" Name="TxtICmp.retcode"/>
		END_VAR;
				//! <Function Comment="Get 0-terminated copy of objectcontent. Note copy will be truncated if objectcontent does not fit into destination.&#13;&#10;Method will return size of single caracter in destination (1=ASCII, 2=UNI) or 0 when nothing is written into destination.&#13;&#10;pdst.... pointer to destination. (where copy should be filed)&#13;&#10;dstsize .... bytesize of destination" Name="TxtGet"/>
	FUNCTION VIRTUAL GLOBAL TxtGet
		VAR_INPUT
			pdst 	: ^void;			//! <Variable Comment="pointer to destination. (where copy should be filed)" Name="TxtGet.pdst"/>
			dstsize 	: UDINT;			//! <Variable Comment="bytesize of destination" Name="TxtGet.dstsize"/>
		END_VAR
		VAR_OUTPUT
			charsize 	: UDINT;			//! <Variable Comment="Method will return size of single caracter in destination (1=ASCII, 2=UNI) or 0 when nothing is written into destination." Name="TxtGet.charsize"/>
		END_VAR;
				//! <Function Comment="Get 0-terminated copy of objectcontent beginning at characteroffset &apos;fromwhere&apos; with length &apos;nchar&apos; . Note copy will be truncated if text does not fit into destination.&#13;&#10;Method will return size of single caracter in destination (1=ASCII, 2=UNI) or 0 when nothing is written into destination.&#13;&#10;pdst.... pointer to destination. (where copy should be filed)&#13;&#10;dstsize .... bytesize of destination&#13;&#10;fromwhere .... startoffset&#13;&#10;nchar .... number of wanted character. if value exceeds length, value will be truncated. &#13;&#10;" Name="TxtGetAt"/>
	FUNCTION VIRTUAL GLOBAL TxtGetAt
		VAR_INPUT
			pdst 	: ^void;			//! <Variable Comment="pointer to destination. (where copy should be filed)" Name="TxtGetAt.pdst"/>
			dstsize 	: UDINT;			//! <Variable Comment="bytesize of destination" Name="TxtGetAt.dstsize"/>
			fromwhere 	: UDINT;			//! <Variable Comment="offset if character where to start copy from&#13;&#10;" Name="TxtGetAt.fromwhere"/>
			nchar 	: UDINT;			//! <Variable Comment="number of wanted character. if value exceeds length, value will be truncated." Name="TxtGetAt.nchar"/>
		END_VAR
		VAR_OUTPUT
			charsize 	: UDINT;			//! <Variable Comment="Method will return size of single caracter in destination (1=ASCII, 2=UNI) or 0 when nothing is written into destination." Name="TxtGetAt.charsize"/>
		END_VAR;
				//! <Function Comment="Set objectcontent to given string. User is able to choose between different styles (ASCII, UNI)&#13;&#10;Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;.&#13;&#10;dstchrsize .... size of single character at target (1=ASCII, 2=UNI)&#13;&#10;psrc .... pointer to 0-terminated string to set&#13;&#10;srcchrsize .... size of single character in given string (1=ASCII, 2=UNI)&#13;&#10;" Name="TxtSet"/>
	FUNCTION VIRTUAL GLOBAL TxtSet
		VAR_INPUT
			dstchrsize 	: UDINT;			//! <Variable Comment="size of single character at target (1=ASCII, 2=UNI)" Name="TxtSet.dstchrsize"/>
			psrc 	: ^void;			//! <Variable Comment="pointer to 0-terminated string to set" Name="TxtSet.psrc"/>
			srcchrsize 	: UDINT;			//! <Variable Comment="size of single character in given string (1=ASCII, 2=UNI)" Name="TxtSet.srcchrsize"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;			//! <Variable Comment="Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;" Name="TxtSet.retcode"/>
		END_VAR;
				//! <Function Comment="Set (overwrite) single character in objectcontent. If offset is greater or equal to contentlength, character will be added at least.&#13;&#10;Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;.&#13;&#10;characteroffset .... offset of character to overwrite.&#13;&#10;character .... given character&#13;&#10;" Name="TxtSetChr"/>
	FUNCTION VIRTUAL GLOBAL TxtSetChr
		VAR_INPUT
			characteroffset 	: UDINT;			//! <Variable Comment="offset of character to overwrite.&#13;&#10;" Name="TxtSetChr.characteroffset"/>
			character 	: UDINT;			//! <Variable Comment="given character to set" Name="TxtSetChr.character"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;			//! <Variable Comment="Method will return &apos;true&apos; on success, on the oter hand &apos;false&apos;." Name="TxtSetChr.retcode"/>
		END_VAR;
				//! <Function Comment="Method will empty content of object" Name="TxtClear"/>
	FUNCTION VIRTUAL GLOBAL TxtClear;
				//! <Function Comment="Find first index of given character in objectcontent.&#13;&#10;Method will return valid index of character on success, on the other hand 16#FFFFFFFF&#13;&#10;character .... given character used to search" Name="TxtChr"/>
	FUNCTION VIRTUAL GLOBAL TxtChr
		VAR_INPUT
			character 	: UDINT;			//! <Variable Comment="given character used to search" Name="TxtChr.character"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: UDINT;			//! <Variable Comment="Method will return valid index of character on success, on the other hand 16#FFFFFFFF" Name="TxtChr.retcode"/>
		END_VAR;
				//! <Function Comment="Method will return number of characters in objectcontent." Name="TxtLen"/>
	FUNCTION VIRTUAL GLOBAL TxtLen
		VAR_OUTPUT
			retcode 	: UDINT;			//! <Variable Comment="number of characters in objectcontent" Name="TxtLen.retcode"/>
		END_VAR;
				//! <Function Comment="Insert new string or part of string into content of object. If offset where part should be inserted is greater or equal than number of characters, part will be added at least.&#13;&#10;Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;.&#13;&#10;index_at .... characteroffset where part sould be inserted&#13;&#10;psrc .... pointer to part to insert&#13;&#10;chrsize .... size of single character in given part (1=ASCII, 2=UNI)&#13;&#10;chrcount .... characterlength of part. If value exceeds length of part, value will be truncated.&#13;&#10;" Name="TxtIns"/>
	FUNCTION VIRTUAL GLOBAL TxtIns
		VAR_INPUT
			index_at 	: UDINT;			//! <Variable Comment="characteroffset where part sould be inserted" Name="TxtIns.index_at"/>
			psrc 	: ^void;			//! <Variable Comment="psrc .... pointer to part used for insertion" Name="TxtIns.psrc"/>
			chrsize 	: UDINT;			//! <Variable Comment="size of single character in given part (1=ASCII, 2=UNI)" Name="TxtIns.chrsize"/>
			chrcount 	: UDINT;			//! <Variable Comment="chrcount .... characterlength of part. If value exceeds length of part, value will be truncated." Name="TxtIns.chrcount"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;			//! <Variable Comment="Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;." Name="TxtIns.retcode"/>
		END_VAR;
				//! <Function Comment="Convert objectcontent to asciicode when having unicode-style.&#13;&#10;Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;" Name="TxtToAscii"/>
	FUNCTION VIRTUAL GLOBAL TxtToAscii
		VAR_OUTPUT
			retcode 	: BOOL;			//! <Variable Comment="Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;" Name="TxtToAscii.retcode"/>
		END_VAR;
				//! <Function Comment="Convert objectcontent to unicode when having asciicode-style.&#13;&#10;Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;" Name="TxtToUni"/>
	FUNCTION VIRTUAL GLOBAL TxtToUni
		VAR_OUTPUT
			retcode 	: BOOL;			//! <Variable Comment="Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;" Name="TxtToUni.retcode"/>
		END_VAR;
				//! <Function Comment="Convert all characters in objectcontent to uppercase." Name="TxtUpr"/>
	FUNCTION VIRTUAL GLOBAL TxtUpr;
				//! <Function Comment="Convert all characters in objectcontent to lowercase." Name="TxtLwr"/>
	FUNCTION VIRTUAL GLOBAL TxtLwr;
				//! <Function Comment="Get checksum of objectcontent." Name="TxtGetCRC"/>
	FUNCTION VIRTUAL GLOBAL TxtGetCRC
		VAR_OUTPUT
			retcode 	: UDINT;			//! <Variable Comment="Method will return checksum of objectcontent" Name="TxtGetCRC.retcode"/>
		END_VAR;
				//! <Function Comment="Get size of single character used in objectcontent. (1=ASCII, 2=UNI)" Name="TxtGetCharSize"/>
	FUNCTION VIRTUAL GLOBAL TxtGetCharSize
		VAR_OUTPUT
			retcode 	: USINT;			//! <Variable Comment="size of single character used in objectcontent. (1=ASCII, 2=UNI)" Name="TxtGetCharSize.retcode"/>
		END_VAR;
				//! <Function Comment="Copy content of given Object to target. Note that format (UNI, ASCII) of target will not change.&#13;&#10;Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;.&#13;&#10;pStr .... Given object to copy content." Name="ObjCpy"/>
	FUNCTION VIRTUAL GLOBAL ObjCpy
		VAR_INPUT
			pStr 	: ^StringInternal;			//! <Variable Comment="Given object to copy content." Name="ObjCpy.pStr"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;			//! <Variable Comment="Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;." Name="ObjCpy.retcode"/>
		END_VAR;
				//! <Function Comment="Copy objectcontent beginning at characteroffset &apos;fromwhere&apos; with length &apos;nchar&apos; to target.&#13;&#10;Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;&#13;&#10;pStr .... Given object to copy content&#13;&#10;fromwhere .... startoffset&#13;&#10;nchar .... number of character to copy. if value exceeds length, value will be truncated" Name="ObjCpyFrom"/>
	FUNCTION VIRTUAL GLOBAL ObjCpyFrom
		VAR_INPUT
			pStr 	: ^StringInternal;			//! <Variable Comment="pStr .... Given object to copy content" Name="ObjCpyFrom.pStr"/>
			fromwhere 	: UDINT;			//! <Variable Comment="offset of character to start copy" Name="ObjCpyFrom.fromwhere"/>
			nchar 	: UDINT;			//! <Variable Comment="number of character to copy. if value exceeds length, value will be truncated" Name="ObjCpyFrom.nchar"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;			//! <Variable Comment="Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;&#13;&#10;" Name="ObjCpyFrom.retcode"/>
		END_VAR;
				//! <Function Comment="Same than method ObjCpy() with difference that style of target will change to style of given content." Name="ObjClone"/>
	FUNCTION VIRTUAL GLOBAL ObjClone
		VAR_INPUT
			pStr 	: ^StringInternal;			//! <Variable Comment="Given object to copy clone." Name="ObjClone.pStr"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;			//! <Variable Comment="Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;." Name="ObjClone.retcode"/>
		END_VAR;
				//! <Function Comment="Concatenate content of given object to target. Format (UNI, ASCII) of target will not change.&#13;&#10;Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;.&#13;&#10;pStr .... Given object to copy content." Name="ObjCat"/>
	FUNCTION VIRTUAL GLOBAL ObjCat
		VAR_INPUT
			pStr 	: ^StringInternal;			//! <Variable Comment="Given object to copy content." Name="ObjCat.pStr"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;			//! <Variable Comment="Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;." Name="ObjCat.retcode"/>
		END_VAR;
				//! <Function Comment="Concatenate target by using content of given object. Given string will always be added at the given position in target string. At the end of given string target will end afterwards. Format (UNI, ASCII) of target will not change.&#13;&#10;Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;.&#13;&#10;chroffset .... offset where given string will be added.&#13;&#10;pStr .... given object used to" Name="ObjCatAt"/>
	FUNCTION VIRTUAL GLOBAL ObjCatAt
		VAR_INPUT
			chroffset 	: UDINT;			//! <Variable Comment="offset where given objectcontent will be added." Name="ObjCatAt.chroffset"/>
			pStr 	: ^StringInternal;			//! <Variable Comment="given object used to concatenate" Name="ObjCatAt.pStr"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;			//! <Variable Comment="Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;." Name="ObjCatAt.retcode"/>
		END_VAR;
				//! <Function Comment="Perform comparison (case sensitive) between given object and content of addressed object. Functionality is independent on style of object- and string-content (UNI, ASCII).&#13;&#10;Method will return 0 when given string and content of object are the same, on the other hand &lt;&gt;0&#13;&#10;pStr .... given object used to comare" Name="ObjCmp"/>
	FUNCTION VIRTUAL GLOBAL ObjCmp
		VAR_INPUT
			pStr 	: ^StringInternal;			//! <Variable Comment="given object used to comare" Name="ObjCmp.pStr"/>
		END_VAR
		VAR_OUTPUT
			udNotEqual 	: UDINT;			//! <Variable Comment="Method will return 0 when given string and content of object are the same, on the other hand &lt;&gt;0" Name="ObjCmp.udNotEqual"/>
		END_VAR;
				//! <Function Comment="Perform case insensitive comparison between given content object and addressed content of object. Functionality is independent on style of object- and string-content (UNI, ASCII).&#13;&#10;Method will return 0 when both content of object are equal, on the other hand &lt;&gt;0" Name="ObjICmp"/>
	FUNCTION VIRTUAL GLOBAL ObjICmp
		VAR_INPUT
			pStr 	: ^StringInternal;			//! <Variable Comment="given object used to comare" Name="ObjICmp.pStr"/>
		END_VAR
		VAR_OUTPUT
			udNotEqual 	: UDINT;			//! <Variable Comment="Method will return 0 when given string and content of object are the same, on the other hand &lt;&gt;0" Name="ObjICmp.udNotEqual"/>
		END_VAR;
				//! <Function Comment="Insert new string or part of string into content of object. If offset where part should be inserted is greater or equal than number of characters, part will be added at least.&#13;&#10;Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;.&#13;&#10;index_at .... characteroffset where part sould be inserted&#13;&#10;pStr .... pointer to given object used for insertion&#13;&#10;chrcount .... characterlength of part. If value exceeds length of part, value will be truncated." Name="ObjIns"/>
	FUNCTION VIRTUAL GLOBAL ObjIns
		VAR_INPUT
			index_at 	: UDINT;			//! <Variable Comment="characteroffset where part sould be inserted" Name="ObjIns.index_at"/>
			pStr 	: ^StringInternal;			//! <Variable Comment="pointer to given object used for insertion" Name="ObjIns.pStr"/>
			chrcount 	: UDINT;			//! <Variable Comment="characterlength of part. If value exceeds length of part, value will be truncated." Name="ObjIns.chrcount"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;			//! <Variable Comment="Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;." Name="ObjIns.retcode"/>
		END_VAR;
				//! <Function Comment="Get 0-terminated copy (ASCII-format) of objectcontent. Note copy is always in ASCII-format and will be truncated if objectcontent does not fit into destination.&#13;&#10;When converting unicode-string to ascii-format all non-representable characters will be replaced by &apos;?&apos;.&#13;&#10;Method will return size of single caracter in destination (1=ASCII) or 0 when nothing is written into destination.&#13;&#10;pdst.... pointer to destination. (where copy should be filed)&#13;&#10;dstsize .... bytesize of destination" Name="TxtGetAscii"/>
	FUNCTION VIRTUAL GLOBAL TxtGetAscii
		VAR_INPUT
			pdst 	: ^CHAR;			//! <Variable Comment="pointer to destination. (where ASCII-copy should be filed)" Name="TxtGetAscii.pdst"/>
			dstsize 	: UDINT;			//! <Variable Comment="bytesize of destination" Name="TxtGetAscii.dstsize"/>
		END_VAR
		VAR_OUTPUT
			charsize 	: UDINT;			//! <Variable Comment="Method will return size of single character in destination (1=ASCII) or 0 when nothing is written into destination." Name="TxtGetAscii.charsize"/>
		END_VAR;
				//! <Function Comment="Get length of given ascii-string after conversion to utf8-string.&#13;&#10;Method will return amount of all characters excluding final 0.&#13;&#10;Method will not use or affect any membervariables of object." Name="TxtLenAsciiToUtf8"/>
	FUNCTION GLOBAL TxtLenAsciiToUtf8
		VAR_INPUT
			src_ascii 	: ^CHAR;			//! <Variable Comment="ascii-string used to compute" Name="TxtLenAsciiToUtf8.src_ascii"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: UDINT;			//! <Variable Comment="stringlength (amount of characters) after convert given string" Name="TxtLenAsciiToUtf8.retcode"/>
		END_VAR;
				//! <Function Comment="Get length of given utf8-formatted string after conversion to ascii-string.&#13;&#10;Method will return amount of all characters excluding final 0.&#13;&#10;Method will not use or affect any membervariables of object.&#13;&#10;NOTE: When converting utf8 to ascii all non-representable characters will be replaced by &apos;?&apos;.&#13;&#10;" Name="TxtLenUtf8ToAscii"/>
	FUNCTION GLOBAL TxtLenUtf8ToAscii
		VAR_INPUT
			src_utf8 	: ^CHAR;			//! <Variable Comment="utf8-string used to compute" Name="TxtLenUtf8ToAscii.src_utf8"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: UDINT;			//! <Variable Comment="stringlength (amount of characters) after conversion of given string" Name="TxtLenUtf8ToAscii.retcode"/>
		END_VAR;
				//! <Function Comment="Get length of given unicode-string after conversion to utf8-string.&#13;&#10;Method will return amount of all characters excluding final 0.&#13;&#10;Method will not use or affect any membervariables of object." Name="TxtLenUniToUtf8"/>
	FUNCTION GLOBAL TxtLenUniToUtf8
		VAR_INPUT
			src_uni 	: ^UINT;			//! <Variable Comment="unicode-string used to compute" Name="TxtLenUniToUtf8.src_uni"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: UDINT;			//! <Variable Comment="stringlength (amount of characters) after conversion of given given string" Name="TxtLenUniToUtf8.retcode"/>
		END_VAR;
				//! <Function Comment="Get length of given utf8-formatted string after conversion to unicode-string.&#13;&#10;Method will return amount of all characters excluding final 0.&#13;&#10;Method will not use or affect any membervariables of object.&#13;&#10;NOTE: Size of each character in unicode-string is 2 bytes" Name="TxtLenUtf8ToUni"/>
	FUNCTION GLOBAL TxtLenUtf8ToUni
		VAR_INPUT
			src_utf8 	: ^CHAR;			//! <Variable Comment="utf8-string used to compute" Name="TxtLenUtf8ToUni.src_utf8"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: UDINT;			//! <Variable Comment="stringlength (amount of characters) after convert given string" Name="TxtLenUtf8ToUni.retcode"/>
		END_VAR;
				//! <Function Comment="Convert given ascii-string into utf8-formatted string.&#13;&#10;Method will return amount of all characters in destination excluding final 0.&#13;&#10;Method will not use or affect any membervariables of object.&#13;&#10;NOTE: To avoid overflows, the size of the dst array shall be long enough to contain the utf8-string and should not overlap in memory with src." Name="TxtAsciiToUtf8"/>
	FUNCTION GLOBAL TxtAsciiToUtf8
		VAR_INPUT
			dst_utf8 	: ^CHAR;			//! <Variable Comment="Address of destination where converted utf8-string should be filed" Name="TxtAsciiToUtf8.dst_utf8"/>
			src_ascii 	: ^CHAR;			//! <Variable Comment="ascii-string to be converted" Name="TxtAsciiToUtf8.src_ascii"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: UDINT;			//! <Variable Comment="stringlength (amount of characters) of destination string" Name="TxtAsciiToUtf8.retcode"/>
		END_VAR;
				//! <Function Comment="Convert given unicode-string into utf8-formatted string.&#13;&#10;Method will return amount of all characters in destination excluding final 0.&#13;&#10;Method will not use or affect any membervariables of object.&#13;&#10;NOTE: To avoid overflows, the size of the dst_utf8 array shall be long enough to contain the utf8-string and should not overlap in memory with src." Name="TxtUniToUtf8"/>
	FUNCTION GLOBAL TxtUniToUtf8
		VAR_INPUT
			dst_utf8 	: ^CHAR;			//! <Variable Comment="Address of destination where converted utf8-string should be filed" Name="TxtUniToUtf8.dst_utf8"/>
			src_uni 	: ^UINT;			//! <Variable Comment="unicode-string to be converted" Name="TxtUniToUtf8.src_uni"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: UDINT;			//! <Variable Comment="stringlength (amount of characters) of destination string" Name="TxtUniToUtf8.retcode"/>
		END_VAR;
				//! <Function Comment="Convert given utf8-formatted string into ascii-string.&#13;&#10;Method will return amount of all characters in destination excluding final 0.&#13;&#10;Method will not use or affect any membervariables of object.&#13;&#10;NOTE: When converting utf8 to ascii all non-representable characters will be replaced by &apos;?&apos;. To avoid overflows, the size of the dst array shall be long enough to contain the ascii-string and should not overlap in memory with src_utf8." Name="TxtUtf8ToAscii"/>
	FUNCTION GLOBAL TxtUtf8ToAscii
		VAR_INPUT
			dst_ascii 	: ^CHAR;			//! <Variable Comment="Address of destination where converted ascii-string should be filed" Name="TxtUtf8ToAscii.dst_ascii"/>
			src_utf8 	: ^CHAR;			//! <Variable Comment="utf8-string to be converted" Name="TxtUtf8ToAscii.src_utf8"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: UDINT;			//! <Variable Comment="stringlength (amount of characters) of destination string" Name="TxtUtf8ToAscii.retcode"/>
		END_VAR;
				//! <Function Comment="Convert given utf8-formatted-string into unicode string.&#13;&#10;Method will return amount of all characters in destination excluding final 0.&#13;&#10;Method will not use or affect any membervariables of object.&#13;&#10;NOTE: To avoid overflows, the size of the dst array shall be long enough to contain the unicode-string and should not overlap in memory with src_utf8." Name="TxtUtf8ToUni"/>
	FUNCTION GLOBAL TxtUtf8ToUni
		VAR_INPUT
			dst_uni 	: ^UINT;			//! <Variable Comment="Address of destination where converted uni-string should be filed" Name="TxtUtf8ToUni.dst_uni"/>
			src_utf8 	: ^CHAR;			//! <Variable Comment="utf8-string to be converted" Name="TxtUtf8ToUni.src_utf8"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: UDINT;			//! <Variable Comment="stringlength (amount of characters) of destination string" Name="TxtUtf8ToUni.retcode"/>
		END_VAR;
				//! <Function Comment="Set content of object with given utf8-formatted string.&#13;&#10;Method will return &apos;true&apos; on success, on the other hand &apos;false&apos;.&#13;&#10;NOTE: Internal used format of string will be unicode. To get content in utf8-format use TxtGetUtf8()&#13;&#10;" Name="TxtSetUtf8"/>
	FUNCTION VIRTUAL GLOBAL TxtSetUtf8
		VAR_INPUT
			src_utf8 	: ^CHAR;			//! <Variable Comment="Address of utf8-string to be copied into objectcontent" Name="TxtSetUtf8.src_utf8"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;			//! <Variable Comment="&apos;true&apos; in case of set success, on the other hand &apos;false&apos; on error" Name="TxtSetUtf8.retcode"/>
		END_VAR;
				//! <Function Comment="Get content of object in utf8-format.&#13;&#10;Method will return amount of characters in destination excluding final 0.&#13;&#10;NOTE: To avoid overflows, the size of the dst array shall be long enough to contain the utf8-formatted-string." Name="TxtGetUtf8"/>
	FUNCTION VIRTUAL GLOBAL TxtGetUtf8
		VAR_INPUT
			dst_utf8 	: ^CHAR;			//! <Variable Comment="Address of destination where converted utf8-string should be filed" Name="TxtGetUtf8.dst_utf8"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: UDINT;			//! <Variable Comment="stringlength (amount of characters) of destination string" Name="TxtGetUtf8.retcode"/>
		END_VAR;
				//! <Function Comment="Method will compute amount of characters when objectcontent is converted to uft8-formatted string.&#13;&#10;Note: Method will not change content of object." Name="TxtLenUtf8"/>
	FUNCTION VIRTUAL GLOBAL TxtLenUtf8
		VAR_OUTPUT
			retcode 	: UDINT;			//! <Variable Comment="computed stringlength (amount of characters) after conversion of objectcontent to utf8-formatted string" Name="TxtLenUtf8.retcode"/>
		END_VAR;
	
	FUNCTION KillUBOM;
				//! <Function Comment="[!GET_ADD_INFO]&#13;&#10; Klassenaghängige Zusatzinformation wird geliefert&#13;&#10;[!GET_ADD_INFO]&#13;&#10; returns class specific additional information&#13;&#10;" Name="Data.NewInst"/>
	FUNCTION VIRTUAL GLOBAL Data::NewInst
		VAR_INPUT
			pPara 	: ^CmdStruct;
			pResult 	: ^results;
		END_VAR
		VAR_OUTPUT
			ret_code 	: iprStates;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL Data::Read
		VAR_OUTPUT
			output (EAX) 	: UDINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL Data::Write
		VAR_INPUT
			input (EAX) 	: UDINT;
		END_VAR
		VAR_OUTPUT
			result (EAX) 	: UDINT;
		END_VAR;
  //Tables:
	FUNCTION @STD
		VAR_OUTPUT
			ret_code	: CONFSTATES;
		END_VAR;
	FUNCTION GLOBAL TAB @CT_;
END_CLASS;

#pragma usingLtd MerkerEx


//}}LSL_DECLARATION


FUNCTION GLOBAL TAB StringInternal::@CT_
0$UINT,
2#0100000000000000$UINT, //TY_STRINGINTERNAL
1$UINT, 85$UINT, (SIZEOF(::StringInternal))$UINT, 
0$UINT, 2$UINT, 0$UINT, 
TO_UDINT(2898603620), "StringInternal", //Class
TO_UDINT(3232495061), "VirtualBaseInit", 1$UINT, 3$UINT, //Baseclass
//Servers:
//Clients:
(::StringInternal.DataBuffer.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000010$UINT, TO_UDINT(4265790926), "DataBuffer", TO_UDINT(2225119864), "MerkerEx", 1$UINT, 22$UINT, 
(::StringInternal.SingleRealloc.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(155664527), "SingleRealloc", 
END_FUNCTION


#define USER_CNT_StringInternal 52

TYPE
	_LSL_STD_VMETH	: STRUCT
			CmdTable	: CMDMETH;
			UserFcts	: ARRAY[0..USER_CNT_StringInternal] OF ^Void;
	END_STRUCT;
END_TYPE

FUNCTION StringInternal::@STD
	VAR_OUTPUT
		ret_code	: CONFSTATES;
	END_VAR
	VAR
		vmt	: _LSL_STD_VMETH;
		nCmdSize	: UINT;
	END_VAR

	ret_code	:= VirtualBaseInit::@STD();
	IF ret_code <> C_OK THEN
		RETURN;
	END_IF;
	nCmdSize		:= VirtualBaseInit::Data.pMeth^.nCmds$UINT*SIZEOF(pVoid) + CMDMETH.Init;

	_memcpy((#vmt.CmdTable)$^USINT, VirtualBaseInit::Data.pMeth, nCmdSize);
	vmt.CmdTable.nCmds		:= nSTDCMD + USER_CNT_StringInternal;
	vmt.CmdTable.NewInstr		:= #Data::NewInst();
	vmt.CmdTable.Read		:= #Data::Read();
	vmt.CmdTable.Write		:= #Data::Write();
	vmt.CmdTable.Init		:= #Init();
#pragma warning (disable : 74)
	vmt.UserFcts[0]		:= #GetLength();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[1]		:= #GetDataAt();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[2]		:= #InitFromTable();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[3]		:= #WriteDataOff();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[4]		:= #GetCRC();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[6]		:= #StrCpy();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[7]		:= #StrCat();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[8]		:= #Clear();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[9]		:= #StrCmp();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[10]		:= #StriCmp();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[11]		:= #Left();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[12]		:= #Right();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[13]		:= #StrUpr();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[14]		:= #ToAscii();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[15]		:= #ToUniCode();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[16]		:= #StrLwr();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[17]		:= #StrChr();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[18]		:= #StrLen();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[19]		:= #SetDataAt();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[20]		:= #GetCharSize();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[21]		:= #WriteDataOffUni();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[22]		:= #TxtCatAt();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[23]		:= #TxtCat();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[24]		:= #TxtCmp();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[25]		:= #TxtICmp();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[26]		:= #TxtGet();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[27]		:= #TxtGetAt();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[28]		:= #TxtSet();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[29]		:= #TxtSetChr();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[30]		:= #TxtClear();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[31]		:= #TxtChr();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[32]		:= #TxtLen();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[33]		:= #TxtIns();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[34]		:= #TxtToAscii();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[35]		:= #TxtToUni();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[36]		:= #TxtUpr();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[37]		:= #TxtLwr();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[38]		:= #TxtGetCRC();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[39]		:= #TxtGetCharSize();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[40]		:= #ObjCpy();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[41]		:= #ObjCpyFrom();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[42]		:= #ObjClone();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[43]		:= #ObjCat();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[44]		:= #ObjCatAt();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[45]		:= #ObjCmp();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[46]		:= #ObjICmp();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[47]		:= #ObjIns();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[48]		:= #TxtGetAscii();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[49]		:= #TxtSetUtf8();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[50]		:= #TxtGetUtf8();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[51]		:= #TxtLenUtf8();

#pragma warning (default : 74)
	VirtualBaseInit::Data.pMeth		:= StoreCmd (pCmd := #vmt.CmdTable, SHARED);

	IF VirtualBaseInit::Data.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;

END_FUNCTION

//{{LSL_IMPLEMENTATION


//*********************Inserted from .\code\String.st*********************

#include <RTOS_MemIntern.h>

//==============================================================
#define GetData()				DataBuffer.GetDataPtr()
#define IsAscii()				GetCharSize() = sizeof(char)
#define IsUniCode()				GetCharSize() = sizeof(UINT)
#define SI_TMP_HELPSIZE 64
//==============================================================

(*
  String-Darstellung:
  
  Die Zeichen sind im DataBuffer gespeichert und mit einem 0-Zeichen abgeschlossen.
  Im neuen Format (UNICODE - Zeichengröße 2) ist zusätzlich in den ersten beiden 
  Bytes die Größe eines Zeichens (immer = 2) gespeichert.
  Die Länge der String-Daten (inkl. optionaler Zeichengröße und 0-Ende-Zeichen) 
  ist ebenfalls im Objekt gespeichert (m_udLength).
  Eine m_udLength von 0 muß als ASCII Leerstring interpretiert werden.
  Eine m_udLength von 2 und Zeichengröße 2 muß als UNICODE Leerstring interpretiert werden.

  Unterscheidung ASCII / UNICODE:
  Wenn im DataBuffer als erstes Byte ein 0er steht und die Länge der Daten im 
  Datenbuffer > 1 und die Zeichengröße 2 ist, dann handelt es sich um einen Unicode-String.
  Alles andere ist ASCII.
  
  Bsp.
  
    m_udLength = 0                  Leerstring in ASCII
    '\0'                            Leerstring in ASCII
    'A'  '\0'                       String "A" in ASCII
    
    '\0' '\2'                       Leerstring in UNICODE
    '\0' '\2' '\0' '\0'             Leerstring in UNICODE
    '\0' '\2' '\0' 'A'  '\0' '\0'   String "A" in UNICODE
*)

FUNCTION VIRTUAL GLOBAL StringInternal::GetLength
VAR_OUTPUT
	udLen		: UDINT;
END_VAR
VAR
  pa : ^usint;
  pu : ^uint;
  tmplen  : UDINT;
END_VAR

  tmplen := DataBuffer.m_udLength; // Get act. allocated size
  udLen := 0;
  pa    := GetData();

  if(pa <> NIL) & (tmplen > 0) then
    if(GetCharSize() = 1) then
      udLen := _strlen(pa);
    else
      pu := pa$^uint;
      while(pu^ <> 0) do
        udLen += 2;
        pu    += 2;
      end_while;
    end_if;
  end_if;

END_FUNCTION
//[#ENGLISH]
//The function extracts the given amount of bytes from a string-buffer.
//udAt specifies the starting position. pData is a pointer to a destination
//buffer, which has to be big enough to contain the extracted part.
//[>pData]	pointer to the destination buffer
//[>udSize]	number of bytes to extract
//[>udAt]	offset within the string-buffer
//[#DEUTSCH]
//Die Funktion kopiert die angegebene Anzahl von Bytes ab dem Offset udAt
//aus dem String in einen zur Verfügung gestellten Ziel-Puffer. Dieser
//Puffer muß ausreichend groß sein, um den extrahierten Teil aufnehmen
//zu können.
//[>pData]	Zeiger auf den Ziel-Puffer
//[>udSize]	Anzahl der Bytes, die kopiert werden sollen
//[>udAt]	Offset im String, ab dem kopiert werden soll
FUNCTION VIRTUAL GLOBAL StringInternal::GetDataAt
VAR_INPUT
	pData		: ^USINT;
	udSize		: UDINT;
	udAt		: UDINT;
END_VAR

	DataBuffer.GetDataAt(pData, udSize, udAt);

END_FUNCTION //VIRTUAL GLOBAL StringInternal::GetDataAt
//[#ENGLISH]
// The function doesn't provide default functionality
// Please overwrite it for derived classes.
//[>udLen]	data length to be copied
//[>udOff]	offset where data should be copied to
//[>pData]	pointer to new data
//[#DEUTSCH]
// Die Funktion stellt keine Standard-Implementierung dar. Sie muß für abgeleitete
// Klassen überschrieben werden.
//[>udLen] Länge des übergebenen Datenpuffers
//[>udOff] Offset innerhalb des internen Datenpuffers, auf den die Daten kopiert werden sollen
//[>pData] Zeiger auf den neuen Datenblock
FUNCTION VIRTUAL GLOBAL StringInternal::WriteDataOff
VAR_INPUT
  udLen 	: UDINT;
  udOff 	: UDINT;
  pData 	: ^USINT;
END_VAR
VAR
  tmplen  : UDINT;
  tmpretcode  : ConfStates;
END_VAR

  tmpretcode := C_OK;

	// check if the string representation is given
	IF udOff = 0 THEN
		IF pData & udLen >= 2 & pData$^UINT^ = 16#0200 THEN
			ToUnicode();
		ELSE
			IF pData & udLen >= 2 & pData$^UINT^ = 16#0100 THEN
				// pr, 13.12.2004 Workaround:
				// Wenn jemand versucht, einen ASCII String mit einem Zeichengröße-WORD 
				// zu initialisieren, dann wird das Zeichengröße-WORD hier entfernt.
				// Ein ASCII String darf nämlich nur ohne Zeichengröße abgespeichert werden !
				// Leider gibt es schon Code, der einen ASCII String mit einem Zeichengröße-WORD 
				// initialisiert, daher ist dieser Workaround nötig.
				pData += 2;
				udLen -= 2;
			END_IF;
			ToAscii();
		END_IF;
	END_IF;

  tmplen := udOff+udLen;

	// set the string to the new length
  IF (SingleRealloc = 0) THEN //  If client is not set the function works like it did before rev. >= 1.8
	  tmpretcode := DataBuffer.SetSize(tmplen);

  ELSE
    IF (tmplen > DataBuffer.m_udLength) THEN
      tmpretcode := DataBuffer.SetSize(tmplen);

    END_IF;
  END_IF;

  if (tmpretcode = C_OK) then
    DataBuffer.SetDataAt(pData, udLen, udOff);

    m_udlen := tmplen;  //  set the length which is used in next method
    AddTermination();
    CalcCRC();
  end_if;

END_FUNCTION //VIRTUAL GLOBAL StringInternal::WriteDataOff
//[#DEUTSCH]
//Initialisiert den String mit konstanten Daten, z.B. aus einer Tabelle
//Der String wird als ASCII-String interpretiert.
//[>udLen]Länge der Initialisierungsdaten in Bytes
//[>pData]Zeiger auf die Initialisierungsdaten
//[#ENGLISH]
//Initializes a string object with constant data (i.e. from a table)
//The string is assumed to be an ASCII-string
//[>udLen]length of initialization data in bytes
//[>pData]pointer to initialization data
FUNCTION VIRTUAL GLOBAL StringInternal::InitFromTable
VAR_INPUT
	udLen		: UDINT;
	pData		: ^USINT;
END_VAR


  IF DataBuffer.GetDataPtr () = 0 THEN
    IF pData & udLen >= 2 & pData$^UINT^ = 16#0100 THEN
      // pr, 13.12.2004 Workaround:
      // Wenn jemand versucht, einen ASCII String mit einem Zeichengröße-WORD 
      // zu initialisieren, dann wird das Zeichengröße-WORD hier entfernt.
      // Ein ASCII String darf nämlich nur ohne Zeichengröße abgespeichert werden !
      // Leider gibt es schon Code, der einen ASCII String mit einem Zeichengröße-WORD 
      // initialisiert, daher ist dieser Workaround nötig.
      pData += 2;
      udLen -= 2;
    END_IF;

    IF DataBuffer.SetSize( udLen ) = C_OK THEN
      DataBuffer.SetData( pData );
      m_udlen := udLen; //  set the length which is used in next method
      AddTermination();
      CalcCRC();
    END_IF;
  END_IF;

END_FUNCTION //VIRTUAL GLOBAL StringInternal::InitFromTable
//[#DEUTSCH]
//Kopiert den Inhalt des übergebenen Strings in das eigene String-Objekt.
//Die Inhalte beider Strings sind danach ident.
//[>pSrc]Zeiger auf den Quell-String
//[#ENGLISH]
// Copies the raw data from the passed string to the current one.
// The contents of the data blocks of both strings are the same
// afterwards.
//[>pSrc]pointer to source string
FUNCTION VIRTUAL GLOBAL StringInternal::StrCpy
	VAR_INPUT
		pSrc 	: ^StringInternal;
	END_VAR
VAR
	udLen		: UDINT;
END_VAR

	// Size includes 0-termination, considers style
	udLen	:= pSrc^.DataBuffer.GetSize();

  IF (SingleRealloc = 0) THEN //  If client is not set the function works like it did before rev. >= 1.8
    IF DataBuffer.SetSize( udLen ) = C_OK THEN

      _memcpy(GetData(), pSrc^.GetData(), udLen);

      m_udCRC		:= pSrc^.GetCRC();

      DataBuffer.UpdateToFile();
    END_IF;

  ELSE
    IF (udLen > DataBuffer.m_udLength) THEN
      IF (DataBuffer.SetSize(udLen) = C_OK) THEN
        _memcpy(GetData(), pSrc^.GetData(), udLen);
        m_udCRC		:= pSrc^.GetCRC();
        DataBuffer.UpdateToFile();

      END_IF;
    ELSE
      _memcpy(GetData(), pSrc^.GetData(), udLen);
      m_udCRC		:= pSrc^.GetCRC();
      DataBuffer.UpdateToFile();

    END_IF;
  END_IF;

END_FUNCTION //GLOBAL StringInternal::StrCpy
//[#DEUTSCH]
//Der String wird auf einen Leerstring gesetzt.
//[#ENGLISH]
// the string contents of the string are set to an empty string
FUNCTION VIRTUAL GLOBAL StringInternal::Clear
VAR
	pData : ^USINT;
END_VAR

  pData := DataBuffer.GetDataPtr();
	IF (SingleRealloc = 0) then //  If client is not set the function works like it did before rev. >= 1.8
    DataBuffer.SetSize(0);

  ELSE
    _memset(pData, 0, DataBuffer.m_udLength);

  END_IF;

	CalcCRC();

END_FUNCTION //GLOBAL StringInternal::Clear
//[#ENGLISH]
//The passed string is appended to the current string
//If the strings styles differ (ASCII/UNICODE), then the passed string
//will be converted to the current string's style prior to appending it.
//[>pSrc]pointer to string to append
//[#DEUTSCH]
//Der übergebene String wird an den eigenen String hinten angehängt.
//Wenn die Strings unterschiedliche Typen haben (ASCII/UNICODE), dann
//wird der übergebene String zuerst angepaßt, und dann erst angehängt.
//[>pSrc]Zeiger auf den anzuhängenden String
FUNCTION VIRTUAL GLOBAL StringInternal::StrCat
	VAR_INPUT
		pSrc 	: ^StringInternal;
	END_VAR
  VAR
  	pdata : ^usint;
  END_VAR

  pdata := pSrc^.GetData();
  if(pdata <> nil) then
    if(TxtCat(pdata, pSrc^.GetCharSize()) = true) then
      CalcCRC(); // to keep compatibility to older version
    end_if;
  end_if;

END_FUNCTION //GLOBAL StringInternal::StrCat
//[#ENGLISH]
// The function returns a CRC of the string's data buffer
// This CRC is recalculated everytime the contents are changed
//[<udCRC]32-bit-CRC
//[#DEUTSCH]
//Die Funktion liefert eine Prüfsumme über den Stringinhalt. Diese CRC
//wird bei jeder String-Änderung angepaßt.
//[<udCRC]32-bit-CRC
FUNCTION VIRTUAL GLOBAL StringInternal::GetCRC
VAR_OUTPUT
	udCRC		: UDINT;
END_VAR

	udCRC	:= m_udCRC;

END_FUNCTION //VIRTUAL GLOBAL StringInternal::GetCRC
//[#ENGLISH]
// Every time the string contents are changed, this function
// should be called to recalculate the check sum.
//[#DEUTSCH]
//Diese Funktion muß nach jeder String-Änderung aufgerufen werden,
//um die Prüfsumme über den Stringinhalt zu aktualisieren.
FUNCTION  StringInternal::CalcCRC

	m_udCRC := CRC32_Buffer(GetData(), DataBuffer.GetSize());

END_FUNCTION // StringInternal::CalcCRC
//[#ENGLISH]
// to have a defined state after configuration
// calculate the CRC
//[#DEUTSCH]
//Die CRC wird am Anfang berechnet, um diesen Wert zu initialisieren
FUNCTION VIRTUAL GLOBAL StringInternal::Init

  SingleRealloc := SingleRealloc.Read();
  if(m_udCRC = 0) then
    CalcCRC();
  end_if;
  
END_FUNCTION //VIRTUAL GLOBAL StringInternal::Init
//[#ENGLISH]
//The two strings are compared case sensitive. The function returns 0
//if the strings are exactly the same, otherwise it returns <>0.
//If one of the two strings is in UNICODE, then the other is converted
//to UNICODE, too, before the comparison.
//None of the strings is changed!
//[>pStr]pointer to the 2nd string
//[<udNotEqual]0 .. equal, <>0 not equal
//[#DEUTSCH]
//Die beiden Strings werden mit Unterscheidung von Groß/Kleinschreibung
//verglichen. Die Funktion liefert 0, wenn die beiden Strings exakt
//gleich sind, sonst <>0.
//Wenn einer der beiden Strings UNICODE-Zeichen enthält, dann wird auch
//der andere String auf UNICODE transformiert, bevor der Vergleich
//durchgeführt wird.
//Keiner der beiden Strings wird dadurch verändert!
//[>pStr]Zeiger auf den 2. String
//[<udNotEqual]0 .. gleich, <>0 .. unterschiedlich
FUNCTION VIRTUAL GLOBAL StringInternal::StrCmp
	VAR_INPUT
		pStr 	: ^StringInternal;
	END_VAR
	VAR_OUTPUT
		udNotEqual 	: UDINT;
	END_VAR

  udNotEqual := TxtCmp(pStr^.GetData(), pStr^.GetCharSize());
  
END_FUNCTION //GLOBAL StringInternal::StrCmp
//[#ENGLISH]
//The two strings are compared case insensitive. The function will return 0 if the
//strings are the same, otherwise it returns <>0.
//Comparing "Abc" with "Abc" or "Abc" with "ABC" will result in 0,
//comparing "PLC" with "SPS" will result in a value different from 0
//[>pStr]pointer to the 2nd string object
//[<udNotEqual]0 .. equal, <> 0 .. not equal
//[#DEUTSCH]
//Die beiden Strings werden ohne Berücksichtigung der Groß/Kleinschreibung
//miteinander verglichen. Die Funktion liefert für gleiche Strings 0,
//ansonsten einen Wert <> 0.
//Der Vergleich von "Abc" mit "Abc" oder von "Abc" mit "ABC" liefert 0,
//der Vergleich "PLC" mit "SPS" liefert einen Wert ungleich 0.
//[>pStr]Zeiger auf das 2. String Objekt
//[<udNotEqual]0 .. gleich, <> 0 .. ungleich
FUNCTION VIRTUAL GLOBAL StringInternal::StriCmp
	VAR_INPUT
		pStr 	: ^StringInternal;
	END_VAR
	VAR_OUTPUT
		udNotEqual 	: UDINT;
	END_VAR
  
  udNotEqual := TxtICmp(pStr^.GetData(), pStr^.GetCharSize());
  
END_FUNCTION //GLOBAL StringInternal::StriCmp
//[#DEUTSCH]
//Die Funktion kopiert die letzten udCnt Zeichen des Strings in den
//Zielstring. Wenn die angegebene Zeichenzahl größer als die String-
//länge ist, wird nur der ursprüngliche String kopiert.
//[>udCnt]Anzahl der zu kopierenden Zeichen
//[>pStr]Zeiger auf den Zielstring
//[#ENGLISH]
//The function copies the specified number of characters to the destination string. If
//the specified number exceeds the string length, only the string contents are copied.
//[>udCnt]number of characters to copy
//[>pStr]pointer to destination string
FUNCTION VIRTUAL GLOBAL StringInternal::Right
	VAR_INPUT
		udCnt 	: UDINT;
		pStr 	: ^StringInternal;
	END_VAR
VAR
	udLen		: UDINT;
	udBufSize	: UDINT;
	pData		: ^USINT;
	usSize		: USINT;
END_VAR

	udLen	:= StrLen();
	IF udCnt > udLen THEN
		udCnt	:= udLen;
	END_IF;

	udCnt += 1;		// wg. 0-Ende-Zeichen

	usSize := GetCharSize();
	IF usSize = 2 THEN
		udBufSize := 2 + udCnt * 2;
	ELSE
		udBufSize := udCnt;
	END_IF;

  IF (SingleRealloc = 0) THEN //  If client is not set the function works like it did before rev. >= 1.8
    IF pStr^.DataBuffer.SetSize( udBufSize ) = C_OK THEN
      pData := pStr^.GetData();
      IF usSize = 2 THEN
        pData$^UINT^ := 0x0200;
        pdata += 2;
      END_IF;
      _memcpy(pData, GetData() + DataBuffer.GetSize() - udCnt * usSize, udCnt * usSize);
      pStr^.AddTermination();
      pStr^.CalcCRC();
      DataBuffer.UpdateToFile();
    END_IF;
  ELSE
    IF (udBufSize > DataBuffer.m_udLength) THEN
      IF pStr^.DataBuffer.SetSize( udBufSize ) = C_OK THEN
        pData := pStr^.GetData();
        IF usSize = 2 THEN
          pData$^UINT^ := 0x0200;
          pdata += 2;
        END_IF;
        _memcpy(pData, GetData() + (GetLength() + usSize) - udCnt * usSize, udCnt * usSize);
        m_udlen := udBufSize; //  set the length which is used in next method
        pStr^.AddTermination();
        pStr^.CalcCRC();
        DataBuffer.UpdateToFile();
      END_IF;
    ELSE
      pData := pStr^.GetData();
      IF usSize = 2 THEN
        pData$^UINT^ := 0x0200;
        pdata += 2;
      END_IF;
      _memcpy(pData, GetData() + (GetLength() + usSize) - udCnt * usSize, udCnt * usSize);
      m_udlen := udBufSize; //  set the length which is used in next method
      pStr^.AddTermination();
      pStr^.CalcCRC();
      DataBuffer.UpdateToFile();

    END_IF;
  END_IF;

END_FUNCTION //GLOBAL StringInternal::Right
//[#DEUTSCH]
//Der linke Teil des Strings wird in den Zielstring kopiert. Wenn
//die angegebene Zeichenzahl größer als die Stringlänge ist, wird
//nur der ursprüngliche String kopiert.
//[>udCnt]Anzahl der zu kopierenden Zeichen
//[>pStr]Zeiger auf den Zielstring
//[#ENGLISH]
//The left part of the string is copied to the specified string object. If udCnt exceeds
//the string length, only the string contents are copied
//[>udCnt]number of characters to extract
//[>pStr]pointer to the destination string
FUNCTION VIRTUAL GLOBAL StringInternal::Left
	VAR_INPUT
		udCnt 	: UDINT;
		pStr 	: ^StringInternal;
	END_VAR
VAR
	udLen		: UDINT;
	udBufSize	: UDINT;
END_VAR

	udLen	:= StrLen();
	IF udCnt > udLen THEN
		udCnt	:= udLen;
	END_IF;

	IF GetCharSize() = 2 THEN
		udBufSize := 2 + udCnt * 2;
	ELSE
		udBufSize := udCnt;
	END_IF;

  IF (SingleRealloc = 0) THEN //  If client is not set the function works like it did before rev. >= 1.8
    IF pStr^.DataBuffer.SetSize( udBufSize ) = C_OK THEN
      pStr^.DataBuffer.SetData( GetData() );
      pStr^.AddTermination();
      pStr^.CalcCRC();
    END_IF;

  ELSE
    IF (udBufSize > DataBuffer.m_udLength) THEN
      IF pStr^.DataBuffer.SetSize( udBufSize ) = C_OK THEN
        pStr^.DataBuffer.SetData( GetData() );
        m_udlen := udBufSize; //  set the length which is used in next method
        pStr^.AddTermination();
        pStr^.CalcCRC();
      END_IF;

    ELSE
      pStr^.DataBuffer.SetData( GetData() );
      m_udlen := udBufSize; //  set the length which is used in next method
      pStr^.AddTermination();
      pStr^.CalcCRC();
    END_IF;
  END_IF;

END_FUNCTION //GLOBAL StringInternal::Left
//[#DEUTSCH]
//[!GET_ADD_INFO]
// Klassenaghängige Zusatzinformation wird geliefert
//[#ENGLISH]
//[!GET_ADD_INFO]
// returns class specific additional information
FUNCTION VIRTUAL GLOBAL StringInternal::Data::NewInst
VAR_INPUT
	pPara		: ^CmdStruct;
	pResult		: ^results;
END_VAR
VAR_OUTPUT
	ret_code		: iprStates;
END_VAR

	ret_code	:= VirtualBaseInit::NewInst(pPara, pResult);

  CASE pPara^.uiCmd $ VirtualBaseInit::CmdData OF
    GET_ADD_INFO:
      pResult^.uiLng			    := sizeof(UINT) + 1 + 1 + sizeof(UDINT);
      pResult^.aData[0]		    := VBI_STRING;
      pResult^.aData[1]		    := GetCharSize();
      // erst ab version 1.31, kann anhand von pResult^.uiLng >= 8 ermittelt werden
      pResult^.aData[2]$UDINT := GetCRC();
  END_CASE;

END_FUNCTION //VIRTUAL GLOBAL StringInternal::Data::NewInst
//[#ENGLISH]
//All lower case letters are converted to upper case letters. The
//string object itself will be changed.
//[#DEUTSCH]
//Alle Kleinbuchstaben werden in Großbuchstaben konvertiert. Durch diese
//Funktion wird der String selbst geändert.
FUNCTION VIRTUAL GLOBAL StringInternal::StrUpr
VAR
  pa : ^usint;
  pu : ^uint;
END_VAR

	pa := GetData();
  if(pa <> NIL) then
    if IsAscii() then
			_strupr(pa);
    else
      pu := pa$^uint;
      while pu^ do
        if((pu^ >= 'a') & (pu^ <= 'z')) then
          pu^ -= 'a'-'A';
        end_if;
        pu += 2;
      end_while;
    end_if;
    
	  CalcCRC();
    DataBuffer.UpdateToFile();
	end_if;

END_FUNCTION
//[#ENGLISH]
//All upper case letters are converted to lower case letters. The
//string object itself will be changed.
//[#DEUTSCH]
//Alle Großbuchstaben werden in Kleinbuchstaben konvertiert. Durch diese
//Funktion wird der String selbst geändert.
FUNCTION VIRTUAL GLOBAL StringInternal::StrLwr
VAR
  pu : ^uint;
  pa : ^usint;
END_VAR

	pa := GetData();
  if(pa <> NIL) then
    if IsAscii() then
      while pa^ do
        if((pa^ <= 'Z') & (pa^ >= 'A')) then
          pa^ -= ('A'-'a');
        end_if;
        pa += 1;
      end_while;
    else
      pu := pa$^uint;
      while pu^ do
        if((pu^ <= 'Z') & (pu^ >= 'A')) then
          pu^ -= ('A'-'a');
        end_if;
        pu += 2;
      end_while;
    end_if;
    
	  CalcCRC();
    DataBuffer.UpdateToFile();
  end_if;

END_FUNCTION
//[#ENGLISH]
//The function searches for the given character in its string-buffer.
//It returns -1 if the character was not found, otherwise the index
//of the 1st matching character.
//[>uiChar]	character to search for
//[#DEUTSCH]
//Die Funktion sucht im String-Puffer nach dem angegebenen Zeichen.
//Sie liefert -1, wenn das Zeichen nicht gefunden wurde, ansonsten
//den Index des ersten übereinstimmenden Zeichens.
//[>uiChar]	Zeichen, nach dem gesucht werden soll
FUNCTION VIRTUAL GLOBAL StringInternal::StrChr
	VAR_INPUT
		uiChar 	: UINT;
	END_VAR
	VAR_OUTPUT
		udPosition 	: UDINT;
	END_VAR
VAR
  pu : ^uint;
  pa : ^usint;
END_VAR

	pa := GetData();
  if(pa <> NIL) then
    udPosition := 0;
    if IsAscii() then
      while pa^ do
        if(pa^ = uiChar) then
          return;
        end_if;
        pa         += 1;
        udPosition += 1;
      end_while;
    else
      pu := pa$^uint;
      while pu^ do
        if(pu^ = uiChar) then
          return;
        end_if;
        pu         += 2;
        udPosition += 1;
      end_while;
    end_if;
  end_if;

  udPosition := 16#FFFFFFFF;
  
END_FUNCTION
//[#ENGLISH]
//All characters of a UNICODE-string are converted to ASCII-characters.
//If a character can not be transformed to ASCII-code, it will be replaced
//by a SPACE-character (0x20).
//[#DEUTSCH]
//Die Zeichen eines UNICODE-STrings werden in ASCII-Code gewandelt. Wenn
//sich ein Zeichen nicht auf ASCII-Code abbilden läßt, dann wird es durch
//ein Leerzeichen (0x20) ersetzt.
FUNCTION VIRTUAL GLOBAL StringInternal::ToAscii
VAR
  pa : ^usint;
  pu : ^uint;
  noc : udint;
END_VAR

	pa := GetData();
  if(pa <> NIL) then
    if IsUnicode() then
      pu  := pa$^uint + 2;
      noc := 0;
      while(pu^) do
        if(pu^ < 256) then
          pa^ := pu$^usint^;
        else
          pa^ := 32; // space
        end_if;
        pu  += 2;
        pa  += 1;
        noc += 1;
      end_while;
      pa^ := 0;
      noc += 1;

      if(SingleRealloc = 0) then // If client is not set the function works like it did before rev. >= 1.8
        DataBuffer.SetSize(noc); // shrink buffer
      end_if;
      
      CalcCRC();
      DataBuffer.UpdateToFile();
    end_if;
  end_if;
  
END_FUNCTION
//[#ENGLISH]
//All characters of an ASCII-string are converted to UNICODE.
//[#DEUTSCH]
//Alle Zeichen eines ASCII-Strings werden auf UNICODE übersetzt.
FUNCTION VIRTUAL GLOBAL StringInternal::ToUniCode
VAR
  pa : ^usint;
  pu : ^uint;
  noc, len : udint;
END_VAR


  if IsAscii() then
    noc := GetLength() + 1;
    len := (noc + 1) * sizeof(uint); // unicodekennung + uni-0-string

    if(SingleRealloc = 0) then // If client is not set the function works like it did before rev. >= 1.8
      if(DataBuffer.SetSize(len) <> C_OK) then
        return;
      end_if;
    else
      if(len > DataBuffer.m_udLength) then
        if(DataBuffer.SetSize(len) <> C_OK) then
          return;
        end_if;
      end_if;
    end_if;

    pa  := GetData();

    if(pa <> NIL) then

      pu  := pa$^uint + len;
      pa  += noc;

      while noc do
        pu  -= 2;
        pa  -= 1;
        pu^ := pa^;
        noc -= 1;
      end_while;

      pu  -= 2;
      pu^ := 16#0200;  // unicode kennung
    
      CalcCRC();
      DataBuffer.UpdateToFile();

    end_if;
  end_if;

END_FUNCTION//[#ENGLISH]
//[#ENGLISH]
//Checks, if the string is terminated with a 0-character. If not, 
//a 0-character is appended. The string length is not changed by
//this function.
//[#DEUTSCH]
//Prüft, ob ein String mit 0 abgeschlossen ist. Wenn nicht, dann
//wird hier ein '\0'-Zeichen angehängt. Die Stringlänge ändert sich dadurch 
//nicht.
FUNCTION  StringInternal::AddTermination
VAR
	pa			:^USINT;
	udLen		: UDINT;
	usSize		: USINT;
  tmplen    : UDINT;
END_VAR

	usSize  := GetCharSize();

  if (SingleRealloc = 0) then
    udLen := DataBuffer.GetSize();  // total buffer size in bytes
  else
  	udLen	:= m_udlen; //  get number of chars
  end_if;

	IF((usSize = 1) & (udLen >= 1)) | ((usSize = 2) & (udLen >= 4)) THEN // space for at least on character
    pa := GetData();
    if pa <> nil then   // HlaWol v1.71
    
      pa += (udLen - usSize);
      if(usSize = 1) then
        if(pa^ = 0) then
          return; // ascii-0-terminated
        end_if;
      else
        if(pa^$uint = 0) then
          return; // uni-0-terminated
        end_if;
      end_if;
      
      tmplen := udLen + usSize;
      
      // allocate space for new 0-char
      IF (SingleRealloc = 0) THEN //  If client is not set the function works like it did before rev. >= 1.8
        IF DataBuffer.SetSize(tmplen) <> C_OK THEN
          RETURN;
        END_IF;
      ELSE
        IF ((udLen+usSize) > DataBuffer.m_udLength) THEN
          IF (DataBuffer.SetSize(tmplen) <> C_OK) then
            RETURN;

          END_IF;
        END_IF;
      END_IF;

      pa	:= GetData();
      if pa <> nil then   // HlaWol v1.71
        
        pa  += udLen;
        pa^ := 0;
        if(usSize = 2) then
          pa^$uint := 0;
        end_if;
        
      end_if;

      DataBuffer.UpdateToFile();
    end_if;      
	ELSE
		IF usSize = 1 THEN

      pa := GetData(); //  get the pointer
      IF(pa <> NIL) THEN //  got pointer?
        pa^ := 0; //  first char to zero because of changed method GetLength()
      END_IF;

      IF (SingleRealloc = 0) THEN //  If client is not set the function works like it did before rev. >= 1.8
        DataBuffer.SetSize(0);
      END_IF;
        
		ELSE
      IF (SingleRealloc = 0) THEN //  If client is not set the function works like it did before rev. >= 1.8
  			DataBuffer.SetSize(4);
      ELSE
        IF (DataBuffer.m_udLength < 4) THEN
          DataBuffer.SetSize(4);
        END_IF;
      END_IF;

			pa := GetData();
      if pa <> nil then   // HlaWol v1.71
        pa += 2;
        pa$^UINT^ := 0;
      end_if;
		END_IF;
    
    DataBuffer.UpdateToFile();
	END_IF;

END_FUNCTION // StringInternal::AddTermination 

//[#ENGLISH]
//Returns the number of characters in the string.
//The string length does not include the terminating zero.
//[#DEUTSCH]
//Liefert die Anzahl der Zeichen in einem String.
//Die Abschluß - Null ist nicht inkludiert.
FUNCTION VIRTUAL GLOBAL StringInternal::StrLen
	VAR_OUTPUT
		udLen 	: UDINT;
	END_VAR

  udLen := GetLength();
	if IsUnicode() then
    udLen :=  (udLen / 2) - 1;
	END_IF;

END_FUNCTION
//[#ENGLISH]
//Set a character to the String at a given position
//[>pData]pointer to source
//[>udAt]offset within the string-buffer
//[#DEUTSCH]
//Setzt ein Zeichen an einer bestimmten Position des Strings
//[>pData]Zeigt auf die Quelldaten
//[>udAt]Position im String an der das Zeichen gesetzt wird
FUNCTION VIRTUAL GLOBAL StringInternal::SetDataAt
	VAR_INPUT
		pData 	: ^UINT;
		udAt 	: UDINT;
	END_VAR
	VAR_OUTPUT
		ret_code 	: ConfStates;
	END_VAR
VAR
	udSize		: UDINT;
END_VAR
	
	IF IsUniCode() THEN
		udSize := 2;
		udAt *= 2;
		//++pr 10.12.2004: 
		//	Wenn udAt 0 ist, dann sollte es meiner Meinung nach auf das 1. Zeichen 
		//	und nicht auf das Zeichengrößen-Wort zeigen.
		//	Wg. der Kompatibilität zu früheren Versionen habe ich aber nichts geändert.
	ELSE
		udSize := 1;
	END_IF;

	ret_code := DataBuffer.SetDataAt(pData$^USINT, udSize, udAt);

	CalcCRC();

END_FUNCTION //GLOBAL StringInternal::SetDataAt
//[#ENGLISH]
//returns 1 for ASCII strings and 2 for Unicode strings
//[<usSize]size of one character in the string (ASCII vs. Unicode)
FUNCTION VIRTUAL GLOBAL StringInternal::GetCharSize
	VAR_OUTPUT
		usSize 	: USINT;
	END_VAR
VAR
	pu : ^uint;
END_VAR

  usSize := 1;

  pu$^usint := GetData();
  if(pu <> NIL) then
    if(DataBuffer.GetSize() >= 2) then
      if(pu^ = 16#0200) then
        usSize := 2;
      end_if;
    end_if;
  end_if;

END_FUNCTION //GLOBAL StringInternal::GetCharSize


FUNCTION VIRTUAL GLOBAL StringInternal::Data::Read
	VAR_OUTPUT
		output (EAX) 	: UDINT;
	END_VAR

	output := NIL $ UDINT;

END_FUNCTION //VIRTUAL GLOBAL StringInternal::Data::Read
//[#ENGLISH]
// input is taken as a pointer to another string object. StrCpy is called to copy the
// string into the current object.
//[>input] pointer to a source string
//[#DEUTSCH]
//Der Übergabe-Parameter wird als Zeiger auf ein String-Objekt interpretiert. Die Funktion kopiert
//den Inhalt dieses String in den eigenen String.
//[>input] Zeiger auf den Quellstring


FUNCTION VIRTUAL GLOBAL StringInternal::Data::Write
	VAR_INPUT
		input (EAX) 	: UDINT;
	END_VAR
	VAR_OUTPUT
		result (EAX) 	: UDINT;
	END_VAR

  Data := input;
	StrCpy(input$^StringInternal);
  result := Data;


END_FUNCTION //VIRTUAL GLOBAL StringInternal::Data::Write
//[#ENGLISH]
// returns the length of the raw data (without termination-0)
//[<udLen]string length
//[#DEUTSCH]
//liefert die Länge der Strings-Rohdaten ohne Abschluß-Null
//[<udLen]Stringlänge


FUNCTION VIRTUAL GLOBAL StringInternal::WriteDataOffUni
VAR_INPUT
  udlen 	: UDINT;
  udOff 	: UDINT;
  pData 	: ^UINT;
  usSize 	: USINT;
END_VAR
VAR
  thelp : array[0..SI_TMP_HELPSIZE] of usint;
	pu : ^UINT;
END_VAR
  
  // --- HubChr v1.81 in case of ASCII string, length of 1 character DOES make sense!
  IF pData THEN 
    IF usSize = 1 & udLen >= 1 then
      WriteDataOff(udLen, udOff, pData$^USINT);
    ELSIF usSize = 2 & udLen >= 2 THEN
  // --- End HubChr v1.81

      IF(udOff = 0) THEN
        if(TmpAlloc(#pu, udlen+2, #thelp[0], sizeof(thelp)) <> 0) then
          pu^ := 16#0200;
          _memcpy(pu+2, pData, udlen);
          WriteDataOff(udlen+2, udOff, pu$^usint);
          TmpFree(#pu, #thelp[0]);
        end_if;
      ELSE
        //  increase the offset, because the identifier is in front of the string
        udOff += 2;
        //  call write method with new offset
        WriteDataOff(udlen, udOff, pData$^USINT);

      END_IF;
    END_IF;
  END_IF;

END_FUNCTION

// *************************************************************************************************
// *************************************************************************************************
// ** NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW **
// ** NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW **
// *************************************************************************************************
// *************************************************************************************************

#define StrInt_GetData()     DataBuffer.GetDataPtr()
#define StrInt_IsAscii()     TxtGetCharSize() = sizeof(char)
#define StrInt_IsUniCode()   TxtGetCharSize() = sizeof(uint)
#define StrInt_CrcMakro(len) CRC32_Buffer((StrInt_GetData()), (len))

FUNCTION StrInt_StrLen16 var_input pu:^uint; end_var var_output retcode:udint; end_var

  retcode := 0;
  while(pu^) do
    pu += 2;
    retcode += 1;
  end_while;
  
end_function

FUNCTION StrInt_StrNCpy16 var_input pd:^uint; ps:^uint; maxlen:udint; end_var

  while((ps^) & (maxlen > 0)) do
    pd^ := ps^;
    ps  += 2;
    pd  += 2;
    maxlen -= 1;
  end_while;
  pd^ := 0;
  
end_function

FUNCTION StrInt_StrNCpy08 var_input pd:^usint; ps:^usint; maxlen:udint; end_var

  while((ps^) & (maxlen > 0)) do
    pd^ := ps^;
    ps  += 1;
    pd  += 1;
    maxlen -= 1;
  end_while;
  pd^ := 0;
  
end_function

FUNCTION StringInternal::TmpFree
  VAR_INPUT
    ppd : ^pvoid;
    phelp : ^void;
  end_var
  VAR
  	tmp : ^void;
  END_VAR

  tmp := ppd^;
  if((tmp <> nil) & (tmp <> phelp)) then
    _free(tmp);
  end_if;
  ppd^ := nil;

END_FUNCTION

FUNCTION StringInternal::TmpAlloc
  VAR_INPUT
    ppd : ^pvoid;
    bytesize : udint;
    phelp : ^void;
    helpsize : udint;
  end_var
  var_output
    retcode : udint;  
  end_var

  if(bytesize > helpsize) then
    phelp := _alloc(bytesize);
  end_if;
  ppd^    := phelp;
  retcode := (phelp <> nil);

END_FUNCTION

FUNCTION StringInternal::AddDataIntern
  VAR_INPUT
    pData : ^usint;
    udLen  : udint;
    udOff : udint;
  END_VAR
  var_output
    retcode : bool;
  end_var
  VAR
    tmplen : udint;
    state : ConfStates;
  END_VAR

  retcode := false;
  state   := C_OK;
  tmplen  := udOff + udLen;
  
  if(SingleRealloc = 0) then
    state := DataBuffer.SetSize(tmplen); // set accurate stringlength
  else
    if(tmplen > DataBuffer.GetSize()) then //m_udLength) then
      state := DataBuffer.SetSize(tmplen); // set accurate stringlength on grow
    end_if;
  end_if;

  if(state = C_OK) then
    DataBuffer.SetDataAt(pData, udLen, udOff); // copy data into databuffer
    m_udlen := tmplen;
    m_udCRC := StrInt_CrcMakro(tmplen);
    retcode := true;
  end_if;

END_FUNCTION

FUNCTION StringInternal::ToUniSequence
	VAR_INPUT
		pu 	: ^UINT;
		pa 	: ^USINT;
		length 	: UDINT;
    zerotermination : bool;
	END_VAR

  // function will work inplace --> therefore reverse convert
  pa  += length;
  pu  += (length * 2);
  
  if(zerotermination = true) then
    pu^ := 0;
  end_if;
  
  while(length > 0) do
    length -= 1;
    pu     -= 2;
    pa     -= 1;
    pu^    := pa^;
  end_while;
  
END_FUNCTION

FUNCTION StringInternal::ToAsciiSequence
	VAR_INPUT
		pa 	: ^USINT;
		pu 	: ^UINT;
		length 	: UDINT;
    zerotermination : bool;
	END_VAR

  // function will work inplace --> therefore forward convert
  while(length > 0) do
    length -= 1;
    pa^    := pu$^usint^;
    if(pu^ > 255) then
      pa^  := 32;
    end_if;
    pu += 2;
    pa += 1;
  end_while;
  
  if(zerotermination = true) then
    pa^ := 0;
  end_if;
  
END_FUNCTION

FUNCTION StringInternal::CmpUniAscii
	VAR_INPUT
		pu 	: ^UINT;
		pa 	: ^USINT;
		len 	: UDINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: UDINT;
	END_VAR

  retcode := 0;
  while(len > 0) do
    len -= 1;
    if(pa^ <> pu^) then
      retcode := 1;
      return;
    end_if;
    pa += 1;
    pu += 2;
  end_while;  

END_FUNCTION

FUNCTION StringInternal::ICmpUniUni
	VAR_INPUT
		pu1 	: ^UINT;
		pu2 	: ^UINT;
		len 	: UDINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: UDINT;
	END_VAR
  VAR
  	ch1, ch2 : uint;
  END_VAR
  
  retcode := 0;
  while(len > 0) do
    len -= 1;
    ch1 := pu1^;
    ch2 := pu2^;
    pu1 += 2;
    pu2 += 1;
    if((ch1 <= 'Z') & (ch1 >= 'A')) then ch1 := ch1 + ('a' - 'A'); end_if;
    if((ch2 <= 'Z') & (ch2 >= 'A')) then ch2 := ch2 + ('a' - 'A'); end_if;
    if(ch1 <> ch2) then
      retcode := 1;
      return;
    end_if;
  end_while; 

END_FUNCTION

FUNCTION StringInternal::ICmpUniAscii
	VAR_INPUT
		pu 	: ^UINT;
		pa 	: ^USINT;
		len 	: UDINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: UDINT;
	END_VAR
  VAR
  	ch1, ch2 : uint;
  END_VAR

  retcode := 0;
  while(len > 0) do
    len -= 1;
    ch1 := pu^;
    ch2 := pa^;
    pu  += 2;
    pa  += 1;
    if((ch1 <= 'Z') & (ch1 >= 'A')) then ch1 := ch1 + ('a' - 'A'); end_if;
    if((ch2 <= 'Z') & (ch2 >= 'A')) then ch2 := ch2 + ('a' - 'A'); end_if;
    if(ch1 <> ch2) then
      retcode := 1;
      return;
    end_if;
  end_while;  

END_FUNCTION

FUNCTION StringInternal::CatAtIntern
	VAR_INPUT
		isuni 	: udint;
		chroffset 	: UDINT;
		psrc 	: ^void;
		chrsize 	: UDINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  VAR
    thelp : array[0..SI_TMP_HELPSIZE] of usint;
  	sln, ubom : udint;
    pu : ^uint;
    pa : ^usint;
  END_VAR

  retcode := true;

  if(psrc <> NIL) then // just on valid pointer
    if(chrsize = 1) then 
      // given string is a ascii-0-string
      sln := _strlen(psrc$^usint) + 1;
      if(isuni) then
        // destination is in uni-style
        
        if(chroffset = 0) then
          if(TmpAlloc(#pu, sln*2+2, #thelp[0], sizeof(thelp)) <> 0) then
            pu^ := 16#0200;
            ToUniSequence(pu+2, psrc$^usint, sln, false);
            retcode := AddDataIntern(pu$^usint, sln*2+2, 0);
            TmpFree(#pu, #thelp[0]);
          end_if;
        else
          if(TmpAlloc(#pu, sln*2, #thelp[0], sizeof(thelp)) <> 0) then
            ToUniSequence(pu, psrc$^usint, sln, false);
            retcode := AddDataIntern(pu$^usint, sln*2, chroffset*2+2);
            TmpFree(#pu, #thelp[0]);
          end_if;
        end_if;
        
      else
        // destination is in ascii-style
        retcode := AddDataIntern(psrc$^usint, sln, chroffset);
      end_if;
    else
      // given string is a uni-0-string
      
      ubom := 0;
      if(psrc$^uint^ = 16#0200) then
        psrc += 2; // ignore unicode id
        ubom := 1; // unicode-id is present
      end_if;
      
      sln := StrInt_StrLen16(psrc$^uint) + 1;
      if(isuni) then
        // destination is in uni-style
        if(chroffset = 0) then
          if(ubom = 1) then
            psrc -= 2;
            retcode := AddDataIntern(psrc$^usint, sln*2+2, 0);
          else
            if(TmpAlloc(#pu, sln*2+2, #thelp[0], sizeof(thelp)) <> 0) then
              pu^:= 16#0200;
              _memcpy(pu+2, psrc, sln*2);
              retcode := AddDataIntern(pu$^usint, sln*2+2, 0);
              TmpFree(#pu, #thelp[0]);
            end_if;
          end_if;
        else
          retcode := AddDataIntern(psrc$^usint, sln*2, chroffset*2+2);
        end_if;
        
      else
        // destination is in ascii-style
        if(TmpAlloc(#pa, sln, #thelp[0], sizeof(thelp)) <> 0) then
          ToAsciiSequence(pa, psrc$^uint, sln, false);
          retcode := AddDataIntern(pa$^usint, sln, chroffset);
          TmpFree(#pa, #thelp[0]);
        end_if;
      end_if;
    end_if;
  end_if;

END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtCatAt
	VAR_INPUT
		chroffset 	: UDINT;
		psrc 	: ^void;
		chrsize 	: UDINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR

  retcode := CatAtIntern(StrInt_IsUnicode(), chroffset, psrc, chrsize);

END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtCat
	VAR_INPUT
		psrc 	: ^void;
		chrsize 	: UDINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  VAR
  	len, isuni : udint;
  END_VAR
  
  isuni   := StrInt_IsUnicode();
  len     := TxtLen();
  retcode := CatAtIntern(isuni, len, psrc, chrsize);
  
END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtCmp
	VAR_INPUT
		psrc 	: ^void;
		chrsize 	: UDINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: UDINT;
	END_VAR
  VAR
    tmpstr : uint;
  	pdst  : ^void;
    slen, dlen, dchrsize : udint;
  END_VAR

  retcode := 1;

  if(psrc = nil) then
    tmpstr := 0; // treat nil as ""
    psrc   := #tmpstr;
  elsif(chrsize = 2) then
    if(psrc$^uint = 16#0200) then
      psrc += 2; // ignore unicode id
    end_if;
  end_if;

  if(chrsize = 2) then
    slen := StrInt_StrLen16(psrc$^uint);
  else
    slen := _strlen(psrc$^char);
  end_if;

  dchrsize := 1;
  pdst     := StrInt_GetData();
  if(pdst = nil) then
    tmpstr := 0; // treat nil as ""
    pdst   := #tmpstr;
    dlen   := 0;
  else
    dlen := TxtLen();
    if(StrInt_IsUnicode()) then
      dchrsize := 2;
      pdst     += 2; // ignore unicode id
    end_if;
  end_if;

  if(dlen = slen) then // both strings are of same charlength
    if(dchrsize = chrsize) then
      retcode := _memcmp(pdst, psrc, dlen*dchrsize);
    else
      if(chrsize = 2) then
        retcode := CmpUniAscii(psrc$^uint, pdst$^usint, dlen);
      else
        retcode := CmpUniAscii(pdst$^uint, psrc$^usint, dlen);
      end_if;
    end_if;
  end_if;

END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtICmp
	VAR_INPUT
		psrc 	: ^void;
		chrsize 	: UDINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: UDINT;
	END_VAR
  VAR
    tmpstr : uint;
  	pdst  : ^void;
    slen, dlen, dchrsize : udint;
  END_VAR

  retcode := 1;

  if(psrc = nil) then
    tmpstr := 0; // treat nil as ""
    psrc   := #tmpstr;
  elsif(chrsize = 2) then
    if(psrc$^uint = 16#0200) then
      psrc += 2; // ignore unicode id
    end_if;
  end_if;

  if(chrsize = 2) then
    slen := StrInt_StrLen16(psrc$^uint);
  else
    slen := _strlen(psrc$^char);
  end_if;

  dchrsize := 1;
  pdst     := StrInt_GetData();
  if(pdst = nil) then
    tmpstr := 0; // treat nil as ""
    pdst   := #tmpstr;
    dlen   := 0;
  else
    dlen := TxtLen();
    if(StrInt_IsUnicode()) then
      dchrsize := 2;
      pdst     += 2; // ignore unicode id
    end_if;
  end_if;

  if(dlen = slen) then // both strings are of same charlength
    if(dchrsize = chrsize) then
      if(chrsize = 1) then
        retcode := _memicmp(pdst, psrc, dlen);
      else
        retcode := ICmpUniUni(pdst$^uint, psrc$^uint, dlen);
      end_if;
    else
      if(chrsize = 2) then
        retcode := ICmpUniAscii(psrc$^uint, pdst$^usint, dlen);
      else
        retcode := ICmpUniAscii(pdst$^uint, psrc$^usint, dlen);
      end_if;
    end_if;
  end_if;
  
END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtGet
	VAR_INPUT
		pdst 	: ^void;
		dstsize 	: UDINT;
	END_VAR
	VAR_OUTPUT
		charsize 	: UDINT;
	END_VAR
  VAR
  	ps : ^usint;
  END_VAR
 
  charsize := 0;
  if((pdst <> nil) & (dstsize > 0)) then
    charsize     := 1;
    pdst$^usint^ := 0; // 0-termination
    
    ps := StrInt_GetData();
    if(ps <> nil) then
      if(StrInt_IsUnicode()) then
        if(dstsize >= 2) then
          StrInt_StrNCpy16(pdst$^uint, ps$^uint+2, dstsize/2-1);
          charsize := 2;
        end_if;
      else
        StrInt_StrNCpy08(pdst$^usint, ps, dstsize-1);
      end_if;
    end_if;
  end_if;
  
END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtGetAscii
	VAR_INPUT
		pdst 	: ^CHAR;
		dstsize 	: UDINT;
	END_VAR
	VAR_OUTPUT
		charsize 	: UDINT;
	END_VAR
  VAR
  	ps : ^usint;
    len : udint;
  END_VAR
 
  charsize := 0;
  if((pdst <> nil) & (dstsize > 0)) then
    charsize     := 1;
    pdst$^usint^ := 0; // 0-termination
    
    ps := StrInt_GetData();
    if(ps <> nil) then
      if(StrInt_IsUnicode()) then
        len := StrInt_StrLen16(ps$^uint+2);
        if(dstsize >= len) then
          len := dstsize - 1;  
        end_if;
        ToAsciiSequence(pdst, ps$^uint+2, len, true);
      else
        StrInt_StrNCpy08(pdst$^usint, ps, dstsize-1);
      end_if;
    end_if;
  end_if;
  
END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtGetAt
	VAR_INPUT
		pdst 	: ^void;
		dstsize 	: UDINT;
    fromwhere : udint;
    nchar : udint;
	END_VAR
	VAR_OUTPUT
		charsize 	: UDINT;
	END_VAR
  VAR
  	ps : ^usint;
    len, tmp : udint;
  END_VAR

  charsize := 0;
  if((pdst <> nil) & (dstsize > 0)) then
    charsize     := 1;
    pdst$^usint^ := 0; // 0-termination

    ps := StrInt_GetData();
    if(ps <> nil) then
      len := TxtLen();
      
      if(fromwhere < len) then
        tmp := len - fromwhere;
        if(nchar > tmp) then
          nchar := tmp;
        end_if;
        
        if(StrInt_IsUnicode()) then
          if(dstsize >= 2) then
            tmp := (dstsize / 2) - 1;
            if(nchar > tmp) then
              nchar := tmp;
            end_if;
            StrInt_StrNCpy16(pdst$^uint, ps$^uint+2+fromwhere*2, nchar);
            charsize := 2;
          end_if;
        else
          tmp := dstsize - 1;
          if(nchar > tmp) then
            nchar := tmp;
          end_if;
          StrInt_StrNCpy08(pdst$^usint, ps+fromwhere, nchar);
        end_if;
      end_if;
    end_if;
  end_if;
  
END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtSet
	VAR_INPUT
		dstchrsize 	: UDINT;
		psrc 	: ^void;
		srcchrsize 	: UDINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  
  if(dstchrsize = 1) then
    KillUBOM();
  end_if;
  
  retcode := CatAtIntern((dstchrsize = 2), 0, psrc, srcchrsize);

END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtSetChr
	VAR_INPUT
		characteroffset 	: UDINT;
		character 	: UDINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  VAR
  	len, tmp : udint;
    pd, pa : ^usint;
  END_VAR

  retcode := true;
  len     := TxtLen();
  pd      := StrInt_GetData();
  
  if((characteroffset < len) & (pd <> nil)) then
    // xchange character
    retcode := true;
    if(StrInt_IsUnicode()) then
      pa         := pd + characteroffset*2+2;
      pa$^uint^  := character$uint;
      if(character = 0) then
        len := characteroffset; // string termination is inserted
      end_if;
      m_udCRC := StrInt_CrcMakro(len*2+2);
    else
      pa         := pd + characteroffset;
      pa$^usint^ := character$usint;
      if(character = 0) then
        len := characteroffset; // string termination is inserted
      end_if;
      m_udCRC := StrInt_CrcMakro(len+1);
    end_if;
    DataBuffer.UpdateToFile();
  else
    // add character
    tmp := character and 16#FFFF;
    if(tmp > 255) then
      retcode := TxtCat(#tmp, 2);
    else
      retcode := TxtCat(#tmp, 1);
    end_if;
  end_if;

END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtClear
  VAR
  	tmp : array[0..3] of usint;
  END_VAR

  if(StrInt_GetData() <> nil) then
    tmp[0]$udint := 16#00000200;
    if(StrInt_IsUnicode()) then
      AddDataIntern(#tmp[0], 4, 0);
    else
      AddDataIntern(#tmp[0], 1, 0);
    end_if;
  end_if;
  
END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtChr
	VAR_INPUT
		character 	: UDINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: UDINT;
	END_VAR
  VAR
  	pa : ^usint;
  	pu : ^uint;
  END_VAR
  
  pa := StrInt_GetData();
  if(pa <> nil) then
    retcode := 0;
    if(StrInt_IsUnicode()) then
      pu := pa + 2;
      if(character = 0) then
        while(pu^) do
          retcode += 1;
          pu      += 2;
        end_while;
        return;
      else
        while(pu^) do
          if(pu^ = character$uint) then
            return;
          end_if;
          retcode += 1;
          pu      += 2;
        end_while;
      end_if;
    else
      if(character = 0) then
        while(pa^) do
          retcode += 1;
          pa      += 1;
        end_while;
        return;
      else
        while(pa^) do
          if(pa^ = character$usint) then
            return;
          end_if;
          retcode += 1;
          pa      += 1;
        end_while;
      end_if;
    end_if;
  end_if;
  
  retcode := 16#FFFFFFFF;
  
END_FUNCTION
    
FUNCTION VIRTUAL GLOBAL StringInternal::TxtLen
	VAR_OUTPUT
		retcode 	: UDINT;
	END_VAR
  VAR
  	pa : ^usint;
  END_VAR
  
  retcode := 0;
  pa      := StrInt_GetData();
  if(pa <> nil) then
  
    if(DataBuffer.GetSize() >= 2) then
      if(pa$^uint^ = 16#0200) then    
        retcode := StrInt_StrLen16(pa$^uint+2);
        return;
      end_if;
    end_if;
    retcode := _strlen(pa);
    
//    if(StrInt_IsUnicode()) then
//      retcode := StrInt_StrLen16(pa$^uint+2);
//    else
//      retcode := _strlen(pa);
//    end_if;
  end_if;

END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtIns
	VAR_INPUT
		index_at 	: UDINT;
		psrc 	: ^void;
		chrsize 	: UDINT;
		chrcount 	: UDINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  VAR
    thelp : array[0..SI_TMP_HELPSIZE] of usint;
    len, sln, tmp, dca, soff, doff : udint;
    pa : ^usint;
    pu : ^uint;
  END_VAR

  retcode := true;
  
  if(chrcount > 0) then
  
    retcode := false;
  
    if(psrc = nil) then
      retcode := TxtSetChr(index_at, 0);
      return;
    end_if;
  
    if(chrsize = 2) then
      sln := StrInt_StrLen16(psrc$^uint);
      if(sln >= 2) then
        if(psrc$^uint^ = 16#0200) then
          psrc += 2;
          sln -= 2;
        end_if;
      end_if;
    else
      chrsize := 1;
      sln     := _strlen(psrc$^char);
    end_if;
    
    if(chrcount > sln) then
      chrcount := sln;
    end_if;
    
    if(chrcount > 0) then
      len := TxtLen(); // get deststringlength
      
      if(index_at < len) then
        // insert inbetween
        dca := TxtGetCharSize(); // destination character size
        tmp := (len + 1 + chrcount) * dca;
        if(TmpAlloc(#pa, tmp, #thelp[0], sizeof(thelp)) <> 0) then
          dca := TxtGet(pa, tmp);
          if(dca > 0) then
            soff := index_at * dca;
            doff := (index_at + chrcount) * dca;
            tmp  := (len - index_at + 1) * dca;
            _memmove(pa+doff, pa+soff, tmp);
            if(dca = chrsize) then
              _memcpy(pa+soff, psrc, chrcount*dca);
            else
              if(chrsize = 2) then
                ToAsciiSequence(pa+soff, psrc$^uint, chrcount, false);
              else
                ToUniSequence(pa$^uint+soff, psrc$^usint, chrcount, false);
              end_if;
            end_if;
            retcode := TxtSet(dca, pa, dca);
          end_if;
      
          TmpFree(#pa, #thelp[0]);
        end_if;
      else
        // cat at end + termination
        tmp := chrcount * chrsize;
        if(TmpAlloc(#pa, tmp+2, #thelp[0], sizeof(thelp)) <> 0) then
          _memcpy(pa, psrc, tmp);
          pu  := pa + tmp;
          pu^ := 0; // do termination
          retcode := TxtCat(pa, chrsize); // concatenate
          TmpFree(#pa, #thelp[0]);
        end_if;
      end_if;
    end_if;
  end_if;
  
END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtToAscii
  VAR_OUTPUT
    retcode : bool;
  END_VAR
  VAR
  	pd : ^usint;
    len : udint;
  END_VAR

  retcode := true;

  pd := StrInt_GetData();
  if(pd <> nil) then
    if(StrInt_IsUnicode()) then
      len := TxtLen() + 1;
      if(len = 1) then
        KillUBOM();
      end_if;
      ToAsciiSequence(pd, pd$^uint+2, len, false);
      if(SingleRealloc = 0) then
        DataBuffer.SetSize(len);
      end_if;
      DataBuffer.UpdateToFile();
      m_udCRC := StrInt_CrcMakro(len);
    end_if;
  end_if;

END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtToUni
  VAR_OUTPUT
    retcode : bool;
  END_VAR
  VAR
    thelp : array[0..SI_TMP_HELPSIZE] of usint;
  	pd : ^usint;
    pu : ^uint;
    len : udint;
  END_VAR

  retcode := true;

  pd := StrInt_GetData();
  if(pd = nil) then
    retcode := TxtSet(2, "", 1);
  else
    if(StrInt_IsAscii()) then
      len := TxtLen() + 1;
      if(TmpAlloc(#pu, len*2+2, #thelp[0], sizeof(thelp)) <> 0) then
        pu^ := 16#0200;
        ToUniSequence(pu+2, pd, len, false);
        retcode := AddDataIntern(pu$^usint, len*2+2, 0);
        TmpFree(#pu, #thelp[0]);
      end_if;
    end_if;
  end_if;

END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtUpr
  VAR
    pa : ^usint;
    pu : ^uint;
    size : udint;
  END_VAR

	pa := StrInt_GetData();
  
  if(pa <> NIL) then
    if(StrInt_IsUnicode()) then
      pu   := pa$^uint + 2;
      size := 4; // 16#0200 + termination
      while(pu^) do
        if((pu^ >= 'a') & (pu^ <= 'z')) then
          pu^ -= 'a'-'A';
        end_if;
        pu   += 2;
        size += 2;
      end_while;
    else
			_strupr(pa);
      size := _strlen(pa) + 1;
    end_if;
    
    DataBuffer.UpdateToFile();
    m_udCrc := StrInt_CrcMakro(size);
	end_if;

END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtLwr
  VAR
    pu : ^uint;
    pa : ^usint;
    size : udint;
  END_VAR

	pa := StrInt_GetData();
  if(pa <> NIL) then
    if(StrInt_IsUnicode()) then
      pu   := pa$^uint + 2;
      size := 4; // 16#0200 + termination
      while(pu^) do
        if((pu^ <= 'Z') & (pu^ >= 'A')) then
          pu^ -= ('A'-'a');
        end_if;
        pu   += 2;
        size += 2;
      end_while;
    else
      size := 1; // termination
      while(pa^) do
        if((pa^ <= 'Z') & (pa^ >= 'A')) then
          pa^ -= ('A'-'a');
        end_if;
        pa   += 1;
        size += 1;
      end_while;
    end_if;
    
    DataBuffer.UpdateToFile();
    m_udCrc := StrInt_CrcMakro(size);
  end_if;

END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtGetCharSize
	VAR_OUTPUT
		retcode 	: USINT;
	END_VAR
  VAR
	  pu : ^uint;
  END_VAR

  retcode   := 1;
  pu$^usint := StrInt_GetData();
  if(pu <> NIL) then
    if(DataBuffer.GetSize() >= 2) then
      if(pu^ = 16#0200) then
        retcode := 2;
      end_if;
    end_if;
  end_if;

END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtGetCRC
	VAR_OUTPUT
		retcode 	: UDINT;
	END_VAR

  retcode := m_udCrc;

END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::ObjCat
	VAR_INPUT
		pStr 	: ^StringInternal;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  VAR
  	ps : ^usint;
    chrsize : udint;
  END_VAR

  retcode := true;
  
  if(pStr <> nil) then
    ps := pStr^.StrInt_GetData();
    if(ps <> nil) then
      chrsize := pStr^.TxtGetCharSize();
      retcode := TxtCat(ps, chrsize);
    end_if;
  end_if;
  
END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::ObjCatAt
	VAR_INPUT
		chroffset 	: UDINT;
		pStr 	: ^StringInternal;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  VAR
  	ps : ^usint;
    chrsize : udint;
  END_VAR

  retcode := true;
  
  if(pStr <> nil) then
    ps := pStr^.StrInt_GetData();
    if(ps <> nil) then
      chrsize := pStr^.TxtGetCharSize();
      retcode := TxtCatAt(chroffset, ps, chrsize);
    end_if;
  end_if;
  
END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::ObjCpy
	VAR_INPUT
		pStr 	: ^StringInternal;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  VAR
  	ps : ^usint;
    chrsize, dchrsiz : udint;
  END_VAR
  
  retcode := true;
  
  if(pStr <> nil) then
    ps      := pStr^.StrInt_GetData();
    chrsize := pStr^.TxtGetCharSize();
    dchrsiz := chrsize;
    if(StrInt_GetData() <> nil) then
      dchrsiz := TxtGetCharSize();
    end_if;
    
    retcode := TxtSet(dchrsiz, ps, chrsize);
  end_if;
  
END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::ObjCpyFrom
	VAR_INPUT
		pStr 	: ^StringInternal;
		fromwhere 	: UDINT;
		nchar 	: UDINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  VAR
    thelp : array[0..SI_TMP_HELPSIZE] of usint;
  	sln, tmp, chrsize, dchrsiz : udint;
    pa : ^usint;
  END_VAR

  sln := pStr^.TxtLen();
  if(nchar > sln) then
    nchar := sln; // truncate number of characters to get
  end_if;

  tmp := (sln + 1) * pStr^.TxtGetCharSize();
  if(TmpAlloc(#pa, tmp+2, #thelp[0], sizeof(thelp)) <> 0) then // +2 for possibly unicode-id
    chrsize := pStr^.TxtGetAt(pa+2, tmp, fromwhere, nchar);
    if(chrsize > 0) then
      dchrsiz := chrsize;
      if(StrInt_GetData() <> nil) then
        dchrsiz := TxtGetCharSize();
      end_if;
      
      if(dchrsiz = 2) & (chrsize = 2) then
        pa$^uint^ := 16#0200; // speedhack
        retcode   := TxtSet(2, pa, 2);
      else
        retcode := TxtSet(dchrsiz, pa+2, chrsize);
      end_if;
    end_if;
    TmpFree(#pa, #thelp[0]);
  end_if;

END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::ObjClone
	VAR_INPUT
		pStr 	: ^StringInternal;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  VAR
  	ps : ^usint;
    chrsize : udint;
  END_VAR
  
  retcode := true;
  
  if(pStr <> nil) then
    ps      := pStr^.StrInt_GetData();
    chrsize := pStr^.TxtGetCharSize();
    retcode := TxtSet(chrsize, ps, chrsize);
  end_if;
  
END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::ObjCmp
	VAR_INPUT
		pStr 	: ^StringInternal;
	END_VAR
	VAR_OUTPUT
		udNotEqual 	: UDINT;
	END_VAR

  udNotEqual := TxtCmp(pStr^.StrInt_GetData(), pStr^.TxtGetCharSize());
  
END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::ObjICmp
	VAR_INPUT
		pStr 	: ^StringInternal;
	END_VAR
	VAR_OUTPUT
		udNotEqual 	: UDINT;
	END_VAR
  
  udNotEqual := TxtICmp(pStr^.StrInt_GetData(), pStr^.TxtGetCharSize());
  
END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::ObjIns
	VAR_INPUT
		index_at 	: UDINT;
		pStr 	: ^StringInternal;
		chrcount 	: UDINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  VAR
  	ps : ^usint;
  END_VAR

  retcode := true;
  
  if(pStr <> nil) then
    ps := pStr^.StrInt_GetData();
    retcode := TxtIns(index_at, ps, pStr^.TxtGetCharSize(), chrcount);
  end_if;

END_FUNCTION

FUNCTION StringInternal::KillUBOM
  VAR
  	ubom : uint;
  END_VAR

  if(StrInt_IsUnicode()) then
    ubom := 0;
    DataBuffer.SetDataAt(#ubom$usint, 2, 0);
  end_if;
  
END_FUNCTION

FUNCTION GLOBAL StringInternal::TxtLenAsciiToUtf8
	VAR_INPUT
		src_ascii 	: ^char;
	END_VAR
	VAR_OUTPUT
		retcode 	: UDINT;
	END_VAR
  VAR
  	ps08 : ^USINT;
  END_VAR
  
  // compute length of given ASCII string in UTF8-Format
  // NOTE: same algorithm as in funktion TxtAsciiToUtf8
  
  retcode := 0;
  
  if(src_ascii <> nil) then
    ps08 := src_ascii$^USINT;
    while(ps08^) do 
      if((ps08^) < 16#80) then    
        retcode += 1;    
      else 
        retcode += 2;
      end_if;
      ps08 += 1;
    end_while;
  end_if;

END_FUNCTION

FUNCTION GLOBAL StringInternal::TxtLenUniToUtf8
	VAR_INPUT
		src_uni 	: ^UINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: UDINT;
	END_VAR
  VAR
  	ps16 : ^UINT;
    chr : UINT;
  END_VAR
  
  // compute length of given UNICODE string in UTF8-Format
  // NOTE: same algorithm as in funktion TxtUniToUtf8
  
  retcode := 0;
  
  if(src_uni <> nil) then
    ps16 := src_uni$^UINT;
    while(ps16^) do
      chr  := ps16^;
      ps16 += 2;    
      if(chr < 16#0080) then
        retcode += 1;
      elsif(chr < 16#0800) then
        retcode += 2;  
      else
        retcode += 3;
      end_if;    
    end_while;
  end_if;

END_FUNCTION

FUNCTION GLOBAL StringInternal::TxtLenUtf8ToAscii
	VAR_INPUT
		src_utf8 	: ^CHAR;
	END_VAR
	VAR_OUTPUT
		retcode 	: UDINT;
	END_VAR

  // compute textlength of given utf8 formatted string in ascii-format
  retcode := TxtLenUtf8ToUni(src_utf8);
  
END_FUNCTION

FUNCTION GLOBAL StringInternal::TxtLenUtf8ToUni
	VAR_INPUT
		src_utf8 	: ^CHAR;
	END_VAR
	VAR_OUTPUT
		retcode 	: UDINT;
	END_VAR
  VAR
    ps : ^USINT;
    follow : UDINT;
    chr : UINT;
  END_VAR
 
  // compute textlength of given utf8 formatted string in u16-format
    
  retcode := 0;
  
  if(src_utf8 <> nil) then
    ps := src_utf8$^USINT;
    
    while(ps^) do
   
      chr := ps^;
      ps += 1;
      
      if(chr AND 16#0080) then
      
        follow := 0;
        
        if((chr AND 16#00E0) = 16#00C0) then      
          follow := 1; // 1 folgebyte
        elsif((chr AND 16#00F0) = 16#00E0) then      
          follow := 2; // 2 folgebytes
        elsif((chr AND 16#00F8) = 16#00F0) then      
          follow := 3; // 3 folgebytes
        end_if;
        
        while(follow <> 0) do
          follow -= 1;
          
          if((ps^ AND 16#C0) = 16#80) then        
            ps += 1;
            if(follow = 0) then          
              retcode += 1;
            end_if;  
          end_if;
        end_while;
        
      else    
        retcode += 1;    
      end_if;
    end_while;
  end_if;

END_FUNCTION

FUNCTION GLOBAL StringInternal::TxtAsciiToUtf8
	VAR_INPUT
		dst_utf8 	: ^CHAR;
		src_ascii 	: ^CHAR;
	END_VAR
	VAR_OUTPUT
		retcode 	: UDINT;
	END_VAR
  VAR
  	ps : ^USINT;
    pd : ^USINT;
    chr : USINT;
  END_VAR
  
  // NOTE: same algorithm as in funktion TxtLenUTF8
  
  retcode := 0;
  
  if(dst_utf8 <> nil) then
    pd := dst_utf8$^USINT;
    
    if(src_ascii <> nil) then
      ps := src_ascii$^USINT;

      while(ps^) do 

        chr := ps^;
        ps  += 1;
        if(chr < 16#0080) then    
          pd^  := chr$USINT;
          pd += 1;
          retcode += 1;    
        else 
          pd^    := to_usint(16#00C0 OR (chr SHR 6));
          pd += 1;
          pd^    := to_usint(16#0080 OR (chr AND 16#003F));
          pd += 1;
          retcode += 2;
        end_if;
      end_while;
    end_if;
    
    pd^ := 0;
  end_if;

END_FUNCTION

FUNCTION GLOBAL StringInternal::TxtUniToUtf8
	VAR_INPUT
		dst_utf8 	: ^CHAR;
		src_uni 	: ^UINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: UDINT;
	END_VAR
  VAR
    pd : ^USINT;
    chr : UINT;
  END_VAR
  
  // convert unicode-0-string to utf8-0-string, function will return number of used bytes in destination, excluding final zero
  // NOTE: same algorithm as in funktion TxtLenUTF8
  
  retcode := 0;
  
  if(dst_utf8 <> nil) then
    pd := dst_utf8$^USINT;
    
    if(src_uni <> nil) then
      while(src_uni^) do
      
        chr := src_uni^;
        src_uni += 2;
        
        if(chr < 16#0080) then
          pd^ := chr$USINT;
          pd += 1;
          retcode += 1;
        elsif(chr < 16#0800) then
          pd^ := to_usint(16#00C0 OR (chr SHR 6));
          pd += 1;
          pd^ := to_usint(16#0080 OR (chr AND 16#003F));
          pd += 1;
          retcode += 2;  
        else
          pd^ := to_usint(16#00E0 OR (chr SHR 12));
          pd += 1;
          pd^ := to_usint(16#0080 OR ((chr SHR 6) AND 16#003F));
          pd += 1;
          pd^ := to_usint(16#0080 OR (chr AND 16#003F)); 
          pd += 1;
          retcode += 3;
        end_if;
        
      end_while;
    end_if;

    pd^ := 0;
  end_if;
  
END_FUNCTION

FUNCTION GLOBAL StringInternal::TxtUtf8ToAscii
	VAR_INPUT
		dst_ascii 	: ^CHAR;
		src_utf8 	: ^CHAR;
	END_VAR
	VAR_OUTPUT
		retcode 	: UDINT;
	END_VAR
  VAR
  	ps : ^USINT;
    pd : ^USINT;
    follow : UDINT;
    chr : UINT;
  END_VAR

  retcode := 0;
  
  if(dst_ascii <> nil) then
    pd := dst_ascii$^USINT;
    
    if(src_utf8 <> nil) then
      ps := src_utf8$^USINT;

      while(ps^) do 
      
        chr := ps^;
        ps  += 1;
        if(chr AND 0x0080) then    
          follow := 0;      
          if ((chr AND 16#00E0) = 16#00C0) then      
            follow := 1; // 1 folgebyte
            chr    := chr AND 16#001F;      
          elsif((chr AND 16#00F0) = 16#00E0) then
            follow := 2; // 2 folgebytes
            chr    := chr AND 16#000F;
          elsif((chr AND 16#00F8) = 16#00F0) then
            follow := 3; // 3 folgebytes
            chr    := chr AND 16#0007;
          end_if;
          
          while(follow <> 0) do
            follow -= 1;
            if((ps^ AND 16#C0) = 16#80) then       
              chr := ((chr SHL 6) OR ((ps^) AND 16#3F));
              ps += 1;
              if(follow = 0) then 
                if(chr > 255) then
                  chr := 63; //'?'
                end_if;
                pd^ := chr$usint;
                pd  += 1;
                retcode += 1;
              end_if;
            end_if;
          end_while;
        else    
          pd^ := chr$usint;
          pd  += 1;
          retcode += 1;
        end_if;
      end_while;
    end_if;
    
    pd^ := 0;
  end_if;

END_FUNCTION

FUNCTION GLOBAL StringInternal::TxtUtf8ToUni
	VAR_INPUT
		dst_uni 	: ^UINT;
		src_utf8 	: ^CHAR;
	END_VAR
	VAR_OUTPUT
		retcode 	: UDINT;
	END_VAR
  VAR
    ps : ^USINT;
    follow : UDINT;
    chr : UINT;
  END_VAR
 
  // convert utf8-0-string to unicode-0-string, function will return number of characters in destination
    
  retcode := 0;
  if(dst_uni <> nil) then
  
    if(src_utf8 <> nil) then
      ps := src_utf8$^USINT;
      
      while(ps^) do
     
        chr := ps^;
        ps += 1;
        
        if(chr AND 16#0080) then
        
          follow := 0;
          
          if((chr AND 16#00E0) = 16#00C0) then      
            follow := 1; // 1 folgebyte
            chr    := chr AND 16#001F;      
          elsif((chr AND 16#00F0) = 16#00E0) then      
            follow := 2; // 2 folgebytes
            chr    := chr AND 0x000F;      
          elsif((chr AND 16#00F8) = 16#00F0) then      
            follow := 3; // 3 folgebytes
            chr    := chr AND 16#0007;     
          end_if;
          
          while(follow <> 0) do
            follow -= 1;
            
            if((ps^ AND 16#C0) = 16#80) then        
              chr := ((chr SHL 6) OR (ps^ AND 16#3F));
              ps += 1;
              if (follow = 0) then          
                dst_uni^ := chr;
                dst_uni += 2;
                retcode += 1;
              end_if;  
            end_if;
          end_while;
          
        else    
          dst_uni^ := chr;
          dst_uni += 2;
          retcode += 1;    
        end_if;
        
      end_while;
    end_if;
    
    dst_uni^ := 0;
  end_if;
  
END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtSetUtf8
	VAR_INPUT
		src_utf8 	: ^CHAR;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  VAR
  	tmplen : udint;
    pu : ^uint;
    thelp : array[0..SI_TMP_HELPSIZE] of uint;
  END_VAR

  retcode := false;
  tmplen  := (TxtLenUtf8ToUni(src_utf8) + 2) * 2; // final zero + unicode mark
  
  if(TmpAlloc(#pu, tmplen, #thelp[0], sizeof(thelp)) <> 0) then
    pu^ := 16#0200;
    TxtUtf8ToUni(pu+2, src_utf8);
    retcode := AddDataIntern(pu$^usint, tmplen, 0);
    TmpFree(#pu, #thelp[0]);
  end_if;

END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtGetUtf8
	VAR_INPUT
		dst_utf8 	: ^CHAR;
	END_VAR
	VAR_OUTPUT
		retcode 	: UDINT;
	END_VAR
  VAR
  	pa : ^usint;
  END_VAR

  retcode := 0;
  
  if(dst_utf8 <> nil) then
    pa        := StrInt_GetData();
    dst_utf8^ := 0;
  
    if(pa <> nil) then
      if(StrInt_IsUnicode()) then
        retcode := TxtUniToUtf8(dst_utf8, 2 + pa$^uint);
      else
        retcode := TxtAsciiToUtf8(dst_utf8, pa);
      end_if;
    end_if;
  end_if;

END_FUNCTION

FUNCTION VIRTUAL GLOBAL StringInternal::TxtLenUtf8
	VAR_OUTPUT
		retcode 	: UDINT;
	END_VAR
  VAR
  	ph : ^usint;
  END_VAR

  retcode := 0;
  ph      := StrInt_GetData();
  if(ph <> nil) then
    if(StrInt_IsUnicode()) then
      retcode := TxtLenUniToUtf8(2 + ph$^uint);
    else
      retcode := TxtLenAsciiToUtf8(ph);
    end_if;
  end_if;

END_FUNCTION

//FUNCTION GLOBAL StringInternal::TxtLen16
//	VAR_INPUT
//    src16 : ^uint;
//	END_VAR
//	VAR_OUTPUT
//		retcode 	: UDINT;
//	END_VAR
//
//  retcode := 0;
//  if(src16 <> nil) then
//    retcode := StrInt_StrLen16(src16);
//  end_if;
//
//END_FUNCTION
//
//FUNCTION GLOBAL StringInternal::TxtLen08
//	VAR_INPUT
//    src08 : ^char;
//	END_VAR
//	VAR_OUTPUT
//		retcode 	: UDINT;
//	END_VAR
//
//  retcode := 0;
//  if(src08 <> nil) then
//    retcode := _strlen(src08);
//  end_if;
//  
//END_FUNCTION
//
//FUNCTION GLOBAL StringInternal::TxtNCpy16 
//	VAR_INPUT
//    pd : ^uint; 
//    ps : ^uint; 
//    maxlen : udint; 
//	END_VAR
//	VAR_OUTPUT
//		retcode 	: ^uint;
//	END_VAR
//
//  retcode := pd;
//  if((pd <> nil) & (ps <> nil)) then
//    StrInt_StrNCpy16(pd, ps, maxlen);
//  end_if;
//  
//END_FUNCTION
//  
//FUNCTION GLOBAL StringInternal::TxtNCpy08 
//	VAR_INPUT
//    pd : ^char; 
//    ps : ^char; 
//    maxlen : udint; 
//	END_VAR
//	VAR_OUTPUT
//		retcode 	: ^char;
//	END_VAR
//
//  retcode := pd;
//  if((pd <> nil) & (ps <> nil)) then
//    StrInt_StrNCpy08(pd&^usint; ps$^usint; maxlen);
//  end_if;
//  
//END_FUNCTION

