Errata

Palm Programming: The Developer's Guide

Errata for Palm Programming: The Developer's Guide

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released. If the error was corrected in a later version or reprint the date of the correction will be displayed in the column titled "Date Corrected".

The following errata were submitted by our customers and approved as valid errors by the author or editor.

Color key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted By Date submitted Date corrected
Printed
Page xix
The following text was added to the preface

How to Contact Us

We have tested and verified the information in this book to the best of our
ability, but you may find that features have changed (or even that we have
made mistakes!). Please let us know about any errors you find, as well as
your suggestions for future editions, by writing to:

O'Reilly & Associates, Inc.
101 Morris Street
Sebastopol, CA 95472
1-800-998-9938 (in the U.S. or Canada)
1-707-829-0515 (international/local)
1-707-829-0104 (FAX)

You can also send us messages electronically. To be put on the mailing list
or request a catalog, send email to:

info@oreilly.com

To ask technical questions or comment on the book, send email to:

bookquestions@oreilly.com

We have a web site for the book, where we'll list examples, errata, and any
plans for future editions. You can access this page at:

http://www.oreilly.com/catalog/9781565925250/

For more information about this book and others, see the O'Reilly web site:

http://www.oreilly.com

Anonymous    Aug 01, 2000
Printed
Page 26
In the tip

(http://www.gnu.org/fsf)

was changed to read:

(http://www.fsf.org)

Anonymous    Mar 01, 1999
Printed
Page 32
2nd paragraph

Satellite Forms, by SoftMagic,

now reads:

Satellite Forms, by Puma Technology

Anonymous    Mar 01, 1999
Printed
Page 32
Figure 2-10 has been added to the page.

Anonymous    Aug 01, 2000
Printed
Page 34
First paragraph,

At the time of this writing, the price tag for Satellite Forms
was $595 (making this the most expensive environment).

Now reads:

As of early 1999, the price tag for Satellite Forms was $369
(plus license fees for the runtime engine).

and,

It only runs on Windows and applications you create require a
runtime library on the Palm device (the runtime is free). After you
hand over the initial money, there is no additional cost to deploying
applications built with Satellite Forms.

now reads:

It only runs on Windows and applications you create require a
runtime library on the Palm device. There is a charge to license the
runtime library which can make it expensive to deploy applications
built with Satellite Forms.

and,

http://www.softmagic.com

now reads:

http://www.pumatech.com

Anonymous    Mar 01, 1999
Printed
Page 44

Change:

Users can upgrade to the 3.0 OS (including IR support and 2MB of memory) for
around $100 at the time of this writing. A user unwilling to spend that kind
of money is probably unwilling to buy your software.

to:

Users were able to upgrade to the 3.0 OS (including IR support and 2MB of
memory) for around $100 (although that upgrade is no longer available). A
user who was unwilling to spend that kind of money is probably unwilling to
buy your software.

Anonymous   
Printed
Page 71
In the code for PilotMain, at the bottom of the page,

Err err;

now reads:

Err err = 0;

Anonymous    Mar 01, 1999
Printed
Page 73
Example 4-3.

HelloWorldRsrc.h Created by Hand

now reads:

HelloWorldRsc.h Created by Hand

Anonymous    Mar 01, 1999
Printed
Page 73
In the code for PilotMain,

Err err;

now reads:

Err err = 0;

Anonymous    Mar 01, 1999
Printed
Page 75
In figure 4-3, the "Main Event Loop" column, the function

SysHandleEvent is listed at both the top and bottom of the loop. This
doesn't match the code. The copy at the bottom of the loop has been
removed. In the same figure,

"FnnDispatchEvent"

now reads:

"FrmDispatchEvent".

Anonymous    Mar 01, 1999
Printed
Page 76
Same changes as on page 75, in figure 4-4.

Anonymous    Mar 01, 1999
Printed
Page 78
In the code for MyCallback at the bottom of the page, an #endif

was missing.

CALLBACK_EPILOGUE
return myReturnResult;

now reads:

CALLBACK_EPILOGUE
#endif
return myReturnResult;

Anonymous    Mar 01, 1999
Printed
Page 81
The first word of the last line of example 4-9 was missing an "e"

"MyFormHandlEvent" now reads "MyFormHandleEvent".

Anonymous    Mar 01, 1999
Printed
Page 83

Halfway down example 4-11, a comment in the right column read:

"Tap on Beep Another Item"

It now reads:

"Tap on Beep More"

Anonymous    Mar 01, 1999
Printed
Page 86
In the paragraph after first code block, the two occurrences of 15

are now 14.

Anonymous    Mar 01, 1999
Printed
Page 88

The following text used to read:

MemMove(void *from, void *to, ULong numBytes);

now it reads:

MemMove(void *to, void *from, ULong numBytes);

Anonymous    Aug 01, 2000
Printed
Page 89
In the first section, there are three definitions of launch codes

which are wrong. They have been changed as follows:

change sysAppLaunchFind to sysAppLaunchCmdFind
change sysAppLaunchGoTo to sysAppLaunchCmdGoTo
change sysAppLaunchNormal to sysAppLaunchCmdNormalLaunch

Anonymous    Mar 01, 1999
Printed
Page 100
First warning

... pass a string with one space init (" ") instead.

now reads:

... pass an empty string ("") instead.

And,

FrmCustomAlert(MyAlertID, "string", " ", NULL)

now reads:

FrmCustomAlert(MyAlertID, "string", "", NULL)

Anonymous    Mar 01, 1999
Printed
Page 102
About half way down the page

The statement:

ControlPtr checkbox = FrmGetObjectPtr(frm,
FrmGetObjectIndex(frm, TrueOrFalseCheckbox) );

does not compile in C++ due to a missing cast.

The solution is to change it to:
ControlPtr checkbox = (ControlPtr) FrmGetObjectPtr(frm,
FrmGetObjectIndex(frm, TrueOrFalseCheckbox));

Anonymous   
Printed
Page 107

The following text used to read:

ErrNonFatalDisplayif(FrmGetObjectType(frm, objectIndex <> frmFieldObj,
"Form object isn't a field"

now it reads:

ErrNonFatalDisplayIf(FrmGetObjectType(frm, objectIndex) != frmFieldObj,
"Form objects isn't a field");

Anonymous    Aug 01, 2000
Printed
Page 109
In the first line on the page,

FrmCopyLabel(FrmGetActiveForm(), MainMyLabel, "newText");

now reads:

FrmCopyLabel(frm, MainMyLabel, "newText");

Anonymous    Mar 01, 1999
Printed
Page 113
Last three bullet items have been changed to

*A null-terminated prefix string which SysStringByIndex
prepends to each of the strings in the list.

*A two-byte count of the number of strings in the list

*The null-terminated strings concatenated together

(SysStringByIndex is in the function-style font.)

Anonymous    Jan 01, 1999
Printed
Page 113

The following text used to read:

Use LstSetArrayChoices to pass...

now it reads:

Use LstSetListChoices to pass...

Anonymous    Aug 01, 2000
Printed
Page 114
The first code block has been changed to

typedef struct StrListType {
char prefixString; // we assume it's empty
char numStringsHiByte; // we assume it's 0
char numStrings; // low byte of the count
char firstString[1]; // more than 1-all concated together
} *StrListPtr;

Anonymous    Jan 01, 1999
Printed
Page 114
This note was added after the first code block

This sample assumes that the prefix string is empty,
and that there are no more than 255 strings in the
string list. For a sample that has been modified to
correctly handle more general cases, see
http://www.calliopeinc.com/PalmProgramming.

Anonymous    Jan 01, 1999
Printed
Page 114

The following text used to read:

StrLstPtr stringsPtr = = MemHandleLock(gStringsHandle);

now it reads:

StrLstPtr stringsPtr = MemHandleLock(gStringsHandle);

Anonymous    Aug 01, 2000
Printed
Page 115
In the definition of ListDrawFunc, delete

FormPtr frm = FrmGetActiveForm();
ListPtr list = FrmGetObjectPtr(frm,
FrmGetObjectIndex(frm, MainMyList));

Anonymous    Mar 01, 1999
Printed
Page 117

You shouldn't draw in a field until the form has been drawn.

static FieldPtr SetFieldTextFromHandle(Word fieldID, Handle txtH)

has been changed to:

static FieldPtr SetFieldTextFromHandle(Word fieldID, Handle txtH, Boolean
redraw)

and:

FldDrawField(fldP);

has been changed to:

if (redraw)
FldDrawField(fldP);

Anonymous    Dec 01, 2000
Printed
Page 118

Same rationale as the change to p. 117.

static FieldPtr SetFieldTextFromStr(Word fieldID, CharPtr strP)

has been changed to:

static FieldPtr SetFieldTextFromStr(Word fieldID, CharPtr strP, Boolean
redraw)

and:

return SetFieldTextFromHandle(fieldID, txtH)

has been changed to:

return SetFieldTextFromHandle(fieldID, txtH, redraw)

and:

static void ClearFieldText(Word fieldID)
{
SetFieldTextFromHandle(fieldID, NULL);
}

has been changed to:

static void ClearFieldText(Word fieldID, Boolean redraw)
{
SetFieldTextFromHandle(fieldID, NULL, redraw);
}

Anonymous    Dec 01, 2000
Printed
Page 120
Second paragraph, the pictures of the prevFieldChr and nextFieldChr have

been changed. Their direction has been changed (now the first character opens
downward while the second opens up) and they are more narrow.

Anonymous    Jan 01, 1999
Printed
Page 128
The second code block, function CustomerHandleEvent(): add the

following line:

Boolean result = false;

before the line beginning if (event-.eType == ctlSelectEvent &&

and,
return true; // don't bail out if they cancel the delete dialog

now reads,

result = true; // don't bail out if they cancel the delete dialog

and,
return true;

now reads:

result = true;

and,
return false;

now reads:

result = false;

Anonymous    Mar 01, 1999
Printed
Page 128

The following text used to read:

return = true; // don't bail out if they cancel the delete
dialog

now it reads:

result = true; // don't bail out if they cancel the delete

The following text used to read:

return = true;

now it reads:

result = true;

The following text used to read:

return = false;

now it reads:

return result;

Anonymous    Aug 01, 2000
Printed
Page 129

Same rationale.

SetFieldTextFromStr(CustomerNameField, (CharPtr) theCustomer.name);
SetFieldTextFromStr(CustomerAddressField,
(CharPtr) theCustomer.address);
SetFieldTextFromStr(CustomerCityField, (CharPtr) theCustomer.city);
SetFieldTextFromStr(CustomerPhoneField, (CharPtr) theCustomer.phone);

has been changed to:

SetFieldTextFromStr(CustomerNameField, (CharPtr) theCustomer.name,
true);
SetFieldTextFromStr(CustomerAddressField,
(CharPtr) theCustomer.address, true);
SetFieldTextFromStr(CustomerCityField, (CharPtr) theCustomer.city,
true);
SetFieldTextFromStr(CustomerPhoneField, (CharPtr) theCustomer.phone,
true);

Anonymous    Dec 01, 2000
Printed
Page 131

Same:

SetFieldTextFromStr(ItemQuantityField, quantityString);

has been changed to:

SetFieldTextFromStr(ItemQuantityField, quantityString, false);

Anonymous    Dec 01, 2000
Printed
Page 139
The third bullet, second sentence: "This attribute contains a

4-bit category: ..." The colon should be a comma.

Anonymous    Mar 01, 1999
Printed
Page 139
The last bullet, replace the word "archived" with the word

"dirty"

Anonymous    Mar 01, 1999
Printed
Page 144-145

DmResetRecordStates is dangerous to call
Replace:
If for some reason your code must close a database while you have locked or
busy records, call DmResetRecordStates before calling DmCloseDatabase:

err = DmResetRecordStates(gDB);
err = DmCloseDatabase(gDB);

The Data Manager doesn't do this resetting automatically from
DmCloseDatabase because of the performance penalty. The philosophy is that
you shouldn't penalize the vast majority of applications that have released
and unlocked all their records. Instead, force the minority of applications
to make the extra call and incur the speed penalty in these rare cases.

with:
Thus, make sure that you unlock and release all records before calling
DmCloseDatabase.

There is a call, DmResetRecordStates, which is advertised to reset locked
and busy records. However, in most versions of the OS, it has a bug that
causes a fatal system alert if your code calls it.

The OS does reset the locked and busy records in the rare case where a
system reset occurs while you have a database opens. It calls
DmResetRecordStates to do this resetting, but the bug doesn't manifest
itself when called by the OS in this case.

Anonymous   
Printed
Page 148
7th line from the bottom,

MemHandleUnlock(theOrderHandle)

now reads:

MemHandleUnlock(theRecordHandle)

Anonymous    Mar 01, 1999
Printed
Page 150
Second code block, third line: removed the errant final "i" in

DoSomethingReadOnlyi so the line now reads:

DoSomethingReadOnly(s->field);

Anonymous    Jan 01, 1999
Printed
Page 150
The first line

sizeof(MyRecordStruct)

now reads:

sizeof(newRecord)

and,
DmWrite(gDB, s, 0, &theStructure, sizeof(theStructure));

now reads:

DmWrite(s, 0, &theStructure, sizeof(theStructure));

Anonymous    Mar 01, 1999
Printed
Page 152
First code block after the heading "Iterating Through the Records in a

Database or Category", fifth line:

for (i = 0; i < totalItems; i++) {

now reads

for (i = 0; i < totalItems; i++, recordNum++) {

Anonymous    Jan 01, 1999
Printed
Page 154
Third sentence.

Instead, the archived bit of the record is set, and ...

now reads:

The deleted bit is set (although the memory chunk is
maintained), and ...

Anonymous    Mar 01, 1999
Printed
Page 157
The code example for "Initialize the field with the handle"

There are several bugs here. First, recPtr is undefined. Then, the if (fld)
should actually be if (oldTextHandle). Finally, the parameter for the StrLen()
call in the last line of the example should be recPtr->textField. And
don't forget to MemHandleUnlock(theRecordHandle), otherwise it maybe
impossible to resize the handle during the editing.

Change the entire code block that starts with:
typedef struct {
to:

typedef struct {
int field;
// other fields
char textField[1]; // may actually be longer, null-terminated
} MyRecType;

Handle theRecordHandle;
Handle oldTextHandle = FldGetTextHandle(fld);
UInt theTextLength;
UInt textOffset = offsetof(MyRecType, textField);

if (oldTextHandle) {
// must dispose of the old handle, or we'll leak memory
MemHandleFree(oldTextHandle);
}
theRecordHandle = DmGetRecord(gDB, recordNumber);
theTextLength = (UInt) MemHandleSize(theRecordHandle) - textOffset;
FldSetText(fld, theRecordHandle, textOffset, theTextLength);

Anonymous    Mar 01, 1999
Printed
Page 182
Figure 7-5, the arrow saying

"converted by PilotRez"

now reads:

"converted by PalmRez"

Anonymous    Mar 01, 1999
Printed
Page 183
Last and second-to-last paragraphs contain three references to

"PalmRez". The 3 occurences to have been changed to read "Rez".

Anonymous    Mar 01, 1999
Printed
Page 184
The first word, "PalmRez," now reads, "Rez".

Anonymous    Mar 01, 1999
Printed
Page 211
In example 8-1, near middle of page, the following line was

deleted:

TblSetItemInt(tableP, i, 5, i * 2);

Anonymous    Mar 01, 1999
Printed
Page 212
In "column 2", second sentence

on for even row numbers and off for odd row numbers

now reads:

off for even row numbers and on for odd row numbers

Anonymous    Mar 01, 1999
Printed
Page 214
The last code block, function StartApplication

Delete:
#ifdef __GNUC__
CALLBACK_PROLOGUE
#endif

and delete:

#ifdef __GNUC__
CALLBACK_EPILOGUE
#endif

and add two lines, changing:

gHandles[i][j] = MemHandleNew(1);

to:

gHandles[i][j] = MemHandleNew(1);
if (!gHandles[i][j])
return false

Anonymous    Mar 01, 1999
Printed
Page 219
The word "Scrolling" has been added to the bullet list at the

top.

Anonymous    Mar 01, 1999
Printed
Page 237
In the first paragraph after first code block,

finds the unique idea

now reads:

finds the unique ID

and the second reference to unique idea also reads unique ID.

Anonymous    Mar 01, 1999
Printed
Page 237
Middle of page,

MemSet(&event, 0, sizeof(EventType))

now reads:

MemSet(&event, sizeof(EventType), 0)

Anonymous    Mar 01, 1999
Printed
Page 265

Buffer can overflow depending on the LAT/LON.

char s[10];

has been changed to:

char s[11];

Anonymous    Dec 01, 2000
Printed
Page 266
The following text used to read:

// Otherwise, we want to read immediately
if (s[5] == '0' || s[5] == '5')

now it reads:

// Otherwise, we want to read immediately
if (s[7] == '0' || s[7] == '5')

Anonymous    Aug 01, 2000
Printed
Page 266

The following comment was wrong:

// 5 is E or W for Lat direction, 6 is lon

has been changed to:

// 6 is E or W for Lon direction, 5 is lon

Anonymous    Dec 01, 2000
Printed
Page 269
Under "A networking reference number", deleted the third sentence

(starting "The default value for..."

Anonymous    Jan 01, 1999
Printed
Page 328
The following text used to read:

#define kMinorVersion 0

now it reads:

#define kMinorVersion 1

Anonymous    Aug 01, 2000
Printed
Page 334

The following text used to read:

Proving ChangeConduit works

now it reads:

Proving ConfigureConduit works

The following text used to read:

... Bringing this dialog up proves that your
ChangeConduit function gets called.

now it reads:

... Bringing this dialog up proves that your
ConfigureConduit function gets called.

Anonymous    Aug 01, 2000
Printed
Page 338
In the section "Opening a Database", the description of "openmode" now

reads:
Use (eDbRead | eDbShowSecret) to read all
records, including private ones. Use (eDbRead
| eDbWrite | eDbShowSecret) to be able to
rite and/or delete records.

(The initial "d" has been changed to "eD" in five instances.)

Anonymous    Jan 01, 1999
Printed
Page 342
Under "Finding the Number of Records"

Two instances of
"Word"
have been changed to
"WORD"

Anonymous    Jan 01, 1999
Printed
Page 347

The following text used to read:

Word SyncHHtoHostWord(Word value)
DWord SyncHHToHostDWord(DWord value)

now it reads:

WORD SyncHHToHostWord(WORD value)
DWORD SyncHHToHostDWord(DWORD value)

The following text used to read:

Word SyncHostToHHWord(Word value)
DWord SyncHostToHHDWord(DWord value)

now it reads:

WORD SyncHostToHHWord(Word value)
DWORD SyncHostTOHHDWord(DWORD value)

The following text used to read:

SyncHHtoHostWord(0x0102) returns 0x0201

now it reads:

SyncHHToHostWord(0x0102) returns 0x0201

Anonymous    Aug 01, 2000
Printed
Page 350
change underlines to hyphens

#define customerDBName "Customers_Sles"
#define orderDBName "Orders_Sles"
#define productDBName "Products_Sles"

now reads:

#define customerDBName "Customers-Sles"
#define orderDBName "Orders-Sles"
#define productDBName "Products-Sles"

Anonymous    Mar 01, 1999
Printed
Page 366
In the table at the bottom of the page, on the second data line,

the tag on the item in the right-hand column is missing a colon. It
now reads "Address:"

Index Changes:

"Puma Technology's Satellite Forms" has been added to page 452.

"SoftMagic's Satelline Forms" has been removed from page 454.

"SyncReadNextModifiedRecInCatgegory()" has been combined with
the entry right above it, on page 455.

"sysAppLaunchFind()", "sysAppLaunchGoTo()", and "sysAppLaunchNormal()"

have been changed to:

"sysAppLaunchCmdFind()", sysAppLaunchCmdGoTo()", and
"sysAppLaunchCmdNormalLaunch()" respectively, thus moving the page
numbers from the old entries to existing entries a little bit above, on
page 455.

Because of these changes, page breaks changed on pages 452 through 455.

Anonymous    Mar 01, 1999
Printed
Page 409

Figure 13-2 had a line from CSynchronizer to CPcMgr. It has been removed
as CSynchronizer does not inherit from anything.

Anonymous    Dec 01, 2000
Printed
Page 436
"http://wademan.com" has been changed to "http://www.wademan.com"

Anonymous    Jan 01, 1999