December 20, 2014
Hot Topics:

Working with Resources in Palm OS Applications

  • January 17, 2005
  • By Alex Gusev
  • Send Email »
  • More Articles »

Getting Access to Resources

The Data Manager exposes several functions to access resources stored in database:

MemHandle  DmGetResource(DmResType type, DmResID resID);
MemHandle  DmGet1Resource(DmResType type, DmResID resID);
Err        DmReleaseResource(MemHandle resourceH);
MemHandle  DmResizeResource(MemHandle resourceH, UInt32 newSize);
MemHandle  DmGetResourceIndex(DmOpenRef dbP, UInt16 index);

An application gets the resources by calling either DmGetResource, DmGet1Resource, or DmGetResourceIndex. The difference between the first two APIs is that DmGetResource searches all opened databases, whereas DmGet1Resource uses the most recently opened one. As an example, the following code loads a string list from the resource and fills in some other list:

// define global containers somewhere
char **pszTestList = NULL;
UInt16 g_nNumItems = 0;
...
   DmOpenRef dbP   = DmNextOpenResDatabase(NULL);
   MemHandle hSTL   = DmGet1Resource('tSTL',StrList);

   if ( hSTL )
   {
      Char *pSTL = (Char*)MemHandleLock(hSTL);
      pSTL += StrLen(pSTL)+1;
      MemMove(&g_nNumItems,pSTL,2);
      pSTL += 2;

      pszTestList = new Char*[g_nNumItems];
      for (UInt16 wIdx = 0; wIdx < g_nNumItems; wIdx++)
      {
         pszTestList[wIdx] = new Char[StrLen(pSTL) + 1];
         StrCopy(pszTestList[wIdx],pSTL);
         pSTL += StrLen(pSTL) + 1;
      }
      UInt16 lstIndex = FrmGetObjectIndex(frmP, ResViewTestList);
      ListType *listP = (ListType *)FrmGetObjectPtr(frmP, lstIndex);
      LstSetListChoices (listP,pszTestList,g_nNumItems);
      LstDrawList(listP);

      MemHandleUnlock(hSTL);
      DmReleaseResource(hSTL);
   }
...

// and then release all allocated data at exit
static void AppStop(void)
{

   /* Close all the open forms. */
   FrmCloseAllForms();

   for (UInt16 wIdx = 0; wIdx < g_nNumItems; wIdx++)
   {
      delete [] pszTestList[wIdx];
   }

   delete [] pszTestList;
}

This sample also gives you the internal structure of the 'tSTL' resource:

  • Prefix string
  • Number of items in list (2 bytes)
  • Strings themselves

So, by enumerating strings one by one, you can get them all. If you need to extract a specific string by a known index, you have another function to be called:

Char *SysStringByIndex (UInt16 resID, UInt16 index, Char *strP,
                        UInt16 maxLen);

// So it is...
// the very first string is taken
Char Str[255];
if ( SysStringByIndex(StrList, 0, Str, sizeof(Str)) )
{
...
}

The returned string is concatenated from the prefix and string at the given index.

The next snippet gives you one more simple example of how to retrieve raw data from a resource via a DmGetResource call:

DmOpenRef dbP = DmNextOpenResDatabase(NULL);

MemHandle hData = DmGetResource('tbin',HexSampleRes);
Char *pHexData  = (Char*)MemHandleLock(hData);
Int32 dwData;
MemMove(&dwData,pHexData,4);
MemHandleUnlock(hData);
DmReleaseResource(hData);

DmGetResource returns the resource located in the overlay if any open overlay has a resource matching that type and ID. Otherwise, this function continues to search the resource in the base database.

Finally, when the resource is no longer needed, you should call DmReleaseResource to release it. Obviously enough, the application must do it as soon as it does not need this resource any more to ease the OS's life.

The Last Piece

In this final section, you will explore a few more API calls. This kind of function handles resource creation and deletion, together with updating existing data. These functions are:

// Resource Info
UInt16  DmNumResources(DmOpenRef dbP);
Err     DmResourceInfo(DmOpenRef dbP, UInt16 index,
                       DmResType *resTypeP, DmResID *resIDP,
                       LocalID *chunkLocalIDP);
Err     DmSetResourceInfo(DmOpenRef dbP, UInt16 index,
                          DmResType *resTypeP, DmResID *resIDP);

// Resource attaching and detaching
Err  DmAttachResource(DmOpenRef dbP, MemHandle newH,
                      DmResType resType, DmResID resID);
Err  DmDetachResource(DmOpenRef dbP, UInt16 index, MemHandle *oldHP);

// Resource creation and deletion
MemHandle  DmNewResource(DmOpenRef dbP, DmResType resType,
                         DmResID resID, UInt32 size);
Err        DmRemoveResource(DmOpenRef dbP, UInt16 index);

As you can see, they are divided into three groups. The first group is informational and simple. The other two groups allow you to manage resources. DmAttachResource converts given memory chunk into a specified resource, so that's the way to create new resources on-the-fly. DmDetachResource removes a resource from the database and reassigns it to a memory chunk. All the rest is self-explained. I will not touch them here in details, leaving it for your own fun. That's it; you're ready to explore new resource islands.

About the Author

Alex Gusev started to play with mainframes at the end of the 1980s, using Pascal and REXX, but soon switched to C/C++ and Java on different platforms. When mobile PDAs seriously rose their heads in the IT market, Alex did it too. Now, he works at an international retail software company as a team leader of the Mobile R department, making programmers' lives in the mobile jungles a little bit simpler.





Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel