Hi
I am working through a table example and it compiles fine, but at run time I
get the following error.
Table.c Line:2153, Invalid Parameter
The program is not called Table.c and the code only contains 1566 lines.
Where is this error coming from?
Below is my code minus the resource file.
------------------------------------
// CH.2 The super-include for the Palm OS
#include <Pilot.h>
// CH.5 Added for the call to GrfSetState()
#include <Graffiti.h>
// CH.3 Our resource file
#include "Contacts_res.h"
// CH.4 Prototypes for our event handler functions
static Boolean contactDetailHandleEvent( EventPtr event );
static Boolean aboutHandleEvent( EventPtr event );
static Boolean enterTimeHandleEvent( EventPtr event );
static Boolean contactListHandleEvent( EventPtr event );
static Boolean menuEventHandler( EventPtr event );
// CH.4 Constants for ROM revision
#define ROM_VERSION_2 0x02003000
#define ROM_VERSION_MIN ROM_VERSION_2
// CH.5 Prototypes for utility functions
static void newRecord( void );
static VoidPtr getObject( FormPtr, Word );
static void setFields( void );
static void getFields( void );
static void setText( FieldPtr, CharPtr );
static void getText( FieldPtr, VoidPtr, Word );
static void setDateTrigger( void );
static void setTimeTrigger( void );
static void setTimeControls( void );
static Int sortFunc( CharPtr, CharPtr, Int );
static void drawTable( void );
static void drawCell( VoidPtr table, Word row, Word column,
RectanglePtr bounds );
// CH.5 Our open database reference
static DmOpenRef contactsDB;
static ULong numRecords;
static UInt cursor;
static Boolean isDirty;
static VoidHand hrecord;
// CH.5 Constants that define the database record
#define DB_ID_START 0
#define DB_ID_SIZE (sizeof( ULong ))
#define DB_DATE_TIME_START (DB_ID_START +\
DB_ID_SIZE)
#define DB_DATE_TIME_SIZE (sizeof( DateTimeType ))
#define DB_FIRST_NAME_START (DB_DATE_TIME_START +\
DB_DATE_TIME_SIZE)
#define DB_FIRST_NAME_SIZE 16
#define DB_LAST_NAME_START (DB_FIRST_NAME_START +\
DB_FIRST_NAME_SIZE)
#define DB_LAST_NAME_SIZE 16
#define DB_PHONE_NUMBER_START (DB_LAST_NAME_START +\
DB_LAST_NAME_SIZE)
#define DB_PHONE_NUMBER_SIZE 16
#define DB_RECORD_SIZE (DB_PHONE_NUMBER_START +\
DB_PHONE_NUMBER_SIZE)
// CH.6 Storage for the record's date and time in expanded form
static DateTimeType dateTime;
static Word timeSelect;
#define NO_DATE 0
#define NO_TIME 0x7fff
// CH.7 The error exit macro
#define errorExit(alert) { ErrThrow( alert ); }
// CH.7 The sort order variable and constants
static Int sortBy;
// CH.7 NOTE: These items match the popup list entries!
#define SORTBY_DATE_TIME 0
#define SORTBY_FIRST_NAME 1
#define SORTBY_LAST_NAME 2
// CH.8 Table constants
#define TABLE_NUM_COLUMNS 3
#define TABLE_NUM_ROWS 11
#define TABLE_COLUMN_DATE 0
#define TABLE_COLUMN_TIME 1
#define TABLE_COLUMN_NAME 2
#define BLACK_UP_ARROW "\x01"
#define BLACK_DOWN_ARROW "\x02"
#define GRAY_UP_ARROW "\x03"
#define GRAY_DOWN_ARROW "\x04"
// CH.2 The main entry point
DWord PilotMain( Word cmd, Ptr, Word )
{
DWord romVersion; // CH.4 ROM version
FormPtr form; // CH.2 A pointer to our form structure
EventType event; // CH.2 Our event structure
Word error; // CH.3 Error word
// CH.4 Get the ROM version
romVersion = 0;
FtrGet( sysFtrCreator, sysFtrNumROMVersion, &romVersion );
// CH.4 If we are below our minimum acceptable ROM revision
if( romVersion < ROM_VERSION_MIN )
{
// CH.4 Display the alert
FrmAlert( LowROMVersionErrorAlert );
// CH.4 PalmOS 1.0 will continuously re-launch this app
// unless we switch to another safe one
if( romVersion < ROM_VERSION_2 )
{
AppLaunchWithCommand( sysFileCDefaultApp,
sysAppLaunchCmdNormalLaunch, NULL );
}
return( 0 );
}
// CH.2 If this is not a normal launch, don't launch
if( cmd != sysAppLaunchCmdNormalLaunch )
return( 0 );
// CH.5 Create a new database in case there isn't one
if( ((error = DmCreateDatabase( 0, "ContactsDB-PPGU", 'PPGU',
'ctct',
false )) != dmErrAlreadyExists) && (error != 0) )
{
// CH.5 Handle db creation error
FrmAlert( DBCreationErrorAlert );
return( 0 );
}
// CH.5 Open the database
contactsDB = DmOpenDatabaseByTypeCreator( 'ctct', 'PPGU',
dmModeReadWrite );
// CH.5 Get the number of records in the database
numRecords = DmNumRecords( contactsDB );
// CH.5 Initialize the record number
cursor = 0;
// CH.7 Choose our starting page
// CH.5 If there are no records, create one
if( numRecords == 0 )
{
newRecord();
FrmGotoForm( ContactDetailForm );
}
else
FrmGotoForm( ContactListForm );
// CH.7 Begin the try block
ErrTry {
// CH.2 Our event loop
do
{
// CH.2 Get the next event
EvtGetEvent( &event, -1 );
// CH.2 Handle system events
if( SysHandleEvent( &event ) )
continue;
// CH.3 Handle menu events
if( MenuHandleEvent( NULL, &event, &error ) )
continue;
// CH.4 Handle form load events
if( event.eType == frmLoadEvent )
{
// CH.4 Initialize our form
switch( event.data.frmLoad.formID )
{
// CH.4 Contact Detail form
case ContactDetailForm:
form = FrmInitForm(
ContactDetailForm );
FrmSetEventHandler( form,
contactDetailHandleEvent );
break;
// CH.4 About form
case AboutForm:
form = FrmInitForm( AboutForm );
FrmSetEventHandler( form,
aboutHandleEvent );
break;
// CH.6 Enter Time form
case EnterTimeForm:
form = FrmInitForm( EnterTimeForm );
FrmSetEventHandler( form,
enterTimeHandleEvent );
break;
// CH.7 Contact List form
case ContactListForm:
form = FrmInitForm( ContactListForm
);
FrmSetEventHandler( form,
contactListHandleEvent );
break;
}
FrmSetActiveForm( form );
}
// CH.2 Handle form events
FrmDispatchEvent( &event );
// CH.2 If it's a stop event, exit
} while( event.eType != appStopEvent );
// CH.7 End the try block and do the catch block
}
ErrCatch( errorAlert )
{
// CH.7 Display the appropriate alert
FrmAlert( errorAlert );
} ErrEndCatch
// CH.5 Close all open forms
FrmCloseAllForms();
// CH.5 Close the database
DmCloseDatabase( contactsDB );
// CH.2 We're done
return( 0 );
}
// CH.4 Our Contact Detail form handler function
static Boolean contactDetailHandleEvent( EventPtr event )
{
FormPtr form; // CH.3 A pointer to our form
structure
VoidPtr precord; // CH.6 Points to a database record
// CH.3 Get our form pointer
form = FrmGetActiveForm();
// CH.4 Parse events
switch( event->eType )
{
// CH.4 Form open event
case frmOpenEvent:
{
// CH.2 Draw the form
FrmDrawForm( form );
// CH.5 Draw the database fields
setFields();
}
break;
// CH.5 Form close event
case frmCloseEvent:
{
// CH.5 Store away any modified fields
getFields();
}
break;
// CH.5 Parse the button events
case ctlSelectEvent:
{
// CH.5 Store any field changes
getFields();
switch( event->data.ctlSelect.controlID )
{
// CH.5 First button
case ContactDetailFirstButton:
{
// CH.5 Set the cursor to the first
record
if( cursor > 0 )
cursor = 0;
}
break;
// CH.5 Previous button
case ContactDetailPrevButton:
{
// CH.5 Move the cursor back one
record
if( cursor > 0 )
cursor--;
}
break;
// CH.5 Next button
case ContactDetailNextButton:
{
// CH.5 Move the cursor up one
record
if( cursor < (numRecords - 1) )
cursor++;
}
break;
// CH.5 Last button
case ContactDetailLastButton:
{
// CH.5 Move the cursor to the last
record
if( cursor < (numRecords - 1) )
cursor = numRecords - 1;
}
break;
// CH.5 Delete button
case ContactDetailDeleteButton:
{
// CH.5 Remove the record from the
database
DmRemoveRecord( contactsDB, cursor
);
// CH.5 Decrease the number of
records
numRecords--;
// CH.5 Place the cursor at the
first record
cursor = 0;
// CH.5 If there are no records
left, create one
if( numRecords == 0 )
newRecord();
}
break;
// CH.5 New button
case ContactDetailNewButton:
{
// CH.5 Create a new record
newRecord();
}
break;
// CH.7 Done button
case ContactDetailDoneButton:
{
// CH.7 Load the contact list
FrmGotoForm( ContactListForm );
}
break;
// CH.6 Date selector trigger
case ContactDetailDateSelTrigger:
{
// CH.6 Initialize the date if
necessary
if( dateTime.year == NO_DATE )
{
DateTimeType currentDate;
// CH.6 Get the current date
TimSecondsToDateTime(
TimGetSeconds(),
¤tDate
);
// CH.6 Copy it
dateTime.year =
currentDate.year;
dateTime.month =
currentDate.month;
dateTime.day =
currentDate.day;
}
// CH.6 Pop up the system date
selection form
SelectDay( selectDayByDay,
&(dateTime.month),
&(dateTime.day),
&(dateTime.year),
"Enter Date" );
// CH.6 Get the record
hrecord = DmQueryRecord( contactsDB,
cursor );
// CH.6 Lock it down
precord = MemHandleLock( hrecord );
// CH.6 Write the date time field
DmWrite( precord,
DB_DATE_TIME_START, &dateTime,
sizeof( DateTimeType
) );
// CH.6 Unlock the record
MemHandleUnlock( hrecord );
// CH.6 Mark the record dirty
isDirty = true;
}
break;
// CH.6 Time selector trigger
case ContactDetailTimeSelTrigger:
{
// CH.6 Pop up our selection form
FrmPopupForm( EnterTimeForm );
}
break;
}
// CH.5 Sync the current record to the fields
setFields();
}
break;
// CH.5 Respond to field tap
case fldEnterEvent:
isDirty = true;
break;
// CH.3 Parse menu events
case menuEvent:
return( menuEventHandler( event ) );
break;
}
// CH.2 We're done
return( false );
}
// CH.4 Our About form event handler function
static Boolean aboutHandleEvent( EventPtr event )
{
FormPtr form; // CH.4 A pointer to our form structure
// CH.4 Get our form pointer
form = FrmGetActiveForm();
// CH.4 Respond to the Open event
if( event->eType == frmOpenEvent )
{
// CH.4 Draw the form
FrmDrawForm( form );
}
// CH.4 Return to the calling form
if( event->eType == ctlSelectEvent )
{
FrmReturnToForm( 0 );
// CH.4 Always return true in this case
return( true );
}
// CH.4 We're done
return( false );
}
// CH.6 Our Enter Time form event handler function
static Boolean enterTimeHandleEvent( EventPtr event )
{
FormPtr form; // CH.6 A form
structure pointer
static DateTimeType oldTime; // CH.6 The original time
// CH.6 Get our form pointer
form = FrmGetActiveForm();
// CH.6 Switch on the event
switch( event->eType )
{
// CH.6 Initialize the form
case frmOpenEvent:
{
// CH.6 Store the time value
oldTime = dateTime;
// CH.6 Draw it
FrmDrawForm( form );
// CH.6 Set the time controls
setTimeControls();
}
break;
// CH.6 If a button was repeated
case ctlRepeatEvent:
// CH.6 If a button was pushed
case ctlSelectEvent:
{
Word buttonID; // CH.6 The ID of the button
// CH.6 Set the ID
buttonID = event->data.ctlSelect.controlID;
// CH.6 Switch on button ID
switch( buttonID )
{
// CH.6 Hours button
case EnterTimeHoursPushButton:
// CH.6 Minute Tens button
case EnterTimeMinuteTensPushButton:
// CH.6 Minute Ones button
case EnterTimeMinuteOnesPushButton:
{
// CH.6 If no time was set
if( dateTime.hour == NO_TIME )
{
// CH.6 Set the time to 12
PM
dateTime.hour = 12;
dateTime.minute = 0;
// CH.6 Set the controls
setTimeControls();
}
// CH.6 Clear the old selection if
any
if( timeSelect )
CtlSetValue( getObject(
form, timeSelect ),
false );
// CH.6 Set the new selection
CtlSetValue( getObject( form,
buttonID ), true );
timeSelect = buttonID;
}
break;
// CH.6 Up button
case EnterTimeTimeUpRepeating:
{
// CH.6 If there's no time, do
nothing
if( dateTime.hour == NO_TIME )
break;
// CH.6 Based on what push button is
selected
switch( timeSelect )
{
// CH.6 Increase hours
case
EnterTimeHoursPushButton:
{
// CH.6 Increment
hours
dateTime.hour++;
// CH.6 If it was 11
AM, make it 12 AM
if( dateTime.hour ==
12 )
dateTime.hour = 0;
// CH.6 If it was 11
PM, make it 12 PM
if( dateTime.hour ==
24 )
dateTime.hour = 12;
}
break;
// CH.6 Increase tens of
minutes
case
EnterTimeMinuteTensPushButton:
{
// CH.6 Increment
minutes
dateTime.minute +=
10;
// CH.6 If it was
5X, roll over
if( dateTime.minute
> 59 )
dateTime.minute -= 60;
}
break;
// CH.6 Increase minutes
case
EnterTimeMinuteOnesPushButton:
{
// CH.6 Increment
minutes
dateTime.minute++;
// CH.6 If it is
zero, subtract ten
if( (dateTime.minute
% 10) == 0 )
dateTime.minute -= 10;
}
break;
}
// Revise the controls
setTimeControls();
}
break;
// CH.6 Down button
case EnterTimeTimeDownRepeating:
{
// CH.6 If there's no time, do
nothing
if( dateTime.hour == NO_TIME )
break;
// CH.6 Based on what push button is
selected
switch( timeSelect )
{
// CH.6 Decrease hours
case
EnterTimeHoursPushButton:
{
// CH.6 Decrement
hours
dateTime.hour--;
// CH.6 If it was 12
AM, make it 11 AM
if( dateTime.hour ==
-1 )
dateTime.hour = 11;
// CH.6 If it was 12
PM, make it 11 PM
if( dateTime.hour ==
11 )
dateTime.hour = 23;
}
break;
// CH.6 Decrease tens of
minutes
case
EnterTimeMinuteTensPushButton:
{
// CH.6 Decrement
minutes
dateTime.minute -=
10;
// CH.6 If it was
0X, roll over
if( dateTime.minute
< 0 )
dateTime.minute += 60;
}
break;
// CH.6 Decrease minutes
case
EnterTimeMinuteOnesPushButton:
{
// CH.6 Decrement
minutes
dateTime.minute--;
// CH.6 If it is 9,
add ten
if( (dateTime.minute
% 10) == 9 )
dateTime.minute += 10;
// CH.6 If less than
zero, make it 9
if( dateTime.minute
< 0 )
dateTime.minute = 9;
}
break;
}
// CH.6 Revise the controls
setTimeControls();
}
break;
// CH.6 AM button
case EnterTimeAMPushButton:
{
// CH.6 If no time was set
if( dateTime.hour == NO_TIME )
{
// CH.6 Set the time to 12
AM
dateTime.hour = 0;
dateTime.minute = 0;
// CH.6 Set the controls
setTimeControls();
}
// CH.6 If it is PM
if( dateTime.hour > 11 )
{
// CH.6 Change to AM
dateTime.hour -= 12;
// CH.6 Set the controls
setTimeControls();
}
}
break;
// CH.6 PM button
case EnterTimePMPushButton:
{
// CH.6 If no time was set
if( dateTime.hour == NO_TIME )
{
// CH.6 Set the time to 12
PM
dateTime.hour = 12;
dateTime.minute = 0;
// CH.6 Set the controls
setTimeControls();
}
// CH.6 If it is AM
if( dateTime.hour < 12 )
{
// CH.6 Change to PM
dateTime.hour += 12;
// CH.6 Set the controls
setTimeControls();
}
}
break;
// CH.6 No Time checkbox
case EnterTimeNoTimeCheckbox:
{
// CH.6 If we are unchecking the box
if( dateTime.hour == NO_TIME )
{
// CH.6 Set the time to 12
PM
dateTime.hour = 12;
dateTime.minute = 0;
// CH.6 Set the controls
setTimeControls();
// CH.6 Set the new
selection
timeSelect =
EnterTimeHoursPushButton;
CtlSetValue( getObject(
form, timeSelect ),
true );
}
else
// CH.6 If we are checking the box
dateTime.hour = NO_TIME;
// CH.6 Set the controls
setTimeControls();
}
break;
// CH.6 Cancel button
case EnterTimeCancelButton:
{
// CH.6 Restore time
dateTime = oldTime;
// CH.6 Return to calling form
FrmReturnToForm( 0 );
}
// CH.6 Always return true
return( true );
// CH.6 OK button
case EnterTimeOKButton:
{
VoidPtr precord; // CH.6
Points to the record
// CH.6 Lock it down
precord = MemHandleLock( hrecord );
// CH.6 Write the date time field
DmWrite( precord,
DB_DATE_TIME_START, &dateTime,
sizeof( DateTimeType
) );
// CH.6 Unlock the record
MemHandleUnlock( hrecord );
// CH.6 Mark the record dirty
isDirty = true;
// CH.6 Return to the Contact
Details form
FrmReturnToForm( 0 );
// CH.6 Update the field
setTimeTrigger();
}
// CH.6 Always return true
return( true );
}
}
break;
}
// CH.6 We're done
return( false );
}
// CH.7 Our Contact List form event handler function
static Boolean contactListHandleEvent( EventPtr event )
{
FormPtr form; // CH.7 A form structure pointer
// CH.7 Get our form pointer
form = FrmGetActiveForm();
// CH.7 Parse events
switch( event->eType )
{
// CH.7 Form open event
case frmOpenEvent:
{
// CH.7 Draw the form
FrmDrawForm( form );
// CH.8 Populate and draw the table
drawTable();
}
break;
// CH.7 Respond to a list selection
case tblSelectEvent:
{
// CH.7 Set the database cursor to the selected
contact
cursor += event->data.tblSelect.row;
// CH.7 Go to contact details
FrmGotoForm( ContactDetailForm );
}
break;
// CH.7 Respond to a menu event
case menuEvent:
return( menuEventHandler( event ) );
// CH.7 Respond to the popup trigger
case popSelectEvent:
{
// CH.7 If there is no change, we're done
if( sortBy == event->data.popSelect.selection )
return( true );
// CH.7 Modify sort order variable
sortBy = event->data.popSelect.selection;
// CH.7 Sort the contact database by the new
criteria
DmQuickSort( contactsDB, (DmComparF*)sortFunc,
sortBy );
// CH.8 Rebuild the table
drawTable();
}
break;
// CH.8 Respond to arrows
case ctlRepeatEvent:
{
switch( event->data.ctlRepeat.controlID )
{
// CH.8 Up arrow
case ContactListRecordUpRepeating:
if( cursor > 0 )
cursor--;
break;
// CH.8 Down arrow
case ContactListRecordDownRepeating:
if( (numRecords > TABLE_NUM_ROWS) &&
(cursor < numRecords
- TABLE_NUM_ROWS) )
cursor++;
break;
}
// CH.8 Now refresh the table
drawTable();
}
return( true );
// CH.8 Respond to up and down arrow hard keys
case keyDownEvent:
{
switch( event->data.keyDown.chr )
{
// CH.8 Up arrow hard key
case pageUpChr:
if( cursor > TABLE_NUM_ROWS - 1 )
cursor -= TABLE_NUM_ROWS -
1;
else
cursor = 0;
break;
// CH.8 Down arrow hard key
case pageDownChr:
if( (numRecords > 2 * TABLE_NUM_ROWS
- 1) &&
(cursor < numRecords
-
2 * TABLE_NUM_ROWS -
1) )
cursor += TABLE_NUM_ROWS -
1;
else
cursor = numRecords -
TABLE_NUM_ROWS;
break;
}
// CH.8 Now refresh the table
drawTable();
}
break;
// CH.8 Respond to scrollbar events
case sclRepeatEvent:
cursor = event->data.sclExit.newValue;
drawTable();
break;
} // CH.7 End of the event switch statement
// CH.7 We're done
return( false );
}
// CH.3 Handle menu events
Boolean menuEventHandler( EventPtr event )
{
FormPtr form; // CH.3 A pointer to our form
structure
Word index; // CH.3 A general purpose control
index
FieldPtr field; // CH.3 Used for manipulating fields
// CH.3 Get our form pointer
form = FrmGetActiveForm();
// CH.3 Erase the menu status from the display
MenuEraseStatus( NULL );
// CH.4 Handle options menu
if( event->data.menu.itemID == OptionsAboutContacts )
{
// CH.4 Pop up the About form as a Dialog
FrmPopupForm( AboutForm );
return( true );
}
// CH.3 Handle graffiti help
if( event->data.menu.itemID == EditGraffitiHelp )
{
// CH.3 Pop up the graffiti reference based on
// the graffiti state
SysGraffitiReferenceDialog( referenceDefault );
return( true );
}
// CH.3 Get the index of our field
index = FrmGetFocus( form );
// CH.3 If there is no field selected, we're done
if( index == noFocus )
return( false );
// CH.3 Get the pointer of our field
field = FrmGetObjectPtr( form, index );
// CH.3 Do the edit command
switch( event->data.menu.itemID )
{
// CH.3 Undo
case EditUndo:
FldUndo( field );
break;
// CH.3 Cut
case EditCut:
FldCut( field );
break;
// CH.3 Copy
case EditCopy:
FldCopy( field );
break;
// CH.3 Paste
case EditPaste:
FldPaste( field );
break;
// CH.3 Select All
case EditSelectAll:
{
// CH.3 Get the length of the string in the field
Word length = FldGetTextLength( field );
// CH.3 Sound an error if appropriate
if( length == 0 )
{
SndPlaySystemSound( sndError );
return( false );
}
// CH.3 Select the whole string
FldSetSelection( field, 0, length );
}
break;
// CH.3 Bring up the keyboard tool
case EditKeyboard:
SysKeyboardDialogV10();
break;
}
// CH.3 We're done
return( true );
}
// CH.5 This function creates and initializes a new record
static void newRecord( void )
{
VoidPtr precord; // CH.5 Pointer to the record
// CH.7 Create the database record and get a handle to it
if( (hrecord = DmNewRecord( contactsDB, &cursor,
DB_RECORD_SIZE )) == NULL )
errorExit( MemoryErrorAlert );
// CH.5 Lock down the record to modify it
precord = MemHandleLock( hrecord );
// CH.5 Clear the record
DmSet( precord, 0, DB_RECORD_SIZE, 0 );
// CH.6 Initialize the date and time
MemSet( &dateTime, sizeof( dateTime ), 0 );
dateTime.year = NO_DATE;
dateTime.hour = NO_TIME;
DmWrite( precord, DB_DATE_TIME_START, &dateTime,
sizeof( DateTimeType ) );
// CH.5 Unlock the record
MemHandleUnlock( hrecord );
// CH.5 Clear the busy bit and set the dirty bit
DmReleaseRecord( contactsDB, cursor, true );
// CH.5 Increment the total record count
numRecords++;
// CH.5 Set the dirty bit
isDirty = true;
// CH.5 We're done
return;
}
// CH.5 A time saver: Gets object pointers based on their ID
static VoidPtr getObject( FormPtr form, Word objectID )
{
Word index; // CH.5 The object index
// CH.5 Get the index
index = FrmGetObjectIndex( form, objectID );
// CH.5 Return the pointer
return( FrmGetObjectPtr( form, index ) );
}
// CH.5 Gets the current database record and displays it
// in the detail fields
static void setFields( void )
{
FormPtr form; // CH.5 The contact detail form
CharPtr precord; // CH.5 A record pointer
Word index; // CH.5 The object index
// CH.5 Get the contact detail form pointer
form = FrmGetActiveForm();
// CH.5 Get the current record
hrecord = DmQueryRecord( contactsDB, cursor );
// CH.6 Initialize the date and time variable
precord = MemHandleLock( hrecord );
MemMove( &dateTime, precord + DB_DATE_TIME_START,
sizeof( dateTime ) );
// CH.6 Initialize the date control
setDateTrigger();
// CH.6 Initialize the time control
setTimeTrigger();
// CH.5 Set the text for the First Name field
setText( getObject( form, ContactDetailFirstNameField ),
precord + DB_FIRST_NAME_START );
// CH.5 Set the text for the Last Name field
setText( getObject( form, ContactDetailLastNameField ),
precord + DB_LAST_NAME_START );
// CH.5 Set the text for the Phone Number field
setText( getObject( form, ContactDetailPhoneNumberField ),
precord + DB_PHONE_NUMBER_START );
MemHandleUnlock( hrecord );
// CH.5 If the record is already dirty, it's new, so set focus
if( isDirty )
{
// CH.3 Get the index of our field
index = FrmGetObjectIndex( form, ContactDetailFirstNameField
);
// CH.3 Set the focus to the First Name field
FrmSetFocus( form, index );
// CH.5 Set upper shift on
GrfSetState( false, false, true );
}
// CH.5 We're done
return;
}
// CH.5 Puts any field changes in the record
static void getFields( void )
{
FormPtr form; // CH.5 The contact detail form
// CH.5 Get the contact detail form pointer
form = FrmGetActiveForm();
// CH.5 Turn off focus
FrmSetFocus( form, -1 );
// CH.5 If the record has been modified
if( isDirty )
{
CharPtr precord; // CH.5 Points to the DB record
// CH.7 Detach the record from the database
DmDetachRecord( contactsDB, cursor, &hrecord );
// CH.5 Lock the record
precord = MemHandleLock( hrecord );
// CH.5 Get the text for the First Name field
getText( getObject( form, ContactDetailFirstNameField ),
precord, DB_FIRST_NAME_START );
// CH.5 Get the text for the Last Name field
getText( getObject( form, ContactDetailLastNameField ),
precord, DB_LAST_NAME_START );
// CH.5 Get the text for the Phone Number field
getText( getObject( form, ContactDetailPhoneNumberField ),
precord, DB_PHONE_NUMBER_START );
// CH.7 Find the proper position
cursor = DmFindSortPosition( contactsDB, precord, NULL,
(DmComparF*)sortFunc, sortBy );
// CH.5 Unlock the record
MemHandleUnlock( hrecord );
// CH.7 Reattach the record
DmAttachRecord( contactsDB, &cursor, hrecord, NULL );
}
// CH.5 Reset the dirty bit
isDirty = false;
// CH.5 We're done
return;
}
// CH.5 Set the text in a field
static void setText( FieldPtr field, CharPtr text )
{
VoidHand hfield; // CH.5 Handle of field text
CharPtr pfield; // CH.5 Pointer to field text
// CH.5 Get the current field handle
hfield = FldGetTextHandle( field );
// CH.5 If we have a handle
if( hfield != NULL )
{
// CH.5 Resize it
if( MemHandleResize( hfield, StrLen( text ) + 1 ) != 0 )
errorExit( MemoryErrorAlert );
}
else
// CH.5 Allocate a handle for the string
{
hfield = MemHandleNew( StrLen( text ) + 1 );
if( hfield == NULL )
errorExit( MemoryErrorAlert );
}
// CH.5 Lock it
pfield = MemHandleLock( hfield );
// CH.5 Copy the string
StrCopy( pfield, text );
// CH.5 Unlock it
MemHandleUnlock( hfield );
// CH.5 Give it to the field
FldSetTextHandle( field, hfield );
// CH.5 Draw the field
FldDrawField( field );
// CH.5 We're done
return;
}
// CH.5 Get the text from a field
static void getText( FieldPtr field, VoidPtr precord, Word offset )
{
CharPtr pfield; // CH.5 Pointer to field text
// CH.5 Get the text pointer
pfield = FldGetTextPtr( field );
// CH.5 Copy it
DmWrite( precord, offset, pfield, StrLen( pfield ) );
// CH.5 We're done
return;
}
// CH.6 Set the Contact Detail date selector trigger
static void setDateTrigger( void )
{
FormPtr form; // CH.5 The contact detail form
// CH.6 Get the contact detail form pointer
form = FrmGetActiveForm();
// CH.6 If there is no date
if( dateTime.year == NO_DATE )
{
CtlSetLabel( getObject( form, ContactDetailDateSelTrigger ),
" " );
}
else
// CH.6 If there is a date
{
Char dateString[dateStringLength];
// CH.6 Get the date string
DateToAscii( dateTime.month, dateTime.day, dateTime.year,
(DateFormatType)PrefGetPreference(
prefDateFormat ), dateString );
// CH.6 Set the selector trigger label
CtlSetLabel( getObject( form, ContactDetailDateSelTrigger ),
dateString );
}
// CH.6 We're done
return;
}
// CH.6 Set the Contact Detail time selector trigger
static void setTimeTrigger( void )
{
FormPtr form; // CH.5 The contact detail form
// CH.6 Get the contact detail form pointer
form = FrmGetActiveForm();
// CH.6 If there's no time
if( dateTime.hour == NO_TIME )
{
CtlSetLabel( getObject( form, ContactDetailTimeSelTrigger ),
" " );
}
else
// CH.6 If there is a time
{
Char timeString[timeStringLength];
// CH.6 Get the time string
TimeToAscii( dateTime.hour, dateTime.minute,
(TimeFormatType)PrefGetPreference(
prefTimeFormat ), timeString );
// CH.6 Set the selector trigger label
CtlSetLabel( getObject( form, ContactDetailTimeSelTrigger ),
timeString );
}
// CH.6 We're done
return;
}
// CH.6 Set the controls in the Enter Time form based on dateTime
static void setTimeControls( void )
{
FormPtr form;
ControlPtr hourButton;
ControlPtr minuteTensButton;
ControlPtr minuteOnesButton;
ControlPtr amButton;
ControlPtr pmButton;
ControlPtr noTimeCheckbox;
Char labelString[3];
SWord hour;
// CH.6 Get the form
form = FrmGetActiveForm();
// CH.6 Get the control pointers
hourButton = getObject( form, EnterTimeHoursPushButton );
minuteTensButton = getObject( form,
EnterTimeMinuteTensPushButton );
minuteOnesButton = getObject( form,
EnterTimeMinuteOnesPushButton );
amButton = getObject( form, EnterTimeAMPushButton );
pmButton = getObject( form, EnterTimePMPushButton );
noTimeCheckbox = getObject( form, EnterTimeNoTimeCheckbox );
// CH.6 If there is a time
if( dateTime.hour != NO_TIME )
{
// CH.6 Update the hour
hour = dateTime.hour % 12;
if( hour == 0 )
hour = 12;
CtlSetLabel( hourButton,
StrIToA( labelString, hour ) );
// CH.6 Update the minute tens
CtlSetLabel( minuteTensButton,
StrIToA( labelString, dateTime.minute / 10 )
);
// CH.6 Update the minute ones
CtlSetLabel( minuteOnesButton,
StrIToA( labelString, dateTime.minute % 10 )
);
// CH.6 Update AM
CtlSetValue( amButton, (dateTime.hour < 12) );
// CH.6 Update PM
CtlSetValue( pmButton, (dateTime.hour > 11) );
// CH.6 Uncheck the no time checkbox
CtlSetValue( noTimeCheckbox, false );
}
else
// If there is no time
{
// CH.6 Update the hour
CtlSetValue( hourButton, false );
CtlSetLabel( hourButton, "" );
// CH.6 Update the minute tens
CtlSetValue( minuteTensButton, false );
CtlSetLabel( minuteTensButton, "" );
// CH.6 Update the minute ones
CtlSetValue( minuteOnesButton, false );
CtlSetLabel( minuteOnesButton, "" );
// CH.6 Update AM
CtlSetValue( amButton, false );
// CH.6 Update PM
CtlSetValue( pmButton, false );
// CH.6 Uncheck the no time checkbox
CtlSetValue( noTimeCheckbox, true );
}
// CH.6 We're done
return;
}
// CH.7 This function is called by Palm OS to sort records
static Int sortFunc( CharPtr precord1, CharPtr precord2, Int sortBy )
{
Int sortResult;
// CH.7 Switch based on sort criteria
switch( sortBy )
{
// CH.7 Sort by date and time
case SORTBY_DATE_TIME:
{
DateTimePtr pdateTime1;
DateTimePtr pdateTime2;
Long lDiff;
pdateTime1 = (DateTimePtr)(precord1 +
DB_DATE_TIME_START);
pdateTime2 = (DateTimePtr)(precord2 +
DB_DATE_TIME_START);
// CH.7 Compare the dates and times
lDiff = (Long)(TimDateTimeToSeconds( pdateTime1 ) /
60 ) -
(Long)(TimDateTimeToSeconds(
pdateTime2 ) / 60 );
// CH.7 Date/time #1 is later
if( lDiff > 0 )
sortResult = 1;
else
// CH.7 Date/time #2 is later
if( lDiff < 0 )
sortResult = -1;
else
// CH.7 They are equal
sortResult = 0;
}
break;
// CH.7 Sort by first name
case SORTBY_FIRST_NAME:
{
sortResult = StrCompare( precord1 +
DB_FIRST_NAME_START,
precord2 + DB_FIRST_NAME_START );
}
break;
// CH.7 Sort by last name
case SORTBY_LAST_NAME:
{
sortResult = StrCompare( precord1 +
DB_LAST_NAME_START,
precord2 + DB_LAST_NAME_START );
}
break;
}
// CH.7 We're done
return( sortResult );
}
// CH.8 Draw our list of choices using a table object
static void drawTable( void )
{
FormPtr form;
TablePtr table;
Int column;
Int count;
ControlPtr upArrow;
ControlPtr downArrow;
// CH.8 Get the form pointer
form = FrmGetActiveForm();
// CH.8 Get the table pointer
table = getObject( form, ContactListTableTable );
// CH.8 For all columns
for( column = 0; column < TABLE_NUM_COLUMNS; column++ )
{
// CH.8 Set the draw routine
TblSetCustomDrawProcedure( table, column, drawCell );
// CH.8 Make the column visible
TblSetColumnUsable( table, column, true );
}
// CH.8 Initialize the table styles
for( count = 0; count < TABLE_NUM_ROWS; count++ )
{
// CH.8 If there is data
if( count < numRecords )
{
// CH.8 Show the row
TblSetRowUsable( table, count, true );
// CH.8 Set the cell styles
for( column = 0; column < TABLE_NUM_COLUMNS;
column++ )
TblSetItemStyle( table, count, column,
customTableItem );
}
else
// CH.8 Hide unused rows if any
TblSetRowUsable( table, count, false );
}
// CH.8 Draw the table
TblDrawTable( table );
// CH.8 Get pointers to the arrow buttons
upArrow = getObject( form, ContactListRecordUpRepeating );
downArrow = getObject( form, ContactListRecordDownRepeating );
// CH.8 Update the arrow buttons and scrollbars
if( numRecords > TABLE_NUM_ROWS )
{
// CH.8 Show the up arrow
if( cursor > 0 )
{
CtlSetLabel( upArrow, BLACK_UP_ARROW );
CtlSetEnabled( upArrow, true );
}
else
{
CtlSetLabel( upArrow, GRAY_UP_ARROW );
CtlSetEnabled( upArrow, false );
}
CtlShowControl( upArrow );
// CH.8 Show the down arrow
if( cursor >= numRecords - TABLE_NUM_ROWS )
{
CtlSetLabel( downArrow, GRAY_DOWN_ARROW );
CtlSetEnabled( downArrow, false );
}
else
{
CtlSetLabel( downArrow, BLACK_DOWN_ARROW );
CtlSetEnabled( downArrow, true );
}
CtlShowControl( downArrow );
// CH.8 Show the scrollbar
FrmShowObject( form, FrmGetObjectIndex( form,
ContactListScrollbarScrollBar ) );
SclSetScrollBar( getObject( form,
ContactListScrollbarScrollBar ), cursor, 0,
numRecords - TABLE_NUM_ROWS, TABLE_NUM_ROWS
);
}
else
{
// CH.8 Hide the arrows
CtlHideControl( upArrow );
CtlHideControl( downArrow );
// CH.8 Hide the scrollbar
FrmHideObject( form, FrmGetObjectIndex( form,
ContactListScrollbarScrollBar ) );
}
// CH.8 We're done
return;
}
// CH.8 The custom drawing routine for a table cell
static void drawCell( VoidPtr table, Word row, Word column,
RectanglePtr bounds )
{
Int record;
CharPtr precord;
Char string[DB_FIRST_NAME_SIZE + DB_LAST_NAME_SIZE];
SWord width;
SWord len;
Boolean noFit;
// CH.8 Calculate our record
record = cursor + row;
// CH.8 Get our record
hrecord = DmQueryRecord( contactsDB, record );
precord = MemHandleLock( hrecord );
// CH.8 Get the date and time
MemMove( &dateTime, precord + DB_DATE_TIME_START,
sizeof( dateTime ) );
// CH.8 Switch on the column
switch( column )
{
// CH.8 Handle dates
case TABLE_COLUMN_DATE:
{
if( dateTime.year != NO_DATE )
{
DateToAscii( dateTime.month, dateTime.day,
dateTime.year,
(DateFormatType)PrefGetPreference(
prefDateFormat ), string );
}
else
StrCopy( string, "-" );
}
break;
// CH.8 Handle times
case TABLE_COLUMN_TIME:
{
if( dateTime.hour != NO_TIME )
{
TimeToAscii( dateTime.hour, dateTime.minute,
(TimeFormatType)PrefGetPreference(
prefTimeFormat ), string );
}
else
StrCopy( string, "-" );
}
break;
// CH.8 Handle names
case TABLE_COLUMN_NAME:
{
StrCopy( string, precord + DB_FIRST_NAME_START );
StrCat( string, " " );
StrCat( string, precord + DB_LAST_NAME_START );
}
break;
}
// CH.8 Unlock the record
MemHandleUnlock( hrecord );
// CH.8 Set the text mode
WinSetUnderlineMode( noUnderline );
FntSetFont( stdFont );
// CH.8 Truncate the string if necessary
width = bounds->extent.x;
len = StrLen( string );
noFit = false;
FntCharsInWidth( string, &width, &len, &noFit );
// CH.8 Draw the cell
WinEraseRectangle( bounds, 0 );
WinDrawChars( string, len, bounds->topLeft.x, bounds->topLeft.y );
// CH.8 We're done
return;
}
--
For information on using the Palm Developer Forums, or to unsubscribe, please see
http://www.palmos.com/dev/tech/support/forums/
- Re: Table.c Line:2153, Invalid Parameter Rochester, Dean
- Re: Table.c Line:2153, Invalid Parameter John Marshall
- RE: Table.c Line:2153, Invalid Parameter Rochester, Dean
- RE: Table.c Line:2153, Invalid Parameter Scott Johnson (Bellevue)
- RE: Table.c Line:2153, Invalid Parameter Rochester, Dean
- RE: Table.c Line:2153, Invalid Parameter Aaron Ardiri
- RE: Table.c Line:2153, Invalid Parameter Scott Johnson (Bellevue)
- RE: Table.c Line:2153, Invalid Parameter Rochester, Dean
- Re: Table.c Line:2153, Invalid Parameter JJK112581
- RE: Table.c Line:2153, Invalid Parameter David Fedor
- RE: Table.c Line:2153, Invalid Parameter Rochester, Dean
