gmslPostingPairClass

The PostingPair Service Class

The service class PostingPair gives simple gives access to the SortPair class in the services library.

PropertyBag ComboBox/ListBox .ItemData and .List

Both List and ItemData must be specified in the property bag for these controls. The internal logic will use the presence in the Registry of this Database to trigger the migration.


<Registry type="Table" source="ItemData" />
The test for the trigger is in the analyser code used to create .NET interface controls based on VB6 specifications


if(Registry_GetNameRoot("Table","ItemData") == 0) return 0;
iRet = GmslHandlers_CallMethod("Utility.ListControls",iChild,0,iStart);
return iRet;
and in the code that authors these controls


if(Registry_GetNameRoot("Table","ItemData") != 0)
{
   GmslHandlers_CallMethod("Utility.ListControls",root,1,0);
}
The additional code in the analyser is called when the property migration logic notices that a ListBox or ComboBox have both ItemData and List specified. A crucial point is that this check is done easily here in the analyser. It is difficult to do in the authoring logic that assumes that everything has been set up properly. Also to block the Items AddRange for the migrated code the specification for the List must be removed from the property bag. A messy problem because this very same information is still needed to author the new AddRange.

Here is the new gmSL method ListControls in the Utilities.gmsl language file.


int ListControls(int iRoot,int action,int iStart)
{
   tCodeBlock codptr;
   int        ctlType;
   int        listAddr;
   int        itemDataAddr;
   int        list;
   int        itemData;
   int        Record[2];
   int        levels[19];
   int        iChild;
   int        index;
   string     listEntry;
   string     itemEntry;
   string     tokens[64];
   string     token;
   int        nToken;
   int        tokenType;
   int        member;
   int        pairRoot;
   int        postPair;
   Handle     storeArea;

   if(action == 0)
   {
      codptr = Opcode.GetCode();
      ctlType = Store.GetObjectType(iRoot);
      listAddr = ControlData.FindProperty(ctlType,"List",iStart);
      itemDataAddr = ControlData.FindProperty(ctlType,"ItemData",iStart);
      Opcode.GetOperation(codptr,listAddr,list);
      Opcode.GetOperation(codptr,itemDataAddr,itemData);
      pairRoot = Registry.GetNameRoot("Table","ItemData");
      postPair = Registry.GetPosting(pairRoot);
      storeArea = Store.GetHandle();
      if(postPair == 0)
      {
         postPair = PostingPair.Create(storeArea);
         Registry.SetPosting(pairRoot,postPair);
      }
      Record[0] = list;
      Record[1] = itemData;
      index = Store.String(Record);
      PostingPair.Write(storeArea,postPair,iRoot,index);
      Opcode.Delete(listAddr,2);
      return 1;
   }
   else if(action == 1)
   {
      pairRoot = Registry.GetNameRoot("Table","ItemData");
      postPair = Registry.GetPosting(pairRoot);
      if(postPair == 0) return 0;
      storeArea = Store.GetHandle();
      for(iChild = Store.FindFirstChild(levels,iRoot); iChild != 0; iChild = Store.FindNextChild(levels))
      {
         index = PostingPair.Find(storeArea,postPair,iChild);
         if(index != 0)
         {
             if(Select.Dialect == Dialects.vbn)
             {
                Write.Line("Me." + Store.GetName(iChild) + ".Items.AddRange(new MigrationSupport.UI.ItemData() {");
             }
             else Write.Line("this." + Store.GetName(iChild) + ".Items.AddRange(new MigrationSupport.UI.ItemData[] {");
             Store.GetInfo(index,Record);
             listEntry = Store.GetString(Record[0]);
             itemEntry = Store.GetString(Record[1]);
             Parser.SetStatement(listEntry);
             nToken = 0;
             while(true)
             {
               token = Parser.GetToken(tokenType);
               if(tokenType == 0) break;
               if(token != ",")
               {
                  tokens[nToken] = token;
                  nToken = nToken + 1;
               }
            }
            Parser.SetStatement(itemEntry);
            Write.ChangeMargin(1);
            for(member = 0; member < nToken; member = member + 1)
            {
               token = Parser.GetToken(tokenType);
               Write.Text("new MigrationSupport.UI.ItemData(""");
               Write.Text(tokens[member] + """," + token + ")");
              if(member < (nToken-1)) Write.Text(",");
              else if(Select.Dialect == Dialects.vbn) Write.Text("})");
              else Write.Text("});");
              Write.Record();
              token = Parser.GetToken(tokenType);
           }
           Write.ChangeMargin(-1);
        }
     }
  }
  return 0;
}
If the PostingPair associated with the Table.ItemData registry entry has not yet been created, then it must be created. The table has 3 fields: an identifier field "Control" and two varchar fields "List" and "ItemData" that contain the property strings. The "symbol" type takes root offsets from the symbol table and VarChar fields are simple "Store_String" offsets. All of this information is directly available at this point in the property bag code so it can be moved directly into the record and written to the table. Once this is in place, we can verify that the strings have been properly stored by using the new gmMetrics tool.

PostingPair.Create Method

The Create method creates a small integer SortPair used for looking up links and relationships between components in long memory based on their defining root offsets.


<Method id="Create" type="Integer" opcode="SCM.PostingPair_Create" >
   <Argument id="Store" type="Object" status="ByVal" />
</Method>
The information structure associated with posting pairs itself is allocated locally on the stack and is never left open; therefore, posting pairs do not have handles and are controlled entirely via their root offsets. Its parameter is:

Parameter Description
Store specifies the long memory area that is to contain the sort pair

If all goes well, then the method returns the root offset in the long memory area of the control information vector for the posting pair. If there is a problem, then a zero is returned.

PostingPair.Find Method

The Find method looks up the posting value associated with a posting index into a posting pair.


<Method id="Find" type="Integer" opcode="SCM.PostingPair_Find" >
   <Argument id="Store" type="Object" status="ByVal" />
   <Argument id="Base" type="Integer" status="ByVal" />
   <Argument id="Index" type="Integer" status="ByVal" />
</Method>
Its parameters are:

Parameter Description
Store Specifies the handle for the long memory area containing the posting pair.
Base Specifies the root offset of the posting pair in the storage area.
Index Specifies the index value for which a corresponding posting value is desired.

If the posting pair contains an entry for the index, then its associated value is returned; else a zero is returned.

PostingPair.Write Method

The Write method writes a new posting to a posting pair.


<Method id="Write" type="Integer" opcode="SCM.PostingPair_Write" >
   <Argument id="Store" type="Object" status="ByVal" />
   <Argument id="Base" type="Integer" status="ByVal" />
   <Argument id="Index" type="Integer" status="ByVal" />
   <Argument id="Posting" type="Integer" status="ByVal"/>
 </Method>
Its parameters are:

Parameter Description
Store Specifies the handle for the long memory area containing the posting pair.
Base Specifies the root offset of the posting pair in the storage area.
Index Specifies the index value for which a corresponding posting value is needed.
Posting Specifies the posting value to be associated with the index.

If the pair already exists and has a nonzero value associated with it, the method returns a zero.
Table of Contents