• Which the release of FS2020 we see an explosition of activity on the forun and of course we are very happy to see this. But having all questions about FS2020 in one forum becomes a bit messy. So therefore we would like to ask you all to use the following guidelines when posting your questions:

    • Tag FS2020 specific questions with the MSFS2020 tag.
    • Questions about making 3D assets can be posted in the 3D asset design forum. Either post them in the subforum of the modelling tool you use or in the general forum if they are general.
    • Questions about aircraft design can be posted in the Aircraft design forum
    • Questions about airport design can be posted in the FS2020 airport design forum. Once airport development tools have been updated for FS2020 you can post tool speciifc questions in the subforums of those tools as well of course.
    • Questions about terrain design can be posted in the FS2020 terrain design forum.
    • Questions about SimConnect can be posted in the SimConnect forum.

    Any other question that is not specific to an aspect of development or tool can be posted in the General chat forum.

    By following these guidelines we make sure that the forums remain easy to read for everybody and also that the right people can find your post to answer it.

Storing String Data

Messages
1,564
Country
thailand
The need to store strings is an issue sometimes faced when coding in XML, particularly when designing a gauge that utilizes the gps module (for example, when making an FMS). Options to store string data include:

1. Use of XML String Operators ord chr and scat to store and retrieve the ascii code equivalent of individual string characters in L:Vars. This has been the standard approach.

2. Macros that make use of the String Operators and enable more than one string character (up to 6) to be stored into a single L:Var. For example, Roman Stoviak has written a very clever set of macros that use String and Numerical Operators to store up to 6 string characters into L:Vars. http://forum.avsim.net/topic/299204-storing-string-data/

3. The internal registers, e.g., s0 … s49, with the limitation that these registers are wiped clean every update cycle.

4. Doug Dawson's String to memory dll module. Doug bottomless bag of cool tricks includes a prototype (September 2011) module that will allow strings to be stored into memory. Tested in FSX. Requires the loading of the dll module (but you won't need the macros from 2.). Please refer to Doug's posts further down in this thread.

5. Tom Aguilo's XMLTOOLS. This powerful module provides many additional functions to XML gauges. The XMLVARS class allows storage of string values.

6. XML read/write to hard disk. Robbie McElrath has completed a dll module that enables very easy file read/write capability: XML--> HDD--> XML. Accommodates strings and numbers, works with all text and .csv file formats, FS9 and FSX. Available on the BlackBox website and also bundled with XMLTOOLS. http://forum.avsim.net/topic/299204-storing-string-data/


A variation on 2), Robbie provides the following macros that utilize String and Bit Operators to manipulate strings and store the result into L:Vars.
Features of these macros:

a) Strings of up to 64 alphanumeric characters, including spaces, in length can be stored in a single, L:Var. All ascii special characters: !, @, #, $, % etc. etc. except "&", "/", "\", "<", and " ' " (single quote) are accommodated in addition to all of the alphanumerics.

b) The L:Var can have any name and there can be any number of such 'string' L:Vars in a gauge. The 'string' L:Vars can be read by any XML gauge of your panel set, similar to normal L:Vars.

c) Functional Backspace

d) FS9, FSX, P3D 32 and 64


THE MACROS. There are 12 of them, but once they are copied and pasted into your gauge, you’re set (and these are an update to the original macros posted in the AVSIM Forum link above):
Code:
<Macro Name="Read4">
  (@1_4, number) 7 &lt;&lt; 0xFFFFFFF &amp; (@1_3, number) 21 >> 0x7F &amp; | (>@1_4, number)
  (@1_3, number) 7 &lt;&lt; 0xFFFFFFF &amp; (@1_2, number) 21 >> 0x7F &amp; | (>@1_3, number)
  (@1_2, number) 7 &lt;&lt; 0xFFFFFFF &amp; (@1_1, number) 21 >> 0x7F &amp; | (>@1_2, number)
  (@1_1, number) 7 &lt;&lt; 0xFFFFFFF &amp; (@2, number)   @3    0x7F &amp; | (>@1_1, number)
</Macro>

<Macro Name="ReadKB">
  @Read4(@1_4, @1_3_4, 21 >>)
  @Read4(@1_3, @1_2_4, 21 >>)
  @Read4(@1_2, @1_1_4, 21 >>)
  @Read4(@1_1, M:Key)
</Macro>

<Macro Name="Read4Str">
  (@1_4, number) 7 &lt;&lt; 0xFFFFFFF &amp; (@1_3, number) 21 >> 0x7F &amp; | (>@1_4, number)
  (@1_3, number) 7 &lt;&lt; 0xFFFFFFF &amp; (@1_2, number) 21 >> 0x7F &amp; | (>@1_3, number)
  (@1_2, number) 7 &lt;&lt; 0xFFFFFFF &amp; (@1_1, number) 21 >> 0x7F &amp; | (>@1_2, number)
  (@1_1, number) 7 &lt;&lt; 0xFFFFFFF &amp;  @2                  0x7F &amp; | (>@1_1, number)
</Macro>  

<Macro Name="ReadStr">
  @Read4(@1_4, @1_3_4, 21 >>)
  @Read4(@1_3, @1_2_4, 21 >>)
  @Read4(@1_2, @1_1_4, 21 >>)
  @Read4Str(@1_1, r)
</Macro>

<Macro Name="Backspace4">
  (@1_1, number) 7 >> (@1_2, number) 0x7F &amp; 21 &lt;&lt; | (>@1_1, number)
  (@1_2, number) 7 >> (@1_3, number) 0x7F &amp; 21 &lt;&lt; | (>@1_2, number)
  (@1_3, number) 7 >> (@1_4, number) 0x7F &amp; 21 &lt;&lt; | (>@1_3, number)
  (@1_4, number) 7 >> (@2_1, number) 0x7F &amp; 21 &lt;&lt; | (>@1_4, number)
</Macro>

<Macro Name="Backspace">
  @Backspace4(@1_1, @1_2)
  @Backspace4(@1_2, @1_3)
  @Backspace4(@1_3, @1_4)
  @Backspace4(@1_4, L:PleaseBeZero)
</Macro>

<Macro Name="Clear4">
  0 (>@1_1, number) 0 (>@1_2, number) 0 (>@1_3, number) 0 (>@1_4, number)
</Macro>

<Macro Name="Clear">
  @Clear4(@1_1) @Clear4(@1_2) @Clear4(@1_3) @Clear4(@1_4)
</Macro>

<Macro Name="ToString1">
  (@1, number) 21 >> 0x7F &amp; chr
  (@1, number) 14 >> 0x7F &amp; chr scat
  (@1, number)  7 >> 0x7F &amp; chr scat
  (@1, number)       0x7F &amp; chr scat
</Macro>

<Macro Name="ToString4">
  @ToString1(@1_4) @ToString1(@1_3) @ToString1(@1_2) @ToString1(@1_1) scat scat scat
</Macro>

<Macro Name="ToString">
  @ToString4(@1_4) @ToString4(@1_3) @ToString4(@1_2) @ToString4(@1_1) scat scat scat
</Macro>
 
<Macro Name="FromString">
    :221 d slen 0 > if{ d 0 symb ord @ReadStr(@1) d slen 1 - 1 r ssub g221 }
</Macro>


USING THE MACROS. This is the easy part.

1. CONVERTING STRING DATA INTO AN L:Var

  • Entering one character at a time such as in direct keyboard entry, automatically concatenating as you type. The use of <On Key="Ascii"> will enable keyboard entry of "-" and "." as well as all the other alphanumerics:
Code:
<On Key="Ascii"> <!-- Keyboard Entry -->
    <Visible>(L:KeyboardEntryEnabled1, bool)</Visible>
    @ReadKB(L:StringLVar1)
</On>

<On Key="Backspace"> <!-- Backspace -->
    <Visible>(L:KeyboardEntryEnabled1, bool)</Visible>
    @Backspace(L:StringLVar1)
</On>
The user just needs to choose an arbitrary L:Var name, such as StringLVar1. No need to include units. Entering data via “typing” on an FMS keypad image in your gauge is a simple variation of this. You only need to adjust the M:Key reference in the ReadKB macro. The last line of the ReadKB macro would read @Read4(@1_1, L:LKey) rather than @Read4(@1_1, M:Key). Then, in the <Mouse> section, for a click on the letter "A" for example:
Code:
<Area Left="25" Top="220" Width="15" Height="15">
    <Cursor Type="Hand" />
        <Click>
            'A' ord (>L:LKey, enum)
            @ReadKB(L:StringLVar1) 
        </Click>
</Area>

  • Entering a string of characters all at once. If you want to store something like:
‘VED BAM’, or (A:NAV1 IDENT, string), the following is used:
Code:
@Clear(L:BAM_VOR_ICAO)
'VED    BAM' @FromString(L:BAM_VOR_ICAO)

or

@Clear(L:Nav1Name)         
(A:NAV1 NAME, string) @FromString(L:Nav1Name)
2. DISPLAYING THE 'STRING' L:Var:
Code:
<String>%(@ToString(L:StringLVar1))%!s!</String>
3. PASSING A 'STRING' L:Var:
Code:
@ToString(L:BAM_VOR_ICAO) (>C:fs9gps:WaypointVorIcao)
4. CLEARING THE 'STRING' L:Var:
Code:
@Clear(L:StringLVar1)

Later today, I will attach a simple, fully functional “test gauge” that can be used to check out the use and capabilities of these string macros.

Appreciate feedback and comments – especially if unintended side effects are found.

Cheers,

Bob :)
 
Last edited:
Attached is an XML "test gauge" that demonstrates use of the string store macros.

Using the Store String Gauge:

  • Click on Text Box 1 to enable Direct Keyboard Entry in that Text Box
  • Type in any valid VOR ICAO. As an example, VRJ_ _ _ _NRE
  • The String L:Var appears in the text box as you type
  • Click the Dark Red button
  • The String L:Var is passed to the gps dll module and the gps variables (C:fs9gps:WaypointVorIdent), (C:fs9gps:WaypointVorName), and (C:fs9gps:WaypointVorFrequency, MHz) appear above the Text Box

  • Click on Text Box 2 to enable Direct Keyboard Entry in that Text Box
  • Type in any valid Facility ICAO, as an example WK3KICTCF19R which is an approach waypoint associated with Runway 19R at Wichita-MidContinent Airport, Kansas USA
  • The String L:Var appears in the text box as you type
  • Click the Royal Blue button
  • The String L:Var is passed to the gps dll module and a Direct To Flight Plan is created
  • The gps variables (C:fs9gps:FlightPlanTitle) and (C:fs9gps:FlightPlanWaypointDistanceRemaining, nmiles) appear above the Text Box
  • Check your Flight Plan or Map to see the new Flight Plan routing

  • Tune your NAV1 to any VOR within range of the aircraft
  • Click the Olive Drab button
  • The A:Vars (A:NAV1 IDENT, string) and (A:NAV1 NAME, string) are then stored into string L:Vars and the string L:Vars are, in turn, displayed next to the Olive Drab button captions

  • Click on the Red Box “R” to clear values

Inspect the XML code to see how the String Macros @ToString, @FromString, @Backspace, @ReadKB, @ReadStr, and @Clear are used.

Cheers,

Bob
 

Attachments

  • String Gauge1 pic.jpg
    String Gauge1 pic.jpg
    25.5 KB · Views: 776
  • Store String 1.xml
    13.2 KB · Views: 760
Last edited:
Hi Bob!
Many thanks for having post this !!
I made a quick test and it seems to work perfectly for me!!
The last blocking point that I have is to be abble to share string between XML and C++ without using a declared dll and generic string variable which is quite complex to install for most of simmers.
I would like to understand how the macros you've posted work, in order to have similar FromString/ToString functions in C++ and be able to share strings using L:Var.
Why? Because I coded c++ gauges which parse xml files (such as carriers or tanker planes configuration values) and I would like to "import" parsed string variables into XML gauge...

Does anyone knows how to translate these macros in C++?
Regars,
Sylvain
 
Hi Bob!
Many thanks for having post this !!
I made a quick test and it seems to work perfectly for me!!
The last blocking point that I have is to be abble to share string between XML and C++ without using a declared dll and generic string variable which is quite complex to install for most of simmers.
I would like to understand how the macros you've posted work, in order to have similar FromString/ToString functions in C++ and be able to share strings using L:Var.
Why? Because I coded c++ gauges which parse xml files (such as carriers or tanker planes configuration values) and I would like to "import" parsed string variables into XML gauge...

Does anyone knows how to translate these macros in C++?
Regars,
Sylvain

Have a look at the CABIN_COMFORT example in the SDK. If you can get that code loading in a gauge, rather than in a module, you are home free. I haven't been able to do that yet, so we are stuck with the .dll module, so far.

Doug
 
Last edited:
I made a quick test and it seems to work perfectly for me!!

Thanks, Sylvain.

I am curious to know - did you test the macros in FS9 or FSX? I have only FS9 on my pc right now, consequently I have not tried them in FSX.

Bob
 
...I am curious to know - did you test the macros in FS9 or FSX?

Hi Bob,
yes I tested it in FSX. For XML gauge that use last ACE XML structure, I just need to add <MacroValue> tag to make it works.

Doug, you're right : CabinConfort done in a "In Proc" process should exactly be what I would like to do...
As SimConnect is something possible in gauge code, I hope CabinConfort should work also I wish I had more time for C++ "exploration" :D

Regards,
Sylvain
 
For the benefit of those who have only had access to the version of the module uploaded in Post #4, above:
The module will also store individual string variables, in addition to arrays of strings or numbers.
The methodology is pretty straightforward.

First, you store the string in a variable, using any variable name you like,
'Some string I want to keep' (>C:FSX_STRINGS:ImportantStringNumberOne)
'Some other useful string' (>C:FSX_STRINGS:ImportantStringNumberTwo)

Then, you use the string variable to retrieve the saved string,
<String>%((C:FSX_STRINGS:ImportantStringNumberOne))%!s!</String>
<String>%((C:FSX_STRINGS:ImportantStringNumberTwo))%!s!</String>

Note that the use of XML style indexes (":" followed by a number), is troublesome at best and really not recommended. That was why I built in the array support.

Sylvain,
There is a C++ interface into the module, above. I will write some documentation for it and post. You can try building it into your existing gauges, if you wish.

Doug
 
Hello rpmc. Thank you for the gauge. Please see attached picture.
1) The first button does not seem to work. I typed in "ELX," a valid VOR but nothing seems to happen.
2) The DTO button seems to only work when "WK3KICTCF19R" is typed in. Shouldn't it work for any valid ICAO waypoint, say KDEN? I tried but to no avail.
3) What do the count up numbers represent next to the buttons?
4) Can the string Lvar's be copied to another Lvar (L:StoringValue)? I tried:
Code:
<Click>
                        @ToString(L:DTO_ICAO_String) (>C:fs9gps:FlightPlanNewWaypointICAO)
                        (>C:fs9gps:FlightPlanDirectToDestination) (>L:StoringValue)
                        (L:Button2Clicks, enum) ++ (>L:Button2Clicks, enum)
                    </Click>

But I did not see any value from L:StoringValue. My goal was to store the string in a Lvar, use a lua to copy it to a FSUIPC offset.
 
Back
Top