Preface The structure of... Programming... References
   

Global variables
Function definitions

 

Palm(r) application

Preface

The Palm application has several responsibilities:

  1. Store channels and programmes coming from the Desktop application
    through the .tvg data file.
  2. Present the information above in a clear and user-friendly fashion.
  3. Transfer relevant information to the Palm built-in system application Date
    Book.

The data file mentioned above is transferred to the Palm Pilot through the Conduit.

Further information about creating the data file and transferring it to the Palm is found in

respective White Papers. This White Paper assumes that the data file is correctly created

and transferred to the Palm.

The structure of the Palm Pilot

Since the Palm operating system differs from ”regular” ones, like Windows or Mac OS, a

closer description is required for certain important parts.

The File System

A Palm Pilot has a very simple file system. Conventional files – text files, binary files

(*.exe) and so forth – does not exist. Instead, all data is stored in one large database [1].

This database is in its turn divided into several parts, where each installed application possesses

a certain part. The size of these databases is not statically defined, but can – and will –

change when the user uses the application.

Memory Management

Memory, or rather the constant shortage of the same, is one of the large setbacks when

using the Palm Pilot. This puts a lot of demands on the programmer’s consequence when

working with memory – for example allocation and de-allocation. However, the most

important and sometimes the most difficult thing is the new way of thinking - to make the

applications small, compact and functional.

Even if the memory management is strictly controlled by the API for the Palm OS, there is

always a risk that the programmer forgets to de-allocate the previously allocated memory

chunks. This always results in so called “memory leaks”; that is: small parts of the

memory “disappears” each time the application is executed [2].

It can also result in worse
cases; often resulting in complete “freeze”-state of the Palm Pilot,
where the user needs to
make a soft reset to continue working.

Events

All Palm OS-applications are controlled by so called ”events”. An example when an event

is generated is when the user taps his/her pen on a button on the screen. Then, the event

will be placed on the bottom of an ”event stack”, which will be emptied event by event. In

each of these steps, the command the event is supposed to generate is applied.

This means that the application is centred around an ”event listener” – a function which

spends its time waiting for an event to be generated, and when it recieves an event, it

delegates the command to the part of the application responsible for applying the actual

command.

This event listener is described in following sections.

Programming the Palm OS

In order to make the application smallest possible, many of the most used functions in the

C language are linked into the OS kernel. In addition to that, their names are also changed.

For that reason, the C standard differs in many cases from the one defined by the ANSI

task force. However, the most common data types and many functions remain the

identical to the ANSI standard.

Basic Data Structures

As we pointed out in previous chapters, the Palm OS cannot handle text files. For this

reason, we can’t simply store the data file (*.tvg) in the storage area and read from it when

we need. Instead, we have to convert the data into a format that can be handled by the

Palm OS.

What we need is a data type which contains several fields – for example ”programme

name”, ”channel”, ”date” and so forth [3].

The natural selection here is the C data type

struct. However, there is no possibility to store a struct with all necessary fields in

the database, which is why we have to define two struct:s : one for storing

(PackedProgram), and one containing all fields (Program):

typedef struct {

Boolean Favo;

Boolean Sel;

char Ch[1];

} PackedProgram;

typedef struct {

Boolean Favo;

Boolean Sel;

const char * Ch;

const char * Prg;

const char * Date;

const char * STime;

const char * ETime;

const char * Desc;

const char * SView;

}

In addition to this, a function converting PackedProgram structs to Program structs.

This function is described in coming sections.

These two data types together controls all the important data the application will present

to the user.

This means that the application is centred around an ”event listener” – a function which

spends its time waiting for an event to be generated, and when it recieves an event, it

delegates the command to the part of the application responsible for applying the actual

command.

This event listener is described in following chapters.

Global Variables and Constants

It is often desirable to avoid global variables as far as possible in the code. However,

sometimes it’s necessary to introduce them in order to make the code easier to understand.

On the other hand, constants are very common in the world of programming, and

contributes almost always to better coding.

In the following two sections, there is a list of the global variables and constants we have

introduced.

Constants

#define appFileCreator ’Tvgu’ [4]

This constant establishes a relation between the database you open or create and the

application.

#define appVersionNum 0x01

#define appPrefID 0x00

#define appPrefVersionNum 0x01

These constants are used for applying version numbers and misc. settings to the

application.

#define PrgDBType ’APPL’

#define PrgDBName "Programs-Tvgu"

#define datebookDBType ’DATA’

#define datebookDBName "DatebookDB"

The application demands two different databases; one user-defined for storage of

programmes, and one system database – the database of the Date Book. That’s why we

have to define constants to enable easy references to the different databases.

#define MAX_NO_PROGRAMS 100

Since we have to treat some arrays as global variables, we must be able to define the sizes

of them in advance. MAX_NO_PROGRAMS is a constant which controls how many

programmes can be stored for each channel. Of course, this constant is easily editable by

users in need of larger arrays!

Global Variables

const char * channels[MAX_NO_PROGRAMS + 2];

We only want our application to show the channels represented in the .tvg data file. In

order to do that, we have to store the channel names as strings (or more accurately as

char *) in an array, and later fill the Pop-up trigger in the main form. Since we want to be

able to have access to the channel names in several function, a global variable is

motivated for this array.

In addition, we add two extra slots in the array to be able to store the options “Favourites”

and “Selected”. [5]

int program_indices[MAX_NO_PROGRAMS];

This array is responsible for a connection between the storage index of the actual

programme in the database and the position in the main form table where it’s shown.

Example: the programme ”X-files” is stored at index 17 in the application

database, and is shown on line 3 in the table. This means that the content of

slot 2 in the array (all arrays are zero-bound) is the integer 17.

int lastProgram = 0;

int lastVisibleProgram = 0;

int firstVisibleProgram = 0;

These integers keep track which programs are shown in the table when the user uses the

scrollbar in the main form.

Boolean programsExists = false;

This boolean is used to check if there exist programs for the alternatives ”Favourite” and

”Selected”.

Functions

System Functions

PilotMain(Word cmd, Ptr cmdPBP, Word launchFlags);

This function is called when the user taps the application icon. In our case, the function

calls another, user defined function:

StarterPilotMain(Word cmd, Ptr cmdPBP, Word

launchFlags);

In the function below, the user’s OS version is approved for compability reasons, and

opens (or creates if the application is executed for the first time) the database for reading

(we don’t have to be able to write to the database!).

OpenOrCreateDB(&PrgDB, PrgDBType, appFileCreator,
dmModeReadWrite,0,PrgDBName, &created);

Next important function opens and initialises the application’s main form [6]

FrmGotoForm(MainForm);

MainForm is a variable, which keeps an integer, and is a unique identifier for form. After

that, the application enters the previously described event listener:


The Event Listener

AppEventLoop();

As we previously mentioned, this function will try to pop an event from the event stack

and then delegate the actual event’s command to another function. This will go on until

the event popped from the stack is of type appStopEvent.

AppEventLoop handles the following events:

· SysHandleEvent

· MenuHandleEvent

· AppHandleEvent

Of course, there has to be a way to figure out what kind of event you’re dealing with when

receiving one. The solution to this problem is to call system functions with the same name

as the event. When the function returns ’true’, not only was the event of that kind, but the

action connected to the event has already taken place in the function! The following

function is especially interesting:

AppHandleEvent(EventPtr eventP);

This function is the one that delegates the responsibility for carrying out the desired

command for the event. Among other things, this function checks if the event was raised

by a form opening; if that is the case, an event handler is connected to the form raising the

event.

Event Handlers

If the latter function delegated away its responsibility, these ones will actually carry out

any order given to them. Just as we concluded, each form has its own event handler,

which handles form-specific events. Establishing the connection between a pointer to a

form (frmP) and a callback function (MainFormHandleEvent) is done simply by

typing:

FrmSetEventHandler(frmP, MainFormHandleEvent);

The event handler is here expressed through the callback function

MainFormHandleEvent . This function handles events raised by objects in the form;

for example buttons being pushed, scrollings, pen-movements and so forth.

GUI Objects in Palm OS

No application is complete without a logical interface to the user. This is created easily

with the application ”Constructor”, which is integrated with the CodeWarrior-environment.

Some of the available objects are:

· Form

· Button

· Checkbox

· Label

· List

· Popup Trigger

· Table

The most basic and most used object of them all is Form, the object all other objects are

placed on. Our application has a number of different forms, some of which are described

in detail in the following sections.

The Main Form

This form handles the presentation of the programmes and the channels the .tvg data file

delivers. The form uses GUI objects according to the illustration Figure 1 below:

The Programme Info Form

When the user taps the pen on the programme title, a form with more detailed information

about the programme is shown. This form with marked GUI objects is shown in Figure 2:

References

Neil Rhodes, Julie McKeehan, David Pogue: Palm Programming. O’Reilly UK

Palm Pilot Devzone: www.palm.com/devzone

Notes

[1]: Actually, there are more than one database, but only one where conventional data – for example channels

and programmes – is stored. [back]

[2]: Naturally, this memory can be restored, but only through a ”hard reset”, where all stored data and

applications are lost. [back]

[3] A complete description of what these fields really are can be found in the documentation of the client application.
[back]

[4] This constant has to be application-unique. Possible duplicates is avoided through the possibility to register

the constant at the web page www.palm.com/devzone. [back]

[5] More detailed information about these options is found in the Client White Paper. [back]

[6] Forms are discussed in the GUI object section
. [back]