Palm Programming on Mac OSX
Get the Toolset
1) Install XCode Developer Tools from Apple
2) Install the PRC-Tools
http://www.zenonez.com/prctoolsx/
3) Install and customize a Palm X-Tools Template
http://www.blackmac.de/download/PRC-Template.dmg
http://www.cocoadev.com/...l?XcodeProjectTemplates
4) Install the Mac Palm Emulator
http://www.palmos.com/dev/tools/emulator/
5) Install RePose on Mac Palm Emulator to automate testing
http://mobile.eric-ponce...palm&product=RePose
6) Compile from XCode using a template and then run on the Mac Emulator Using
RePose
Sample Code
A trivial encryption program that uses the low security XOR algorithm. 
PilRC
CodeHere is the PilRC text document that describes the GUI. #include "TestPalm.h" /****************************************************************** TestPalm.rcp
TestPalm Created by Jeff Louie on Sat Oct 30 2004.
Copyright (c) 2004 __MyCompanyName__. All rights reserved.
*******************************************************************/ ICON "TestPalmIcon.bmp" // Forms and Alerts
FORM ID MainForm AT (0 0 160 160)
USABLE
NOSAVEBEHIND
NOFRAME
MENUID MainMenuBar BEGIN
TITLE "TestPalm"
BUTTON "Encrypt" ID 1001 AT (34 90 AUTO AUTO) FONT 1
BUTTON "Decrypt" ID 1002 AT (94 90 AUTO AUTO) FONT 1
LABEL "Key" AUTOID AT (8 24) FONT 0
LABEL "Plain Text" AUTOID AT (8 42) FONT 0
LABEL "Encrypted" AUTOID AT (8 113) FONT 0
FIELD ID 1006 AT (60 21 87 14) USABLE EDITABLE UNDERLINED SINGLELINE MAXCHARS 80 LEFTALIGN
FIELD ID 1007 AT (60 41 89 39) USABLE EDITABLE UNDERLINED MULTIPLELINES MAXCHARS 80 LEFTALIGN
FIELD ID 1008 AT (60 113 88 44) USABLE NONEDITABLE UNDERLINED MULTIPLELINES MAXCHARS 80 LEFTALIGN
GRAFFITISTATEINDICATOR AT (148 147)
END FORM ID AboutForm AT (0 0 160 160)
USABLE
SAVEBEHIND
BEGIN
TITLE "About"
BUTTON "OK" ID AboutOKButton AT (65 131 36 12) USABLE LEFTANCHOR FRAME
LABEL "TestPalm\r\r© 2004 by Jeff Louie" ID AboutMessageLabel AT (5 24) USABLE FONT 1
END
// Menu
MENU MenuMenu
BEGIN
PULLDOWN "About"
BEGIN
MENUITEM "About TestPalm..." ID MenuAboutThis "I"
END
END// Alert
ALERT ID alertMemory
WARNING
BEGIN
TITLE "Warning"
MESSAGE "Program Error: Out of Memory!"
BUTTONS "OK"
END ALERT ID alertInvalidLength
WARNING
BEGIN
TITLE "Warning"
MESSAGE "Invalid ^1: Length is Zero or >255 Character(s)"
BUTTONS "OK"
END ALERT ID alertDebug
INFORMATION
BEGIN
TITLE "Debug"
MESSAGE "Message: ^1"
BUTTONS "OK"
END HeadersHere are the headers. /****************************************************************** TestPalm.h
TestPalm Created by Jeff Louie on Sat Oct 30 2004.
Copyright (c) 2004 __MyCompanyName__. All rights reserved.
*******************************************************************/
#define DEBUG 1
#define MAX_STRING_LENGTH 255 #define MainForm 1000
#define MainMessageLabel 1001
#define AboutForm 1100
#define AboutOKButton 1101
#define AboutMessageLabel 1102
#define NewButton 1104
#define MainMenuBar 1000
#define MenuMenu 1000
#define MenuAboutThis 1000
// Resource: tFRM 1000
#define btnEncrypt 1001
#define btnDecrypt 1002
#define fldKey 1006
#define fldPlain 1007
#define fldEncrypt 1008
#define alertMemory 1000
#define alertInvalidLength 1001
#define alertDebug 1002 Code FileHere is the code file. /****************************************************************** TestPalm.c
TestPalm Created by Jeff Louie on Sat Oct 30 2004.
Copyright (c) 2004 __MyCompanyName__. All rights reserved.
*******************************************************************/
// standard include for PalmSDK3.5+
#include <PalmOS.h> // StrIToA // define resource constants in .h
#include "TestPalm.h" // BEGIN ALERTS static void SignalInvalidKeyLength() {
FrmCustomAlert(alertInvalidLength," Key ",NULL,NULL);
} static void SignalInvalidPlainText() {
FrmCustomAlert(alertInvalidLength," Plain Text ",NULL,NULL);
}static void SignalInvalidEncryptedText() {
FrmCustomAlert(alertInvalidLength," Encryted Text ",NULL,NULL);
}// END ALERTS // BEGIN UTILITY FUNCTIONS static void Debug(char *message) {
FrmCustomAlert(alertDebug,message,NULL,NULL);
}#ifdef DEBUG
static void Assert(BOOL b, char* message) {
if (!b) {Debug(message);}
}
#else
static void Assert(BOOL b, char* message) {;}
#endifstatic void SignalOutOfMemory() {
FrmAlert(alertMemory);
}// GetObjectPointer
// Get a MemPtr from object in Active Form by object ID
// ASSERT valid object ID for Active Form
static MemPtr GetObjectPointer(UInt16 objectID) {
FormType *frmP;
frmP= FrmGetActiveForm();
return (FrmGetObjectPtr(frmP,FrmGetObjectIndex(frmP,objectID)));
} // GetFieldText Gets text (char*) from a text field in Active Form by object ID
// ASSERT object is a FieldType and valid ID for Active Form
// returns read only const char * client should call StrCopy immediately
// field owns this string and text may change
static const char* GetFieldText(const UInt16 fldID) {
FieldType *fldP;
fldP= (FieldType*)GetObjectPointer(fldID);
if (FldGetTextLength(fldP) > 0 )
{
return FldGetTextPtr(fldP);
}
else {return "";}
}
// SetFieldText eg someField.SetText(message)
// Sets the text in field
// ASSERT object is FieldType and valid ID for active form
// ASSERT message != NULL
static void SetFieldText(UInt16 fldID, char* message) {
MemHandle oldTextH;
char *str;
FieldType *fieldP;
MemHandle textH;
fieldP= (FieldType*)GetObjectPointer(fldID);
textH= MemHandleNew(StrLen(message)+1);
if (!textH) {
SignalOutOfMemory();
return;
}
str= MemHandleLock(textH); // lock memory and get pointer
StrCopy(str,message);
MemHandleUnlock(textH);
oldTextH= FldGetTextHandle(fieldP);
FldSetTextHandle(fieldP,textH); // field must release handle on exit
FldDrawField(fieldP);
if (oldTextH) {MemHandleFree(oldTextH);}
}// END UTILITY FUNCTIONS // BEGIN ALGO // note if char == key --> '\0' and array will not display properly as char*
// ASSERT strlen(encrypted) == strlen(plain)
// ASSERT strlen(key)>0
// return length of encrypted string
static int EncryptIt(int *encrypted, const char *plain, const char *key) {
int keyLength= StrLen(key);
int plainLength= StrLen(plain);
int iKey=0;
int i;
Assert((keyLength>0),"Pre-condition violation in EncryptIt");
for (i=0;*plain;i++) {
*encrypted++= *plain++ ^ key[iKey++];
if (iKey==keyLength) {iKey=0;}
}
return i; // i should == plainLength
}// stops at first null char
// use c library first parameter is lho
static void IntToCharArray(char *out, const int *in) {
while(*in) {
*out++= (char)(*in++);
}
*out= '\0';
}// ASSERT strlen(encrypted) == strlen(plain)
// ASSERT strlen(key)>0
// use c library first parameter is lho
static void DecryptIt(char * plain, const int* encrypted,const char * key, int lengthString) {
int keyLength= StrLen(key);
int iKey= 0;
int i;
for (i=0;i<lengthString && i<MAX_STRING_LENGTH;i++) {
*plain++= *encrypted++ ^ key[iKey++];
if (iKey==keyLength) {iKey=0;}
}
*plain= '\0';
return;
}
// END ALGO // BEGIN INIT/DISPOSE // app init function
static Err AppStart(void)
{
//init stuff here
return errNone;
}// app dispose function
static void AppStop(void)
{
// clean up any open forms here to avoid memory leak
FrmCloseAllForms();
}// END INIT/DISPOSE // BEGIN EVENT HANDLERS // our form handle event handler, set up in AppHandleEvent
static Boolean MainFormHandleEvent(EventPtr eventP) {
Boolean handled = false;
FormType *frmP;
char *messageC= "";
char key[MAX_STRING_LENGTH+1];
char plain[MAX_STRING_LENGTH+1];
char encrypt[MAX_STRING_LENGTH+1];
int lenKey, lenPlain;
static lenEncrypted=0;
static int encryptAsInt[MAX_STRING_LENGTH+1]; // internal storage encrypted text
switch (eventP->eType) {
case ctlSelectEvent:
switch (eventP->data.ctlSelect.controlID) {
case btnEncrypt:
lenKey= StrLen(GetFieldText(fldKey));
if (lenKey <1 || lenKey > MAX_STRING_LENGTH) {
SignalInvalidKeyLength();
break;
}
lenPlain= StrLen(GetFieldText(fldPlain));
if (lenPlain <1 || lenPlain > MAX_STRING_LENGTH) {
SignalInvalidPlainText();
break;
}
StrCopy(key,GetFieldText(fldKey));
StrCopy(plain,GetFieldText(fldPlain));
lenEncrypted= EncryptIt(encryptAsInt,plain,key);
IntToCharArray(encrypt,encryptAsInt);
SetFieldText(fldEncrypt,encrypt); // may be truncated by null char
SetFieldText(fldPlain,messageC); // clear field
break;
case btnDecrypt:
lenKey= StrLen(GetFieldText(fldKey));
if (lenKey <1 || lenKey > MAX_STRING_LENGTH) {
SignalInvalidKeyLength();
break;
}
StrCopy(key,GetFieldText(fldKey));
DecryptIt(plain, encryptAsInt, key, lenEncrypted);
SetFieldText(fldPlain,plain);
SetFieldText(fldEncrypt,messageC);
break;
default:
break;
}
break;
case menuEvent:
if (eventP->data.menu.itemID == MenuAboutThis) {
MenuEraseStatus(0); // Clear the menu status from the display.
frmP = FrmInitForm(AboutForm);
FrmDoDialog(frmP); // Display the About Box.
FrmDeleteForm(frmP);
handled = true;
break;
}
break;
case frmOpenEvent:
frmP = FrmGetActiveForm();
FrmDrawForm(frmP);
handled = true;
break; default:
break;
}
return handled;
} // application event handler
// load resources and set up callbacks for form events here
static Boolean AppHandleEvent(EventPtr eventP) {
Boolean handled = false;
FormType *frmP; if (eventP->eType == frmLoadEvent) {
// Initialize and activate the form resource.
frmP = FrmInitForm(eventP->data.frmLoad.formID);
FrmSetActiveForm(frmP);
// set up app callback event handler MainFormHandleEvent
if (eventP->data.frmLoad.formID == MainForm)
FrmSetEventHandler(frmP, MainFormHandleEvent);
handled = true;
}
else if (eventP->eType == frmOpenEvent) {
// Load and display the form resource.
frmP = FrmGetActiveForm();
FrmDrawForm(frmP);
handled = true;
}
else if (eventP->eType == appStopEvent) {
// unload the form resource.
frmP = FrmGetActiveForm();
FrmEraseForm(frmP);
FrmDeleteForm(frmP);
handled = true;
}
return(handled);
} // main entry point palm application
// UsrInterfaceApplicationShell (UIAS) passes launch code to PilotMain
// such as sysAppLaunchCmdNormalLaunch then ignore cmdPBP and ignore launchFlags
// such as sysAppLaunchCmdFind then use cmdPBP as pointer to text string
UInt32 PilotMain(UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags) {
EventType event;
Err err = 0;
switch (cmd) {
case sysAppLaunchCmdNormalLaunch:
err= AppStart();
if (err) return err;
// init OK so send frmLoadEvent and frmOpenEvent
// pass constant for MainForm resource
FrmGotoForm(MainForm);
// loop until get appStopEvent
do {
UInt16 MenuError;
EvtGetEvent(&event, evtWaitForever); // evtWaitForever doze until new event if (! SysHandleEvent(&event)) // system events eg. power off
if (! MenuHandleEvent(0, &event, &MenuError)) // menu events return true if done
if (! AppHandleEvent(&event)) // load resources and set up callbacks for form events
// mini loop default ends in FrmHandleEvent
FrmDispatchEvent(&event); // pass to app callbacks or OS default FrmHandleEvent } while (event.eType != appStopEvent);
AppStop();
break;
// ignore other cmds
default:
break;
}
return(err);
} // END EVENT HANDLERS |