Resource Types
Before diving into the Palm OS resource managemnent stuff, take a look at what you are going to manage. The following table describes the main resource types available in Palm OS:
Constant | Value | Description |
---|---|---|
strRsc | 'tSTR' | String resource |
ainRsc | 'tAIN' | Application Icon Name resource |
iconType | 'tAIB' | Icon resource |
bitmapRsc | 'Tbmp' | Bitmap resource |
bsBitmapRsc | 'Tbsb' | Boot screen bitmap. This resource is system reserved |
alertRscType | 'Talt' | Alert resource |
kbdRscType | 'tkbd' | Keyboard resource. This resource is system reserved |
MenuRscType | 'MBAR' | Menu Bar resource |
fontRscType | 'NFNT' | Single density Font resource |
fontExtRscType | 'nfnt' | High density Font resource |
verRsc | 'tver' | Version resource |
appInfoStringsRsc | 'tAIS' | Application Categories are store here. This resource can be passed to the CategoryInitialize() API |
fontIndexType | 'fnti' | Represents the font index. This resource is system reserved |
midiRsc | 'MIDI' | Palm MIDI compliant resource |
colorTableRsc | 'tclt' | UI Color Table resource |
constantRscType | 'tint' | Integer constant resource. ResLoadConstant() API can be called to load the this type of resource |
formRscType | 'tFRM' | UI Form resource |
strListRscType | 'tSTL' | This is a string list resource |
wrdListRscType | 'wrdl' | List of WORD (2 bytes) values |
defaultCategoryRscType | 'taic' | Launcher Category ID. Your application will be placed under the appropriate category on the Palm device |
binaryGeneralRscType | 'tbin' | General binary resource. You may store any raw data here |
After such a smart start, you can see how rich this game is. It's odd to say that, by using resources, you make all localization issues much easier. For custom launch codes, when you can't have global variables, a resource may be an ideal solution to work around it, and so forth. If you're already convinced, the next sections will guide you through the supporting API calls.
Searching Resource Databases
First of all, consider how to conduct a resources search. DataMgr.h defines the following functions for this purpose:
DmOpenRef DmNextOpenResDatabase(DmOpenRef dbP);
UInt16 DmFindResourceType(DmOpenRef dbP, DmResType resType,
UInt16 typeIndex);
UInt16 DmFindResource(DmOpenRef dbP, DmResType resType,
DmResID resID, MemHandle resH);
UInt16 DmSearchResource(DmResType resType, DmResID resID,
MemHandle resH, DmOpenRef *dbPP);
These functions expose various ways to get the desired results. Usually, resources are stored in PDB on a Palm device. When you request a specific resource, the Palm OS will start from recently opened databases. The DmNextOpenResDatabase function controls which database will be searched for. The first one in the search chain will be returned, passing NULL as a parameter. Actually, it is the last loaded resource database; for example, your application. Note, that in case of using overlays, the returned pointer will reference the overlay, not the base resource.
DmFindResource and DmFindResourceType run over a given database for specified resource parameters such as type, index, ID, or memory handle. In turn, DmSearchResource does its job over all open resource databases and returns a reference to the appropriate database.
Although Palm OS 6 still supports a "search chain" notion for backward compatibility, new applications should not rely on this. To illustrate what was said above, take a look at the following code sample:
...
DmOpenRef dbP = DmNextOpenResDatabase(NULL);
UInt16 nIdx = DmFindResourceType(dbP,'tSTR',1);
MemHandle hMem = DmGetResourceIndex(dbP,nIdx);
Char *pData = (Char*)MemHandleLock(hMem);
...
MemHandleUnlock(hMem);
This code snippet obtains a reference of the recent resource database (application itself in this case), searches for the string of index 1, and finally loads it by using a DmGetResourceIndex call. Here's a standard trick: First, obtain a resource index inside a database and then get it itself. Such a technique is useful when you need to enumerate some kind of resources and display them; for example, in some list.
The Data Manager exposes several functions to access resources stored in database:Getting Access to Resources
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 <>
{
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 <>
{
delete [] pszTestList[wIdx];
}
delete [] pszTestList;
}
This sample also gives you the internal structure of the 'tSTL' resource: 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. 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:The Last Piece
// 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.
|