<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.secondlife.com/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Phil+Metalhead</id>
	<title>Second Life Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.secondlife.com/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Phil+Metalhead"/>
	<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/wiki/Special:Contributions/Phil_Metalhead"/>
	<updated>2026-07-28T06:13:49Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.42.1</generator>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Category:LSL_Integer&amp;diff=1200513</id>
		<title>Category:LSL Integer</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Category:LSL_Integer&amp;diff=1200513"/>
		<updated>2016-06-24T15:02:12Z</updated>

		<summary type="html">&lt;p&gt;Phil Metalhead: /* Examples */ added decimal test case, and signature&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Header|ml=*}}&lt;br /&gt;
{{LSLC|}}{{LSLC|Types}}&lt;br /&gt;
&lt;br /&gt;
=Integers=&lt;br /&gt;
The integer data type is a signed 32 bit value between −2,147,483,648 and +2,147,483,647 (that is 0x80000000 to 0x7FFFFFFF in hex). Integers are whole numbers. The fractional datatype is the [[float]].&lt;br /&gt;
&lt;br /&gt;
[[DEBUG_CHANNEL]] can be used as a constant for the maximum integer (for that is the value it is defined as).&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
All of the following are integers:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;integer firstInt = 5512623;&lt;br /&gt;
integer secondInt = ACTIVE;&lt;br /&gt;
integer thirdInt = 0x61EC1A;&lt;br /&gt;
integer fourthInt = -160693;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following are NOT integers, use {{LSLG|float}} for them:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
integer decimalValue = 125.2; // ERROR : Type mismatch -- Integer literals can&#039;t have a decimal.&lt;br /&gt;
integer bigValue = 3147483647; // An undocumented way to say -1,147,483,649 // Integer literals can&#039;t be larger than 2,147,483,647.&lt;br /&gt;
integer biggerValue = 10123456789; // An undocumented way to say -1 // Integer literals can&#039;t be larger than 2,147,483,647.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following function can be used to determine whether a string of characters consists only of integers. This can be important if you need to know that a user has entered a valid integer in chat or a textbox, for example.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
integer IsInteger(string var)&lt;br /&gt;
{&lt;br /&gt;
    integer i;&lt;br /&gt;
    for (i=0;i&amp;lt;llStringLength(var);++i)&lt;br /&gt;
    {&lt;br /&gt;
        if(!~llListFindList([&amp;quot;1&amp;quot;,&amp;quot;2&amp;quot;,&amp;quot;3&amp;quot;,&amp;quot;4&amp;quot;,&amp;quot;5&amp;quot;,&amp;quot;6&amp;quot;,&amp;quot;7&amp;quot;,&amp;quot;8&amp;quot;,&amp;quot;9&amp;quot;,&amp;quot;0&amp;quot;],[llGetSubString(var,i,i)]))&lt;br /&gt;
        {&lt;br /&gt;
            return FALSE;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return TRUE;&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here&#039;s a simpler solution for strings containing positive or negative decimal integers (values from −2147483648 and 2147483647 written without + sign, leading zeros, or thousands separators &#039;,&#039; ). Omei Qunhua.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
    if ( (string) ( (integer) data) == data)&lt;br /&gt;
        llOwnerSay(&amp;quot;&#039;&amp;quot; + data + &amp;quot;&#039; contains a valid integer&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following examples will validate that a string contains only the characters 0 though 9. Omei Qunhua.&lt;br /&gt;
&lt;br /&gt;
a) Example for a string of length 5&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
    StringOf5Dec(string test)&lt;br /&gt;
    {&lt;br /&gt;
        return ( (integer) (&amp;quot;1&amp;quot; + test) &amp;gt;= 100000);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
b) Example for a string of length 1 through 9&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
    VarStringIsDecimal(string test)&lt;br /&gt;
    {&lt;br /&gt;
        integer limit = (integer) llPow(10.0, llStringLength(test) );&lt;br /&gt;
        return ( (integer) (&amp;quot;1&amp;quot; + test) &amp;gt;= limit);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function should validate any decimal integer, with or without signs or leading zeroes, and with leading/trailing space but does not accept thousands separators. (Phil Metalhead)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
    integer uIsInteger(string input)&lt;br /&gt;
    {&lt;br /&gt;
        input = llStringTrim(input,STRING_TRIM); // remove leading/trailing whitespace&lt;br /&gt;
        // &amp;quot;+123&amp;quot; is a valid integer string but would otherwise fail, so strip leading &amp;quot;+&amp;quot; if it&#039;s there&lt;br /&gt;
        if (llGetSubString(input,0,0) == &amp;quot;+&amp;quot;) input = llGetSubString(input,1,-1);&lt;br /&gt;
        return ((string)((integer)input) == input);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Test cases for the above function (click &amp;quot;Expand&amp;quot; link on the right side of the page):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot; class=&amp;quot;mw-collapsible mw-collapsed&amp;quot;&amp;gt;&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 1 // (leading and trailing whitespace)&lt;br /&gt;
   2352316&lt;br /&gt;
&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 1 // (leading &amp;quot;+&amp;quot;)&lt;br /&gt;
+151613662&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 1 // (negative number)&lt;br /&gt;
-263163626&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 1 // (largest positive integer)&lt;br /&gt;
2147483647&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 1 // (largest negative integer) &lt;br /&gt;
-2147483648&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 1 // (largest positive integer with leading and trailing whitespace, and leading &amp;quot;+&amp;quot;)&lt;br /&gt;
   +2147483647&lt;br /&gt;
&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 0 // (contains letters)&lt;br /&gt;
161362stuff&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 0 // (number is a float, not an integer -- contains &amp;quot;.&amp;quot; in string)&lt;br /&gt;
123.4&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 0 // (whitespace in middle of string)&lt;br /&gt;
2347&lt;br /&gt;
9089&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 0 // (contains thousands separator &amp;quot;,&amp;quot;)&lt;br /&gt;
844,241&lt;br /&gt;
// Returns 0 // (&amp;quot;+&amp;quot; in middle of string)&lt;br /&gt;
2378+87668&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 0 // (&amp;quot;-&amp;quot; in middle of string)&lt;br /&gt;
3462098-12&lt;br /&gt;
// Returns 0 // (number &amp;gt; 2147483647)&lt;br /&gt;
2147483648&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 0 // (number &amp;lt; -2147483648)&lt;br /&gt;
-2147483649&lt;br /&gt;
///////////////&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Further Reading==&lt;br /&gt;
For a more extensive coverage of integers, including the different ways they are used in LSL, see [[LSL_101/LSL_in_Focus:_Integers|LSL in Focus: Integers]].&lt;/div&gt;</summary>
		<author><name>Phil Metalhead</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Category:LSL_Integer&amp;diff=1200512</id>
		<title>Category:LSL Integer</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Category:LSL_Integer&amp;diff=1200512"/>
		<updated>2016-06-24T14:59:12Z</updated>

		<summary type="html">&lt;p&gt;Phil Metalhead: /* Examples */  Added integer test function&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Header|ml=*}}&lt;br /&gt;
{{LSLC|}}{{LSLC|Types}}&lt;br /&gt;
&lt;br /&gt;
=Integers=&lt;br /&gt;
The integer data type is a signed 32 bit value between −2,147,483,648 and +2,147,483,647 (that is 0x80000000 to 0x7FFFFFFF in hex). Integers are whole numbers. The fractional datatype is the [[float]].&lt;br /&gt;
&lt;br /&gt;
[[DEBUG_CHANNEL]] can be used as a constant for the maximum integer (for that is the value it is defined as).&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
All of the following are integers:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;integer firstInt = 5512623;&lt;br /&gt;
integer secondInt = ACTIVE;&lt;br /&gt;
integer thirdInt = 0x61EC1A;&lt;br /&gt;
integer fourthInt = -160693;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following are NOT integers, use {{LSLG|float}} for them:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
integer decimalValue = 125.2; // ERROR : Type mismatch -- Integer literals can&#039;t have a decimal.&lt;br /&gt;
integer bigValue = 3147483647; // An undocumented way to say -1,147,483,649 // Integer literals can&#039;t be larger than 2,147,483,647.&lt;br /&gt;
integer biggerValue = 10123456789; // An undocumented way to say -1 // Integer literals can&#039;t be larger than 2,147,483,647.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following function can be used to determine whether a string of characters consists only of integers. This can be important if you need to know that a user has entered a valid integer in chat or a textbox, for example.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
integer IsInteger(string var)&lt;br /&gt;
{&lt;br /&gt;
    integer i;&lt;br /&gt;
    for (i=0;i&amp;lt;llStringLength(var);++i)&lt;br /&gt;
    {&lt;br /&gt;
        if(!~llListFindList([&amp;quot;1&amp;quot;,&amp;quot;2&amp;quot;,&amp;quot;3&amp;quot;,&amp;quot;4&amp;quot;,&amp;quot;5&amp;quot;,&amp;quot;6&amp;quot;,&amp;quot;7&amp;quot;,&amp;quot;8&amp;quot;,&amp;quot;9&amp;quot;,&amp;quot;0&amp;quot;],[llGetSubString(var,i,i)]))&lt;br /&gt;
        {&lt;br /&gt;
            return FALSE;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return TRUE;&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here&#039;s a simpler solution for strings containing positive or negative decimal integers (values from −2147483648 and 2147483647 written without + sign, leading zeros, or thousands separators &#039;,&#039; ). Omei Qunhua.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
    if ( (string) ( (integer) data) == data)&lt;br /&gt;
        llOwnerSay(&amp;quot;&#039;&amp;quot; + data + &amp;quot;&#039; contains a valid integer&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following examples will validate that a string contains only the characters 0 though 9. Omei Qunhua.&lt;br /&gt;
&lt;br /&gt;
a) Example for a string of length 5&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
    StringOf5Dec(string test)&lt;br /&gt;
    {&lt;br /&gt;
        return ( (integer) (&amp;quot;1&amp;quot; + test) &amp;gt;= 100000);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
b) Example for a string of length 1 through 9&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
    VarStringIsDecimal(string test)&lt;br /&gt;
    {&lt;br /&gt;
        integer limit = (integer) llPow(10.0, llStringLength(test) );&lt;br /&gt;
        return ( (integer) (&amp;quot;1&amp;quot; + test) &amp;gt;= limit);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function should validate any decimal integer, with or without signs or leading zeroes, and with leading/trailing space (does not accept thousands separators):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
    integer uIsInteger(string input)&lt;br /&gt;
    {&lt;br /&gt;
        input = llStringTrim(input,STRING_TRIM); // remove leading/trailing whitespace&lt;br /&gt;
        // &amp;quot;+123&amp;quot; is a valid integer string but would otherwise fail, so strip leading &amp;quot;+&amp;quot; if it&#039;s there&lt;br /&gt;
        if (llGetSubString(input,0,0) == &amp;quot;+&amp;quot;) input = llGetSubString(input,1,-1);&lt;br /&gt;
        return ((string)((integer)input) == input);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Test cases (click &amp;quot;Expand&amp;quot; link on the right side of the page):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot; class=&amp;quot;mw-collapsible mw-collapsed&amp;quot;&amp;gt;&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 1 // (leading and trailing whitespace)&lt;br /&gt;
   2352316&lt;br /&gt;
&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 1 // (leading &amp;quot;+&amp;quot;)&lt;br /&gt;
+151613662&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 1 // (negative number)&lt;br /&gt;
-263163626&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 1 // (largest positive integer)&lt;br /&gt;
2147483647&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 1 // (largest negative integer) &lt;br /&gt;
-2147483648&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 1 // (largest positive integer with leading and trailing whitespace, and leading &amp;quot;+&amp;quot;)&lt;br /&gt;
   +2147483647&lt;br /&gt;
&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 0 // (contains letters)&lt;br /&gt;
161362stuff&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 0 // (whitespace in middle of string)&lt;br /&gt;
2347&lt;br /&gt;
9089&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 0 // (contains thousands separator &amp;quot;,&amp;quot;)&lt;br /&gt;
844,241&lt;br /&gt;
// Returns 0 // (&amp;quot;+&amp;quot; in middle of string)&lt;br /&gt;
2378+87668&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 0 // (&amp;quot;-&amp;quot; in middle of string)&lt;br /&gt;
3462098-12&lt;br /&gt;
// Returns 0 // (number &amp;gt; 2147483647)&lt;br /&gt;
2147483648&lt;br /&gt;
///////////////&lt;br /&gt;
// Returns 0 // (number &amp;lt; -2147483648)&lt;br /&gt;
-2147483649&lt;br /&gt;
///////////////&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Further Reading==&lt;br /&gt;
For a more extensive coverage of integers, including the different ways they are used in LSL, see [[LSL_101/LSL_in_Focus:_Integers|LSL in Focus: Integers]].&lt;/div&gt;</summary>
		<author><name>Phil Metalhead</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=ZZText&amp;diff=1199902</id>
		<title>ZZText</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=ZZText&amp;diff=1199902"/>
		<updated>2016-04-18T20:40:42Z</updated>

		<summary type="html">&lt;p&gt;Phil Metalhead: /* Mega-image maker python-fu script */ updated for proper code tag ~&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== What is it ==&lt;br /&gt;
&lt;br /&gt;
Scripting tools to allow display of text on a prim: [[XyText 1.5]] (aka XyText) , [[XyzzyText]], [[XyyyyzText]], [[XyzzyText-UTF8]], [[ZZText]], [[VariText]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ZZText&#039;&#039;&#039; is a low-prim, low-lag, international variation of [[XyText]] with the following features:&lt;br /&gt;
* can be enhanced with new fonts or UTF-8 characters using GIMP and python-fu.&lt;br /&gt;
* uses only 35 textures instead of 66 for the 10 chars on prim solution (this gives a bit less quality then the original xytext, but under normal situations is acceptable.&lt;br /&gt;
&lt;br /&gt;
Rationale: if you have problems with prim usage, then you can accept this compromise.&lt;br /&gt;
&lt;br /&gt;
* this particular combination of textures gives something way more rapid than [[XyzzyText]], which is very slow for big boards, and less lagger than [[XyText]].&lt;br /&gt;
* small warning: there is still some slight improvements for this zzText to be reasonably acceptable (consider it in a Beta stage), will post soon when it will be fully acceptable.&lt;br /&gt;
&lt;br /&gt;
== Credits and copyright ==&lt;br /&gt;
ZZText is heavily dependent on [[XyText]] so it shares and extends credits and copyrights.&lt;br /&gt;
&lt;br /&gt;
Also this is a low prim variation of the [[XyzzyText-UTF8]] page but downgraded to use XyText lower quality paradigm instead than the 1 character face approach.&lt;br /&gt;
&lt;br /&gt;
== How to generate the textures ==&lt;br /&gt;
&lt;br /&gt;
* GIMP 2.8 has already python-fu installed so you don&#039;t need to bother on installing it as I suggested some years ago&lt;br /&gt;
* Use the mega-image maker python-fu script (see following sections)&lt;br /&gt;
* Use the splitter python-fu script to produce 512x512 guides for later splitting&lt;br /&gt;
* Use the filter/web/slice... button to produce 64 slices in png format to retain transparence (from 0-0 to 7-7)&lt;br /&gt;
* Manually remove the empty slices (the i-j where j&amp;gt;i for instance 2-3, 6-7) so you have only 35 images png.&lt;br /&gt;
* Manually convert each png to tga (this is solving some problems with sl uploading regarding transparence)&lt;br /&gt;
* Upload the textures keeping the order 0-0 1-0 1-1 2-0 2-1 2-3 .... until 7-7)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Manual parts can be automated by another python-fu, but I was so exhausted with the others that it was ok for me doing manually :)&lt;br /&gt;
&lt;br /&gt;
There is still some fix needed to do on the python-fu script. Currently characters are still a bit unevenly put so that when displaying them&lt;br /&gt;
depending on which couple using we might see some slight asymmetric unbalancing. You can note this only when looking very closely to the chars.&lt;br /&gt;
Whenever I fix myself this problem I will post here.&lt;br /&gt;
&lt;br /&gt;
For those of you who already accept fonts I did last week, look at next sections for the 35 texture UUIDs:&lt;br /&gt;
&lt;br /&gt;
== So how can I use it? ==&lt;br /&gt;
&lt;br /&gt;
* Put the script named ZZText into each prim of your board naming each cell 1000 ---- 1099 as far as you need cells&lt;br /&gt;
* Have a main script doing the following: llMessageLinked(LINK_SET,1040,&amp;quot;çòàùè&amp;quot;,NULL_KEY) to write on cell named 1040&lt;br /&gt;
&lt;br /&gt;
To divide in rows, use simple modulus operations.&lt;br /&gt;
&lt;br /&gt;
== Variation on [[XyText 1.5]] standard script ==&lt;br /&gt;
&lt;br /&gt;
For not being so difficult to follow, I only publish differences between my script and [[XyText 1.5]] so that you might be able to understand better what I did:&lt;br /&gt;
=== Change CHARACTER_GRID with our full permission textures ===&lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
list    CHARACTER_GRID  = [&lt;br /&gt;
        &amp;quot;96f4578b-879e-44ae-d223-427cc615f5a4&amp;quot;, // my slice-0-0&lt;br /&gt;
        &amp;quot;eab5360f-6653-593f-b679-69c68b0dd001&amp;quot;, // 1-0&lt;br /&gt;
        &amp;quot;367330be-717a-277d-5205-131cd6ded458&amp;quot;, // 1-1&lt;br /&gt;
        &amp;quot;32046675-6e7e-2425-ce77-69000b0b4d96&amp;quot;, // 2-0&lt;br /&gt;
        &amp;quot;40085901-bde6-2dd4-40cd-b6d48d242997&amp;quot;, // 2-1&lt;br /&gt;
        &amp;quot;205d318b-09b7-7ecc-922e-801c93a546c8&amp;quot;, // 2-2&lt;br /&gt;
        &amp;quot;841e7826-3645-d4f0-d48b-389586dd8e90&amp;quot;, // 3-0&lt;br /&gt;
        &amp;quot;e2db78c5-fb47-d767-4744-8cb6d84610d0&amp;quot;, // 3-1&lt;br /&gt;
        &amp;quot;15312c89-afd4-854c-9d9b-5b9e11844aed&amp;quot;, // 3-2&lt;br /&gt;
        &amp;quot;d180e771-0393-d09b-8cac-0af6d550ae4a&amp;quot;, // 3-3&lt;br /&gt;
        &amp;quot;c6c1d2c8-5dfd-b13a-7f1e-c3ede8126769&amp;quot;, // 4-0&lt;br /&gt;
        &amp;quot;bc100d0c-a445-947f-caa4-285d9cc8a9de&amp;quot;, // 4-1&lt;br /&gt;
        &amp;quot;0b31e862-75a4-9ed3-6331-e9e700a0fedb&amp;quot;, // 4-2&lt;br /&gt;
        &amp;quot;0eacc306-6bd5-ab31-de47-c686141a6733&amp;quot;, // 4-3&lt;br /&gt;
        &amp;quot;b68de1d9-4890-74a0-4d25-d4d5c83a0dba&amp;quot;, // 4-4&lt;br /&gt;
        &amp;quot;04b2bf9b-a8bb-0a39-1062-9b005229eba9&amp;quot;, // 5-0&lt;br /&gt;
        &amp;quot;be293f10-25ec-beb9-738b-fe1892b82aef&amp;quot;, // 5-1&lt;br /&gt;
        &amp;quot;5e9c8317-71f5-f073-76ab-7c412d3acb84&amp;quot;, // 5-2&lt;br /&gt;
        &amp;quot;030b441b-9022-2aba-f7a7-af6810c354b8&amp;quot;, // 5-3&lt;br /&gt;
        &amp;quot;9f455858-8ae6-3a9a-c2d4-bc5ee92430ac&amp;quot;, // 5-4&lt;br /&gt;
        &amp;quot;ee741143-f01e-f730-667e-66a3cd57d1cc&amp;quot;, // 5-5&lt;br /&gt;
        &amp;quot;710282bc-bd80-5a44-6987-0c4c11a4c294&amp;quot;, // 6-0&lt;br /&gt;
        &amp;quot;c9c410db-675a-1e98-4107-debd3c73a754&amp;quot;, // 6-1&lt;br /&gt;
        &amp;quot;486c2336-71c5-b962-266c-838a865c067c&amp;quot;, // 6-2&lt;br /&gt;
        &amp;quot;d4722155-0b6d-3673-0208-a727729bc117&amp;quot;, // 6-3&lt;br /&gt;
        &amp;quot;bc7af3cd-ee48-08df-fe8b-a6ca8a425733&amp;quot;, // 6-4&lt;br /&gt;
        &amp;quot;f23d7a73-00c3-1ffd-69a7-0cca031c939d&amp;quot;, // 6-5&lt;br /&gt;
        &amp;quot;aa95bfd1-ac80-f962-7acf-d6aeed9c7e81&amp;quot;, // 6-6&lt;br /&gt;
        &amp;quot;53fd52e3-0e8b-dcc8-42f8-332aef421bd2&amp;quot;, // 7-0&lt;br /&gt;
        &amp;quot;da3f6f09-3e3a-e156-8e2e-1040111a5635&amp;quot;, // 7-1&lt;br /&gt;
        &amp;quot;409a95c0-b685-2036-d0de-75e8ab654243&amp;quot;, // 7-2&lt;br /&gt;
        &amp;quot;14e05aca-3a61-b892-3632-dcde72324779&amp;quot;, // 7-3&lt;br /&gt;
        &amp;quot;546c0e4f-b678-895d-2035-0f39bb7f4979&amp;quot;, // 7-4&lt;br /&gt;
        &amp;quot;cf2fc337-109f-ba25-8ff5-786f7d6ceb5b&amp;quot;, // 7-5&lt;br /&gt;
        &amp;quot;9943204b-a4de-868a-3cdd-8785d1864ede&amp;quot;, // 7-6&lt;br /&gt;
        &amp;quot;765cfd9c-9703-b5ba-2c5d-f1c8bd44e0f4&amp;quot;  // 7-7&lt;br /&gt;
          ];&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Enabling answering to only a specific channel instead of DISPLAY_STRING channel ===&lt;br /&gt;
This heavily helps in producing multi cell boards:&lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
integer ME;&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        // need that each cell has its own number as object name starting from 1000 for instance&lt;br /&gt;
        ME = (integer)llGetObjectName();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // be sure we are answering only to channel ME&lt;br /&gt;
    link_message(integer sender, integer channel, string data, key id)&lt;br /&gt;
    {&lt;br /&gt;
        if (channel == (ME)&lt;br /&gt;
        {&lt;br /&gt;
            RenderString(data);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== UTF-8 character specification ===&lt;br /&gt;
This must closely match what you produced with python-fu&lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
ResetCharIndex() {&lt;br /&gt;
    gCharIndex  = &amp;quot; !\&amp;quot;#$%&amp;amp;&#039;()*+,-./0123456789:;&amp;lt;=&amp;gt;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`&amp;quot;;&lt;br /&gt;
    // \&amp;quot; &amp;lt;-- Fixes LSL syntax highlighting bug.&lt;br /&gt;
    gCharIndex += &amp;quot;abcdefghijklmnopqrstuvwxyz{|}~&amp;quot;;&lt;br /&gt;
  //        cap cedille      u:         e/            a^         a:          a/         a ring      cedille     e^           e:&lt;br /&gt;
  decode=  [&amp;quot;%C3%87&amp;quot;, &amp;quot;%C3%BC&amp;quot;, &amp;quot;%C3%A9&amp;quot;, &amp;quot;%C3%A2&amp;quot;, &amp;quot;%C3%A4&amp;quot;, &amp;quot;%C3%A0&amp;quot;, &amp;quot;%C3%A5&amp;quot;, &amp;quot;%C3%A7&amp;quot;, &amp;quot;%C3%AA&amp;quot;, &amp;quot;%C3%AB&amp;quot;,&lt;br /&gt;
  &lt;br /&gt;
    &lt;br /&gt;
  //                    e\           i:               i^            i\                A:          A ring          E/              ae           AE           marker &amp;gt;&lt;br /&gt;
       &amp;quot;%C3%A8&amp;quot;, &amp;quot;%C3%AF&amp;quot;, &amp;quot;%C3%AE&amp;quot;, &amp;quot;%C3%AC&amp;quot;, &amp;quot;%C3%84&amp;quot;, &amp;quot;%C3%85&amp;quot;, &amp;quot;%C3%89&amp;quot;, &amp;quot;%C3%A6&amp;quot;, &amp;quot;%C3%86&amp;quot;, &amp;quot;%E2%96%B6&amp;quot; ,&lt;br /&gt;
&lt;br /&gt;
  //                 o:               o/           u^          u\              y:               O:             U:          cent           pound        yen&lt;br /&gt;
       &amp;quot;%C3%B6&amp;quot;, &amp;quot;%C3%B2&amp;quot;, &amp;quot;%C3%BB&amp;quot;, &amp;quot;%C3%B9&amp;quot;, &amp;quot;%C3%BF&amp;quot;, &amp;quot;%C3%96&amp;quot;, &amp;quot;%C3%9C&amp;quot;, &amp;quot;%C2%A2&amp;quot;, &amp;quot;%C2%A3&amp;quot;, &amp;quot;%C2%A5&amp;quot;,&lt;br /&gt;
   &lt;br /&gt;
  //                 A^              a/              i/                o/            u/              n~           E:            y/              inv ?         O^&lt;br /&gt;
       &amp;quot;%C3%82&amp;quot;, &amp;quot;%C3%A1&amp;quot;, &amp;quot;%C3%AD&amp;quot;, &amp;quot;%C3%B3&amp;quot;, &amp;quot;%C3%BA&amp;quot;, &amp;quot;%C3%B1&amp;quot;, &amp;quot;%C3%8B&amp;quot;, &amp;quot;%C3%BD&amp;quot;, &amp;quot;%C2%BF&amp;quot;, &amp;quot;%C3%94&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
  //                   inv !             I\             I/           degree       E^              I^            o^            U^&lt;br /&gt;
       &amp;quot;%C2%A1&amp;quot;, &amp;quot;%C3%8C&amp;quot;, &amp;quot;%C3%8D&amp;quot;, &amp;quot;%C2%B0&amp;quot;, &amp;quot;%C3%8A&amp;quot;, &amp;quot;%C3%8E&amp;quot;, &amp;quot;%C3%B4&amp;quot;, &amp;quot;%C3%9B&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
  //                     Y:          euro           german ss         E\              A\           A/              U\           U/               O\           O/&lt;br /&gt;
       &amp;quot;%C3%9D&amp;quot;, &amp;quot;%E2%82%AC&amp;quot;, &amp;quot;%C3%9F&amp;quot;, &amp;quot;%C3%88&amp;quot;, &amp;quot;%C3%80&amp;quot;, &amp;quot;%C3%81&amp;quot;, &amp;quot;%C3%99&amp;quot;, &amp;quot;%C3%9A&amp;quot;, &amp;quot;%C3%92&amp;quot;, &amp;quot;%C3%93&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
  //                   Sv           sv             zv             Zv              Y:             I:&lt;br /&gt;
       &amp;quot;%C5%A0&amp;quot;, &amp;quot;%C5%A1&amp;quot;, &amp;quot;%C5%BE&amp;quot;, &amp;quot;%C5%BD&amp;quot;, &amp;quot;%C3%9D&amp;quot;, &amp;quot;%C3%8C&amp;quot; ];&lt;br /&gt;
     &lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Accessing the new characters from textures ===&lt;br /&gt;
This is the most difficult part. Still need to clean up offsets, since now they are still a bit wrong.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
vector GetGridOffset(vector grid_pos)&lt;br /&gt;
{&lt;br /&gt;
    // Zoom in on the texture showing our character pair.&lt;br /&gt;
    integer Col = llRound(grid_pos.x) % 40; // PK was 20&lt;br /&gt;
    integer Row = llRound(grid_pos.y) % 20; // PK was 10&lt;br /&gt;
&lt;br /&gt;
    // Return the offset in the texture.&lt;br /&gt;
    return &amp;lt;-0.45 + 0.025 * Col, 0.45 - 0.05 * Row, 0.0&amp;gt;; // PK was 0.05 and 0.1&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ShowChars(vector grid_pos1, vector grid_pos2, vector grid_pos3, vector grid_pos4, vector grid_pos5)&lt;br /&gt;
{&lt;br /&gt;
   // Set the primitive textures directly.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   llSetLinkPrimitiveParamsFast(LINK_THIS, [&lt;br /&gt;
        PRIM_TEXTURE, FACE_1, GetGridTexture(grid_pos1), &amp;lt;0.125, 0.05, 0&amp;gt;, GetGridOffset(grid_pos1) + &amp;lt;0.0375-0.025-0.002, 0.025, 0&amp;gt;, 0.0,&lt;br /&gt;
        PRIM_TEXTURE, FACE_2, GetGridTexture(grid_pos2), &amp;lt;0.05, 0.05, 0&amp;gt;, GetGridOffset(grid_pos2)+&amp;lt;-0.025-0.002, 0.025,0&amp;gt;, 0.0,&lt;br /&gt;
        PRIM_TEXTURE, FACE_3, GetGridTexture(grid_pos3), &amp;lt;-0.74, 0.05, 0&amp;gt;, GetGridOffset(grid_pos3)+ &amp;lt;-.34-0.002, 0.025, 0&amp;gt;, 0.0,&lt;br /&gt;
        PRIM_TEXTURE, FACE_4, GetGridTexture(grid_pos4), &amp;lt;0.05, 0.05, 0&amp;gt;, GetGridOffset(grid_pos4)+&amp;lt;-0.025-0.002, 0.025,0&amp;gt;, 0.0,&lt;br /&gt;
        PRIM_TEXTURE, FACE_5, GetGridTexture(grid_pos5), &amp;lt;0.125, 0.05, 0&amp;gt;, GetGridOffset(grid_pos5) + &amp;lt;0.0375-0.025-0.077-0.002, 0.025, 0&amp;gt;, 0.0&lt;br /&gt;
&lt;br /&gt;
//      PRIM_TEXTURE, FACE_1, GetGridTexture(grid_pos1), &amp;lt;0.25, 0.1, 0&amp;gt;, GetGridOffset(grid_pos1) + &amp;lt;0.075, 0, 0&amp;gt;, 0.0,&lt;br /&gt;
//      PRIM_TEXTURE, FACE_2, GetGridTexture(grid_pos2), &amp;lt;0.1, 0.1, 0&amp;gt;, GetGridOffset(grid_pos2), 0.0,&lt;br /&gt;
//      PRIM_TEXTURE, FACE_3, GetGridTexture(grid_pos3), &amp;lt;-1.48, 0.1, 0&amp;gt;, GetGridOffset(grid_pos3)+ &amp;lt;0.37, 0, 0&amp;gt;, 0.0,&lt;br /&gt;
//      PRIM_TEXTURE, FACE_4, GetGridTexture(grid_pos4), &amp;lt;0.1, 0.1, 0&amp;gt;, GetGridOffset(grid_pos4), 0.0,&lt;br /&gt;
//      PRIM_TEXTURE, FACE_5, GetGridTexture(grid_pos5), &amp;lt;0.25, 0.1, 0&amp;gt;, GetGridOffset(grid_pos5) - &amp;lt;0.075, 0, 0&amp;gt;, 0.0&lt;br /&gt;
 &lt;br /&gt;
        ]);&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
integer GetIndex(string char)&lt;br /&gt;
{&lt;br /&gt;
    integer ret = llSubStringIndex(gCharIndex, char);&lt;br /&gt;
&lt;br /&gt;
    if(0 &amp;lt;= ret)&lt;br /&gt;
        return ret;&lt;br /&gt;
&lt;br /&gt;
    // special char do nice trick :)&lt;br /&gt;
    string escaped = llEscapeURL(char);&lt;br /&gt;
&lt;br /&gt;
    // remap ’&lt;br /&gt;
    if (escaped == &amp;quot;%E2%80%99&amp;quot;)&lt;br /&gt;
        return 7;&lt;br /&gt;
&lt;br /&gt;
    // llSay(PUBLIC_CHANNEL, &amp;quot;Looking for &amp;quot; + escaped);&lt;br /&gt;
    integer found = llListFindList(decode, [escaped]);&lt;br /&gt;
&lt;br /&gt;
    // not found&lt;br /&gt;
    if(found &amp;lt; 0)&lt;br /&gt;
        return FALSE;&lt;br /&gt;
&lt;br /&gt;
    // return correct index&lt;br /&gt;
    return llStringLength(gCharIndex) + found;&lt;br /&gt;
 &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
RenderString(string str)&lt;br /&gt;
{&lt;br /&gt;
    // Get the grid positions for each pair of characters.&lt;br /&gt;
    vector GridPos1 = GetGridPos( GetIndex(llGetSubString(str, 0, 0)),&lt;br /&gt;
                                  GetIndex(llGetSubString(str, 1, 1)) );&lt;br /&gt;
    vector GridPos2 = GetGridPos( GetIndex(llGetSubString(str, 2, 2)),&lt;br /&gt;
                                  GetIndex(llGetSubString(str, 3, 3)) );&lt;br /&gt;
    vector GridPos3 = GetGridPos( GetIndex(llGetSubString(str, 4, 4)),&lt;br /&gt;
                                  GetIndex(llGetSubString(str, 5, 5)) );&lt;br /&gt;
    vector GridPos4 = GetGridPos( GetIndex(llGetSubString(str, 6, 6)),&lt;br /&gt;
                                  GetIndex(llGetSubString(str, 7, 7)) );&lt;br /&gt;
    vector GridPos5 = GetGridPos( GetIndex(llGetSubString(str, 8, 8)),&lt;br /&gt;
                                  GetIndex(llGetSubString(str, 9, 9)) );                                   &lt;br /&gt;
&lt;br /&gt;
    // Use these grid positions to display the correct textures/offsets.&lt;br /&gt;
    ShowChars(GridPos1, GridPos2, GridPos3, GridPos4, GridPos5);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Splitter python-fu script ==&lt;br /&gt;
You need to put this under the %USERPROFILE%\.gimp-2.6\plug-ins folder (in my case: \Documents and Settings\salahzar.SALAHZAR-PC\.gimp-2.6\plug-ins).&lt;br /&gt;
&lt;br /&gt;
To avoid problems with indents, spaces and tabs create the file with explorer guides.py and right clich use the IDLE edit to past the following source.&lt;br /&gt;
&lt;br /&gt;
Note: you need to restart GIMP to see it working.&lt;br /&gt;
&lt;br /&gt;
When running it is very simple just tell it &amp;quot;512&amp;quot; to split every 512 points.&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
&lt;br /&gt;
import math&lt;br /&gt;
from gimpfu import *&lt;br /&gt;
&lt;br /&gt;
def python_guides(timg, tdrawable, interval=100):&lt;br /&gt;
    timg.undo_group_start()&lt;br /&gt;
    for x in range(0, timg.width, interval):&lt;br /&gt;
       timg.add_vguide(x)&lt;br /&gt;
       &lt;br /&gt;
    for y in range(0, timg.height, interval):&lt;br /&gt;
       timg.add_hguide(y)&lt;br /&gt;
       &lt;br /&gt;
    timg.undo_group_end()&lt;br /&gt;
    &lt;br /&gt;
    gimp.displays_flush()&lt;br /&gt;
&lt;br /&gt;
register(&lt;br /&gt;
        &amp;quot;python_fu_guides&amp;quot;,&lt;br /&gt;
        &amp;quot;Guides: this will split the images in sections...&amp;quot;,&lt;br /&gt;
        &amp;quot;Guides: this will split the images in sections...&amp;quot;,&lt;br /&gt;
        &amp;quot;Salahzar Stenvaag&amp;quot;,&lt;br /&gt;
        &amp;quot; &amp;quot;,&lt;br /&gt;
        &amp;quot;2008&amp;quot;,&lt;br /&gt;
        &amp;quot;&amp;lt;Image&amp;gt;/Filters/Guides...&amp;quot;,&lt;br /&gt;
        &amp;quot;RGB*, GRAY*&amp;quot;,&lt;br /&gt;
        [&lt;br /&gt;
                (PF_INT, &amp;quot;interval&amp;quot;, &amp;quot;Interval&amp;quot;, 100)&lt;br /&gt;
        ],&lt;br /&gt;
        [],&lt;br /&gt;
        python_guides)&lt;br /&gt;
&lt;br /&gt;
main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the guides.py script is correctly installed you will see the following:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:XyText-utf8-Guides.jpg]]&lt;br /&gt;
&lt;br /&gt;
Options to choose:&lt;br /&gt;
&lt;br /&gt;
[[Image:XyText-UTF8-Guides2.jpg]]&lt;br /&gt;
&lt;br /&gt;
And the image with the lines in blue:&lt;br /&gt;
&lt;br /&gt;
[[Image:XyText-UTF8-Guides3.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Mega-image maker python-fu script ==&lt;br /&gt;
You need to put this under the %USERPROFILE%\.gimp-2.6\plug-ins folder (in my case: \Documents and Settings\salahzar.SALAHZAR-PC\.gimp-2.6\plug-ins).&lt;br /&gt;
&lt;br /&gt;
To avoid problems with indents, spaces and tabs create the file with explorer megaimages.py and right clich use the IDLE edit to past the following source.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you need your characters you need to change the UTF-8 codings in &amp;quot;decode&amp;quot; var&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#! /usr/bin/env python&lt;br /&gt;
from gimpfu import *&lt;br /&gt;
&lt;br /&gt;
# you can remove logging, I used it to be sure program was working since it can be a bit slow &lt;br /&gt;
# to generate all the combination&lt;br /&gt;
def python_log_init():&lt;br /&gt;
    fileHandle = open( &#039;python.log&#039;, &#039;w&#039;)&lt;br /&gt;
    fileHandle.close()&lt;br /&gt;
    &lt;br /&gt;
def python_log(s):&lt;br /&gt;
    fileHandle = open ( &#039;python.log&#039;, &#039;a&#039; )&lt;br /&gt;
    fileHandle.write(str(s)+&amp;quot;\n&amp;quot;)&lt;br /&gt;
    fileHandle.close() &lt;br /&gt;
&lt;br /&gt;
def python_xytext2(font,color,size,limit):&lt;br /&gt;
  &amp;quot;&amp;quot;&amp;quot;Print the arguments on standard output&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
  python_log_init()&lt;br /&gt;
  python_log(&amp;quot;font: %s color: &amp;lt;%d,%d,%d&amp;gt; size: %d limit: %d&amp;quot; % ( font, color[0], color[1], color[2], size, limit ))&lt;br /&gt;
  chars = &amp;quot; !\&amp;quot;#$%&amp;amp;&#039;()*+,-./0123456789:;&amp;lt;=&amp;gt;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~&amp;quot;&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  # &lt;br /&gt;
  &lt;br /&gt;
  #        cap cedille      u:         e/            a^         a:          a/         a ring      cedille     e^           e:&lt;br /&gt;
  decode=  [&amp;quot;\xC3\x87&amp;quot;, &amp;quot;\xC3\xBC&amp;quot;, &amp;quot;\xC3\xA9&amp;quot;, &amp;quot;\xC3\xA2&amp;quot;, &amp;quot;\xC3\xA4&amp;quot;, &amp;quot;\xC3\xA0&amp;quot;, &amp;quot;\xC3\xA5&amp;quot;, &amp;quot;\xC3\xA7&amp;quot;, &amp;quot;\xC3\xAA&amp;quot;, &amp;quot;\xC3\xAB&amp;quot; ]  &lt;br /&gt;
  &lt;br /&gt;
    &lt;br /&gt;
  #                    e\           i:               i^            i\                A:          A ring          E/              ae           AE           marker &amp;gt;&lt;br /&gt;
  decode+=[&amp;quot;\xC3\xA8&amp;quot;, &amp;quot;\xC3\xAF&amp;quot;, &amp;quot;\xC3\xAE&amp;quot;, &amp;quot;\xC3\xAC&amp;quot;, &amp;quot;\xC3\x84&amp;quot;, &amp;quot;\xC3\x85&amp;quot;, &amp;quot;\xC3\x89&amp;quot;, &amp;quot;\xC3\xA6&amp;quot;, &amp;quot;\xC3\x86&amp;quot;, &amp;quot;\xE2\x96\xB6&amp;quot; ]&lt;br /&gt;
&lt;br /&gt;
  #                 o:               o/           u^          u\              y:               O:             U:          cent           pound        yen&lt;br /&gt;
  decode+=[&amp;quot;\xC3\xB6&amp;quot;, &amp;quot;\xC3\xB2&amp;quot;, &amp;quot;\xC3\xBB&amp;quot;, &amp;quot;\xC3\xB9&amp;quot;, &amp;quot;\xC3\xBF&amp;quot;, &amp;quot;\xC3\x96&amp;quot;, &amp;quot;\xC3\x9C&amp;quot;, &amp;quot;\xC2\xA2&amp;quot;, &amp;quot;\xC2\xA3&amp;quot;, &amp;quot;\xC2\xA5&amp;quot;]&lt;br /&gt;
   &lt;br /&gt;
  #                 A^              a/              i/                o/            u/              n~           E:            y/              inv ?         O^&lt;br /&gt;
  decode+=[&amp;quot;\xC3\x82&amp;quot;, &amp;quot;\xC3\xA1&amp;quot;, &amp;quot;\xC3\xAD&amp;quot;, &amp;quot;\xC3\xB3&amp;quot;, &amp;quot;\xC3\xBA&amp;quot;, &amp;quot;\xC3\xB1&amp;quot;, &amp;quot;\xC3\x8B&amp;quot;, &amp;quot;\xC3\xBD&amp;quot;, &amp;quot;\xC2\xBF&amp;quot;, &amp;quot;\xC3\x94&amp;quot; ] &lt;br /&gt;
&lt;br /&gt;
  #                   inv !             I\             I/           degree       E^              I^            o^            U^&lt;br /&gt;
  decode+=[&amp;quot;\xC2\xA1&amp;quot;, &amp;quot;\xC3\x8C&amp;quot;, &amp;quot;\xC3\x8D&amp;quot;, &amp;quot;\xC2\xB0&amp;quot;, &amp;quot;\xC3\x8A&amp;quot;, &amp;quot;\xC3\x8E&amp;quot;, &amp;quot;\xC3\xB4&amp;quot;, &amp;quot;\xC3\x9B&amp;quot; ]&lt;br /&gt;
&lt;br /&gt;
  #                     Y:          euro           german ss         E\              A\           A/              U\           U/               O\           O/&lt;br /&gt;
  decode+=[&amp;quot;\xC3\x9D&amp;quot;, &amp;quot;\xE2\x82\xAC&amp;quot;, &amp;quot;\xC3\x9F&amp;quot;, &amp;quot;\xC3\x88&amp;quot;, &amp;quot;\xC3\x80&amp;quot;, &amp;quot;\xC3\x81&amp;quot;, &amp;quot;\xC3\x99&amp;quot;, &amp;quot;\xC3\x9A&amp;quot;, &amp;quot;\xC3\x92&amp;quot;, &amp;quot;\xC3\x93&amp;quot;   ]                  &lt;br /&gt;
&lt;br /&gt;
  #                   Sv           sv             zv             Zv              Y:             I:&lt;br /&gt;
  decode+=[ &amp;quot;\xC5\xA0&amp;quot;, &amp;quot;\xC5\xA1&amp;quot;, &amp;quot;\xC5\xBE&amp;quot;, &amp;quot;\xC5\xBD&amp;quot;, &amp;quot;\xC3\x9D&amp;quot;, &amp;quot;\xC3\x8C&amp;quot; ]&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
  width=5120&lt;br /&gt;
  height=5120&lt;br /&gt;
  img = gimp.Image(width, height, RGB)&lt;br /&gt;
  layer = gimp.Layer(img, &amp;quot;my font&amp;quot;, width, height, RGB_IMAGE, 100, NORMAL_MODE)&lt;br /&gt;
  img.add_layer(layer, 0)&lt;br /&gt;
  layer.add_alpha()&lt;br /&gt;
  gimp.set_foreground(color)&lt;br /&gt;
  pdb.gimp_selection_all(img)&lt;br /&gt;
  pdb.gimp_edit_clear(layer)&lt;br /&gt;
  pdb.gimp_selection_none(img)&lt;br /&gt;
  size= 20 # 23 # 21.3 # 30&lt;br /&gt;
  &lt;br /&gt;
  index=0&lt;br /&gt;
  numtot=len(chars)+len(decode)&lt;br /&gt;
  #numtot=50&lt;br /&gt;
  if limit&amp;gt;0: numtot=limit&lt;br /&gt;
  deltay=12.8 # 13.8215 # 12.8 # 18&lt;br /&gt;
  deltax=25.6 # 27.6432 # 25.6 # 36&lt;br /&gt;
  maxchars=len(chars)&lt;br /&gt;
  for first in range(numtot):&lt;br /&gt;
  &lt;br /&gt;
     if first&amp;lt;maxchars: &lt;br /&gt;
        el1=chars[first]&lt;br /&gt;
     else:&lt;br /&gt;
        el1=decode[first-maxchars]&lt;br /&gt;
     &lt;br /&gt;
     python_log(str(first)+&amp;quot;/&amp;quot;+str(numtot)+&amp;quot;:  &amp;quot;+el1)&lt;br /&gt;
     for second in range(first+1):&lt;br /&gt;
&lt;br /&gt;
          # to save time removed function call&lt;br /&gt;
          if second&amp;lt;maxchars: &lt;br /&gt;
             el2=chars[second]&lt;br /&gt;
          else:&lt;br /&gt;
             el2=decode[second-maxchars]&lt;br /&gt;
                 &lt;br /&gt;
          y=second * deltay * 2 # horizontal distance&lt;br /&gt;
          x=first*deltax # line distance&lt;br /&gt;
          pdb.gimp_text_fontname(img,layer,y,x,el1,0,TRUE,size,PIXELS,font)&lt;br /&gt;
          pdb.gimp_text_fontname(img,layer,y+deltay,x,el2,0,TRUE,size,PIXELS,font)&lt;br /&gt;
          &lt;br /&gt;
          index+=1&lt;br /&gt;
          &lt;br /&gt;
  &lt;br /&gt;
  # Now ready to display this image&lt;br /&gt;
  img.merge_visible_layers(0)&lt;br /&gt;
  gimp.Display(img)&lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
register(&lt;br /&gt;
  &amp;quot;xytext2&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;,&lt;br /&gt;
  &amp;quot;&amp;lt;Toolbox&amp;gt;/Xtns/_MegaImage&amp;quot;, &amp;quot;&amp;quot;,&lt;br /&gt;
  [&lt;br /&gt;
  (PF_FONT, &amp;quot;font&amp;quot;, &amp;quot;Font to use&amp;quot;, &amp;quot;Arial&amp;quot;),&lt;br /&gt;
  (PF_COLOR,&amp;quot;color&amp;quot;,&amp;quot;Color to use&amp;quot;, (255,255,255) ),&lt;br /&gt;
  (PF_INT,    &amp;quot;size&amp;quot;, &amp;quot;Font size&amp;quot;, 45          ),&lt;br /&gt;
  (PF_INT,  &amp;quot;limit&amp;quot;, &amp;quot;limit font generation &amp;quot;, 0  ),&lt;br /&gt;
 &lt;br /&gt;
  ],&lt;br /&gt;
  [],&lt;br /&gt;
  python_xytext2&lt;br /&gt;
  )&lt;br /&gt;
&lt;br /&gt;
main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here how the menu should appear:&lt;br /&gt;
&lt;br /&gt;
[[Image:XyText-UTF8-Megaimagechoose.jpg]]&lt;br /&gt;
&lt;br /&gt;
How to launch it: &#039;&#039;&#039;Note!! DON&#039;T USE PROPORTIONAL CHARACTERS!!! BUT MONOSPACE 43 MIGHT BE BETTER&#039;&#039;&#039;&lt;br /&gt;
Also when checking use the limit font generation to 10: the computing process for all 200 characters is VEEERY LOOONG!!!! 0 means all the characters.&lt;br /&gt;
&lt;br /&gt;
[[Image:XyText-UTF8-Megaimage2.jpg]]&lt;br /&gt;
&lt;br /&gt;
How to zoom on the megaimage (Zoom 100%) and check produced characters:&lt;br /&gt;
&lt;br /&gt;
[[Image:XyText-UTF8-Zoom11.jpg]]&lt;br /&gt;
&lt;br /&gt;
As you see the default is producing BAD characters.. Proportional cannot be used since characters cannot be computed with xytext optimized algorithm.&lt;br /&gt;
&lt;br /&gt;
[[Image:XyText-UTF8-Zoom2.jpg]]&lt;br /&gt;
&lt;br /&gt;
== What if I want the full script? ==&lt;br /&gt;
Here you are:&lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
// ZZText (5 Face, Multi Texture)&lt;br /&gt;
//&lt;br /&gt;
// Originally Written by Xylor Baysklef&lt;br /&gt;
//&lt;br /&gt;
// Modified by Thraxis Epsilon January 20, 2006&lt;br /&gt;
// Added Support for 5 Face Prim, based on modification&lt;br /&gt;
// of XyText v1.1.1 by Kermitt Quick for Single Texture.&lt;br /&gt;
//&lt;br /&gt;
// Modified by Salahzar Stenvaag for International and new textures&lt;br /&gt;
// produced with GIMP. See wiki page ZZText for further info&lt;br /&gt;
// Obtain ME (starting linking channel from Object name)&lt;br /&gt;
// thane can use all the other commands&lt;br /&gt;
// IDEAL for linked structures&lt;br /&gt;
&lt;br /&gt;
// XyText Message Map.&lt;br /&gt;
integer DISPLAY_STRING      = 0;&lt;br /&gt;
integer DISPLAY_EXTENDED    = 100;&lt;br /&gt;
integer REMAP_INDICES       = 200;&lt;br /&gt;
integer RESET_INDICES       = 300;&lt;br /&gt;
integer SET_CELL_INFO       = 400;&lt;br /&gt;
integer SET_THICKNESS       = 600;&lt;br /&gt;
integer SET_COLOR           = 700;&lt;br /&gt;
&lt;br /&gt;
// This is an extended character escape sequence.&lt;br /&gt;
string  ESCAPE_SEQUENCE = &amp;quot;\\e&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// This is used to get an index for the extended character.&lt;br /&gt;
string  EXTENDED_INDEX  = &amp;quot;123456789abcdef&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Face numbers.&lt;br /&gt;
integer FACE_1          = 3;&lt;br /&gt;
integer FACE_2          = 7;&lt;br /&gt;
integer FACE_3          = 4;&lt;br /&gt;
integer FACE_4          = 6;&lt;br /&gt;
integer FACE_5          = 1;&lt;br /&gt;
&lt;br /&gt;
// to handle special characters from CP850 page for european countries&lt;br /&gt;
list decode = [];&lt;br /&gt;
&lt;br /&gt;
// Used to hide the text after a fade-out.&lt;br /&gt;
key     TRANSPARENT     = &amp;quot;701917a8-d614-471f-13dd-5f4644e36e3c&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// This is a list of textures for all 2-character combinations.&lt;br /&gt;
list    CHARACTER_GRID  = [&lt;br /&gt;
    &amp;quot;96f4578b-879e-44ae-d223-427cc615f5a4&amp;quot;, // my slice-0-0&lt;br /&gt;
    &amp;quot;eab5360f-6653-593f-b679-69c68b0dd001&amp;quot;, // 1-0&lt;br /&gt;
    &amp;quot;367330be-717a-277d-5205-131cd6ded458&amp;quot;, // 1-1&lt;br /&gt;
    &amp;quot;32046675-6e7e-2425-ce77-69000b0b4d96&amp;quot;, // 2-0&lt;br /&gt;
    &amp;quot;40085901-bde6-2dd4-40cd-b6d48d242997&amp;quot;, // 2-1&lt;br /&gt;
    &amp;quot;205d318b-09b7-7ecc-922e-801c93a546c8&amp;quot;, // 2-2&lt;br /&gt;
    &amp;quot;841e7826-3645-d4f0-d48b-389586dd8e90&amp;quot;, // 3-0&lt;br /&gt;
    &amp;quot;e2db78c5-fb47-d767-4744-8cb6d84610d0&amp;quot;, // 3-1&lt;br /&gt;
    &amp;quot;15312c89-afd4-854c-9d9b-5b9e11844aed&amp;quot;, // 3-2&lt;br /&gt;
    &amp;quot;d180e771-0393-d09b-8cac-0af6d550ae4a&amp;quot;, // 3-3&lt;br /&gt;
    &amp;quot;c6c1d2c8-5dfd-b13a-7f1e-c3ede8126769&amp;quot;, // 4-0&lt;br /&gt;
    &amp;quot;bc100d0c-a445-947f-caa4-285d9cc8a9de&amp;quot;, // 4-1&lt;br /&gt;
    &amp;quot;0b31e862-75a4-9ed3-6331-e9e700a0fedb&amp;quot;, // 4-2&lt;br /&gt;
    &amp;quot;0eacc306-6bd5-ab31-de47-c686141a6733&amp;quot;, // 4-3&lt;br /&gt;
    &amp;quot;b68de1d9-4890-74a0-4d25-d4d5c83a0dba&amp;quot;, // 4-4&lt;br /&gt;
    &amp;quot;04b2bf9b-a8bb-0a39-1062-9b005229eba9&amp;quot;, // 5-0&lt;br /&gt;
    &amp;quot;be293f10-25ec-beb9-738b-fe1892b82aef&amp;quot;, // 5-1&lt;br /&gt;
    &amp;quot;5e9c8317-71f5-f073-76ab-7c412d3acb84&amp;quot;, // 5-2&lt;br /&gt;
    &amp;quot;030b441b-9022-2aba-f7a7-af6810c354b8&amp;quot;, // 5-3&lt;br /&gt;
    &amp;quot;9f455858-8ae6-3a9a-c2d4-bc5ee92430ac&amp;quot;, // 5-4&lt;br /&gt;
    &amp;quot;ee741143-f01e-f730-667e-66a3cd57d1cc&amp;quot;, // 5-5&lt;br /&gt;
    &amp;quot;710282bc-bd80-5a44-6987-0c4c11a4c294&amp;quot;, // 6-0&lt;br /&gt;
    &amp;quot;c9c410db-675a-1e98-4107-debd3c73a754&amp;quot;, // 6-1&lt;br /&gt;
    &amp;quot;486c2336-71c5-b962-266c-838a865c067c&amp;quot;, // 6-2&lt;br /&gt;
    &amp;quot;d4722155-0b6d-3673-0208-a727729bc117&amp;quot;, // 6-3&lt;br /&gt;
    &amp;quot;bc7af3cd-ee48-08df-fe8b-a6ca8a425733&amp;quot;, // 6-4&lt;br /&gt;
    &amp;quot;f23d7a73-00c3-1ffd-69a7-0cca031c939d&amp;quot;, // 6-5&lt;br /&gt;
    &amp;quot;aa95bfd1-ac80-f962-7acf-d6aeed9c7e81&amp;quot;, // 6-6&lt;br /&gt;
    &amp;quot;53fd52e3-0e8b-dcc8-42f8-332aef421bd2&amp;quot;, // 7-0&lt;br /&gt;
    &amp;quot;da3f6f09-3e3a-e156-8e2e-1040111a5635&amp;quot;, // 7-1&lt;br /&gt;
    &amp;quot;409a95c0-b685-2036-d0de-75e8ab654243&amp;quot;, // 7-2&lt;br /&gt;
    &amp;quot;14e05aca-3a61-b892-3632-dcde72324779&amp;quot;, // 7-3&lt;br /&gt;
    &amp;quot;546c0e4f-b678-895d-2035-0f39bb7f4979&amp;quot;, // 7-4&lt;br /&gt;
    &amp;quot;cf2fc337-109f-ba25-8ff5-786f7d6ceb5b&amp;quot;, // 7-5&lt;br /&gt;
    &amp;quot;9943204b-a4de-868a-3cdd-8785d1864ede&amp;quot;, // 7-6&lt;br /&gt;
    &amp;quot;765cfd9c-9703-b5ba-2c5d-f1c8bd44e0f4&amp;quot;  // 7-7&lt;br /&gt;
        ];&lt;br /&gt;
&lt;br /&gt;
integer ME;&lt;br /&gt;
&lt;br /&gt;
// All displayable characters.  Default to ASCII order.&lt;br /&gt;
string gCharIndex;&lt;br /&gt;
&lt;br /&gt;
// This is the channel to listen on while acting&lt;br /&gt;
// as a cell in a larger display.&lt;br /&gt;
integer gCellChannel      = -1;&lt;br /&gt;
&lt;br /&gt;
// This is the starting character position in the cell channel message&lt;br /&gt;
// to render.&lt;br /&gt;
integer gCellCharPosition = 0;&lt;br /&gt;
&lt;br /&gt;
// This is whether or not to use the fade in/out special effect.&lt;br /&gt;
integer gCellUseFading      = FALSE;&lt;br /&gt;
&lt;br /&gt;
// This is how long to display the text before fading out (if using&lt;br /&gt;
// fading special effect).&lt;br /&gt;
// Note: &amp;lt; 0  means don&#039;t fade out.&lt;br /&gt;
float   gCellHoldDelay      = 1.0;&lt;br /&gt;
&lt;br /&gt;
ResetCharIndex()&lt;br /&gt;
{&lt;br /&gt;
    gCharIndex  = &amp;quot; !\&amp;quot;#$%&amp;amp;&#039;()*+,-./0123456789:;&amp;lt;=&amp;gt;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`&amp;quot;;&lt;br /&gt;
    // \&amp;quot; &amp;lt;-- Fixes LSL syntax highlighting bug.&lt;br /&gt;
    gCharIndex += &amp;quot;abcdefghijklmnopqrstuvwxyz{|}~&amp;quot;;&lt;br /&gt;
    //        cap cedille      u:         e/            a^         a:          a/         a ring      cedille     e^           e:&lt;br /&gt;
    decode=  [&amp;quot;%C3%87&amp;quot;, &amp;quot;%C3%BC&amp;quot;, &amp;quot;%C3%A9&amp;quot;, &amp;quot;%C3%A2&amp;quot;, &amp;quot;%C3%A4&amp;quot;, &amp;quot;%C3%A0&amp;quot;, &amp;quot;%C3%A5&amp;quot;, &amp;quot;%C3%A7&amp;quot;, &amp;quot;%C3%AA&amp;quot;, &amp;quot;%C3%AB&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        //                    e\           i:               i^            i\                A:          A ring          E/              ae           AE           marker &amp;gt;&lt;br /&gt;
        &amp;quot;%C3%A8&amp;quot;, &amp;quot;%C3%AF&amp;quot;, &amp;quot;%C3%AE&amp;quot;, &amp;quot;%C3%AC&amp;quot;, &amp;quot;%C3%84&amp;quot;, &amp;quot;%C3%85&amp;quot;, &amp;quot;%C3%89&amp;quot;, &amp;quot;%C3%A6&amp;quot;, &amp;quot;%C3%86&amp;quot;, &amp;quot;%E2%96%B6&amp;quot; ,&lt;br /&gt;
&lt;br /&gt;
        //                 o:               o/           u^          u\              y:               O:             U:          cent           pound        yen&lt;br /&gt;
        &amp;quot;%C3%B6&amp;quot;, &amp;quot;%C3%B2&amp;quot;, &amp;quot;%C3%BB&amp;quot;, &amp;quot;%C3%B9&amp;quot;, &amp;quot;%C3%BF&amp;quot;, &amp;quot;%C3%96&amp;quot;, &amp;quot;%C3%9C&amp;quot;, &amp;quot;%C2%A2&amp;quot;, &amp;quot;%C2%A3&amp;quot;, &amp;quot;%C2%A5&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
        //                 A^              a/              i/                o/            u/              n~           E:            y/              inv ?         O^&lt;br /&gt;
        &amp;quot;%C3%82&amp;quot;, &amp;quot;%C3%A1&amp;quot;, &amp;quot;%C3%AD&amp;quot;, &amp;quot;%C3%B3&amp;quot;, &amp;quot;%C3%BA&amp;quot;, &amp;quot;%C3%B1&amp;quot;, &amp;quot;%C3%8B&amp;quot;, &amp;quot;%C3%BD&amp;quot;, &amp;quot;%C2%BF&amp;quot;, &amp;quot;%C3%94&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
        //                   inv !             I\             I/           degree       E^              I^            o^            U^&lt;br /&gt;
        &amp;quot;%C2%A1&amp;quot;, &amp;quot;%C3%8C&amp;quot;, &amp;quot;%C3%8D&amp;quot;, &amp;quot;%C2%B0&amp;quot;, &amp;quot;%C3%8A&amp;quot;, &amp;quot;%C3%8E&amp;quot;, &amp;quot;%C3%B4&amp;quot;, &amp;quot;%C3%9B&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
        //                     Y:          euro           german ss         E\              A\           A/              U\           U/               O\           O/&lt;br /&gt;
        &amp;quot;%C3%9D&amp;quot;, &amp;quot;%E2%82%AC&amp;quot;, &amp;quot;%C3%9F&amp;quot;, &amp;quot;%C3%88&amp;quot;, &amp;quot;%C3%80&amp;quot;, &amp;quot;%C3%81&amp;quot;, &amp;quot;%C3%99&amp;quot;, &amp;quot;%C3%9A&amp;quot;, &amp;quot;%C3%92&amp;quot;, &amp;quot;%C3%93&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
        //                   Sv           sv             zv             Zv              Y:             I:&lt;br /&gt;
        &amp;quot;%C5%A0&amp;quot;, &amp;quot;%C5%A1&amp;quot;, &amp;quot;%C5%BE&amp;quot;, &amp;quot;%C5%BD&amp;quot;, &amp;quot;%C3%9D&amp;quot;, &amp;quot;%C3%8C&amp;quot; ];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
vector GetGridPos(integer index1, integer index2)&lt;br /&gt;
{&lt;br /&gt;
    // There are two ways to use the lookup table...&lt;br /&gt;
    integer Col;&lt;br /&gt;
    integer Row;&lt;br /&gt;
    if (index1 &amp;gt;= index2)&lt;br /&gt;
    {&lt;br /&gt;
        // In this case, the row is the index of the first character:&lt;br /&gt;
        Row = index1;&lt;br /&gt;
        // And the col is the index of the second character (x2)&lt;br /&gt;
        Col = index2 * 2;&lt;br /&gt;
    }&lt;br /&gt;
    // Index1 &amp;lt; Index2&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        // In this case, the row is the index of the second character:&lt;br /&gt;
        Row = index2;&lt;br /&gt;
        // And the col is the index of the first character, x2, offset by 1.&lt;br /&gt;
        Col = index1 * 2 + 1;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return &amp;lt;Col, Row, 0&amp;gt;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
string GetGridTexture(vector grid_pos)&lt;br /&gt;
{&lt;br /&gt;
    // Calculate the texture in the grid to use.&lt;br /&gt;
    integer GridCol = llRound(grid_pos.x) / 40; // PK was 20&lt;br /&gt;
    integer GridRow = llRound(grid_pos.y) / 20; // PK was 10&lt;br /&gt;
&lt;br /&gt;
    // Lookup the texture.&lt;br /&gt;
    key Texture = llList2Key(CHARACTER_GRID, GridRow * (GridRow + 1) / 2 + GridCol);&lt;br /&gt;
    return Texture;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
vector GetGridOffset(vector grid_pos)&lt;br /&gt;
{&lt;br /&gt;
    // Zoom in on the texture showing our character pair.&lt;br /&gt;
    integer Col = llRound(grid_pos.x) % 40; // PK was 20&lt;br /&gt;
    integer Row = llRound(grid_pos.y) % 20; // PK was 10&lt;br /&gt;
&lt;br /&gt;
    // Return the offset in the texture.&lt;br /&gt;
    return &amp;lt;-0.45 + 0.025 * Col, 0.45 - 0.05 * Row, 0.0&amp;gt;; // PK was 0.05 and 0.1&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ShowChars(vector grid_pos1, vector grid_pos2, vector grid_pos3, vector grid_pos4, vector grid_pos5)&lt;br /&gt;
{&lt;br /&gt;
    // Set the primitive textures directly.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    llSetLinkPrimitiveParamsFast(LINK_THIS, [&lt;br /&gt;
        PRIM_TEXTURE, FACE_1, GetGridTexture(grid_pos1), &amp;lt;0.125, 0.05, 0&amp;gt;, GetGridOffset(grid_pos1) + &amp;lt;0.0375-0.025-0.002, 0.025, 0&amp;gt;, 0.0,&lt;br /&gt;
        PRIM_TEXTURE, FACE_2, GetGridTexture(grid_pos2), &amp;lt;0.05, 0.05, 0&amp;gt;, GetGridOffset(grid_pos2)+&amp;lt;-0.025-0.002, 0.025,0&amp;gt;, 0.0,&lt;br /&gt;
        PRIM_TEXTURE, FACE_3, GetGridTexture(grid_pos3), &amp;lt;-0.74, 0.05, 0&amp;gt;, GetGridOffset(grid_pos3)+ &amp;lt;-.34-0.002, 0.025, 0&amp;gt;, 0.0,&lt;br /&gt;
        PRIM_TEXTURE, FACE_4, GetGridTexture(grid_pos4), &amp;lt;0.05, 0.05, 0&amp;gt;, GetGridOffset(grid_pos4)+&amp;lt;-0.025-0.002, 0.025,0&amp;gt;, 0.0,&lt;br /&gt;
        PRIM_TEXTURE, FACE_5, GetGridTexture(grid_pos5), &amp;lt;0.125, 0.05, 0&amp;gt;, GetGridOffset(grid_pos5) + &amp;lt;0.0375-0.025-0.077-0.002, 0.025, 0&amp;gt;, 0.0&lt;br /&gt;
//      PRIM_TEXTURE, FACE_1, GetGridTexture(grid_pos1), &amp;lt;0.25, 0.1, 0&amp;gt;, GetGridOffset(grid_pos1) + &amp;lt;0.075, 0, 0&amp;gt;, 0.0,&lt;br /&gt;
//      PRIM_TEXTURE, FACE_2, GetGridTexture(grid_pos2), &amp;lt;0.1, 0.1, 0&amp;gt;, GetGridOffset(grid_pos2), 0.0,&lt;br /&gt;
//      PRIM_TEXTURE, FACE_3, GetGridTexture(grid_pos3), &amp;lt;-1.48, 0.1, 0&amp;gt;, GetGridOffset(grid_pos3)+ &amp;lt;0.37, 0, 0&amp;gt;, 0.0,&lt;br /&gt;
//      PRIM_TEXTURE, FACE_4, GetGridTexture(grid_pos4), &amp;lt;0.1, 0.1, 0&amp;gt;, GetGridOffset(grid_pos4), 0.0,&lt;br /&gt;
//  PRIM_TEXTURE, FACE_5, GetGridTexture(grid_pos5), &amp;lt;0.25, 0.1, 0&amp;gt;, GetGridOffset(grid_pos5) - &amp;lt;0.075, 0, 0&amp;gt;, 0.0&lt;br /&gt;
            ]);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
integer GetIndex(string char)&lt;br /&gt;
{&lt;br /&gt;
    integer ret = llSubStringIndex(gCharIndex, char);&lt;br /&gt;
&lt;br /&gt;
    if(0 &amp;lt;= ret)&lt;br /&gt;
        return ret;&lt;br /&gt;
&lt;br /&gt;
    // special char do nice trick :)&lt;br /&gt;
    string escaped = llEscapeURL(char);&lt;br /&gt;
&lt;br /&gt;
    // remap ’&lt;br /&gt;
    if(escaped == &amp;quot;%E2%80%99&amp;quot;)&lt;br /&gt;
        return 7;&lt;br /&gt;
&lt;br /&gt;
    //llSay(PUBLIC_CHANNEL, &amp;quot;Looking for &amp;quot; + escaped);&lt;br /&gt;
    integer found = llListFindList(decode, [escaped]);&lt;br /&gt;
&lt;br /&gt;
    // not found&lt;br /&gt;
    if(found &amp;lt; 0)&lt;br /&gt;
        return FALSE;&lt;br /&gt;
&lt;br /&gt;
    // return correct index&lt;br /&gt;
    return llStringLength(gCharIndex) + found;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
RenderString(string str)&lt;br /&gt;
{&lt;br /&gt;
    // Get the grid positions for each pair of characters.&lt;br /&gt;
    vector GridPos1 = GetGridPos( GetIndex(llGetSubString(str, 0, 0)),&lt;br /&gt;
        GetIndex(llGetSubString(str, 1, 1)) );&lt;br /&gt;
    vector GridPos2 = GetGridPos( GetIndex(llGetSubString(str, 2, 2)),&lt;br /&gt;
        GetIndex(llGetSubString(str, 3, 3)) );&lt;br /&gt;
    vector GridPos3 = GetGridPos( GetIndex(llGetSubString(str, 4, 4)),&lt;br /&gt;
        GetIndex(llGetSubString(str, 5, 5)) );&lt;br /&gt;
    vector GridPos4 = GetGridPos( GetIndex(llGetSubString(str, 6, 6)),&lt;br /&gt;
        GetIndex(llGetSubString(str, 7, 7)) );&lt;br /&gt;
    vector GridPos5 = GetGridPos( GetIndex(llGetSubString(str, 8, 8)),&lt;br /&gt;
        GetIndex(llGetSubString(str, 9, 9)) );&lt;br /&gt;
&lt;br /&gt;
    // Use these grid positions to display the correct textures/offsets.&lt;br /&gt;
    ShowChars(GridPos1, GridPos2, GridPos3, GridPos4, GridPos5);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
RenderWithEffects(string str)&lt;br /&gt;
{&lt;br /&gt;
    // Get the grid positions for each pair of characters.&lt;br /&gt;
    vector GridPos1 = GetGridPos( llSubStringIndex(gCharIndex, llGetSubString(str, 0, 0)),&lt;br /&gt;
        llSubStringIndex(gCharIndex, llGetSubString(str, 1, 1)) );&lt;br /&gt;
    vector GridPos2 = GetGridPos( llSubStringIndex(gCharIndex, llGetSubString(str, 2, 2)),&lt;br /&gt;
        llSubStringIndex(gCharIndex, llGetSubString(str, 3, 3)) );&lt;br /&gt;
    vector GridPos3 = GetGridPos( llSubStringIndex(gCharIndex, llGetSubString(str, 4, 4)),&lt;br /&gt;
        llSubStringIndex(gCharIndex, llGetSubString(str, 5, 5)) );&lt;br /&gt;
    vector GridPos4 = GetGridPos( llSubStringIndex(gCharIndex, llGetSubString(str, 6, 6)),&lt;br /&gt;
        llSubStringIndex(gCharIndex, llGetSubString(str, 7, 7)) );&lt;br /&gt;
    vector GridPos5 = GetGridPos( llSubStringIndex(gCharIndex, llGetSubString(str, 8, 8)),&lt;br /&gt;
        llSubStringIndex(gCharIndex, llGetSubString(str, 9, 9)) );&lt;br /&gt;
&lt;br /&gt;
    // First set the alpha to the lowest possible.&lt;br /&gt;
    llSetAlpha(0.05, ALL_SIDES);&lt;br /&gt;
&lt;br /&gt;
    // Use these grid positions to display the correct textures/offsets.&lt;br /&gt;
    ShowChars(GridPos1, GridPos2, GridPos3, GridPos4, GridPos5);&lt;br /&gt;
&lt;br /&gt;
    float Alpha;&lt;br /&gt;
    for (Alpha = 0.10; Alpha &amp;lt;= 1.0; Alpha += 0.05)&lt;br /&gt;
        llSetAlpha(Alpha, ALL_SIDES);&lt;br /&gt;
&lt;br /&gt;
    // See if we want to fade out as well.&lt;br /&gt;
    if (gCellHoldDelay &amp;lt; 0.0)&lt;br /&gt;
        // No, bail out. (Just keep showing the string at full strength).&lt;br /&gt;
        return;&lt;br /&gt;
&lt;br /&gt;
    // Hold the text for a while.&lt;br /&gt;
    llSleep(gCellHoldDelay);&lt;br /&gt;
&lt;br /&gt;
    // Now fade out.&lt;br /&gt;
    for (Alpha = 0.95; Alpha &amp;gt;= 0.05; Alpha -= 0.05)&lt;br /&gt;
        llSetAlpha(Alpha, ALL_SIDES);&lt;br /&gt;
&lt;br /&gt;
    // Make the text transparent to fully hide it.&lt;br /&gt;
    llSetTexture(TRANSPARENT, ALL_SIDES);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
RenderExtended(string str)&lt;br /&gt;
{&lt;br /&gt;
    // Look for escape sequences.&lt;br /&gt;
    list Parsed       = llParseString2List(str, [], [ESCAPE_SEQUENCE]);&lt;br /&gt;
    integer ParsedLen = llGetListLength(Parsed);&lt;br /&gt;
&lt;br /&gt;
    // Create a list of index values to work with.&lt;br /&gt;
    list Indices;&lt;br /&gt;
    // We start with room for 6 indices.&lt;br /&gt;
    integer IndicesLeft = 10;&lt;br /&gt;
&lt;br /&gt;
    integer i;&lt;br /&gt;
    string Token;&lt;br /&gt;
    integer Clipped;&lt;br /&gt;
    integer LastWasEscapeSequence = FALSE;&lt;br /&gt;
    // Work from left to right.&lt;br /&gt;
    for (i = 0; i &amp;lt; ParsedLen &amp;amp;&amp;amp; IndicesLeft &amp;gt; 0; i++)&lt;br /&gt;
    {&lt;br /&gt;
        Token = llList2String(Parsed, i);&lt;br /&gt;
&lt;br /&gt;
        // If this is an escape sequence, just set the flag and move on.&lt;br /&gt;
        if (Token == ESCAPE_SEQUENCE)&lt;br /&gt;
        {&lt;br /&gt;
            LastWasEscapeSequence = TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        // Token != ESCAPE_SEQUENCE&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            // Otherwise this is a normal token.  Check its length.&lt;br /&gt;
            Clipped = FALSE;&lt;br /&gt;
            integer TokenLength = llStringLength(Token);&lt;br /&gt;
&lt;br /&gt;
            // Clip if necessary.&lt;br /&gt;
            if (TokenLength &amp;gt; IndicesLeft)&lt;br /&gt;
            {&lt;br /&gt;
                Token = llGetSubString(Token, 0, IndicesLeft - 1);&lt;br /&gt;
                TokenLength = llStringLength(Token);&lt;br /&gt;
                IndicesLeft = 0;&lt;br /&gt;
                Clipped = TRUE;&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
                IndicesLeft -= TokenLength;&lt;br /&gt;
&lt;br /&gt;
            // Was the previous token an escape sequence?&lt;br /&gt;
            if (LastWasEscapeSequence)&lt;br /&gt;
            {&lt;br /&gt;
                // Yes, the first character is an escape character, the rest are normal.&lt;br /&gt;
&lt;br /&gt;
                // This is the extended character.&lt;br /&gt;
                Indices += [llSubStringIndex(EXTENDED_INDEX, llGetSubString(Token, 0, 0)) + 95];&lt;br /&gt;
&lt;br /&gt;
                // These are the normal characters.&lt;br /&gt;
                integer j;&lt;br /&gt;
                for (j = 1; j &amp;lt; TokenLength; j++)&lt;br /&gt;
                    Indices += [llSubStringIndex(gCharIndex, llGetSubString(Token, j, j))];&lt;br /&gt;
            }&lt;br /&gt;
            // Normal string.&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                // Just add the characters normally.&lt;br /&gt;
                integer j;&lt;br /&gt;
                for (j = 0; j &amp;lt; TokenLength; j++)&lt;br /&gt;
                    Indices += [llSubStringIndex(gCharIndex, llGetSubString(Token, j, j))];&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // Unset this flag, since this was not an escape sequence.&lt;br /&gt;
            LastWasEscapeSequence = FALSE;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Use the indices to create grid positions.&lt;br /&gt;
    vector GridPos1 = GetGridPos( llList2Integer(Indices, 0), llList2Integer(Indices, 1) );&lt;br /&gt;
    vector GridPos2 = GetGridPos( llList2Integer(Indices, 2), llList2Integer(Indices, 3) );&lt;br /&gt;
    vector GridPos3 = GetGridPos( llList2Integer(Indices, 4), llList2Integer(Indices, 5) );&lt;br /&gt;
    vector GridPos4 = GetGridPos( llList2Integer(Indices, 6), llList2Integer(Indices, 7) );&lt;br /&gt;
    vector GridPos5 = GetGridPos( llList2Integer(Indices, 8), llList2Integer(Indices, 9) );&lt;br /&gt;
&lt;br /&gt;
    // Use these grid positions to display the correct textures/offsets.&lt;br /&gt;
    ShowChars(GridPos1, GridPos2, GridPos3, GridPos4, GridPos5);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
integer ConvertIndex(integer index)&lt;br /&gt;
{&lt;br /&gt;
    // This converts from an ASCII based index to our indexing scheme.&lt;br /&gt;
    // &#039; &#039; or higher&lt;br /&gt;
    if (index &amp;gt;= 32)&lt;br /&gt;
        index -= 32;&lt;br /&gt;
    // index &amp;lt; 32&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        // Quick bounds check.&lt;br /&gt;
        if (index &amp;gt; 15)&lt;br /&gt;
            index = 15;&lt;br /&gt;
&lt;br /&gt;
        index += 94; // extended characters&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return index;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        // Initialize the character index.&lt;br /&gt;
        ResetCharIndex();&lt;br /&gt;
        ME=(integer)llGetObjectName();&lt;br /&gt;
        //llOwnerSay(&amp;quot;Channel:&amp;quot;+(string)ME);&lt;br /&gt;
        //llSay(0, &amp;quot;Free Memory: &amp;quot; + (string) llGetFreeMemory());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    link_message(integer sender, integer channel, string data, key id)&lt;br /&gt;
    {&lt;br /&gt;
        if (channel == (ME+DISPLAY_STRING))&lt;br /&gt;
        {&lt;br /&gt;
            RenderString(data);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if (channel == (ME+DISPLAY_EXTENDED))&lt;br /&gt;
        {&lt;br /&gt;
            RenderExtended(data);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if (channel == gCellChannel)&lt;br /&gt;
        {&lt;br /&gt;
            // Extract the characters we are interested in, and use those to render.&lt;br /&gt;
            string TextToRender = llGetSubString(data, gCellCharPosition, gCellCharPosition + 9);&lt;br /&gt;
            if (gCellUseFading)&lt;br /&gt;
                RenderWithEffects( TextToRender );&lt;br /&gt;
            else // !gCellUseFading&lt;br /&gt;
                RenderString( TextToRender );&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if (channel == (ME+REMAP_INDICES))&lt;br /&gt;
        {&lt;br /&gt;
            // Parse the message, splitting it up into index values.&lt;br /&gt;
            list Parsed = llCSV2List(data);&lt;br /&gt;
            integer i;&lt;br /&gt;
            // Go through the list and swap each pair of indices.&lt;br /&gt;
            for (i = 0; i &amp;lt; llGetListLength(Parsed); i += 2)&lt;br /&gt;
            {&lt;br /&gt;
                integer Index1 = ConvertIndex( llList2Integer(Parsed, i) );&lt;br /&gt;
                integer Index2 = ConvertIndex( llList2Integer(Parsed, i + 1) );&lt;br /&gt;
&lt;br /&gt;
                // Swap these index values.&lt;br /&gt;
                string Value1 = llGetSubString(gCharIndex, Index1, Index1);&lt;br /&gt;
                string Value2 = llGetSubString(gCharIndex, Index2, Index2);&lt;br /&gt;
&lt;br /&gt;
                gCharIndex = llDeleteSubString(gCharIndex, Index1, Index1);&lt;br /&gt;
                gCharIndex = llInsertString(gCharIndex, Index1, Value2);&lt;br /&gt;
&lt;br /&gt;
                gCharIndex = llDeleteSubString(gCharIndex, Index2, Index2);&lt;br /&gt;
                gCharIndex = llInsertString(gCharIndex, Index2, Value1);&lt;br /&gt;
            }&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if (channel == (ME+RESET_INDICES))&lt;br /&gt;
        {&lt;br /&gt;
            // Restore the character index back to default settings.&lt;br /&gt;
            ResetCharIndex();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if (channel == (ME+SET_CELL_INFO))&lt;br /&gt;
        {&lt;br /&gt;
            // Change the channel we listen to for cell commands, and the&lt;br /&gt;
            // starting character position to extract from.&lt;br /&gt;
            list Parsed = llCSV2List(data);&lt;br /&gt;
            gCellChannel        = (integer) llList2String(Parsed, 0);&lt;br /&gt;
            gCellCharPosition   = (integer) llList2String(Parsed, 1);&lt;br /&gt;
            gCellUseFading      = (integer) llList2String(Parsed, 2);&lt;br /&gt;
            gCellHoldDelay      = (float)   llList2String(Parsed, 3);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if (channel == (ME+SET_THICKNESS))&lt;br /&gt;
        {&lt;br /&gt;
            // Set our z scale to thickness, while staying fixed&lt;br /&gt;
            // in position relative the prim below us.&lt;br /&gt;
            vector Scale    = llGetScale();&lt;br /&gt;
            float Thickness = (float) data;&lt;br /&gt;
            // Reposition only if this isn&#039;t the root prim.&lt;br /&gt;
            integer ThisLink = llGetLinkNumber();&lt;br /&gt;
            if (ThisLink != 0 || ThisLink != 1)&lt;br /&gt;
            {&lt;br /&gt;
                // This is not the root prim.&lt;br /&gt;
                vector Up = llRot2Up(llGetLocalRot());&lt;br /&gt;
                float DistanceToMove = Thickness / 2.0 - Scale.z / 2.0;&lt;br /&gt;
                vector Pos = llGetLocalPos();&lt;br /&gt;
                llSetPos(Pos + DistanceToMove * Up);&lt;br /&gt;
            }&lt;br /&gt;
            // Apply the new thickness.&lt;br /&gt;
            Scale.z = Thickness;&lt;br /&gt;
            llSetScale(Scale);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        if (channel == (ME+SET_COLOR))&lt;br /&gt;
        {&lt;br /&gt;
            vector newColor = (vector)data;&lt;br /&gt;
            llSetColor(newColor, ALL_SIDES);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;/div&gt;</summary>
		<author><name>Phil Metalhead</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Toy_Wylie/Phoenix/Preprocessor&amp;diff=1197296</id>
		<title>User:Toy Wylie/Phoenix/Preprocessor</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Toy_Wylie/Phoenix/Preprocessor&amp;diff=1197296"/>
		<updated>2015-08-29T16:40:04Z</updated>

		<summary type="html">&lt;p&gt;Phil Metalhead: Changing code indents to actual &amp;lt;source&amp;gt; tags&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
==Phoenix LSL Preprocessor==&lt;br /&gt;
&lt;br /&gt;
===an overview by [[User:Toy Wylie|Toy Wylie]], rev. 0.8===&lt;br /&gt;
&lt;br /&gt;
===1. Overview===&lt;br /&gt;
 &lt;br /&gt;
Developing scripts in LSL can be tedious, especially if you are creating scripts that use the same things over and over again, and you keep copying pieces of your older scripts to new creations. And even within one project, you often have to copy parts of your scripts into sub-scripts (example: link message numbers as identifiers for commands). Changing any of these numbers or updating and fixing bugs in older variants of the code might result in different versions of the same functions being used or in bugs found in older versions not being fixed in newer creations. The Phoenix LSL Preprocessor is a tool to help you circumvent a lot of these problems.&lt;br /&gt;
 &lt;br /&gt;
Adding and removing debugging statements is another thing with which the Preprocessor can be helpful. Usually you have debugging functions in the script to see if all is working fine, and you take them out before release. But this in itself creates new places for mistakes as well as the opportunity for some debugging output to remain in the script on release day because it was overlooked during final screening. Using the Phoenix LSL Preprocessor gives you a very simple way of making sure that no debug output is left in your final release.&lt;br /&gt;
 &lt;br /&gt;
===2. Setup===&lt;br /&gt;
&lt;br /&gt;
To enable the Phoenix LSL Preprocessor, open your preferences panel (CTRL-P), click on &amp;quot;Phoenix&amp;quot;, &amp;quot;Page 2&amp;quot;, and then on &amp;quot;Inventory&amp;quot;. Mark the checkbox &amp;quot;Enable LSL Preprocessor Filesystem Includes&amp;quot; and click on &amp;quot;Set&amp;quot;. This will open a file requester, prompting you to point at a directory on your local computer. This is the place where you store all your LSL include files. Next, open any LSL script, click on &amp;quot;Advanced&amp;quot;, and select &amp;quot;Enable Preprocessor&amp;quot;. Then close the script.&lt;br /&gt;
 &lt;br /&gt;
===3. How it Works===&lt;br /&gt;
 &lt;br /&gt;
After setting up, you will see two tabs in your LSL editor: &amp;quot;Script&amp;quot; and &amp;quot;Preprocessed&amp;quot; (&amp;quot;Postprocessed&amp;quot; in older versions). The first is your active scripting window; the second shows the output of the Preprocessor, essentially the content that gets stored in the script. The postprocessed script contains the entire source code of what you have written in a comment block at the beginning, and the postprocessed output following this comment block. This ensures backwards compatibility with older versions of Phoenix and regular viewers that do not support preprocessing at all.&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; Since the LSL/Mono compiler gets the script after preprocessing, the line numbers in error messages refer to the postprocessed script. So if you are getting compiler errors, be sure to look for the error in the &amp;quot;Postprocessed&amp;quot; tab rather than in your original script.&lt;br /&gt;
&lt;br /&gt;
===4. A Short Example===&lt;br /&gt;
 &lt;br /&gt;
Create a file in your include folder with the name &amp;lt;tt&amp;gt;debug.lsl&amp;lt;/tt&amp;gt;. Copy the following snippet into this file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
#ifdef DEBUG&lt;br /&gt;
debug(string text)&lt;br /&gt;
{&lt;br /&gt;
    llOwnerSay(text);&lt;br /&gt;
}&lt;br /&gt;
#else&lt;br /&gt;
#define debug(dummy)&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now create a new LSL script and copy the following code into the script editor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
#define DEBUG&lt;br /&gt;
#include &amp;quot;debug.lsl&amp;quot;&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
   state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        debug(&amp;quot;Debugging with the Phoenix LSL Preprocessor.&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save the script. You will see the &amp;quot;Debugging with the Phoenix LSL Preprocessor&amp;quot; message in your chat console. Now change the first line of the LSL script to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
#undef DEBUG&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save the script again. You will see that the debugging message is gone. This is a very handy way to enable and disable all debugging code in one single line. To understand what really happens, have a look at the &amp;quot;Postprocessed&amp;quot; tab. You can clearly see how the debug line will simply disappear, a lonely &amp;quot;;&amp;quot; the only trace of it having been there.&lt;br /&gt;
&lt;br /&gt;
===5. The Optimizer===&lt;br /&gt;
&lt;br /&gt;
Including files has one disadvantage though. You will get the complete contents of the file, if you need it or not. But the Phoenix LSL Preprocessor uses an optimizing technique, which only keeps the things you really used in your code and removes all global functions and variables you didn&#039;t reference in your script. This makes sure that your scripts don&#039;t get burdened with a lot of unused code. You can enable or disable this functionality in the script editor&#039;s &amp;quot;Advanced&amp;quot; menu.&lt;br /&gt;
 &lt;br /&gt;
===6. &amp;lt;tt&amp;gt;switch/case&amp;lt;/tt&amp;gt; addition===&lt;br /&gt;
&lt;br /&gt;
The Preprocessor also adds a set of new commands to the LSL editor which has been sorely missing until now: the &amp;lt;tt&amp;gt;switch/case&amp;lt;/tt&amp;gt; construct known from many other languages. You can enable support for this construct in the script editor&#039;s &amp;quot;Advanced&amp;quot; menu. &amp;lt;tt&amp;gt;switch/case&amp;lt;/tt&amp;gt; is a handy replacement for &amp;lt;tt&amp;gt;if(...) else if()&amp;lt;/tt&amp;gt; chains. Additionally, switch/case supports &amp;quot;fallthrough&amp;quot; from one case to another, so you can chain up several cases with different conditions. A &amp;lt;tt&amp;gt;break&amp;lt;/tt&amp;gt; statement is used to prevent fallthrough. The &amp;lt;tt&amp;gt;default&amp;lt;/tt&amp;gt; case is used if none of the cases match the &amp;lt;tt&amp;gt;switch()&amp;lt;/tt&amp;gt; condition.&lt;br /&gt;
 &lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        integer i;&lt;br /&gt;
        switch(i)&lt;br /&gt;
        {&lt;br /&gt;
            case 1:&lt;br /&gt;
            {&lt;br /&gt;
                llOwnerSay(&amp;quot;1&amp;quot;);&lt;br /&gt;
                // fallthrough to case 2&lt;br /&gt;
            }&lt;br /&gt;
            case 2:&lt;br /&gt;
            {&lt;br /&gt;
                llOwnerSay(&amp;quot;1 or 2&amp;quot;);&lt;br /&gt;
                // no fallthrough&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            case 3:&lt;br /&gt;
            {&lt;br /&gt;
                llOwnerSay(&amp;quot;3&amp;quot;);&lt;br /&gt;
                // fallthrough to default&lt;br /&gt;
            }&lt;br /&gt;
            default:&lt;br /&gt;
            {&lt;br /&gt;
                llOwnerSay(&amp;quot;3 or default&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===7. Lazy Lists addition===&lt;br /&gt;
&lt;br /&gt;
Assigning values to list indexes is always a cumbersome thing to do in LSL (&amp;lt;tt&amp;gt;llListReplaceList()&amp;lt;/tt&amp;gt; needed). Lazy Lists can help you a little by providing a way to just say:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
myList[index] = value;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sadly it is not really possible to get list elements the same way because the return data can be of different types.&lt;br /&gt;
 &lt;br /&gt;
===8. Preprocessor Commands and Macros===&lt;br /&gt;
 &lt;br /&gt;
The Preprocessor understands the following commands:&lt;br /&gt;
&lt;br /&gt;
 #define&lt;br /&gt;
 #undef&lt;br /&gt;
 #ifdef&lt;br /&gt;
 #ifndef&lt;br /&gt;
 #if&lt;br /&gt;
 #elif&lt;br /&gt;
 #else&lt;br /&gt;
 #endif&lt;br /&gt;
 #warning&lt;br /&gt;
 #error&lt;br /&gt;
 #include&lt;br /&gt;
&lt;br /&gt;
There are a few more, but these are not really useful within LSL.&lt;br /&gt;
&lt;br /&gt;
Additionally, you can use the following macros in your scripts to help with debugging and giving you other useful information:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;__FILE__&amp;lt;/tt&amp;gt; - the full path to the script as it would appear in the include cache. The top script only uses its name.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__LINE__&amp;lt;/tt&amp;gt; - the line of the current script where it is expanded; this starts at line 0&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__SHORTFILE__&amp;lt;/tt&amp;gt; - the name of the current script without full file path&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__AGENTID__&amp;lt;/tt&amp;gt; - a string-encapsulated version of the agent&#039;s key who compiles the script&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__AGENTKEY__&amp;lt;/tt&amp;gt; - same as above, legacy version&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__AGENTIDRAW__&amp;lt;/tt&amp;gt; - a nonstring-encapsulated version of the agent&#039;s key who compiles the script&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__AGENTNAME__&amp;lt;/tt&amp;gt; - a string-encapsulated version of the agent&#039;s full name who compiles the script&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__ASSETID__&amp;lt;/tt&amp;gt; - a string-encapsulated version of the assetid of the current script; may return &amp;quot;NOT IN WORLD&amp;quot; or a nonstring-encapsulated null key in rare circumstances &lt;br /&gt;
&lt;br /&gt;
Thanks to Zwagoth Klaar for this list.&lt;br /&gt;
&lt;br /&gt;
===8.1 &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt;===&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt; creates a case-sensitive macro which will be replaced while saving and compiling a script. This can be applied as simple constant numbers, strings, and even functions. What happens is a literal text replacement in the source code. Because of this, be careful with &amp;quot;;&amp;quot; inside your macros. These usually don&#039;t cause any harm; but within a one-line conditional, things can break in unexpected ways if it creates a &amp;quot;;;&amp;quot; in the end of a line, for example.&lt;br /&gt;
 &lt;br /&gt;
The following examples will give you an overview of what &amp;lt;/tt&amp;gt;#define&amp;lt;/tt&amp;gt; does. Have a look at the &amp;quot;Postprocessed&amp;quot; tab to see what the Preprocessor creates from the source.&lt;br /&gt;
 &lt;br /&gt;
Example 1:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
#define CHANNEL 12345&lt;br /&gt;
llOwnerSay((string) CHANNEL); // CHANNEL will be replaced with the literal 12345 stated in the #define above&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt; can also take parameters to apply to the replacement code:&lt;br /&gt;
 &lt;br /&gt;
Example 2:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
#define OS(b,c) llOwnerSay(b+c)&lt;br /&gt;
OS(&amp;quot;Test&amp;quot;,&amp;quot;123&amp;quot;); // will expand to: llOwnerSay(&amp;quot;Test&amp;quot;+&amp;quot;123&amp;quot;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example 3: Making strings out of parameters&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
#define OS(a) llOwnerSay(#a)&lt;br /&gt;
OS(1234); // will expand to: llOwnerSay(&amp;quot;1234&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example 4: Using &amp;lt;tt&amp;gt;&amp;quot;&amp;quot;##&amp;quot;&amp;quot;&amp;lt;/tt&amp;gt; to concatenate parameters&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
#define OS(a,b) llOwnerSay((string) a##b)&lt;br /&gt;
OS(1234,5678); // will expand to: llOwnerSay((string) 12345678);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===8.2 &amp;lt;tt&amp;gt;#undef&amp;lt;/tt&amp;gt;===&lt;br /&gt;
 &lt;br /&gt;
Removes a macro previously set up with &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt;. If the macro was not made in the first place, nothing happens. This is a useful way to enable or disable parts of the source code for debugging. See Section 4 above for an example on how to use it.&lt;br /&gt;
&lt;br /&gt;
===8.3 &amp;lt;tt&amp;gt;#ifdef&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#ifndef&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;#else&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#endif&amp;lt;/tt&amp;gt;===&lt;br /&gt;
 &lt;br /&gt;
This command is a part of conditional preprocessing in association with &amp;lt;tt&amp;gt;#else&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#endif&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;#ifdef&amp;lt;/tt&amp;gt; checks if a macro has been previously &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt;d. It doesn&#039;t matter if the macro has actually a value assigned to it. It just needs to be &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt;d. If it has, all of the code after &amp;lt;tt&amp;gt;#ifdef&amp;lt;/tt&amp;gt; up to &amp;lt;tt&amp;gt;#endif&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;#else&amp;lt;/tt&amp;gt; gets replaced into the postprocessed code. &amp;lt;tt&amp;gt;#ifndef&amp;lt;/tt&amp;gt; does the exact opposite. If a macro does not exist, the code goes into the Preprocessor.&lt;br /&gt;
 &lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
#define OWNER_ONLY&lt;br /&gt;
...&lt;br /&gt;
#ifdef OWNER_ONLY&lt;br /&gt;
key var=llGetOwner();&lt;br /&gt;
#else&lt;br /&gt;
key var=llDetectedKey(0);&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===8.4 &amp;lt;tt&amp;gt;#if&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#elif&amp;lt;/tt&amp;gt;===&lt;br /&gt;
 &lt;br /&gt;
These are also conditional preprocessing commands. They take a general condition and pass on the code to the Preprocessor if the condition evaluates to &amp;lt;tt&amp;gt;TRUE&amp;lt;/tt&amp;gt;. They can also be used in conjunction with &amp;lt;tt&amp;gt;#else&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;#elif&amp;lt;/tt&amp;gt; is the equivalent to &amp;lt;tt&amp;gt;else if&amp;lt;/tt&amp;gt;.&lt;br /&gt;
 &lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
#define DEBUGLEVEL 2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
#if DEBUGLEVEL==1&lt;br /&gt;
llOwnerSay(&amp;quot;Point reached&amp;quot;);&lt;br /&gt;
#elif DEBUGLEVEL==2&lt;br /&gt;
llOwnerSay(&amp;quot;Lots of more data here&amp;quot;);&lt;br /&gt;
#else&lt;br /&gt;
llOwnerSay(&amp;quot;Unknown debug level: &amp;quot;+(string) DEBUGLEVEL);&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===8.5 &amp;lt;tt&amp;gt;#warning&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#error&amp;lt;/tt&amp;gt;===&lt;br /&gt;
 &lt;br /&gt;
These two commands show a string in the compiler window to warn you about certain problems or to halt compilation immediately due to a fatal error. Right now, both &amp;lt;tt&amp;gt;#warning&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#error&amp;lt;/tt&amp;gt; cause the compiler to stop. It is unclear yet if &amp;lt;tt&amp;gt;#warning&amp;lt;/tt&amp;gt; will allow the compiler to continue to completion in the future.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; If one of these commands is hit by the Preprocessor, the script is &#039;&#039;&#039;NOT&#039;&#039;&#039; saved!&lt;br /&gt;
&lt;br /&gt;
Example 1:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
#warning This include file is obsolete!&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example 2:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
#error This include file does not work anymore. Please update.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===8.6 &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
This is probably the most powerful feature of the Phoenix LSL Preprocessor. It includes whole source code files from your harddisk or from the same folder tree in your inventory into the script you are working on. A small example of this feature can be seen above in Section 4. &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; takes a file name relative to the include path set up in your Preferences. You can also include files inside of subfolders. If you are compiling your script from your inventory, the Preprocessor will search the inventory path you are working in, descending into any subfolders, to find the referenced include file. Unused functions and global variable declarations are removed by the Optimizer.&lt;br /&gt;
 &lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;quot;command_ids.lsl&amp;quot;&lt;br /&gt;
#include &amp;quot;general_functions.lsl&amp;quot;&lt;br /&gt;
#include &amp;quot;hud/layout.lsl&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; Be careful about including files from within &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt;s. You might &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; a file twice, if you are not really keeping track, and this will lead to problems. This issue is usually addressed by using so-called &amp;quot;Include guards&amp;quot;. You basically have a conditional compile that sets a &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt; macro and checks if it&#039;s already there. If it&#039;s not, &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; the contents of the file. If it was set, ignore the contents.&lt;br /&gt;
 &lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
#ifndef SCRIPT_NAME_LSL&lt;br /&gt;
#define SCRIPT_NAME_LSL&lt;br /&gt;
your_script_starts_here()&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
#endif //SCRIPT_NAME_LSL&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These &amp;lt;tt&amp;gt;#ifndef&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#endif&amp;lt;/tt&amp;gt; commands make sure that the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; happens only once regardless of how often the file is actually referenced with &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt;.&lt;br /&gt;
 &lt;br /&gt;
===9. Known Issues===&lt;br /&gt;
&lt;br /&gt;
* Including a file from your hard drive containing a &amp;lt;tt&amp;gt;#endif&amp;lt;/tt&amp;gt; as last line (without linebreak) will not produce a warning about not having a line break but rather a statement error&lt;br /&gt;
* This can be fixed by adding a line break to the end of the file&lt;br /&gt;
* &amp;quot;Enable Text Compress&amp;quot; &#039;&#039;&#039;will break your script!&#039;&#039;&#039; (At least in its current form. It may be fixed, or removed, in the future.)&lt;/div&gt;</summary>
		<author><name>Phil Metalhead</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Toy_Wylie/Phoenix/Preprocessor&amp;diff=1197232</id>
		<title>User:Toy Wylie/Phoenix/Preprocessor</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Toy_Wylie/Phoenix/Preprocessor&amp;diff=1197232"/>
		<updated>2015-08-16T16:08:51Z</updated>

		<summary type="html">&lt;p&gt;Phil Metalhead: Fixing the rest of the broken &amp;lt;lsl&amp;gt; tags&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
==Phoenix LSL Preprocessor==&lt;br /&gt;
&lt;br /&gt;
===an overview by [[User:Toy Wylie|Toy Wylie]], rev. 0.8===&lt;br /&gt;
&lt;br /&gt;
===1. Overview===&lt;br /&gt;
 &lt;br /&gt;
Developing scripts in LSL can be tedious, especially if you are creating scripts that use the same things over and over again, and you keep copying pieces of your older scripts to new creations. And even within one project, you often have to copy parts of your scripts into sub-scripts (example: link message numbers as identifiers for commands). Changing any of these numbers or updating and fixing bugs in older variants of the code might result in different versions of the same functions being used or in bugs found in older versions not being fixed in newer creations. The Phoenix LSL Preprocessor is a tool to help you circumvent a lot of these problems.&lt;br /&gt;
 &lt;br /&gt;
Adding and removing debugging statements is another thing with which the Preprocessor can be helpful. Usually you have debugging functions in the script to see if all is working fine, and you take them out before release. But this in itself creates new places for mistakes as well as the opportunity for some debugging output to remain in the script on release day because it was overlooked during final screening. Using the Phoenix LSL Preprocessor gives you a very simple way of making sure that no debug output is left in your final release.&lt;br /&gt;
 &lt;br /&gt;
===2. Setup===&lt;br /&gt;
&lt;br /&gt;
To enable the Phoenix LSL Preprocessor, open your preferences panel (CTRL-P), click on &amp;quot;Phoenix&amp;quot;, &amp;quot;Page 2&amp;quot;, and then on &amp;quot;Inventory&amp;quot;. Mark the checkbox &amp;quot;Enable LSL Preprocessor Filesystem Includes&amp;quot; and click on &amp;quot;Set&amp;quot;. This will open a file requester, prompting you to point at a directory on your local computer. This is the place where you store all your LSL include files. Next, open any LSL script, click on &amp;quot;Advanced&amp;quot;, and select &amp;quot;Enable Preprocessor&amp;quot;. Then close the script.&lt;br /&gt;
 &lt;br /&gt;
===3. How it Works===&lt;br /&gt;
 &lt;br /&gt;
After setting up, you will see two tabs in your LSL editor: &amp;quot;Script&amp;quot; and &amp;quot;Preprocessed&amp;quot; (&amp;quot;Postprocessed&amp;quot; in older versions). The first is your active scripting window; the second shows the output of the Preprocessor, essentially the content that gets stored in the script. The postprocessed script contains the entire source code of what you have written in a comment block at the beginning, and the postprocessed output following this comment block. This ensures backwards compatibility with older versions of Phoenix and regular viewers that do not support preprocessing at all.&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; Since the LSL/Mono compiler gets the script after preprocessing, the line numbers in error messages refer to the postprocessed script. So if you are getting compiler errors, be sure to look for the error in the &amp;quot;Postprocessed&amp;quot; tab rather than in your original script.&lt;br /&gt;
&lt;br /&gt;
===4. A Short Example===&lt;br /&gt;
 &lt;br /&gt;
Create a file in your include folder with the name &amp;lt;tt&amp;gt;debug.lsl&amp;lt;/tt&amp;gt;. Copy the following snippet into this file:&lt;br /&gt;
&lt;br /&gt;
 #ifdef DEBUG&lt;br /&gt;
 debug(string text)&lt;br /&gt;
 {&lt;br /&gt;
     llOwnerSay(text);&lt;br /&gt;
 }&lt;br /&gt;
 #else&lt;br /&gt;
 #define debug(dummy)&lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
Now create a new LSL script and copy the following code into the script editor:&lt;br /&gt;
&lt;br /&gt;
 #define DEBUG&lt;br /&gt;
 #include &amp;quot;debug.lsl&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 default&lt;br /&gt;
 {&lt;br /&gt;
     state_entry()&lt;br /&gt;
     {&lt;br /&gt;
         debug(&amp;quot;Debugging with the Phoenix LSL Preprocessor.&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Save the script. You will see the &amp;quot;Debugging with the Phoenix LSL Preprocessor&amp;quot; message in your chat console. Now change the first line of the LSL script to:&lt;br /&gt;
&lt;br /&gt;
 #undef DEBUG&lt;br /&gt;
&lt;br /&gt;
Save the script again. You will see that the debugging message is gone. This is a very handy way to enable and disable all debugging code in one single line. To understand what really happens, have a look at the &amp;quot;Postprocessed&amp;quot; tab. You can clearly see how the debug line will simply disappear, a lonely &amp;quot;;&amp;quot; the only trace of it having been there.&lt;br /&gt;
&lt;br /&gt;
===5. The Optimizer===&lt;br /&gt;
&lt;br /&gt;
Including files has one disadvantage though. You will get the complete contents of the file, if you need it or not. But the Phoenix LSL Preprocessor uses an optimizing technique, which only keeps the things you really used in your code and removes all global functions and variables you didn&#039;t reference in your script. This makes sure that your scripts don&#039;t get burdened with a lot of unused code. You can enable or disable this functionality in the script editor&#039;s &amp;quot;Advanced&amp;quot; menu.&lt;br /&gt;
 &lt;br /&gt;
===6. &amp;lt;tt&amp;gt;switch/case&amp;lt;/tt&amp;gt; addition===&lt;br /&gt;
&lt;br /&gt;
The Preprocessor also adds a set of new commands to the LSL editor which has been sorely missing until now: the &amp;lt;tt&amp;gt;switch/case&amp;lt;/tt&amp;gt; construct known from many other languages. You can enable support for this construct in the script editor&#039;s &amp;quot;Advanced&amp;quot; menu. &amp;lt;tt&amp;gt;switch/case&amp;lt;/tt&amp;gt; is a handy replacement for &amp;lt;tt&amp;gt;if(...) else if()&amp;lt;/tt&amp;gt; chains. Additionally, switch/case supports &amp;quot;fallthrough&amp;quot; from one case to another, so you can chain up several cases with different conditions. A &amp;lt;tt&amp;gt;break&amp;lt;/tt&amp;gt; statement is used to prevent fallthrough. The &amp;lt;tt&amp;gt;default&amp;lt;/tt&amp;gt; case is used if none of the cases match the &amp;lt;tt&amp;gt;switch()&amp;lt;/tt&amp;gt; condition.&lt;br /&gt;
 &lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 default&lt;br /&gt;
 {&lt;br /&gt;
     state_entry()&lt;br /&gt;
     {&lt;br /&gt;
         integer i;&lt;br /&gt;
         switch(i)&lt;br /&gt;
         {&lt;br /&gt;
             case 1:&lt;br /&gt;
             {&lt;br /&gt;
                 llOwnerSay(&amp;quot;1&amp;quot;);&lt;br /&gt;
                 // fallthrough to case 2&lt;br /&gt;
             }&lt;br /&gt;
             case 2:&lt;br /&gt;
             {&lt;br /&gt;
                 llOwnerSay(&amp;quot;1 or 2&amp;quot;);&lt;br /&gt;
                 // no fallthrough&lt;br /&gt;
                 break;&lt;br /&gt;
             }&lt;br /&gt;
             case 3:&lt;br /&gt;
             {&lt;br /&gt;
                 llOwnerSay(&amp;quot;3&amp;quot;);&lt;br /&gt;
                 // fallthrough to default&lt;br /&gt;
             }&lt;br /&gt;
             default:&lt;br /&gt;
             {&lt;br /&gt;
                 llOwnerSay(&amp;quot;3 or default&amp;quot;);&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===7. Lazy Lists addition===&lt;br /&gt;
&lt;br /&gt;
Assigning values to list indexes is always a cumbersome thing to do in LSL (&amp;lt;tt&amp;gt;llListReplaceList()&amp;lt;/tt&amp;gt; needed). Lazy Lists can help you a little by providing a way to just say:&lt;br /&gt;
&lt;br /&gt;
 myList[index]=value;&lt;br /&gt;
&lt;br /&gt;
Sadly it is not really possible to get list elements the same way because the return data can be of different types.&lt;br /&gt;
 &lt;br /&gt;
===8. Preprocessor Commands and Macros===&lt;br /&gt;
 &lt;br /&gt;
The Preprocessor understands the following commands:&lt;br /&gt;
&lt;br /&gt;
 #define&lt;br /&gt;
 #undef&lt;br /&gt;
 #ifdef&lt;br /&gt;
 #ifndef&lt;br /&gt;
 #if&lt;br /&gt;
 #elif&lt;br /&gt;
 #else&lt;br /&gt;
 #endif&lt;br /&gt;
 #warning&lt;br /&gt;
 #error&lt;br /&gt;
 #include&lt;br /&gt;
&lt;br /&gt;
There are a few more, but these are not really useful within LSL.&lt;br /&gt;
&lt;br /&gt;
Additionally, you can use the following macros in your scripts to help with debugging and giving you other useful information:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;__FILE__&amp;lt;/tt&amp;gt; - the full path to the script as it would appear in the include cache. The top script only uses its name.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__LINE__&amp;lt;/tt&amp;gt; - the line of the current script where it is expanded; this starts at line 0&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__SHORTFILE__&amp;lt;/tt&amp;gt; - the name of the current script without full file path&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__AGENTID__&amp;lt;/tt&amp;gt; - a string-encapsulated version of the agent&#039;s key who compiles the script&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__AGENTKEY__&amp;lt;/tt&amp;gt; - same as above, legacy version&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__AGENTIDRAW__&amp;lt;/tt&amp;gt; - a nonstring-encapsulated version of the agent&#039;s key who compiles the script&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__AGENTNAME__&amp;lt;/tt&amp;gt; - a string-encapsulated version of the agent&#039;s full name who compiles the script&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__ASSETID__&amp;lt;/tt&amp;gt; - a string-encapsulated version of the assetid of the current script; may return &amp;quot;NOT IN WORLD&amp;quot; or a nonstring-encapsulated null key in rare circumstances &lt;br /&gt;
&lt;br /&gt;
Thanks to Zwagoth Klaar for this list.&lt;br /&gt;
&lt;br /&gt;
===8.1 &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt;===&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt; creates a case-sensitive macro which will be replaced while saving and compiling a script. This can be applied as simple constant numbers, strings, and even functions. What happens is a literal text replacement in the source code. Because of this, be careful with &amp;quot;;&amp;quot; inside your macros. These usually don&#039;t cause any harm; but within a one-line conditional, things can break in unexpected ways if it creates a &amp;quot;;;&amp;quot; in the end of a line, for example.&lt;br /&gt;
 &lt;br /&gt;
The following examples will give you an overview of what &amp;lt;/tt&amp;gt;#define&amp;lt;/tt&amp;gt; does. Have a look at the &amp;quot;Postprocessed&amp;quot; tab to see what the Preprocessor creates from the source.&lt;br /&gt;
 &lt;br /&gt;
Example 1:&lt;br /&gt;
&lt;br /&gt;
 #define CHANNEL 12345&lt;br /&gt;
 llOwnerSay((string) CHANNEL); // CHANNEL will be replaced with the literal 12345 stated in the #define above&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt; can also take parameters to apply to the replacement code:&lt;br /&gt;
 &lt;br /&gt;
Example 2:&lt;br /&gt;
&lt;br /&gt;
 #define OS(b,c) llOwnerSay(b+c)&lt;br /&gt;
 OS(&amp;quot;Test&amp;quot;,&amp;quot;123&amp;quot;); // will expand to: llOwnerSay(&amp;quot;Test&amp;quot;+&amp;quot;123&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Example 3: Making strings out of parameters&lt;br /&gt;
&lt;br /&gt;
 #define OS(a) llOwnerSay(#a)&lt;br /&gt;
 OS(1234); // will expand to: llOwnerSay(&amp;quot;1234&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Example 4: Using &amp;lt;tt&amp;gt;&amp;quot;&amp;quot;##&amp;quot;&amp;quot;&amp;lt;/tt&amp;gt; to concatenate parameters&lt;br /&gt;
&lt;br /&gt;
 #define OS(a,b) llOwnerSay((string) a##b)&lt;br /&gt;
 OS(1234,5678); // will expand to: llOwnerSay((string) 12345678);&lt;br /&gt;
&lt;br /&gt;
===8.2 &amp;lt;tt&amp;gt;#undef&amp;lt;/tt&amp;gt;===&lt;br /&gt;
 &lt;br /&gt;
Removes a macro previously set up with &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt;. If the macro was not made in the first place, nothing happens. This is a useful way to enable or disable parts of the source code for debugging. See Section 4 above for an example on how to use it.&lt;br /&gt;
&lt;br /&gt;
===8.3 &amp;lt;tt&amp;gt;#ifdef&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#ifndef&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;#else&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#endif&amp;lt;/tt&amp;gt;===&lt;br /&gt;
 &lt;br /&gt;
This command is a part of conditional preprocessing in association with &amp;lt;tt&amp;gt;#else&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#endif&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;#ifdef&amp;lt;/tt&amp;gt; checks if a macro has been previously &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt;d. It doesn&#039;t matter if the macro has actually a value assigned to it. It just needs to be &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt;d. If it has, all of the code after &amp;lt;tt&amp;gt;#ifdef&amp;lt;/tt&amp;gt; up to &amp;lt;tt&amp;gt;#endif&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;#else&amp;lt;/tt&amp;gt; gets replaced into the postprocessed code. &amp;lt;tt&amp;gt;#ifndef&amp;lt;/tt&amp;gt; does the exact opposite. If a macro does not exist, the code goes into the Preprocessor.&lt;br /&gt;
 &lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 #define OWNER_ONLY&lt;br /&gt;
 ...&lt;br /&gt;
 #ifdef OWNER_ONLY&lt;br /&gt;
 key var=llGetOwner();&lt;br /&gt;
 #else&lt;br /&gt;
 key var=llDetectedKey(0);&lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
===8.4 &amp;lt;tt&amp;gt;#if&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#elif&amp;lt;/tt&amp;gt;===&lt;br /&gt;
 &lt;br /&gt;
These are also conditional preprocessing commands. They take a general condition and pass on the code to the Preprocessor if the condition evaluates to &amp;lt;tt&amp;gt;TRUE&amp;lt;/tt&amp;gt;. They can also be used in conjunction with &amp;lt;tt&amp;gt;#else&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;#elif&amp;lt;/tt&amp;gt; is the equivalent to &amp;lt;tt&amp;gt;else if&amp;lt;/tt&amp;gt;.&lt;br /&gt;
 &lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 #define DEBUGLEVEL 2&lt;br /&gt;
 &lt;br /&gt;
 #if DEBUGLEVEL==1&lt;br /&gt;
 llOwnerSay(&amp;quot;Point reached&amp;quot;);&lt;br /&gt;
 #elif DEBUGLEVEL==2&lt;br /&gt;
 llOwnerSay(&amp;quot;Lots of more data here&amp;quot;);&lt;br /&gt;
 #else&lt;br /&gt;
 llOwnerSay(&amp;quot;Unknown debug level: &amp;quot;+(string) DEBUGLEVEL);&lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
===8.5 &amp;lt;tt&amp;gt;#warning&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#error&amp;lt;/tt&amp;gt;===&lt;br /&gt;
 &lt;br /&gt;
These two commands show a string in the compiler window to warn you about certain problems or to halt compilation immediately due to a fatal error. Right now, both &amp;lt;tt&amp;gt;#warning&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#error&amp;lt;/tt&amp;gt; cause the compiler to stop. It is unclear yet if &amp;lt;tt&amp;gt;#warning&amp;lt;/tt&amp;gt; will allow the compiler to continue to completion in the future.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; If one of these commands is hit by the Preprocessor, the script is &#039;&#039;&#039;NOT&#039;&#039;&#039; saved!&lt;br /&gt;
&lt;br /&gt;
Example 1:&lt;br /&gt;
&lt;br /&gt;
 #warning This include file is obsolete!&lt;br /&gt;
&lt;br /&gt;
Example 2:&lt;br /&gt;
&lt;br /&gt;
 #error This include file does not work anymore. Please update.&lt;br /&gt;
&lt;br /&gt;
===8.6 &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
This is probably the most powerful feature of the Phoenix LSL Preprocessor. It includes whole source code files from your harddisk or from the same folder tree in your inventory into the script you are working on. A small example of this feature can be seen above in Section 4. &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; takes a file name relative to the include path set up in your Preferences. You can also include files inside of subfolders. If you are compiling your script from your inventory, the Preprocessor will search the inventory path you are working in, descending into any subfolders, to find the referenced include file. Unused functions and global variable declarations are removed by the Optimizer.&lt;br /&gt;
 &lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;command_ids.lsl&amp;quot;&lt;br /&gt;
 #include &amp;quot;general_functions.lsl&amp;quot;&lt;br /&gt;
 #include &amp;quot;hud/layout.lsl&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; Be careful about including files from within &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt;s. You might &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; a file twice, if you are not really keeping track, and this will lead to problems. This issue is usually addressed by using so-called &amp;quot;Include guards&amp;quot;. You basically have a conditional compile that sets a &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt; macro and checks if it&#039;s already there. If it&#039;s not, &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; the contents of the file. If it was set, ignore the contents.&lt;br /&gt;
 &lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 #ifndef SCRIPT_NAME_LSL&lt;br /&gt;
 #define SCRIPT_NAME_LSL&lt;br /&gt;
 your_script_starts_here()&lt;br /&gt;
 {&lt;br /&gt;
 }&lt;br /&gt;
 #endif //SCRIPT_NAME_LSL&lt;br /&gt;
&lt;br /&gt;
These &amp;lt;tt&amp;gt;#ifndef&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#endif&amp;lt;/tt&amp;gt; commands make sure that the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; happens only once regardless of how often the file is actually referenced with &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt;.&lt;br /&gt;
 &lt;br /&gt;
===9. Known Issues===&lt;br /&gt;
&lt;br /&gt;
* Including a file from your hard drive containing a &amp;lt;tt&amp;gt;#endif&amp;lt;/tt&amp;gt; as last line (without linebreak) will not produce a warning about not having a line break but rather a statement error&lt;br /&gt;
* This can be fixed by adding a line break to the end of the file&lt;br /&gt;
* &amp;quot;Enable Text Compress&amp;quot; &#039;&#039;&#039;will break your script!&#039;&#039;&#039; (At least in its current form. It may be fixed, or removed, in the future.)&lt;/div&gt;</summary>
		<author><name>Phil Metalhead</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Toy_Wylie/Phoenix/Preprocessor&amp;diff=1197231</id>
		<title>User:Toy Wylie/Phoenix/Preprocessor</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Toy_Wylie/Phoenix/Preprocessor&amp;diff=1197231"/>
		<updated>2015-08-16T15:57:20Z</updated>

		<summary type="html">&lt;p&gt;Phil Metalhead: Fixing broken &amp;lt;lsl&amp;gt; tags :(&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
==Phoenix LSL Preprocessor==&lt;br /&gt;
&lt;br /&gt;
===an overview by [[User:Toy Wylie|Toy Wylie]], rev. 0.8===&lt;br /&gt;
&lt;br /&gt;
===1. Overview===&lt;br /&gt;
 &lt;br /&gt;
Developing scripts in LSL can be tedious, especially if you are creating scripts that use the same things over and over again, and you keep copying pieces of your older scripts to new creations. And even within one project, you often have to copy parts of your scripts into sub-scripts (example: link message numbers as identifiers for commands). Changing any of these numbers or updating and fixing bugs in older variants of the code might result in different versions of the same functions being used or in bugs found in older versions not being fixed in newer creations. The Phoenix LSL Preprocessor is a tool to help you circumvent a lot of these problems.&lt;br /&gt;
 &lt;br /&gt;
Adding and removing debugging statements is another thing with which the Preprocessor can be helpful. Usually you have debugging functions in the script to see if all is working fine, and you take them out before release. But this in itself creates new places for mistakes as well as the opportunity for some debugging output to remain in the script on release day because it was overlooked during final screening. Using the Phoenix LSL Preprocessor gives you a very simple way of making sure that no debug output is left in your final release.&lt;br /&gt;
 &lt;br /&gt;
===2. Setup===&lt;br /&gt;
&lt;br /&gt;
To enable the Phoenix LSL Preprocessor, open your preferences panel (CTRL-P), click on &amp;quot;Phoenix&amp;quot;, &amp;quot;Page 2&amp;quot;, and then on &amp;quot;Inventory&amp;quot;. Mark the checkbox &amp;quot;Enable LSL Preprocessor Filesystem Includes&amp;quot; and click on &amp;quot;Set&amp;quot;. This will open a file requester, prompting you to point at a directory on your local computer. This is the place where you store all your LSL include files. Next, open any LSL script, click on &amp;quot;Advanced&amp;quot;, and select &amp;quot;Enable Preprocessor&amp;quot;. Then close the script.&lt;br /&gt;
 &lt;br /&gt;
===3. How it Works===&lt;br /&gt;
 &lt;br /&gt;
After setting up, you will see two tabs in your LSL editor: &amp;quot;Script&amp;quot; and &amp;quot;Preprocessed&amp;quot; (&amp;quot;Postprocessed&amp;quot; in older versions). The first is your active scripting window; the second shows the output of the Preprocessor, essentially the content that gets stored in the script. The postprocessed script contains the entire source code of what you have written in a comment block at the beginning, and the postprocessed output following this comment block. This ensures backwards compatibility with older versions of Phoenix and regular viewers that do not support preprocessing at all.&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; Since the LSL/Mono compiler gets the script after preprocessing, the line numbers in error messages refer to the postprocessed script. So if you are getting compiler errors, be sure to look for the error in the &amp;quot;Postprocessed&amp;quot; tab rather than in your original script.&lt;br /&gt;
&lt;br /&gt;
===4. A Short Example===&lt;br /&gt;
 &lt;br /&gt;
Create a file in your include folder with the name &amp;lt;tt&amp;gt;debug.lsl&amp;lt;/tt&amp;gt;. Copy the following snippet into this file:&lt;br /&gt;
&lt;br /&gt;
 #ifdef DEBUG&lt;br /&gt;
 debug(string text)&lt;br /&gt;
 {&lt;br /&gt;
     llOwnerSay(text);&lt;br /&gt;
 }&lt;br /&gt;
 #else&lt;br /&gt;
 #define debug(dummy)&lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
Now create a new LSL script and copy the following code into the script editor:&lt;br /&gt;
&lt;br /&gt;
 #define DEBUG&lt;br /&gt;
 #include &amp;quot;debug.lsl&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 default&lt;br /&gt;
 {&lt;br /&gt;
     state_entry()&lt;br /&gt;
     {&lt;br /&gt;
         debug(&amp;quot;Debugging with the Phoenix LSL Preprocessor.&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Save the script. You will see the &amp;quot;Debugging with the Phoenix LSL Preprocessor&amp;quot; message in your chat console. Now change the first line of the LSL script to:&lt;br /&gt;
&lt;br /&gt;
 #undef DEBUG&lt;br /&gt;
&lt;br /&gt;
Save the script again. You will see that the debugging message is gone. This is a very handy way to enable and disable all debugging code in one single line. To understand what really happens, have a look at the &amp;quot;Postprocessed&amp;quot; tab. You can clearly see how the debug line will simply disappear, a lonely &amp;quot;;&amp;quot; the only trace of it having been there.&lt;br /&gt;
&lt;br /&gt;
===5. The Optimizer===&lt;br /&gt;
&lt;br /&gt;
Including files has one disadvantage though. You will get the complete contents of the file, if you need it or not. But the Phoenix LSL Preprocessor uses an optimizing technique, which only keeps the things you really used in your code and removes all global functions and variables you didn&#039;t reference in your script. This makes sure that your scripts don&#039;t get burdened with a lot of unused code. You can enable or disable this functionality in the script editor&#039;s &amp;quot;Advanced&amp;quot; menu.&lt;br /&gt;
 &lt;br /&gt;
===6. &amp;lt;tt&amp;gt;switch/case&amp;lt;/tt&amp;gt; addition===&lt;br /&gt;
&lt;br /&gt;
The Preprocessor also adds a set of new commands to the LSL editor which has been sorely missing until now: the &amp;lt;tt&amp;gt;switch/case&amp;lt;/tt&amp;gt; construct known from many other languages. You can enable support for this construct in the script editor&#039;s &amp;quot;Advanced&amp;quot; menu. &amp;lt;tt&amp;gt;switch/case&amp;lt;/tt&amp;gt; is a handy replacement for &amp;lt;tt&amp;gt;if(...) else if()&amp;lt;/tt&amp;gt; chains. Additionally, switch/case supports &amp;quot;fallthrough&amp;quot; from one case to another, so you can chain up several cases with different conditions. A &amp;lt;tt&amp;gt;break&amp;lt;/tt&amp;gt; statement is used to prevent fallthrough. The &amp;lt;tt&amp;gt;default&amp;lt;/tt&amp;gt; case is used if none of the cases match the &amp;lt;tt&amp;gt;switch()&amp;lt;/tt&amp;gt; condition.&lt;br /&gt;
 &lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lsl&amp;gt;default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        integer i;&lt;br /&gt;
        switch(i)&lt;br /&gt;
        {&lt;br /&gt;
            case 1:&lt;br /&gt;
            {&lt;br /&gt;
                llOwnerSay(&amp;quot;1&amp;quot;);&lt;br /&gt;
                // fallthrough to case 2&lt;br /&gt;
            }&lt;br /&gt;
            case 2:&lt;br /&gt;
            {&lt;br /&gt;
                llOwnerSay(&amp;quot;1 or 2&amp;quot;);&lt;br /&gt;
                // no fallthrough&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            case 3:&lt;br /&gt;
            {&lt;br /&gt;
                llOwnerSay(&amp;quot;3&amp;quot;);&lt;br /&gt;
                // fallthrough to default&lt;br /&gt;
            }&lt;br /&gt;
            default:&lt;br /&gt;
            {&lt;br /&gt;
                llOwnerSay(&amp;quot;3 or default&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===7. Lazy Lists addition===&lt;br /&gt;
&lt;br /&gt;
Assigning values to list indexes is always a cumbersome thing to do in LSL (&amp;lt;tt&amp;gt;llListReplaceList()&amp;lt;/tt&amp;gt; needed). Lazy Lists can help you a little by providing a way to just say:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lsl&amp;gt;myList[index]=value;&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sadly it is not really possible to get list elements the same way because the return data can be of different types.&lt;br /&gt;
 &lt;br /&gt;
===8. Preprocessor Commands and Macros===&lt;br /&gt;
 &lt;br /&gt;
The Preprocessor understands the following commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lsl&amp;gt;#define&lt;br /&gt;
#undef&lt;br /&gt;
#ifdef&lt;br /&gt;
#ifndef&lt;br /&gt;
#if&lt;br /&gt;
#elif&lt;br /&gt;
#else&lt;br /&gt;
#endif&lt;br /&gt;
#warning&lt;br /&gt;
#error&lt;br /&gt;
#include&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are a few more, but these are not really useful within LSL.&lt;br /&gt;
&lt;br /&gt;
Additionally, you can use the following macros in your scripts to help with debugging and giving you other useful information:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;__FILE__&amp;lt;/tt&amp;gt; - the full path to the script as it would appear in the include cache. The top script only uses its name.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__LINE__&amp;lt;/tt&amp;gt; - the line of the current script where it is expanded; this starts at line 0&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__SHORTFILE__&amp;lt;/tt&amp;gt; - the name of the current script without full file path&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__AGENTID__&amp;lt;/tt&amp;gt; - a string-encapsulated version of the agent&#039;s key who compiles the script&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__AGENTKEY__&amp;lt;/tt&amp;gt; - same as above, legacy version&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__AGENTIDRAW__&amp;lt;/tt&amp;gt; - a nonstring-encapsulated version of the agent&#039;s key who compiles the script&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__AGENTNAME__&amp;lt;/tt&amp;gt; - a string-encapsulated version of the agent&#039;s full name who compiles the script&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__ASSETID__&amp;lt;/tt&amp;gt; - a string-encapsulated version of the assetid of the current script; may return &amp;quot;NOT IN WORLD&amp;quot; or a nonstring-encapsulated null key in rare circumstances &lt;br /&gt;
&lt;br /&gt;
Thanks to Zwagoth Klaar for this list.&lt;br /&gt;
&lt;br /&gt;
===8.1 &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt;===&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt; creates a case-sensitive macro which will be replaced while saving and compiling a script. This can be applied as simple constant numbers, strings, and even functions. What happens is a literal text replacement in the source code. Because of this, be careful with &amp;quot;;&amp;quot; inside your macros. These usually don&#039;t cause any harm; but within a one-line conditional, things can break in unexpected ways if it creates a &amp;quot;;;&amp;quot; in the end of a line, for example.&lt;br /&gt;
 &lt;br /&gt;
The following examples will give you an overview of what &amp;lt;/tt&amp;gt;#define&amp;lt;/tt&amp;gt; does. Have a look at the &amp;quot;Postprocessed&amp;quot; tab to see what the Preprocessor creates from the source.&lt;br /&gt;
 &lt;br /&gt;
Example 1:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lsl&amp;gt;#define CHANNEL 12345&lt;br /&gt;
llOwnerSay((string) CHANNEL); // CHANNEL will be replaced with the literal 12345 stated in the #define above&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt; can also take parameters to apply to the replacement code:&lt;br /&gt;
 &lt;br /&gt;
Example 2:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lsl&amp;gt;#define OS(b,c) llOwnerSay(b+c)&lt;br /&gt;
 OS(&amp;quot;Test&amp;quot;,&amp;quot;123&amp;quot;); // will expand to: llOwnerSay(&amp;quot;Test&amp;quot;+&amp;quot;123&amp;quot;)&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example 3: Making strings out of parameters&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lsl&amp;gt;#define OS(a) llOwnerSay(#a)&lt;br /&gt;
OS(1234); // will expand to: llOwnerSay(&amp;quot;1234&amp;quot;);&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example 4: Using &amp;lt;tt&amp;gt;&amp;quot;&amp;quot;##&amp;quot;&amp;quot;&amp;lt;/tt&amp;gt; to concatenate parameters&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lsl&amp;gt;#define OS(a,b) llOwnerSay((string) a##b)&lt;br /&gt;
OS(1234,5678); // will expand to: llOwnerSay((string) 12345678);&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===8.2 &amp;lt;tt&amp;gt;#undef&amp;lt;/tt&amp;gt;===&lt;br /&gt;
 &lt;br /&gt;
Removes a macro previously set up with &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt;. If the macro was not made in the first place, nothing happens. This is a useful way to enable or disable parts of the source code for debugging. See Section 4 above for an example on how to use it.&lt;br /&gt;
&lt;br /&gt;
===8.3 &amp;lt;tt&amp;gt;#ifdef&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#ifndef&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;#else&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#endif&amp;lt;/tt&amp;gt;===&lt;br /&gt;
 &lt;br /&gt;
This command is a part of conditional preprocessing in association with &amp;lt;tt&amp;gt;#else&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#endif&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;#ifdef&amp;lt;/tt&amp;gt; checks if a macro has been previously &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt;d. It doesn&#039;t matter if the macro has actually a value assigned to it. It just needs to be &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt;d. If it has, all of the code after &amp;lt;tt&amp;gt;#ifdef&amp;lt;/tt&amp;gt; up to &amp;lt;tt&amp;gt;#endif&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;#else&amp;lt;/tt&amp;gt; gets replaced into the postprocessed code. &amp;lt;tt&amp;gt;#ifndef&amp;lt;/tt&amp;gt; does the exact opposite. If a macro does not exist, the code goes into the Preprocessor.&lt;br /&gt;
 &lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lsl&amp;gt;#define OWNER_ONLY&lt;br /&gt;
...&lt;br /&gt;
#ifdef OWNER_ONLY&lt;br /&gt;
key var=llGetOwner();&lt;br /&gt;
#else&lt;br /&gt;
key var=llDetectedKey(0);&lt;br /&gt;
#endif&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===8.4 &amp;lt;tt&amp;gt;#if&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#elif&amp;lt;/tt&amp;gt;===&lt;br /&gt;
 &lt;br /&gt;
These are also conditional preprocessing commands. They take a general condition and pass on the code to the Preprocessor if the condition evaluates to &amp;lt;tt&amp;gt;TRUE&amp;lt;/tt&amp;gt;. They can also be used in conjunction with &amp;lt;tt&amp;gt;#else&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;#elif&amp;lt;/tt&amp;gt; is the equivalent to &amp;lt;tt&amp;gt;else if&amp;lt;/tt&amp;gt;.&lt;br /&gt;
 &lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lsl&amp;gt;#define DEBUGLEVEL 2&lt;br /&gt;
&lt;br /&gt;
#if DEBUGLEVEL==1&lt;br /&gt;
llOwnerSay(&amp;quot;Point reached&amp;quot;);&lt;br /&gt;
#elif DEBUGLEVEL==2&lt;br /&gt;
llOwnerSay(&amp;quot;Lots of more data here&amp;quot;);&lt;br /&gt;
#else&lt;br /&gt;
llOwnerSay(&amp;quot;Unknown debug level: &amp;quot;+(string) DEBUGLEVEL);&lt;br /&gt;
#endif&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===8.5 &amp;lt;tt&amp;gt;#warning&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#error&amp;lt;/tt&amp;gt;===&lt;br /&gt;
 &lt;br /&gt;
These two commands show a string in the compiler window to warn you about certain problems or to halt compilation immediately due to a fatal error. Right now, both &amp;lt;tt&amp;gt;#warning&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#error&amp;lt;/tt&amp;gt; cause the compiler to stop. It is unclear yet if &amp;lt;tt&amp;gt;#warning&amp;lt;/tt&amp;gt; will allow the compiler to continue to completion in the future.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; If one of these commands is hit by the Preprocessor, the script is &#039;&#039;&#039;NOT&#039;&#039;&#039; saved!&lt;br /&gt;
&lt;br /&gt;
Example 1:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lsl&amp;gt;#warning This include file is obsolete!&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example 2:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lsl&amp;gt;#error This include file does not work anymore. Please update.&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===8.6 &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
This is probably the most powerful feature of the Phoenix LSL Preprocessor. It includes whole source code files from your harddisk or from the same folder tree in your inventory into the script you are working on. A small example of this feature can be seen above in Section 4. &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; takes a file name relative to the include path set up in your Preferences. You can also include files inside of subfolders. If you are compiling your script from your inventory, the Preprocessor will search the inventory path you are working in, descending into any subfolders, to find the referenced include file. Unused functions and global variable declarations are removed by the Optimizer.&lt;br /&gt;
 &lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lsl&amp;gt;#include &amp;quot;command_ids.lsl&amp;quot;&lt;br /&gt;
#include &amp;quot;general_functions.lsl&amp;quot;&lt;br /&gt;
#include &amp;quot;hud/layout.lsl&amp;quot;&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; Be careful about including files from within &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt;s. You might &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; a file twice, if you are not really keeping track, and this will lead to problems. This issue is usually addressed by using so-called &amp;quot;Include guards&amp;quot;. You basically have a conditional compile that sets a &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt; macro and checks if it&#039;s already there. If it&#039;s not, &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; the contents of the file. If it was set, ignore the contents.&lt;br /&gt;
 &lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lsl&amp;gt;#ifndef SCRIPT_NAME_LSL&lt;br /&gt;
#define SCRIPT_NAME_LSL&lt;br /&gt;
your_script_starts_here()&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
#endif //SCRIPT_NAME_LSL&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These &amp;lt;tt&amp;gt;#ifndef&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#endif&amp;lt;/tt&amp;gt; commands make sure that the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; happens only once regardless of how often the file is actually referenced with &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt;.&lt;br /&gt;
 &lt;br /&gt;
===9. Known Issues===&lt;br /&gt;
&lt;br /&gt;
* Including a file from your hard drive containing a &amp;lt;tt&amp;gt;#endif&amp;lt;/tt&amp;gt; as last line (without linebreak) will not produce a warning about not having a line break but rather a statement error&lt;br /&gt;
* This can be fixed by adding a line break to the end of the file&lt;br /&gt;
* &amp;quot;Enable Text Compress&amp;quot; &#039;&#039;&#039;will break your script!&#039;&#039;&#039; (At least in its current form. It may be fixed, or removed, in the future.)&lt;/div&gt;</summary>
		<author><name>Phil Metalhead</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=String2Hex&amp;diff=1196037</id>
		<title>String2Hex</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=String2Hex&amp;diff=1196037"/>
		<updated>2015-04-06T02:00:33Z</updated>

		<summary type="html">&lt;p&gt;Phil Metalhead: updated &amp;lt;lsl&amp;gt; tags to &amp;lt;source&amp;gt; tags&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Full Unicode Support==&lt;br /&gt;
&lt;br /&gt;
Uses UTF-8 encoding of characters. If you can get the character into a string in LSL, this will encode that character in hex.&lt;br /&gt;
&lt;br /&gt;
For performance reasons you should really just get used to using Base64. Since LSL has no hex functions, implementing them comes at a great performance cost.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
string String2Hex(string str){&lt;br /&gt;
    string b64 = (string)llParseString2List(llStringToBase64(str), [&amp;quot;=&amp;quot;], []);&lt;br /&gt;
    integer length = ((llStringLength(b64) * 3) &amp;gt;&amp;gt; 1) &amp;amp; -2;&lt;br /&gt;
    b64 += &amp;quot;AAAAAAA&amp;quot;; // we will trim these off in the end, this works around SVC-104.&lt;br /&gt;
    integer count = -3;&lt;br /&gt;
    integer position = -4;&lt;br /&gt;
    string out;&lt;br /&gt;
    while ((count += 6) &amp;lt; length) {&lt;br /&gt;
        integer I = llBase64ToInteger(llGetSubString(b64, position += 4, position + 7)) | 1;//This is a bottle neck&lt;br /&gt;
        string T = &amp;quot;&amp;quot;;&lt;br /&gt;
        do {&lt;br /&gt;
            integer A = (I &amp;gt;&amp;gt;  2) &amp;amp; 0x3C000000; //28 -&amp;gt; 26&lt;br /&gt;
            integer B = (I &amp;gt;&amp;gt;  4) &amp;amp; 0x00F00000; //24 -&amp;gt; 20&lt;br /&gt;
            integer C = (I &amp;gt;&amp;gt;  6) &amp;amp; 0x0003C000; //20 -&amp;gt; 14&lt;br /&gt;
            T += llGetSubString( //ABC&lt;br /&gt;
                llIntegerToBase64(&lt;br /&gt;
                    A + B + C + 0xD34D0000&lt;br /&gt;
                    - (0xF8000000 * (A / 0x28000000)) //lowercase=0x90000000, uppercase=0xF8000000&lt;br /&gt;
                    - (0x03E00000 * (B / 0x00A00000)) //lowercase=0x02400000, uppercase=0x03E00000&lt;br /&gt;
                    - (0x000F8000 * (C / 0x00028000)) //lowercase=0x00090000, uppercase=0x000F8000&lt;br /&gt;
                ), 0, 3);&lt;br /&gt;
        } while (((I = (I &amp;lt;&amp;lt; 12)) &amp;amp; 0x1EE7);&lt;br /&gt;
        out += T;//This is a bottle neck&lt;br /&gt;
    }&lt;br /&gt;
    return llGetSubString(out, 0, length - 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
string Hex2String(string hex) {&lt;br /&gt;
    integer length = (llStringLength(hex) + 1) &amp;amp; -2;&lt;br /&gt;
    while(length)&lt;br /&gt;
        hex = llInsertString(hex, length -= 2, &amp;quot;%&amp;quot;);&lt;br /&gt;
    return llUnescapeURL(hex); //lol&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Limited ASCII-7 Support==&lt;br /&gt;
&lt;br /&gt;
These functions only works for ASCII-7 non-control characters. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
string c_chr=&amp;quot; !\&amp;quot;#$%&amp;amp;&#039;()*+,-./0123456789:;&amp;lt;=&amp;gt;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//	http://wiki.secondlife.com/wiki/Int2Hex&lt;br /&gt;
string int2hex(integer x){&lt;br /&gt;
	string toret;&lt;br /&gt;
	do{&lt;br /&gt;
		toret=llGetSubString(&amp;quot;0123456789ABCDEF&amp;quot;,x&amp;amp;0x0000000F,x&amp;amp;0x0000000F)+toret;&lt;br /&gt;
	}while (x=x&amp;gt;&amp;gt;4&amp;amp;0x0FFFFFFF);&lt;br /&gt;
	return toret;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
string str2hex(string str){&lt;br /&gt;
	string ret=&amp;quot;&amp;quot;;&lt;br /&gt;
	integer strlen=llStringLength(str);&lt;br /&gt;
	integer i=0;&lt;br /&gt;
	for(;i&amp;lt;strlen;++i){&lt;br /&gt;
		ret+=int2hex(32+llSubStringIndex(c_chr,llGetSubString(str,i,i)));&lt;br /&gt;
	}&lt;br /&gt;
	return ret;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
string hex2str(string str){&lt;br /&gt;
	string ret=&amp;quot;&amp;quot;;&lt;br /&gt;
	integer strlen=llStringLength(str);&lt;br /&gt;
	integer i=0;integer index;&lt;br /&gt;
	for(;i&amp;lt;strlen;i+=2){&lt;br /&gt;
		index=((integer)(&amp;quot;0x&amp;quot;+llGetSubString(str,i,i+1)))-32;&lt;br /&gt;
		ret+=llGetSubString(c_chr,index,index);&lt;br /&gt;
	}&lt;br /&gt;
	return ret;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default{&lt;br /&gt;
	state_entry(){&lt;br /&gt;
		llOwnerSay(str2hex(&amp;quot;test ~&amp;quot;));&lt;br /&gt;
		llOwnerSay(hex2str(&amp;quot;74657374207E&amp;quot;));&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Phil Metalhead</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=NumPad&amp;diff=1196028</id>
		<title>NumPad</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=NumPad&amp;diff=1196028"/>
		<updated>2015-04-05T05:56:41Z</updated>

		<summary type="html">&lt;p&gt;Phil Metalhead: Un-broke the code formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Header}}&lt;br /&gt;
{{RightToc}}&lt;br /&gt;
&lt;br /&gt;
Scripting tools to allow display of text on a prim: [[XyText 1.5]] , [[XyzzyText]], [[XyyyyzText]], [[XyText-UTF8]], [[XyzzyText-UTF8]], [[ZZText]], [[VariText]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NumPad&#039;&#039;&#039; is a variant of the text on a prim but with some changes&lt;br /&gt;
&lt;br /&gt;
* 1 texture vs 5 textures needed for XyText 1.5 &#039;to render numbers&#039;&lt;br /&gt;
* Numbers and spaces only.&lt;br /&gt;
* About 73 lines of code.&lt;br /&gt;
&lt;br /&gt;
=Copyright &amp;amp; Licensing=&lt;br /&gt;
&amp;lt;font size=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
* Madpeter Zond hereby releases his contributions to this under the MIT license. [Starting texture and Starting code]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=NumPad 10digits=&lt;br /&gt;
&lt;br /&gt;
Quickstart:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* Take a copy of the 10 char prim setup from [[XyText 1.5]] and setup a prim&lt;br /&gt;
* After running the code create a new script and copy the NumPad code to it.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* Set render_to_prim_number to the number of the prim you wish to render to,&lt;br /&gt;
* if you dont know the number you can put the script inside of the prim you want&lt;br /&gt;
* and not change this.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Main Script==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
////////////////////////////////////////////////////&lt;br /&gt;
//  NumPad&lt;br /&gt;
//  ----------------&lt;br /&gt;
//  Version: 1.0&lt;br /&gt;
//  By: Madpeter Zond&lt;br /&gt;
//  About: A 1 texture 10 digit number display&lt;br /&gt;
//         great for a score output.&lt;br /&gt;
////////////////////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
string texture = &amp;quot;31f72af5-dee3-72f5-3981-bde21bf85e9c&amp;quot;;&lt;br /&gt;
integer render_to_prim_number = LINK_THIS;&lt;br /&gt;
vector render_color = &amp;lt;1,1,1&amp;gt;;&lt;br /&gt;
float glow_amount = 0.00;&lt;br /&gt;
&lt;br /&gt;
// please dont change this unless you want to break something ^_^&lt;br /&gt;
list faces = [3,7,4,6,1];&lt;br /&gt;
list grid_offset_starts = [&amp;lt;-0.38941,-0.54747,0&amp;gt;  ,&amp;lt;-0.44939,-0.54750,0&amp;gt;,  &amp;lt;0.01800,0.45256,0&amp;gt;,&amp;lt;-0.44939,-0.54750,0&amp;gt;,&amp;lt;-0.50941,-0.54747,0&amp;gt;];&lt;br /&gt;
list repeats_corrections = [&amp;lt;0.1,0,0&amp;gt;,&amp;lt;0,0,0&amp;gt;,&amp;lt;-1.35,0,0&amp;gt;,&amp;lt;0,0,0&amp;gt;,&amp;lt;0.1,0,0&amp;gt;];&lt;br /&gt;
vector repeats_config = &amp;lt;0.1,0.083333,0&amp;gt;;&lt;br /&gt;
float fix(float input)  // render blocking fix [haxy]   &lt;br /&gt;
{&lt;br /&gt;
     if(input &amp;gt; 1.0) input -= 1.0;&lt;br /&gt;
     else if(input &amp;lt; -1.0) input += 1.0;&lt;br /&gt;
     return input; &lt;br /&gt;
}&lt;br /&gt;
render(string output)&lt;br /&gt;
{&lt;br /&gt;
    while(llStringLength(output) &amp;lt;= 10) { output = &amp;quot;&amp;quot;+output+&amp;quot; &amp;quot;; }&lt;br /&gt;
    list renderrules = [];&lt;br /&gt;
    integer loop = 0;&lt;br /&gt;
    while(loop &amp;lt; 5)&lt;br /&gt;
    {&lt;br /&gt;
        string part = llGetSubString(output,(2*loop),(2*loop)+1);&lt;br /&gt;
        if(part == &amp;quot;  &amp;quot;)&lt;br /&gt;
        {&lt;br /&gt;
            // empty&lt;br /&gt;
            renderrules = renderrules + [PRIM_COLOR,llList2Integer(faces,loop),&amp;lt;1,1,1&amp;gt;,0,PRIM_GLOW,llList2Integer(faces,loop),0];&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            integer Y_offset = (integer)llGetSubString(part,0,0);&lt;br /&gt;
            integer X_offset = (integer)llGetSubString(part,1,1);&lt;br /&gt;
            if(llGetSubString(part,0,0) == &amp;quot; &amp;quot;) Y_offset = 10; // left side empty &lt;br /&gt;
            else if(llGetSubString(part,1,1) == &amp;quot; &amp;quot;) &lt;br /&gt;
            {&lt;br /&gt;
                Y_offset = 11; // right side empty&lt;br /&gt;
                X_offset = (integer)llGetSubString(part,0,0);&lt;br /&gt;
            }&lt;br /&gt;
            vector start = llList2Vector(grid_offset_starts,loop);&lt;br /&gt;
            start = &amp;lt;fix(start.x + (0.1 * X_offset)),fix(start.y + (-0.083333333 * Y_offset)),0&amp;gt;;&lt;br /&gt;
            renderrules = renderrules + [PRIM_TEXTURE,llList2Integer(faces,loop),texture,repeats_config+llList2Vector(repeats_corrections,loop),start,0,PRIM_COLOR,llList2Integer(faces,loop),render_color,1,PRIM_GLOW,llList2Integer(faces,loop),glow_amount];&lt;br /&gt;
        }&lt;br /&gt;
        loop++;&lt;br /&gt;
    }&lt;br /&gt;
    llSetLinkPrimitiveParamsFast(render_to_prim_number,renderrules);&lt;br /&gt;
}&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        render(&amp;quot;1234567890&amp;quot;);&lt;br /&gt;
    }    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Texture layout==&lt;br /&gt;
&amp;lt;p&amp;gt; the texture is setup in a 10x12 format as follows.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
00 01 02 03 04 05 06 07 08 09&lt;br /&gt;
10 11 12 13 14 15 16 17 18 19&lt;br /&gt;
20 21 22 23 24 25 26 27 28 29&lt;br /&gt;
30 31 32 33 34 35 36 37 38 39&lt;br /&gt;
40 41 42 43 44 45 46 47 48 49&lt;br /&gt;
50 51 52 53 54 55 56 57 58 59&lt;br /&gt;
60 61 62 63 64 65 66 67 68 69&lt;br /&gt;
70 71 72 73 74 75 76 77 78 79&lt;br /&gt;
80 81 82 83 84 85 86 87 88 89&lt;br /&gt;
90 91 92 93 94 95 96 97 98 99&lt;br /&gt;
_0 _1 _2 _3 _4 _5 _6 _7 _8 _9&lt;br /&gt;
0_ 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_ 9_&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Improvements==&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
there are some improvements that could be made&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
1: Change the texture format to 11x11 to improve the quality of the numbers.&amp;lt;br/&amp;gt;&lt;br /&gt;
2: Change the while loop to a for loop if that saves memory.&amp;lt;br/&amp;gt;&lt;br /&gt;
3: Change the way it builds rules if a way is found that saves script memory.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Phil Metalhead</name></author>
	</entry>
</feed>